ObjFW  Check-in [860b0bf1e9]

Overview
Comment:Merge trunk into branch "amiga-library"
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | amiga-library
Files: files | file ages | folders
SHA3-256: 860b0bf1e9d80b64ef7dd64a43f94162dd3e83ec3fdbdb8f59aff22296c31709
User & Date: js on 2023-07-15 20:57:41
Other Links: branch diff | manifest | tags
Context
2023-07-15
21:03
Rerun generators/amiga-library check-in: 9e5e68ca05 user: js tags: amiga-library
20:57
Merge trunk into branch "amiga-library" check-in: 860b0bf1e9 user: js tags: amiga-library
18:04
PLATFORMS.md: Add GNU/Hurd check-in: 40020084fd user: js tags: trunk
2022-12-18
08:48
amiga-library.xml: Fix register double use check-in: cee2c04176 user: js tags: amiga-library
Changes

Modified .fossil-settings/clean-glob from [06b87ad48d] to [0ae1b8a1ac].

35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
35
36
37
38
39
40
41

42
43
44
45
46
47
48







-







src/tls/Info.plist
tests/DerivedData
tests/EBOOT.PBP
tests/Info.plist
tests/PARAM.SFO
tests/objc_sync/objc_sync
tests/plugin/Info.plist
tests/serialization_xml.m
tests/terminal/terminal_tests
tests/testfile_bin.m
tests/testfile_ini.m
tests/tests
tests/tests.3dsx
tests/tests.arm9
tests/tests.nds

Modified .fossil-settings/ignore-glob from [23cb69850b] to [eed8ea3523].

40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
40
41
42
43
44
45
46

47
48
49
50
51
52
53







-







tests/Info.plist
tests/PARAM.SFO
tests/iOS.xcodeproj/*.pbxuser
tests/iOS.xcodeproj/project.xcworkspace
tests/iOS.xcodeproj/xcuserdata
tests/objc_sync/objc_sync
tests/plugin/Info.plist
tests/serialization_xml.m
tests/terminal/terminal_tests
tests/testfile_bin.m
tests/testfile_ini.m
tests/tests
tests/tests.3dsx
tests/tests.arm9
tests/tests.nds

Added .github/workflows/dragonflybsd.yml version [e4f8b62803].


























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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
name: dragonflybsd
on: [push, pull_request]
jobs:
  tests:
    runs-on: macos-12
    strategy:
      matrix:
        configure_flags:
          -
          - --disable-shared
          - --with-tls=gnutls
    steps:
    - uses: actions/checkout@v3
    - uses: vmactions/dragonflybsd-vm@v0
      with:
        usesh: true
        copyback: false
        prepare: |
          pkg install -y autoconf automake gnutls llvm pkgconf
        run: |
          ./autogen.sh
          ./configure OBJC=clang ${{ matrix.configure_flags }}
          make -j4
          make check
          make install

Added .github/workflows/freebsd.yml version [9828c9c463].


























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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
name: freebsd
on: [push, pull_request]
jobs:
  tests:
    runs-on: macos-12
    strategy:
      matrix:
        configure_flags:
          -
          - --disable-shared
          - --with-tls=gnutls
    steps:
    - uses: actions/checkout@v3
    - uses: vmactions/freebsd-vm@v0
      with:
        usesh: true
        copyback: false
        prepare: |
          pkg install -y autoconf automake gnutls pkgconf
        run: |
          ./autogen.sh
          ./configure OBJC=clang ${{ matrix.configure_flags }}
          make -j4
          make check
          make install

Added .github/workflows/netbsd-gcc.yml version [4694c85176].


























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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
name: netbsd-gcc
on: [push, pull_request]
jobs:
  tests:
    runs-on: macos-12
    strategy:
      matrix:
        configure_flags:
          -
          - --disable-shared
          - --with-tls=gnutls
    steps:
    - uses: actions/checkout@v3
    - uses: vmactions/netbsd-vm@v0
      with:
        usesh: true
        copyback: false
        prepare: |
          pkg_add autoconf automake gnutls pkgconf
        run: |
          ./autogen.sh
          ./configure OBJC=gcc ${{ matrix.configure_flags }}
          make -j4
          make check
          make install

Added .github/workflows/netbsd.yml version [2c6f34efc4].


























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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
name: netbsd
on: [push, pull_request]
jobs:
  tests:
    runs-on: macos-12
    strategy:
      matrix:
        configure_flags:
          -
          - --disable-shared
          - --with-tls=gnutls
    steps:
    - uses: actions/checkout@v3
    - uses: vmactions/netbsd-vm@v0
      with:
        usesh: true
        copyback: false
        prepare: |
          pkg_add autoconf automake clang gnutls pkgconf
        run: |
          ./autogen.sh
          ./configure OBJC=clang ${{ matrix.configure_flags }}
          make -j4
          make check
          make install

Added .github/workflows/openbsd.yml version [7e76f12fa8].


























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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
name: openbsd
on: [push, pull_request]
jobs:
  tests:
    runs-on: macos-12
    strategy:
      matrix:
        configure_flags:
          -
          - --disable-shared
          - --with-tls=gnutls
    steps:
    - uses: actions/checkout@v3
    - uses: vmactions/openbsd-vm@v0
      with:
        usesh: true
        copyback: false
        prepare: |
          pkg_add autoconf-2.71 automake-1.16.5 gnutls pkgconf
        run: |
          ./autogen.sh
          ./configure OBJC=clang ${{ matrix.configure_flags }}
          make -j4
          make check
          make install

Modified .gitignore from [726b780402] to [9fa51c850c].

40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
40
41
42
43
44
45
46

47
48
49
50
51
52
53







-







tests/Info.plist
tests/PARAM.SFO
tests/iOS.xcodeproj/*.pbxuser
tests/iOS.xcodeproj/project.xcworkspace
tests/iOS.xcodeproj/xcuserdata
tests/objc_sync/objc_sync
tests/plugin/Info.plist
tests/serialization_xml.m
tests/terminal/terminal_tests
tests/testfile_bin.m
tests/testfile_ini.m
tests/tests
tests/tests.3dsx
tests/tests.arm9
tests/tests.nds

Modified Doxyfile from [6b8aa42255] to [3c7cbc0d44].

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
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










-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+




PROJECT_NAME = "ObjFW"
OUTPUT_DIRECTORY = docs/
INPUT = src src/exceptions src/runtime
FILE_PATTERNS = *.h *.m
HTML_OUTPUT = .
HAVE_DOT = NO
GENERATE_LATEX = NO
HIDE_UNDOC_CLASSES = YES
HIDE_UNDOC_MEMBERS = YES
TYPEDEF_HIDES_STRUCT = YES
PREDEFINED = __OBJC__				\
	     _Nonnull=				\
	     _Nullable=				\
	     DOXYGEN				\
	     OF_BOXABLE=			\
	     OF_CONSUMED=			\
	     OF_DESIGNATED_INITIALIZER=		\
	     OF_GENERIC(...)=			\
	     OF_HAVE_BLOCKS			\
	     OF_HAVE_FILES			\
	     OF_HAVE_SANDBOX			\
	     OF_HAVE_SOCKETS			\
	     OF_HAVE_THREADS			\
	     OF_KINDOF(...)=			\
	     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_WARN_UNUSED_RESULT=		\
	     OF_WEAK_UNAVAILABLE=		\
	     SIGHUP				\
	     SIGUSR1				\
PREDEFINED = __OBJC__						\
	     _Nonnull=						\
	     _Nullable=						\
	     DOXYGEN						\
	     OF_BOXABLE=					\
	     OF_CONSUMED=					\
	     OF_DESIGNATED_INITIALIZER=				\
	     OF_FILE_MANAGER_SUPPORTS_EXTENDED_ATTRIBUTES	\
	     OF_FILE_MANAGER_SUPPORTS_LINKS			\
	     OF_FILE_MANAGER_SUPPORTS_OWNER			\
	     OF_FILE_MANAGER_SUPPORTS_PERMISSIONS		\
	     OF_FILE_MANAGER_SUPPORTS_SYMLINKS			\
	     OF_GENERIC(...)=					\
	     OF_HAVE_APPLETALK					\
	     OF_HAVE_BLOCKS					\
	     OF_HAVE_FILES					\
	     OF_HAVE_IPV6					\
	     OF_HAVE_IPX					\
	     OF_HAVE_SANDBOX					\
	     OF_HAVE_SOCKETS					\
	     OF_HAVE_THREADS					\
	     OF_KINDOF(...)=					\
	     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_WARN_UNUSED_RESULT=				\
	     OF_WEAK_UNAVAILABLE=				\
	     SIGHUP						\
	     SIGUSR1						\
	     SIGUSR2
MACRO_EXPANSION = YES
EXPAND_ONLY_PREDEF = YES
IGNORE_PREFIX = OF of_

Modified Makefile from [4341fed160] to [fa94f358a5].

8
9
10
11
12
13
14
15

16
17
18
19
20
21
22
8
9
10
11
12
13
14

15
16
17
18
19
20
21
22







-
+







	    config.h		\
	    config.log		\
	    config.status	\
	    extra.mk

include buildsys.mk

.PHONY: docs release
.PHONY: check docs release

utils tests: src

check: tests
	cd tests && ${MAKE} -s run

docs:

Modified PLATFORMS.md from [cb8b9b98c6] to [1aba75e60e].

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
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







-
+








-
+



+
+
+
+
+
+
+
+
+
+
+







  * Runtimes: ObjFW


DragonFlyBSD
------------

  * OS Versions: 3.0, 3.3-DEVELOPMENT
  * Architectures: x86, x86_64
  * Architectures: AMD64, x86
  * Compilers: GCC 4.4.7
  * Runtimes: ObjFW


FreeBSD
-------

  * OS Versions: 9.1-rc3, 10.0
  * Architectures: x86_64
  * Architectures: AMD64
  * Compilers: Clang 3.1, Clang 3.3
  * Runtimes: ObjFW


GNU/Hurd
--------

  * OS Versions: 0.9
  * Architectures: i686
  * Compilers: Clang 14.0.6
  * Runtimes: ObjFW
  * Limitations: No support for UNIX sockets (`AF_UNIX` with `SOCK_DGRAM` is
                 currently broken in Hurd)


Haiku
-----

  * OS version: r1-alpha4
  * Architectures: x86
  * Compilers: Clang 3.2, GCC 4.6.3
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
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







-
-
+
+
-

+







-
+







  * Compilers: Clang
  * Runtimes: Apple


Linux
-----

  * Architectures: Alpha, ARMv6, ARMv7, ARM64, Itanium, m68k, MIPS (O32),
                   MIPS64 (N64), RISC-V 64, PowerPC, S390x, SuperH-4, x86,
  * Architectures: Alpha, AMD64, ARMv6, ARMv7, ARM64, Itanium, m68k, MIPS (O32),
                   MIPS64 (N64), RISC-V 64, PowerPC, S390x, SuperH-4, x86
                   x86_64
  * Compilers: Clang 3.0-10.0, GCC 4.6-10.0
  * C libraries: glibc, musl
  * Runtimes: ObjFW


macOS
-----

  * OS Versions: 10.5, 10.7-10.15, Darling
  * Architectures: PowerPC, PowerPC64, x86, x86_64
  * Architectures: AMD64, PowerPC, PowerPC64, x86
  * Compilers: Clang 3.1-10.0, Apple GCC 4.0.1 & 4.2.1
  * Runtimes: Apple, ObjFW


MiNT
----

125
126
127
128
129
130
131
132
133


134
135
136
137
138
139
140
136
137
138
139
140
141
142


143
144
145
146
147
148
149
150
151







-
-
+
+







  * Runtimes: ObjFW


NetBSD
------

  * OS Versions: 5.1-9.0
  * Architectures: ARM, ARM (big endian, BE8 mode), MIPS (O32), PowerPC, SPARC,
                   SPARC64, x86, x86_64
  * Architectures: AMD64, ARM, ARM (big endian, BE8 mode), MIPS (O32), PowerPC,
                   SPARC, SPARC64, x86
  * Compilers: Clang 3.0-3.2, GCC 4.1.3 & 4.5.3 & 7.4.0
  * Runtimes: ObjFW


Nintendo 3DS
------------

165
166
167
168
169
170
171
172

173
174
175
176
177
178
179
176
177
178
179
180
181
182

183
184
185
186
187
188
189
190







-
+







  * Limitations: No sockets, no shared libraries, not tested on real hardware


OpenBSD
-------

  * OS Versions: 5.2-6.7
  * Architectures: MIPS64, PA-RISC, PowerPC, SPARC64, x86_64
  * Architectures: AMD64, MIPS64, PA-RISC, PowerPC, SPARC64
  * Compilers: GCC 6.3.0, Clang 4.0
  * Runtimes: ObjFW


PlayStation Portable
--------------------

192
193
194
195
196
197
198
199
200
201



202
203
204
205
206
207
208
203
204
205
206
207
208
209



210
211
212
213
214
215
216
217
218
219







-
-
-
+
+
+







  * Compilers: GCC 4.6.1
  * Runtimes: ObjFW


Solaris
-------

  * OS Versions: OpenIndiana 2015.03
  * Architectures: x86, x86_64
  * Compilers: Clang 3.4.2, GCC 4.8.3
  * OS Versions: OpenIndiana 2015.03, OpenIndiana 2023.04, Oracle Solaris 11.4
  * Architectures: AMD64, x86
  * Compilers: Clang 3.4.2, Clang 11.0.0, Clang 13.0.1, GCC 4.8.3, GCC 10.4.0
  * Runtimes: ObjFW


Wii
---

  * OS Versions: 4.3E / Homebrew Channel 1.1.0
224
225
226
227
228
229
230
231
232


233
234

235
236
237
238
239
240
241
235
236
237
238
239
240
241


242
243
244

245
246
247
248
249
250
251
252







-
-
+
+

-
+









Windows
-------

  * OS Versions: 98 SE, NT 4.0, XP (x86), 7 (x64), 8 (x64), 8.1 (x64), 10, 11,
                 Wine (x86 & x64)
  * Architectures: x86, x86_64, AArch64
  * Compilers: GCC 5.3.0 & 6.2.0 from msys2 (x86 & x64),
  * Architectures: AArch64, AMD64, x86
  * Compilers: GCC 5.3.0 & 6.2.0 from msys2 (AMD64 & x86),
               Clang 3.9.0 from msys2 (x86),
               Clang 10.0 from msys2 (x86 & x86_64),
               Clang 10.0 from msys2 (AMD64 & x86),
               Clang 14.0.4 from msys2 (AArch64)
  * Runtimes: ObjFW


Others
------

252
253
254
255
256
257
258

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

278
279
280







+







-



==========

As forwarding needs hand-written assembly for each combination of CPU
architecture, executable format and calling convention, it is only available
for the following platforms (except resolveClassMethod: and
resolveInstanceMethod:, which are always available):

  * AMD64 (SysV/ELF, Apple/Mach-O, Mach-O, Win64/PE)
  * ARM (EABI/ELF, Apple/Mach-O)
  * ARM64 (ARM64/ELF, Apple/Mach-O)
  * MIPS (O32/ELF, EABI/ELF)
  * PowerPC (SysV/ELF, EABI/ELF, Apple/Mach-O)
  * SPARC (SysV/ELF)
  * SPARC64 (SysV/ELF)
  * x86 (SysV/ELF, Apple/Mach-O, Win32/PE)
  * x86_64 (SysV/ELF, Apple/Mach-O, Mach-O, Win64/PE)

Apple/Mach-O means both, the Apple ABI and runtime, while Mach-O means the
ObjFW runtime on Mach-O.

Modified README.md from [b12bc1a9ce] to [2681c29664].

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
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







-
-
-
-
+
+
+
+





-
-
+
+
-
-
-
+
+








  To build for macOS, just follow the
  <a href="#installation">regular instructions</a> above.

  To build for iOS, follow the regular instructions, but instead of
  `./configure` do something like this:

    $ clang="clang -isysroot $(xcrun --sdk iphoneos --show-sdk-path)"
    $ export OBJC="$clang -arch armv7 -arch arm64"
    $ export OBJCPP="$clang -arch armv7 -E"
    $ export IPHONEOS_DEPLOYMENT_TARGET="9.0"
    $ clang="xcrun --sdk iphoneos clang"
    $ export OBJC="$clang -arch arm64e -arch arm64"
    $ export OBJCPP="$clang -arch arm64e -E"
    $ export IPHONEOS_DEPLOYMENT_TARGET="10.0"
    $ ./configure --prefix=/usr/local/ios --host=arm64-apple-darwin

  To build for the iOS simulator, follow the regular instructions, but instead
  of `./configure` use something like this:

    $ clang="clang -isysroot $(xcrun --sdk iphonesimulator --show-sdk-path)"
    $ export OBJC="$clang -arch arm64 -arch x86_64"
    $ clang="xcrun --sdk iphonesimulator clang"
    $ export OBJC="$clang -arch $(uname -m)"
    $ export OBJCPP="$clang -arch arm64 -E"
    $ export IPHONEOS_DEPLOYMENT_TARGET="9.0"
    $ ./configure --prefix=/usr/local/iossim --host=arm64-apple-darwin
    $ export IPHONEOS_DEPLOYMENT_TARGET="10.0"
    $ ./configure --prefix=/usr/local/iossim --host=$(uname -m)-apple-darwin

<h3 id="framework-in-xcode">Using the macOS or iOS framework in Xcode</h3>

  To use the macOS framework in Xcode, you need to add the `.framework`s to
  your project and add the following flags to `Other C Flags`:

    -fconstant-string-class=OFConstantString -fno-constant-cfstrings

Modified autogen.sh from [4f8a1648f4] to [fd90c83211].

1
2
3
4

5
6
7




8
9
10
11
1
2
3
4
5



6
7
8
9
10
11
12
13




+
-
-
-
+
+
+
+




#!/bin/sh
set -e

# Set a version for OpenBSD
if test x"$(uname -s)" = x"OpenBSD"; then
: ${AUTOCONF_VERSION:=2.69}
: ${AUTOMAKE_VERSION:=1.16}
export AUTOCONF_VERSION AUTOMAKE_VERSION
	: ${AUTOCONF_VERSION:=2.71}
	: ${AUTOMAKE_VERSION:=1.16}
	export AUTOCONF_VERSION AUTOMAKE_VERSION
fi

aclocal -I build-aux/m4
autoconf
autoheader

Modified build-aux/m4/buildsys.m4 from [8a265c0c72] to [4066b24b6a].

1
2
3

4
5
6
7
8
9
10
1
2

3
4
5
6
7
8
9
10


-
+







dnl
dnl Copyright (c) 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2016, 2017,
dnl               2018, 2020, 2021, 2022
dnl               2018, 2020, 2021, 2022, 2023
dnl   Jonathan Schleifer <js@nil.im>
dnl
dnl https://fossil.nil.im/buildsys
dnl
dnl Permission to use, copy, modify, and/or distribute this software for any
dnl purpose with or without fee is hereby granted, provided that the above
dnl copyright notice and this permission notice is present in all copies.
144
145
146
147
148
149
150

151
152
153
154
155
156
157
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158







+







			#endif
		], [
			host_is_ios="yes"
		], [
			host_is_ios="no"
		])
		AC_MSG_RESULT($host_is_ios)
		AC_CHECK_TOOL(CODESIGN, codesign)
		;;
	esac
])

AC_DEFUN([BUILDSYS_PROG_IMPLIB], [
	AC_REQUIRE([AC_CANONICAL_HOST])
	AC_MSG_CHECKING(whether we need an implib)
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
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
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
























































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
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
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







-
+












-
-
-
-
-
-
-
-


-
-










-
-
-
-


-
-












-
-
-
-


-
-












-
-
-
-


-
-









-
-
-
-


-
-













-
-
-
-


-
-













-
-
-
-


-
-












-
-
-
-


-
-











-
-
-
-


-
-








-
-


















+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
	AC_SUBST(PROG_IMPLIB_NEEDED)
	AC_SUBST(PROG_IMPLIB_LDFLAGS)
])

AC_DEFUN([BUILDSYS_SHARED_LIB], [
	AC_REQUIRE([AC_CANONICAL_HOST])
	AC_REQUIRE([BUILDSYS_CHECK_IOS])
	AC_MSG_CHECKING(for shared library system)
	AC_MSG_CHECKING(for shared library type)

	case "$host" in
	*-*-darwin*)
		AC_MSG_RESULT(Darwin)
		LIB_CFLAGS='-fPIC -DPIC'
		LIB_LDFLAGS='-dynamiclib -current_version ${LIB_MAJOR}.${LIB_MINOR} -compatibility_version ${LIB_MAJOR}'
		LIB_LDFLAGS_INSTALL_NAME='-Wl,-install_name,${libdir}/$${out%.dylib}.${LIB_MAJOR}.dylib'
		LIB_PREFIX='lib'
		LIB_SUFFIX='.dylib'
		AS_IF([test x"$enable_rpath" != x"no"], [
			LDFLAGS_RPATH='-Wl,-rpath,${libdir}'
		])
		PLUGIN_CFLAGS='-fPIC -DPIC'
		PLUGIN_LDFLAGS='-bundle ${PLUGIN_LDFLAGS_BUNDLE_LOADER}'
		PLUGIN_SUFFIX='.bundle'
		AS_IF([test x"$host_is_ios" = x"yes"], [
			LINK_PLUGIN='rm -fr $$out && ${MKDIR_P} $$out && if test -f Info.plist; then ${INSTALL} -m 644 Info.plist $$out/Info.plist; fi && ${LD} -o $$out/$${out%${PLUGIN_SUFFIX}} ${PLUGIN_OBJS} ${PLUGIN_OBJS_EXTRA} ${PLUGIN_LDFLAGS} ${LDFLAGS} ${LIBS} && ${CODESIGN} -fs ${CODESIGN_IDENTITY} --timestamp=none $$out'
		], [
			LINK_PLUGIN='rm -fr $$out && ${MKDIR_P} $$out/Contents/MacOS && if test -f Info.plist; then ${INSTALL} -m 644 Info.plist $$out/Contents/Info.plist; fi && ${LD} -o $$out/Contents/MacOS/$${out%${PLUGIN_SUFFIX}} ${PLUGIN_OBJS} ${PLUGIN_OBJS_EXTRA} ${PLUGIN_LDFLAGS} ${LDFLAGS} ${LIBS} && ${CODESIGN} -fs ${CODESIGN_IDENTITY} --timestamp=none $$out'
		])
		INSTALL_LIB='&& ${INSTALL} -m 755 $$i ${DESTDIR}${libdir}/$${i%.dylib}.${LIB_MAJOR}.${LIB_MINOR}.dylib && ${LN_S} -f $${i%.dylib}.${LIB_MAJOR}.${LIB_MINOR}.dylib ${DESTDIR}${libdir}/$${i%.dylib}.${LIB_MAJOR}.dylib && ${LN_S} -f $${i%.dylib}.${LIB_MAJOR}.${LIB_MINOR}.dylib ${DESTDIR}${libdir}/$$i'
		UNINSTALL_LIB='&& rm -f ${DESTDIR}${libdir}/$$i ${DESTDIR}${libdir}/$${i%.dylib}.${LIB_MAJOR}.dylib ${DESTDIR}${libdir}/$${i%.dylib}.${LIB_MAJOR}.${LIB_MINOR}.dylib'
		INSTALL_PLUGIN='&& rm -fr ${DESTDIR}${plugindir}/$$i && cp -R $$i ${DESTDIR}${plugindir}/'
		UNINSTALL_PLUGIN='&& rm -fr ${DESTDIR}${plugindir}/$$i'
		CLEAN_LIB=''
		;;
	*-*-mingw* | *-*-cygwin*)
		AC_MSG_RESULT(MinGW / Cygwin)
		LIB_CFLAGS=''
		LIB_LDFLAGS='-shared -Wl,--export-all-symbols'
		LIB_LDFLAGS_INSTALL_NAME=''
		LIB_PREFIX=''
		LIB_SUFFIX='${LIB_MAJOR}.dll'
		LINK_LIB='&& rm -f lib$${out%${LIB_SUFFIX}}.dll.a && ${LN_S} $$out lib$${out%${LIB_SUFFIX}}.dll.a'
		PLUGIN_CFLAGS=''
		PLUGIN_LDFLAGS='-shared -Wl,--export-all-symbols'
		PLUGIN_SUFFIX='.dll'
		LINK_PLUGIN='${LD} -o $$out ${PLUGIN_OBJS} ${PLUGIN_OBJS_EXTRA} ${PLUGIN_LDFLAGS} ${LDFLAGS} ${LIBS}'
		INSTALL_LIB='&& ${MKDIR_P} ${DESTDIR}${bindir} && ${INSTALL} -m 755 $$i ${DESTDIR}${bindir}/$$i && ${INSTALL} -m 755 lib$${i%${LIB_SUFFIX}}.dll.a ${DESTDIR}${libdir}/lib$${i%${LIB_SUFFIX}}.dll.a'
		UNINSTALL_LIB='&& rm -f ${DESTDIR}${bindir}/$$i ${DESTDIR}${libdir}/lib$${i%${LIB_SUFFIX}}.dll.a'
		INSTALL_PLUGIN='&& ${INSTALL} -m 755 $$i ${DESTDIR}${plugindir}/$$i'
		UNINSTALL_PLUGIN='&& rm -f ${DESTDIR}${plugindir}/$$i'
		CLEAN_LIB='${SHARED_LIB}.a ${SHARED_LIB_NOINST}.a'
		;;
	*-*-openbsd* | *-*-mirbsd*)
		AC_MSG_RESULT(OpenBSD)
		LIB_CFLAGS='-fPIC -DPIC'
		LIB_LDFLAGS='-shared'
		LIB_LDFLAGS_INSTALL_NAME=''
		LIB_PREFIX='lib'
		LIB_SUFFIX='.so.${LIB_MAJOR}.${LIB_MINOR}'
		AS_IF([test x"$enable_rpath" != x"no"], [
			LDFLAGS_RPATH='-Wl,-rpath,${libdir}'
		])
		PLUGIN_CFLAGS='-fPIC -DPIC'
		PLUGIN_LDFLAGS='-shared'
		PLUGIN_SUFFIX='.so'
		LINK_PLUGIN='${LD} -o $$out ${PLUGIN_OBJS} ${PLUGIN_OBJS_EXTRA} ${PLUGIN_LDFLAGS} ${LDFLAGS} ${LIBS}'
		INSTALL_LIB='&& ${INSTALL} -m 755 $$i ${DESTDIR}${libdir}/$$i'
		UNINSTALL_LIB='&& rm -f ${DESTDIR}${libdir}/$$i'
		INSTALL_PLUGIN='&& ${INSTALL} -m 755 $$i ${DESTDIR}${plugindir}/$$i'
		UNINSTALL_PLUGIN='&& rm -f ${DESTDIR}${plugindir}/$$i'
		CLEAN_LIB=''
		;;
	*-*-solaris*)
		AC_MSG_RESULT(Solaris)
		LIB_CFLAGS='-fPIC -DPIC'
		LIB_LDFLAGS='-shared -Wl,-soname=$$out.${LIB_MAJOR}.${LIB_MINOR}'
		LIB_LDFLAGS_INSTALL_NAME=''
		LIB_PREFIX='lib'
		LIB_SUFFIX='.so'
		AS_IF([test x"$enable_rpath" != x"no"], [
			LDFLAGS_RPATH='-Wl,-rpath,${libdir}'
		])
		PLUGIN_CFLAGS='-fPIC -DPIC'
		PLUGIN_LDFLAGS='-shared'
		PLUGIN_SUFFIX='.so'
		LINK_PLUGIN='${LD} -o $$out ${PLUGIN_OBJS} ${PLUGIN_OBJS_EXTRA} ${PLUGIN_LDFLAGS} ${LDFLAGS} ${LIBS}'
		INSTALL_LIB='&& ${INSTALL} -m 755 $$i ${DESTDIR}${libdir}/$$i.${LIB_MAJOR}.${LIB_MINOR} && rm -f ${DESTDIR}${libdir}/$$i && ${LN_S} $$i.${LIB_MAJOR}.${LIB_MINOR} ${DESTDIR}${libdir}/$$i'
		UNINSTALL_LIB='&& rm -f ${DESTDIR}${libdir}/$$i ${DESTDIR}${libdir}/$$i.${LIB_MAJOR}.${LIB_MINOR}'
		INSTALL_PLUGIN='&& ${INSTALL} -m 755 $$i ${DESTDIR}${plugindir}/$$i'
		UNINSTALL_PLUGIN='&& rm -f ${DESTDIR}${plugindir}/$$i'
		CLEAN_LIB=''
		;;
	*-*-android*)
		AC_MSG_RESULT(Android)
		LIB_CFLAGS='-fPIC -DPIC'
		LIB_LDFLAGS='-shared -Wl,-soname=$$out.${LIB_MAJOR}'
		LIB_LDFLAGS_INSTALL_NAME=''
		LIB_PREFIX='lib'
		LIB_SUFFIX='.so'
		PLUGIN_CFLAGS='-fPIC -DPIC'
		PLUGIN_LDFLAGS='-shared'
		PLUGIN_SUFFIX='.so'
		LINK_PLUGIN='${LD} -o $$out ${PLUGIN_OBJS} ${PLUGIN_OBJS_EXTRA} ${PLUGIN_LDFLAGS} ${LDFLAGS} ${LIBS}'
		INSTALL_LIB='&& ${INSTALL} -m 755 $$i ${DESTDIR}${libdir}/$$i.${LIB_MAJOR}.${LIB_MINOR}.0 && ${LN_S} -f $$i.${LIB_MAJOR}.${LIB_MINOR}.0 ${DESTDIR}${libdir}/$$i.${LIB_MAJOR} && ${LN_S} -f $$i.${LIB_MAJOR}.${LIB_MINOR}.0 ${DESTDIR}${libdir}/$$i'
		UNINSTALL_LIB='&& rm -f ${DESTDIR}${libdir}/$$i ${DESTDIR}${libdir}/$$i.${LIB_MAJOR} ${DESTDIR}${libdir}/$$i.${LIB_MAJOR}.${LIB_MINOR}.0'
		INSTALL_PLUGIN='&& ${INSTALL} -m 755 $$i ${DESTDIR}${plugindir}/$$i'
		UNINSTALL_PLUGIN='&& rm -f ${DESTDIR}${plugindir}/$$i'
		CLEAN_LIB=''
		;;
	hppa*-*-hpux*)
		AC_MSG_RESULT([HP-UX (PA-RISC)])
		LIB_CFLAGS='-fPIC -DPIC'
		LIB_LDFLAGS='-shared -Wl,+h,$$out'
		LIB_LDFLAGS_INSTALL_NAME=''
		LIB_PREFIX='lib'
		LIB_SUFFIX='.${LIB_MAJOR}'
		LINK_LIB='&& rm -f $${out%%.*}.sl && ${LN_S} $$out $${out%%.*}.sl'
		AS_IF([test x"$enable_rpath" != x"no"], [
			LDFLAGS_RPATH='-Wl,+b,${libdir}'
		])
		PLUGIN_CFLAGS='-fPIC -DPIC'
		PLUGIN_LDFLAGS='-shared'
		PLUGIN_SUFFIX='.sl'
		LINK_PLUGIN='${LD} -o $$out ${PLUGIN_OBJS} ${PLUGIN_OBJS_EXTRA} ${PLUGIN_LDFLAGS} ${LDFLAGS} ${LIBS}'
		INSTALL_LIB='&& ${INSTALL} -m 755 $$i ${DESTDIR}${libdir}/$$i && ${LN_S} -f $$i ${DESTDIR}${libdir}/$${i%%.*}.sl'
		UNINSTALL_LIB='&& rm -f ${DESTDIR}${libdir}/$$i ${DESTDIR}${libdir}/$${i%%.*}.sl'
		INSTALL_PLUGIN='&& ${INSTALL} -m 755 $$i ${DESTDIR}${plugindir}/$$i'
		UNINSTALL_PLUGIN='&& rm -f ${DESTDIR}${plugindir}/$$i'
		CLEAN_LIB=''
		;;
	ia64*-*-hpux*)
		AC_MSG_RESULT([HP-UX (Itanium)])
		LIB_CFLAGS='-fPIC -DPIC'
		LIB_LDFLAGS='-shared -Wl,+h,$$out'
		LIB_LDFLAGS_INSTALL_NAME=''
		LIB_PREFIX='lib'
		LIB_SUFFIX='.${LIB_MAJOR}'
		LINK_LIB='&& rm -f $${out%%.*}.so && ${LN_S} $$out $${out%%.*}.so'
		AS_IF([test x"$enable_rpath" != x"no"], [
			LDFLAGS_RPATH='-Wl,+b,${libdir}'
		])
		PLUGIN_CFLAGS='-fPIC -DPIC'
		PLUGIN_LDFLAGS='-shared'
		PLUGIN_SUFFIX='.so'
		LINK_PLUGIN='${LD} -o $$out ${PLUGIN_OBJS} ${PLUGIN_OBJS_EXTRA} ${PLUGIN_LDFLAGS} ${LDFLAGS} ${LIBS}'
		INSTALL_LIB='&& ${INSTALL} -m 755 $$i ${DESTDIR}${libdir}/$$i && ${LN_S} -f $$i ${DESTDIR}${libdir}/$${i%%.*}.so'
		UNINSTALL_LIB='&& rm -f ${DESTDIR}${libdir}/$$i ${DESTDIR}${libdir}/$${i%%.*}.so'
		INSTALL_PLUGIN='&& ${INSTALL} -m 755 $$i ${DESTDIR}${plugindir}/$$i'
		UNINSTALL_PLUGIN='&& rm -f ${DESTDIR}${plugindir}/$$i'
		CLEAN_LIB=''
		;;
	*)
		AC_MSG_RESULT(ELF)
		LIB_CFLAGS='-fPIC -DPIC'
		LIB_LDFLAGS='-shared -Wl,-soname=$$out.${LIB_MAJOR}'
		LIB_LDFLAGS_INSTALL_NAME=''
		LIB_PREFIX='lib'
		LIB_SUFFIX='.so'
		AS_IF([test x"$enable_rpath" != x"no"], [
			LDFLAGS_RPATH='-Wl,-rpath,${libdir}'
		])
		PLUGIN_CFLAGS='-fPIC -DPIC'
		PLUGIN_LDFLAGS='-shared'
		PLUGIN_SUFFIX='.so'
		LINK_PLUGIN='${LD} -o $$out ${PLUGIN_OBJS} ${PLUGIN_OBJS_EXTRA} ${PLUGIN_LDFLAGS} ${LDFLAGS} ${LIBS}'
		INSTALL_LIB='&& ${INSTALL} -m 755 $$i ${DESTDIR}${libdir}/$$i.${LIB_MAJOR}.${LIB_MINOR}.0 && ${LN_S} -f $$i.${LIB_MAJOR}.${LIB_MINOR}.0 ${DESTDIR}${libdir}/$$i.${LIB_MAJOR} && ${LN_S} -f $$i.${LIB_MAJOR}.${LIB_MINOR}.0 ${DESTDIR}${libdir}/$$i'
		UNINSTALL_LIB='&& rm -f ${DESTDIR}${libdir}/$$i ${DESTDIR}${libdir}/$$i.${LIB_MAJOR} ${DESTDIR}${libdir}/$$i.${LIB_MAJOR}.${LIB_MINOR}.0'
		INSTALL_PLUGIN='&& ${INSTALL} -m 755 $$i ${DESTDIR}${plugindir}/$$i'
		UNINSTALL_PLUGIN='&& rm -f ${DESTDIR}${plugindir}/$$i'
		CLEAN_LIB=''
		;;
	esac

	AC_SUBST(LIB_CFLAGS)
	AC_SUBST(LIB_LDFLAGS)
	AC_SUBST(LIB_LDFLAGS_INSTALL_NAME)
	AC_SUBST(LIB_PREFIX)
	AC_SUBST(LIB_SUFFIX)
	AC_SUBST(LINK_LIB)
	AC_SUBST(LDFLAGS_RPATH)
	AC_SUBST(PLUGIN_CFLAGS)
	AC_SUBST(PLUGIN_LDFLAGS)
	AC_SUBST(PLUGIN_SUFFIX)
	AC_SUBST(LINK_PLUGIN)
	AC_SUBST(INSTALL_LIB)
	AC_SUBST(UNINSTALL_LIB)
	AC_SUBST(INSTALL_PLUGIN)
	AC_SUBST(UNINSTALL_PLUGIN)
	AC_SUBST(CLEAN_LIB)
])

AC_DEFUN([BUILDSYS_FRAMEWORK], [
	AC_REQUIRE([AC_CANONICAL_HOST])
	AC_REQUIRE([BUILDSYS_CHECK_IOS])
	AC_REQUIRE([BUILDSYS_SHARED_LIB])

	AC_CHECK_TOOL(CODESIGN, codesign)

	case "$host_os" in
	darwin*)
		AS_IF([test x"$host_is_ios" = x"yes"], [
			FRAMEWORK_LDFLAGS='-dynamiclib -current_version ${LIB_MAJOR}.${LIB_MINOR} -compatibility_version ${LIB_MAJOR}'
			FRAMEWORK_LDFLAGS_INSTALL_NAME='-Wl,-install_name,@executable_path/Frameworks/$$out/$${out%.framework}'
		], [
			FRAMEWORK_LDFLAGS='-dynamiclib -current_version ${LIB_MAJOR}.${LIB_MINOR} -compatibility_version ${LIB_MAJOR}'
			FRAMEWORK_LDFLAGS_INSTALL_NAME='-Wl,-install_name,@executable_path/../Frameworks/$$out/$${out%.framework}'
		])

		AC_SUBST(FRAMEWORK_LDFLAGS)
		AC_SUBST(FRAMEWORK_LDFLAGS_INSTALL_NAME)
		AC_SUBST(FRAMEWORK_LIBS)

		$1
		;;
	esac
])

AC_DEFUN([BUILDSYS_PLUGIN], [
	AC_REQUIRE([AC_CANONICAL_HOST])
	AC_REQUIRE([BUILDSYS_CHECK_IOS])
	AC_MSG_CHECKING(for plugin type)

	case "$host" in
	*-*-darwin*)
		AC_MSG_RESULT(Darwin)
		PLUGIN_CFLAGS='-fPIC -DPIC'
		PLUGIN_LDFLAGS='-bundle ${PLUGIN_LDFLAGS_BUNDLE_LOADER}'
		PLUGIN_SUFFIX='.bundle'
		AS_IF([test x"$host_is_ios" = x"yes"], [
			LINK_PLUGIN='rm -fr $$out && ${MKDIR_P} $$out && if test -f Info.plist; then ${INSTALL} -m 644 Info.plist $$out/Info.plist; fi && ${LD} -o $$out/$${out%${PLUGIN_SUFFIX}} ${PLUGIN_OBJS} ${PLUGIN_OBJS_EXTRA} ${PLUGIN_LDFLAGS} ${LDFLAGS} ${LIBS} && ${CODESIGN} -fs ${CODESIGN_IDENTITY} --timestamp=none $$out'
		], [
			LINK_PLUGIN='rm -fr $$out && ${MKDIR_P} $$out/Contents/MacOS && if test -f Info.plist; then ${INSTALL} -m 644 Info.plist $$out/Contents/Info.plist; fi && ${LD} -o $$out/Contents/MacOS/$${out%${PLUGIN_SUFFIX}} ${PLUGIN_OBJS} ${PLUGIN_OBJS_EXTRA} ${PLUGIN_LDFLAGS} ${LDFLAGS} ${LIBS} && ${CODESIGN} -fs ${CODESIGN_IDENTITY} --timestamp=none $$out'
		])
		INSTALL_PLUGIN='&& rm -fr ${DESTDIR}${plugindir}/$$i && cp -R $$i ${DESTDIR}${plugindir}/'
		UNINSTALL_PLUGIN='&& rm -fr ${DESTDIR}${plugindir}/$$i'
		;;
	*-*-mingw* | *-*-cygwin*)
		AC_MSG_RESULT(MinGW / Cygwin)
		PLUGIN_CFLAGS=''
		PLUGIN_LDFLAGS='-shared -Wl,--export-all-symbols'
		PLUGIN_SUFFIX='.dll'
		LINK_PLUGIN='${LD} -o $$out ${PLUGIN_OBJS} ${PLUGIN_OBJS_EXTRA} ${PLUGIN_LDFLAGS} ${LDFLAGS} ${LIBS}'
		INSTALL_PLUGIN='&& ${INSTALL} -m 755 $$i ${DESTDIR}${plugindir}/$$i'
		UNINSTALL_PLUGIN='&& rm -f ${DESTDIR}${plugindir}/$$i'
		;;
	hppa*-*-hpux*)
		AC_MSG_RESULT([HP-UX (PA-RISC)])
		PLUGIN_CFLAGS='-fPIC -DPIC'
		PLUGIN_LDFLAGS='-shared'
		PLUGIN_SUFFIX='.sl'
		LINK_PLUGIN='${LD} -o $$out ${PLUGIN_OBJS} ${PLUGIN_OBJS_EXTRA} ${PLUGIN_LDFLAGS} ${LDFLAGS} ${LIBS}'
		INSTALL_PLUGIN='&& ${INSTALL} -m 755 $$i ${DESTDIR}${plugindir}/$$i'
		UNINSTALL_PLUGIN='&& rm -f ${DESTDIR}${plugindir}/$$i'
		;;
	*)
		AC_MSG_RESULT(ELF)
		PLUGIN_CFLAGS='-fPIC -DPIC'
		PLUGIN_LDFLAGS='-shared'
		PLUGIN_SUFFIX='.so'
		LINK_PLUGIN='${LD} -o $$out ${PLUGIN_OBJS} ${PLUGIN_OBJS_EXTRA} ${PLUGIN_LDFLAGS} ${LDFLAGS} ${LIBS}'
		INSTALL_PLUGIN='&& ${INSTALL} -m 755 $$i ${DESTDIR}${plugindir}/$$i'
		UNINSTALL_PLUGIN='&& rm -f ${DESTDIR}${plugindir}/$$i'
		;;
	esac

	AC_SUBST(PLUGIN_CFLAGS)
	AC_SUBST(PLUGIN_LDFLAGS)
	AC_SUBST(PLUGIN_SUFFIX)
	AC_SUBST(LINK_PLUGIN)
	AC_SUBST(INSTALL_PLUGIN)
	AC_SUBST(UNINSTALL_PLUGIN)
])

Modified buildsys.mk.in from [e067a2f2b2] to [b42288d277].

759
760
761
762
763
764
765
766

767
768
769
770
771
772
773
759
760
761
762
763
764
765

766
767
768
769
770
771
772
773







-
+







		else \
			${INSTALL_FAILED}; \
		fi \
	done

install-extra:

uninstall: uninstall-extra
uninstall:
	for i in "" ${SUBDIRS} ${SUBDIRS_AFTER}; do \
		test x"$$i" = x"" && continue; \
		${DIR_ENTER}; \
		${MAKE} -s uninstall || exit $$?; \
		${DIR_LEAVE}; \
	done

871
872
873
874
875
876
877


878
879
880
881
882
883
884
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886







+
+







			if rm -f ${DESTDIR}${mandir}/${mansubdir}/$$i; then \
				${DELETE_OK}; \
			else \
				${DELETE_FAILED}; \
			fi \
		fi \
	done

	${MAKE} -s uninstall-extra

uninstall-extra:

clean:
	for i in "" ${SUBDIRS} ${SUBDIRS_AFTER}; do \
		test x"$$i" = x"" && continue; \
		${DIR_ENTER}; \

Modified configure.ac from [40a1438a77] to [1f8f03a89e].

1

2
3
4
5
6
7
8

1
2
3
4
5
6
7
8
-
+







AC_INIT(ObjFW, 1.1dev, js@nil.im)
AC_INIT(ObjFW, 1.1dev, js@nil.im, objfw, https://objfw.nil.im/)
AC_CONFIG_SRCDIR(src)
AC_CONFIG_AUX_DIR(build-aux)
AC_CONFIG_MACRO_DIR(build-aux/m4)

AC_DEFINE(OBJFW_VERSION_MAJOR, 1, [The major version of ObjFW])
AC_DEFINE(OBJFW_VERSION_MINOR, 1, [The minor version of ObjFW])
dnl This may only be set to 1.1 once 1.1 is released
99
100
101
102
103
104
105
106

107
108
109
110
111
112
113
99
100
101
102
103
104
105

106
107
108
109
110
111
112
113







-
+







	;;
*-msdosdjgpp*)
	enable_shared="no"
	enable_threads="no"
	enable_sockets="no"
	;;
*-*-mingw*)
	LDFLAGS="$LDFLAGS -Wl,--allow-multiple-definition -static-libgcc"
	LDFLAGS="$LDFLAGS -Wl,--allow-multiple-definition"
	LIBS="$LIBS -lversion"

	AC_SUBST(USE_SRCS_WINDOWS, '${SRCS_WINDOWS}')
	;;
*-psp-*)
	AS_IF([test x"$DEVKITPSP" = x""], [
		AC_MSG_ERROR([DEVKITPSP is not set! Please set DEVKITPSP.])
144
145
146
147
148
149
150








151
152
153
154
155
156
157
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165







+
+
+
+
+
+
+
+







	LIBS="$LIBS -latomic"
	;;
*-*-mint*)
	enable_shared="no"
	enable_threads="no"	# TODO
	with_tls="no"
	;;
*-apple-macos*)
	enable_shared="no"
	enable_threads="no"	# TODO
	enable_sockets="no"	# TODO

	AC_DEFINE(OF_CLASSIC_MACOS, 1,
		[Whether we are compiling for classic macOS])
	;;
esac

AS_IF([test x"$host_os" = x"msdosdjgpp" -a x"$build_os" = x"msdosdjgpp"], [
	dnl Hack to make configure find these on DOS.
	: ${AR:=ar.exe}
	: ${GREP:=grep.exe}
	: ${RANLIB:=ranlib.exe}
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
175
176
177
178
179
180
181

182
183
184
185
186
187
188







-







*)
	potential_compilers="clang egcc gcc"
	;;
esac
AC_PROG_OBJC($potential_compilers)
AC_PROG_OBJCPP
AC_PROG_LN_S
AC_PROG_EGREP

BUILDSYS_CHECK_IOS

AC_ARG_WITH(wii,
	AS_HELP_STRING([--with-wii], [build for Wii]))
AS_IF([test x"$with_wii" = x"yes"], [
	AS_IF([test x"$DEVKITPRO" = x""], [
416
417
418
419
420
421
422


423

424
425
426
427
428
429
430
423
424
425
426
427
428
429
430
431

432
433
434
435
436
437
438
439







+
+
-
+







	AS_HELP_STRING([--disable-amiga-lib], [do not build Amiga library]))
AS_IF([test x"$supports_amiga_lib" != x"yes"], [enable_amiga_lib="no"])

AC_ARG_ENABLE(shared,
	AS_HELP_STRING([--disable-shared], [do not build shared library]))
AS_IF([test x"$enable_shared" != x"no"], [
	BUILDSYS_SHARED_LIB
	BUILDSYS_PLUGIN

	AC_SUBST(OBJFW_SHARED_LIB, "${LIB_PREFIX}objfw${LIB_SUFFIX}")
	AC_SUBST(OBJFW_SHARED_LIB, '${LIB_PREFIX}objfw${LIB_SUFFIX}')
	AC_SUBST(EXCEPTIONS_LIB_A, "exceptions.lib.a")
	AC_SUBST(FORWARDING_LIB_A, "forwarding.lib.a")
	AC_SUBST(LOOKUP_ASM_LIB_A, "lookup-asm.lib.a")

	BUILDSYS_FRAMEWORK([
		AC_SUBST(OBJFW_FRAMEWORK, "ObjFW.framework")
		build_framework="yes"
592
593
594
595
596
597
598
599

600
601
602
603
604
605
606
601
602
603
604
605
606
607

608
609
610
611
612
613
614
615







-
+







	])

	AC_SUBST(RUNTIME, "runtime")
	AC_CONFIG_FILES(src/runtime/Info.plist)

	AS_IF([test x"$enable_shared" != x"no"], [
		AC_SUBST(OBJFWRT_SHARED_LIB,
			"${LIB_PREFIX}objfwrt${LIB_SUFFIX}")
			'${LIB_PREFIX}objfwrt${LIB_SUFFIX}')
	])

	AS_IF([test x"$enable_static" = x"yes"], [
		AC_SUBST(OBJFWRT_STATIC_LIB, "libobjfwrt.a")
	])

	AS_IF([test x"$build_framework" = x"yes"], [
1054
1055
1056
1057
1058
1059
1060








1061











1062
1063
1064
1065
1066
1067
1068
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077

1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095







+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+








		AC_CHECK_FUNC(sched_yield, [
			AC_DEFINE(OF_HAVE_SCHED_YIELD, 1,
				[Whether we have sched_yield()])
		])

		AC_CHECK_FUNCS(pthread_attr_getschedpolicy)

		old_OBJCFLAGS="$OBJCFLAGS"
		OBJCFLAGS="$OBJCFLAGS -Werror"
		AC_MSG_CHECKING(for pthread_attr_setinheritsched)
		AC_COMPILE_IFELSE([
			AC_LANG_PROGRAM([
				#include <pthread.h>
			], [
		AC_CHECK_FUNCS(pthread_attr_setinheritsched)
				pthread_attr_setinheritsched(
				    (pthread_attr_t *)-1, 0);
			])
		], [
			AC_MSG_RESULT(yes)
			AC_DEFINE(HAVE_PTHREAD_ATTR_SETINHERITSCHED, 1,
				[Whether we have pthread_attr_setinheritsched])
		], [
			AC_MSG_RESULT(no)
		])
		OBJCFLAGS="$old_OBJCFLAGS"

		AC_CHECK_HEADERS(pthread_np.h, [], [], [#include <pthread.h>])
		AC_CHECK_FUNCS(pthread_set_name_np pthread_setname_np, break)
		;;
	esac

	AC_DEFINE(OF_HAVE_THREADS, 1, [Whether we have threads])
1330
1331
1332
1333
1334
1335
1336
1337

1338
1339
1340
1341
1342
1343
1344
1357
1358
1359
1360
1361
1362
1363

1364
1365
1366
1367
1368
1369
1370
1371







-
+







*)
	AC_CHECK_HEADERS(fcntl.h)
	AC_CHECK_FUNCS([fcntl nanosleep])
	;;
esac

AC_CHECK_HEADERS(xlocale.h)
AC_CHECK_FUNCS([strtod_l strtof_l asprintf_l])
AC_CHECK_FUNCS([strtod_l strtof_l asprintf_l uselocale])
AS_IF([test x"$gnu_source" != x"yes" -a \( \
    x"$ac_cv_func_strtod_l" = x"yes" -o x"$ac_cv_func_strtof_l" = x"yes" -o \
    x"$ac_cv_func_asprintf_l" = x"yes" \)], [
	AC_MSG_CHECKING(whether *_l functions need _GNU_SOURCE)
	AC_COMPILE_IFELSE([
		AC_LANG_PROGRAM([
			#include <stdlib.h>
1416
1417
1418
1419
1420
1421
1422














1423
1424
1425
1426
1427
1428
1429
1430
1431
1432


1433








1434
1435
1436
1437
1438
1439
1440
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472

1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490







+
+
+
+
+
+
+
+
+
+
+
+
+
+









-
+
+

+
+
+
+
+
+
+
+







		;;
	esac

	AC_CHECK_HEADER(sys/socket.h, [
		AC_DEFINE(OF_HAVE_SYS_SOCKET_H, 1,
			[Whether we have sys/socket.h])
	])
	AC_CHECK_TYPE([struct sockaddr_storage], [
		AC_DEFINE(OF_HAVE_SOCKADDR_STORAGE, 1,
			[Whether we have struct sockaddr_storage])
	], [], [
		#ifdef OF_HAVE_SYS_TYPES_H
		# include <sys/types.h>
		#endif
		#ifdef OF_HAVE_SYS_SOCKET_H
		# include <sys/socket.h>
		#endif
		#ifdef _WIN32
		# include <winsock2.h>
		#endif
	])

	AC_CHECK_HEADER(netinet/in.h, [
		AC_DEFINE(OF_HAVE_NETINET_IN_H, 1,
			[Whether we have netinet/in.h])
	])
	AC_CHECK_HEADER(netinet/tcp.h, [
		AC_DEFINE(OF_HAVE_NETINET_TCP_H, 1,
			[Whether we have netinet/tcp.h])
	])
	AC_CHECK_HEADERS([arpa/inet.h netdb.h net/if.h])
	AC_CHECK_HEADERS([arpa/inet.h netdb.h])
	AC_CHECK_HEADERS([net/if.h net/if_arp.h net/if_dl.h net/if_types.h])
	AC_CHECK_FUNCS([if_indextoname if_nametoindex])
	AC_CHECK_TYPES([struct sockaddr_dl], [], [], [
		#ifdef HAVAE_SYS_TYPES_H
		# include <sys/types.h>
		#endif
		#ifdef HAVE_NET_IF_DL_H
		# include <net/if_dl.h>
		#endif
	])
	AC_CHECK_HEADER(sys/un.h, [
		AC_DEFINE(OF_HAVE_SYS_UN_H, 1, [Whether we have sys/un.h])
	])
	AC_CHECK_MEMBER([struct sockaddr_in6.sin6_addr], [
		AC_EGREP_CPP(egrep_cpp_yes, [
			#ifdef _WIN32
			typedef int BOOL;
1493
1494
1495
1496
1497
1498
1499















1500
1501
1502
1503
1504
1505
1506
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







		# include <winsock2.h>
		#endif
	])
	AC_CHECK_MEMBER(struct sockaddr_un.sun_path, [
		AC_DEFINE(OF_HAVE_UNIX_SOCKETS, 1,
			[Whether we have UNIX sockets])
		AC_SUBST(USE_SRCS_UNIX_SOCKETS, '${SRCS_UNIX_SOCKETS}')

		AC_CHECK_MEMBERS(struct sockaddr_un.sun_len, [], [], [
			#ifdef OF_HAVE_SYS_TYPES_H
			# include <sys/types.h>
			#endif
			#ifdef OF_HAVE_SYS_UN_H
			# include <sys/un.h>
			#endif
			#ifdef _WIN32
			# include <winsock2.h>
			#endif
			#ifdef HAVE_AFUNIX_H
			# include <afunix.h>
			#endif
		])
	], [], [
		#ifdef OF_HAVE_SYS_TYPES_H
		# include <sys/types.h>
		#endif
		#ifdef OF_HAVE_SYS_UN_H
		# include <sys/un.h>
		#endif
1514
1515
1516
1517
1518
1519
1520




1521
1522
1523
1524
1525
1526
1527
1528












1529
1530
1531




1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551




1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569


1570
1571
1572
1573
1574
1575
1576
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596

1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656

1657
1658
1659
1660
1661
1662
1663
1664
1665







+
+
+
+







-
+
+
+
+
+
+
+
+
+
+
+
+



+
+
+
+




















+
+
+
+

















-
+
+







		#ifdef __morphos__
		# error MorphOS has the struct but does not support it
		#endif

		#ifdef __MINT__
		# error Gives invalid argument at runtime
		#endif

		#ifdef __gnu_hurd__
		# error Empty sun_path in the source given by recvfrom()
		#endif
	])

	AC_CHECK_HEADER(netipx/ipx.h, [
		AC_DEFINE(OF_HAVE_NETIPX_IPX_H, 1,
			[Whether we have netipx/ipx.h])
	])
	AC_CHECK_MEMBER(struct sockaddr_ipx.sipx_network, [], [
		AC_CHECK_MEMBER(struct sockaddr_ipx.sa_netnum, [], [], [
		AC_CHECK_MEMBER(struct sockaddr_ipx.sa_netnum, [], [
			AC_CHECK_MEMBER(struct sockaddr_ipx.sipx_addr.x_port, [
			], [], [
				#ifdef HAVE_SYS_TYPES_H
				# include <sys/types.h>
				#endif

				#ifdef OF_HAVE_NETIPX_IPX_H
				# include <netipx/ipx.h>
				#endif
			])
		], [
			#ifdef _WIN32
			typedef int BOOL;
			#endif

			#ifdef HAVE_SYS_TYPES_H
			# include <sys/types.h>
			#endif

			#ifdef OF_HAVE_NETIPX_IPX_H
			# include <netipx/ipx.h>
			#endif

			#ifdef _WIN32
			# ifdef __MINGW32__
			#  include <_mingw.h>
			#  ifdef __MINGW64_VERSION_MAJOR
			#   include <winsock2.h>
			#  endif
			# endif
			# include <windows.h>
			# include <wsipx.h>
			#endif
		])
	], [
		#ifdef _WIN32
		typedef int BOOL;
		#endif

		#ifdef HAVE_SYS_TYPES_H
		# include <sys/types.h>
		#endif

		#ifdef OF_HAVE_NETIPX_IPX_H
		# include <netipx/ipx.h>
		#endif

		#ifdef _WIN32
		# ifdef __MINGW32__
		#  include <_mingw.h>
		#  ifdef __MINGW64_VERSION_MAJOR
		#   include <winsock2.h>
		#  endif
		# endif
		# include <windows.h>
		# include <wsipx.h>
		#endif
	])
	AS_IF([test x"$ac_cv_member_struct_sockaddr_ipx_sipx_network" = x"yes" \
	    -o x"$ac_cv_member_struct_sockaddr_ipx_sa_netnum" = x"yes"], [
	    -o x"$ac_cv_member_struct_sockaddr_ipx_sa_netnum" = x"yes" -o \
	    x"$ac_cv_member_struct_sockaddr_ipx_sipx_addr_x_port" = x"yes"], [
		AC_EGREP_CPP(egrep_cpp_yes, [
			#ifdef _WIN32
			typedef int BOOL;
			#endif

			#ifdef OF_HAVE_SYS_SOCKET_H
			# include <sys/socket.h>
1728
1729
1730
1731
1732
1733
1734



1735
1736
1737
1738
1739
1740
1741
1742
1743

1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767

1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784

1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834

1835
1836
1837
1838
1839
1840



1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855

1856
1857


1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870

1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884



1885
1886
1887
1888
1889
1890
1891







+
+
+








-
+





-
-
-















-
+

-
-













-
+













-
-
-







				[Whether we have select() or similar])
			AC_SUBST(OF_SELECT_KERNEL_EVENT_OBSERVER_M,
				"OFSelectKernelEventObserver.m")
		])
		;;
	esac

	AC_CHECK_HEADERS(net/if.h)
	AC_CHECK_FUNCS(if_nameindex)

	AC_ARG_WITH(tls,
		AS_HELP_STRING([--with-tls], [
			enable TLS support using the specified library
			(yes, openssl, gnutls, securetransport or no)]))
	AS_IF([test x"$with_tls" = x""], [with_tls="yes"])
	tls_support="no"

	AS_IF([test x"$with_tls" = x"securetransport" \
		-o x"$with_tls" = x"yes"], [
	    -o x"$with_tls" = x"yes"], [
		AC_CHECK_HEADERS(Security/SecureTransport.h, [
			old_LIBS="$LIBS"
			LIBS="-framework Security -framework Foundation $LIBS"

			AC_CHECK_FUNC(SSLHandshake, [
				AC_DEFINE(HAVE_SECURE_TRANSPORT, 1,
					[Whether we have Secure Transport])

				tls_support="Secure Transport"
				TLS_LIBS="-framework Foundation $TLS_LIBS"
				TLS_LIBS="-framework Security $TLS_LIBS"

				AC_SUBST(OF_SECURE_TRANSPORT_TLS_STREAM_M,
					"OFSecureTransportTLSStream.m")

				AC_CHECK_FUNCS(SSLCreateContext)
			], [])

			LIBS="$old_LIBS"
		])
	])

	AS_IF([test x"$with_tls" = x"gnutls" \
		-o \( x"$with_tls" = x"yes" -a x"$tls_support" = x"no" \)], [
	    -o \( x"$with_tls" = x"yes" -a x"$tls_support" = x"no" \)], [
		PKG_CHECK_MODULES(gnutls, [gnutls >= 3.5.0], [
			AC_DEFINE(HAVE_GNUTLS, 1, [Whether we have GnuTLS])

			tls_support="GnuTLS"
			TLS_CPPFLAGS="$gnutls_CFLAGS $TLS_CPPFLAGS"
			TLS_LIBS="$gnutls_LIBS $TLS_LIBS"

			AC_SUBST(OF_GNUTLS_TLS_STREAM_M, "OFGnuTLSTLSStream.m")
		], [
			dnl Disable default action-if-not-found, which exits
			dnl configure with an error.
			:
		])
	])

	AS_IF([test x"$with_tls" = x"openssl" \
		-o \( x"$with_tls" = x"yes" -a x"$tls_support" = x"no" \)], [
	    -o \( x"$with_tls" = x"yes" -a x"$tls_support" = x"no" \)], [
		case "$host_os" in
		morphos*)
			ssl="ssl_shared"
			crypto="crypto_shared"
			;;
		*)
			ssl="ssl"
			crypto="crypto"
			;;
		esac

		AC_CHECK_LIB($ssl, SSL_set1_host, [
			AC_CHECK_HEADER(openssl/ssl.h, [
				AC_DEFINE(HAVE_OPENSSL, 1,
					[Whether we have OpenSSL])

				tls_support="OpenSSL"
				TLS_LIBS="-l$ssl -l$crypto $TLS_LIBS"

				AC_SUBST(OF_OPENSSL_TLS_STREAM_M,
					"OFOpenSSLTLSStream.m")
			])
		], [], [-l$crypto])
1815
1816
1817
1818
1819
1820
1821
1822

1823
1824
1825
1826
1827
1828
1829
1899
1900
1901
1902
1903
1904
1905

1906
1907
1908
1909
1910
1911
1912
1913







-
+







			[Whether we have an implementation for TLS])
		AC_CONFIG_FILES(src/tls/Info.plist)

		OFHTTP_LIBS="-lobjfwtls $TLS_LIBS $OFHTTP_LIBS"

		AS_IF([test x"$enable_shared" != x"no"], [
			AC_SUBST(OBJFWTLS_SHARED_LIB,
				"${LIB_PREFIX}objfwtls${LIB_SUFFIX}")
				'${LIB_PREFIX}objfwtls${LIB_SUFFIX}')
		])
		AS_IF([test x"$enable_static" = x"yes" \
		    -o x"$enable_shared" = x"no"], [
			AC_SUBST(OBJFWTLS_STATIC_LIB, "libobjfwtls.a")
		])
		AS_IF([test x"$build_framework" = x"yes"], [
			AC_SUBST(OBJFWTLS_FRAMEWORK, "ObjFWTLS.framework")
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901


1902
1903
1904
1905
1906
1907
1908


1909
1910
1911



1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926

1927
1928
1929
1930
1931
1932
1933

1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946

1947
1948
1949
1950
1951
1952
1953
1963
1964
1965
1966
1967
1968
1969




1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980

1981
1982
1983
1984
1985
1986
1987


1988
1989



1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005


2006
2007
2008
2009
2010
2011
2012

2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025

2026
2027
2028
2029
2030
2031
2032
2033







-
-
-
-











-
+
+





-
-
+
+
-
-
-
+
+
+













-
-
+






-
+












-
+








		#if (!defined(TARGET_OS_IPHONE) || !TARGET_OS_IPHONE) && \
		    (!defined(TARGET_OS_SIMULATOR) || !TARGET_OS_SIMULATOR)
		egrep_cpp_yes
		#endif
	], [
		AC_MSG_RESULT(yes)
		have_subprocesses="yes"

		AC_CHECK_FUNCS(posix_spawnp)
		AC_CHECK_HEADERS(spawn.h)
	], [
		AC_MSG_RESULT(no)
		have_subprocesses="no"
	])
	;;
mingw*)
	have_subprocesses="yes"
	;;
msdosdjgpp*)
	have_subprocesses="no"
	;;
*)
esac
AS_IF([test x"$have_subprocesses" = x""], [
	AC_HEADER_SYS_WAIT
	AC_CHECK_FUNCS(kill)

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

			AC_CHECK_HEADERS(spawn.h, [have_subprocesses="yes"])
		])
			AC_CHECK_HEADERS(spawn.h)
		])
	], [
	])

	AS_IF([test x"$have_subprocesses" = x""], [
		AC_CHECK_FUNCS([vfork dup2 execvp _exit], [
			AS_IF([test x"$ac_cv_func_vfork" = x"yes" \
			    -a x"$ac_cv_func_pipe" = x"yes" \
			    -a x"$ac_cv_func_dup2" = x"yes" \
			    -a x"$ac_cv_func_execvp" = x"yes" \
			    -a x"$ac_cv_func_kill" = x"yes" \
			    -a x"$ac_cv_func__exit" = x"yes"], [
				have_subprocesses="yes"
			])
		], [
			break
		])
	])
	;;
esac
])
AS_IF([test x"$have_subprocesses" = x"yes"], [
	AC_SUBST(OF_SUBPROCESS_M, "OFSubprocess.m")
	AC_DEFINE(OF_HAVE_SUBPROCESSES, 1, [Whether we have subprocesses])
])

AC_CHECK_HEADERS_ONCE([complex.h sys/ioctl.h sys/ttycom.h])
AC_CHECK_FUNCS(isatty)
AC_CHECK_FUNCS(ioctl isatty)

AC_CHECK_FUNC(pledge, [
	AC_DEFINE(OF_HAVE_PLEDGE, 1, [Whether we have pledge()])
])

AS_IF([test x"$objc_runtime" = x"Apple runtime"], [
	AC_CHECK_HEADER(Foundation/NSObject.h, [
		AC_SUBST(BRIDGE, "bridge")
		AC_CONFIG_FILES(src/bridge/Info.plist)

		AS_IF([test x"$enable_shared" != x"no"], [
			AC_SUBST(OBJFWBRIDGE_SHARED_LIB,
				"${LIB_PREFIX}objfwbridge${LIB_SUFFIX}")
				'${LIB_PREFIX}objfwbridge${LIB_SUFFIX}')
		])
		AS_IF([test x"$enable_static" = x"yes" \
		    -o x"$enable_shared" = x"no"], [
			AC_SUBST(OBJFWBRIDGE_STATIC_LIB, "libobjfwbridge.a")
		])
		AS_IF([test x"$build_framework" = x"yes"], [
			AC_SUBST(OBJFWBRIDGE_FRAMEWORK,
2217
2218
2219
2220
2221
2222
2223














2224
2225
2226
2227
2228
2229
2230
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324







+
+
+
+
+
+
+
+
+
+
+
+
+
+







		], [
			AC_MSG_RESULT(no)
		], [
			AC_MSG_RESULT(yes)
			OBJCFLAGS="$old_OBJCFLAGS"
		])
	])

	AC_MSG_CHECKING(whether we need -Wno-strict-prototypes)
	AC_COMPILE_IFELSE([
		AC_LANG_PROGRAM([
			#include <signal.h>
		], [
			signal(SIGINT, SIG_DFL);
		])
	], [
		AC_MSG_RESULT(no)
	], [
		AC_MSG_RESULT(yes)
		OBJCFLAGS="$OBJCFLAGS -Wno-strict-prototypes"
	])

	AS_IF([test x"$ac_cv_header_complex_h" = x"yes"], [
		AC_MSG_CHECKING(whether we need -Wno-gnu-imaginary-constant)
		AC_COMPILE_IFELSE([
			AC_LANG_PROGRAM([
				#include <complex.h>
			], [
2247
2248
2249
2250
2251
2252
2253
2254
2255

2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2341
2342
2343
2344
2345
2346
2347


2348


2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361











2362
2363
2364
2365
2366
2367
2368







-
-
+
-
-













-
-
-
-
-
-
-
-
-
-
-







	i?86-*-mingw*)
		AC_CHECK_PROG(WINE, wine, wine)
		;;
	x86_64-*-mingw*)
		AC_CHECK_PROG(WINE, wine64, wine64)
		;;
	esac

	AS_IF([test x"$WINE" != x""], [
	AS_IF([test x"$WINE" != x""], [AC_SUBST(WRAPPER, "$WINE")])
		AC_SUBST(WRAPPER, "$WINE")
	])

	AS_IF([test x"$with_wii" = x"yes"], [
		dnl Keep this lowercase, as WIILOAD is a variable used by
		dnl wiiload and thus likely already set by the user to something
		dnl that is not the path of the wiiload binary.
		AC_CHECK_PROG(wiiload, wiiload, wiiload)

		AS_IF([test x"$wiiload" != x""], [
			AC_SUBST(WRAPPER, "$wiiload")
		])
	])
])

AC_ARG_WITH(fish_completions,
	AS_HELP_STRING([--with-fish-completions],
		[install completions for the fish shell]))
AS_IF([test x"$with_fish_completions" = x""], [
	AC_CHECK_PROG(FISH, fish, fish)
	AS_IF([test x"$FISH" != x""], [with_fish_completions="yes"])
])
AS_IF([test x"$with_fish_completions" = x"yes"], [
	AC_SUBST(FISH_COMPLETIONS, fish)
])

dnl We don't call AC_PROG_CPP, but only AC_PROG_OBJCPP and set CPP to OBJCPP
dnl and add OBJCPPFLAGS to CPPFLAGS, thus we need to AC_SUBST these ourself.
AC_SUBST(CPP)
AC_SUBST(CPPFLAGS)
dnl We use the ObjC compiler as our assembler
AC_SUBST(AS, $OBJC)
AC_SUBST(ASFLAGS)

Modified extra.mk.in from [e1760eea9d] to [bdbfcf399d].

28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
28
29
30
31
32
33
34

35
36
37
38
39
40
41







-







ENCODINGS_A = @ENCODINGS_A@
ENCODINGS_AMIGALIB_A = @ENCODINGS_AMIGALIB_A@
ENCODINGS_LIB_A = @ENCODINGS_LIB_A@
ENCODINGS_SRCS = @ENCODINGS_SRCS@
EXCEPTIONS_A = @EXCEPTIONS_A@
EXCEPTIONS_AMIGALIB_A = @EXCEPTIONS_AMIGALIB_A@
EXCEPTIONS_LIB_A = @EXCEPTIONS_LIB_A@
FISH_COMPLETIONS = @FISH_COMPLETIONS@
FORWARDING_A = @FORWARDING_A@
FORWARDING_AMIGALIB_A = @FORWARDING_AMIGALIB_A@
FORWARDING_LIB_A = @FORWARDING_LIB_A@
LIBBASES_M = @LIBBASES_M@
LIBOBJFWRT_DEP = @LIBOBJFWRT_DEP@
LIBOBJFWRT_DEP_LVL2 = @LIBOBJFWRT_DEP_LVL2@
LIBOBJFW_DEP = @LIBOBJFW_DEP@

Modified generators/library/FuncArrayGenerator.h from [2d0edf7996] to [d8b783c7a3].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified generators/library/FuncArrayGenerator.m from [4ed090453c] to [71c76426fb].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified generators/library/GlueGenerator.h from [df3f9366c5] to [9ffcc85ae6].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified generators/library/GlueGenerator.m from [a4f73aa06c] to [ec62f49bc2].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified generators/library/LibraryGenerator.m from [5f9c6926df] to [d060eed3f3].

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
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

-
+


















-
+














-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+

-
+


-
+


-
+


-
+

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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 "OFApplication.h"
#import "OFFile.h"
#import "OFFileManager.h"
#import "OFURI.h"
#import "OFIRI.h"
#import "OFXMLElement.h"

#import "FuncArrayGenerator.h"
#import "GlueGenerator.h"
#import "LinkLibGenerator.h"

@interface LibraryGenerator: OFObject <OFApplicationDelegate>
@end

OF_APPLICATION_DELEGATE(LibraryGenerator)

@implementation LibraryGenerator
- (void)generateInDirectory: (OFString *)directory
{
	OFURI *sourcesURI = [[OFFileManager defaultManager].currentDirectoryURI
	    URIByAppendingPathComponent: directory];
	OFURI *libraryURI = [sourcesURI
	    URIByAppendingPathComponent: @"amiga-library.xml"];
	OFURI *linkLibURI = [sourcesURI
	    URIByAppendingPathComponent: @"linklib/linklib.m"];
	OFURI *glueHeaderURI = [sourcesURI
	    URIByAppendingPathComponent: @"amiga-glue.h"];
	OFURI *glueURI = [sourcesURI
	    URIByAppendingPathComponent: @"amiga-glue.m"];
	OFURI *funcArrayURI = [sourcesURI
	    URIByAppendingPathComponent: @"amiga-funcarray.inc"];
	OFIRI *sourcesIRI = [[OFFileManager defaultManager].currentDirectoryIRI
	    IRIByAppendingPathComponent: directory];
	OFIRI *libraryIRI = [sourcesIRI
	    IRIByAppendingPathComponent: @"amiga-library.xml"];
	OFIRI *linkLibIRI = [sourcesIRI
	    IRIByAppendingPathComponent: @"linklib/linklib.m"];
	OFIRI *glueHeaderIRI = [sourcesIRI
	    IRIByAppendingPathComponent: @"amiga-glue.h"];
	OFIRI *glueIRI = [sourcesIRI
	    IRIByAppendingPathComponent: @"amiga-glue.m"];
	OFIRI *funcArrayIRI = [sourcesIRI
	    IRIByAppendingPathComponent: @"amiga-funcarray.inc"];
	OFXMLElement *library = [OFXMLElement elementWithStream:
	    [OFFile fileWithPath: libraryURI.fileSystemRepresentation
	    [OFFile fileWithPath: libraryIRI.fileSystemRepresentation
			    mode: @"r"]];
	OFFile *linkLib =
	    [OFFile fileWithPath: linkLibURI.fileSystemRepresentation
	    [OFFile fileWithPath: linkLibIRI.fileSystemRepresentation
			    mode: @"w"];
	OFFile *glueHeader =
	    [OFFile fileWithPath: glueHeaderURI.fileSystemRepresentation
	    [OFFile fileWithPath: glueHeaderIRI.fileSystemRepresentation
			    mode: @"w"];
	OFFile *glue =
	    [OFFile fileWithPath: glueURI.fileSystemRepresentation mode: @"w"];
	    [OFFile fileWithPath: glueIRI.fileSystemRepresentation mode: @"w"];
	OFFile *funcArray =
	    [OFFile fileWithPath: funcArrayURI.fileSystemRepresentation
	    [OFFile fileWithPath: funcArrayIRI.fileSystemRepresentation
			    mode: @"w"];
	LinkLibGenerator *linkLibGenerator = [[[LinkLibGenerator alloc]
	    initWithLibrary: library
	     implementation: linkLib] autorelease];
	GlueGenerator *glueGenerator = [[[GlueGenerator alloc]
	    initWithLibrary: library
		     header: glueHeader

Modified generators/library/LinkLibGenerator.h from [58647bf17f] to [fb82d2e9a6].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified generators/library/LinkLibGenerator.m from [223399c150] to [0ba5af7f3b].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified generators/library/copyright.h from [c0b22b50fd] to [210478e1ad].

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
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

-
+

















-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 */

#import "OFString.h"

#define COPYRIGHT \
    @"/*\n"								       \
    @" * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>\n"	       \
    @" * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>\n"	       \
    @" *\n"								       \
    @" * All rights reserved.\n"					       \
    @" *\n"								       \
    @" * This file is part of ObjFW. It may be distributed under the terms "   \
    @"of the\n"								       \
    @" * Q Public License 1.0, which can be found in the file LICENSE.QPL "    \
    @"included in\n"							       \

Modified generators/unicode/TableGenerator.h from [d5ba8e12b8] to [68e11922ac].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified generators/unicode/TableGenerator.m from [f18304006d] to [3403a36c8e].

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
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

-
+

















-
+

-
-
+
+


-
-
-
+
+
+






-
+

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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"

#include <string.h>

#import "OFString.h"
#import "OFApplication.h"
#import "OFArray.h"
#import "OFApplication.h"
#import "OFURI.h"
#import "OFFile.h"
#import "OFHTTPClient.h"
#import "OFHTTPRequest.h"
#import "OFHTTPResponse.h"
#import "OFHTTPClient.h"
#import "OFFile.h"
#import "OFStdIOStream.h"
#import "OFIRI.h"
#import "OFStdIOStream.h"
#import "OFString.h"

#import "OFOutOfRangeException.h"

#import "TableGenerator.h"
#import "copyright.h"

static OFString *const unicodeDataURI =
static OFString *const unicodeDataIRI =
    @"http://www.unicode.org/Public/UNIDATA/UnicodeData.txt";
static OFString *const caseFoldingURI =
static OFString *const caseFoldingIRI =
    @"http://www.unicode.org/Public/UNIDATA/CaseFolding.txt";

OF_APPLICATION_DELEGATE(TableGenerator)

@implementation TableGenerator
- (instancetype)init
{
64
65
66
67
68
69
70
71
72


73
74
75
76
77
78
79
64
65
66
67
68
69
70


71
72
73
74
75
76
77
78
79







-
-
+
+








- (void)applicationDidFinishLaunching: (OFNotification *)notification
{
	OFHTTPRequest *request;

	[OFStdOut writeString: @"Downloading UnicodeData.txt…"];
	_state = stateUnicodeData;
	request = [OFHTTPRequest requestWithURI:
	    [OFURI URIWithString: unicodeDataURI]];
	request = [OFHTTPRequest requestWithIRI:
	    [OFIRI IRIWithString: unicodeDataIRI]];
	[_HTTPClient asyncPerformRequest: request];
}

-      (void)client: (OFHTTPClient *)client
  didPerformRequest: (OFHTTPRequest *)request
	   response: (OFHTTPResponse *)response
	  exception: (id)exception
164
165
166
167
168
169
170
171
172


173
174
175
176
177
178
179
164
165
166
167
168
169
170


171
172
173
174
175
176
177
178
179







-
-
+
+







	[self applyDecompositionRecursivelyForTable: _decompositionTable];
	[self applyDecompositionRecursivelyForTable: _decompositionCompatTable];

	[OFStdOut writeLine: @" done"];

	[OFStdOut writeString: @"Downloading CaseFolding.txt…"];
	_state = stateCaseFolding;
	request = [OFHTTPRequest requestWithURI:
	    [OFURI URIWithString: caseFoldingURI]];
	request = [OFHTTPRequest requestWithIRI:
	    [OFIRI IRIWithString: caseFoldingIRI]];
	[_HTTPClient asyncPerformRequest: request];
}

- (void)parseCaseFolding: (OFHTTPResponse *)response
{
	OFString *line;

266
267
268
269
270
271
272
273

274
275
276
277
278


279
280
281


282
283
284
285
286
287
288
266
267
268
269
270
271
272

273
274
275
276


277
278
279


280
281
282
283
284
285
286
287
288







-
+



-
-
+
+

-
-
+
+







			objc_autoreleasePoolPop(pool);
		}
	} while (!done);
}

- (void)writeFiles
{
	OFURI *URI;
	OFIRI *IRI;

	[OFStdOut writeString: @"Writing files…"];

	URI = [OFURI fileURIWithPath: @"../../src/unicode.m"];
	[self writeTablesToFile: URI.fileSystemRepresentation];
	IRI = [OFIRI fileIRIWithPath: @"../../src/unicode.m"];
	[self writeTablesToFile: IRI.fileSystemRepresentation];

	URI = [OFURI fileURIWithPath: @"../../src/unicode.h"];
	[self writeHeaderToFile: URI.fileSystemRepresentation];
	IRI = [OFIRI fileIRIWithPath: @"../../src/unicode.h"];
	[self writeHeaderToFile: IRI.fileSystemRepresentation];

	[OFStdOut writeLine: @" done"];

	[OFApplication terminate];
}

- (void)writeTablesToFile: (OFString *)path

Modified generators/unicode/copyright.h from [c0b22b50fd] to [210478e1ad].

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
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

-
+

















-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 */

#import "OFString.h"

#define COPYRIGHT \
    @"/*\n"								       \
    @" * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>\n"	       \
    @" * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>\n"	       \
    @" *\n"								       \
    @" * All rights reserved.\n"					       \
    @" *\n"								       \
    @" * This file is part of ObjFW. It may be distributed under the terms "   \
    @"of the\n"								       \
    @" * Q Public License 1.0, which can be found in the file LICENSE.QPL "    \
    @"included in\n"							       \

Modified objfw.spec from [218ec62f80] to [77fa467494].

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



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







-
+

-
+


-
-
-
+

-
+
+
+


-
-
-
+
+
+


+

-
-
-
+
+


-
-
-
+

-
+
+
+


-
-
-
+

-
+
+
+


-
-
-
+

-
+
+
+


-
-
-
+

-
+
+
+


-
-
-
-
+

-
+
-
-
-
-
-
-
+
+
+
+
+

-
+
-
-
-
-
-
-
+
+
+
+
+

-
+
+
+


-
-
-
-
+

-
+
+
+
%post -n %{libobjfw_pkgname} -p /sbin/ldconfig
%postun -n %{libobjfw_pkgname} -p /sbin/ldconfig
%post -n %{libobjfwrt_pkgname} -p /sbin/ldconfig
%postun -n %{libobjfwrt_pkgname} -p /sbin/ldconfig
%endif

%files
%license LICENSE.QPL
%license LICENSE.GPLv2
%license LICENSE.GPLv3
%license LICENSE.GPLv2
%license LICENSE.QPL

%files -n %{libobjfw_pkgname}
%{_libdir}/libobjfw.so.%{libobjfw_major}
%{_libdir}/libobjfw.so.%{libobjfw_major}.%{libobjfw_minor}.0
%license LICENSE.QPL
%license LICENSE.GPLv2
%license LICENSE.GPLv3
%license LICENSE.GPLv2
%license LICENSE.QPL
%{_libdir}/libobjfw.so.%{libobjfw_major}
%{_libdir}/libobjfw.so.%{libobjfw_major}.%{libobjfw_minor}.0

%files -n %{libobjfw_pkgname}-devel
%{_libdir}/libobjfw.so
%dir %{_includedir}/ObjFW
%{_includedir}/ObjFW
%license LICENSE.GPLv2
%license LICENSE.GPLv3
%license LICENSE.QPL
%{_bindir}/objfw-compile
%{_bindir}/objfw-config
%{_bindir}/objfw-embed
%{_bindir}/objfw-new
%license LICENSE.QPL
%license LICENSE.GPLv3
%license LICENSE.GPLv2
%{_includedir}/ObjFW
%{_libdir}/libobjfw.so

%files -n %{libobjfwrt_pkgname}
%{_libdir}/libobjfwrt.so.%{libobjfwrt_major}
%{_libdir}/libobjfwrt.so.%{libobjfwrt_major}.%{libobjfwrt_minor}.0
%license LICENSE.QPL
%license LICENSE.GPLv2
%license LICENSE.GPLv3
%license LICENSE.GPLv2
%license LICENSE.QPL
%{_libdir}/libobjfwrt.so.%{libobjfwrt_major}
%{_libdir}/libobjfwrt.so.%{libobjfwrt_major}.%{libobjfwrt_minor}.0

%files -n %{libobjfwrt_pkgname}-devel
%{_libdir}/libobjfwrt.so
%{_includedir}/ObjFWRT/ObjFWRT.h
%license LICENSE.QPL
%license LICENSE.GPLv2
%license LICENSE.GPLv3
%license LICENSE.GPLv2
%license LICENSE.QPL
%{_includedir}/ObjFWRT
%{_libdir}/libobjfwrt.so

%files -n %{libobjfwtls_pkgname}
%{_libdir}/libobjfwtls.so.%{libobjfwtls_major}
%{_libdir}/libobjfwtls.so.%{libobjfwtls_major}.%{libobjfwtls_minor}.0
%license LICENSE.QPL
%license LICENSE.GPLv2
%license LICENSE.GPLv3
%license LICENSE.GPLv2
%license LICENSE.QPL
%{_libdir}/libobjfwtls.so.%{libobjfwtls_major}
%{_libdir}/libobjfwtls.so.%{libobjfwtls_major}.%{libobjfwtls_minor}.0

%files -n %{libobjfwtls_pkgname}-devel
%{_libdir}/libobjfwtls.so
%{_includedir}/ObjFWTLS/ObjFWTLS.h
%license LICENSE.QPL
%license LICENSE.GPLv2
%license LICENSE.GPLv3
%license LICENSE.GPLv2
%license LICENSE.QPL
%{_includedir}/ObjFWTLS
%{_libdir}/libobjfwtls.so

%files -n ofarc
%{_bindir}/ofarc
%{_datadir}/ofarc/lang/de.json
%{_datadir}/ofarc/lang/languages.json
%license LICENSE.QPL
%license LICENSE.GPLv2
%license LICENSE.GPLv3
%license LICENSE.GPLv2
%license LICENSE.QPL

%files -n ofdns
%{_bindir}/ofdns
%{_datadir}/ofdns/lang/de.json
%{_datadir}/ofdns/lang/languages.json
%license LICENSE.QPL
%{_bindir}/ofarc
%{_datadir}/ofarc

%files -n ofdns
%license LICENSE.GPLv2
%license LICENSE.GPLv3
%license LICENSE.GPLv2
%license LICENSE.QPL

%files -n ofhash
%{_bindir}/ofhash
%{_datadir}/ofhash/lang/de.json
%{_datadir}/ofhash/lang/languages.json
%license LICENSE.QPL
%{_bindir}/ofdns
%{_datadir}/ofdns

%files -n ofhash
%license LICENSE.GPLv2
%license LICENSE.GPLv3
%license LICENSE.GPLv2
%license LICENSE.QPL
%{_bindir}/ofhash
%{_datadir}/ofhash

%files -n ofhttp
%{_bindir}/ofhttp
%{_datadir}/ofhttp/lang/de.json
%{_datadir}/ofhttp/lang/languages.json
%license LICENSE.QPL
%license LICENSE.GPLv2
%license LICENSE.GPLv3
%license LICENSE.GPLv2
%license LICENSE.QPL
%{_bindir}/ofhttp
%{_datadir}/ofhttp

Modified src/Makefile from [3a642b130e] to [176138bf55].

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
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







-






+
+









+






+






-







-
















-










-









-
-







-







       OFConstantString.m		\
       OFCountedSet.m			\
       OFData.m				\
       OFData+CryptographicHashing.m	\
       OFData+MessagePackParsing.m	\
       OFDate.m				\
       OFDictionary.m			\
       OFEmbeddedURIHandler.m		\
       OFEnumerator.m			\
       OFFileManager.m			\
       OFGZIPStream.m			\
       OFHMAC.m				\
       OFINICategory.m			\
       OFINIFile.m			\
       OFIRI.m				\
       OFIRIHandler.m			\
       OFInflate64Stream.m		\
       OFInflateStream.m		\
       OFInvocation.m			\
       OFLHAArchive.m			\
       OFLHAArchiveEntry.m		\
       OFList.m				\
       OFLocale.m			\
       OFMD5Hash.m			\
       OFMapTable.m			\
       OFMatrix4x4.m			\
       OFMemoryStream.m			\
       OFMessagePackExtension.m		\
       OFMethodSignature.m		\
       OFMutableArray.m			\
       OFMutableData.m			\
       OFMutableDictionary.m		\
       OFMutableIRI.m			\
       OFMutableLHAArchiveEntry.m	\
       OFMutablePair.m			\
       OFMutableSet.m			\
       OFMutableString.m		\
       OFMutableTarArchiveEntry.m	\
       OFMutableTriple.m		\
       OFMutableURI.m			\
       OFMutableZIPArchiveEntry.m	\
       OFNotification.m			\
       OFNotificationCenter.m		\
       OFNull.m				\
       OFNumber.m			\
       OFObject.m			\
       OFObject+KeyValueCoding.m	\
       OFObject+Serialization.m		\
       OFOnce.m				\
       OFOptionsParser.m		\
       OFPBKDF2.m			\
       OFPair.m				\
       OFRIPEMD160Hash.m		\
       OFRunLoop.m			\
       OFSHA1Hash.m			\
       OFSHA224Hash.m			\
       OFSHA224Or256Hash.m		\
       OFSHA256Hash.m			\
       OFSHA384Hash.m			\
       OFSHA384Or512Hash.m		\
       OFSHA512Hash.m			\
       OFScrypt.m			\
       OFSecureData.m			\
       OFSeekableStream.m		\
       OFSerialization.m		\
       OFSet.m				\
       OFSettings.m			\
       OFSortedList.m			\
       OFStdIOStream.m			\
       OFStream.m			\
       OFString.m			\
       OFString+CryptographicHashing.m	\
       OFString+JSONParsing.m		\
       OFString+PercentEncoding.m	\
       OFString+PropertyListParsing.m	\
       OFString+Serialization.m		\
       OFString+XMLEscaping.m		\
       OFString+XMLUnescaping.m		\
       ${OF_SUBPROCESS_M}		\
       OFSystemInfo.m			\
       OFTarArchive.m			\
       OFTarArchiveEntry.m		\
       OFThread.m			\
       OFTimer.m			\
       OFTriple.m			\
       OFURI.m				\
       OFURIHandler.m			\
       OFUUID.m				\
       OFValue.m			\
       OFXMLAttribute.m			\
       OFXMLCDATA.m			\
       OFXMLCharacters.m		\
       OFXMLComment.m			\
       OFXMLElement.m			\
       OFXMLElement+Serialization.m	\
       OFXMLElementBuilder.m		\
       OFXMLNode.m			\
       OFXMLParser.m			\
       OFXMLProcessingInstruction.m	\
       OFZIPArchive.m			\
       OFZIPArchiveEntry.m		\
       ${USE_SRCS_FILES}		\
138
139
140
141
142
143
144

145
146
147
148
149
150
151
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148







+







	       OFHTTPCookieManager.m		\
	       OFHTTPRequest.m			\
	       OFHTTPResponse.m			\
	       OFHTTPServer.m			\
	       OFSequencedPacketSocket.m	\
	       OFSocket.m			\
	       OFStreamSocket.m			\
	       OFSystemInfo+NetworkInterfaces.m	\
	       OFTCPSocket.m			\
	       OFTLSStream.m			\
	       OFUDPSocket.m			\
	       ${USE_SRCS_APPLETALK}		\
	       ${USE_SRCS_IPX}			\
	       ${USE_SRCS_UNIX_SOCKETS}
SRCS_APPLETALK = OFDDPSocket.m
184
185
186
187
188
189
190
191

192
193
194
195
196
197

198
199
200
201
202
203
204
181
182
183
184
185
186
187

188
189
190
191
192
193
194
195
196
197
198
199
200
201
202







-
+






+







	    objfw-defs.h			\
	    platform.h				\
	    ${USE_INCLUDES_ATOMIC}

SRCS += OFASPrintF.m			\
	OFAdjacentArray.m		\
	OFAdjacentSubarray.m		\
	OFArchiveURIHandler.m		\
	OFArchiveIRIHandler.m		\
	OFBase64.m			\
	OFBitSetCharacterSet.m		\
	OFBytesValue.m			\
	OFCRC16.m			\
	OFCRC32.m			\
	OFCountedMapTableSet.m		\
	OFEmbeddedIRIHandler.m		\
	OFHuffmanTree.m			\
	OFINIFileSettings.m		\
	OFInvertedCharacterSet.m	\
	OFLHADecompressingStream.m	\
	OFMapTableDictionary.m		\
	OFMapTableSet.m			\
	OFMutableAdjacentArray.m	\
216
217
218
219
220
221
222
223

224
225
226
227

228
229
230
231
232
233
234
214
215
216
217
218
219
220

221
222
223
224

225
226
227
228
229
230
231
232







-
+



-
+







	OFStrPTime.m			\
	OFSubarray.m			\
	OFUTF8String.m			\
	${LIBBASES_M}			\
	${RUNTIME_AUTORELEASE_M}	\
	${RUNTIME_INSTANCE_M}		\
	${UNICODE_M}
SRCS_FILES += OFFileURIHandler.m
SRCS_FILES += OFFileIRIHandler.m
SRCS_SOCKETS += OFAsyncIPSocketConnector.m		\
		OFDNSResolverSettings.m			\
		${OF_EPOLL_KERNEL_EVENT_OBSERVER_M}	\
		OFHTTPURIHandler.m			\
		OFHTTPIRIHandler.m			\
		OFHostAddressResolver.m			\
		OFKernelEventObserver.m			\
		${OF_KQUEUE_KERNEL_EVENT_OBSERVER_M}	\
		${OF_POLL_KERNEL_EVENT_OBSERVER_M}	\
		${OF_SELECT_KERNEL_EVENT_OBSERVER_M}	\
		OFTCPSocketSOCKS5Connector.m
SRCS_WINDOWS += platform/Windows/OFWin32ConsoleStdIOStream.m	\
262
263
264
265
266
267
268








260
261
262
263
264
265
266
267
268
269
270
271
272
273
274







+
+
+
+
+
+
+
+
AMIGA_LIB_LIBS := -Lruntime -Lruntime/linklib -lobjfwrt.library.amigalib ${LIBS}
LIBS := -Lruntime -Lruntime/linklib ${RUNTIME_LIBS} ${REEXPORT_RUNTIME} ${LIBS}
RCFLAGS = --use-temp-file						\
	  -DOBJFW_LIB_MAJOR=${OBJFW_LIB_MAJOR}				\
	  -DOBJFW_LIB_MINOR=${OBJFW_LIB_MINOR}				\
	  -DOBJFW_LIB_VERSION=\"${OBJFW_LIB_MAJOR}.${OBJFW_LIB_MINOR}\" \
	  -DOBJFW_SHARED_LIB=\"${OBJFW_SHARED_LIB}\"

uninstall-extra:
	for i in platform/GCC4 platform/GCC4.7 platform/PowerPC platform/macOS \
	    platform/x86 platform ""; do \
		if test -d ${DESTDIR}${includedir}/${includesubdir}/$$i; then \
			rmdir ${DESTDIR}${includedir}/${includesubdir}/$$i; \
		fi; \
	done

Modified src/OFASPrintF.h from [090f42d33a] to [a9b63bfa65].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFASPrintF.m from [882db55cea] to [84a6c0408a].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
21
22
23
24
25
26
27
28

29
30
31
32
33
34
35
21
22
23
24
25
26
27

28
29
30
31
32
33
34
35







-
+







#include <stdarg.h>
#include <stdbool.h>

#ifdef HAVE_WCHAR_H
# include <wchar.h>
#endif

#ifdef HAVE_ASPRINTF_L
#if defined(HAVE_ASPRINTF_L) || defined(HAVE_USELOCALE)
# include <locale.h>
#endif
#ifdef HAVE_XLOCALE_H
# include <xlocale.h>
#endif

#ifdef OF_HAVE_SYS_TYPES_H
79
80
81
82
83
84
85
86

87
88
89
90
91
92
93
79
80
81
82
83
84
85

86
87
88
89
90
91
92
93







-
+







		lengthModifierZ,
		lengthModifierT,
		lengthModifierCapitalL
	} lengthModifier;
	bool useLocale;
};

#ifdef HAVE_ASPRINTF_L
#if defined(HAVE_ASPRINTF_L) || defined(HAVE_USELOCALE)
static locale_t cLocale;

OF_CONSTRUCTOR()
{
	if ((cLocale = newlocale(LC_ALL_MASK, "C", NULL)) == NULL)
		@throw [OFInitializationFailedException exception];
}
373
374
375
376
377
378
379
380

381
382
383
384
385
386
387
373
374
375
376
377
378
379

380
381
382
383
384
385
386
387







-
+







}

static bool
formatConversionSpecifierState(struct Context *ctx)
{
	char *tmp = NULL;
	int tmpLen = 0;
#ifndef HAVE_ASPRINTF_L
#if !defined(HAVE_ASPRINTF_L) && !defined(HAVE_USELOCALE)
	OFString *point;
#endif

	if (!appendSubformat(ctx, ctx->format + ctx->i, 1))
		return false;

	switch (ctx->format[ctx->i]) {
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
572
573
574
575
576

577
578
579
580
581
582
583



584
585
586
587
588
589
590
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
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589

590
591
592
593
594



595
596
597
598
599
600
601
602
603
604







-
+





+
+
+
+
+
+
+





-
+





+
+
+
+
+
+
+








-
+




-
-
-
+
+
+







	case 'g':
	case 'G':
	case 'a':
	case 'A':
		switch (ctx->lengthModifier) {
		case lengthModifierNone:
		case lengthModifierL:
#ifdef HAVE_ASPRINTF_L
#if defined(HAVE_ASPRINTF_L)
			if (!ctx->useLocale)
				tmpLen = asprintf_l(&tmp, cLocale,
				    ctx->subformat,
				    va_arg(ctx->arguments, double));
			else
#elif defined(HAVE_USELOCALE)
			if (!ctx->useLocale) {
				locale_t previousLocale = uselocale(cLocale);
				tmpLen = asprintf(&tmp, ctx->subformat,
				    va_arg(ctx->arguments, double));
				uselocale(previousLocale);
			} else
#endif
				tmpLen = asprintf(&tmp, ctx->subformat,
				    va_arg(ctx->arguments, double));
			break;
		case lengthModifierCapitalL:
#ifdef HAVE_ASPRINTF_L
#if defined(HAVE_ASPRINTF_L)
			if (!ctx->useLocale)
				tmpLen = asprintf_l(&tmp, cLocale,
				    ctx->subformat,
				    va_arg(ctx->arguments, long double));
			else
#elif defined(HAVE_USELOCALE)
			if (!ctx->useLocale) {
				locale_t previousLocale = uselocale(cLocale);
				tmpLen = asprintf(&tmp, ctx->subformat,
				    va_arg(ctx->arguments, long double));
				uselocale(previousLocale);
			} else
#endif
				tmpLen = asprintf(&tmp, ctx->subformat,
				    va_arg(ctx->arguments, long double));
			break;
		default:
			return false;
		}

#ifndef HAVE_ASPRINTF_L
#if !defined(HAVE_ASPRINTF_L) && !defined(HAVE_USELOCALE)
		if (tmpLen == -1)
			return false;

		/*
		 * If there's no asprintf_l, we have no other choice than to
		 * use this ugly hack to replace the locale's decimal point
		 * back to ".".
		 * If there's no asprintf_l and no uselocale, we have no other
		 * choice than to use this ugly hack to replace the locale's
		 * decimal point back to ".".
		 */
		point = [OFLocale decimalSeparator];

		if (!ctx->useLocale && point != nil && ![point isEqual: @"."]) {
			void *pool = objc_autoreleasePoolPush();
			char *tmp2;

Modified src/OFAdjacentArray.h from [9facc27db0] to [e6ee87088b].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFAdjacentArray.m from [e305e33733] to [3d57d1e63c].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
18
19
20
21
22
23
24

25
26
27
28
29
30
31







-







#include <stdarg.h>

#import "OFAdjacentArray.h"
#import "OFAdjacentSubarray.h"
#import "OFData.h"
#import "OFMutableAdjacentArray.h"
#import "OFString.h"
#import "OFXMLElement.h"

#import "OFEnumerationMutationException.h"
#import "OFInvalidArgumentException.h"
#import "OFOutOfRangeException.h"

@implementation OFAdjacentArray
- (instancetype)init
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
145
146
147
148
149
150
151

































152
153
154
155
156
157
158







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







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

		[self release];
		@throw e;
	}

	return self;
}

- (instancetype)initWithSerialization: (OFXMLElement *)element
{
	self = [self init];

	@try {
		void *pool = objc_autoreleasePoolPush();

		if ((![element.name isEqual: @"OFArray"] &&
		    ![element.name isEqual: @"OFMutableArray"]) ||
		    ![element.namespace isEqual: OFSerializationNS])
			@throw [OFInvalidArgumentException exception];

		for (OFXMLElement *child in
		    [element elementsForNamespace: OFSerializationNS]) {
			void *pool2 = objc_autoreleasePoolPush();
			id object;

			object = child.objectByDeserializing;
			[_array addItem: &object];
			[object retain];

			objc_autoreleasePoolPop(pool2);
		}

		objc_autoreleasePoolPop(pool);
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (size_t)count
{
	return _array.count;
}

Modified src/OFAdjacentSubarray.h from [08f4f942e1] to [abbd5bb00b].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFAdjacentSubarray.m from [76d5c349a9] to [c5bbd0c071].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFApplication.h from [df94634a83] to [e5cf81a0bb].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
161
162
163
164
165
166
167
168

169
170
171
172
173
174
175
161
162
163
164
165
166
167

168
169
170
171
172
173
174
175







-
+







 * @brief A class which represents the application as an object.
 *
 * In order to create a new OFApplication, you should create a class conforming
 * to the optional @ref OFApplicationDelegate protocol and put
 * `OF_APPLICATION_DELEGATE(NameOfYourClass)` in the .m file of that class.
 *
 * When the application is about to be terminated,
 * @ref OFApplicationDelegate#applicationWillTerminate will be called on the
 * @ref OFApplicationDelegate#applicationWillTerminate: will be called on the
 * delegate and an @ref OFApplicationWillTerminateNotification will be sent.
 */
OF_SUBCLASSING_RESTRICTED
@interface OFApplication: OFObject
{
	OFString *_programName;
	OFArray OF_GENERIC(OFString *) *_arguments;

Modified src/OFApplication.m from [d6f9eb583b] to [594a3c0f6e].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
51
52
53
54
55
56
57

58
59

60
61
62
63
64
65
66
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68







+


+







#if defined(OF_MACOS)
# include <crt_externs.h>
#elif defined(OF_WINDOWS)
# include <windows.h>
extern int _CRT_glob;
extern void __wgetmainargs(int *, wchar_t ***, wchar_t ***, int, int *);
#elif defined(OF_AMIGAOS)
# define Class IntuitionClass
# include <proto/exec.h>
# include <proto/dos.h>
# undef Class
#elif !defined(OF_IOS)
extern char **environ;
#endif

#ifdef OF_PSP
# include <pspkerneltypes.h>
# include <psploadexec.h>

Modified src/OFArchiveEntry.h from [70aea150d9] to [a5b126fe56].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Renamed and modified src/OFArchiveURIHandler.h [7c81cf8db2] to src/OFArchiveIRIHandler.h [328a2eb672].

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
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

-
+













-
+



-
+





-
-
+
+





/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 */

#import "OFURIHandler.h"
#import "OFIRIHandler.h"

OF_ASSUME_NONNULL_BEGIN

@interface OFArchiveURIHandler: OFURIHandler
@interface OFArchiveIRIHandler: OFIRIHandler
@end

#ifdef __cplusplus
extern "C" {
#endif
extern OFURI *OFArchiveURIHandlerURIForFileInArchive(OFString *, OFString *,
    OFURI *);
extern OFIRI *OFArchiveIRIHandlerIRIForFileInArchive(OFString *, OFString *,
    OFIRI *);
#ifdef __cplusplus
}
#endif

OF_ASSUME_NONNULL_END

Renamed and modified src/OFArchiveURIHandler.m [010e8050b6] to src/OFArchiveIRIHandler.m [e770c9f1e9].

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
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

-
+

















-
+


+



-





-
+












-
+


-
-
+
+


-
+


-
+


-
-
+
+















-
-
+
+





-
+





-
+







-
+










-
+



-
+










-
+



-
+















-
+






-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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"

#include <errno.h>

#import "OFArchiveURIHandler.h"
#import "OFArchiveIRIHandler.h"
#import "OFCharacterSet.h"
#import "OFGZIPStream.h"
#import "OFIRI.h"
#import "OFLHAArchive.h"
#import "OFStream.h"
#import "OFTarArchive.h"
#import "OFURI.h"
#import "OFZIPArchive.h"

#import "OFInvalidArgumentException.h"
#import "OFOpenItemFailedException.h"

@interface OFArchiveURIHandlerPathAllowedCharacterSet: OFCharacterSet
@interface OFArchiveIRIHandlerPathAllowedCharacterSet: OFCharacterSet
{
	OFCharacterSet *_characterSet;
	bool (*_characterIsMember)(id, SEL, OFUnichar);
}
@end

static OFCharacterSet *pathAllowedCharacters;

static void
initPathAllowedCharacters(void)
{
	pathAllowedCharacters =
	    [[OFArchiveURIHandlerPathAllowedCharacterSet alloc] init];
	    [[OFArchiveIRIHandlerPathAllowedCharacterSet alloc] init];
}

@implementation OFArchiveURIHandler
- (OFStream *)openItemAtURI: (OFURI *)URI mode: (OFString *)mode
@implementation OFArchiveIRIHandler
- (OFStream *)openItemAtIRI: (OFIRI *)IRI mode: (OFString *)mode
{
	void *pool = objc_autoreleasePoolPush();
	OFString *scheme = URI.scheme;
	OFString *scheme = IRI.scheme;
	OFString *percentEncodedPath, *path;
	size_t pos;
	OFURI *archiveURI;
	OFIRI *archiveIRI;
	OFStream *stream;

	if (URI.host != nil || URI.port != nil || URI.user != nil ||
	    URI.password != nil || URI.query != nil || URI.fragment != nil)
	if (IRI.host != nil || IRI.port != nil || IRI.user != nil ||
	    IRI.password != nil || IRI.query != nil || IRI.fragment != nil)
		@throw [OFInvalidArgumentException exception];

	if (![mode isEqual: @"r"])
		/*
		 * Writing has some implications that are not decided yet: Will
		 * it always append to an archive? What happens if the file
		 * already exists?
		 */
		@throw [OFInvalidArgumentException exception];

	/*
	 * GZIP only compresses one file and thus has no path inside an
	 * archive.
	 */
	if ([scheme isEqual: @"gzip"]) {
		stream = [OFURIHandler openItemAtURI: [OFURI URIWithString:
							  URI.path]
		stream = [OFIRIHandler openItemAtIRI: [OFIRI IRIWithString:
							  IRI.path]
						mode: @"r"];
		stream = [OFGZIPStream streamWithStream: stream mode: @"r"];
		goto end;
	}

	percentEncodedPath = URI.percentEncodedPath;
	percentEncodedPath = IRI.percentEncodedPath;
	pos = [percentEncodedPath rangeOfString: @"!"].location;

	if (pos == OFNotFound)
		@throw [OFInvalidArgumentException exception];

	archiveURI = [OFURI URIWithString:
	archiveIRI = [OFIRI IRIWithString:
	    [percentEncodedPath substringWithRange: OFMakeRange(0, pos)]
	    .stringByRemovingPercentEncoding];
	path = [percentEncodedPath substringWithRange:
	    OFMakeRange(pos + 1, percentEncodedPath.length - pos - 1)]
	    .stringByRemovingPercentEncoding;

	if ([scheme isEqual: @"lha"]) {
		OFLHAArchive *archive = [OFLHAArchive archiveWithURI: archiveURI
		OFLHAArchive *archive = [OFLHAArchive archiveWithIRI: archiveIRI
								mode: @"r"];
		OFLHAArchiveEntry *entry;

		while ((entry = [archive nextEntry]) != nil) {
			if ([entry.fileName isEqual: path]) {
				stream = [archive streamForReadingCurrentEntry];
				goto end;
			}
		}

		@throw [OFOpenItemFailedException exceptionWithURI: URI
		@throw [OFOpenItemFailedException exceptionWithIRI: IRI
							      mode: mode
							     errNo: ENOENT];
	} else if ([scheme isEqual: @"tar"]) {
		OFTarArchive *archive = [OFTarArchive archiveWithURI: archiveURI
		OFTarArchive *archive = [OFTarArchive archiveWithIRI: archiveIRI
								mode: @"r"];
		OFTarArchiveEntry *entry;

		while ((entry = [archive nextEntry]) != nil) {
			if ([entry.fileName isEqual: path]) {
				stream = [archive streamForReadingCurrentEntry];
				goto end;
			}
		}

		@throw [OFOpenItemFailedException exceptionWithURI: URI
		@throw [OFOpenItemFailedException exceptionWithIRI: IRI
							      mode: mode
							     errNo: ENOENT];
	} else if ([scheme isEqual: @"zip"]) {
		OFZIPArchive *archive = [OFZIPArchive archiveWithURI: archiveURI
		OFZIPArchive *archive = [OFZIPArchive archiveWithIRI: archiveIRI
								mode: @"r"];

		stream = [archive streamForReadingFile: path];
	} else
		@throw [OFInvalidArgumentException exception];

end:
	stream = [stream retain];

	objc_autoreleasePoolPop(pool);

	return [stream autorelease];
}
@end

@implementation OFArchiveURIHandlerPathAllowedCharacterSet
@implementation OFArchiveIRIHandlerPathAllowedCharacterSet
- (instancetype)init
{
	self = [super init];

	@try {
		_characterSet =
		    [[OFCharacterSet URIPathAllowedCharacterSet] retain];
		    [[OFCharacterSet IRIPathAllowedCharacterSet] retain];
		_characterIsMember = (bool (*)(id, SEL, OFUnichar))
		    [_characterSet methodForSelector:
		    @selector(characterIsMember:)];
	} @catch (id e) {
		[self release];
		@throw e;
	}
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
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







-
-
-
+
+
+


-
+

-
+






-
+




-
+






- (bool)characterIsMember: (OFUnichar)character
{
	return (character != '!' && _characterIsMember(_characterSet,
	    @selector(characterIsMember:), character));
}
@end

OFURI *
OFArchiveURIHandlerURIForFileInArchive(OFString *scheme,
    OFString *pathInArchive, OFURI *archiveURI)
OFIRI *
OFArchiveIRIHandlerIRIForFileInArchive(OFString *scheme,
    OFString *pathInArchive, OFIRI *archiveIRI)
{
	static OFOnceControl onceControl = OFOnceControlInitValue;
	OFMutableURI *ret = [OFMutableURI URIWithScheme: scheme];
	OFMutableIRI *ret = [OFMutableIRI IRIWithScheme: scheme];
	void *pool = objc_autoreleasePoolPush();
	OFString *archiveURIString;
	OFString *archiveIRIString;

	OFOnce(&onceControl, initPathAllowedCharacters);

	pathInArchive = [pathInArchive
	    stringByAddingPercentEncodingWithAllowedCharacters:
	    pathAllowedCharacters];
	archiveURIString = [archiveURI.string
	archiveIRIString = [archiveIRI.string
	    stringByAddingPercentEncodingWithAllowedCharacters:
	    pathAllowedCharacters];

	ret.percentEncodedPath = [OFString
	    stringWithFormat: @"%@!%@", archiveURIString, pathInArchive];
	    stringWithFormat: @"%@!%@", archiveIRIString, pathInArchive];
	[ret makeImmutable];

	objc_autoreleasePoolPop(pool);

	return ret;
}

Modified src/OFArray+Private.h from [9a457a5499] to [6c89dad268].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFArray.h from [f90f803ff9] to [3d63ad7d51].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
21
22
23
24
25
26
27

28
29
30
31
32
33
34







-







#endif

#include <stdarg.h>

#import "OFObject.h"
#import "OFCollection.h"
#import "OFEnumerator.h"
#import "OFSerialization.h"
#import "OFJSONRepresentation.h"
#import "OFMessagePackRepresentation.h"

OF_ASSUME_NONNULL_BEGIN

/** @file */

98
99
100
101
102
103
104
105

106
107
108
109
110
111
112
97
98
99
100
101
102
103

104
105
106
107
108
109
110
111







-
+







 * @class OFArray OFArray.h ObjFW/OFArray.h
 *
 * @brief An abstract class for storing objects in an array.
 *
 * @note Subclasses must implement @ref count and @ref objectAtIndex:.
 */
@interface OFArray OF_GENERIC(ObjectType): OFObject <OFCopying,
    OFMutableCopying, OFCollection, OFSerialization, OFJSONRepresentation,
    OFMutableCopying, OFCollection, OFJSONRepresentation,
    OFMessagePackRepresentation>
#if !defined(OF_HAVE_GENERICS) && !defined(DOXYGEN)
# define ObjectType id
#endif
/**
 * @brief The objects of the array as a C array.
 *
401
402
403
404
405
406
407














408
409
410
411
412
413
414
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+







 * @param options The options to use when sorting the array
 * @return A sorted copy of the array
 */
- (OFArray OF_GENERIC(ObjectType) *)
    sortedArrayUsingSelector: (SEL)selector
		     options: (OFArraySortOptions)options;

/**
 * @brief Returns a copy of the array sorted using the specified function and
 *	  options.
 *
 * @param compare The function to use to sort the array
 * @param context Context passed to the function to compare
 * @param options The options to use when sorting the array
 * @return A sorted copy of the array
 */
- (OFArray OF_GENERIC(ObjectType) *)
    sortedArrayUsingFunction: (OFCompareFunction)compare
		     context: (nullable void *)context
		     options: (OFArraySortOptions)options;

#ifdef OF_HAVE_BLOCKS
/**
 * @brief Returns a copy of the array sorted using the specified selector and
 *	  options.
 *
 * @param comparator The comparator to use to sort the array
 * @param options The options to use when sorting the array

Modified src/OFArray.m from [26b9b812f3] to [79e2c56f24].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
21
22
23
24
25
26
27

28
29
30
31
32
33
34







-







#import "OFArray.h"
#import "OFArray+Private.h"
#import "OFAdjacentArray.h"
#import "OFData.h"
#import "OFNull.h"
#import "OFString.h"
#import "OFSubarray.h"
#import "OFXMLElement.h"

#import "OFEnumerationMutationException.h"
#import "OFInvalidArgumentException.h"
#import "OFOutOfRangeException.h"

static struct {
	Class isa;
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
82
83
84
85
86
87
88





89
90
91
92
93
94
95







-
-
-
-
-







- (instancetype)initWithObjects: (id const *)objects
			  count: (size_t)count
{
	return (id)[[OFAdjacentArray alloc] initWithObjects: objects
						      count: count];
}

- (instancetype)initWithSerialization: (OFXMLElement *)element
{
	return (id)[[OFAdjacentArray alloc] initWithSerialization: element];
}

- (instancetype)retain
{
	return self;
}

- (instancetype)autorelease
{
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
204
205
206
207
208
209
210





211
212
213
214
215
216
217







-
-
-
-
-







{
	OF_INVALID_INIT_METHOD
}

- (instancetype)initWithObjects: (id const *)objects
			  count: (size_t)count
{
	OF_INVALID_INIT_METHOD
}

- (instancetype)initWithSerialization: (OFXMLElement *)element
{
	OF_INVALID_INIT_METHOD
}

- (size_t)count
{
	OF_UNRECOGNIZED_SELECTOR
}
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
572
573
574
575
576
577
578
579
580
581
582
583
584
533
534
535
536
537
538
539



























540
541
542
543
544
545
546







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







	objc_autoreleasePoolPop(pool);

	[ret makeImmutable];

	return [ret autorelease];
}

- (OFXMLElement *)XMLElementBySerializing
{
	void *pool = objc_autoreleasePoolPush();
	OFXMLElement *element;

	if ([self isKindOfClass: [OFMutableArray class]])
		element = [OFXMLElement elementWithName: @"OFMutableArray"
					      namespace: OFSerializationNS];
	else
		element = [OFXMLElement elementWithName: @"OFArray"
					      namespace: OFSerializationNS];

	for (id <OFSerialization> object in self) {
		void *pool2 = objc_autoreleasePoolPush();

		[element addChild: object.XMLElementBySerializing];

		objc_autoreleasePoolPop(pool2);
	}

	[element retain];

	objc_autoreleasePoolPop(pool);

	return [element autorelease];
}

- (OFString *)JSONRepresentation
{
	return [self of_JSONRepresentationWithOptions: 0 depth: 0];
}

- (OFString *)JSONRepresentationWithOptions:
    (OFJSONRepresentationOptions)options
721
722
723
724
725
726
727










728
729
730
731
732
733
734
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706







+
+
+
+
+
+
+
+
+
+







			      options: (OFArraySortOptions)options
{
	OFMutableArray *new = [[self mutableCopy] autorelease];
	[new sortUsingSelector: selector options: options];
	[new makeImmutable];
	return new;
}

- (OFArray *)sortedArrayUsingFunction: (OFCompareFunction)compare
			      context: (void *)context
			      options: (OFArraySortOptions)options
{
	OFMutableArray *new = [[self mutableCopy] autorelease];
	[new sortUsingFunction: compare context: context options: options];
	[new makeImmutable];
	return new;
}

#ifdef OF_HAVE_BLOCKS
- (OFArray *)sortedArrayUsingComparator: (OFComparator)comparator
				options: (OFArraySortOptions)options
{
	OFMutableArray *new = [[self mutableCopy] autorelease];
	[new sortUsingComparator: comparator options: options];

Modified src/OFAsyncIPSocketConnector.h from [00aff2415e] to [82fab4738c].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFAsyncIPSocketConnector.m from [b9084cfb8c] to [4db6b7d2e4].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFAtomic.h from [25c89d25b5] to [7b3ed1a98e].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
165
166
167
168
169
170
171
172

173
174
175
176
177
178
179
180
181
182
183
184
185
165
166
167
168
169
170
171

172
173
174
175
176
177
178
179
180
181
182
183
184
185







-
+













}

static OF_INLINE void
OFReleaseMemoryBarrier(void)
{
	/* nop */
}
#elif (defined(OF_X86_64) || defined(OF_X86)) && defined(__GNUC__)
#elif (defined(OF_AMD64) || defined(OF_X86)) && defined(__GNUC__)
# import "platform/x86/OFAtomic.h"
#elif defined(OF_POWERPC) && defined(__GNUC__) && !defined(__APPLE_CC__) && \
    !defined(OF_AIX)
# import "platform/PowerPC/OFAtomic.h"
#elif defined(OF_HAVE_ATOMIC_BUILTINS)
# import "platform/GCC4.7/OFAtomic.h"
#elif defined(OF_HAVE_SYNC_BUILTINS)
# import "platform/GCC4/OFAtomic.h"
#elif defined(OF_HAVE_OSATOMIC)
# import "platform/macOS/OFAtomic.h"
#else
# error No atomic operations available!
#endif

Modified src/OFBase64.h from [14838b60d0] to [dc1538a199].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFBase64.m from [7cc5f21d9d] to [65e2efa6c1].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFBitSetCharacterSet.h from [6dd7022dff] to [3881bf645d].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFBitSetCharacterSet.m from [d65aed83c7] to [86d9bb92c4].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFBlock.h from [ae09bf0d6b] to [f1e51ec3d8].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFBlock.m from [ab07b43024] to [d7b2cab799].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFBytesValue.h from [ca1dbf0669] to [fa7ec42d63].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFBytesValue.m from [b331442837] to [b82083e896].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFCRC16.h from [6bd74791bc] to [2c8e24788e].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFCRC16.m from [ba4e599142] to [4dacc44a0d].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFCRC32.h from [139d8dccac] to [854faab2ac].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFCRC32.m from [b50ad38210] to [1fe12fcc7a].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFCharacterSet.h from [20dd965c47] to [380acae6ed].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFCharacterSet.m from [76e8828364] to [272d843979].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFCollection.h from [8d8461caff] to [5762c77876].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFColor.h from [bce9432d45] to [de724e96d7].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFColor.m from [ff82ab6aae] to [2f23670cfa].

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
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

-
+














+
+



+



+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+






+
-
-
-
-
+
+
+
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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"

#include <math.h>

#import "OFColor.h"
#import "OFOnce.h"
#import "OFString.h"

#import "OFInvalidArgumentException.h"

@interface OFColor ()
+ (instancetype)of_alloc;
@end

@interface OFColorSingleton: OFColor
@end

@interface OFColorPlaceholder: OFColorSingleton
@end

#ifdef OF_OBJFW_RUNTIME
@interface OFTaggedPointerColor: OFColorSingleton
@end

static const float allowedImprecision = 0.0000001;
#endif

static struct {
	Class isa;
} placeholder;

#ifdef OF_OBJFW_RUNTIME
static int colorTag;
#endif

@implementation OFColorSingleton
- (instancetype)autorelease
{
	return self;
}

- (instancetype)retain
{
	return self;
}

- (void)release
{
}

- (unsigned int)retainCount
{
	return OFMaxRetainCount;
}
@end

@implementation OFColorPlaceholder
- (instancetype)initWithRed: (float)red
		      green: (float)green
		       blue: (float)blue
		      alpha: (float)alpha
{
#ifdef OF_OBJFW_RUNTIME
	uint8_t redInt = nearbyintf(red * 255);
	uint8_t greenInt = nearbyintf(green * 255);
	uint8_t blueInt = nearbyintf(blue * 255);

	if (fabsf(red * 255 - redInt) < allowedImprecision &&
	    fabsf(green * 255 - greenInt) < allowedImprecision &&
	    fabsf(blue * 255 - blueInt) < allowedImprecision && alpha == 1) {
		id ret = objc_createTaggedPointer(colorTag,
		    (uintptr_t)redInt << 16 | (uintptr_t)greenInt << 8 |
		    (uintptr_t)blueInt);

		if (ret != nil)
			return ret;
	}
#endif

	return (id)[[OFColor of_alloc] initWithRed: red
					     green: green
					      blue: blue
					     alpha: alpha];
}
@end

#ifdef OF_OBJFW_RUNTIME
@implementation OFTaggedPointerColor
- (void)getRed: (float *)red
	 green: (float *)green
	  blue: (float *)blue
	 alpha: (float *)alpha
{
	uintptr_t value = object_getTaggedPointerValue(self);

	*red = (float)(value >> 16) / 255;
	*green = (float)((value >> 8) & 0xFF) / 255;
	*blue = (float)(value & 0xFF) / 255;

	if (alpha != NULL)
		*alpha = 1;
}
@end
#endif

@implementation OFColor
+ (void)initialize
{
	if (self != [OFColor class])
		return;

	placeholder.isa = [OFColorPlaceholder class];
#ifdef OF_OBJFW_RUNTIME
	colorTag =
	    objc_registerTaggedPointerClass([OFTaggedPointerColor class]);
#endif
}

+ (instancetype)of_alloc
{
	return [super alloc];
}

+ (instancetype)alloc
{
	if (self == [OFColor class])
		return (id)&placeholder;

	return [super alloc];
}

#define PREDEFINED_COLOR(name, redValue, greenValue, blueValue)		   \
	static OFColor *name##Color = nil;				   \
									   \
	static void							   \
	initPredefinedColor_##name(void)				   \
	{								   \
		name##Color = [[OFColorSingleton alloc]			   \
		name##Color = [[OFColor alloc] initWithRed: redValue	   \
						     green: greenValue	   \
						      blue: blueValue	   \
						     alpha: 1];		   \
		    initWithRed: redValue				   \
			  green: greenValue				   \
			   blue: blueValue				   \
			  alpha: 1];					   \
	}								   \
									   \
	+ (OFColor *)name						   \
	{								   \
		static OFOnceControl onceControl = OFOnceControlInitValue; \
		OFOnce(&onceControl, initPredefinedColor_##name);	   \
									   \
155
156
157
158
159
160
161











162
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297







+
+
+
+
+
+
+
+
+
+
+

	*red = _red;
	*green = _green;
	*blue = _blue;

	if (alpha != NULL)
		*alpha = _alpha;
}

- (OFString *)description
{
	float red, green, blue, alpha;

	[self getRed: &red green: &green blue: &blue alpha: &alpha];

	return [OFString stringWithFormat:
	    @"<%@ red=%f green=%f blue=%f alpha=%f>",
	    self.class, red, green, blue, alpha];
}
@end

Modified src/OFCondition.h from [2de2d56fa5] to [e9f86d3ccf].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFCondition.m from [28f8553bac] to [46420e8064].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFConstantString.h from [4428a8bf71] to [bf7c0894b9].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFConstantString.m from [3adc07df05] to [01f4965770].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
581
582
583
584
585
586
587
588

589
590
591

592
593
594

595
596
597

598
599
600
601
602
603
604
605
606
607
581
582
583
584
585
586
587

588
589
590

591
592
593

594
595
596

597
598
599
600
601
602
603
604
605
606
607







-
+


-
+


-
+


-
+










- (void)writeToFile: (OFString *)path encoding: (OFStringEncoding)encoding
{
	[self finishInitialization];
	[self writeToFile: path encoding: encoding];
}
#endif

- (void)writeToURI: (OFURI *)URI
- (void)writeToIRI: (OFIRI *)IRI
{
	[self finishInitialization];
	[self writeToURI: URI];
	[self writeToIRI: IRI];
}

- (void)writeToURI: (OFURI *)URI encoding: (OFStringEncoding)encoding
- (void)writeToIRI: (OFIRI *)IRI encoding: (OFStringEncoding)encoding
{
	[self finishInitialization];
	[self writeToURI: URI encoding: encoding];
	[self writeToIRI: IRI encoding: encoding];
}

#ifdef OF_HAVE_BLOCKS
- (void)enumerateLinesUsingBlock: (OFStringLineEnumerationBlock)block
{
	[self finishInitialization];
	[self enumerateLinesUsingBlock: block];
}
#endif
@end

Modified src/OFCountedMapTableSet.h from [1da95cb48f] to [05ce680e3e].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFCountedMapTableSet.m from [d7ae224517] to [7a63d8437b].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
17
18
19
20
21
22
23

24
25
26
27
28
29
30







-








#import "OFCountedMapTableSet.h"
#import "OFArray.h"
#import "OFMapTable.h"
#import "OFMutableMapTableSet.h"
#import "OFString.h"
#import "OFXMLAttribute.h"
#import "OFXMLElement.h"

#import "OFInvalidArgumentException.h"
#import "OFInvalidFormatException.h"
#import "OFEnumerationMutationException.h"
#import "OFOutOfRangeException.h"

@implementation OFCountedMapTableSet
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
109
110
111
112
113
114
115














































116
117
118
119
120
121
122







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







		while ((object = va_arg(arguments, id)) != nil)
			[self addObject: object];
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (instancetype)initWithSerialization: (OFXMLElement *)element
{
	self = [self init];

	@try {
		void *pool = objc_autoreleasePoolPush();

		if (![element.name isEqual: @"OFCountedSet"] ||
		    ![element.namespace isEqual: OFSerializationNS])
			@throw [OFInvalidArgumentException exception];

		for (OFXMLElement *objectElement in
		    [element elementsForName: @"object"
				   namespace: OFSerializationNS]) {
			void *pool2 = objc_autoreleasePoolPush();
			OFXMLElement *object;
			OFXMLAttribute *countAttribute;
			unsigned long long count;

			object = [objectElement elementsForNamespace:
			    OFSerializationNS].firstObject;
			countAttribute =
			    [objectElement attributeForName: @"count"];

			if (object == nil || countAttribute == nil)
				@throw [OFInvalidFormatException exception];

			count = countAttribute.unsignedLongLongValue;
			if (count > SIZE_MAX || count > UINTPTR_MAX)
				@throw [OFOutOfRangeException exception];

			[_mapTable setObject: (void *)(uintptr_t)count
				      forKey: object.objectByDeserializing];

			objc_autoreleasePoolPop(pool2);
		}

		objc_autoreleasePoolPop(pool);
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (size_t)countForObject: (id)object
{
	return (size_t)(uintptr_t)[_mapTable objectForKey: object];
}

Modified src/OFCountedSet.h from [b22ee9691d] to [e9f2d45c4d].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFCountedSet.m from [985e10aa24] to [2550c38e59].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
17
18
19
20
21
22
23

24
25
26
27
28
29
30







-








#include <stdlib.h>

#import "OFCountedSet.h"
#import "OFCountedMapTableSet.h"
#import "OFNumber.h"
#import "OFString.h"
#import "OFXMLElement.h"

static struct {
	Class isa;
} placeholder;

@interface OFCountedSetPlaceholder: OFCountedSet
@end
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
66
67
68
69
70
71
72






73
74
75
76
77
78
79







-
-
-
-
-
-








- (instancetype)initWithObject: (id)firstObject arguments: (va_list)arguments
{
	return (id)[[OFCountedMapTableSet alloc] initWithObject: firstObject
						      arguments: arguments];
}

- (instancetype)initWithSerialization: (OFXMLElement *)element
{
	return (id)[[OFCountedMapTableSet alloc]
	    initWithSerialization: element];
}

- (instancetype)retain
{
	return self;
}

- (instancetype)autorelease
{
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
166
167
168
169
170
171
172




































173
174
175
176
177
178
179







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







}

- (id)mutableCopy
{
	return [[OFCountedSet alloc] initWithSet: self];
}

- (OFXMLElement *)XMLElementBySerializing
{
	void *pool = objc_autoreleasePoolPush();
	OFXMLElement *element;

	element = [OFXMLElement elementWithName: @"OFCountedSet"
				      namespace: OFSerializationNS];

	for (id <OFSerialization> object in self) {
		void *pool2 = objc_autoreleasePoolPush();

		OFXMLElement *objectElement;
		OFString *count;

		count =
		    [OFString stringWithFormat: @"%zu",
						[self countForObject: object]];

		objectElement = [OFXMLElement
		    elementWithName: @"object"
			  namespace: OFSerializationNS];
		[objectElement addAttributeWithName: @"count"
					stringValue: count];
		[objectElement addChild: object.XMLElementBySerializing];
		[element addChild: objectElement];

		objc_autoreleasePoolPop(pool2);
	}

	[element retain];

	objc_autoreleasePoolPop(pool);

	return [element autorelease];
}

#ifdef OF_HAVE_BLOCKS
- (void)enumerateObjectsAndCountUsingBlock: (OFCountedSetEnumerationBlock)block
{
	[self enumerateObjectsUsingBlock: ^ (id object, bool *stop) {
		block(object, [self countForObject: object], stop);
	}];
}

Modified src/OFCryptographicHash.h from [635d4f982a] to [bcec3c10c5].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFDDPSocket.h from [86e7a28476] to [d9acc0eea7].

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
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

-
+


















+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 */

#import "OFDatagramSocket.h"

OF_ASSUME_NONNULL_BEGIN

@class OFString;
@class OFDictionary OF_GENERIC(KeyType, ObjectType);

/**
 * @protocol OFDDPSocketDelegate OFDDPSocket.h ObjFW/OFDDPSocket.h
 *
 * @brief A delegate for OFDDPSocket.
 */
@protocol OFDDPSocketDelegate <OFDatagramSocketDelegate>
39
40
41
42
43
44
45
46

47
48
49
50
51
52
53
40
41
42
43
44
45
46

47
48
49
50
51
52
53
54







-
+







 * @ref OFSocketAddressAppleTalkNode to get the AppleTalk node and
 * @ref OFSocketAddressAppleTalkPort to get the port (sometimes also called
 * socket number).
 *
 * @note On some systems, packets received with the wrong protocol type just
 *	 get filtered by the kernel, however, on other systems, the packet is
 *	 queued up and will raise an @ref OFReadFailedException with the
 *	 @ref errNo set to `ENOMSG` when being received.
 *	 @ref OFReadFailedException#errNo set to `ENOMSG` when being received.
 *
 * @warning Even though the OFCopying protocol is implemented, it does *not*
 *	    return an independent copy of the socket, but instead retains it.
 *	    This is so that the socket can be used as a key for a dictionary,
 *	    so context can be associated with a socket. Using a socket in more
 *	    than one thread at the same time is not thread-safe, even if copy
 *	    was called to create one "instance" for every thread!
77
78
79
80
81
82
83
84

85
86
87
88
89
90
91
92
78
79
80
81
82
83
84

85
86
87
88
89
90
91
92
93







-
+








 * @param port The port to bind to. 0 means to pick one and return it via the
 *	       returned socket address.
 * @param protocolType The DDP protocol type to use. Must not be 0. If you want
 *		       to use DDP directly and not a protocol built on top of
 *		       it, use 11 for compatibility with Open Transport.
 * @return The address on which this socket can be reached
 * @throw OFBindDDPSockeFailedException Binding failed
 * @throw OFAlreadyConnectedException The socket is already bound
 * @throw OFAlreadyOpenException The socket is already bound
 */
- (OFSocketAddress)bindToNetwork: (uint16_t)network
			    node: (uint8_t)node
			    port: (uint8_t)port
		    protocolType: (uint8_t)protocolType;
@end

OF_ASSUME_NONNULL_END

Modified src/OFDDPSocket.m from [d532fdd70f] to [0f90d0e13f].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
18
19
20
21
22
23
24



25
26
27
28

29

30
31

32

33







34
35
36
37
38
39
40
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







+
+
+



-
+

+


+

+

+
+
+
+
+
+
+







#include <errno.h>

#ifdef HAVE_FCNTL_H
# include <fcntl.h>
#endif

#import "OFDDPSocket.h"
#import "OFDictionary.h"
#import "OFNumber.h"
#import "OFPair.h"
#import "OFSocket.h"
#import "OFSocket+Private.h"

#import "OFAlreadyConnectedException.h"
#import "OFAlreadyOpenException.h"
#import "OFBindDDPSocketFailedException.h"
#import "OFGetOptionFailedException.h"
#import "OFInvalidArgumentException.h"
#import "OFNotOpenException.h"
#import "OFOutOfRangeException.h"
#import "OFReadFailedException.h"
#import "OFSetOptionFailedException.h"
#import "OFWriteFailedException.h"

#ifdef HAVE_NET_IF_H
# include <net/if.h>
#endif
#ifdef HAVE_SYS_IOCTL_H
# include <sys/ioctl.h>
#endif

#ifdef OF_HAVE_NETAT_APPLETALK_H
# include <netat/ddp.h>
# include <sys/ioctl.h>

/* Unfortulately, there is no struct for the following in userland headers */
struct ATInterfaceConfig {
63
64
65
66
67
68
69
70

71
72
73
74
75
76
77
76
77
78
79
80
81
82

83
84
85
86
87
88
89
90







-
+







	int flags;
#endif

	if (protocolType == 0)
		@throw [OFInvalidArgumentException exception];

	if (_socket != OFInvalidSocketHandle)
		@throw [OFAlreadyConnectedException exceptionWithSocket: self];
		@throw [OFAlreadyOpenException exceptionWithObject: self];

	address = OFSocketAddressMakeAppleTalk(network, node, port);

#if defined(OF_MACOS)
	if ((_socket = socket(address.sockaddr.at.sat_family,
	    SOCK_RAW | SOCK_CLOEXEC, protocolType)) == OFInvalidSocketHandle)
#elif defined(OF_WINDOWS)

Modified src/OFDNSQuery.h from [b49f52a5a4] to [d9763523d4].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFDNSQuery.m from [eb5858939c] to [f7f99b0724].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
39
40
41
42
43
44
45
46

47
48
49
50
51
52
53
39
40
41
42
43
44
45

46
47
48
49
50
51
52
53







-
+








	@try {
		void *pool = objc_autoreleasePoolPush();

		if (![domainName hasSuffix: @"."])
			domainName = [domainName stringByAppendingString: @"."];

		_domainName = [domainName copy];
		_domainName = [domainName.lowercaseString copy];
		_DNSClass = DNSClass;
		_recordType = recordType;

		objc_autoreleasePoolPop(pool);
	} @catch (id e) {
		[self release];
		@throw e;

Modified src/OFDNSResolver.h from [a91104c174] to [511ca7b000].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
176
177
178
179
180
181
182
183

184
185

186
187
188
189
190
191
192
176
177
178
179
180
181
182

183
184

185
186
187
188
189
190
191
192







-
+

-
+








/**
 * @brief The minimum number of dots for a name to be considered absolute.
 */
@property (nonatomic) unsigned int minNumberOfDotsInAbsoluteName;

/**
 * @brief Whether the resolver uses TCP to talk to a name server.
 * @brief Whether the resolver forces TCP to talk to a name server.
 */
@property (nonatomic) bool usesTCP;
@property (nonatomic) bool forcesTCP;

/**
 * @brief The interval in seconds in which the config should be reloaded.
 *
 * Setting this to 0 disables config reloading.
 */
@property (nonatomic) OFTimeInterval configReloadInterval;

Modified src/OFDNSResolver.m from [9048cbfc52] to [1f222a13ca].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
419
420
421
422
423
424
425
426

427
428
429
430
431
432
433
419
420
421
422
423
424
425

426
427
428
429
430
431
432
433







-
+







{
	OFMutableDictionary *ret = [OFMutableDictionary dictionary];
	OFEnumerator OF_GENERIC(OFMutableArray *) *objectEnumerator;
	OFMutableArray *array;

	for (uint_fast16_t j = 0; j < count; j++) {
		OFString *name = parseName(buffer, length, i,
		    maxAllowedPointers);
		    maxAllowedPointers).lowercaseString;
		OFDNSClass DNSClass;
		OFDNSRecordType recordType;
		uint32_t TTL;
		uint16_t dataLength;
		OFDNSResourceRecord *record;

		if (*i + 10 > length)
674
675
676
677
678
679
680
681

682
683

684
685
686

687
688

689
690
691
692
693
694
695
674
675
676
677
678
679
680

681
682

683
684
685

686
687

688
689
690
691
692
693
694
695







-
+

-
+


-
+

-
+







- (void)setMinNumberOfDotsInAbsoluteName:
    (unsigned int)minNumberOfDotsInAbsoluteName
{
	_settings->_minNumberOfDotsInAbsoluteName =
	    minNumberOfDotsInAbsoluteName;
}

- (bool)usesTCP
- (bool)forcesTCP
{
	return _settings->_usesTCP;
	return _settings->_forcesTCP;
}

- (void)setUsesTCP: (bool)usesTCP
- (void)setForcesTCP: (bool)forcesTCP
{
	_settings->_usesTCP = usesTCP;
	_settings->_forcesTCP = forcesTCP;
}

- (OFTimeInterval)configReloadInterval
{
	return _settings->_configReloadInterval;
}

719
720
721
722
723
724
725
726

727
728
729
730
731
732
733
719
720
721
722
723
724
725

726
727
728
729
730
731
732
733







-
+







		     repeats: false];
	[[OFRunLoop currentRunLoop] addTimer: context->_cancelTimer
				     forMode: runLoopMode];

	nameServer = [context->_settings->_nameServers
	    objectAtIndex: context->_nameServersIndex];

	if (context->_settings->_usesTCP) {
	if (context->_settings->_forcesTCP) {
		OFEnsure(context->_TCPSocket == nil);

		context->_TCPSocket = [[OFTCPSocket alloc] init];
		[_TCPQueries setObject: context forKey: context->_TCPSocket];

		context->_TCPSocket.delegate = self;
		[context->_TCPSocket asyncConnectToHost: nameServer
944
945
946
947
948
949
950
951

952
953
954

955
956
957
958
959
960
961
944
945
946
947
948
949
950

951
952
953

954
955
956
957
958
959
960
961







-
+


-
+







		if ((buffer[2] & 0x78) != (queryDataBuffer[2] & 0x78))
			@throw [OFInvalidServerResponseException exception];

		/* TC */
		if (buffer[2] & 0x02) {
			OFRunLoopMode runLoopMode;

			if (context->_settings->_usesTCP)
			if (context->_settings->_forcesTCP)
				@throw [OFTruncatedDataException exception];

			context->_settings->_usesTCP = true;
			context->_settings->_forcesTCP = true;
			runLoopMode = [OFRunLoop currentRunLoop].currentMode;
			[self of_sendQueryForContext: context
					 runLoopMode: runLoopMode];
			return false;
		}

		/* RCODE */

Modified src/OFDNSResolverSettings.h from [1250cc4b4c] to [59a97ffd04].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
27
28
29
30
31
32
33
34

35
36
37
38
39
40
41
42
43
27
28
29
30
31
32
33

34
35
36
37
38
39
40
41
42
43







-
+









	OFDictionary OF_GENERIC(OFString *, OFArray OF_GENERIC(OFString *) *)
	    *_staticHosts;
	OFArray OF_GENERIC(OFString *) *_nameServers;
	OFString *_Nullable _localDomain;
	OFArray OF_GENERIC(OFString *) *_searchDomains;
	OFTimeInterval _timeout;
	unsigned int _maxAttempts, _minNumberOfDotsInAbsoluteName;
	bool _usesTCP;
	bool _forcesTCP;
	OFTimeInterval _configReloadInterval;
@protected
	OFDate *_lastConfigReload;
}

- (void)reload;
@end

OF_ASSUME_NONNULL_END

Modified src/OFDNSResolverSettings.m from [1a84838633] to [179fc83ef4].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
28
29
30
31
32
33
34



35
36

37
38
39
40
41
42
43
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47







+
+
+


+







#import "OFString.h"
#ifdef OF_WINDOWS
# import "OFWindowsRegistryKey.h"
#endif

#import "OFInvalidFormatException.h"
#import "OFOpenItemFailedException.h"
#ifdef OF_WINDOWS
# import "OFOpenWindowsRegistryKeyFailedException.h"
#endif
#import "OFOutOfMemoryException.h"
#import "OFOutOfRangeException.h"
#import "OFUndefinedKeyException.h"

#ifdef OF_WINDOWS
# define interface struct
# include <iphlpapi.h>
# undef interface
#endif

209
210
211
212
213
214
215
216

217
218
219
220
221
222
223
213
214
215
216
217
218
219

220
221
222
223
224
225
226
227







-
+







		copy->_nameServers = [_nameServers copy];
		copy->_localDomain = [_localDomain copy];
		copy->_searchDomains = [_searchDomains copy];
		copy->_timeout = _timeout;
		copy->_maxAttempts = _maxAttempts;
		copy->_minNumberOfDotsInAbsoluteName =
		    _minNumberOfDotsInAbsoluteName;
		copy->_usesTCP = _usesTCP;
		copy->_forcesTCP = _forcesTCP;
		copy->_configReloadInterval = _configReloadInterval;
		copy->_lastConfigReload = [_lastConfigReload copy];
	} @catch (id e) {
		[copy release];
		@throw e;
	}

237
238
239
240
241
242
243
244

245
246
247
248
249
250
251
241
242
243
244
245
246
247

248
249
250
251
252
253
254
255







-
+








	[_searchDomains release];
	_searchDomains = nil;

	_timeout = 2;
	_maxAttempts = 3;
	_minNumberOfDotsInAbsoluteName = 1;
	_usesTCP = false;
	_forcesTCP = false;
#ifndef OF_NINTENDO_3DS
	_configReloadInterval = 2;
#else
	_configReloadInterval = 0;
#endif
}

286
287
288
289
290
291
292
293
294




295
296
297
298
299
300
301
290
291
292
293
294
295
296


297
298
299
300
301
302
303
304
305
306
307







-
-
+
+
+
+







			continue;

		address = components.firstObject;
		hosts = [components objectsInRange:
		    OFMakeRange(1, components.count - 1)];

		for (OFString *host in hosts) {
			OFMutableArray *addresses =
			    [staticHosts objectForKey: host];
			OFMutableArray *addresses;

			host = host.lowercaseString;
			addresses = [staticHosts objectForKey: host];

			if (addresses == nil) {
				addresses = [OFMutableArray array];
				[staticHosts setObject: addresses forKey: host];
			}

			[addresses addObject: address];
339
340
341
342
343
344
345
346

347
348
349
350
351
352
353
345
346
347
348
349
350
351

352
353
354
355
356
357
358
359







-
+








			_maxAttempts = (unsigned int)number;
		} else if ([option hasPrefix: @"reload-period:"]) {
			option = [option substringFromIndex: 14];

			_configReloadInterval = option.unsignedLongLongValue;
		} else if ([option isEqual: @"tcp"])
			_usesTCP = true;
			_forcesTCP = true;
	} @catch (OFInvalidFormatException *e) {
	}
}

- (void)parseResolvConf: (OFString *)path
{
	void *pool = objc_autoreleasePoolPush();
443
444
445
446
447
448
449
450
451



452
453





454
455
456
457
458
459
460
449
450
451
452
453
454
455


456
457
458
459

460
461
462
463
464
465
466
467
468
469
470
471







-
-
+
+
+

-
+
+
+
+
+







	PIP_ADDR_STRING iter;

	if (GetNetworkParams(fixedInfo, &length) != ERROR_SUCCESS)
		return;

	nameServers = [OFMutableArray array];

	for (iter = &fixedInfo->DnsServerList; iter != NULL; iter = iter->Next)
		[nameServers addObject:
	for (iter = &fixedInfo->DnsServerList; iter != NULL;
	    iter = iter->Next) {
		OFString *nameServer =
		    [OFString stringWithCString: iter->IpAddress.String
				       encoding: encoding]];
				       encoding: encoding];

		if (nameServer.length > 0)
			[nameServers addObject: nameServer];
	}

	if (nameServers.count > 0) {
		[nameServers makeImmutable];
		_nameServers = [nameServers copy];
	}

	if (fixedInfo->DomainName[0] != '\0')
489
490
491
492
493
494
495
496
497




498
499
500
501
502
503
504
500
501
502
503
504
505
506


507
508
509
510
511
512
513
514
515
516
517







-
-
+
+
+
+







			continue;

		address = components.firstObject;
		hosts = [components objectsInRange:
		    OFMakeRange(1, components.count - 1)];

		for (OFString *host in hosts) {
			OFMutableArray *addresses =
			    [staticHosts objectForKey: host];
			OFMutableArray *addresses;

			host = host.lowercaseString;
			addresses = [staticHosts objectForKey: host];

			if (addresses == nil) {
				addresses = [OFMutableArray array];
				[staticHosts setObject: addresses forKey: host];
			}

			[addresses addObject: address];
598
599
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
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
647
648
649
650
651
652
653
654
655
656
657
658
659
660







-

-
+

+
















+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







		_nameServers = [nameServers copy];
	}
}
#endif

- (void)reload
{
	void *pool;
#ifdef OF_WINDOWS
	OFString *path;
	OFString *path = nil;
#endif
	void *pool;

	/*
	 * TODO: Rather than reparsing every time, check what actually changed
	 *	 (mtime) and only reset those.
	 */

	if (_lastConfigReload != nil && _configReloadInterval > 0 &&
	    _lastConfigReload.timeIntervalSinceNow < _configReloadInterval)
		return;

	pool = objc_autoreleasePoolPush();

	[self setDefaults];

#if defined(OF_WINDOWS)
# ifdef OF_HAVE_FILES
	@try {
	OFWindowsRegistryKey *key = [[OFWindowsRegistryKey localMachineKey]
		   openSubkeyAtPath: @"SYSTEM\\CurrentControlSet\\Services\\"
				     @"Tcpip\\Parameters"
		       accessRights: KEY_QUERY_VALUE
			    options: 0];
	path = [[[key stringForValueNamed: @"DataBasePath"]
	    stringByAppendingPathComponent: @"hosts"]
	    stringByExpandingWindowsEnvironmentStrings];
		OFWindowsRegistryKey *key;

		key = [[OFWindowsRegistryKey localMachineKey]
		    openSubkeyAtPath: @"SYSTEM\\CurrentControlSet\\Services\\"
				      @"Tcpip\\Parameters"
			accessRights: KEY_QUERY_VALUE
			     options: 0];
		path = [[[key stringForValueNamed: @"DataBasePath"]
		   stringByAppendingPathComponent: @"hosts"]
		   stringByExpandingWindowsEnvironmentStrings];
	} @catch (OFOpenWindowsRegistryKeyFailedException *e) {
		/* Ignore */
	} @catch (OFUndefinedKeyException *e) {
		/* Ignore */
	}

	if (path != nil)
		[self parseHosts: path];
# endif

	[self obtainWindowsSystemConfig];
#elif defined(OF_MORPHOS)

Modified src/OFDNSResourceRecord.h from [30273f1f1b] to [967b25e8fc].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFDNSResourceRecord.m from [b7ec251a31] to [b264bcb878].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFDNSResponse.h from [229f42ebfc] to [2edd119b7d].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFDNSResponse.m from [6e61ece6f0] to [ced7000804].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFData+CryptographicHashing.h from [7264dfad2c] to [6577c2d747].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFData+CryptographicHashing.m from [caf70aabc2] to [d27651b9f8].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFData+MessagePackParsing.h from [1a7c410992] to [b81c76becd].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFData+MessagePackParsing.m from [8bd7ef8227] to [5961e97b5f].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFData.h from [750f7eff94] to [c6b9b129b7].

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
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

-
+














-






-
-
+
+















-
-
-


-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 */

#import "OFObject.h"
#import "OFSerialization.h"
#import "OFMessagePackRepresentation.h"

/*! @file */

OF_ASSUME_NONNULL_BEGIN

@class OFString;
@class OFURI;
@class OFIRI;
@class OFString;

/**
 * @brief Options for searching in data.
 *
 * This is a bit mask.
 */
typedef enum {
	/** Search backwards in the data */
	OFDataSearchBackwards = 1
} OFDataSearchOptions;

/**
 * @class OFData OFData.h ObjFW/OFData.h
 *
 * @brief A class for storing arbitrary data in an array.
 *
 * For security reasons, serialization and deserialization is only implemented
 * for OFData with item size 1.
 */
@interface OFData: OFObject <OFCopying, OFMutableCopying, OFComparing,
    OFSerialization, OFMessagePackRepresentation>
    OFMessagePackRepresentation>
{
	unsigned char *_Nullable _items;
	size_t _count, _itemSize;
	bool _freeWhenDone;
@private
	OFData *_Nullable _parentData;
	OF_RESERVE_IVARS(OFData, 4)
163
164
165
166
167
168
169
170

171
172

173
174
175

176
177
178
179
180
181
182
159
160
161
162
163
164
165

166
167

168
169
170

171
172
173
174
175
176
177
178







-
+

-
+


-
+







 * @return A new autoreleased OFData
 */
+ (instancetype)dataWithContentsOfFile: (OFString *)path;
#endif

/**
 * @brief Creates a new OFData with an item size of 1, containing the data of
 *	  the specified URI.
 *	  the specified IRI.
 *
 * @param URI The URI to the contents for the OFData
 * @param IRI The IRI to the contents for the OFData
 * @return A new autoreleased OFData
 */
+ (instancetype)dataWithContentsOfURI: (OFURI *)URI;
+ (instancetype)dataWithContentsOfIRI: (OFIRI *)IRI;

/**
 * @brief Creates a new OFData with an item size of 1, containing the data of
 *	  the hex string representation.
 *
 * @param string The hex string representation of the data
 * @return A new autoreleased OFData
266
267
268
269
270
271
272
273

274
275

276
277
278

279
280
281
282
283
284
285
262
263
264
265
266
267
268

269
270

271
272
273

274
275
276
277
278
279
280
281







-
+

-
+


-
+







 * @return An initialized OFData
 */
- (instancetype)initWithContentsOfFile: (OFString *)path;
#endif

/**
 * @brief Initializes an already allocated OFData with an item size of 1,
 *	  containing the data of the specified URI.
 *	  containing the data of the specified IRI.
 *
 * @param URI The URI to the contents for the OFData
 * @param IRI The IRI to the contents for the OFData
 * @return A new autoreleased OFData
 */
- (instancetype)initWithContentsOfURI: (OFURI *)URI;
- (instancetype)initWithContentsOfIRI: (OFIRI *)IRI;

/**
 * @brief Initializes an already allocated OFData with an item size of 1,
 *	  containing the data of the hex string representation.
 *
 * @param string The hex string representation of the data
 * @return A new autoreleased OFData
342
343
344
345
346
347
348
349

350
351

352
353

354
355
356
357
358
359
360
338
339
340
341
342
343
344

345
346

347
348

349
350
351
352
353
354
355
356







-
+

-
+

-
+







 *
 * @param path The path of the file to write to
 */
- (void)writeToFile: (OFString *)path;
#endif

/**
 * @brief Writes the OFData to the specified URI.
 * @brief Writes the OFData to the specified IRI.
 *
 * @param URI The URI to write to
 * @param IRI The IRI to write to
 */
- (void)writeToURI: (OFURI *)URI;
- (void)writeToIRI: (OFIRI *)IRI;
@end

OF_ASSUME_NONNULL_END

#import "OFMutableData.h"
#import "OFData+CryptographicHashing.h"
#import "OFData+MessagePackParsing.h"

Modified src/OFData.m from [b0fcc38dae] to [fedaecf95c].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
22
23
24
25
26
27
28


29
30
31
32
33
34
35
36
37
38
39
40
41
22
23
24
25
26
27
28
29
30
31
32
33



34
35
36
37
38
39
40







+
+



-
-
-







#import "OFData.h"
#import "OFBase64.h"
#import "OFDictionary.h"
#ifdef OF_HAVE_FILES
# import "OFFile.h"
# import "OFFileManager.h"
#endif
#import "OFIRI.h"
#import "OFIRIHandler.h"
#import "OFStream.h"
#import "OFString.h"
#import "OFSystemInfo.h"
#import "OFURI.h"
#import "OFURIHandler.h"
#import "OFXMLElement.h"

#import "OFInvalidArgumentException.h"
#import "OFInvalidFormatException.h"
#import "OFNotImplementedException.h"
#import "OFOutOfMemoryException.h"
#import "OFOutOfRangeException.h"
#import "OFTruncatedDataException.h"
89
90
91
92
93
94
95
96

97
98

99
100
101
102
103
104
105
88
89
90
91
92
93
94

95
96

97
98
99
100
101
102
103
104







-
+

-
+







#ifdef OF_HAVE_FILES
+ (instancetype)dataWithContentsOfFile: (OFString *)path
{
	return [[[self alloc] initWithContentsOfFile: path] autorelease];
}
#endif

+ (instancetype)dataWithContentsOfURI: (OFURI *)URI
+ (instancetype)dataWithContentsOfIRI: (OFIRI *)IRI
{
	return [[[self alloc] initWithContentsOfURI: URI] autorelease];
	return [[[self alloc] initWithContentsOfIRI: IRI] autorelease];
}

+ (instancetype)dataWithStringRepresentation: (OFString *)string
{
	return [[[self alloc]
	    initWithStringRepresentation: string] autorelease];
}
207
208
209
210
211
212
213
214

215
216
217
218
219
220

221
222
223
224
225
226
227
206
207
208
209
210
211
212

213
214
215
216
217
218

219
220
221
222
223
224
225
226







-
+





-
+







		@throw e;
	}

	return self;
}
#endif

- (instancetype)initWithContentsOfURI: (OFURI *)URI
- (instancetype)initWithContentsOfIRI: (OFIRI *)IRI
{
	self = [super init];

	@try {
		void *pool = objc_autoreleasePoolPush();
		OFStream *stream = [OFURIHandler openItemAtURI: URI mode: @"r"];
		OFStream *stream = [OFIRIHandler openItemAtIRI: IRI mode: @"r"];
		size_t pageSize;
		unsigned char *buffer;

		_count = 0;
		_itemSize = 1;
		_freeWhenDone = true;

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
359
360
361
362
363
364
365
366
329
330
331
332
333
334
335























336
337
338
339
340
341
342







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







		[self release];
		@throw e;
	}

	if (!mutable)
		[(OFMutableData *)self makeImmutable];

	return self;
}

- (instancetype)initWithSerialization: (OFXMLElement *)element
{
	void *pool = objc_autoreleasePoolPush();
	OFString *stringValue;

	@try {
		if (![element.name isEqual: self.className] ||
		    ![element.namespace isEqual: OFSerializationNS])
			@throw [OFInvalidArgumentException exception];

		stringValue = element.stringValue;
	} @catch (id e) {
		[self release];
		@throw e;
	}

	self = [self initWithBase64EncodedString: stringValue];

	objc_autoreleasePoolPop(pool);

	return self;
}

- (void)dealloc
{
	if (_freeWhenDone)
		OFFreeMemory(_items);
583
584
585
586
587
588
589
590

591
592
593
594

595
596
597
598
599
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
559
560
561
562
563
564
565

566
567
568
569

570
571
572






















573
574
575
576
577
578
579







-
+



-
+


-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







		[file writeBuffer: _items length: _count * _itemSize];
	} @finally {
		[file release];
	}
}
#endif

- (void)writeToURI: (OFURI *)URI
- (void)writeToIRI: (OFIRI *)IRI
{
	void *pool = objc_autoreleasePoolPush();

	[[OFURIHandler openItemAtURI: URI mode: @"w"] writeData: self];
	[[OFIRIHandler openItemAtIRI: IRI mode: @"w"] writeData: self];

	objc_autoreleasePoolPop(pool);
}

- (OFXMLElement *)XMLElementBySerializing
{
	void *pool;
	OFXMLElement *element;

	if (_itemSize != 1)
		@throw [OFNotImplementedException exceptionWithSelector: _cmd
								 object: self];

	pool = objc_autoreleasePoolPush();
	element = [OFXMLElement
	    elementWithName: self.className
		  namespace: OFSerializationNS
		stringValue: OFBase64Encode(_items, _count * _itemSize)];

	[element retain];

	objc_autoreleasePoolPop(pool);

	return [element autorelease];
}

- (OFData *)messagePackRepresentation
{
	OFMutableData *data;

	if (_itemSize != 1)

Modified src/OFDatagramSocket.h from [81b28eb069] to [c25f58addd].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFDatagramSocket.m from [ea19c6b109] to [0e772bf0c7].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFDate.h from [ba59d767f1] to [5d6447d0f7].

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
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

-
+















-














-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 */

#import "OFObject.h"
#import "OFMessagePackRepresentation.h"
#import "OFSerialization.h"

OF_ASSUME_NONNULL_BEGIN

@class OFString;
@class OFConstantString;

/**
 * @class OFDate OFDate.h ObjFW/OFDate.h
 *
 * @brief A class for storing, accessing and comparing dates.
 */
#ifndef OF_DATE_M
OF_SUBCLASSING_RESTRICTED
#endif
@interface OFDate: OFObject <OFCopying, OFComparing, OFSerialization,
@interface OFDate: OFObject <OFCopying, OFComparing,
    OFMessagePackRepresentation>
{
	OFTimeInterval _seconds;
}

#ifdef OF_HAVE_CLASS_PROPERTIES
@property (class, readonly, nonatomic) OFDate *distantFuture;

Modified src/OFDate.m from [692871b1cf] to [8b8a822187].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
30
31
32
33
34
35
36

37
38
39
40
41
42
43







-







#ifdef OF_HAVE_THREADS
# import "OFMutex.h"
#endif
#import "OFStrPTime.h"
#import "OFString.h"
#import "OFSystemInfo.h"
#import "OFXMLAttribute.h"
#import "OFXMLElement.h"

#import "OFInitializationFailedException.h"
#import "OFInvalidArgumentException.h"
#import "OFInvalidFormatException.h"
#import "OFOutOfMemoryException.h"
#import "OFOutOfRangeException.h"

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
491
492
493
494
495
496
497

































498
499
500
501
502
503
504







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







		seconds = tmAndTzToTime(&tm, tz);

	objc_autoreleasePoolPop(pool);

	return [self initWithTimeIntervalSince1970: seconds];
}

- (instancetype)initWithSerialization: (OFXMLElement *)element
{
	OFTimeInterval seconds;

	@try {
		void *pool = objc_autoreleasePoolPush();
		unsigned long long value;

		if (![element.name isEqual: @"OFDate"] ||
		    ![element.namespace isEqual: OFSerializationNS])
			@throw [OFInvalidArgumentException exception];

		if (![[element attributeForName: @"encoding"].stringValue
		    isEqual: @"hex"])
			@throw [OFInvalidFormatException exception];

		value = [element unsignedLongLongValueWithBase: 16];

		if (value > UINT64_MAX)
			@throw [OFOutOfRangeException exception];

		seconds = OFFromBigEndianDouble(OFRawUInt64ToDouble(
		    OFToBigEndian64(value)));

		objc_autoreleasePoolPop(pool);
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return [self initWithTimeIntervalSince1970: seconds];
}

- (bool)isEqual: (id)object
{
	OFDate *otherDate;

	if (object == self)
		return true;

583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
549
550
551
552
553
554
555




















556
557
558
559
560
561
562







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







}

- (OFString *)description
{
	return [self dateStringWithFormat: @"%Y-%m-%dT%H:%M:%SZ"];
}

- (OFXMLElement *)XMLElementBySerializing
{
	void *pool = objc_autoreleasePoolPush();
	OFXMLElement *element;

	element = [OFXMLElement elementWithName: @"OFDate"
				      namespace: OFSerializationNS];

	[element addAttributeWithName: @"encoding" stringValue: @"hex"];
	element.stringValue = [OFString stringWithFormat: @"%016" PRIx64,
	    OFFromBigEndian64(OFDoubleToRawUInt64(OFToBigEndianDouble(
	    self.timeIntervalSince1970)))];

	[element retain];

	objc_autoreleasePoolPop(pool);

	return [element autorelease];
}

- (OFData *)messagePackRepresentation
{
	void *pool = objc_autoreleasePoolPush();
	OFTimeInterval timeInterval = self.timeIntervalSince1970;
	int64_t seconds = (int64_t)timeInterval;
	uint32_t nanoseconds =
	    (uint32_t)((timeInterval - trunc(timeInterval)) * 1000000000);

Modified src/OFDictionary.h from [73af2a9ef3] to [b2fad599b6].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
21
22
23
24
25
26
27

28
29
30
31
32
33
34







-







#endif

#include <stdarg.h>

#import "OFObject.h"
#import "OFCollection.h"
#import "OFEnumerator.h"
#import "OFSerialization.h"
#import "OFJSONRepresentation.h"
#import "OFMessagePackRepresentation.h"

OF_ASSUME_NONNULL_BEGIN

@class OFArray OF_GENERIC(ObjectType);

73
74
75
76
77
78
79
80

81
82
83
84
85
86
87
72
73
74
75
76
77
78

79
80
81
82
83
84
85
86







-
+







 * @note Fast enumeration on a dictionary enumerates through the keys of the
 *	 dictionary.
 *
 * @note Subclasses must implement @ref objectForKey:, @ref count and
 *	 @ref keyEnumerator.
 */
@interface OFDictionary OF_GENERIC(KeyType, ObjectType): OFObject <OFCopying,
    OFMutableCopying, OFCollection, OFSerialization, OFJSONRepresentation,
    OFMutableCopying, OFCollection, OFJSONRepresentation,
    OFMessagePackRepresentation>
#if !defined(OF_HAVE_GENERICS) && !defined(DOXYGEN)
# define KeyType id
# define ObjectType id
#endif
/**
 * @brief An array of all keys.

Modified src/OFDictionary.m from [cbf5abac37] to [12d43fb634].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
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
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







-









-
-



















-
-
-
-
-







#import "OFDictionary.h"
#import "OFArray.h"
#import "OFCharacterSet.h"
#import "OFData.h"
#import "OFEnumerator.h"
#import "OFMapTableDictionary.h"
#import "OFString.h"
#import "OFXMLElement.h"

#import "OFInvalidArgumentException.h"
#import "OFOutOfRangeException.h"
#import "OFUndefinedKeyException.h"

static struct {
	Class isa;
} placeholder;

static OFCharacterSet *URIQueryPartAllowedCharacterSet = nil;

@interface OFDictionary ()
- (OFString *)
    of_JSONRepresentationWithOptions: (OFJSONRepresentationOptions)options
			       depth: (size_t)depth;
@end

@interface OFDictionaryPlaceholder: OFDictionary
@end

OF_DIRECT_MEMBERS
@interface OFDictionaryObjectEnumerator: OFEnumerator
{
	OFDictionary *_dictionary;
	OFEnumerator *_keyEnumerator;
}

- (instancetype)initWithDictionary: (OFDictionary *)dictionary;
@end

OF_DIRECT_MEMBERS
@interface OFURIQueryPartAllowedCharacterSet: OFCharacterSet
+ (OFCharacterSet *)URIQueryPartAllowedCharacterSet;
@end

@implementation OFDictionaryPlaceholder
- (instancetype)init
{
	return (id)[[OFMapTableDictionary alloc] init];
}

- (instancetype)initWithDictionary: (OFDictionary *)dictionary
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
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







-
-
-
-
-
-


















-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







- (instancetype)initWithKey: (id <OFCopying>)firstKey
		  arguments: (va_list)arguments
{
	return (id)[[OFMapTableDictionary alloc] initWithKey: firstKey
						   arguments: arguments];
}

- (instancetype)initWithSerialization: (OFXMLElement *)element
{
	return (id)[[OFMapTableDictionary alloc]
	    initWithSerialization: element];
}

- (instancetype)retain
{
	return self;
}

- (instancetype)autorelease
{
	return self;
}

- (void)release
{
}

- (void)dealloc
{
	OF_DEALLOC_UNSUPPORTED
}
@end

@implementation OFURIQueryPartAllowedCharacterSet
+ (void)initialize
{
	if (self != [OFURIQueryPartAllowedCharacterSet class])
		return;

	URIQueryPartAllowedCharacterSet =
	    [[OFURIQueryPartAllowedCharacterSet alloc] init];
}

+ (OFCharacterSet *)URIQueryPartAllowedCharacterSet
{
	return URIQueryPartAllowedCharacterSet;
}

- (instancetype)autorelease
{
	return self;
}

- (instancetype)retain
{
	return self;
}

- (void)release
{
}

- (unsigned int)retainCount
{
	return OFMaxRetainCount;
}

- (bool)characterIsMember: (OFUnichar)character
{
	if (character < CHAR_MAX && OFASCIIIsAlnum(character))
		return true;

	switch (character) {
	case '-':
	case '.':
	case '_':
	case '~':
	case '!':
	case '$':
	case '\'':
	case '(':
	case ')':
	case '*':
	case '+':
	case ',':
	case ';':
		return true;
	default:
		return false;
	}
}
@end

@implementation OFDictionary
+ (void)initialize
{
	if (self == [OFDictionary class])
		placeholder.isa = [OFDictionaryPlaceholder class];
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
252
253
254
255
256
257
258





259
260
261
262
263
264
265







-
-
-
-
-







	va_end(arguments);

	return ret;
}

- (instancetype)initWithKey: (id)firstKey arguments: (va_list)arguments
{
	OF_INVALID_INIT_METHOD
}

- (instancetype)initWithSerialization: (OFXMLElement *)element
{
	OF_INVALID_INIT_METHOD
}

- (id)objectForKey: (id)key
{
	OF_UNRECOGNIZED_SELECTOR
}
633
634
635
636
637
638
639
640
641
642
643
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
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
554
555
556
557
558
559
560












































561
562
563
564
565
566
567







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







	[ret makeImmutable];

	objc_autoreleasePoolPop(pool);

	return ret;
}

- (OFXMLElement *)XMLElementBySerializing
{
	void *pool = objc_autoreleasePoolPush();
	OFXMLElement *element;
	OFEnumerator *keyEnumerator, *objectEnumerator;
	id <OFSerialization> key, object;

	if ([self isKindOfClass: [OFMutableDictionary class]])
		element = [OFXMLElement elementWithName: @"OFMutableDictionary"
					      namespace: OFSerializationNS];
	else
		element = [OFXMLElement elementWithName: @"OFDictionary"
					      namespace: OFSerializationNS];

	keyEnumerator = [self keyEnumerator];
	objectEnumerator = [self objectEnumerator];
	while ((key = [keyEnumerator nextObject]) != nil &&
	       (object = [objectEnumerator nextObject]) != nil) {
		void *pool2 = objc_autoreleasePoolPush();
		OFXMLElement *keyElement, *objectElement;

		keyElement = [OFXMLElement
		    elementWithName: @"key"
			  namespace: OFSerializationNS];
		[keyElement addChild: key.XMLElementBySerializing];

		objectElement = [OFXMLElement
		    elementWithName: @"object"
			  namespace: OFSerializationNS];
		[objectElement addChild: object.XMLElementBySerializing];

		[element addChild: keyElement];
		[element addChild: objectElement];

		objc_autoreleasePoolPop(pool2);
	}

	[element retain];

	objc_autoreleasePoolPop(pool);

	return [element autorelease];
}

- (OFString *)JSONRepresentation
{
	return [self of_JSONRepresentationWithOptions: 0 depth: 0];
}

- (OFString *)JSONRepresentationWithOptions:
    (OFJSONRepresentationOptions)options

Renamed and modified src/OFEmbeddedURIHandler.h [c72607aa86] to src/OFEmbeddedIRIHandler.h [e6c81f46fa].

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
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

-
+













-
+



-
+






-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 */

#import "OFURIHandler.h"
#import "OFIRIHandler.h"

OF_ASSUME_NONNULL_BEGIN

@interface OFEmbeddedURIHandler: OFURIHandler
@interface OFEmbeddedIRIHandler: OFIRIHandler
@end

#ifdef __cplusplus
extern "C" {
#endif
/**
 * @brief Register a file for the `embedded:` URI scheme.
 * @brief Register a file for the `embedded:` IRI scheme.
 *
 * Usually, you should not use the directly, but rather generate a source file
 * for a file to be embedded using the `objfw-embed` tool.
 *
 * @param path The path to the file under the `embedded:` scheme. This is not
 *	       retained, so you must either pass a constant string or pass a
 *	       string that is already retained!

Renamed and modified src/OFEmbeddedURIHandler.m [1976c624c2] to src/OFEmbeddedIRIHandler.m [3c1f214812].

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
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

-
+



















-
-
-
+
+
+

















+


-
+









-
-
+


















-
-
+
+
+
+
+
+
+
+
+
+



-
-
-
+
+
+



-
+



-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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"

#include <errno.h>
#include <stdlib.h>
#include <string.h>

#import "OFEmbeddedURIHandler.h"
#import "OFMemoryStream.h"
#import "OFURI.h"
#import "OFEmbeddedIRIHandler.h"
#import "OFIRI.h"
#import "OFMemoryStream.h"

#import "OFInvalidArgumentException.h"
#import "OFOpenItemFailedException.h"

#ifdef OF_HAVE_THREADS
# import "OFOnce.h"
# import "OFPlainMutex.h"
#endif

struct EmbeddedFile {
	OFString *path;
	const uint8_t *bytes;
	size_t size;
} *embeddedFiles = NULL;
size_t numEmbeddedFiles = 0;
#ifdef OF_HAVE_THREADS
static OFPlainMutex mutex;
static OFOnceControl mutexOnceControl = OFOnceControlInitValue;

static void
init(void)
initMutex(void)
{
	OFEnsure(OFPlainMutexNew(&mutex) == 0);
}
#endif

void
OFRegisterEmbeddedFile(OFString *path, const uint8_t *bytes, size_t size)
{
#ifdef OF_HAVE_THREADS
	static OFOnceControl onceControl = OFOnceControlInitValue;
	OFOnce(&onceControl, init);
	OFOnce(&mutexOnceControl, initMutex);

	OFEnsure(OFPlainMutexLock(&mutex) == 0);
#endif

	embeddedFiles = realloc(embeddedFiles,
	    sizeof(*embeddedFiles) * (numEmbeddedFiles + 1));
	OFEnsure(embeddedFiles != NULL);

	embeddedFiles[numEmbeddedFiles].path = path;
	embeddedFiles[numEmbeddedFiles].bytes = bytes;
	embeddedFiles[numEmbeddedFiles].size = size;
	numEmbeddedFiles++;

#ifdef OF_HAVE_THREADS
	OFEnsure(OFPlainMutexUnlock(&mutex) == 0);
#endif
}

@implementation OFEmbeddedURIHandler
- (OFStream *)openItemAtURI: (OFURI *)URI mode: (OFString *)mode
@implementation OFEmbeddedIRIHandler
#ifdef OF_HAVE_THREADS
+ (void)initialize
{
	if (self == [OFEmbeddedIRIHandler class])
		OFOnce(&mutexOnceControl, initMutex);
}
#endif

- (OFStream *)openItemAtIRI: (OFIRI *)IRI mode: (OFString *)mode
{
	OFString *path;

	if (![URI.scheme isEqual: @"embedded"] || URI.host.length > 0 ||
	    URI.port != nil || URI.user != nil || URI.password != nil ||
	    URI.query != nil || URI.fragment != nil)
	if (![IRI.scheme isEqual: @"embedded"] || IRI.host.length > 0 ||
	    IRI.port != nil || IRI.user != nil || IRI.password != nil ||
	    IRI.query != nil || IRI.fragment != nil)
		@throw [OFInvalidArgumentException exception];

	if (![mode isEqual: @"r"])
		@throw [OFOpenItemFailedException exceptionWithURI: URI
		@throw [OFOpenItemFailedException exceptionWithIRI: IRI
							      mode: mode
							     errNo: EROFS];

	if ((path = URI.path) == nil) {
	if ((path = IRI.path) == nil) {
		@throw [OFInvalidArgumentException exception];
	}

#ifdef OF_HAVE_THREADS
	OFEnsure(OFPlainMutexLock(&mutex) == 0);
	@try {
#endif
106
107
108
109
110
111
112
113

114
115
116
117
114
115
116
117
118
119
120

121
122
123
124
125







-
+




		}
#ifdef OF_HAVE_THREADS
	} @finally {
		OFEnsure(OFPlainMutexUnlock(&mutex) == 0);
	}
#endif

	@throw [OFOpenItemFailedException exceptionWithURI: URI
	@throw [OFOpenItemFailedException exceptionWithIRI: IRI
						      mode: mode
						     errNo: ENOENT];
}
@end

Modified src/OFEnumerator.h from [bebf66139d] to [d1ff19008a].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFEnumerator.m from [bb10b4629e] to [ad753eb610].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFEpollKernelEventObserver.h from [d3c4bbd7da] to [c12b332835].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFEpollKernelEventObserver.m from [68ed1a2421] to [7b99a4a097].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFFile.h from [b56cdf66da] to [95a6d86e52].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
23
24
25
26
27
28
29


30
31
32
33
34
35
36







-
-







#else
typedef struct _OFFileHandle *OFFileHandle;
static const OFFileHandle OFInvalidFileHandle = NULL;
#endif

OF_ASSUME_NONNULL_BEGIN

@class OFURI;

/**
 * @class OFFile OFFile.h ObjFW/OFFile.h
 *
 * @brief A class which provides methods to read and write files.
 */
OF_SUBCLASSING_RESTRICTED
@interface OFFile: OFSeekableStream

Modified src/OFFile.m from [c784d31e2e] to [11d5a8e0e1].

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
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

-
+















+
-
+
+
















-
















+


+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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"

#ifndef _LARGEFILE64_SOURCE
#define _LARGEFILE64_SOURCE
# define _LARGEFILE64_SOURCE
#endif

#include <errno.h>

#ifdef HAVE_FCNTL_H
# include <fcntl.h>
#endif
#include "unistd_wrapper.h"

#ifdef HAVE_SYS_STAT_H
# include <sys/stat.h>
#endif

#import "OFFile.h"
#import "OFLocale.h"
#import "OFString.h"
#import "OFSystemInfo.h"
#import "OFURI.h"

#import "OFInitializationFailedException.h"
#import "OFInvalidArgumentException.h"
#import "OFNotOpenException.h"
#import "OFOpenItemFailedException.h"
#import "OFOutOfMemoryException.h"
#import "OFOutOfRangeException.h"
#import "OFReadFailedException.h"
#import "OFSeekFailedException.h"
#import "OFWriteFailedException.h"

#ifdef OF_WINDOWS
# include <windows.h>
#endif

#ifdef OF_AMIGAOS
# define Class IntuitionClass
# include <proto/exec.h>
# include <proto/dos.h>
# undef Class
#endif

#ifdef OF_WII
# include <fat.h>
#endif

#ifdef OF_NINTENDO_DS

Renamed and modified src/OFFileURIHandler.h [24ec18a27d] to src/OFFileIRIHandler.h [5f206fb1d4].

1
2

3
4
5
6
7
8
9
10
11
12
13
14
15
16

17
18
19
20

21
22
23
24
1

2
3
4
5
6
7
8
9
10
11
12
13
14
15

16
17
18
19

20
21
22
23
24

-
+













-
+



-
+




/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 */

#import "OFURIHandler.h"
#import "OFIRIHandler.h"

OF_ASSUME_NONNULL_BEGIN

@interface OFFileURIHandler: OFURIHandler
@interface OFFileIRIHandler: OFIRIHandler
+ (bool)of_directoryExistsAtPath: (OFString *)path OF_DIRECT;
@end

OF_ASSUME_NONNULL_END

Renamed and modified src/OFFileURIHandler.m [d74cbf6f89] to src/OFFileIRIHandler.m [624183587b].

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
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

-
+















+
-
+
+














+
+
+



+
+
+

+
+
+







-
+

+



+



-







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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"

#ifndef _LARGEFILE64_SOURCE
#define _LARGEFILE64_SOURCE
# define _LARGEFILE64_SOURCE
#endif

#include <errno.h>
#include <math.h>

#ifdef HAVE_DIRENT_H
# include <dirent.h>
#endif
#include "unistd_wrapper.h"

#include "platform.h"
#ifdef HAVE_SYS_STAT_H
# include <sys/stat.h>
#endif
#include <sys/time.h>
#if defined(OF_LINUX) || defined(OF_MACOS)
# include <sys/xattr.h>
#endif
#ifdef OF_WINDOWS
# include <utime.h>
#endif
#ifdef OF_DJGPP
# include <syslimits.h>
#endif

#ifdef HAVE_FCNTL_H
# include <fcntl.h>
#endif
#ifdef HAVE_PWD_H
# include <pwd.h>
#endif
#ifdef HAVE_GRP_H
# include <grp.h>
#endif

#import "OFFileURIHandler.h"
#import "OFFileIRIHandler.h"
#import "OFArray.h"
#import "OFData.h"
#import "OFDate.h"
#import "OFFile.h"
#import "OFFileManager.h"
#import "OFIRI.h"
#import "OFLocale.h"
#import "OFNumber.h"
#import "OFSystemInfo.h"
#import "OFURI.h"

#ifdef OF_HAVE_THREADS
# import "OFMutex.h"
#endif

#import "OFCreateDirectoryFailedException.h"
#import "OFCreateSymbolicLinkFailedException.h"
73
74
75
76
77
78
79

80
81
82

83
84
85
86
87
88
89
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103







+



+







# include <windows.h>
# include <direct.h>
# include <ntdef.h>
# include <wchar.h>
#endif

#ifdef OF_AMIGAOS
# define Class IntuitionClass
# include <proto/exec.h>
# include <proto/dos.h>
# include <proto/locale.h>
# undef Class
# ifdef OF_AMIGAOS4
#  define DeleteFile(path) Delete(path)
# endif
#endif

#if defined(OF_WINDOWS) || defined(OF_AMIGAOS)
typedef struct {
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
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
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
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







-
+

-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-










-
+














-
+




-
+



















+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



-
+






-
+







# endif
#endif
}

#ifdef OF_FILE_MANAGER_SUPPORTS_SYMLINKS
static void
setSymbolicLinkDestinationAttribute(OFMutableFileAttributes attributes,
    OFURI *URI)
    OFIRI *IRI)
{
	OFString *path = URI.fileSystemRepresentation;
# ifndef OF_WINDOWS
	OFString *path = IRI.fileSystemRepresentation;
# ifdef OF_WINDOWS
	OFStringEncoding encoding = [OFLocale encoding];
	char destinationC[PATH_MAX];
	ssize_t length;
	OFString *destination;

	length = readlink([path cStringWithEncoding: encoding], destinationC,
	    PATH_MAX);

	if (length < 0)
		@throw [OFGetItemAttributesFailedException
		    exceptionWithURI: URI
			       errNo: errno];

	destination = [OFString stringWithCString: destinationC
					 encoding: encoding
					   length: length];

	[attributes setObject: destination
		       forKey: OFFileSymbolicLinkDestination];
# else
	HANDLE handle;
	OFString *destination;

	if (createSymbolicLinkWFuncPtr == NULL)
		return;

	if ((handle = CreateFileW(path.UTF16String, 0, (FILE_SHARE_READ |
	    FILE_SHARE_WRITE), NULL, OPEN_EXISTING,
	    FILE_FLAG_OPEN_REPARSE_POINT, NULL)) == INVALID_HANDLE_VALUE)
		@throw [OFGetItemAttributesFailedException
		    exceptionWithURI: URI
		    exceptionWithIRI: IRI
			       errNo: lastError()];

	@try {
		union {
			char bytes[MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
			REPARSE_DATA_BUFFER data;
		} buffer;
		DWORD size;
		wchar_t *tmp;

		if (!DeviceIoControl(handle, FSCTL_GET_REPARSE_POINT, NULL, 0,
		    buffer.bytes, MAXIMUM_REPARSE_DATA_BUFFER_SIZE, &size,
		    NULL))
			@throw [OFGetItemAttributesFailedException
			    exceptionWithURI: URI
			    exceptionWithIRI: IRI
				       errNo: lastError()];

		if (buffer.data.ReparseTag != IO_REPARSE_TAG_SYMLINK)
			@throw [OFGetItemAttributesFailedException
			    exceptionWithURI: URI
			    exceptionWithIRI: IRI
				       errNo: lastError()];

#  define slrb buffer.data.SymbolicLinkReparseBuffer
		tmp = slrb.PathBuffer +
		    (slrb.SubstituteNameOffset / sizeof(wchar_t));

		destination = [OFString
		    stringWithUTF16String: tmp
				   length: slrb.SubstituteNameLength /
					   sizeof(wchar_t)];

		[attributes setObject: OFFileTypeSymbolicLink
			       forKey: OFFileType];
		[attributes setObject: destination
			       forKey: OFFileSymbolicLinkDestination];
#  undef slrb
	} @finally {
		CloseHandle(handle);
	}
# elif defined(OF_HURD)
	OFStringEncoding encoding = [OFLocale encoding];
	int fd;
	OFMutableData *destinationData;
	OFString *destination;

	fd = open([path cStringWithEncoding: encoding], O_RDONLY | O_NOLINK);
	if (fd == -1)
		@throw [OFGetItemAttributesFailedException
		    exceptionWithIRI: IRI
			       errNo: errno];

	@try {
		char buffer[512];
		ssize_t length;

		destinationData = [OFMutableData data];
		while ((length = read(fd, buffer, 512)) > 0)
			[destinationData addItems: buffer count: length];
	} @finally {
		close(fd);
	}

	destination = [OFString stringWithCString: destinationData.items
					 encoding: encoding
					   length: destinationData.count];

	[attributes setObject: destination
		       forKey: OFFileSymbolicLinkDestination];
# else
	OFStringEncoding encoding = [OFLocale encoding];
	char destinationC[PATH_MAX];
	ssize_t length;
	OFString *destination;

	length = readlink([path cStringWithEncoding: encoding], destinationC,
	    PATH_MAX);

	if (length < 0)
		@throw [OFGetItemAttributesFailedException
		    exceptionWithIRI: IRI
			       errNo: errno];

	destination = [OFString stringWithCString: destinationC
					 encoding: encoding
					   length: length];

	[attributes setObject: destination
		       forKey: OFFileSymbolicLinkDestination];
# endif
}
#endif

#ifdef OF_FILE_MANAGER_SUPPORTS_EXTENDED_ATTRIBUTES
static void
setExtendedAttributes(OFMutableFileAttributes attributes, OFIRI *IRI)
{
	OFString *path = IRI.fileSystemRepresentation;
	OFStringEncoding encoding = [OFLocale encoding];
	const char *cPath = [path cStringWithEncoding: encoding];
# if defined(OF_LINUX)
	ssize_t size = llistxattr(cPath, NULL, 0);
# elif defined(OF_MACOS)
	ssize_t size = listxattr(cPath, NULL, 0, XATTR_NOFOLLOW);
# endif
	char *list = OFAllocMemory(1, size);
	OFMutableArray *names = nil;

	@try {
		char *name;

# if defined(OF_LINUX)
		if ((size = llistxattr(cPath, list, size)) < 0)
# elif defined(OF_MACOS)
		if ((size = listxattr(cPath, list, size, XATTR_NOFOLLOW)) < 0)
# endif
			return;

		names = [OFMutableArray array];
		name = list;

		while (size > 0) {
			size_t length = strlen(name);

			[names addObject: [OFString stringWithCString: name
							     encoding: encoding
							       length: length]];

			name += length + 1;
			size -= length + 1;
		}
	} @finally {
		OFFreeMemory(list);
	}

	[attributes setObject: names forKey: OFFileExtendedAttributesNames];
}
#endif

@implementation OFFileURIHandler
@implementation OFFileIRIHandler
+ (void)initialize
{
#ifdef OF_WINDOWS
	HMODULE module;
#endif

	if (self != [OFFileURIHandler class])
	if (self != [OFFileIRIHandler class])
		return;

#if defined(OF_FILE_MANAGER_SUPPORTS_OWNER) && defined(OF_HAVE_THREADS)
	passwdMutex = [[OFMutex alloc] init];
	atexit(releasePasswdMutex);
#endif
#if !defined(HAVE_READDIR_R) && !defined(OF_WINDOWS) && defined(OF_HAVE_THREADS)
583
584
585
586
587
588
589
590

591
592
593
594

595
596
597
598
599
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
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


676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691






692
693

694
695
696


697
698
699
700
701
702
703
672
673
674
675
676
677
678

679
680
681
682

683
684
685
686
687
688
689
690

691
692
693
694
695
696
697
698

699
700
701

702
703
704

705
706
707
708

709
710
711
712
713
714
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
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762

763
764
765
766
767
768
769

770
771
772

773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789

790
791
792
793
794
795
796

797
798
799

800
801
802
803
804
805
806
807
808







-
+



-
+







-
+







-
+


-
+


-
+



-
+


















-
+
+
+
+
+









-
+


-
+

















-
+
+
+
+
+
+

-
+


-
+
+















-
+
+
+
+
+
+

-
+


-
+
+








	if (statWrapper(path, &s) != 0)
		return false;

	return S_ISDIR(s.st_mode);
}

- (OFStream *)openItemAtURI: (OFURI *)URI mode: (OFString *)mode
- (OFStream *)openItemAtIRI: (OFIRI *)IRI mode: (OFString *)mode
{
	void *pool = objc_autoreleasePoolPush();
	OFFile *file = [[OFFile alloc]
	    initWithPath: URI.fileSystemRepresentation
	    initWithPath: IRI.fileSystemRepresentation
		    mode: mode];

	objc_autoreleasePoolPop(pool);

	return [file autorelease];
}

- (OFFileAttributes)attributesOfItemAtURI: (OFURI *)URI
- (OFFileAttributes)attributesOfItemAtIRI: (OFIRI *)IRI
{
	OFMutableFileAttributes ret = [OFMutableDictionary dictionary];
	void *pool = objc_autoreleasePoolPush();
	OFString *path;
	int error;
	Stat s;

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

	if (![[URI scheme] isEqual: _scheme])
	if (![[IRI scheme] isEqual: _scheme])
		@throw [OFInvalidArgumentException exception];

	path = URI.fileSystemRepresentation;
	path = IRI.fileSystemRepresentation;

	if ((error = lstatWrapper(path, &s)) != 0)
		@throw [OFGetItemAttributesFailedException
		    exceptionWithURI: URI
		    exceptionWithIRI: IRI
			       errNo: error];

	if (s.st_size < 0)
		@throw [OFOutOfRangeException exception];

	[ret setObject: [NSNumber numberWithUnsignedLongLong: s.st_size]
		forKey: OFFileSize];

	setTypeAttribute(ret, &s);

	[ret setObject: [NSNumber numberWithUnsignedLong: s.st_mode]
		forKey: OFFilePOSIXPermissions];

	setOwnerAndGroupAttributes(ret, &s);
	setDateAttributes(ret, &s);

#ifdef OF_FILE_MANAGER_SUPPORTS_SYMLINKS
	if (S_ISLNK(s.st_mode))
		setSymbolicLinkDestinationAttribute(ret, URI);
		setSymbolicLinkDestinationAttribute(ret, IRI);
#endif

#ifdef OF_FILE_MANAGER_SUPPORTS_EXTENDED_ATTRIBUTES
	setExtendedAttributes(ret, IRI);
#endif

	objc_autoreleasePoolPop(pool);

	return ret;
}

- (void)of_setLastAccessDate: (OFDate *)lastAccessDate
	 andModificationDate: (OFDate *)modificationDate
		 ofItemAtURI: (OFURI *)URI
		 ofItemAtIRI: (OFIRI *)IRI
		  attributes: (OFFileAttributes)attributes OF_DIRECT
{
	OFString *path = URI.fileSystemRepresentation;
	OFString *path = IRI.fileSystemRepresentation;
	OFFileAttributeKey attributeKey = (modificationDate != nil
	    ? OFFileModificationDate : OFFileLastAccessDate);

	if (lastAccessDate == nil)
		lastAccessDate = modificationDate;
	if (modificationDate == nil)
		modificationDate = lastAccessDate;

#if defined(OF_WINDOWS)
	if (_wutime64FuncPtr != NULL) {
		struct __utimbuf64 times = {
			.actime =
			    (__time64_t)lastAccessDate.timeIntervalSince1970,
			.modtime =
			    (__time64_t)modificationDate.timeIntervalSince1970
		};

		if (_wutime64FuncPtr([path UTF16String], &times) != 0)
		if (_wutime64FuncPtr([path UTF16String], &times) != 0) {
			int errNo = errno;

			if (errNo == EACCES && [self directoryExistsAtIRI: IRI])
				errNo = EISDIR;

			@throw [OFSetItemAttributesFailedException
			    exceptionWithURI: URI
			    exceptionWithIRI: IRI
				  attributes: attributes
			     failedAttribute: attributeKey
				       errNo: errno];
				       errNo: errNo];
		}
	} else {
		struct _utimbuf times = {
			.actime = (time_t)lastAccessDate.timeIntervalSince1970,
			.modtime =
			    (time_t)modificationDate.timeIntervalSince1970
		};
		int status;

		if ([OFSystemInfo isWindowsNT])
			status = _wutime([path UTF16String], &times);
		else
			status = _utime(
			    [path cStringWithEncoding: [OFLocale encoding]],
			    &times);

		if (status != 0)
		if (status != 0) {
			int errNo = errno;

			if (errNo == EACCES && [self directoryExistsAtIRI: IRI])
				errNo = EISDIR;

			@throw [OFSetItemAttributesFailedException
			    exceptionWithURI: URI
			    exceptionWithIRI: IRI
				  attributes: attributes
			     failedAttribute: attributeKey
				       errNo: errno];
				       errNo: errNo];
		}
	}
#elif defined(OF_AMIGAOS)
	/* AmigaOS does not support access time. */
	OFTimeInterval modificationTime =
	    modificationDate.timeIntervalSince1970;
	struct Locale *locale;
	struct DateStamp date;
724
725
726
727
728
729
730
731

732
733
734
735
736
737
738
829
830
831
832
833
834
835

836
837
838
839
840
841
842
843







-
+







	if (!SetDate([path cStringWithEncoding: [OFLocale encoding]],
	    &date) != 0)
# else
	if (!SetFileDate([path cStringWithEncoding: [OFLocale encoding]],
	    &date) != 0)
# endif
		@throw [OFSetItemAttributesFailedException
		    exceptionWithURI: URI
		    exceptionWithIRI: IRI
			  attributes: attributes
		     failedAttribute: attributeKey
			       errNo: lastError()];
#else
	OFTimeInterval lastAccessTime = lastAccessDate.timeIntervalSince1970;
	OFTimeInterval modificationTime =
	    modificationDate.timeIntervalSince1970;
747
748
749
750
751
752
753
754

755
756
757
758
759
760
761
762

763
764
765
766
767

768
769
770
771
772
773
774
775
776
777
778
779
780

781
782
783
784
785
786
787
788
789
790
791

792
793
794
795
796

797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816

817
818
819
820
821
822
823
824
825
826
827
828
829
830

831
832
833
834
835
836
837
838
839
840
841
842
843
844
845

846
847
848
849
850
851
852
853
854

855
856
857
858
859
860
861
862
863

864
865
866

867
868
869
870
871
872
873
874
875
876
877
878
879

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

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
976
977
978
979
980
981
982
983

984
985
986
987
988
989
990
991

992
993
994
995
996
997
998

999
1000
1001
1002
1003
1004
1005

1006
1007

1008
1009
1010
1011

1012
1013
1014

1015
1016
1017

1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030

1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046


1047
1048
1049
1050
1051
1052
1053
852
853
854
855
856
857
858

859
860
861
862
863
864
865
866

867
868
869
870
871

872
873
874
875
876
877
878
879
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
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
976
977
978
979
980
981
982
983

984
985
986
987
988

989
990
991
992
993
994

995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009

1010
1011
1012
1013
1014
1015

1016
1017
1018
1019
1020
1021

1022
1023
1024

1025
1026
1027

1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039

1040
1041
1042
1043
1044
1045

1046
1047
1048

1049
1050
1051

1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063

1064
1065
1066
1067
1068

1069
1070
1071

1072
1073
1074

1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087

1088
1089
1090
1091
1092
1093
1094
1095

1096
1097
1098
1099
1100
1101
1102

1103
1104
1105
1106
1107
1108
1109

1110
1111

1112
1113
1114
1115

1116
1117
1118

1119
1120
1121

1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134

1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149


1150
1151
1152
1153
1154
1155
1156
1157
1158







-
+







-
+




-
+












-
+










-
+




-
+



















-
+













-
+














-
+








-
+








-
+


-
+












-
+




-
+





-
+














-
+





-
+





-
+


-
+


-
+











-
+





-
+


-
+


-
+











-
+




-
+


-
+


-
+












-
+







-
+






-
+






-
+

-
+



-
+


-
+


-
+












-
+














-
-
+
+







			.tv_usec = (int)((modificationTime - times[1].tv_sec) *
			    1000000)
		},
	};

	if (utimes([path cStringWithEncoding: [OFLocale encoding]], times) != 0)
		@throw [OFSetItemAttributesFailedException
		    exceptionWithURI: URI
		    exceptionWithIRI: IRI
			  attributes: attributes
		     failedAttribute: attributeKey
			       errNo: errno];
#endif
}

- (void)of_setPOSIXPermissions: (OFNumber *)permissions
		   ofItemAtURI: (OFURI *)URI
		   ofItemAtIRI: (OFIRI *)IRI
		    attributes: (OFFileAttributes)attributes OF_DIRECT
{
#ifdef OF_FILE_MANAGER_SUPPORTS_PERMISSIONS
	mode_t mode = (mode_t)permissions.unsignedLongValue;
	OFString *path = URI.fileSystemRepresentation;
	OFString *path = IRI.fileSystemRepresentation;
	int status;

# ifdef OF_WINDOWS
	if ([OFSystemInfo isWindowsNT])
		status = _wchmod(path.UTF16String, mode);
	else
# endif
		status = chmod(
		    [path cStringWithEncoding: [OFLocale encoding]], mode);

	if (status != 0)
		@throw [OFSetItemAttributesFailedException
		    exceptionWithURI: URI
		    exceptionWithIRI: IRI
			  attributes: attributes
		     failedAttribute: OFFilePOSIXPermissions
			       errNo: errno];
#else
	OF_UNRECOGNIZED_SELECTOR
#endif
}

- (void)of_setOwnerAccountName: (OFString *)owner
      andGroupOwnerAccountName: (OFString *)group
		   ofItemAtURI: (OFURI *)URI
		   ofItemAtIRI: (OFIRI *)IRI
		  attributeKey: (OFFileAttributeKey)attributeKey
		    attributes: (OFFileAttributes)attributes OF_DIRECT
{
#ifdef OF_FILE_MANAGER_SUPPORTS_OWNER
	OFString *path = URI.fileSystemRepresentation;
	OFString *path = IRI.fileSystemRepresentation;
	uid_t uid = -1;
	gid_t gid = -1;
	OFStringEncoding encoding;

	if (owner == nil && group == nil)
		@throw [OFInvalidArgumentException exception];

	encoding = [OFLocale encoding];

# ifdef OF_HAVE_THREADS
	[passwdMutex lock];
	@try {
# endif
		if (owner != nil) {
			struct passwd *passwd;

			if ((passwd = getpwnam([owner
			    cStringWithEncoding: encoding])) == NULL)
				@throw [OFSetItemAttributesFailedException
				    exceptionWithURI: URI
				    exceptionWithIRI: IRI
					  attributes: attributes
				     failedAttribute: attributeKey
					       errNo: errno];

			uid = passwd->pw_uid;
		}

		if (group != nil) {
			struct group *group_;

			if ((group_ = getgrnam([group
			    cStringWithEncoding: encoding])) == NULL)
				@throw [OFSetItemAttributesFailedException
				    exceptionWithURI: URI
				    exceptionWithIRI: IRI
					  attributes: attributes
				     failedAttribute: attributeKey
					       errNo: errno];

			gid = group_->gr_gid;
		}
# ifdef OF_HAVE_THREADS
	} @finally {
		[passwdMutex unlock];
	}
# endif

	if (chown([path cStringWithEncoding: encoding], uid, gid) != 0)
		@throw [OFSetItemAttributesFailedException
		    exceptionWithURI: URI
		    exceptionWithIRI: IRI
			  attributes: attributes
		     failedAttribute: attributeKey
			       errNo: errno];
#else
	OF_UNRECOGNIZED_SELECTOR
#endif
}

- (void)setAttributes: (OFFileAttributes)attributes ofItemAtURI: (OFURI *)URI
- (void)setAttributes: (OFFileAttributes)attributes ofItemAtIRI: (OFIRI *)IRI
{
	void *pool = objc_autoreleasePoolPush();
	OFEnumerator OF_GENERIC(OFFileAttributeKey) *keyEnumerator;
	OFEnumerator *objectEnumerator;
	OFFileAttributeKey key;
	id object;
	OFDate *lastAccessDate, *modificationDate;

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

	if (![URI.scheme isEqual: _scheme])
	if (![IRI.scheme isEqual: _scheme])
		@throw [OFInvalidArgumentException exception];

	keyEnumerator = [attributes keyEnumerator];
	objectEnumerator = [attributes objectEnumerator];

	while ((key = [keyEnumerator nextObject]) != nil &&
	    (object = [objectEnumerator nextObject]) != nil) {
		if ([key isEqual: OFFileModificationDate] ||
		    [key isEqual: OFFileLastAccessDate])
			continue;
		else if ([key isEqual: OFFilePOSIXPermissions])
			[self of_setPOSIXPermissions: object
					 ofItemAtURI: URI
					 ofItemAtIRI: IRI
					  attributes: attributes];
		else if ([key isEqual: OFFileOwnerAccountName])
			[self of_setOwnerAccountName: object
			    andGroupOwnerAccountName: nil
					 ofItemAtURI: URI
					 ofItemAtIRI: IRI
					attributeKey: key
					  attributes: attributes];
		else if ([key isEqual: OFFileGroupOwnerAccountName])
			[self of_setOwnerAccountName: nil
			    andGroupOwnerAccountName: object
					 ofItemAtURI: URI
					 ofItemAtIRI: IRI
					attributeKey: key
					  attributes: attributes];
		else
			@throw [OFNotImplementedException
			    exceptionWithSelector: _cmd
					   object: self];
	}

	lastAccessDate = [attributes objectForKey: OFFileLastAccessDate];
	modificationDate = [attributes objectForKey: OFFileModificationDate];

	if (lastAccessDate != nil || modificationDate != nil)
		[self of_setLastAccessDate: lastAccessDate
		       andModificationDate: modificationDate
			       ofItemAtURI: URI
			       ofItemAtIRI: IRI
				attributes: attributes];

	objc_autoreleasePoolPop(pool);
}

- (bool)fileExistsAtURI: (OFURI *)URI
- (bool)fileExistsAtIRI: (OFIRI *)IRI
{
	void *pool = objc_autoreleasePoolPush();
	Stat s;
	bool ret;

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

	if (![URI.scheme isEqual: _scheme])
	if (![IRI.scheme isEqual: _scheme])
		@throw [OFInvalidArgumentException exception];

	if (statWrapper(URI.fileSystemRepresentation, &s) != 0) {
	if (statWrapper(IRI.fileSystemRepresentation, &s) != 0) {
		objc_autoreleasePoolPop(pool);
		return false;
	}

	ret = S_ISREG(s.st_mode);

	objc_autoreleasePoolPop(pool);

	return ret;
}

- (bool)directoryExistsAtURI: (OFURI *)URI
- (bool)directoryExistsAtIRI: (OFIRI *)IRI
{
	void *pool = objc_autoreleasePoolPush();
	Stat s;
	bool ret;

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

	if (![URI.scheme isEqual: _scheme])
	if (![IRI.scheme isEqual: _scheme])
		@throw [OFInvalidArgumentException exception];

	if (statWrapper(URI.fileSystemRepresentation, &s) != 0) {
	if (statWrapper(IRI.fileSystemRepresentation, &s) != 0) {
		objc_autoreleasePoolPop(pool);
		return false;
	}

	ret = S_ISDIR(s.st_mode);

	objc_autoreleasePoolPop(pool);

	return ret;
}

- (void)createDirectoryAtURI: (OFURI *)URI
- (void)createDirectoryAtIRI: (OFIRI *)IRI
{
	void *pool = objc_autoreleasePoolPush();
	OFString *path;

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

	if (![URI.scheme isEqual: _scheme])
	if (![IRI.scheme isEqual: _scheme])
		@throw [OFInvalidArgumentException exception];

	path = URI.fileSystemRepresentation;
	path = IRI.fileSystemRepresentation;

#if defined(OF_WINDOWS)
	int status;

	if ([OFSystemInfo isWindowsNT])
		status = _wmkdir(path.UTF16String);
	else
		status = _mkdir(
		    [path cStringWithEncoding: [OFLocale encoding]]);

	if (status != 0)
		@throw [OFCreateDirectoryFailedException
		    exceptionWithURI: URI
		    exceptionWithIRI: IRI
			       errNo: errno];
#elif defined(OF_AMIGAOS)
	BPTR lock;

	if ((lock = CreateDir(
	    [path cStringWithEncoding: [OFLocale encoding]])) == 0)
		@throw [OFCreateDirectoryFailedException
		    exceptionWithURI: URI
		    exceptionWithIRI: IRI
			       errNo: lastError()];

	UnLock(lock);
#else
	if (mkdir([path cStringWithEncoding: [OFLocale encoding]], 0777) != 0)
		@throw [OFCreateDirectoryFailedException
		    exceptionWithURI: URI
		    exceptionWithIRI: IRI
			       errNo: errno];
#endif

	objc_autoreleasePoolPop(pool);
}

- (OFArray OF_GENERIC(OFURI *) *)contentsOfDirectoryAtURI: (OFURI *)URI
- (OFArray OF_GENERIC(OFIRI *) *)contentsOfDirectoryAtIRI: (OFIRI *)IRI
{
	OFMutableArray *URIs = [OFMutableArray array];
	OFMutableArray *IRIs = [OFMutableArray array];
	void *pool = objc_autoreleasePoolPush();
	OFString *path;

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

	if (![URI.scheme isEqual: _scheme])
	if (![IRI.scheme isEqual: _scheme])
		@throw [OFInvalidArgumentException exception];

	path = URI.fileSystemRepresentation;
	path = IRI.fileSystemRepresentation;

#if defined(OF_WINDOWS)
	HANDLE handle;

	path = [path stringByAppendingString: @"\\*"];

	if ([OFSystemInfo isWindowsNT]) {
		WIN32_FIND_DATAW fd;

		if ((handle = FindFirstFileW(path.UTF16String,
		    &fd)) == INVALID_HANDLE_VALUE)
			@throw [OFOpenItemFailedException
			    exceptionWithURI: URI
			    exceptionWithIRI: IRI
					mode: nil
				       errNo: lastError()];

		@try {
			do {
				OFString *file;

				if (wcscmp(fd.cFileName, L".") == 0 ||
				    wcscmp(fd.cFileName, L"..") == 0)
					continue;

				file = [[OFString alloc]
				    initWithUTF16String: fd.cFileName];
				@try {
					[URIs addObject: [URI
					    URIByAppendingPathComponent: file]];
					[IRIs addObject: [IRI
					    IRIByAppendingPathComponent: file]];
				} @finally {
					[file release];
				}
			} while (FindNextFileW(handle, &fd));

			if (GetLastError() != ERROR_NO_MORE_FILES)
				@throw [OFReadFailedException
1061
1062
1063
1064
1065
1066
1067
1068

1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085


1086
1087
1088
1089
1090
1091
1092
1166
1167
1168
1169
1170
1171
1172

1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188


1189
1190
1191
1192
1193
1194
1195
1196
1197







-
+















-
-
+
+







		OFStringEncoding encoding = [OFLocale encoding];
		WIN32_FIND_DATA fd;

		if ((handle = FindFirstFileA(
		    [path cStringWithEncoding: encoding], &fd)) ==
		    INVALID_HANDLE_VALUE)
			@throw [OFOpenItemFailedException
			    exceptionWithURI: URI
			    exceptionWithIRI: IRI
					mode: nil
				       errNo: lastError()];

		@try {
			do {
				OFString *file;

				if (strcmp(fd.cFileName, ".") == 0 ||
				    strcmp(fd.cFileName, "..") == 0)
					continue;

				file = [[OFString alloc]
				    initWithCString: fd.cFileName
					   encoding: encoding];
				@try {
					[URIs addObject: [URI
					    URIByAppendingPathComponent: file]];
					[IRIs addObject: [IRI
					    IRIByAppendingPathComponent: file]];
				} @finally {
					[file release];
				}
			} while (FindNextFileA(handle, &fd));

			if (GetLastError() != ERROR_NO_MORE_FILES)
				@throw [OFReadFailedException
1100
1101
1102
1103
1104
1105
1106
1107

1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120

1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132


1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145

1146
1147
1148
1149
1150
1151
1152
1153
1154
1155


1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174

1175
1176
1177
1178
1179
1180
1181
1205
1206
1207
1208
1209
1210
1211

1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224

1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235


1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249

1250
1251
1252
1253
1254
1255
1256
1257
1258


1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278

1279
1280
1281
1282
1283
1284
1285
1286







-
+












-
+










-
-
+
+












-
+








-
-
+
+


















-
+







#elif defined(OF_AMIGAOS)
	OFStringEncoding encoding = [OFLocale encoding];
	BPTR lock;

	if ((lock = Lock([path cStringWithEncoding: encoding],
	    SHARED_LOCK)) == 0)
		@throw [OFOpenItemFailedException
		    exceptionWithURI: URI
		    exceptionWithIRI: IRI
				mode: nil
			       errNo: lastError()];

	@try {
# ifdef OF_AMIGAOS4
		struct ExamineData *ed;
		APTR context;

		if ((context = ObtainDirContextTags(EX_FileLockInput, lock,
		    EX_DoCurrentDir, TRUE, EX_DataFields, EXF_NAME,
		    TAG_END)) == NULL)
			@throw [OFOpenItemFailedException
			    exceptionWithURI: URI
			    exceptionWithIRI: IRI
					mode: nil
				       errNo: lastError()];

		@try {
			while ((ed = ExamineDir(context)) != NULL) {
				OFString *file = [[OFString alloc]
				    initWithCString: ed->Name
					   encoding: encoding];

				@try {
					[URIs addObject: [URI
					    URIByAppendingPathComponent: file]];
					[IRIs addObject: [IRI
					    IRIByAppendingPathComponent: file]];
				} @finally {
					[file release];
				}
			}
		} @finally {
			ReleaseDirContext(context);
		}
# else
		struct FileInfoBlock fib;

		if (!Examine(lock, &fib))
			@throw [OFOpenItemFailedException
			    exceptionWithURI: URI
			    exceptionWithIRI: IRI
					mode: nil
				       errNo: lastError()];

		while (ExNext(lock, &fib)) {
			OFString *file = [[OFString alloc]
			    initWithCString: fib.fib_FileName
				   encoding: encoding];
			@try {
				[URIs addObject:
				    [URI URIByAppendingPathComponent: file]];
				[IRIs addObject:
				    [IRI IRIByAppendingPathComponent: file]];
			} @finally {
				[file release];
			}
		}
# endif

		if (IoErr() != ERROR_NO_MORE_ENTRIES)
			@throw [OFReadFailedException
			    exceptionWithObject: self
				requestedLength: 0
					  errNo: lastError()];
	} @finally {
		UnLock(lock);
	}
#else
	OFStringEncoding encoding = [OFLocale encoding];
	DIR *dir;
	if ((dir = opendir([path cStringWithEncoding: encoding])) == NULL)
		@throw [OFOpenItemFailedException exceptionWithURI: URI
		@throw [OFOpenItemFailedException exceptionWithIRI: IRI
							      mode: nil
							     errNo: errno];

# if !defined(HAVE_READDIR_R) && defined(OF_HAVE_THREADS)
	@try {
		[readdirMutex lock];
	} @catch (id e) {
1217
1218
1219
1220
1221
1222
1223
1224
1225


1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238

1239
1240
1241
1242

1243
1244
1245

1246
1247
1248
1249
1250
1251
1252

1253
1254
1255

1256
1257
1258

1259
1260
1261

1262
1263
1264
1265

1266
1267
1268

1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279

1280
1281
1282
1283
1284
1285

1286
1287
1288

1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306

1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321

1322
1323
1324
1325
1326
1327
1328
1329

1330
1331
1332
1333
1334
1335
1336
1337

1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359


1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370


1371
1372
1373
1374
1375
1376
1377
1378
1379

1380
1381
1382
1383
1384
1385

1386
1387
1388

1389
1390
1391

1392
1393
1394
1395
1396
1397
1398
1399

1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410

1411
1412
1413
1414
1415
1416
1417
1418
1419

1420
1421
1422
1423
1424
1425
1426
1427

1428
1429
1430


1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444


1445
1446
1447
1448
1449
1450
1451
1322
1323
1324
1325
1326
1327
1328


1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342

1343
1344
1345
1346

1347
1348
1349

1350
1351
1352
1353
1354
1355
1356

1357
1358
1359

1360
1361
1362

1363
1364
1365

1366
1367
1368
1369

1370
1371
1372

1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383

1384
1385
1386
1387
1388
1389

1390
1391
1392

1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410

1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425

1426
1427
1428
1429
1430
1431
1432
1433

1434
1435
1436
1437
1438
1439
1440
1441

1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462


1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473


1474
1475
1476
1477
1478
1479
1480
1481
1482
1483

1484
1485
1486
1487
1488
1489

1490
1491
1492

1493
1494
1495

1496
1497
1498
1499
1500
1501
1502
1503

1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514

1515
1516
1517
1518
1519
1520
1521
1522
1523

1524
1525
1526
1527
1528
1529
1530
1531

1532
1533


1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547


1548
1549
1550
1551
1552
1553
1554
1555
1556







-
-
+
+












-
+



-
+


-
+






-
+


-
+


-
+


-
+



-
+


-
+










-
+





-
+


-
+

















-
+














-
+







-
+







-
+




















-
-
+
+









-
-
+
+








-
+





-
+


-
+


-
+







-
+










-
+








-
+







-
+

-
-
+
+












-
-
+
+







			if (strcmp(dirent->d_name, ".") == 0 ||
			    strcmp(dirent->d_name, "..") == 0)
				continue;

			file = [[OFString alloc] initWithCString: dirent->d_name
							encoding: encoding];
			@try {
				[URIs addObject:
				    [URI URIByAppendingPathComponent: file]];
				[IRIs addObject:
				    [IRI IRIByAppendingPathComponent: file]];
			} @finally {
				[file release];
			}
		}
	} @finally {
		closedir(dir);
# if !defined(HAVE_READDIR_R) && defined(OF_HAVE_THREADS)
		[readdirMutex unlock];
# endif
	}
#endif

	[URIs makeImmutable];
	[IRIs makeImmutable];

	objc_autoreleasePoolPop(pool);

	return URIs;
	return IRIs;
}

- (void)removeItemAtURI: (OFURI *)URI
- (void)removeItemAtIRI: (OFIRI *)IRI
{
	void *pool = objc_autoreleasePoolPush();
	OFString *path;
	int error;
	Stat s;

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

	if (![URI.scheme isEqual: _scheme])
	if (![IRI.scheme isEqual: _scheme])
		@throw [OFInvalidArgumentException exception];

	path = URI.fileSystemRepresentation;
	path = IRI.fileSystemRepresentation;

	if ((error = lstatWrapper(path, &s)) != 0)
		@throw [OFRemoveItemFailedException exceptionWithURI: URI
		@throw [OFRemoveItemFailedException exceptionWithIRI: IRI
							       errNo: error];

	if (S_ISDIR(s.st_mode)) {
		OFArray OF_GENERIC(OFURI *) *contents;
		OFArray OF_GENERIC(OFIRI *) *contents;

		@try {
			contents = [self contentsOfDirectoryAtURI: URI];
			contents = [self contentsOfDirectoryAtIRI: IRI];
		} @catch (id e) {
			/*
			 * Only convert exceptions to
			 * OFRemoveItemFailedException that have an errNo
			 * property. This covers all I/O related exceptions
			 * from the operations used to remove an item, all
			 * others should be left as is.
			 */
			if ([e respondsToSelector: @selector(errNo)])
				@throw [OFRemoveItemFailedException
				    exceptionWithURI: URI
				    exceptionWithIRI: IRI
					       errNo: [e errNo]];

			@throw e;
		}

		for (OFURI *item in contents) {
		for (OFIRI *item in contents) {
			void *pool2 = objc_autoreleasePoolPush();

			[self removeItemAtURI: item];
			[self removeItemAtIRI: item];

			objc_autoreleasePoolPop(pool2);
		}

#ifndef OF_AMIGAOS
		int status;

# ifdef OF_WINDOWS
		if ([OFSystemInfo isWindowsNT])
			status = _wrmdir(path.UTF16String);
		else
# endif
			status = rmdir(
			    [path cStringWithEncoding: [OFLocale encoding]]);

		if (status != 0)
			@throw [OFRemoveItemFailedException
				exceptionWithURI: URI
				exceptionWithIRI: IRI
					   errNo: errno];
	} else {
		int status;

# ifdef OF_WINDOWS
		if ([OFSystemInfo isWindowsNT])
			status = _wunlink(path.UTF16String);
		else
# endif
			status = unlink(
			    [path cStringWithEncoding: [OFLocale encoding]]);

		if (status != 0)
			@throw [OFRemoveItemFailedException
			    exceptionWithURI: URI
			    exceptionWithIRI: IRI
				       errNo: errno];
#endif
	}

#ifdef OF_AMIGAOS
	if (!DeleteFile([path cStringWithEncoding: [OFLocale encoding]]))
		@throw [OFRemoveItemFailedException
		    exceptionWithURI: URI
		    exceptionWithIRI: IRI
			       errNo: lastError()];
#endif

	objc_autoreleasePoolPop(pool);
}

#ifdef OF_FILE_MANAGER_SUPPORTS_LINKS
- (void)linkItemAtURI: (OFURI *)source toURI: (OFURI *)destination
- (void)linkItemAtIRI: (OFIRI *)source toIRI: (OFIRI *)destination
{
	void *pool = objc_autoreleasePoolPush();
	OFString *sourcePath, *destinationPath;

	if (source == nil || destination == nil)
		@throw [OFInvalidArgumentException exception];

	if (![source.scheme isEqual: _scheme] ||
	    ![destination.scheme isEqual: _scheme])
		@throw [OFInvalidArgumentException exception];

	sourcePath = source.fileSystemRepresentation;
	destinationPath = destination.fileSystemRepresentation;

# ifndef OF_WINDOWS
	OFStringEncoding encoding = [OFLocale encoding];

	if (link([sourcePath cStringWithEncoding: encoding],
	    [destinationPath cStringWithEncoding: encoding]) != 0)
		@throw [OFLinkItemFailedException
		    exceptionWithSourceURI: source
			    destinationURI: destination
		    exceptionWithSourceIRI: source
			    destinationIRI: destination
				     errNo: errno];
# else
	if (createHardLinkWFuncPtr == NULL)
		@throw [OFNotImplementedException exceptionWithSelector: _cmd
								 object: self];

	if (!createHardLinkWFuncPtr(destinationPath.UTF16String,
	    sourcePath.UTF16String, NULL))
		@throw [OFLinkItemFailedException
		    exceptionWithSourceURI: source
			    destinationURI: destination
		    exceptionWithSourceIRI: source
			    destinationIRI: destination
				     errNo: lastError()];
# endif

	objc_autoreleasePoolPop(pool);
}
#endif

#ifdef OF_FILE_MANAGER_SUPPORTS_SYMLINKS
- (void)createSymbolicLinkAtURI: (OFURI *)URI
- (void)createSymbolicLinkAtIRI: (OFIRI *)IRI
	    withDestinationPath: (OFString *)target
{
	void *pool = objc_autoreleasePoolPush();
	OFString *path;

	if (URI == nil || target == nil)
	if (IRI == nil || target == nil)
		@throw [OFInvalidArgumentException exception];

	if (![URI.scheme isEqual: _scheme])
	if (![IRI.scheme isEqual: _scheme])
		@throw [OFInvalidArgumentException exception];

	path = URI.fileSystemRepresentation;
	path = IRI.fileSystemRepresentation;

# ifndef OF_WINDOWS
	OFStringEncoding encoding = [OFLocale encoding];

	if (symlink([target cStringWithEncoding: encoding],
	    [path cStringWithEncoding: encoding]) != 0)
		@throw [OFCreateSymbolicLinkFailedException
		    exceptionWithURI: URI
		    exceptionWithIRI: IRI
			      target: target
			       errNo: errno];
# else
	if (createSymbolicLinkWFuncPtr == NULL)
		@throw [OFNotImplementedException exceptionWithSelector: _cmd
								 object: self];

	if (!createSymbolicLinkWFuncPtr(path.UTF16String, target.UTF16String,
	    0))
		@throw [OFCreateSymbolicLinkFailedException
		    exceptionWithURI: URI
		    exceptionWithIRI: IRI
			      target: target
			       errNo: lastError()];
# endif

	objc_autoreleasePoolPop(pool);
}
#endif

- (bool)moveItemAtURI: (OFURI *)source toURI: (OFURI *)destination
- (bool)moveItemAtIRI: (OFIRI *)source toIRI: (OFIRI *)destination
{
	void *pool;

	if (![source.scheme isEqual: _scheme] ||
	    ![destination.scheme isEqual: _scheme])
		return false;

	if ([self fileExistsAtURI: destination])
	if ([self fileExistsAtIRI: destination])
		@throw [OFMoveItemFailedException
		    exceptionWithSourceURI: source
			    destinationURI: destination
		    exceptionWithSourceIRI: source
			    destinationIRI: destination
				     errNo: EEXIST];

	pool = objc_autoreleasePoolPush();

#ifdef OF_AMIGAOS
	OFStringEncoding encoding = [OFLocale encoding];

	if (!Rename([source.fileSystemRepresentation
	    cStringWithEncoding: encoding],
	    [destination.fileSystemRepresentation
	    cStringWithEncoding: encoding]))
		@throw [OFMoveItemFailedException
		    exceptionWithSourceURI: source
			    destinationURI: destination
		    exceptionWithSourceIRI: source
			    destinationIRI: destination
				     errNo: lastError()];
#else
	int status;

# ifdef OF_WINDOWS
	if ([OFSystemInfo isWindowsNT])
		status = _wrename(source.fileSystemRepresentation.UTF16String,
1460
1461
1462
1463
1464
1465
1466
1467
1468


1469
1470
1471
1472
1473
1474
1475


































































































1476
1565
1566
1567
1568
1569
1570
1571


1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679







-
-
+
+







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

		    cStringWithEncoding: encoding]);
# ifdef OF_WINDOWS
	}
# endif

	if (status != 0)
		@throw [OFMoveItemFailedException
		    exceptionWithSourceURI: source
			    destinationURI: destination
		    exceptionWithSourceIRI: source
			    destinationIRI: destination
				     errNo: errno];
#endif

	objc_autoreleasePoolPop(pool);

	return true;
}

#ifdef OF_FILE_MANAGER_SUPPORTS_EXTENDED_ATTRIBUTES
- (OFData *)extendedAttributeDataForName: (OFString *)name
			     ofItemAtIRI: (OFIRI *)IRI
{
	void *pool = objc_autoreleasePoolPush();
	OFString *path = IRI.fileSystemRepresentation;
	OFStringEncoding encoding = [OFLocale encoding];
	const char *cPath = [path cStringWithEncoding: encoding];
	const char *cName = [name cStringWithEncoding: encoding];
# if defined(OF_LINUX)
	ssize_t size = lgetxattr(cPath, cName, NULL, 0);
# elif defined(OF_MACOS)
	ssize_t size = getxattr(cPath, cName, NULL, 0, 0, XATTR_NOFOLLOW);
# endif
	void *value = OFAllocMemory(1, size);
	OFData *data;

	@try {
# if defined(OF_LINUX)
		if ((size = lgetxattr(cPath, cName, value, size)) < 0)
# elif defined(OF_MACOS)
		if ((size = getxattr(cPath, cName, value, size, 0,
		    XATTR_NOFOLLOW)) < 0)
# endif
			@throw [OFGetItemAttributesFailedException
			    exceptionWithIRI: IRI
				       errNo: errno];

		data = [OFData dataWithItems: value count: size];
	} @finally {
		OFFreeMemory(value);
	}

	[data retain];

	objc_autoreleasePoolPop(pool);

	return [data autorelease];
}

- (void)setExtendedAttributeData: (OFData *)data
			 forName: (OFString *)name
		     ofItemAtIRI: (OFIRI *)IRI
{
	void *pool = objc_autoreleasePoolPush();
	OFString *path = IRI.fileSystemRepresentation;
	OFStringEncoding encoding = [OFLocale encoding];

# if defined(OF_LINUX)
	if (lsetxattr([path cStringWithEncoding: encoding],
	    [name cStringWithEncoding: encoding], data.items,
	    data.count * data.itemSize, 0) != 0) {
# elif defined(OF_MACOS)
	if (setxattr([path cStringWithEncoding: encoding],
	    [name cStringWithEncoding: encoding], data.items,
	    data.count * data.itemSize, 0, XATTR_NOFOLLOW) != 0) {
# endif
		int errNo = errno;

		/* TODO: Add an attribute (prefix?) for extended attributes? */
		@throw [OFSetItemAttributesFailedException
		    exceptionWithIRI: IRI
			  attributes: [OFDictionary dictionary]
		     failedAttribute: @""
			       errNo: errNo];
	}

	objc_autoreleasePoolPop(pool);
}

- (void)removeExtendedAttributeForName: (OFString *)name
			   ofItemAtIRI: (OFIRI *)IRI
{
	void *pool = objc_autoreleasePoolPush();
	OFString *path = IRI.fileSystemRepresentation;
	OFStringEncoding encoding = [OFLocale encoding];

# if defined(OF_LINUX)
	if (lremovexattr([path cStringWithEncoding: encoding],
	    [name cStringWithEncoding: encoding]) != 0) {
# elif defined(OF_MACOS)
	if (removexattr([path cStringWithEncoding: encoding],
	    [name cStringWithEncoding: encoding], XATTR_NOFOLLOW) != 0) {
# endif
		int errNo = errno;

		/* TODO: Add an attribute (prefix?) for extended attributes? */
		@throw [OFSetItemAttributesFailedException
		    exceptionWithIRI: IRI
			  attributes: [OFDictionary dictionary]
		     failedAttribute: @""
			       errNo: errNo];
	}

	objc_autoreleasePoolPop(pool);
}
#endif
@end

Modified src/OFFileManager.h from [1cfc8cfdf6] to [eca60449c1].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
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
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







+
+
+





-
-
+
+




-
+













+

-
+






-
+










-
+







# endif
# if (defined(OF_HAVE_LINK) && !defined(OF_AMIGAOS)) || defined(OF_WINDOWS)
#  define OF_FILE_MANAGER_SUPPORTS_LINKS
# endif
# if (defined(OF_HAVE_SYMLINK) && !defined(OF_AMIGAOS)) || defined(OF_WINDOWS)
#  define OF_FILE_MANAGER_SUPPORTS_SYMLINKS
# endif
# if defined(OF_LINUX) || defined(OF_MACOS)
#  define OF_FILE_MANAGER_SUPPORTS_EXTENDED_ATTRIBUTES
# endif
#endif

@class OFArray OF_GENERIC(ObjectType);
@class OFConstantString;
@class OFDate;
@class OFString;
@class OFURI;
@class OFIRI;
@class OFString;

/**
 * @brief A key for a file attribute in the file attributes dictionary.
 *
 * Possible keys for file URIs are:
 * Possible keys for file IRIs are:
 *
 *  * @ref OFFileSize
 *  * @ref OFFileType
 *  * @ref OFFilePOSIXPermissions
 *  * @ref OFFileOwnerAccountID
 *  * @ref OFFileGroupOwnerAccountID
 *  * @ref OFFileOwnerAccountName
 *  * @ref OFFileGroupOwnerAccountName
 *  * @ref OFFileLastAccessDate
 *  * @ref OFFileModificationDate
 *  * @ref OFFileStatusChangeDate
 *  * @ref OFFileCreationDate
 *  * @ref OFFileSymbolicLinkDestination
 *  * @ref OFFileExtendedAttributesNames
 *
 * Other URI schemes might not have all keys and might have keys not listed.
 * Other IRI schemes might not have all keys and might have keys not listed.
 */
typedef OFConstantString *OFFileAttributeKey;

/**
 * @brief The type of a file.
 *
 * Possibles values for file URIs are:
 * Possibles values for file IRIs are:
 *
 *  * @ref OFFileTypeRegular
 *  * @ref OFFileTypeDirectory
 *  * @ref OFFileTypeSymbolicLink
 *  * @ref OFFileTypeFIFO
 *  * @ref OFFileTypeCharacterSpecial
 *  * @ref OFFileTypeBlockSpecial
 *  * @ref OFFileTypeSocket
 *  * @ref OFFileTypeUnknown
 *
 * Other URI schemes might not have all types and might have types not listed.
 * Other IRI schemes might not have all types and might have types not listed.
 */
typedef OFConstantString *OFFileAttributeType;

/**
 * @brief A dictionary mapping keys of type @ref OFFileAttributeKey to their
 *	  attribute values.
 */
184
185
186
187
188
189
190
191

192
193
194
195
196
197









198
199
200
201
202
203
204
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







-
+






+
+
+
+
+
+
+
+
+







 *
 * For convenience, a category on @ref OFDictionary is provided to access this
 * via @ref OFDictionary#fileCreationDate.
 */
extern const OFFileAttributeKey OFFileCreationDate;

/**
 * @brief The destination of a symbolic link as an OFString.
 * @brief The destination of a symbolic link as an @ref OFString.
 *
 * For convenience, a category on @ref OFDictionary is provided to access this
 * via @ref OFDictionary#fileSymbolicLinkDestination.
 */
extern const OFFileAttributeKey OFFileSymbolicLinkDestination;

/**
 * @brief The names of the extended attributes as an @ref OFArray of
 *	  @ref OFString.
 *
 * For convenience, a category on @ref OFDictionary is provided to access this
 * via @ref OFDictionary#fileExtendedAttributesNames.
 */
extern const OFFileAttributeKey OFFileExtendedAttributesNames;

/**
 * @brief A regular file.
 */
extern const OFFileAttributeType OFFileTypeRegular;

/**
 * @brief A directory.
261
262
263
264
265
266
267
268

269
270
271
272

273
274
275
276
277
278
279
274
275
276
277
278
279
280

281
282
283
284

285
286
287
288
289
290
291
292







-
+



-
+







 * @brief The path of the current working directory.
 *
 * @throw OFGetCurrentDirectoryFailedException Couldn't get current directory
 */
@property (readonly, nonatomic) OFString *currentDirectoryPath;

/**
 * @brief The URI of the current working directory.
 * @brief The IRI of the current working directory.
 *
 * @throw OFGetCurrentDirectoryFailedException Couldn't get current directory
 */
@property (readonly, nonatomic) OFURI *currentDirectoryURI;
@property (readonly, nonatomic) OFIRI *currentDirectoryIRI;
#endif

/**
 * @brief Returns the default file manager.
 */
+ (OFFileManager *)defaultManager;

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
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
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
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







-
+

-
-
+
+



-
+


-
+




















-
+



-
-
+
+


-
+





-
+












-
+

-
-
-
+
+
+


-
+












-
+

-
-
-
+
+
+


-
+







 * @throw OFGetItemAttributesFailedException Failed to get the attributes of
 *					     the item
 */
- (OFFileAttributes)attributesOfItemAtPath: (OFString *)path;
#endif

/**
 * @brief Returns the attributes for the item at the specified URI.
 * @brief Returns the attributes for the item at the specified IRI.
 *
 * @param URI The URI to return the attributes for
 * @return A dictionary of attributes for the specified URI, with the keys of
 * @param IRI The IRI to return the attributes for
 * @return A dictionary of attributes for the specified IRI, with the keys of
 *	   type @ref OFFileAttributeKey
 * @throw OFGetItemAttributesFailedException Failed to get the attributes of
 *					     the item
 * @throw OFUnsupportedProtocolException No handler is registered for the URI's
 * @throw OFUnsupportedProtocolException No handler is registered for the IRI's
 *					 scheme
 */
- (OFFileAttributes)attributesOfItemAtURI: (OFURI *)URI;
- (OFFileAttributes)attributesOfItemAtIRI: (OFIRI *)IRI;

#ifdef OF_HAVE_FILES
/**
 * @brief Sets the attributes for the item at the specified path.
 *
 * All attributes not part of the dictionary are left unchanged.
 *
 * @param attributes The attributes to set for the specified path
 * @param path The path of the item to set the attributes for
 * @throw OFSetItemAttributesFailedException Failed to set the attributes of
 *					     the item
 * @throw OFNotImplementedException Setting one or more of the specified
 *				    attributes is not implemented for the
 *				    specified item
 */
- (void)setAttributes: (OFFileAttributes)attributes
	 ofItemAtPath: (OFString *)path;
#endif

/**
 * @brief Sets the attributes for the item at the specified URI.
 * @brief Sets the attributes for the item at the specified IRI.
 *
 * All attributes not part of the dictionary are left unchanged.
 *
 * @param attributes The attributes to set for the specified URI
 * @param URI The URI of the item to set the attributes for
 * @param attributes The attributes to set for the specified IRI
 * @param IRI The IRI of the item to set the attributes for
 * @throw OFSetItemAttributesFailedException Failed to set the attributes of
 *					     the item
 * @throw OFUnsupportedProtocolException No handler is registered for the URI's
 * @throw OFUnsupportedProtocolException No handler is registered for the IRI's
 *					 scheme
 * @throw OFNotImplementedException Setting one or more of the specified
 *				    attributes is not implemented for the
 *				    specified item
 */
- (void)setAttributes: (OFFileAttributes)attributes ofItemAtURI: (OFURI *)URI;
- (void)setAttributes: (OFFileAttributes)attributes ofItemAtIRI: (OFIRI *)IRI;

#ifdef OF_HAVE_FILES
/**
 * @brief Checks whether a file exists at the specified path.
 *
 * @param path The path to check
 * @return A boolean whether there is a file at the specified path
 */
- (bool)fileExistsAtPath: (OFString *)path;
#endif

/**
 * @brief Checks whether a file exists at the specified URI.
 * @brief Checks whether a file exists at the specified IRI.
 *
 * @param URI The URI to check
 * @return A boolean whether there is a file at the specified URI
 * @throw OFUnsupportedProtocolException No handler is registered for the URI's
 * @param IRI The IRI to check
 * @return A boolean whether there is a file at the specified IRI
 * @throw OFUnsupportedProtocolException No handler is registered for the IRI's
 *					 scheme
 */
- (bool)fileExistsAtURI: (OFURI *)URI;
- (bool)fileExistsAtIRI: (OFIRI *)IRI;

#ifdef OF_HAVE_FILES
/**
 * @brief Checks whether a directory exists at the specified path.
 *
 * @param path The path to check
 * @return A boolean whether there is a directory at the specified path
 */
- (bool)directoryExistsAtPath: (OFString *)path;
#endif

/**
 * @brief Checks whether a directory exists at the specified URI.
 * @brief Checks whether a directory exists at the specified IRI.
 *
 * @param URI The URI to check
 * @return A boolean whether there is a directory at the specified URI
 * @throw OFUnsupportedProtocolException No handler is registered for the URI's
 * @param IRI The IRI to check
 * @return A boolean whether there is a directory at the specified IRI
 * @throw OFUnsupportedProtocolException No handler is registered for the IRI's
 *					 scheme
 */
- (bool)directoryExistsAtURI: (OFURI *)URI;
- (bool)directoryExistsAtIRI: (OFIRI *)IRI;

#ifdef OF_HAVE_FILES
/**
 * @brief Creates a directory at the specified path.
 *
 * @param path The path of the directory to create
 * @throw OFCreateDirectoryFailedException Creating the directory failed
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
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







-
+

-
+

-
+


-
+


-
+

-
+



-
+


-
+
















-
+




-
-
+
+


-
+


-
+







 *					   parents failed
 */
- (void)createDirectoryAtPath: (OFString *)path
		createParents: (bool)createParents;
#endif

/**
 * @brief Creates a directory at the specified URI.
 * @brief Creates a directory at the specified IRI.
 *
 * @param URI The URI of the directory to create
 * @param IRI The IRI of the directory to create
 * @throw OFCreateDirectoryFailedException Creating the directory failed
 * @throw OFUnsupportedProtocolException No handler is registered for the URI's
 * @throw OFUnsupportedProtocolException No handler is registered for the IRI's
 *					 scheme
 */
- (void)createDirectoryAtURI: (OFURI *)URI;
- (void)createDirectoryAtIRI: (OFIRI *)IRI;

/**
 * @brief Creates a directory at the specified URI.
 * @brief Creates a directory at the specified IRI.
 *
 * @param URI The URI of the directory to create
 * @param IRI The IRI of the directory to create
 * @param createParents Whether to create the parents of the directory
 * @throw OFCreateDirectoryFailedException Creating the directory or one of its
 *					   parents failed
 * @throw OFUnsupportedProtocolException No handler is registered for the URI's
 * @throw OFUnsupportedProtocolException No handler is registered for the IRI's
 *					 scheme
 */
- (void)createDirectoryAtURI: (OFURI *)URI createParents: (bool)createParents;
- (void)createDirectoryAtIRI: (OFIRI *)IRI createParents: (bool)createParents;

#ifdef OF_HAVE_FILES
/**
 * @brief Returns an array with the items in the specified directory.
 *
 * @note `.` and `..` are not part of the returned array.
 *
 * @param path The path to the directory whose items should be returned
 * @return An array of OFString with the items in the specified directory
 * @throw OFOpenItemFailedException Opening the directory failed
 * @throw OFReadFailedException Reading from the directory failed
 */
- (OFArray OF_GENERIC(OFString *) *)contentsOfDirectoryAtPath: (OFString *)path;
#endif

/**
 * @brief Returns an array with the URIs of the items in the specified
 * @brief Returns an array with the IRIs of the items in the specified
 *	  directory.
 *
 * @note `.` and `..` are not part of the returned array.
 *
 * @param URI The URI to the directory whose items should be returned
 * @return An array with the URIs of the items in the specified directory
 * @param IRI The IRI to the directory whose items should be returned
 * @return An array with the IRIs of the items in the specified directory
 * @throw OFOpenItemFailedException Opening the directory failed
 * @throw OFReadFailedException Reading from the directory failed
 * @throw OFUnsupportedProtocolException No handler is registered for the URI's
 * @throw OFUnsupportedProtocolException No handler is registered for the IRI's
 *					 scheme
 */
- (OFArray OF_GENERIC(OFURI *) *)contentsOfDirectoryAtURI: (OFURI *)URI;
- (OFArray OF_GENERIC(OFIRI *) *)contentsOfDirectoryAtIRI: (OFIRI *)IRI;

#ifdef OF_HAVE_FILES
/**
 * @brief Returns an array with all subpaths of the specified directory.
 *
 * @note `.` and `..` (of the directory itself or any subdirectory) are not
 * part of the returned array.
470
471
472
473
474
475
476
477

478
479
480
481

482
483
484
485
486
487
488
483
484
485
486
487
488
489

490
491
492
493

494
495
496
497
498
499
500
501







-
+



-
+







 *						  directory failed
 */
- (void)changeCurrentDirectoryPath: (OFString *)path;

/**
 * @brief Changes the current working directory.
 *
 * @param URI The new directory to change to
 * @param IRI The new directory to change to
 * @throw OFChangeCurrentDirectoryFailedException Changing the current working
 *						  directory failed
 */
- (void)changeCurrentDirectoryURI: (OFURI *)URI;
- (void)changeCurrentDirectoryIRI: (OFIRI *)IRI;

/**
 * @brief Copies a file, directory or symbolic link (if supported by the OS).
 *
 * The destination path must be a full path, which means it must include the
 * name of the item.
 *
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
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







-
+







-
+




-
+

-
+







 */
- (void)copyItemAtPath: (OFString *)source toPath: (OFString *)destination;
#endif

/**
 * @brief Copies a file, directory or symbolic link (if supported by the OS).
 *
 * The destination URI must have a full path, which means it must include the
 * The destination IRI must have a full path, which means it must include the
 * name of the item.
 *
 * If an item already exists, the copy operation fails. This is also the case
 * if a directory is copied and an item already exists in the destination
 * directory.
 *
 * @param source The file, directory or symbolic link to copy
 * @param destination The destination URI
 * @param destination The destination IRI
 * @throw OFCopyItemFailedException Copying failed
 * @throw OFCreateDirectoryFailedException Creating a destination directory
 *					   failed
 * @throw OFUnsupportedProtocolException No handler is registered for either of
 *					 the URI's scheme
 *					 the IRI's scheme
 */
- (void)copyItemAtURI: (OFURI *)source toURI: (OFURI *)destination;
- (void)copyItemAtIRI: (OFIRI *)source toIRI: (OFIRI *)destination;

#ifdef OF_HAVE_FILES
/**
 * @brief Moves an item.
 *
 * The destination path must be a full path, which means it must include the
 * name of the item.
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
572
573
574
575
576
577
578
579
580
581
582
583
584
585

586
587

588
589

590
591

592
593
594

595
596
597
598
599
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
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
676
677
678
556
557
558
559
560
561
562

563
564
565
566
567

568
569
570
571
572
573
574
575
576
577
578
579
580

581
582

583
584
585
586
587
588
589
590
591
592
593
594
595
596
597

598
599

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
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
676
677

678
679
680

681
682
683

684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
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
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804







-
+




-
+












-
+

-
+














-
+

-
+

-
+

-
+


-
+














-
+







-
+


-
+

-
-
+
+

-
+


-
+

-
+

















-
+








-
+


-
+

-
-
+
+

-
+

+
-
+


-
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







 */
- (void)moveItemAtPath: (OFString *)source toPath: (OFString *)destination;
#endif

/**
 * @brief Moves an item.
 *
 * The destination URI must have a full path, which means it must include the
 * The destination IRI must have a full path, which means it must include the
 * name of the item.
 *
 * If the destination is on a different logical device or uses a different
 * scheme, the source will be copied to the destination using
 * @ref copyItemAtURI:toURI: and the source removed using @ref removeItemAtURI:.
 * @ref copyItemAtIRI:toIRI: and the source removed using @ref removeItemAtIRI:.
 *
 * @param source The item to rename
 * @param destination The new name for the item
 * @throw OFMoveItemFailedException Moving failed
 * @throw OFCopyItemFailedException Copying (to move between different devices)
 *				    failed
 * @throw OFRemoveItemFailedException Removing the source after copying to the
 *				      destination (to move between different
 *				      devices) failed
 * @throw OFCreateDirectoryFailedException Creating a destination directory
 *					   failed
 * @throw OFUnsupportedProtocolException No handler is registered for either of
 *					 the URI's scheme
 *					 the IRI's scheme
 */
- (void)moveItemAtURI: (OFURI *)source toURI: (OFURI *)destination;
- (void)moveItemAtIRI: (OFIRI *)source toIRI: (OFIRI *)destination;

#ifdef OF_HAVE_FILES
/**
 * @brief Removes the item at the specified path.
 *
 * If the item at the specified path is a directory, it is removed recursively.
 *
 * @param path The path to the item which should be removed
 * @throw OFRemoveItemFailedException Removing the item failed
 */
- (void)removeItemAtPath: (OFString *)path;
#endif

/**
 * @brief Removes the item at the specified URI.
 * @brief Removes the item at the specified IRI.
 *
 * If the item at the specified URI is a directory, it is removed recursively.
 * If the item at the specified IRI is a directory, it is removed recursively.
 *
 * @param URI The URI to the item which should be removed
 * @param IRI The IRI to the item which should be removed
 * @throw OFRemoveItemFailedException Removing the item failed
 * @throw OFUnsupportedProtocolException No handler is registered for the URI's
 * @throw OFUnsupportedProtocolException No handler is registered for the IRI's
 *					 scheme
 */
- (void)removeItemAtURI: (OFURI *)URI;
- (void)removeItemAtIRI: (OFIRI *)IRI;

#ifdef OF_FILE_MANAGER_SUPPORTS_LINKS
/**
 * @brief Creates a hard link for the specified item.
 *
 * The destination path must be a full path, which means it must include the
 * name of the item.
 *
 * This method is not available on some systems.
 *
 * @param source The path to the item for which a link should be created
 * @param destination The path to the item which should link to the source
 * @throw OFLinkItemFailedException Linking the item failed
 * @throw OFNotImplementedException Hardlinks are not implemented for the
 *				    specified URI
 *				    specified IRI
 */
- (void)linkItemAtPath: (OFString *)source toPath: (OFString *)destination;
#endif

/**
 * @brief Creates a hard link for the specified item.
 *
 * The destination URI must have a full path, which means it must include the
 * The destination IRI must have a full path, which means it must include the
 * name of the item.
 *
 * This method is not available for all URIs.
 * This method is not available for all IRIs.
 *
 * @param source The URI to the item for which a link should be created
 * @param destination The URI to the item which should link to the source
 * @param source The IRI to the item for which a link should be created
 * @param destination The IRI to the item which should link to the source
 * @throw OFLinkItemFailedException Linking the item failed
 * @throw OFUnsupportedProtocolException No handler is registered for the URI's
 * @throw OFUnsupportedProtocolException No handler is registered for the IRI's
 *					 scheme
 * @throw OFNotImplementedException Hardlinks are not implemented for the
 *				    specified URI
 *				    specified IRI
 */
- (void)linkItemAtURI: (OFURI *)source toURI: (OFURI *)destination;
- (void)linkItemAtIRI: (OFIRI *)source toIRI: (OFIRI *)destination;

#ifdef OF_FILE_MANAGER_SUPPORTS_SYMLINKS
/**
 * @brief Creates a symbolic link for an item.
 *
 * The destination path must be a full path, which means it must include the
 * name of the item.
 *
 * This method is not available on some systems.
 *
 * @note On Windows, this requires at least Windows Vista and administrator
 *	 privileges!
 *
 * @param path The path to the item which should symbolically link to the target
 * @param target The target of the symbolic link
 * @throw OFCreateSymbolicLinkFailedException Creating the symbolic link failed
 * @throw OFNotImplementedException Symbolic links are not implemented for the
 *				    specified URI
 *				    specified IRI
 */
- (void)createSymbolicLinkAtPath: (OFString *)path
	     withDestinationPath: (OFString *)target;
#endif

/**
 * @brief Creates a symbolic link for an item.
 *
 * The destination URI must have a full path, which means it must include the
 * The destination IRI must have a full path, which means it must include the
 * name of the item.
 *
 * This method is not available for all URIs.
 * This method is not available for all IRIs.
 *
 * @note On Windows, this requires at least Windows Vista and administrator
 *	 privileges!
 * @note For file IRIs on Windows, this requires at least Windows Vista and
 *	 administrator privileges!
 *
 * @param URI The URI to the item which should symbolically link to the target
 * @param IRI The IRI to the item which should symbolically link to the target
 * @param target The target of the symbolic link
 * @throw OFOFCreateSymbolicLinkFailedException Creating a symbolic link failed
 * @throw OFUnsupportedProtocolException No handler is registered for the URI's
 * @throw OFUnsupportedProtocolException No handler is registered for the IRI's
 *					 scheme
 */
- (void)createSymbolicLinkAtURI: (OFURI *)URI
- (void)createSymbolicLinkAtIRI: (OFIRI *)IRI
	    withDestinationPath: (OFString *)target;

#ifdef OF_FILE_MANAGER_SUPPORTS_EXTENDED_ATTRIBUTES
/**
 * @brief Returns the extended attribute data for the specified name of the
 *	  item at the specified path.
 *
 * This method is not available on some systems.
 *
 * @param name The name of the extended attribute
 * @param path The path of the item to return the extended attribute from
 * @throw OFGetItemAttributesFailedException Getting the extended attribute
 *					     failed
 * @throw OFNotImplementedException Getting extended attributes is not
 *				    implemented for the specified item
 */
- (OFData *)extendedAttributeDataForName: (OFString *)name
			    ofItemAtPath: (OFString *)path;
#endif

/**
 * @brief Returns the extended attribute data for the specified name of the
 *	  item at the specified IRI.
 *
 * This method is not available for all IRIs.
 *
 * @param name The name of the extended attribute
 * @param IRI The IRI of the item to return the extended attribute from
 * @throw OFGetItemAttributesFailedException Getting the extended attribute
 *					     failed
 * @throw OFUnsupportedProtocolException No handler is registered for the IRI's
 *					 scheme
 * @throw OFNotImplementedException Getting extended attributes is not
 *				    implemented for the specified item
 */
- (OFData *)extendedAttributeDataForName: (OFString *)name
			     ofItemAtIRI: (OFIRI *)IRI;

#ifdef OF_FILE_MANAGER_SUPPORTS_EXTENDED_ATTRIBUTES
/**
 * @brief Sets the extended attribute data for the specified name of the item
 *	  at the specified path.
 *
 * This method is not available on some systems.
 *
 * @param data The data for the extended attribute
 * @param name The name of the extended attribute
 * @param path The path of the item to set the extended attribute on
 * @throw OFSetItemAttributesFailedException Setting the extended attribute
 *					     failed
 * @throw OFNotImplementedException Setting extended attributes is not
 *				    implemented for the specified item
 */
- (void)setExtendedAttributeData: (OFData *)data
			 forName: (OFString *)name
		    ofItemAtPath: (OFString *)path;
#endif

/**
 * @brief Sets the extended attribute data for the specified name of the item
 *	  at the specified IRI.
 *
 * This method is not available for all IRIs.
 *
 * @param data The data for the extended attribute
 * @param name The name of the extended attribute
 * @param IRI The IRI of the item to set the extended attribute on
 * @throw OFSetItemAttributesFailedException Setting the extended attribute
 *					     failed
 * @throw OFUnsupportedProtocolException No handler is registered for the IRI's
 *					 scheme
 * @throw OFNotImplementedException Setting extended attributes is not
 *				    implemented for the specified item
 */
- (void)setExtendedAttributeData: (OFData *)data
			 forName: (OFString *)name
		     ofItemAtIRI: (OFIRI *)IRI;

#ifdef OF_FILE_MANAGER_SUPPORTS_EXTENDED_ATTRIBUTES
/**
 * @brief Removes the extended attribute for the specified name wof the item at
 *	  the specified path.
 *
 * This method is not available on some systems.
 *
 * @param name The name of the extended attribute to remove
 * @param path The path of the item to remove the extended attribute from
 * @throw OFSetItemAttributesFailedException Removing the extended attribute
 *					     failed
 * @throw OFNotImplementedException Removing extended attributes is not
 *				    implemented for the specified item
 */
- (void)removeExtendedAttributeForName: (OFString *)name
			  ofItemAtPath: (OFString *)path;
#endif

/**
 * @brief Removes the extended attribute for the specified name wof the item at
 *	  the specified IRI.
 *
 * This method is not available for all IRIs.
 *
 * @param name The name of the extended attribute to remove
 * @param IRI The IRI of the item to remove the extended attribute from
 * @throw OFSetItemAttributesFailedException Removing the extended attribute
 *					     failed
 * @throw OFUnsupportedProtocolException No handler is registered for the IRI's
 *					 scheme
 * @throw OFNotImplementedException Removing extended attributes is not
 *				    implemented for the specified item
 */
- (void)removeExtendedAttributeForName: (OFString *)name
			   ofItemAtIRI: (OFIRI *)IRI;
@end

@interface OFDictionary (FileAttributes)
/**
 * @brief The @ref OFFileSize key from the dictionary.
 *
 * @throw OFUndefinedKeyException The key is missing
751
752
753
754
755
756
757








758
759
760
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894







+
+
+
+
+
+
+
+




/**
 * @brief The @ref OFFileSymbolicLinkDestination key from the dictionary.
 *
 * @throw OFUndefinedKeyException The key is missing
 */
@property (readonly, nonatomic) OFString *fileSymbolicLinkDestination;

/**
 * @brief The @ref OFFileExtendedAttributesNames key from the dictionary.
 *
 * @throw OFUndefinedKeyException The key is missing
 */
@property (readonly, nonatomic)
    OFArray OF_GENERIC(OFString *) *fileExtendedAttributesNames;
@end

OF_ASSUME_NONNULL_END

Modified src/OFFileManager.m from [5dfeac045a] to [c425786752].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
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
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







+
+
+





+






+
+





-
-








#include <errno.h>
#include <limits.h>
#include "unistd_wrapper.h"

#include "platform.h"

#ifdef OF_DJGPP
# include <syslimits.h>
#endif
#ifdef OF_PSP
# include <sys/syslimits.h>
#endif

#import "OFArray.h"
#import "OFData.h"
#import "OFDate.h"
#import "OFDictionary.h"
#ifdef OF_HAVE_FILES
# import "OFFile.h"
#endif
#import "OFFileManager.h"
#import "OFIRI.h"
#import "OFIRIHandler.h"
#import "OFLocale.h"
#import "OFNumber.h"
#import "OFStream.h"
#import "OFString.h"
#import "OFSystemInfo.h"
#import "OFURI.h"
#import "OFURIHandler.h"

#import "OFChangeCurrentDirectoryFailedException.h"
#import "OFCopyItemFailedException.h"
#import "OFCreateDirectoryFailedException.h"
#import "OFGetCurrentDirectoryFailedException.h"
#import "OFInitializationFailedException.h"
#import "OFInvalidArgumentException.h"
60
61
62
63
64
65
66

67
68

69
70
71
72
73
74
75
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81







+


+







#ifdef OF_WINDOWS
# include <windows.h>
# include <direct.h>
# include <ntdef.h>
#endif

#ifdef OF_AMIGAOS
# define Class IntuitionClass
# include <proto/exec.h>
# include <proto/dos.h>
# undef Class
#endif

#ifdef OF_MINT
# include <bits/local_lim.h>
#endif

@interface OFDefaultFileManager: OFFileManager
163
164
165
166
167
168
169
















170
171
172
173
174
175
176
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







			@throw [OFOutOfRangeException exception];

		return nil;
	}

	return [OFString stringWithCString: buffer
				  encoding: [OFLocale encoding]];
# elif defined(OF_GLIBC)
	char *buffer;
	OFString *path;

	if ((buffer = getcwd(NULL, 0)) == NULL)
		@throw [OFGetCurrentDirectoryFailedException
		    exceptionWithErrNo: errno];

	@try {
		path = [OFString stringWithCString: buffer
					  encoding: [OFLocale encoding]];
	} @finally {
		free(buffer);
	}

	return path;
# else
	char buffer[PATH_MAX];

	if ((getcwd(buffer, PATH_MAX)) == NULL)
		@throw [OFGetCurrentDirectoryFailedException
		    exceptionWithErrNo: errno];

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

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
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
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
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
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

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
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







-
+


-
+

-
+
+

-





-
+

-
+

-
+


-
-
+
+

-
+








-
+
-
-
+







-
+

-
+

-
+


-
-
+
+

-
+








-
+




-
+

-
+

-
+


-
-
+
+

-
+








-
+







-
+

-
+

-
+


-
-
+
+

-
+








-
+







-
+

-
+

-
+


-
-
+
+

-
+


-
+


-
+

-
-
+
+


-
+



-
+










-
+



-
+











-
-
+
+



-
-
-
-
+
+
+
+


-
+

-
-
-
+
+
+


-
-
-
-
+
+
+
+



-
+

-
+







-
-
+
+









-
+









-
+






-
+

-
+

-
+


-
-
+
+

-
+






-
+


-
-
+
+

-
-
+
+


-
+







#  endif

	return [OFString stringWithCString: buffer
				  encoding: [OFLocale encoding]];
# endif
}

- (OFURI *)currentDirectoryURI
- (OFIRI *)currentDirectoryIRI
{
	void *pool = objc_autoreleasePoolPush();
	OFURI *ret;
	OFIRI *ret;

	ret = [OFURI fileURIWithPath: self.currentDirectoryPath];
	ret = [OFIRI fileIRIWithPath: self.currentDirectoryPath];
	ret = [ret retain];

	[ret retain];
	objc_autoreleasePoolPop(pool);
	return [ret autorelease];
}
#endif

- (OFFileAttributes)attributesOfItemAtURI: (OFURI *)URI
- (OFFileAttributes)attributesOfItemAtIRI: (OFIRI *)IRI
{
	OFURIHandler *URIHandler;
	OFIRIHandler *IRIHandler;

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

	if ((URIHandler = [OFURIHandler handlerForURI: URI]) == nil)
		@throw [OFUnsupportedProtocolException exceptionWithURI: URI];
	if ((IRIHandler = [OFIRIHandler handlerForIRI: IRI]) == nil)
		@throw [OFUnsupportedProtocolException exceptionWithIRI: IRI];

	return [URIHandler attributesOfItemAtURI: URI];
	return [IRIHandler attributesOfItemAtIRI: IRI];
}

#ifdef OF_HAVE_FILES
- (OFFileAttributes)attributesOfItemAtPath: (OFString *)path
{
	void *pool = objc_autoreleasePoolPush();
	OFFileAttributes ret;

	ret = [self attributesOfItemAtURI: [OFURI fileURIWithPath: path]];
	ret = [self attributesOfItemAtIRI: [OFIRI fileIRIWithPath: path]];

	[ret retain];
	ret = [ret retain];

	objc_autoreleasePoolPop(pool);

	return [ret autorelease];
}
#endif

- (void)setAttributes: (OFFileAttributes)attributes ofItemAtURI: (OFURI *)URI
- (void)setAttributes: (OFFileAttributes)attributes ofItemAtIRI: (OFIRI *)IRI
{
	OFURIHandler *URIHandler;
	OFIRIHandler *IRIHandler;

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

	if ((URIHandler = [OFURIHandler handlerForURI: URI]) == nil)
		@throw [OFUnsupportedProtocolException exceptionWithURI: URI];
	if ((IRIHandler = [OFIRIHandler handlerForIRI: IRI]) == nil)
		@throw [OFUnsupportedProtocolException exceptionWithIRI: IRI];

	[URIHandler setAttributes: attributes ofItemAtURI: URI];
	[IRIHandler setAttributes: attributes ofItemAtIRI: IRI];
}

#ifdef OF_HAVE_FILES
- (void)setAttributes: (OFFileAttributes)attributes
	 ofItemAtPath: (OFString *)path
{
	void *pool = objc_autoreleasePoolPush();
	[self setAttributes: attributes
		ofItemAtURI: [OFURI fileURIWithPath: path]];
		ofItemAtIRI: [OFIRI fileIRIWithPath: path]];
	objc_autoreleasePoolPop(pool);
}
#endif

- (bool)fileExistsAtURI: (OFURI *)URI
- (bool)fileExistsAtIRI: (OFIRI *)IRI
{
	OFURIHandler *URIHandler;
	OFIRIHandler *IRIHandler;

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

	if ((URIHandler = [OFURIHandler handlerForURI: URI]) == nil)
		@throw [OFUnsupportedProtocolException exceptionWithURI: URI];
	if ((IRIHandler = [OFIRIHandler handlerForIRI: IRI]) == nil)
		@throw [OFUnsupportedProtocolException exceptionWithIRI: IRI];

	return [URIHandler fileExistsAtURI: URI];
	return [IRIHandler fileExistsAtIRI: IRI];
}

#ifdef OF_HAVE_FILES
- (bool)fileExistsAtPath: (OFString *)path
{
	void *pool = objc_autoreleasePoolPush();
	bool ret;

	ret = [self fileExistsAtURI: [OFURI fileURIWithPath: path]];
	ret = [self fileExistsAtIRI: [OFIRI fileIRIWithPath: path]];

	objc_autoreleasePoolPop(pool);

	return ret;
}
#endif

- (bool)directoryExistsAtURI: (OFURI *)URI
- (bool)directoryExistsAtIRI: (OFIRI *)IRI
{
	OFURIHandler *URIHandler;
	OFIRIHandler *IRIHandler;

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

	if ((URIHandler = [OFURIHandler handlerForURI: URI]) == nil)
		@throw [OFUnsupportedProtocolException exceptionWithURI: URI];
	if ((IRIHandler = [OFIRIHandler handlerForIRI: IRI]) == nil)
		@throw [OFUnsupportedProtocolException exceptionWithIRI: IRI];

	return [URIHandler directoryExistsAtURI: URI];
	return [IRIHandler directoryExistsAtIRI: IRI];
}

#ifdef OF_HAVE_FILES
- (bool)directoryExistsAtPath: (OFString *)path
{
	void *pool = objc_autoreleasePoolPush();
	bool ret;

	ret = [self directoryExistsAtURI: [OFURI fileURIWithPath: path]];
	ret = [self directoryExistsAtIRI: [OFIRI fileIRIWithPath: path]];

	objc_autoreleasePoolPop(pool);

	return ret;
}
#endif

- (void)createDirectoryAtURI: (OFURI *)URI
- (void)createDirectoryAtIRI: (OFIRI *)IRI
{
	OFURIHandler *URIHandler;
	OFIRIHandler *IRIHandler;

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

	if ((URIHandler = [OFURIHandler handlerForURI: URI]) == nil)
		@throw [OFUnsupportedProtocolException exceptionWithURI: URI];
	if ((IRIHandler = [OFIRIHandler handlerForIRI: IRI]) == nil)
		@throw [OFUnsupportedProtocolException exceptionWithIRI: IRI];

	[URIHandler createDirectoryAtURI: URI];
	[IRIHandler createDirectoryAtIRI: IRI];
}

- (void)createDirectoryAtURI: (OFURI *)URI createParents: (bool)createParents
- (void)createDirectoryAtIRI: (OFIRI *)IRI createParents: (bool)createParents
{
	void *pool = objc_autoreleasePoolPush();
	OFMutableURI *mutableURI;
	OFMutableIRI *mutableIRI;
	OFArray OF_GENERIC(OFString *) *components;
	OFMutableArray OF_GENERIC(OFURI *) *componentURIs;
	size_t componentURIsCount;
	OFMutableArray OF_GENERIC(OFIRI *) *componentIRIs;
	size_t componentIRIsCount;
	ssize_t i;

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

	if (!createParents) {
		[self createDirectoryAtURI: URI];
		[self createDirectoryAtIRI: IRI];
		return;
	}

	/*
	 * Try blindly creating the directory first.
	 *
	 * The reason for this is that we might be sandboxed, so attempting to
	 * create any of the parent directories will fail, while creating the
	 * directory itself will work.
	 */
	if ([self directoryExistsAtURI: URI])
	if ([self directoryExistsAtIRI: IRI])
		return;

	@try {
		[self createDirectoryAtURI: URI];
		[self createDirectoryAtIRI: IRI];
		return;
	} @catch (OFCreateDirectoryFailedException *e) {
		/*
		 * If we didn't fail because any of the parents is missing,
		 * there is no point in trying to create the parents.
		 */
		if (e.errNo != ENOENT)
			@throw e;
	}

	/*
	 * Because we might be sandboxed (and for remote URIs don't even know
	 * anything at all), we generate the URI for every component. We then
	 * Because we might be sandboxed (and for remote IRIs don't even know
	 * anything at all), we generate the IRI for every component. We then
	 * iterate them in reverse order until we find the first existing
	 * directory, and then create subdirectories from there.
	 */
	mutableURI = [[URI mutableCopy] autorelease];
	mutableURI.percentEncodedPath = @"/";
	components = URI.pathComponents;
	componentURIs = [OFMutableArray arrayWithCapacity: components.count];
	mutableIRI = [[IRI mutableCopy] autorelease];
	mutableIRI.percentEncodedPath = @"/";
	components = IRI.pathComponents;
	componentIRIs = [OFMutableArray arrayWithCapacity: components.count];

	for (OFString *component in components) {
		[mutableURI appendPathComponent: component];
		[mutableIRI appendPathComponent: component];

		if (![mutableURI.percentEncodedPath isEqual: @"/"])
			[componentURIs addObject:
			    [[mutableURI copy] autorelease]];
		if (![mutableIRI.percentEncodedPath isEqual: @"/"])
			[componentIRIs addObject:
			    [[mutableIRI copy] autorelease]];
	}

	componentURIsCount = componentURIs.count;
	for (i = componentURIsCount - 1; i > 0; i--) {
		if ([self directoryExistsAtURI:
		    [componentURIs objectAtIndex: i]])
	componentIRIsCount = componentIRIs.count;
	for (i = componentIRIsCount - 1; i > 0; i--) {
		if ([self directoryExistsAtIRI:
		    [componentIRIs objectAtIndex: i]])
			break;
	}

	if (++i == (ssize_t)componentURIsCount) {
	if (++i == (ssize_t)componentIRIsCount) {
		/*
		 * The URI exists, even though before we made sure it did not.
		 * The IRI exists, even though before we made sure it did not.
		 * That means it was created in the meantime by something else,
		 * so we're done here.
		 */
		objc_autoreleasePoolPop(pool);
		return;
	}

	for (; i < (ssize_t)componentURIsCount; i++)
		[self createDirectoryAtURI: [componentURIs objectAtIndex: i]];
	for (; i < (ssize_t)componentIRIsCount; i++)
		[self createDirectoryAtIRI: [componentIRIs objectAtIndex: i]];

	objc_autoreleasePoolPop(pool);
}

#ifdef OF_HAVE_FILES
- (void)createDirectoryAtPath: (OFString *)path
{
	void *pool = objc_autoreleasePoolPush();

	[self createDirectoryAtURI: [OFURI fileURIWithPath: path]];
	[self createDirectoryAtIRI: [OFIRI fileIRIWithPath: path]];

	objc_autoreleasePoolPop(pool);
}

- (void)createDirectoryAtPath: (OFString *)path
		createParents: (bool)createParents
{
	void *pool = objc_autoreleasePoolPush();

	[self createDirectoryAtURI: [OFURI fileURIWithPath: path]
	[self createDirectoryAtIRI: [OFIRI fileIRIWithPath: path]
		     createParents: createParents];

	objc_autoreleasePoolPop(pool);
}
#endif

- (OFArray OF_GENERIC(OFURI *) *)contentsOfDirectoryAtURI: (OFURI *)URI
- (OFArray OF_GENERIC(OFIRI *) *)contentsOfDirectoryAtIRI: (OFIRI *)IRI
{
	OFURIHandler *URIHandler;
	OFIRIHandler *IRIHandler;

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

	if ((URIHandler = [OFURIHandler handlerForURI: URI]) == nil)
		@throw [OFUnsupportedProtocolException exceptionWithURI: URI];
	if ((IRIHandler = [OFIRIHandler handlerForIRI: IRI]) == nil)
		@throw [OFUnsupportedProtocolException exceptionWithIRI: IRI];

	return [URIHandler contentsOfDirectoryAtURI: URI];
	return [IRIHandler contentsOfDirectoryAtIRI: IRI];
}

#ifdef OF_HAVE_FILES
- (OFArray OF_GENERIC(OFString *) *)contentsOfDirectoryAtPath: (OFString *)path
{
	void *pool = objc_autoreleasePoolPush();
	OFArray OF_GENERIC(OFURI *) *URIs;
	OFArray OF_GENERIC(OFIRI *) *IRIs;
	OFMutableArray OF_GENERIC(OFString *) *ret;

	URIs = [self contentsOfDirectoryAtURI: [OFURI fileURIWithPath: path]];
	ret = [OFMutableArray arrayWithCapacity: URIs.count];
	IRIs = [self contentsOfDirectoryAtIRI: [OFIRI fileIRIWithPath: path]];
	ret = [OFMutableArray arrayWithCapacity: IRIs.count];

	for (OFURI *URI in URIs)
		[ret addObject: URI.lastPathComponent];
	for (OFIRI *IRI in IRIs)
		[ret addObject: IRI.lastPathComponent];

	[ret makeImmutable];
	[ret retain];
	ret = [ret retain];

	objc_autoreleasePoolPop(pool);

	return [ret autorelease];
}

- (OFArray OF_GENERIC(OFString *) *)subpathsOfDirectoryAtPath: (OFString *)path
478
479
480
481
482
483
484
485

486
487
488
489
490
491
492
499
500
501
502
503
504
505

506
507
508
509
510
511
512
513







-
+







		else
			[ret addObject: fullSubpath];

		objc_autoreleasePoolPop(pool2);
	}

	[ret makeImmutable];
	[ret retain];
	ret = [ret retain];

	objc_autoreleasePoolPop(pool);

	return [ret autorelease];
}

- (void)changeCurrentDirectoryPath: (OFString *)path
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

572
573
574
575
576
577
578
579
580

581
582

583
584

585
586
587

588
589
590


591
592
593
594

595
596
597
598


599
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
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
562
563
564
565
566
567
568

569
570
571
572

573
574
575
576
577
578
579
580
581


582
583
584
585
586
587
588

589
590
591

592
593
594
595
596
597
598
599
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
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
676
677
678
679
680
681
682

683
684


685
686
687
688
689
690
691
692
693







-
+



-
+








-
-
+
+





-
+


-
+








-
+

-
+

-
+


-
+

-
-
+
+



-
+


-
-
+
+






-
+


-
+













-
+




-
+









-
-
+
+





-
+

-
-
+
+


-
+











-
+

-
-
+
+







	if (status != 0)
		@throw [OFChangeCurrentDirectoryFailedException
		    exceptionWithPath: path
				errNo: errno];
# endif
}

- (void)changeCurrentDirectoryURI: (OFURI *)URI
- (void)changeCurrentDirectoryIRI: (OFIRI *)IRI
{
	void *pool = objc_autoreleasePoolPush();

	[self changeCurrentDirectoryPath: URI.fileSystemRepresentation];
	[self changeCurrentDirectoryPath: IRI.fileSystemRepresentation];

	objc_autoreleasePoolPop(pool);
}

- (void)copyItemAtPath: (OFString *)source toPath: (OFString *)destination
{
	void *pool = objc_autoreleasePoolPush();

	[self copyItemAtURI: [OFURI fileURIWithPath: source]
		      toURI: [OFURI fileURIWithPath: destination]];
	[self copyItemAtIRI: [OFIRI fileIRIWithPath: source]
		      toIRI: [OFIRI fileIRIWithPath: destination]];

	objc_autoreleasePoolPop(pool);
}
#endif

- (void)copyItemAtURI: (OFURI *)source toURI: (OFURI *)destination
- (void)copyItemAtIRI: (OFIRI *)source toIRI: (OFIRI *)destination
{
	void *pool;
	OFURIHandler *URIHandler;
	OFIRIHandler *IRIHandler;
	OFFileAttributes attributes;
	OFFileAttributeType type;

	if (source == nil || destination == nil)
		@throw [OFInvalidArgumentException exception];

	pool = objc_autoreleasePoolPush();

	if ((URIHandler = [OFURIHandler handlerForURI: source]) == nil)
	if ((IRIHandler = [OFIRIHandler handlerForIRI: source]) == nil)
		@throw [OFUnsupportedProtocolException
		    exceptionWithURI: source];
		    exceptionWithIRI: source];

	if ([URIHandler copyItemAtURI: source toURI: destination])
	if ([IRIHandler copyItemAtIRI: source toIRI: destination])
		return;

	if ([self fileExistsAtURI: destination])
	if ([self fileExistsAtIRI: destination])
		@throw [OFCopyItemFailedException
		    exceptionWithSourceURI: source
			    destinationURI: destination
		    exceptionWithSourceIRI: source
			    destinationIRI: destination
				     errNo: EEXIST];

	@try {
		attributes = [self attributesOfItemAtURI: source];
		attributes = [self attributesOfItemAtIRI: source];
	} @catch (OFGetItemAttributesFailedException *e) {
		@throw [OFCopyItemFailedException
		    exceptionWithSourceURI: source
			    destinationURI: destination
		    exceptionWithSourceIRI: source
			    destinationIRI: destination
				     errNo: e.errNo];
	}

	type = attributes.fileType;

	if ([type isEqual: OFFileTypeDirectory]) {
		OFArray OF_GENERIC(OFURI *) *contents;
		OFArray OF_GENERIC(OFIRI *) *contents;

		@try {
			[self createDirectoryAtURI: destination];
			[self createDirectoryAtIRI: destination];

			@try {
				OFFileAttributeKey key = OFFilePOSIXPermissions;
				OFNumber *permissions =
				    [attributes objectForKey: key];
				OFFileAttributes destinationAttributes;

				if (permissions != nil) {
					destinationAttributes = [OFDictionary
					    dictionaryWithObject: permissions
							  forKey: key];
					[self
					    setAttributes: destinationAttributes
					      ofItemAtURI: destination];
					      ofItemAtIRI: destination];
				}
			} @catch (OFNotImplementedException *e) {
			}

			contents = [self contentsOfDirectoryAtURI: source];
			contents = [self contentsOfDirectoryAtIRI: source];
		} @catch (id e) {
			/*
			 * Only convert exceptions to OFCopyItemFailedException
			 * that have an errNo property. This covers all I/O
			 * related exceptions from the operations used to copy
			 * an item, all others should be left as is.
			 */
			if ([e respondsToSelector: @selector(errNo)])
				@throw [OFCopyItemFailedException
				    exceptionWithSourceURI: source
					    destinationURI: destination
				    exceptionWithSourceIRI: source
					    destinationIRI: destination
						     errNo: [e errNo]];

			@throw e;
		}

		for (OFURI *item in contents) {
		for (OFIRI *item in contents) {
			void *pool2 = objc_autoreleasePoolPush();
			OFURI *destinationURI = [destination
			    URIByAppendingPathComponent:
			OFIRI *destinationIRI = [destination
			    IRIByAppendingPathComponent:
			    item.lastPathComponent];

			[self copyItemAtURI: item toURI: destinationURI];
			[self copyItemAtIRI: item toIRI: destinationIRI];

			objc_autoreleasePoolPop(pool2);
		}
	} else if ([type isEqual: OFFileTypeRegular]) {
		size_t pageSize = [OFSystemInfo pageSize];
		OFStream *sourceStream = nil;
		OFStream *destinationStream = nil;
		char *buffer;

		buffer = OFAllocMemory(1, pageSize);
		@try {
			sourceStream = [OFURIHandler openItemAtURI: source
			sourceStream = [OFIRIHandler openItemAtIRI: source
							      mode: @"r"];
			destinationStream = [OFURIHandler
			    openItemAtURI: destination
			destinationStream = [OFIRIHandler
			    openItemAtIRI: destination
				     mode: @"w"];

			while (!sourceStream.atEndOfStream) {
				size_t length;

				length = [sourceStream
				    readIntoBuffer: buffer
683
684
685
686
687
688
689
690

691
692
693
694
695
696
697
698
699
700
701
702
703
704


705
706
707
708
709
710
711
712
713
714
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
746
747
748
749


750
751
752
753
754

755
756
757

758
759
760
761
762
763
764

765
766

767
768
769

770
771
772
773
774
775
776

777
778
779


780
781
782
783

784
785

786
787
788
789


790
791
792
793
794

795
796
797
798


799
800
801
802
803
804
805

806
807

808
809

810
811
812
813


814
815

816
817
818
819
820
821
822

823
824
825
826
827

828
829
830

831
832
833
834
835
836
837
838

839
840

841
842

843
844

845
846
847
848
849
850
851
852
853
854


855
856
857
858
859

860
861
862
863

864
865

866
867
868

869
870
871


872
873

874
875
876
877
878
879
880
881
882
883

884
885
886
887























































































888
889
890
891
892
893
894
704
705
706
707
708
709
710

711
712
713
714
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
746
747
748
749


750
751
752
753
754
755
756
757


758
759
760
761
762
763
764
765
766
767
768


769
770
771
772
773
774

775
776
777

778
779
780
781
782
783
784

785
786

787
788
789

790
791
792
793
794
795
796

797
798


799
800
801
802
803

804
805

806
807
808


809
810
811
812
813
814

815
816
817


818
819
820
821
822
823
824
825

826
827

828
829

830
831
832


833
834
835

836
837
838
839
840
841
842

843
844
845
846
847

848
849
850

851
852
853
854
855
856
857
858

859
860

861
862

863
864

865
866
867
868
869
870
871
872
873


874
875
876
877
878
879

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
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
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002







-
+












-
-
+
+













-
+










-
-
+
+






-
-
+
+









-
-
+
+




-
+


-
+






-
+

-
+


-
+






-
+

-
-
+
+



-
+

-
+


-
-
+
+




-
+


-
-
+
+






-
+

-
+

-
+


-
-
+
+

-
+






-
+




-
+


-
+







-
+

-
+

-
+

-
+








-
-
+
+




-
+



-
+

-
+


-
+

-
-
+
+

-
+









-
+




+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+








				if (permissions != nil) {
					destinationAttributes = [OFDictionary
					    dictionaryWithObject: permissions
							  forKey: key];
					[self
					    setAttributes: destinationAttributes
					      ofItemAtURI: destination];
					      ofItemAtIRI: destination];
				}
			} @catch (OFNotImplementedException *e) {
			}
		} @catch (id e) {
			/*
			 * Only convert exceptions to OFCopyItemFailedException
			 * that have an errNo property. This covers all I/O
			 * related exceptions from the operations used to copy
			 * an item, all others should be left as is.
			 */
			if ([e respondsToSelector: @selector(errNo)])
				@throw [OFCopyItemFailedException
				    exceptionWithSourceURI: source
					    destinationURI: destination
				    exceptionWithSourceIRI: source
					    destinationIRI: destination
						     errNo: [e errNo]];

			@throw e;
		} @finally {
			[sourceStream close];
			[destinationStream close];
			OFFreeMemory(buffer);
		}
	} else if ([type isEqual: OFFileTypeSymbolicLink]) {
		@try {
			OFString *linkDestination =
			    attributes.fileSymbolicLinkDestination;

			[self createSymbolicLinkAtURI: destination
			[self createSymbolicLinkAtIRI: destination
				  withDestinationPath: linkDestination];
		} @catch (id e) {
			/*
			 * Only convert exceptions to OFCopyItemFailedException
			 * that have an errNo property. This covers all I/O
			 * related exceptions from the operations used to copy
			 * an item, all others should be left as is.
			 */
			if ([e respondsToSelector: @selector(errNo)])
				@throw [OFCopyItemFailedException
				    exceptionWithSourceURI: source
					    destinationURI: destination
				    exceptionWithSourceIRI: source
					    destinationIRI: destination
						     errNo: [e errNo]];

			@throw e;
		}
	} else
		@throw [OFCopyItemFailedException
		    exceptionWithSourceURI: source
			    destinationURI: destination
		    exceptionWithSourceIRI: source
			    destinationIRI: destination
				     errNo: EINVAL];

	objc_autoreleasePoolPop(pool);
}

#ifdef OF_HAVE_FILES
- (void)moveItemAtPath: (OFString *)source toPath: (OFString *)destination
{
	void *pool = objc_autoreleasePoolPush();
	[self moveItemAtURI: [OFURI fileURIWithPath: source]
		      toURI: [OFURI fileURIWithPath: destination]];
	[self moveItemAtIRI: [OFIRI fileIRIWithPath: source]
		      toIRI: [OFIRI fileIRIWithPath: destination]];
	objc_autoreleasePoolPop(pool);
}
#endif

- (void)moveItemAtURI: (OFURI *)source toURI: (OFURI *)destination
- (void)moveItemAtIRI: (OFIRI *)source toIRI: (OFIRI *)destination
{
	void *pool;
	OFURIHandler *URIHandler;
	OFIRIHandler *IRIHandler;

	if (source == nil || destination == nil)
		@throw [OFInvalidArgumentException exception];

	pool = objc_autoreleasePoolPush();

	if ((URIHandler = [OFURIHandler handlerForURI: source]) == nil)
	if ((IRIHandler = [OFIRIHandler handlerForIRI: source]) == nil)
		@throw [OFUnsupportedProtocolException
		    exceptionWithURI: source];
		    exceptionWithIRI: source];

	@try {
		if ([URIHandler moveItemAtURI: source toURI: destination])
		if ([IRIHandler moveItemAtIRI: source toIRI: destination])
			return;
	} @catch (OFMoveItemFailedException *e) {
		if (e.errNo != EXDEV)
			@throw e;
	}

	if ([self fileExistsAtURI: destination])
	if ([self fileExistsAtIRI: destination])
		@throw [OFMoveItemFailedException
		    exceptionWithSourceURI: source
			    destinationURI: destination
		    exceptionWithSourceIRI: source
			    destinationIRI: destination
				     errNo: EEXIST];

	@try {
		[self copyItemAtURI: source toURI: destination];
		[self copyItemAtIRI: source toIRI: destination];
	} @catch (OFCopyItemFailedException *e) {
		[self removeItemAtURI: destination];
		[self removeItemAtIRI: destination];

		@throw [OFMoveItemFailedException
		    exceptionWithSourceURI: source
			    destinationURI: destination
		    exceptionWithSourceIRI: source
			    destinationIRI: destination
				     errNo: e.errNo];
	}

	@try {
		[self removeItemAtURI: source];
		[self removeItemAtIRI: source];
	} @catch (OFRemoveItemFailedException *e) {
		@throw [OFMoveItemFailedException
		    exceptionWithSourceURI: source
			    destinationURI: destination
		    exceptionWithSourceIRI: source
			    destinationIRI: destination
				     errNo: e.errNo];
	}

	objc_autoreleasePoolPop(pool);
}

- (void)removeItemAtURI: (OFURI *)URI
- (void)removeItemAtIRI: (OFIRI *)IRI
{
	OFURIHandler *URIHandler;
	OFIRIHandler *IRIHandler;

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

	if ((URIHandler = [OFURIHandler handlerForURI: URI]) == nil)
		@throw [OFUnsupportedProtocolException exceptionWithURI: URI];
	if ((IRIHandler = [OFIRIHandler handlerForIRI: IRI]) == nil)
		@throw [OFUnsupportedProtocolException exceptionWithIRI: IRI];

	[URIHandler removeItemAtURI: URI];
	[IRIHandler removeItemAtIRI: IRI];
}

#ifdef OF_HAVE_FILES
- (void)removeItemAtPath: (OFString *)path
{
	void *pool = objc_autoreleasePoolPush();
	[self removeItemAtURI: [OFURI fileURIWithPath: path]];
	[self removeItemAtIRI: [OFIRI fileIRIWithPath: path]];
	objc_autoreleasePoolPop(pool);
}
#endif

- (void)linkItemAtURI: (OFURI *)source toURI: (OFURI *)destination
- (void)linkItemAtIRI: (OFIRI *)source toIRI: (OFIRI *)destination
{
	void *pool = objc_autoreleasePoolPush();
	OFURIHandler *URIHandler;
	OFIRIHandler *IRIHandler;

	if (source == nil || destination == nil)
		@throw [OFInvalidArgumentException exception];

	if (![destination.scheme isEqual: source.scheme])
		@throw [OFInvalidArgumentException exception];

	URIHandler = [OFURIHandler handlerForURI: source];
	IRIHandler = [OFIRIHandler handlerForIRI: source];

	if (URIHandler == nil)
	if (IRIHandler == nil)
		@throw [OFUnsupportedProtocolException
		    exceptionWithURI: source];
		    exceptionWithIRI: source];

	[URIHandler linkItemAtURI: source toURI: destination];
	[IRIHandler linkItemAtIRI: source toIRI: destination];

	objc_autoreleasePoolPop(pool);
}

#ifdef OF_FILE_MANAGER_SUPPORTS_LINKS
- (void)linkItemAtPath: (OFString *)source toPath: (OFString *)destination
{
	void *pool = objc_autoreleasePoolPush();
	[self linkItemAtURI: [OFURI fileURIWithPath: source]
		      toURI: [OFURI fileURIWithPath: destination]];
	[self linkItemAtIRI: [OFIRI fileIRIWithPath: source]
		      toIRI: [OFIRI fileIRIWithPath: destination]];
	objc_autoreleasePoolPop(pool);
}
#endif

- (void)createSymbolicLinkAtURI: (OFURI *)URI
- (void)createSymbolicLinkAtIRI: (OFIRI *)IRI
	    withDestinationPath: (OFString *)target
{
	void *pool = objc_autoreleasePoolPush();
	OFURIHandler *URIHandler;
	OFIRIHandler *IRIHandler;

	if (URI == nil || target == nil)
	if (IRI == nil || target == nil)
		@throw [OFInvalidArgumentException exception];

	URIHandler = [OFURIHandler handlerForURI: URI];
	IRIHandler = [OFIRIHandler handlerForIRI: IRI];

	if (URIHandler == nil)
		@throw [OFUnsupportedProtocolException exceptionWithURI: URI];
	if (IRIHandler == nil)
		@throw [OFUnsupportedProtocolException exceptionWithIRI: IRI];

	[URIHandler createSymbolicLinkAtURI: URI withDestinationPath: target];
	[IRIHandler createSymbolicLinkAtIRI: IRI withDestinationPath: target];

	objc_autoreleasePoolPop(pool);
}

#ifdef OF_FILE_MANAGER_SUPPORTS_SYMLINKS
- (void)createSymbolicLinkAtPath: (OFString *)path
	     withDestinationPath: (OFString *)target
{
	void *pool = objc_autoreleasePoolPush();
	[self createSymbolicLinkAtURI: [OFURI fileURIWithPath: path]
	[self createSymbolicLinkAtIRI: [OFIRI fileIRIWithPath: path]
		  withDestinationPath: target];
	objc_autoreleasePoolPop(pool);
}
#endif

- (OFData *)extendedAttributeDataForName: (OFString *)name
			     ofItemAtIRI: (OFIRI *)IRI
{
	OFIRIHandler *IRIHandler;

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

	if ((IRIHandler = [OFIRIHandler handlerForIRI: IRI]) == nil)
		@throw [OFUnsupportedProtocolException exceptionWithIRI: IRI];

	return [IRIHandler extendedAttributeDataForName: name ofItemAtIRI: IRI];
}

#ifdef OF_FILE_MANAGER_SUPPORTS_EXTENDED_ATTRIBUTES
- (OFData *)extendedAttributeDataForName: (OFString *)name
			    ofItemAtPath: (OFString *)path
{
	void *pool = objc_autoreleasePoolPush();
	OFData *ret;

	ret = [self
	    extendedAttributeDataForName: name
			     ofItemAtIRI: [OFIRI fileIRIWithPath: path]];
	ret = [ret retain];

	objc_autoreleasePoolPop(pool);

	return [ret autorelease];
}
#endif

- (void)setExtendedAttributeData: (OFData *)data
			 forName: (OFString *)name
		     ofItemAtIRI: (OFIRI *)IRI
{
	OFIRIHandler *IRIHandler;

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

	if ((IRIHandler = [OFIRIHandler handlerForIRI: IRI]) == nil)
		@throw [OFUnsupportedProtocolException exceptionWithIRI: IRI];

	[IRIHandler setExtendedAttributeData: data
				     forName: name
				 ofItemAtIRI: IRI];
}

#ifdef OF_FILE_MANAGER_SUPPORTS_EXTENDED_ATTRIBUTES
- (void)setExtendedAttributeData: (OFData *)data
			 forName: (OFString *)name
		    ofItemAtPath: (OFString *)path
{
	void *pool = objc_autoreleasePoolPush();
	[self setExtendedAttributeData: data
			       forName: name
			   ofItemAtIRI: [OFIRI fileIRIWithPath: path]];
	objc_autoreleasePoolPop(pool);
}
#endif

- (void)removeExtendedAttributeForName: (OFString *)name
			   ofItemAtIRI: (OFIRI *)IRI
{
	OFIRIHandler *IRIHandler;

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

	if ((IRIHandler = [OFIRIHandler handlerForIRI: IRI]) == nil)
		@throw [OFUnsupportedProtocolException exceptionWithIRI: IRI];

	[IRIHandler removeExtendedAttributeForName: name ofItemAtIRI: IRI];
}

#ifdef OF_FILE_MANAGER_SUPPORTS_EXTENDED_ATTRIBUTES
- (void)removeExtendedAttributeForName: (OFString *)name
			  ofItemAtPath: (OFString *)path
{
	void *pool = objc_autoreleasePoolPush();
	[self removeExtendedAttributeForName: name
				 ofItemAtIRI: [OFIRI fileIRIWithPath: path]];
	objc_autoreleasePoolPop(pool);
}
#endif
@end

@implementation OFDefaultFileManager
- (instancetype)autorelease
{
	return self;
}
968
969
970
971
972
973
974





975
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088







+
+
+
+
+

	return attributeForKeyOrException(self, OFFileCreationDate);
}

- (OFString *)fileSymbolicLinkDestination
{
	return attributeForKeyOrException(self, OFFileSymbolicLinkDestination);
}

- (OFArray OF_GENERIC(OFString *) *)fileExtendedAttributesNames
{
	return attributeForKeyOrException(self, OFFileExtendedAttributesNames);
}
@end

Modified src/OFFileManagerConstants.inc from [7a3eb9bf4f] to [9aaf7f17d6].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
24
25
26
27
28
29
30


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







+
+










    @"OFFileGroupOwnerAccountName";
const OFFileAttributeKey OFFileLastAccessDate = @"OFFileLastAccessDate";
const OFFileAttributeKey OFFileModificationDate = @"OFFileModificationDate";
const OFFileAttributeKey OFFileStatusChangeDate = @"OFFileStatusChangeDate";
const OFFileAttributeKey OFFileCreationDate = @"OFFileCreationDate";
const OFFileAttributeKey OFFileSymbolicLinkDestination =
    @"OFFileSymbolicLinkDestination";
const OFFileAttributeKey OFFileExtendedAttributesNames =
    @"OFFileExtendedAttributesNames";

const OFFileAttributeType OFFileTypeRegular = @"OFFileTypeRegular";
const OFFileAttributeType OFFileTypeDirectory = @"OFFileTypeDirectory";
const OFFileAttributeType OFFileTypeSymbolicLink = @"OFFileTypeSymbolicLink";
const OFFileAttributeType OFFileTypeFIFO = @"OFFileTypeFIFO";
const OFFileAttributeType OFFileTypeCharacterSpecial =
    @"OFFileTypeCharacterSpecial";
const OFFileAttributeType OFFileTypeBlockSpecial = @"OFFileTypeBlockSpecial";
const OFFileAttributeType OFFileTypeSocket = @"OFFileTypeSocket";
const OFFileAttributeType OFFileTypeUnknown = @"OFFileTypeUnknown";

Modified src/OFGZIPStream.h from [40a91bbae5] to [0581f33830].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFGZIPStream.m from [947da42ac6] to [1ebfe8e246].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFHMAC.h from [2d8e8879fb] to [2091f0e079].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFHMAC.m from [2ceebc7fc2] to [8e66f29fa5].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFHTTPClient.h from [d5da950339] to [67bbe697a1].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
21
22
23
24
25
26
27

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

32
33
34
35
36
37
38







+



-








OF_ASSUME_NONNULL_BEGIN

@class OFDictionary OF_GENERIC(KeyType, ObjectType);
@class OFHTTPClient;
@class OFHTTPRequest;
@class OFHTTPResponse;
@class OFIRI;
@class OFStream;
@class OFTCPSocket;
@class OFTLSStream;
@class OFURI;

/**
 * @protocol OFHTTPClientDelegate OFHTTPClient.h ObjFW/OFHTTPClient.h
 *
 * @brief A delegate for OFHTTPClient.
 */
@protocol OFHTTPClientDelegate <OFObject>
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
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







-
+




-
+





-
+



















-
+







 * to detect a redirect.
 *
 * This callback will only be called if the OFHTTPClient will follow a
 * redirect. If the maximum number of redirects has been reached already, this
 * callback will not be called.
 *
 * @param client The OFHTTPClient which wants to follow a redirect
 * @param URI The URI to which it will follow a redirect
 * @param IRI The IRI to which it will follow a redirect
 * @param statusCode The status code for the redirection
 * @param request The request for which the OFHTTPClient wants to redirect.
 *		  You are allowed to change the request's headers from this
 *		  callback and they will be used when following the redirect
 *		  (e.g. to set the cookies for the new URI), however, keep in
 *		  (e.g. to set the cookies for the new IRI), however, keep in
 *		  mind that this will change the request you originally passed.
 * @param response The response indicating the redirect
 * @return A boolean whether the OFHTTPClient should follow the redirect
 */
-	       (bool)client: (OFHTTPClient *)client
  shouldFollowRedirectToURI: (OFURI *)URI
  shouldFollowRedirectToIRI: (OFIRI *)IRI
		 statusCode: (short)statusCode
		    request: (OFHTTPRequest *)request
		   response: (OFHTTPResponse *)response;
@end

/**
 * @class OFHTTPClient OFHTTPClient.h ObjFW/OFHTTPClient.h
 *
 * @brief A class for performing HTTP requests.
 */
OF_SUBCLASSING_RESTRICTED
@interface OFHTTPClient: OFObject
{
#ifdef OF_HTTP_CLIENT_M
@public
#endif
	OFObject <OFHTTPClientDelegate> *_Nullable _delegate;
	bool _allowsInsecureRedirects, _inProgress;
	OFStream *_Nullable _stream;
	OFURI *_Nullable _lastURI;
	OFIRI *_Nullable _lastIRI;
	bool _lastWasHEAD;
	OFHTTPResponse *_Nullable _lastResponse;
}

/**
 * @brief The delegate of the HTTP request.
 */
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
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







-
+



















-
+








-
+










-
+











 *
 * @param request The request to perform
 * @return The OFHTTPResponse for the request
 * @throw OFHTTPRequestFailedException The HTTP request failed
 * @throw OFInvalidServerResponseException The server sent an invalid response
 * @throw OFUnsupportedVersionException The server responded in an unsupported
 *					version
 * @throw OFAlreadyConnectedException The client is already performing a request
 * @throw OFAlreadyOpenException The client is already performing a request
 */
- (OFHTTPResponse *)performRequest: (OFHTTPRequest *)request;

/**
 * @brief Synchronously performs the specified HTTP request.
 *
 * @note You must not change the delegate while a synchronous request is
 *	 running! If you want to change the delegate during the request,
 *	 perform an asynchronous request instead!
 *
 * @param request The request to perform
 * @param redirects The maximum number of redirects after which no further
 *		    attempt is done to follow the redirect, but instead the
 *		    redirect is treated as an OFHTTPResponse
 * @return The OFHTTPResponse for the request
 * @throw OFHTTPRequestFailedException The HTTP request failed
 * @throw OFInvalidServerResponseException The server sent an invalid response
 * @throw OFUnsupportedVersionException The server responded in an unsupported
 *					version
 * @throw OFAlreadyConnectedException The client is already performing a request
 * @throw OFAlreadyOpenException The client is already performing a request
 */
- (OFHTTPResponse *)performRequest: (OFHTTPRequest *)request
			 redirects: (unsigned int)redirects;

/**
 * @brief Asynchronously performs the specified HTTP request.
 *
 * @param request The request to perform
 * @throw OFAlreadyConnectedException The client is already performing a request
 * @throw OFAlreadyOpenException The client is already performing a request
 */
- (void)asyncPerformRequest: (OFHTTPRequest *)request;

/**
 * @brief Asynchronously performs the specified HTTP request.
 *
 * @param request The request to perform
 * @param redirects The maximum number of redirects after which no further
 *		    attempt is done to follow the redirect, but instead the
 *		    redirect is treated as an OFHTTPResponse
 * @throw OFAlreadyConnectedException The client is already performing a request
 * @throw OFAlreadyOpenException The client is already performing a request
 */
- (void)asyncPerformRequest: (OFHTTPRequest *)request
		  redirects: (unsigned int)redirects;

/**
 * @brief Closes connections that are still open due to keep-alive.
 */
- (void)close;
@end

OF_ASSUME_NONNULL_END

Modified src/OFHTTPClient.m from [e887f99bf5] to [feb32daab7].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
21
22
23
24
25
26
27

28
29
30
31
32
33
34
35
36

37
38
39
40
41
42
43
21
22
23
24
25
26
27
28
29
30
31
32
33
34

35

36
37
38
39
40
41
42
43







+






-

-
+







#include <string.h>

#import "OFHTTPClient.h"
#import "OFData.h"
#import "OFDictionary.h"
#import "OFHTTPRequest.h"
#import "OFHTTPResponse.h"
#import "OFIRI.h"
#import "OFKernelEventObserver.h"
#import "OFNumber.h"
#import "OFRunLoop.h"
#import "OFString.h"
#import "OFTCPSocket.h"
#import "OFTLSStream.h"
#import "OFURI.h"

#import "OFAlreadyConnectedException.h"
#import "OFAlreadyOpenException.h"
#import "OFHTTPRequestFailedException.h"
#import "OFInvalidArgumentException.h"
#import "OFInvalidEncodingException.h"
#import "OFInvalidFormatException.h"
#import "OFInvalidServerResponseException.h"
#import "OFNotImplementedException.h"
#import "OFNotOpenException.h"
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
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







-
+

-
+






-
-
+
+






-
+

-
+











-
+



-
+



-
+







@end

static OFString *
constructRequestString(OFHTTPRequest *request)
{
	void *pool = objc_autoreleasePoolPush();
	OFHTTPRequestMethod method = request.method;
	OFURI *URI = request.URI;
	OFIRI *IRI = request.IRI.IRIByAddingPercentEncodingForUnicodeCharacters;
	OFString *path;
	OFString *user = URI.user, *password = URI.password;
	OFString *user = IRI.user, *password = IRI.password;
	OFMutableString *requestString;
	OFMutableDictionary OF_GENERIC(OFString *, OFString *) *headers;
	bool hasContentLength, chunked;
	OFEnumerator OF_GENERIC(OFString *) *keyEnumerator, *objectEnumerator;
	OFString *key, *object;

	if (URI.path.length > 0)
		path = URI.percentEncodedPath;
	if (IRI.path.length > 0)
		path = IRI.percentEncodedPath;
	else
		path = @"/";

	requestString = [OFMutableString stringWithFormat:
	    @"%s %@", OFHTTPRequestMethodName(method), path];

	if (URI.query != nil) {
	if (IRI.query != nil) {
		[requestString appendString: @"?"];
		[requestString appendString: URI.percentEncodedQuery];
		[requestString appendString: IRI.percentEncodedQuery];
	}

	[requestString appendString: @" HTTP/"];
	[requestString appendString: request.protocolVersionString];
	[requestString appendString: @"\r\n"];

	headers = [[request.headers mutableCopy] autorelease];
	if (headers == nil)
		headers = [OFMutableDictionary dictionary];

	if ([headers objectForKey: @"Host"] == nil) {
		OFNumber *port = URI.port;
		OFNumber *port = IRI.port;

		if (port != nil) {
			OFString *host = [OFString stringWithFormat:
			    @"%@:%@", URI.percentEncodedHost, port];
			    @"%@:%@", IRI.percentEncodedHost, port];

			[headers setObject: host forKey: @"Host"];
		} else
			[headers setObject: URI.percentEncodedHost
			[headers setObject: IRI.percentEncodedHost
				    forKey: @"Host"];
	}

	if ((user.length > 0 || password.length > 0) &&
	    [headers objectForKey: @"Authorization"] == nil) {
		OFMutableData *authorizationData = [OFMutableData data];
		OFString *authorization;
295
296
297
298
299
300
301
302

303
304
305
306
307
308
309
295
296
297
298
299
300
301

302
303
304
305
306
307
308
309







-
+







		 didPerformRequest: _request
			  response: nil
			 exception: exception];
}

- (void)createResponseWithStreamOrThrow: (OFStream *)stream
{
	OFURI *URI = _request.URI;
	OFIRI *IRI = _request.IRI;
	OFHTTPClientResponse *response;
	OFString *connectionHeader;
	bool keepAlive;
	OFString *location;
	id exception;

	response = [[[OFHTTPClientResponse alloc] initWithStream: stream]
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

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
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
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







-
+









-
-
+
+

-
-
+
+

-
+

-
+




-
+

-
+




-
+


-
+














-
+







			keepAlive = false;
	}

	if (keepAlive) {
		response.of_keepAlive = true;

		_client->_stream = [stream retain];
		_client->_lastURI = [URI copy];
		_client->_lastIRI = [IRI copy];
		_client->_lastWasHEAD =
		    (_request.method == OFHTTPRequestMethodHead);
		_client->_lastResponse = [response retain];
	}

	if (_redirects > 0 && (_status == 301 || _status == 302 ||
	    _status == 303 || _status == 307) &&
	    (location = [_serverHeaders objectForKey: @"Location"]) != nil) {
		bool follow = true;
		OFURI *newURI;
		OFString *newURIScheme;
		OFIRI *newIRI;
		OFString *newIRIScheme;

		newURI = [OFURI URIWithString: location relativeToURI: URI];
		newURIScheme = newURI.scheme;
		newIRI = [OFIRI IRIWithString: location relativeToIRI: IRI];
		newIRIScheme = newIRI.scheme;

		if ([newURIScheme caseInsensitiveCompare: @"http"] !=
		if ([newIRIScheme caseInsensitiveCompare: @"http"] !=
		    OFOrderedSame &&
		    [newURIScheme caseInsensitiveCompare: @"https"] !=
		    [newIRIScheme caseInsensitiveCompare: @"https"] !=
		    OFOrderedSame)
			follow = false;

		if (!_client->_allowsInsecureRedirects &&
		    [URI.scheme caseInsensitiveCompare: @"https"] ==
		    [IRI.scheme caseInsensitiveCompare: @"https"] ==
		    OFOrderedSame &&
		    [newURIScheme caseInsensitiveCompare: @"http"] ==
		    [newIRIScheme caseInsensitiveCompare: @"http"] ==
		    OFOrderedSame)
			follow = false;

		if (follow && [_client->_delegate respondsToSelector:
		    @selector(client:shouldFollowRedirectToURI:statusCode:
		    @selector(client:shouldFollowRedirectToIRI:statusCode:
		    request:response:)])
			follow = [_client->_delegate client: _client
				  shouldFollowRedirectToURI: newURI
				  shouldFollowRedirectToIRI: newIRI
						 statusCode: _status
						    request: _request
						   response: response];
		else if (follow)
			follow = defaultShouldFollow(_request.method, _status);

		if (follow) {
			OFDictionary OF_GENERIC(OFString *, OFString *)
			    *headers = _request.headers;
			OFHTTPRequest *newRequest =
			    [[_request copy] autorelease];
			OFMutableDictionary *newHeaders =
			    [[headers mutableCopy] autorelease];

			if (![newURI.host isEqual: URI.host])
			if (![newIRI.host isEqual: IRI.host])
				[newHeaders removeObjectForKey: @"Host"];

			/*
			 * 303 means the request should be converted to a GET
			 * request before redirection. This also means stripping
			 * the entity of the request.
			 */
400
401
402
403
404
405
406
407

408
409
410
411
412
413
414
400
401
402
403
404
405
406

407
408
409
410
411
412
413
414







-
+







					    [key hasPrefix: @"Transfer-"])
						[newHeaders
						    removeObjectForKey: key];

				newRequest.method = OFHTTPRequestMethodGet;
			}

			newRequest.URI = newURI;
			newRequest.IRI = newIRI;
			newRequest.headers = newHeaders;

			_client->_inProgress = false;

			[_client asyncPerformRequest: newRequest
					   redirects: _redirects - 1];
			return;
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
676
677
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
676
677
678







-
+







-
+










-
+
+








	if ([_client->_delegate respondsToSelector:
	    @selector(client:didCreateTCPSocket:request:)])
		[_client->_delegate client: _client
			didCreateTCPSocket: sock
				   request: _request];

	if ([_request.URI.scheme caseInsensitiveCompare: @"https"] ==
	if ([_request.IRI.scheme caseInsensitiveCompare: @"https"] ==
	    OFOrderedSame) {
		OFTLSStream *stream;
		@try {
			stream = [OFTLSStream streamWithStream: sock];
		} @catch (OFNotImplementedException *e) {
			[self raiseException:
			    [OFUnsupportedProtocolException
			    exceptionWithURI: _request.URI]];
			    exceptionWithIRI: _request.IRI]];
			return;
		}

		if ([_client->_delegate respondsToSelector:
		    @selector(client:didCreateTLSStream:request:)])
			[_client->_delegate client: _client
				didCreateTLSStream: stream
					   request: _request];

		stream.delegate = self;
		[stream asyncPerformClientHandshakeWithHost: _request.URI.host];
		[stream asyncPerformClientHandshakeWithHost: _request.IRI
		    .IRIByAddingPercentEncodingForUnicodeCharacters.host];
	} else {
		sock.delegate = self;
		[self performSelector: @selector(handleStream:)
			   withObject: sock
			   afterDelay: 0];
	}
}
688
689
690
691
692
693
694
695

696
697
698
699
700
701
702
703




704
705
706
707
708
709
710
711
712
713
714


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
746
747
748



749
750
751

752
753
754
755
756
757
758
689
690
691
692
693
694
695

696
697
698
699
700




701
702
703
704
705
706
707
708
709
710
711
712
713


714
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
746
747



748
749
750
751
752

753
754
755
756
757
758
759
760







-
+




-
-
-
-
+
+
+
+









-
-
+
+
















-
+
+


-
+





-
+





-
-
-
+
+
+


-
+







	[self performSelector: @selector(handleStream:)
		   withObject: stream
		   afterDelay: 0];
}

- (void)start
{
	OFURI *URI = _request.URI;
	OFIRI *IRI = _request.IRI;
	OFStream *stream;

	/* Can we reuse the last socket? */
	if (_client->_stream != nil && !_client->_stream.atEndOfStream &&
	    [_client->_lastURI.scheme isEqual: URI.scheme] &&
	    [_client->_lastURI.host isEqual: URI.host] &&
	    (_client->_lastURI.port == URI.port ||
	    [_client->_lastURI.port isEqual: URI.port]) &&
	    [_client->_lastIRI.scheme isEqual: IRI.scheme] &&
	    [_client->_lastIRI.host isEqual: IRI.host] &&
	    (_client->_lastIRI.port == IRI.port ||
	    [_client->_lastIRI.port isEqual: IRI.port]) &&
	    (_client->_lastWasHEAD || _client->_lastResponse.atEndOfStream)) {
		/*
		 * Set _stream to nil, so that in case of an error it won't be
		 * reused. If everything is successful, we set _stream again
		 * at the end.
		 */
		stream = [_client->_stream autorelease];
		_client->_stream = nil;

		[_client->_lastURI release];
		_client->_lastURI = nil;
		[_client->_lastIRI release];
		_client->_lastIRI = nil;

		[_client->_lastResponse release];
		_client->_lastResponse = nil;

		stream.delegate = self;

		[self performSelector: @selector(handleStream:)
			   withObject: stream
			   afterDelay: 0];
	} else
		[self closeAndReconnect];
}

- (void)closeAndReconnect
{
	@try {
		OFURI *URI = _request.URI;
		OFIRI *IRI =
		    _request.IRI.IRIByAddingPercentEncodingForUnicodeCharacters;
		OFTCPSocket *sock;
		uint16_t port;
		OFNumber *URIPort;
		OFNumber *IRIPort;

		[_client close];

		sock = [OFTCPSocket socket];

		if ([URI.scheme caseInsensitiveCompare: @"https"] ==
		if ([IRI.scheme caseInsensitiveCompare: @"https"] ==
		    OFOrderedSame)
			port = 443;
		else
			port = 80;

		URIPort = URI.port;
		if (URIPort != nil)
			port = URIPort.unsignedShortValue;
		IRIPort = IRI.port;
		if (IRIPort != nil)
			port = IRIPort.unsignedShortValue;

		sock.delegate = self;
		[sock asyncConnectToHost: URI.host port: port];
		[sock asyncConnectToHost: IRI.host port: port];
	} @catch (id e) {
		[self raiseException: e];
	}
}
@end

@implementation OFHTTPClientRequestBodyStream
1199
1200
1201
1202
1203
1204
1205
1206

1207
1208
1209
1210
1211
1212

1213
1214

1215
1216
1217
1218
1219
1220
1221
1201
1202
1203
1204
1205
1206
1207

1208
1209
1210
1211
1212
1213

1214
1215

1216
1217
1218
1219
1220
1221
1222
1223







-
+





-
+

-
+







		[_delegate     client: client
		    didReceiveHeaders: headers
			   statusCode: statusCode
			      request: request];
}

-	       (bool)client: (OFHTTPClient *)client
  shouldFollowRedirectToURI: (OFURI *)URI
  shouldFollowRedirectToIRI: (OFIRI *)IRI
		 statusCode: (short)statusCode
		    request: (OFHTTPRequest *)request
		   response: (OFHTTPResponse *)response
{
	if ([_delegate respondsToSelector: @selector(
	    client:shouldFollowRedirectToURI:statusCode:request:response:)])
	    client:shouldFollowRedirectToIRI:statusCode:request:response:)])
		return [_delegate      client: client
		    shouldFollowRedirectToURI: URI
		    shouldFollowRedirectToIRI: IRI
				   statusCode: statusCode
				      request: request
				     response: response];
	else
		return defaultShouldFollow(request.method, statusCode);
}
@end
1263
1264
1265
1266
1267
1268
1269
1270
1271


1272
1273
1274
1275

1276
1277
1278

1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296


1297
1298
1299
1300
1301
1265
1266
1267
1268
1269
1270
1271


1272
1273
1274
1275
1276

1277
1278
1279

1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296


1297
1298
1299
1300
1301
1302
1303







-
-
+
+



-
+


-
+
















-
-
+
+





	[self asyncPerformRequest: request redirects: defaultRedirects];
}

- (void)asyncPerformRequest: (OFHTTPRequest *)request
		  redirects: (unsigned int)redirects
{
	void *pool = objc_autoreleasePoolPush();
	OFURI *URI = request.URI;
	OFString *scheme = URI.scheme;
	OFIRI *IRI = request.IRI;
	OFString *scheme = IRI.scheme;

	if ([scheme caseInsensitiveCompare: @"http"] != OFOrderedSame &&
	    [scheme caseInsensitiveCompare: @"https"] != OFOrderedSame)
		@throw [OFUnsupportedProtocolException exceptionWithURI: URI];
		@throw [OFUnsupportedProtocolException exceptionWithIRI: IRI];

	if (_inProgress)
		@throw [OFAlreadyConnectedException exception];
		@throw [OFAlreadyOpenException exceptionWithObject: self];

	_inProgress = true;

	[[[[OFHTTPClientRequestHandler alloc]
	    initWithClient: self
		   request: request
		 redirects: redirects] autorelease] start];

	objc_autoreleasePoolPop(pool);
}

- (void)close
{
	[_stream release];
	_stream = nil;

	[_lastURI release];
	_lastURI = nil;
	[_lastIRI release];
	_lastIRI = nil;

	[_lastResponse release];
	_lastResponse = nil;
}
@end

Modified src/OFHTTPCookie.h from [ff53970b1e] to [b9b2600bbf].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
17
18
19
20
21
22
23

24
25
26
27
28
29
30
31
32
17
18
19
20
21
22
23
24
25

26
27
28
29
30
31
32







+

-







#import "OFString.h"

OF_ASSUME_NONNULL_BEGIN

@class OFArray OF_GENERIC(ObjectType);
@class OFDate;
@class OFDictionary OF_GENERIC(KeyType, ObjectType);
@class OFIRI;
@class OFMutableArray OF_GENERIC(ObjectType);
@class OFURI;

/**
 * @class OFHTTPCookie OFHTTPCookie.h ObjFW/OFHTTPCookie.h
 *
 * @brief A class for storing and manipulating HTTP cookies.
 */
OF_SUBCLASSING_RESTRICTED
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
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







-
+



-
+






-
+







/**
 * @brief An array of other attributes.
 */
@property (readonly, nonatomic)
    OFMutableArray OF_GENERIC(OFString *) *extensions;

/**
 * @brief Parses the specified response header fields for the specified URI and
 * @brief Parses the specified response header fields for the specified IRI and
 *	  returns an array of cookies.
 *
 * @param headerFields The response header fields to parse
 * @param URI The URI for the response header fields to parse
 * @param IRI The IRI for the response header fields to parse
 * @return An array of cookies
 * @throw OFInvalidFormatException The specified response header has an invalid
 *				   format
 */
+ (OFArray OF_GENERIC(OFHTTPCookie *) *)cookiesWithResponseHeaderFields:
    (OFDictionary OF_GENERIC(OFString *, OFString *) *)headerFields
    forURI: (OFURI *)URI;
    forIRI: (OFIRI *)IRI;

/**
 * @brief Returns the request header fields for the specified cookies.
 *
 * @param cookies The cookies to return the request header fields for
 * @return The request header fields for the specified cookies
 */

Modified src/OFHTTPCookie.m from [a7d6a07918] to [25b009e19f].

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
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

-
+



















-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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 "OFHTTPCookie.h"
#import "OFArray.h"
#import "OFDate.h"
#import "OFDictionary.h"
#import "OFURI.h"
#import "OFIRI.h"

#import "OFInvalidFormatException.h"

static void
handleAttribute(OFHTTPCookie *cookie, OFString *name, OFString *value)
{
	OFString *lowercaseName = name.lowercaseString;
58
59
60
61
62
63
64
65

66
67
68
69
70


71
72
73
74
75
76
77
58
59
60
61
62
63
64

65
66
67
68
69

70
71
72
73
74
75
76
77
78







-
+




-
+
+







@implementation OFHTTPCookie
@synthesize name = _name, value = _value, domain = _domain, path = _path;
@synthesize expires = _expires, secure = _secure, HTTPOnly = _HTTPOnly;
@synthesize extensions = _extensions;

+ (OFArray OF_GENERIC(OFHTTPCookie *) *)cookiesWithResponseHeaderFields:
    (OFDictionary OF_GENERIC(OFString *, OFString *) *)headerFields
    forURI: (OFURI *)URI
    forIRI: (OFIRI *)IRI
{
	OFMutableArray OF_GENERIC(OFHTTPCookie *) *ret = [OFMutableArray array];
	void *pool = objc_autoreleasePoolPush();
	OFString *string = [headerFields objectForKey: @"Set-Cookie"];
	OFString *domain = URI.host;
	OFString *domain = IRI.IRIByAddingPercentEncodingForUnicodeCharacters
	    .host;
	const OFUnichar *characters = string.characters;
	size_t length = string.length, last = 0;
	enum {
		statePreName,
		stateName,
		stateExpectValue,
		stateValue,

Modified src/OFHTTPCookieManager.h from [3cc0432376] to [97276ce2e8].

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
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

-
+



















+

-







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 */

#import "OFObject.h"

OF_ASSUME_NONNULL_BEGIN

@class OFArray OF_GENERIC(ObjectType);
@class OFHTTPCookie;
@class OFIRI;
@class OFMutableArray OF_GENERIC(ObjectType);
@class OFURI;

/**
 * @class OFHTTPCookieManager OFHTTPCookieManager.h ObjFW/OFHTTPCookieManager.h
 *
 * @brief A class for managing cookies for multiple domains.
 */
OF_SUBCLASSING_RESTRICTED
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
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







-
+





-
+

-
+


-
+





-
+


-
+


-
+

-
-
+
+

-
+








 * @brief Create a new cookie manager.
 *
 * @return A new, autoreleased OFHTTPCookieManager
 */
+ (instancetype)manager;

/**
 * @brief Adds the specified cookie for the specified URI.
 * @brief Adds the specified cookie for the specified IRI.
 *
 * @warning This modifies the cookie (e.g. it sets the domain if it is unset)!
 *	    If you do not want this, pass a copy!
 *
 * @param cookie The cookie to add to the manager
 * @param URI The URI for which the cookie should be added
 * @param IRI The IRI for which the cookie should be added
 */
- (void)addCookie: (OFHTTPCookie *)cookie forURI: (OFURI *)URI;
- (void)addCookie: (OFHTTPCookie *)cookie forIRI: (OFIRI *)IRI;

/**
 * @brief Adds the specified cookies for the specified URI.
 * @brief Adds the specified cookies for the specified IRI.
 *
 * @warning This modifies the cookies (e.g. it sets the domain if it is unset)!
 *	    If you do not want this, pass copies!
 *
 * @param cookies An array of cookies to add to the manager
 * @param URI The URI for which the cookies should be added
 * @param IRI The IRI for which the cookies should be added
 */
- (void)addCookies: (OFArray OF_GENERIC(OFHTTPCookie *) *)cookies
	    forURI: (OFURI *)URI;
	    forIRI: (OFIRI *)IRI;

/**
 * @brief Returns the cookies for the specified URI.
 * @brief Returns the cookies for the specified IRI.
 *
 * @param URI The URI for which the cookies should be returned
 * @return The cookies for the specified URI
 * @param IRI The IRI for which the cookies should be returned
 * @return The cookies for the specified IRI
 */
- (OFArray OF_GENERIC(OFHTTPCookie *) *)cookiesForURI: (OFURI *)URI;
- (OFArray OF_GENERIC(OFHTTPCookie *) *)cookiesForIRI: (OFIRI *)IRI;

/**
 * @brief Purges all expired cookies.
 */
- (void)purgeExpiredCookies;
@end

OF_ASSUME_NONNULL_END

Modified src/OFHTTPCookieManager.m from [1dd74fe07e] to [8d1e7efb55].

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
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

-
+



















-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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 "OFHTTPCookieManager.h"
#import "OFArray.h"
#import "OFDate.h"
#import "OFHTTPCookie.h"
#import "OFURI.h"
#import "OFIRI.h"

@implementation OFHTTPCookieManager
+ (instancetype)manager
{
	return [[[self alloc] init] autorelease];
}

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
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







-
+


-
+

+
+





-
+







-
-
-
+
+
+

-
+







}

- (OFArray OF_GENERIC(OFHTTPCookie *) *)cookies
{
	return [[_cookies copy] autorelease];
}

- (void)addCookie: (OFHTTPCookie *)cookie forURI: (OFURI *)URI
- (void)addCookie: (OFHTTPCookie *)cookie forIRI: (OFIRI *)IRI
{
	void *pool = objc_autoreleasePoolPush();
	OFString *cookieDomain, *URIHost;
	OFString *cookieDomain, *IRIHost;
	size_t i;

	IRI = IRI.IRIByAddingPercentEncodingForUnicodeCharacters;

	if (![cookie.path hasPrefix: @"/"])
		cookie.path = @"/";

	if (cookie.secure &&
	    [URI.scheme caseInsensitiveCompare: @"https"] != OFOrderedSame) {
	    [IRI.scheme caseInsensitiveCompare: @"https"] != OFOrderedSame) {
		objc_autoreleasePoolPop(pool);
		return;
	}

	cookieDomain = cookie.domain.lowercaseString;
	cookie.domain = cookieDomain;

	URIHost = URI.host.lowercaseString;
	if (![cookieDomain isEqual: URIHost]) {
		URIHost = [@"." stringByAppendingString: URIHost];
	IRIHost = IRI.host.lowercaseString;
	if (![cookieDomain isEqual: IRIHost]) {
		IRIHost = [@"." stringByAppendingString: IRIHost];

		if (![cookieDomain hasSuffix: URIHost]) {
		if (![cookieDomain hasSuffix: IRIHost]) {
			objc_autoreleasePoolPop(pool);
			return;
		}
	}

	i = 0;
	for (OFHTTPCookie *iter in _cookies) {
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
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







-
+


-
+


-
+


+

+
+

-
+

-
+






-
+



-
+


-
+

-
+





-
+


-
+


-
+




-
+

-
+






-
+



-
+








+
+








	[_cookies addObject: cookie];

	objc_autoreleasePoolPop(pool);
}

- (void)addCookies: (OFArray OF_GENERIC(OFHTTPCookie *) *)cookies
	    forURI: (OFURI *)URI
	    forIRI: (OFIRI *)IRI
{
	for (OFHTTPCookie *cookie in cookies)
		[self addCookie: cookie forURI: URI];
		[self addCookie: cookie forIRI: IRI];
}

- (OFArray OF_GENERIC(OFHTTPCookie *) *)cookiesForURI: (OFURI *)URI
- (OFArray OF_GENERIC(OFHTTPCookie *) *)cookiesForIRI: (OFIRI *)IRI
{
	OFMutableArray *ret = [OFMutableArray array];
	void *pool = objc_autoreleasePoolPush();

	IRI = IRI.IRIByAddingPercentEncodingForUnicodeCharacters;

	for (OFHTTPCookie *cookie in _cookies) {
		void *pool;
		void *pool2;
		OFDate *expires;
		OFString *cookieDomain, *URIHost, *cookiePath, *URIPath;
		OFString *cookieDomain, *IRIHost, *cookiePath, *IRIPath;
		bool match;

		expires = cookie.expires;
		if (expires != nil && expires.timeIntervalSinceNow <= 0)
			continue;

		if (cookie.secure && [URI.scheme caseInsensitiveCompare:
		if (cookie.secure && [IRI.scheme caseInsensitiveCompare:
		    @"https"] != OFOrderedSame)
			continue;

		pool = objc_autoreleasePoolPush();
		pool2 = objc_autoreleasePoolPush();

		cookieDomain = cookie.domain.lowercaseString;
		URIHost = URI.host.lowercaseString;
		IRIHost = IRI.host.lowercaseString;
		if ([cookieDomain hasPrefix: @"."]) {
			if ([URIHost hasSuffix: cookieDomain])
			if ([IRIHost hasSuffix: cookieDomain])
				match = true;
			else {
				cookieDomain =
				    [cookieDomain substringFromIndex: 1];

				match = [cookieDomain isEqual: URIHost];
				match = [cookieDomain isEqual: IRIHost];
			}
		} else
			match = [cookieDomain isEqual: URIHost];
			match = [cookieDomain isEqual: IRIHost];

		if (!match) {
			objc_autoreleasePoolPop(pool);
			objc_autoreleasePoolPop(pool2);
			continue;
		}

		cookiePath = cookie.path;
		URIPath = URI.path;
		IRIPath = IRI.path;
		if (![cookiePath isEqual: @"/"]) {
			if ([cookiePath isEqual: URIPath])
			if ([cookiePath isEqual: IRIPath])
				match = true;
			else {
				if (![cookiePath hasSuffix: @"/"])
					cookiePath = [cookiePath
					    stringByAppendingString: @"/"];

				match = [URIPath hasPrefix: cookiePath];
				match = [IRIPath hasPrefix: cookiePath];
			}

			if (!match) {
				objc_autoreleasePoolPop(pool);
				objc_autoreleasePoolPop(pool2);
				continue;
			}
		}

		[ret addObject: cookie];
	}

	[ret makeImmutable];

	objc_autoreleasePoolPop(pool);

	return ret;
}

- (void)purgeExpiredCookies
{
	for (size_t i = 0, count = _cookies.count; i < count; i++) {

Renamed and modified src/OFHTTPURIHandler.h [1fbd933246] to src/OFHTTPIRIHandler.h [e3a6563685].

1
2

3
4
5
6
7
8
9
10
11
12
13
14
15
16

17
18
19
20

21
22
23
1

2
3
4
5
6
7
8
9
10
11
12
13
14
15

16
17
18
19

20
21
22
23

-
+













-
+



-
+



/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 */

#import "OFURIHandler.h"
#import "OFIRIHandler.h"

OF_ASSUME_NONNULL_BEGIN

@interface OFHTTPURIHandler: OFURIHandler
@interface OFHTTPIRIHandler: OFIRIHandler
@end

OF_ASSUME_NONNULL_END

Renamed and modified src/OFHTTPURIHandler.m [9e6fa9d3fe] to src/OFHTTPIRIHandler.m [b9d37cc0a5].

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
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

-
+















-
+




-
-
+
+



-
+









/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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 "OFHTTPURIHandler.h"
#import "OFHTTPIRIHandler.h"
#import "OFHTTPClient.h"
#import "OFHTTPRequest.h"
#import "OFHTTPResponse.h"

@implementation OFHTTPURIHandler
- (OFStream *)openItemAtURI: (OFURI *)URI mode: (OFString *)mode
@implementation OFHTTPIRIHandler
- (OFStream *)openItemAtIRI: (OFIRI *)IRI mode: (OFString *)mode
{
	void *pool = objc_autoreleasePoolPush();
	OFHTTPClient *client = [OFHTTPClient client];
	OFHTTPRequest *request = [OFHTTPRequest requestWithURI: URI];
	OFHTTPRequest *request = [OFHTTPRequest requestWithIRI: IRI];
	OFHTTPResponse *response = [client performRequest: request];

	[response retain];

	objc_autoreleasePoolPop(pool);

	return [response autorelease];
}
@end

Modified src/OFHTTPRequest.h from [1278addd47] to [f431611fce].

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
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

-
+



















-
+

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 */

#import "OFObject.h"
#import "OFSocket.h"
#import "OFString.h"

OF_ASSUME_NONNULL_BEGIN

@class OFURI;
@class OFData;
@class OFDictionary OF_GENERIC(KeyType, ObjectType);
@class OFData;
@class OFIRI;
@class OFString;

/** @file */

/**
 * @brief The type of an HTTP request.
 */
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
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







-
+








-
+

-
+







 * @class OFHTTPRequest OFHTTPRequest.h ObjFW/OFHTTPRequest.h
 *
 * @brief A class for storing HTTP requests.
 */
OF_SUBCLASSING_RESTRICTED
@interface OFHTTPRequest: OFObject <OFCopying>
{
	OFURI *_URI;
	OFIRI *_IRI;
	OFHTTPRequestMethod _method;
	OFHTTPRequestProtocolVersion _protocolVersion;
	OFDictionary OF_GENERIC(OFString *, OFString *) *_Nullable _headers;
	OFSocketAddress _remoteAddress;
	bool _hasRemoteAddress;
}

/**
 * @brief The URI of the HTTP request.
 * @brief The IRI of the HTTP request.
 */
@property (copy, nonatomic) OFURI *URI;
@property (copy, nonatomic) OFIRI *IRI;

/**
 * @brief The protocol version of the HTTP request.
 *
 * @throw OFUnsupportedVersionException The specified version cannot be set
 *					because it is not supported
 */
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
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







-
+

-
+


-
+


-
+

-
+


-
+







 * @brief The remote address from which the request originates.
 *
 * @note The setter creates a copy of the remote address.
 */
@property OF_NULLABLE_PROPERTY (nonatomic) const OFSocketAddress *remoteAddress;

/**
 * @brief Creates a new OFHTTPRequest with the specified URI.
 * @brief Creates a new OFHTTPRequest with the specified IRI.
 *
 * @param URI The URI for the request
 * @param IRI The IRI for the request
 * @return A new, autoreleased OFHTTPRequest
 */
+ (instancetype)requestWithURI: (OFURI *)URI;
+ (instancetype)requestWithIRI: (OFIRI *)IRI;

/**
 * @brief Initializes an already allocated OFHTTPRequest with the specified URI.
 * @brief Initializes an already allocated OFHTTPRequest with the specified IRI.
 *
 * @param URI The URI for the request
 * @param IRI The IRI for the request
 * @return An initialized OFHTTPRequest
 */
- (instancetype)initWithURI: (OFURI *)URI;
- (instancetype)initWithIRI: (OFIRI *)IRI;

- (instancetype)init OF_UNAVAILABLE;
@end

#ifdef __cplusplus
extern "C" {
#endif

Modified src/OFHTTPRequest.m from [c85955ea02] to [f630f4e80b].

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
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

-
+


















-
-
+
+

-
-
+
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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"

#include <string.h>

#import "OFHTTPRequest.h"
#import "OFString.h"
#import "OFURI.h"
#import "OFArray.h"
#import "OFData.h"
#import "OFDictionary.h"
#import "OFData.h"
#import "OFArray.h"
#import "OFIRI.h"
#import "OFString.h"

#import "OFInvalidArgumentException.h"
#import "OFInvalidFormatException.h"
#import "OFOutOfRangeException.h"
#import "OFUnsupportedVersionException.h"

const char *
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
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







-
+

-
+

-
+


-
+




-
+


















-
+







	if ([string isEqual: @"CONNECT"])
		return OFHTTPRequestMethodConnect;

	@throw [OFInvalidFormatException exception];
}

@implementation OFHTTPRequest
@synthesize URI = _URI, method = _method, headers = _headers;
@synthesize IRI = _IRI, method = _method, headers = _headers;

+ (instancetype)requestWithURI: (OFURI *)URI
+ (instancetype)requestWithIRI: (OFIRI *)IRI
{
	return [[[self alloc] initWithURI: URI] autorelease];
	return [[[self alloc] initWithIRI: IRI] autorelease];
}

- (instancetype)initWithURI: (OFURI *)URI
- (instancetype)initWithIRI: (OFIRI *)IRI
{
	self = [super init];

	@try {
		_URI = [URI copy];
		_IRI = [IRI copy];
		_method = OFHTTPRequestMethodGet;
		_protocolVersion.major = 1;
		_protocolVersion.minor = 1;
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (instancetype)init
{
	OF_INVALID_INIT_METHOD
}

- (void)dealloc
{
	[_URI release];
	[_IRI release];
	[_headers release];

	[super dealloc];
}

- (void)setRemoteAddress: (const OFSocketAddress *)remoteAddress
{
129
130
131
132
133
134
135
136

137
138
139
140
141
142
143
129
130
131
132
133
134
135

136
137
138
139
140
141
142
143







-
+







		return &_remoteAddress;

	return NULL;
}

- (id)copy
{
	OFHTTPRequest *copy = [[OFHTTPRequest alloc] initWithURI: _URI];
	OFHTTPRequest *copy = [[OFHTTPRequest alloc] initWithIRI: _IRI];

	@try {
		copy->_method = _method;
		copy->_protocolVersion = _protocolVersion;
		copy.headers = _headers;
		copy.remoteAddress = self.remoteAddress;
	} @catch (id e) {
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
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







-
+



















-
+







		return false;

	request = object;

	if (request->_method != _method ||
	    request->_protocolVersion.major != _protocolVersion.major ||
	    request->_protocolVersion.minor != _protocolVersion.minor ||
	    ![request->_URI isEqual: _URI] ||
	    ![request->_IRI isEqual: _IRI] ||
	    ![request->_headers isEqual: _headers])
		return false;

	if (request.remoteAddress != self.remoteAddress &&
	    !OFSocketAddressEqual(request.remoteAddress, self.remoteAddress))
		return false;

	return true;
}

- (unsigned long)hash
{
	unsigned long hash;

	OFHashInit(&hash);

	OFHashAddByte(&hash, _method);
	OFHashAddByte(&hash, _protocolVersion.major);
	OFHashAddByte(&hash, _protocolVersion.minor);
	OFHashAddHash(&hash, _URI.hash);
	OFHashAddHash(&hash, _IRI.hash);
	OFHashAddHash(&hash, _headers.hash);
	if (_hasRemoteAddress)
		OFHashAddHash(&hash, OFSocketAddressHash(&_remoteAddress));

	OFHashFinalize(&hash);

	return hash;
252
253
254
255
256
257
258
259

260
261
262
263
264

265
266
267
268
269
270
252
253
254
255
256
257
258

259
260
261
262
263

264
265
266
267
268
269
270







-
+




-
+







	if (_hasRemoteAddress)
		remoteAddress = OFSocketAddressString(&_remoteAddress);
	else
		remoteAddress = nil;

	ret = [[OFString alloc] initWithFormat:
	    @"<%@:\n\tURI = %@\n"
	    @"<%@:\n\tIRI = %@\n"
	    @"\tMethod = %s\n"
	    @"\tHeaders = %@\n"
	    @"\tRemote address = %@\n"
	    @">",
	    self.class, _URI, method, indentedHeaders, remoteAddress];
	    self.class, _IRI, method, indentedHeaders, remoteAddress];

	objc_autoreleasePoolPop(pool);

	return [ret autorelease];
}
@end

Modified src/OFHTTPResponse.h from [3c482db81b] to [a7b884a494].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFHTTPResponse.m from [17a72a5d36] to [dd8060da94].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFHTTPServer.h from [ba5fc5aae1] to [3618d652f0].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
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
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







-
-
+
+






-
-
+
+


















-
-
+
+







	OFArray *_threadPool;
#endif
}

/**
 * @brief The host on which the HTTP server will listen.
 *
 * @throw OFAlreadyConnectedException The host could not be set because
 *				      @ref start had already been called
 * @throw OFAlreadyOpenException The host could not be set because @ref start
 *				  had already been called
 */
@property OF_NULLABLE_PROPERTY (copy, nonatomic) OFString *host;

/**
 * @brief The port on which the HTTP server will listen.
 *
 * @throw OFAlreadyConnectedException The port could not be set because
 *				      @ref start had already been called
 * @throw OFAlreadyOpenException The port could not be set because @ref start
 *				 had already been called
 */
@property (nonatomic) uint16_t port;

/**
 * @brief The delegate for the HTTP server.
 */
@property OF_NULLABLE_PROPERTY (assign, nonatomic)
    id <OFHTTPServerDelegate> delegate;

#ifdef OF_HAVE_THREADS
/**
 * @brief The number of threads the OFHTTPServer should use.
 *
 * If this is larger than 1 (the default), one thread will be used to accept
 * incoming connections and all others will be used to handle connections.
 *
 * For maximum CPU utilization, set this to `[OFSystemInfo numberOfCPUs] + 1`.
 *
 * @throw OFAlreadyConnectedException The number of threads could not be set
 *				      because @ref start had already been called
 * @throw OFAlreadyOpenException The number of threads could not be set because
 *				 @ref start had already been called
 */
@property (nonatomic) size_t numberOfThreads;
#endif

/**
 * @brief The server name the server presents to clients.
 *
154
155
156
157
158
159
160
161

162
163
164
165
166
167
168
169
170
171
172
173
154
155
156
157
158
159
160

161
162
163
164
165
166
167
168
169
170
171
172
173







-
+












 * @return A new HTTP server
 */
+ (instancetype)server;

/**
 * @brief Starts the HTTP server in the current thread's run loop.
 *
 * @throw OFAlreadyConnectedException The server had already been started
 * @throw OFAlreadyOpenException The server had already been started
 */
- (void)start;

/**
 * @brief Stops the HTTP server, meaning it will not accept any new incoming
 *	  connections, but still handle existing connections until they are
 *	  finished or timed out.
 */
- (void)stop;
@end

OF_ASSUME_NONNULL_END

Modified src/OFHTTPServer.m from [e75cf57b42] to [df8e40fa8b].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
24
25
26
27
28
29
30

31
32
33
34
35
36
37
38

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

37

38
39
40
41
42
43
44
45







+





-

-
+







#import "OFHTTPServer.h"
#import "OFArray.h"
#import "OFData.h"
#import "OFDate.h"
#import "OFDictionary.h"
#import "OFHTTPRequest.h"
#import "OFHTTPResponse.h"
#import "OFIRI.h"
#import "OFNumber.h"
#import "OFSocket+Private.h"
#import "OFTCPSocket.h"
#import "OFThread.h"
#import "OFTimer.h"
#import "OFURI.h"

#import "OFAlreadyConnectedException.h"
#import "OFAlreadyOpenException.h"
#import "OFInvalidArgumentException.h"
#import "OFInvalidEncodingException.h"
#import "OFInvalidFormatException.h"
#import "OFNotOpenException.h"
#import "OFOutOfMemoryException.h"
#import "OFOutOfRangeException.h"
#import "OFTruncatedDataException.h"
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
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







-
+



















-
-
+
+

-
+









-
-
+
+

-
+






-
+

-
+







			      date, _server.name];
	return false;
}

- (void)createResponse
{
	void *pool = objc_autoreleasePoolPush();
	OFMutableURI *URI;
	OFMutableIRI *IRI;
	OFHTTPRequest *request;
	OFHTTPServerResponse *response;
	size_t pos;

	[_timer invalidate];
	[_timer release];
	_timer = nil;

	if (_host == nil || _port == 0) {
		if (_HTTPMinorVersion > 0) {
			[self sendErrorAndClose: 400];
			return;
		}

		[_host release];
		_host = [_server.host copy];
		_port = [_server port];
	}

	URI = [OFMutableURI URIWithScheme: @"http"];
	URI.host = _host;
	IRI = [OFMutableIRI IRIWithScheme: @"http"];
	IRI.host = _host;
	if (_port != 80)
		URI.port = [OFNumber numberWithUnsignedShort: _port];
		IRI.port = [OFNumber numberWithUnsignedShort: _port];

	@try {
		if ((pos = [_path rangeOfString: @"?"].location) !=
		    OFNotFound) {
			OFString *path, *query;

			path = [_path substringToIndex: pos];
			query = [_path substringFromIndex: pos + 1];

			URI.percentEncodedPath = path;
			URI.percentEncodedQuery = query;
			IRI.percentEncodedPath = path;
			IRI.percentEncodedQuery = query;
		} else
			URI.percentEncodedPath = _path;
			IRI.percentEncodedPath = _path;
	} @catch (OFInvalidFormatException *e) {
		objc_autoreleasePoolPop(pool);
		[self sendErrorAndClose: 400];
		return;
	}

	[URI makeImmutable];
	[IRI makeImmutable];

	request = [OFHTTPRequest requestWithURI: URI];
	request = [OFHTTPRequest requestWithIRI: IRI];
	request.method = _method;
	request.protocolVersion =
	    (OFHTTPRequestProtocolVersion){ 1, _HTTPMinorVersion };
	request.headers = _headers;
	request.remoteAddress = _socket.remoteAddress;

	response = [[[OFHTTPServerResponse alloc]
800
801
802
803
804
805
806
807

808
809
810
811
812
813
814
815
816
817
818
819
820
821
822

823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839

840
841
842
843
844
845
846
847
848
849
850
851
852

853
854
855
856
857
858

859
860
861


862
863
864
865
866
867
868
800
801
802
803
804
805
806

807
808
809
810
811
812
813
814
815
816
817
818
819
820
821

822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838

839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858

859
860
861

862
863
864
865
866
867
868
869
870







-
+














-
+
















-
+













+





-
+


-
+
+







}

- (void)setHost: (OFString *)host
{
	OFString *old;

	if (_listeningSocket != nil)
		@throw [OFAlreadyConnectedException exception];
		@throw [OFAlreadyOpenException exceptionWithObject: self];

	old = _host;
	_host = [host copy];
	[old release];
}

- (OFString *)host
{
	return _host;
}

- (void)setPort: (uint16_t)port
{
	if (_listeningSocket != nil)
		@throw [OFAlreadyConnectedException exception];
		@throw [OFAlreadyOpenException exceptionWithObject: self];

	_port = port;
}

- (uint16_t)port
{
	return _port;
}

#ifdef OF_HAVE_THREADS
- (void)setNumberOfThreads: (size_t)numberOfThreads
{
	if (numberOfThreads == 0)
		@throw [OFInvalidArgumentException exception];

	if (_listeningSocket != nil)
		@throw [OFAlreadyConnectedException exception];
		@throw [OFAlreadyOpenException exceptionWithObject: self];

	_numberOfThreads = numberOfThreads;
}

- (size_t)numberOfThreads
{
	return _numberOfThreads;
}
#endif

- (void)start
{
	void *pool = objc_autoreleasePoolPush();
	OFSocketAddress address;

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

	if (_listeningSocket != nil)
		@throw [OFAlreadyConnectedException exception];
		@throw [OFAlreadyOpenException exceptionWithObject: self];

	_listeningSocket = [[OFTCPSocket alloc] init];
	_port = [_listeningSocket bindToHost: _host port: _port];
	address = [_listeningSocket bindToHost: _host port: _port];
	_port = OFSocketAddressIPPort(&address);
	[_listeningSocket listen];

#ifdef OF_HAVE_THREADS
	if (_numberOfThreads > 1) {
		OFMutableArray *threads =
		    [OFMutableArray arrayWithCapacity: _numberOfThreads - 1];

Modified src/OFHostAddressResolver.h from [5c6783fd03] to [449bceebed].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFHostAddressResolver.m from [3275d58c93] to [1a75dd0a5b].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
149
150
151
152
153
154
155
156
157





158
159
160
161
162
163
164
149
150
151
152
153
154
155


156
157
158
159
160
161
162
163
164
165
166
167







-
-
+
+
+
+
+







}

- (void)sendQueries
{
	OFString *domainName;

	if (!_isFQDN) {
		OFString *searchDomain = [_settings->_searchDomains
		    objectAtIndex: _searchDomainIndex];
		OFString *searchDomain = @"";

		if (_searchDomainIndex < _settings->_searchDomains.count)
			searchDomain = [_settings->_searchDomains
			    objectAtIndex: _searchDomainIndex];

		domainName = [OFString stringWithFormat: @"%@.%@",
							 _host, searchDomain];
	} else
		domainName = _host;

#ifdef OF_HAVE_IPV6
284
285
286
287
288
289
290
291


292
293
294
295
296
297
298
287
288
289
290
291
292
293

294
295
296
297
298
299
300
301
302







-
+
+







		    addresses, exception);

		objc_autoreleasePoolPop(pool);
		return;
	} @catch (OFInvalidFormatException *e) {
	}

	if ((aliases = [_settings->_staticHosts objectForKey: _host]) != nil) {
	if ((aliases = [_settings->_staticHosts objectForKey:
	    _host.lowercaseString]) != nil) {
		OFMutableData *addresses = [OFMutableData
		    dataWithItemSize: sizeof(OFSocketAddress)];
		id exception = nil;

		for (OFString *alias in aliases) {
			OFSocketAddress address;

Modified src/OFHuffmanTree.h from [0152a399af] to [55fb6bc288].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFHuffmanTree.m from [13f0a946b0] to [a61d8159f9].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFINICategory+Private.h from [6b757dc025] to [1882471bdd].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFINICategory.h from [8e0c968abf] to [78e7ff0afc].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFINICategory.m from [1db2d24df3] to [cc663f3e2a].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFINIFile.h from [f35fd21473] to [b499732126].

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
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

-
+



















+

-




















-
+







-
+





-
+







-
+







-
+







-
+





-
+







-
+

















-
+

-
+





-
+


-
+



/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 */

#import "OFObject.h"
#import "OFString.h"
#import "OFINICategory.h"

OF_ASSUME_NONNULL_BEGIN

@class OFIRI;
@class OFMutableArray OF_GENERIC(ObjectType);
@class OFURI;

/**
 * @class OFINIFile OFINIFile.h ObjFW/OFINIFile.h
 *
 * @brief A class for reading, creating and modifying INI files.
 */
OF_SUBCLASSING_RESTRICTED
@interface OFINIFile: OFObject
{
	OFMutableArray OF_GENERIC(OFINICategory *) *_categories;
}

/**
 * @brief All categories in the INI file.
 */
@property (readonly, nonatomic) OFArray OF_GENERIC(OFINICategory *) *categories;

/**
 * @brief Creates a new OFINIFile with the contents of the specified file.
 *
 * @param URI The URI to the file whose contents the OFINIFile should contain
 * @param IRI The IRI to the file whose contents the OFINIFile should contain
 *
 * @return A new, autoreleased OFINIFile with the contents of the specified file
 * @throw OFInvalidFormatException The format of the specified INI file is
 *				   invalid
 * @throw OFInvalidEncodingException The INI file is not in the specified
 *				     encoding
 */
+ (instancetype)fileWithURI: (OFURI *)URI;
+ (instancetype)fileWithIRI: (OFIRI *)IRI;

/**
 * @brief Creates a new OFINIFile with the contents of the specified file in
 *	  the specified encoding.
 *
 * @param URI The URI to the file whose contents the OFINIFile should contain
 * @param IRI The IRI to the file whose contents the OFINIFile should contain
 * @param encoding The encoding of the specified file
 * @return A new, autoreleased OFINIFile with the contents of the specified file
 * @throw OFInvalidFormatException The format of the specified INI file is
 *				   invalid
 * @throw OFInvalidEncodingException The INI file is not in the specified
 *				     encoding
 */
+ (instancetype)fileWithURI: (OFURI *)URI encoding: (OFStringEncoding)encoding;
+ (instancetype)fileWithIRI: (OFIRI *)IRI encoding: (OFStringEncoding)encoding;

- (instancetype)init OF_UNAVAILABLE;

/**
 * @brief Initializes an already allocated OFINIFile with the contents of the
 *	  specified file.
 *
 * @param URI The URI to the file whose contents the OFINIFile should contain
 * @param IRI The IRI to the file whose contents the OFINIFile should contain
 *
 * @return An initialized OFINIFile with the contents of the specified file
 * @throw OFInvalidFormatException The format of the specified INI file is
 *				   invalid
 * @throw OFInvalidEncodingException The INI file is not in the specified
 *				     encoding
 */
- (instancetype)initWithURI: (OFURI *)URI;
- (instancetype)initWithIRI: (OFIRI *)IRI;

/**
 * @brief Initializes an already allocated OFINIFile with the contents of the
 *	  specified file in the specified encoding.
 *
 * @param URI The URI to the file whose contents the OFINIFile should contain
 * @param IRI The IRI to the file whose contents the OFINIFile should contain
 * @param encoding The encoding of the specified file
 * @return An initialized OFINIFile with the contents of the specified file
 * @throw OFInvalidFormatException The format of the specified INI file is
 *				   invalid
 * @throw OFInvalidEncodingException The INI file is not in the specified
 *				     encoding
 */
- (instancetype)initWithURI: (OFURI *)URI
- (instancetype)initWithIRI: (OFIRI *)IRI
		   encoding: (OFStringEncoding)encoding
    OF_DESIGNATED_INITIALIZER;

/**
 * @brief Returns an @ref OFINICategory for the category with the specified
 *	  name.
 *
 * @param name The name of the category for which an @ref OFINICategory should
 *	       be returned
 *
 * @return An @ref OFINICategory for the category with the specified name
 */
- (OFINICategory *)categoryForName: (OFString *)name;

/**
 * @brief Writes the contents of the OFINIFile to a file.
 *
 * @param URI The URI of the file to write to
 * @param IRI The IRI of the file to write to
 */
- (void)writeToURI: (OFURI *)URI;
- (void)writeToIRI: (OFIRI *)IRI;

/**
 * @brief Writes the contents of the OFINIFile to a file in the specified
 *	  encoding.
 *
 * @param URI The URI of the file to write to
 * @param IRI The IRI of the file to write to
 * @param encoding The encoding to use
 */
- (void)writeToURI: (OFURI *)URI encoding: (OFStringEncoding)encoding;
- (void)writeToIRI: (OFIRI *)IRI encoding: (OFStringEncoding)encoding;
@end

OF_ASSUME_NONNULL_END

Modified src/OFINIFile.m from [7850530cf1] to [462321b787].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
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
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







-
-
-
-
+
+
+
+






-
+


















-
+

-
+


-
+

-
+







-
+

-
+


-
+






-
+








#include <errno.h>

#import "OFINIFile.h"
#import "OFArray.h"
#import "OFINICategory+Private.h"
#import "OFINICategory.h"
#import "OFStream.h"
#import "OFString.h"
#import "OFURI.h"
#import "OFURIHandler.h"
#import "OFIRI.h"
#import "OFIRIHandler.h"
#import "OFStream.h"
#import "OFString.h"

#import "OFInvalidFormatException.h"
#import "OFOpenItemFailedException.h"

OF_DIRECT_MEMBERS
@interface OFINIFile ()
- (void)of_parseURI: (OFURI *)URI encoding: (OFStringEncoding)encoding;
- (void)of_parseIRI: (OFIRI *)IRI encoding: (OFStringEncoding)encoding;
@end

static bool
isWhitespaceLine(OFString *line)
{
	const char *cString = line.UTF8String;
	size_t length = line.UTF8StringLength;

	for (size_t i = 0; i < length; i++)
		if (!OFASCIIIsSpace(cString[i]))
			return false;

	return true;
}

@implementation OFINIFile
@synthesize categories = _categories;

+ (instancetype)fileWithURI: (OFURI *)URI
+ (instancetype)fileWithIRI: (OFIRI *)IRI
{
	return [[[self alloc] initWithURI: URI] autorelease];
	return [[[self alloc] initWithIRI: IRI] autorelease];
}

+ (instancetype)fileWithURI: (OFURI *)URI encoding: (OFStringEncoding)encoding
+ (instancetype)fileWithIRI: (OFIRI *)IRI encoding: (OFStringEncoding)encoding
{
	return [[[self alloc] initWithURI: URI encoding: encoding] autorelease];
	return [[[self alloc] initWithIRI: IRI encoding: encoding] autorelease];
}

- (instancetype)init
{
	OF_INVALID_INIT_METHOD
}

- (instancetype)initWithURI: (OFURI *)URI
- (instancetype)initWithIRI: (OFIRI *)IRI
{
	return [self initWithURI: URI encoding: OFStringEncodingAutodetect];
	return [self initWithIRI: IRI encoding: OFStringEncodingAutodetect];
}

- (instancetype)initWithURI: (OFURI *)URI encoding: (OFStringEncoding)encoding
- (instancetype)initWithIRI: (OFIRI *)IRI encoding: (OFStringEncoding)encoding
{
	self = [super init];

	@try {
		_categories = [[OFMutableArray alloc] init];

		[self of_parseURI: URI encoding: encoding];
		[self of_parseIRI: IRI encoding: encoding];
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}
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
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







-
+










-
+







	[_categories addObject: category];

	objc_autoreleasePoolPop(pool);

	return category;
}

- (void)of_parseURI: (OFURI *)URI encoding: (OFStringEncoding)encoding
- (void)of_parseIRI: (OFIRI *)IRI encoding: (OFStringEncoding)encoding
{
	void *pool = objc_autoreleasePoolPush();
	OFStream *file;
	OFINICategory *category = nil;
	OFString *line;

	if (encoding == OFStringEncodingAutodetect)
		encoding = OFStringEncodingUTF8;

	@try {
		file = [OFURIHandler openItemAtURI: URI mode: @"r"];
		file = [OFIRIHandler openItemAtIRI: IRI mode: @"r"];
	} @catch (OFOpenItemFailedException *e) {
		/* Handle missing file like an empty file */
		if (e.errNo == ENOENT)
			return;

		@throw e;
	}
152
153
154
155
156
157
158
159

160
161

162
163
164

165
166
167

168
169
170
171
172
173
174
152
153
154
155
156
157
158

159
160

161
162
163

164
165
166

167
168
169
170
171
172
173
174







-
+

-
+


-
+


-
+







			[category of_parseLine: line];
		}
	}

	objc_autoreleasePoolPop(pool);
}

- (void)writeToURI: (OFURI *)URI
- (void)writeToIRI: (OFIRI *)IRI
{
	[self writeToURI: URI encoding: OFStringEncodingUTF8];
	[self writeToIRI: IRI encoding: OFStringEncodingUTF8];
}

- (void)writeToURI: (OFURI *)URI encoding: (OFStringEncoding)encoding
- (void)writeToIRI: (OFIRI *)IRI encoding: (OFStringEncoding)encoding
{
	void *pool = objc_autoreleasePoolPush();
	OFStream *file = [OFURIHandler openItemAtURI: URI mode: @"w"];
	OFStream *file = [OFIRIHandler openItemAtIRI: IRI mode: @"w"];
	bool first = true;

	for (OFINICategory *category in _categories)
		if ([category of_writeToStream: file
				      encoding: encoding
					 first: first])
			first = false;

Modified src/OFINIFileSettings.h from [125e92a3e8] to [a0a2ba7635].

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
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

-
+


















-
-
+
+



-
+





/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 */

#import "OFSettings.h"

OF_ASSUME_NONNULL_BEGIN

@class OFINIFile;
@class OFString;
@class OFURI;
@class OFIRI;
@class OFString;

@interface OFINIFileSettings: OFSettings
{
	OFURI *_fileURI;
	OFIRI *_fileIRI;
	OFINIFile *_INIFile;
}
@end

OF_ASSUME_NONNULL_END

Modified src/OFINIFileSettings.m from [b3d1a39e2b] to [1fd7fce291].

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
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

-
+


















-
-
-
+
+
+











-
-
-
+
+
+












-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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 "OFINIFileSettings.h"
#import "OFArray.h"
#import "OFINIFile.h"
#import "OFString.h"
#import "OFSystemInfo.h"
#import "OFURI.h"
#import "OFIRI.h"
#import "OFString.h"
#import "OFSystemInfo.h"

@implementation OFINIFileSettings
- (instancetype)initWithApplicationName: (OFString *)applicationName
{
	self = [super initWithApplicationName: applicationName];

	@try {
		void *pool = objc_autoreleasePoolPush();
		OFString *fileName;

		fileName = [applicationName stringByAppendingString: @".ini"];
		_fileURI = [[[OFSystemInfo userConfigURI]
		    URIByAppendingPathComponent: fileName] copy];
		_INIFile = [[OFINIFile alloc] initWithURI: _fileURI];
		_fileIRI = [[[OFSystemInfo userConfigIRI]
		    IRIByAppendingPathComponent: fileName] copy];
		_INIFile = [[OFINIFile alloc] initWithIRI: _fileIRI];

		objc_autoreleasePoolPop(pool);
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (void)dealloc
{
	[_fileURI release];
	[_fileIRI release];
	[_INIFile release];

	[super dealloc];
}

- (void)of_getCategory: (OFString **)category
		andKey: (OFString **)key
239
240
241
242
243
244
245
246

247
248
239
240
241
242
243
244
245

246
247
248







-
+


	[[_INIFile categoryForName: category] removeValueForKey: key];

	objc_autoreleasePoolPop(pool);
}

- (void)save
{
	[_INIFile writeToURI: _fileURI];
	[_INIFile writeToIRI: _fileIRI];
}
@end

Modified src/OFIPXSocket.h from [8dc615311a] to [6b971bfd5b].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
31
32
33
34
35
36
37
38

39
40
41
42
43
44
45
31
32
33
34
35
36
37

38
39
40
41
42
43
44
45







-
+







 * @class OFIPXSocket OFIPXSocket.h ObjFW/OFIPXSocket.h
 *
 * @brief A class which provides methods to create and use IPX sockets.
 *
 * Addresses are of type @ref OFSocketAddress. You can use
 * @ref OFSocketAddressMakeIPX to create an address or
 * @ref OFSocketAddressIPXNetwork to get the IPX network,
 * @ref OFSocketAddressIPXNode to get the IPX node and
 * @ref OFSocketAddressGetIPXNode to get the IPX node and
 * @ref OFSocketAddressIPXPort to get the port (sometimes also called
 * socket number).
 *
 * @warning Even though the OFCopying protocol is implemented, it does *not*
 *	    return an independent copy of the socket, but instead retains it.
 *	    This is so that the socket can be used as a key for a dictionary,
 *	    so context can be associated with a socket. Using a socket in more
71
72
73
74
75
76
77
78

79
80
81
82
83
84
85
86
87
71
72
73
74
75
76
77

78
79
80
81
82
83
84
85
86
87







-
+









 * @param node The IPX network to bind to. An all zero node means the
 *	       computer's node.
 * @param port The port (sometimes called socket number) to bind to. 0 means to
 *	       pick one and return via the returned socket address.
 * @param packetType The packet type to use on the socket
 * @return The address on which this socket can be reached
 * @throw OFBindIPXSocketFailedException Binding failed
 * @throw OFAlreadyConnectedException The socket is already bound
 * @throw OFAlreadyOpenException The socket is already bound
 */
- (OFSocketAddress)
    bindToNetwork: (uint32_t)network
	     node: (const unsigned char [_Nonnull IPX_NODE_LEN])node
	     port: (uint16_t)port
       packetType: (uint8_t)packetType;
@end

OF_ASSUME_NONNULL_END

Modified src/OFIPXSocket.m from [1dc137a6b3] to [137cbc4465].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
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
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







-
+

+
+
+
+
















-
+



-
+







# include <fcntl.h>
#endif

#import "OFIPXSocket.h"
#import "OFSocket.h"
#import "OFSocket+Private.h"

#import "OFAlreadyConnectedException.h"
#import "OFAlreadyOpenException.h"
#import "OFBindIPXSocketFailedException.h"

#ifndef NSPROTO_IPX
# define NSPROTO_IPX 0
#endif

@implementation OFIPXSocket
@dynamic delegate;

- (OFSocketAddress)bindToNetwork: (uint32_t)network
			    node: (const unsigned char [IPX_NODE_LEN])node
			    port: (uint16_t)port
		      packetType: (uint8_t)packetType
{
	OFSocketAddress address;
	int protocol = 0;
#if SOCK_CLOEXEC == 0 && defined(HAVE_FCNTL_H) && defined(FD_CLOEXEC)
	int flags;
#endif

	if (_socket != OFInvalidSocketHandle)
		@throw [OFAlreadyConnectedException exceptionWithSocket: self];
		@throw [OFAlreadyOpenException exceptionWithObject: self];

	address = OFSocketAddressMakeIPX(network, node, port);

#ifdef OF_WINDOWS
#if defined(OF_WINDOWS) || defined(OF_FREEBSD)
	protocol = NSPROTO_IPX + packetType;
#else
	_packetType = address.sockaddr.ipx.sipx_type = packetType;
#endif

	if ((_socket = socket(address.sockaddr.ipx.sipx_family,
	    SOCK_DGRAM | SOCK_CLOEXEC, protocol)) == OFInvalidSocketHandle)
118
119
120
121
122
123
124
125

126
127
128
129
130
131
132
122
123
124
125
126
127
128

129
130
131
132
133
134
135
136







-
+







				  socket: self
				   errNo: EAFNOSUPPORT];
	}

	return address;
}

#ifndef OF_WINDOWS
#if !defined(OF_WINDOWS) && !defined(OF_FREEBSD)
- (void)sendBuffer: (const void *)buffer
	    length: (size_t)length
	  receiver: (const OFSocketAddress *)receiver
{
	OFSocketAddress fixedReceiver;

	memcpy(&fixedReceiver, receiver, sizeof(fixedReceiver));

Renamed and modified src/OFURI+Private.h [c5dc8bc44b] to src/OFIRI+Private.h [89abd85c72].

1
2

3
4
5
6
7
8
9
10
11
12
13
14
15
16

17
18
19
20

21
22
23
24
1

2
3
4
5
6
7
8
9
10
11
12
13
14
15

16
17
18
19

20
21
22
23
24

-
+













-
+



-
+




/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 */

#import "OFURI.h"
#import "OFIRI.h"

OF_ASSUME_NONNULL_BEGIN

@interface OFURI ()
@interface OFIRI ()
- (instancetype)of_init OF_METHOD_FAMILY(init);
@end

OF_ASSUME_NONNULL_END

Renamed and modified src/OFURI.h [90c837e175] to src/OFIRI.h [659e656a72].

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

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
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

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

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

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
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

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

-
+















-










-
+

+
-
+
+
+

-
+









-
+



-
+




-
+




-
+





-
+




-
+




-
+





-
+




-
+





-
+




-
+




-
+







-
+






-
+




-
+





-
+















-
+




-
+





-
+




-
+

+
+
+
+
+
-
+
+



-
+

-
+







-
+

-
-
-
+
+
+


-
+


-
-
+
+

-
-
-
-
+
+
+
+


-
+



-
+





-
+


-
+


-
+




-
+

-
+




-
+

-
-
-
+
+
+





-
-
+
+

-
-
-
-
+
+
+
+


-
+



-
+






-
+


-
+


-
+





-
+

-
+






-
+

-
+





-
+

-
+


-
+





-
-
+
+

-
+



-
+


-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+



-
+

-
+

-
+


-
+

-
+

-
+


-
+

-
+

-
+


-
+

-
+

-
+


-
+

-
+

-
+


-
+

-
+

-
+



-
+

-
+

-
+


-
+

-
+

-
+





-
-
+
+






-
+
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 */

#import "OFObject.h"
#import "OFCharacterSet.h"
#import "OFSerialization.h"

OF_ASSUME_NONNULL_BEGIN

@class OFArray OF_GENERIC(ObjectType);
@class OFDictionary OF_GENERIC(KeyType, ObjectType);
@class OFNumber;
@class OFPair OF_GENERIC(FirstType, SecondType);
@class OFString;

/**
 * @class OFURI OFURI.h ObjFW/OFURI.h
 * @class OFIRI OFIRI.h ObjFW/OFIRI.h
 *
 * @brief A class for representing IRIs, URIs, URLs and URNs, for parsing them
 * @brief A class for parsing URIs as per RFC 3986 and accessing parts of it.
 *	  as well as accessing parts of them.
 *
 * This class follows RFC 3976 and RFC 3987.
 */
@interface OFURI: OFObject <OFCopying, OFMutableCopying, OFSerialization>
@interface OFIRI: OFObject <OFCopying, OFMutableCopying>
{
	OFString *_scheme;
	OFString *_Nullable _percentEncodedHost;
	OFNumber *_Nullable _port;
	OFString *_Nullable _percentEncodedUser;
	OFString *_Nullable _percentEncodedPassword;
	OFString *_percentEncodedPath;
	OFString *_Nullable _percentEncodedQuery;
	OFString *_Nullable _percentEncodedFragment;
	OF_RESERVE_IVARS(OFURI, 4)
	OF_RESERVE_IVARS(OFIRI, 4)
}

/**
 * @brief The scheme part of the URI.
 * @brief The scheme part of the IRI.
 */
@property (readonly, copy, nonatomic) OFString *scheme;

/**
 * @brief The host part of the URI.
 * @brief The host part of the IRI.
 */
@property OF_NULLABLE_PROPERTY (readonly, copy, nonatomic) OFString *host;

/**
 * @brief The host part of the URI in percent-encoded form.
 * @brief The host part of the IRI in percent-encoded form.
 */
@property OF_NULLABLE_PROPERTY (readonly, copy, nonatomic)
    OFString *percentEncodedHost;

/**
 * @brief The port part of the URI.
 * @brief The port part of the IRI.
 */
@property OF_NULLABLE_PROPERTY (readonly, copy, nonatomic) OFNumber *port;

/**
 * @brief The user part of the URI.
 * @brief The user part of the IRI.
 */
@property OF_NULLABLE_PROPERTY (readonly, copy, nonatomic) OFString *user;

/**
 * @brief The user part of the URI in percent-encoded form.
 * @brief The user part of the IRI in percent-encoded form.
 */
@property OF_NULLABLE_PROPERTY (readonly, copy, nonatomic)
    OFString *percentEncodedUser;

/**
 * @brief The password part of the URI.
 * @brief The password part of the IRI.
 */
@property OF_NULLABLE_PROPERTY (readonly, copy, nonatomic) OFString *password;

/**
 * @brief The password part of the URI in percent-encoded form.
 * @brief The password part of the IRI in percent-encoded form.
 */
@property OF_NULLABLE_PROPERTY (readonly, copy, nonatomic)
    OFString *percentEncodedPassword;

/**
 * @brief The path part of the URI.
 * @brief The path part of the IRI.
 */
@property (readonly, copy, nonatomic) OFString *path;

/**
 * @brief The path part of the URI in percent-encoded form.
 * @brief The path part of the IRI in percent-encoded form.
 */
@property (readonly, copy, nonatomic) OFString *percentEncodedPath;

/**
 * @brief The path of the URI split into components.
 * @brief The path of the IRI split into components.
 *
 * The first component must always be `/` to designate the root.
 */
@property (readonly, copy, nonatomic)
    OFArray OF_GENERIC(OFString *) *pathComponents;

/**
 * @brief The last path component of the URI.
 * @brief The last path component of the IRI.
 *
 * Returns the empty string if the path is the root.
 */
@property (readonly, copy, nonatomic) OFString *lastPathComponent;

/**
 * @brief The query part of the URI.
 * @brief The query part of the IRI.
 */
@property OF_NULLABLE_PROPERTY (readonly, copy, nonatomic) OFString *query;

/**
 * @brief The query part of the URI in percent-encoded form.
 * @brief The query part of the IRI in percent-encoded form.
 */
@property OF_NULLABLE_PROPERTY (readonly, copy, nonatomic)
    OFString *percentEncodedQuery;

/**
 * @brief The query part of the URI as an array.
 * @brief The query part of the IRI as an array.
 *
 * For example, a query like `key1=value1&key2=value2` would correspond to the
 * following array:
 *
 *     @[
 *         [OFPair pairWithFirstObject: @"key1" secondObject: @"value1"],
 *         [OFPair pairWithFirstObject: @"key2" secondObject: @"value2"],
 *     ]
 *
 * @throw OFInvalidFormatException The query is not in the correct format
 */
@property OF_NULLABLE_PROPERTY (readonly, copy, nonatomic)
    OFArray OF_GENERIC(OFPair OF_GENERIC(OFString *, OFString *) *) *queryItems;

/**
 * @brief The fragment part of the URI.
 * @brief The fragment part of the IRI.
 */
@property OF_NULLABLE_PROPERTY (readonly, copy, nonatomic) OFString *fragment;

/**
 * @brief The fragment part of the URI in URI-encoded form.
 * @brief The fragment part of the IRI in percent-encoded form.
 */
@property OF_NULLABLE_PROPERTY (readonly, copy, nonatomic)
    OFString *percentEncodedFragment;

/**
 * @brief The URI as a string.
 * @brief The IRI as a string.
 */
@property (readonly, nonatomic) OFString *string;

/**
 * @brief The URI with relative subpaths resolved.
 * @brief The IRI with relative subpaths resolved.
 */
@property (readonly, nonatomic) OFIRI *IRIByStandardizingPath;

/**
 * @brief The IRI with percent-encoding added for all Unicode characters.
 */
@property (readonly, nonatomic) OFURI *URIByStandardizingPath;
@property (readonly, nonatomic)
    OFIRI *IRIByAddingPercentEncodingForUnicodeCharacters;

#ifdef OF_HAVE_FILES
/**
 * @brief The local file system representation for a file URI.
 * @brief The local file system representation for a file IRI.
 *
 * @note This only exists for URIs with the file scheme and throws an exception
 * @note This only exists for IRIs with the file scheme and throws an exception
 *	 otherwise.
 */
@property OF_NULLABLE_PROPERTY (readonly, nonatomic)
    OFString *fileSystemRepresentation;
#endif

/**
 * @brief Creates a new URI with the specified string.
 * @brief Creates a new IRI with the specified string.
 *
 * @param string A string describing a URI
 * @return A new, autoreleased OFURI
 * @throw OFInvalidFormatException The specified string is not a valid URI
 * @param string A string describing an IRI
 * @return A new, autoreleased OFIRI
 * @throw OFInvalidFormatException The specified string is not a valid IRI
 *				   string
 */
+ (instancetype)URIWithString: (OFString *)string;
+ (instancetype)IRIWithString: (OFString *)string;

/**
 * @brief Creates a new URI with the specified string relative to the
 *	  specified URI.
 * @brief Creates a new IRI with the specified string relative to the
 *	  specified IRI.
 *
 * @param string A string describing a relative or absolute URI
 * @param URI An URI to which the string is relative
 * @return A new, autoreleased OFURI
 * @throw OFInvalidFormatException The specified string is not a valid URI
 * @param string A string describing a relative or absolute IRI
 * @param IRI An IRI to which the string is relative
 * @return A new, autoreleased OFIRI
 * @throw OFInvalidFormatException The specified string is not a valid IRI
 *				   string
 */
+ (instancetype)URIWithString: (OFString *)string relativeToURI: (OFURI *)URI;
+ (instancetype)IRIWithString: (OFString *)string relativeToIRI: (OFIRI *)IRI;

#ifdef OF_HAVE_FILES
/**
 * @brief Creates a new URI with the specified local file path.
 * @brief Creates a new IRI with the specified local file path.
 *
 * If a directory exists at the specified path, a slash is appended if there is
 * no slash yet.
 *
 * @param path The local file path
 * @return A new, autoreleased OFURI
 * @return A new, autoreleased OFIRI
 * @throw OFInvalidFormatException The specified path is not a valid path
 */
+ (instancetype)fileURIWithPath: (OFString *)path;
+ (instancetype)fileIRIWithPath: (OFString *)path;

/**
 * @brief Creates a new URI with the specified local file path.
 * @brief Creates a new IRI with the specified local file path.
 *
 * @param path The local file path
 * @param isDirectory Whether the path is a directory, in which case a slash is
 *		      appened if there is no slash yet
 * @return An initialized OFURI
 * @return An initialized OFIRI
 */
+ (instancetype)fileURIWithPath: (OFString *)path
+ (instancetype)fileIRIWithPath: (OFString *)path
		    isDirectory: (bool)isDirectory;
#endif

/**
 * @brief Initializes an already allocated OFURI with the specified string.
 * @brief Initializes an already allocated OFIRI with the specified string.
 *
 * @param string A string describing a URI
 * @return An initialized OFURI
 * @throw OFInvalidFormatException The specified string is not a valid URI
 * @param string A string describing an IRI
 * @return An initialized OFIRI
 * @throw OFInvalidFormatException The specified string is not a valid IRI
 *				   string
 */
- (instancetype)initWithString: (OFString *)string;

/**
 * @brief Initializes an already allocated OFURI with the specified string and
 *	  relative URI.
 * @brief Initializes an already allocated OFIRI with the specified string and
 *	  relative IRI.
 *
 * @param string A string describing a relative or absolute URI
 * @param URI A URI to which the string is relative
 * @return An initialized OFURI
 * @throw OFInvalidFormatException The specified string is not a valid URI
 * @param string A string describing a relative or absolute IRI
 * @param IRI An IRI to which the string is relative
 * @return An initialized OFIRI
 * @throw OFInvalidFormatException The specified string is not a valid IRI
 *				   string
 */
- (instancetype)initWithString: (OFString *)string relativeToURI: (OFURI *)URI;
- (instancetype)initWithString: (OFString *)string relativeToIRI: (OFIRI *)IRI;

#ifdef OF_HAVE_FILES
/**
 * @brief Initializes an already allocated OFURI with the specified local file
 * @brief Initializes an already allocated OFIRI with the specified local file
 *	  path.
 *
 * If a directory exists at the specified path, a slash is appended if there is
 * no slash yet.
 *
 * @param path The local file path
 * @return An initialized OFURI
 * @return An initialized OFIRI
 * @throw OFInvalidFormatException The specified path is not a valid path
 */
- (instancetype)initFileURIWithPath: (OFString *)path;
- (instancetype)initFileIRIWithPath: (OFString *)path;

/**
 * @brief Initializes an already allocated OFURI with the specified local file
 * @brief Initializes an already allocated OFIRI with the specified local file
 *	  path.
 *
 * @param path The local file path
 * @param isDirectory Whether the path is a directory, in which case a slash is
 *		      appened if there is no slash yet
 * @return An initialized OFURI
 * @return An initialized OFIRI
 */
- (instancetype)initFileURIWithPath: (OFString *)path
- (instancetype)initFileIRIWithPath: (OFString *)path
			isDirectory: (bool)isDirectory;
#endif

- (instancetype)init OF_UNAVAILABLE;

/**
 * @brief Returns a new URI with the specified path component appended.
 * @brief Returns a new IRI with the specified path component appended.
 *
 * If the URI is a file URI, the file system is queried whether the appended
 * If the IRI is a file IRI, the file system is queried whether the appended
 * component is a directory.
 *
 * @param component The path component to append. If it starts with the slash,
 *		    the component is not appended, but replaces the path
 *		    instead.
 * @return A new URI with the specified path component appended
 * @return A new IRI with the specified path component appended
 */
- (OFURI *)URIByAppendingPathComponent: (OFString *)component;
- (OFIRI *)IRIByAppendingPathComponent: (OFString *)component;

/**
 * @brief Returns a new URI with the specified path component appended.
 * @brief Returns a new IRI with the specified path component appended.
 *
 * @param component The path component to append. If it starts with the slash,
 *		    the component is not appended, but replaces the path
 *		    instead.
 * @param isDirectory Whether the appended component is a directory, meaning
 *		      that the URI path should have a trailing slash
 * @return A new URI with the specified path component appended
 *		      that the IRI path should have a trailing slash
 * @return A new IRI with the specified path component appended
 */
- (OFURI *)URIByAppendingPathComponent: (OFString *)component
- (OFIRI *)IRIByAppendingPathComponent: (OFString *)component
			   isDirectory: (bool)isDirectory;
@end

@interface OFCharacterSet (URICharacterSets)
@interface OFCharacterSet (IRICharacterSets)
#ifdef OF_HAVE_CLASS_PROPERTIES
@property (class, readonly, nonatomic)
    OFCharacterSet *URISchemeAllowedCharacterSet;
    OFCharacterSet *IRISchemeAllowedCharacterSet;
@property (class, readonly, nonatomic)
    OFCharacterSet *URIHostAllowedCharacterSet;
    OFCharacterSet *IRIHostAllowedCharacterSet;
@property (class, readonly, nonatomic)
    OFCharacterSet *URIUserAllowedCharacterSet;
    OFCharacterSet *IRIUserAllowedCharacterSet;
@property (class, readonly, nonatomic)
    OFCharacterSet *URIPasswordAllowedCharacterSet;
    OFCharacterSet *IRIPasswordAllowedCharacterSet;
@property (class, readonly, nonatomic)
    OFCharacterSet *URIPathAllowedCharacterSet;
    OFCharacterSet *IRIPathAllowedCharacterSet;
@property (class, readonly, nonatomic)
    OFCharacterSet *URIQueryAllowedCharacterSet;
    OFCharacterSet *IRIQueryAllowedCharacterSet;
@property (class, readonly, nonatomic)
    OFCharacterSet *URIQueryKeyValueAllowedCharacterSet;
    OFCharacterSet *IRIQueryKeyValueAllowedCharacterSet;
@property (class, readonly, nonatomic)
    OFCharacterSet *URIFragmentAllowedCharacterSet;
    OFCharacterSet *IRIFragmentAllowedCharacterSet;
#endif

/**
 * @brief Returns the characters allowed in the scheme part of a URI.
 * @brief Returns the characters allowed in the scheme part of an IRI.
 *
 * @return The characters allowed in the scheme part of a URI.
 * @return The characters allowed in the scheme part of an IRI.
 */
+ (OFCharacterSet *)URISchemeAllowedCharacterSet;
+ (OFCharacterSet *)IRISchemeAllowedCharacterSet;

/**
 * @brief Returns the characters allowed in the host part of a URI.
 * @brief Returns the characters allowed in the host part of an IRI.
 *
 * @return The characters allowed in the host part of a URI.
 * @return The characters allowed in the host part of an IRI.
 */
+ (OFCharacterSet *)URIHostAllowedCharacterSet;
+ (OFCharacterSet *)IRIHostAllowedCharacterSet;

/**
 * @brief Returns the characters allowed in the user part of a URI.
 * @brief Returns the characters allowed in the user part of an IRI.
 *
 * @return The characters allowed in the user part of a URI.
 * @return The characters allowed in the user part of an IRI.
 */
+ (OFCharacterSet *)URIUserAllowedCharacterSet;
+ (OFCharacterSet *)IRIUserAllowedCharacterSet;

/**
 * @brief Returns the characters allowed in the password part of a URI.
 * @brief Returns the characters allowed in the password part of an IRI.
 *
 * @return The characters allowed in the password part of a URI.
 * @return The characters allowed in the password part of an IRI.
 */
+ (OFCharacterSet *)URIPasswordAllowedCharacterSet;
+ (OFCharacterSet *)IRIPasswordAllowedCharacterSet;

/**
 * @brief Returns the characters allowed in the path part of a URI.
 * @brief Returns the characters allowed in the path part of an IRI.
 *
 * @return The characters allowed in the path part of a URI.
 * @return The characters allowed in the path part of an IRI.
 */
+ (OFCharacterSet *)URIPathAllowedCharacterSet;
+ (OFCharacterSet *)IRIPathAllowedCharacterSet;

/**
 * @brief Returns the characters allowed in the query part of a URI.
 * @brief Returns the characters allowed in the query part of an IRI.
 *
 * @return The characters allowed in the query part of a URI.
 * @return The characters allowed in the query part of an IRI.
 */
+ (OFCharacterSet *)URIQueryAllowedCharacterSet;
+ (OFCharacterSet *)IRIQueryAllowedCharacterSet;

/**
 * @brief Returns the characters allowed in a key/value in the query part of a
 *	  URI.
 *	  IRI.
 *
 * @return The characters allowed in a key/value in the query part of a URI.
 * @return The characters allowed in a key/value in the query part of an IRI.
 */
+ (OFCharacterSet *)URIQueryKeyValueAllowedCharacterSet;
+ (OFCharacterSet *)IRIQueryKeyValueAllowedCharacterSet;

/**
 * @brief Returns the characters allowed in the fragment part of a URI.
 * @brief Returns the characters allowed in the fragment part of an IRI.
 *
 * @return The characters allowed in the fragment part of a URI.
 * @return The characters allowed in the fragment part of an IRI.
 */
+ (OFCharacterSet *)URIFragmentAllowedCharacterSet;
+ (OFCharacterSet *)IRIFragmentAllowedCharacterSet;
@end

#ifdef __cplusplus
extern "C" {
#endif
extern bool OFURIIsIPv6Host(OFString *host);
extern void OFURIVerifyIsEscaped(OFString *, OFCharacterSet *, bool);
extern bool OFIRIIsIPv6Host(OFString *host);
extern void OFIRIVerifyIsEscaped(OFString *, OFCharacterSet *, bool);
#ifdef __cplusplus
}
#endif

OF_ASSUME_NONNULL_END

#import "OFMutableURI.h"
#import "OFMutableIRI.h"

Renamed and modified src/OFURI.m [fd812a6a57] to src/OFIRI.m [fdb5d156bf].

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
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
222
223
224
225
226
227
228

-
+


















-
+




-
+





-





-
+


-
+


-
+


-
+


-
+


-
+
+
+
+












-
-
-
-
-
+
+
+
+
+
+

-
+
-
-


-
+

-
+



-
+

-
-
+
+



-
+

-
-
+
+



-
+

-
-
+
+



-
+

-
-
+
+


+
+
+
+
+
+
+

-
+



















+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+




















-
+




+
+
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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"

#include <stdlib.h>
#include <string.h>

#import "OFURI.h"
#import "OFIRI.h"
#import "OFArray.h"
#import "OFDictionary.h"
#ifdef OF_HAVE_FILES
# import "OFFileManager.h"
# import "OFFileURIHandler.h"
# import "OFFileIRIHandler.h"
#endif
#import "OFNumber.h"
#import "OFOnce.h"
#import "OFPair.h"
#import "OFString.h"
#import "OFXMLElement.h"

#import "OFInvalidArgumentException.h"
#import "OFInvalidFormatException.h"
#import "OFOutOfMemoryException.h"

@interface OFURIAllowedCharacterSetBase: OFCharacterSet
@interface OFIRIAllowedCharacterSetBase: OFCharacterSet
@end

@interface OFURIAllowedCharacterSet: OFURIAllowedCharacterSetBase
@interface OFIRIAllowedCharacterSet: OFIRIAllowedCharacterSetBase
@end

@interface OFURISchemeAllowedCharacterSet: OFURIAllowedCharacterSetBase
@interface OFIRISchemeAllowedCharacterSet: OFIRIAllowedCharacterSetBase
@end

@interface OFURIPathAllowedCharacterSet: OFURIAllowedCharacterSetBase
@interface OFIRIPathAllowedCharacterSet: OFIRIAllowedCharacterSetBase
@end

@interface OFURIQueryOrFragmentAllowedCharacterSet: OFURIAllowedCharacterSetBase
@interface OFIRIQueryAllowedCharacterSet: OFIRIAllowedCharacterSetBase
@end

@interface OFURIQueryKeyValueAllowedCharacterSet: OFURIAllowedCharacterSetBase
@interface OFIRIQueryKeyValueAllowedCharacterSet: OFIRIAllowedCharacterSetBase
@end

@interface OFIRIFragmentAllowedCharacterSet: OFIRIAllowedCharacterSetBase
@end

OF_DIRECT_MEMBERS
@interface OFInvertedCharacterSetWithoutPercent: OFCharacterSet
{
	OFCharacterSet *_characterSet;
	bool (*_characterIsMember)(id, SEL, OFUnichar);
}

- (instancetype)initWithCharacterSet: (OFCharacterSet *)characterSet;
@end

static OFCharacterSet *URIAllowedCharacterSet = nil;
static OFCharacterSet *URISchemeAllowedCharacterSet = nil;
static OFCharacterSet *URIPathAllowedCharacterSet = nil;
static OFCharacterSet *URIQueryOrFragmentAllowedCharacterSet = nil;
static OFCharacterSet *URIQueryKeyValueAllowedCharacterSet = nil;
static OFCharacterSet *IRIAllowedCharacterSet = nil;
static OFCharacterSet *IRISchemeAllowedCharacterSet = nil;
static OFCharacterSet *IRIPathAllowedCharacterSet = nil;
static OFCharacterSet *IRIQueryAllowedCharacterSet = nil;
static OFCharacterSet *IRIQueryKeyValueAllowedCharacterSet = nil;
static OFCharacterSet *IRIFragmentAllowedCharacterSet = nil;

static OFOnceControl URIAllowedCharacterSetOnce = OFOnceControlInitValue;
static OFOnceControl IRIAllowedCharacterSetOnce = OFOnceControlInitValue;
static OFOnceControl URIQueryOrFragmentAllowedCharacterSetOnce =
    OFOnceControlInitValue;

static void
initURIAllowedCharacterSet(void)
initIRIAllowedCharacterSet(void)
{
	URIAllowedCharacterSet = [[OFURIAllowedCharacterSet alloc] init];
	IRIAllowedCharacterSet = [[OFIRIAllowedCharacterSet alloc] init];
}

static void
initURISchemeAllowedCharacterSet(void)
initIRISchemeAllowedCharacterSet(void)
{
	URISchemeAllowedCharacterSet =
	    [[OFURISchemeAllowedCharacterSet alloc] init];
	IRISchemeAllowedCharacterSet =
	    [[OFIRISchemeAllowedCharacterSet alloc] init];
}

static void
initURIPathAllowedCharacterSet(void)
initIRIPathAllowedCharacterSet(void)
{
	URIPathAllowedCharacterSet =
	    [[OFURIPathAllowedCharacterSet alloc] init];
	IRIPathAllowedCharacterSet =
	    [[OFIRIPathAllowedCharacterSet alloc] init];
}

static void
initURIQueryOrFragmentAllowedCharacterSet(void)
initIRIQueryAllowedCharacterSet(void)
{
	URIQueryOrFragmentAllowedCharacterSet =
	    [[OFURIQueryOrFragmentAllowedCharacterSet alloc] init];
	IRIQueryAllowedCharacterSet =
	    [[OFIRIQueryAllowedCharacterSet alloc] init];
}

static void
initURIQueryKeyValueAllowedCharacterSet(void)
initIRIQueryKeyValueAllowedCharacterSet(void)
{
	URIQueryKeyValueAllowedCharacterSet =
	    [[OFURIQueryKeyValueAllowedCharacterSet alloc] init];
	IRIQueryKeyValueAllowedCharacterSet =
	    [[OFIRIQueryKeyValueAllowedCharacterSet alloc] init];
}

static void
initIRIFragmentAllowedCharacterSet(void)
{
	IRIFragmentAllowedCharacterSet =
	    [[OFIRIFragmentAllowedCharacterSet alloc] init];
}

bool
OFURIIsIPv6Host(OFString *host)
OFIRIIsIPv6Host(OFString *host)
{
	const char *UTF8String = host.UTF8String;
	bool hasColon = false;

	while (*UTF8String != '\0') {
		if (!OFASCIIIsDigit(*UTF8String) && *UTF8String != ':' &&
		    (*UTF8String < 'a' || *UTF8String > 'f') &&
		    (*UTF8String < 'A' || *UTF8String > 'F'))
			return false;

		if (*UTF8String == ':')
			hasColon = true;

		UTF8String++;
	}

	return hasColon;
}

static bool
isUnicode(OFUnichar character)
{
	if (character >= 0xA0 && character <= 0xD7FF)
		return true;
	if (character >= 0xF900 && character <= 0xFDCF)
		return true;
	if (character >= 0xFDF0 && character <= 0xFFEF)
		return true;
	if (character >= 0x10000 && character <= 0x1FFFD)
		return true;
	if (character >= 0x20000 && character <= 0x2FFFD)
		return true;
	if (character >= 0x30000 && character <= 0x3FFFD)
		return true;
	if (character >= 0x40000 && character <= 0x4FFFD)
		return true;
	if (character >= 0x50000 && character <= 0x5FFFD)
		return true;
	if (character >= 0x60000 && character <= 0x6FFFD)
		return true;
	if (character >= 0x70000 && character <= 0x7FFFD)
		return true;
	if (character >= 0x80000 && character <= 0x8FFFD)
		return true;
	if (character >= 0x90000 && character <= 0x9FFFD)
		return true;
	if (character >= 0xA0000 && character <= 0xAFFFD)
		return true;
	if (character >= 0xB0000 && character <= 0xBFFFD)
		return true;
	if (character >= 0xC0000 && character <= 0xCFFFD)
		return true;
	if (character >= 0xD0000 && character <= 0xDFFFD)
		return true;
	if (character >= 0xE0000 && character <= 0xEFFFD)
		return true;

	return false;
}

static bool
isUnicodePrivate(OFUnichar character)
{
	if (character >= 0xE00 && character <= 0xF8FF)
		return true;
	if (character >= 0xF0000 && character <= 0xFFFFD)
		return true;
	if (character >= 0x100000 && character <= 0x10FFFD)
		return true;

	return false;
}

@implementation OFURIAllowedCharacterSetBase
@implementation OFIRIAllowedCharacterSetBase
- (instancetype)autorelease
{
	return self;
}

- (instancetype)retain
{
	return self;
}

- (void)release
{
}

- (unsigned int)retainCount
{
	return OFMaxRetainCount;
}
@end

@implementation OFURIAllowedCharacterSet
@implementation OFIRIAllowedCharacterSet
- (bool)characterIsMember: (OFUnichar)character
{
	if (character < CHAR_MAX && OFASCIIIsAlnum(character))
		return true;

	if (isUnicode(character))
		return true;

	switch (character) {
	case '-':
	case '.':
	case '_':
	case '~':
	case '!':
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
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







-
+
















-
+




+
+
+







		return true;
	default:
		return false;
	}
}
@end

@implementation OFURISchemeAllowedCharacterSet
@implementation OFIRISchemeAllowedCharacterSet
- (bool)characterIsMember: (OFUnichar)character
{
	if (character < CHAR_MAX && OFASCIIIsAlnum(character))
		return true;

	switch (character) {
	case '+':
	case '-':
	case '.':
		return true;
	default:
		return false;
	}
}
@end

@implementation OFURIPathAllowedCharacterSet
@implementation OFIRIPathAllowedCharacterSet
- (bool)characterIsMember: (OFUnichar)character
{
	if (character < CHAR_MAX && OFASCIIIsAlnum(character))
		return true;

	if (isUnicode(character))
		return true;

	switch (character) {
	case '-':
	case '.':
	case '_':
	case '~':
	case '!':
223
224
225
226
227
228
229
230

231
232
233
234



235
236
237
238
239
240
241
291
292
293
294
295
296
297

298
299
300
301
302
303
304
305
306
307
308
309
310
311
312







-
+




+
+
+







		return true;
	default:
		return false;
	}
}
@end

@implementation OFURIQueryOrFragmentAllowedCharacterSet
@implementation OFIRIQueryAllowedCharacterSet
- (bool)characterIsMember: (OFUnichar)character
{
	if (character < CHAR_MAX && OFASCIIIsAlnum(character))
		return true;

	if (isUnicode(character) || isUnicodePrivate(character))
		return true;

	switch (character) {
	case '-':
	case '.':
	case '_':
	case '~':
	case '!':
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
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
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







-
+




+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+








+







+







		return true;
	default:
		return false;
	}
}
@end

@implementation OFURIQueryKeyValueAllowedCharacterSet
@implementation OFIRIQueryKeyValueAllowedCharacterSet
- (bool)characterIsMember: (OFUnichar)character
{
	if (character < CHAR_MAX && OFASCIIIsAlnum(character))
		return true;

	if (isUnicode(character) || isUnicodePrivate(character))
		return true;

	switch (character) {
	case '-':
	case '.':
	case '_':
	case '~':
	case '!':
	case '$':
	case '\'':
	case '(':
	case ')':
	case '*':
	case '+':
	case ',':
	case ';':
	case ':':
	case '@':
	case '/':
	case '?':
		return true;
	default:
		return false;
	}
}
@end

@implementation OFIRIFragmentAllowedCharacterSet
- (bool)characterIsMember: (OFUnichar)character
{
	if (character < CHAR_MAX && OFASCIIIsAlnum(character))
		return true;

	if (isUnicode(character))
		return true;

	switch (character) {
	case '-':
	case '.':
	case '_':
	case '~':
	case '!':
	case '$':
	case '&':
	case '\'':
	case '(':
	case ')':
	case '*':
	case '+':
	case ',':
	case ';':
	case '=':
	case ':':
	case '@':
	case '/':
	case '?':
		return true;
	default:
		return false;
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
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
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
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
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

572
573
574
575
576
577
578
579







-
+
















-
-
+
+


-
+

-
+


-
+

-
+

-
+


-
+

-
+

-
+


-
+

-
+

-
+


-
+


-
+

-
+


-
+

-
-
+
+

-
+


-
+


-
+

-
+


-
+

-
-
+
+

-
+



-
-
+
+




-
+




-
+
-


-
+



-
+

-
+


-
-
+

-
+





-
+











-
-
+
+





-
-
+
+



-
+







{
	return (character != '%' && !_characterIsMember(_characterSet,
	    @selector(characterIsMember:), character));
}
@end

void
OFURIVerifyIsEscaped(OFString *string, OFCharacterSet *characterSet,
OFIRIVerifyIsEscaped(OFString *string, OFCharacterSet *characterSet,
    bool allowPercent)
{
	void *pool = objc_autoreleasePoolPush();

	if (allowPercent)
		characterSet = [[[OFInvertedCharacterSetWithoutPercent alloc]
		    initWithCharacterSet: characterSet] autorelease];
	else
		characterSet = characterSet.invertedSet;

	if ([string indexOfCharacterFromSet: characterSet] != OFNotFound)
		@throw [OFInvalidFormatException exception];

	objc_autoreleasePoolPop(pool);
}

@implementation OFCharacterSet (URICharacterSets)
+ (OFCharacterSet *)URISchemeAllowedCharacterSet
@implementation OFCharacterSet (IRICharacterSets)
+ (OFCharacterSet *)IRISchemeAllowedCharacterSet
{
	static OFOnceControl onceControl = OFOnceControlInitValue;
	OFOnce(&onceControl, initURISchemeAllowedCharacterSet);
	OFOnce(&onceControl, initIRISchemeAllowedCharacterSet);

	return URISchemeAllowedCharacterSet;
	return IRISchemeAllowedCharacterSet;
}

+ (OFCharacterSet *)URIHostAllowedCharacterSet
+ (OFCharacterSet *)IRIHostAllowedCharacterSet
{
	OFOnce(&URIAllowedCharacterSetOnce, initURIAllowedCharacterSet);
	OFOnce(&IRIAllowedCharacterSetOnce, initIRIAllowedCharacterSet);

	return URIAllowedCharacterSet;
	return IRIAllowedCharacterSet;
}

+ (OFCharacterSet *)URIUserAllowedCharacterSet
+ (OFCharacterSet *)IRIUserAllowedCharacterSet
{
	OFOnce(&URIAllowedCharacterSetOnce, initURIAllowedCharacterSet);
	OFOnce(&IRIAllowedCharacterSetOnce, initIRIAllowedCharacterSet);

	return URIAllowedCharacterSet;
	return IRIAllowedCharacterSet;
}

+ (OFCharacterSet *)URIPasswordAllowedCharacterSet
+ (OFCharacterSet *)IRIPasswordAllowedCharacterSet
{
	OFOnce(&URIAllowedCharacterSetOnce, initURIAllowedCharacterSet);
	OFOnce(&IRIAllowedCharacterSetOnce, initIRIAllowedCharacterSet);

	return URIAllowedCharacterSet;
	return IRIAllowedCharacterSet;
}

+ (OFCharacterSet *)URIPathAllowedCharacterSet
+ (OFCharacterSet *)IRIPathAllowedCharacterSet
{
	static OFOnceControl onceControl = OFOnceControlInitValue;
	OFOnce(&onceControl, initURIPathAllowedCharacterSet);
	OFOnce(&onceControl, initIRIPathAllowedCharacterSet);

	return URIPathAllowedCharacterSet;
	return IRIPathAllowedCharacterSet;
}

+ (OFCharacterSet *)URIQueryAllowedCharacterSet
+ (OFCharacterSet *)IRIQueryAllowedCharacterSet
{
	OFOnce(&URIQueryOrFragmentAllowedCharacterSetOnce,
	    initURIQueryOrFragmentAllowedCharacterSet);
	static OFOnceControl onceControl = OFOnceControlInitValue;
	OFOnce(&onceControl, initIRIQueryAllowedCharacterSet);

	return URIQueryOrFragmentAllowedCharacterSet;
	return IRIQueryAllowedCharacterSet;
}

+ (OFCharacterSet *)URIQueryKeyValueAllowedCharacterSet
+ (OFCharacterSet *)IRIQueryKeyValueAllowedCharacterSet
{
	static OFOnceControl onceControl = OFOnceControlInitValue;
	OFOnce(&onceControl, initURIQueryKeyValueAllowedCharacterSet);
	OFOnce(&onceControl, initIRIQueryKeyValueAllowedCharacterSet);

	return URIQueryKeyValueAllowedCharacterSet;
	return IRIQueryKeyValueAllowedCharacterSet;
}

+ (OFCharacterSet *)URIFragmentAllowedCharacterSet
+ (OFCharacterSet *)IRIFragmentAllowedCharacterSet
{
	OFOnce(&URIQueryOrFragmentAllowedCharacterSetOnce,
	    initURIQueryOrFragmentAllowedCharacterSet);
	static OFOnceControl onceControl = OFOnceControlInitValue;
	OFOnce(&onceControl, initIRIFragmentAllowedCharacterSet);

	return URIQueryOrFragmentAllowedCharacterSet;
	return IRIFragmentAllowedCharacterSet;
}
@end

@implementation OFURI
+ (instancetype)URI
@implementation OFIRI
+ (instancetype)IRI
{
	return [[[self alloc] init] autorelease];
}

+ (instancetype)URIWithString: (OFString *)string
+ (instancetype)IRIWithString: (OFString *)string
{
	return [[[self alloc] initWithString: string] autorelease];
}

+ (instancetype)URIWithString: (OFString *)string
+ (instancetype)IRIWithString: (OFString *)string relativeToIRI: (OFIRI *)IRI
		relativeToURI: (OFURI *)URI
{
	return [[[self alloc] initWithString: string
			       relativeToURI: URI] autorelease];
			       relativeToIRI: IRI] autorelease];
}

#ifdef OF_HAVE_FILES
+ (instancetype)fileURIWithPath: (OFString *)path
+ (instancetype)fileIRIWithPath: (OFString *)path
{
	return [[[self alloc] initFileURIWithPath: path] autorelease];
	return [[[self alloc] initFileIRIWithPath: path] autorelease];
}

+ (instancetype)fileURIWithPath: (OFString *)path
		    isDirectory: (bool)isDirectory
+ (instancetype)fileIRIWithPath: (OFString *)path isDirectory: (bool)isDirectory
{
	return [[[self alloc] initFileURIWithPath: path
	return [[[self alloc] initFileIRIWithPath: path
				      isDirectory: isDirectory] autorelease];
}
#endif

static void
parseUserInfo(OFURI *self, const char *UTF8String, size_t length)
parseUserInfo(OFIRI *self, const char *UTF8String, size_t length)
{
	const char *colon;

	if ((colon = memchr(UTF8String, ':', length)) != NULL) {
		self->_percentEncodedUser = [[OFString alloc]
		    initWithUTF8String: UTF8String
				length: colon - UTF8String];
		self->_percentEncodedPassword = [[OFString alloc]
		    initWithUTF8String: colon + 1
				length: length - (colon - UTF8String) - 1];

		OFURIVerifyIsEscaped(self->_percentEncodedPassword,
		    [OFCharacterSet URIPasswordAllowedCharacterSet], true);
		OFIRIVerifyIsEscaped(self->_percentEncodedPassword,
		    [OFCharacterSet IRIPasswordAllowedCharacterSet], true);
	} else
		self->_percentEncodedUser = [[OFString alloc]
		    initWithUTF8String: UTF8String
				length: length];

	OFURIVerifyIsEscaped(self->_percentEncodedUser,
	    [OFCharacterSet URIUserAllowedCharacterSet], true);
	OFIRIVerifyIsEscaped(self->_percentEncodedUser,
	    [OFCharacterSet IRIUserAllowedCharacterSet], true);
}

static void
parseHostPort(OFURI *self, const char *UTF8String, size_t length)
parseHostPort(OFIRI *self, const char *UTF8String, size_t length)
{
	OFString *portString;

	if (*UTF8String == '[') {
		const char *end = memchr(UTF8String, ']', length);

		if (end == NULL)
498
499
500
501
502
503
504
505
506


507
508
509
510
511
512
513
606
607
608
609
610
611
612


613
614
615
616
617
618
619
620
621







-
-
+
+







			    initWithUTF8String: UTF8String
					length: length];

			UTF8String += length;
			length = 0;
		}

		OFURIVerifyIsEscaped(self->_percentEncodedHost,
		    [OFCharacterSet URIHostAllowedCharacterSet], true);
		OFIRIVerifyIsEscaped(self->_percentEncodedHost,
		    [OFCharacterSet IRIHostAllowedCharacterSet], true);
	}

	if (length == 0)
		return;

	if (length <= 1 || *UTF8String != ':')
		@throw [OFInvalidFormatException exception];
525
526
527
528
529
530
531
532

533
534
535
536
537
538
539
633
634
635
636
637
638
639

640
641
642
643
644
645
646
647







-
+







		@throw [OFInvalidFormatException exception];

	self->_port = [[OFNumber alloc] initWithUnsignedShort:
	    (unsigned short)portString.unsignedLongLongValue];
}

static size_t
parseAuthority(OFURI *self, const char *UTF8String, size_t length)
parseAuthority(OFIRI *self, const char *UTF8String, size_t length)
{
	size_t ret;
	const char *slash, *at;

	if ((slash = memchr(UTF8String, '/', length)) != NULL)
		length = slash - UTF8String;

558
559
560
561
562
563
564
565
566


567
568
569
570
571
572
573
574
575
576
577


578
579
580
581
582
583
584
585
586


587
588
589
590
591
592
593
666
667
668
669
670
671
672


673
674
675
676
677
678
679
680
681
682
683


684
685
686
687
688
689
690
691
692


693
694
695
696
697
698
699
700
701







-
-
+
+









-
-
+
+







-
-
+
+







	const char *fragment, *query;

	if ((fragment = memchr(UTF8String, '#', length)) != NULL) {
		*fragmentString = [OFString
		    stringWithUTF8String: fragment + 1
				  length: length - (fragment - UTF8String) - 1];

		OFURIVerifyIsEscaped(*fragmentString,
		    [OFCharacterSet URIQueryAllowedCharacterSet], true);
		OFIRIVerifyIsEscaped(*fragmentString,
		    [OFCharacterSet IRIQueryAllowedCharacterSet], true);

		length = fragment - UTF8String;
	}

	if ((query = memchr(UTF8String, '?', length)) != NULL) {
		*queryString = [OFString
		    stringWithUTF8String: query + 1
				  length: length - (query - UTF8String) - 1];

		OFURIVerifyIsEscaped(*queryString,
		    [OFCharacterSet URIFragmentAllowedCharacterSet], true);
		OFIRIVerifyIsEscaped(*queryString,
		    [OFCharacterSet IRIFragmentAllowedCharacterSet], true);

		length = query - UTF8String;
	}

	*pathString = [OFString stringWithUTF8String: UTF8String
					      length: length];

	OFURIVerifyIsEscaped(*pathString,
	    [OFCharacterSet URIQueryAllowedCharacterSet], true);
	OFIRIVerifyIsEscaped(*pathString,
	    [OFCharacterSet IRIPathAllowedCharacterSet], true);
}

- (instancetype)initWithString: (OFString *)string
{
	self = [super init];

	@try {
601
602
603
604
605
606
607
608
609


610
611
612
613
614
615
616
709
710
711
712
713
714
715


716
717
718
719
720
721
722
723
724







-
-
+
+







		    colon - UTF8String < 1 || !OFASCIIIsAlpha(UTF8String[0]))
			@throw [OFInvalidFormatException exception];

		_scheme = [[[OFString stringWithUTF8String: UTF8String
						    length: colon - UTF8String]
		    lowercaseString] copy];

		OFURIVerifyIsEscaped(_scheme,
		    [OFCharacterSet URISchemeAllowedCharacterSet], false);
		OFIRIVerifyIsEscaped(_scheme,
		    [OFCharacterSet IRISchemeAllowedCharacterSet], false);

		length -= colon - UTF8String + 1;
		UTF8String = colon + 1;

		if (length >= 2 && UTF8String[0] == '/' &&
		    UTF8String[1] == '/') {
			size_t authorityLength;
690
691
692
693
694
695
696
697

698
699
700
701
702
703
704
798
799
800
801
802
803
804

805
806
807
808
809
810
811
812







-
+







	else
		[components replaceObjectAtIndex: components.count - 1
				      withObject: path];

	return [components componentsJoinedByString: @"/"];
}

- (instancetype)initWithString: (OFString *)string relativeToURI: (OFURI *)URI
- (instancetype)initWithString: (OFString *)string relativeToIRI: (OFIRI *)IRI
{
	bool absolute;

	@try {
		absolute = isAbsolute(string);
	} @catch (id e) {
		[self release];
713
714
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
746
747
748
749
750
751
752
753
754
755
756
757

758
759
760

761
762
763
764
765
766

767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783

784
785
786
787
788
789
790
791
792
793
794
795
796

797
798
799
800
801

802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819

820
821
822
823
824
825
826
827
828
829

830
831
832
833
834
835
836
821
822
823
824
825
826
827

828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847



848
849
850
851

852
853
854
855
856
857
858
859
860
861
862
863
864

865
866
867

868
869
870
871
872
873

874
875
876
877
878
879
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







-
+



















-
-
-
+
+
+

-
+












-
+


-
+





-
+
















-
+












-
+




-
+

















-
+









-
+







	@try {
		void *pool = objc_autoreleasePoolPush();
		const char *UTF8String = string.UTF8String;
		size_t length = string.UTF8StringLength;
		bool hasAuthority = false;
		OFString *path, *query = nil, *fragment = nil;

		_scheme = [URI->_scheme copy];
		_scheme = [IRI->_scheme copy];

		if (length >= 2 && UTF8String[0] == '/' &&
		    UTF8String[1] == '/') {
			size_t authorityLength;

			hasAuthority = true;

			UTF8String += 2;
			length -= 2;

			authorityLength = parseAuthority(self,
			    UTF8String, length);

			UTF8String += authorityLength;
			length -= authorityLength;

			if (length > 0)
				OFEnsure(UTF8String[0] == '/');
		} else {
			_percentEncodedHost = [URI->_percentEncodedHost copy];
			_port = [URI->_port copy];
			_percentEncodedUser = [URI->_percentEncodedUser copy];
			_percentEncodedHost = [IRI->_percentEncodedHost copy];
			_port = [IRI->_port copy];
			_percentEncodedUser = [IRI->_percentEncodedUser copy];
			_percentEncodedPassword =
			    [URI->_percentEncodedPassword copy];
			    [IRI->_percentEncodedPassword copy];
		}

		parsePathQueryFragment(UTF8String, length,
		    &path, &query, &fragment);
		_percentEncodedFragment = [fragment copy];

		if (hasAuthority) {
			_percentEncodedPath = [path copy];
			_percentEncodedQuery = [query copy];
		} else {
			if (path.length == 0) {
				_percentEncodedPath =
				    [URI->_percentEncodedPath copy];
				    [IRI->_percentEncodedPath copy];
				_percentEncodedQuery = (query != nil
				    ? [query copy]
				    : [URI->_percentEncodedQuery copy]);
				    : [IRI->_percentEncodedQuery copy]);
			} else {
				if ([path hasPrefix: @"/"])
					_percentEncodedPath = [path copy];
				else
					_percentEncodedPath = [merge(
					    URI->_percentEncodedPath, path)
					    IRI->_percentEncodedPath, path)
					    copy];

				_percentEncodedQuery = [query copy];
			}
		}

		objc_autoreleasePoolPop(pool);
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

#ifdef OF_HAVE_FILES
- (instancetype)initFileURIWithPath: (OFString *)path
- (instancetype)initFileIRIWithPath: (OFString *)path
{
	bool isDirectory;

	@try {
		void *pool = objc_autoreleasePoolPush();
		isDirectory = [path of_isDirectoryPath];
		objc_autoreleasePoolPop(pool);
	} @catch (id e) {
		[self release];
		@throw e;
	}

	self = [self initFileURIWithPath: path isDirectory: isDirectory];
	self = [self initFileIRIWithPath: path isDirectory: isDirectory];

	return self;
}

- (instancetype)initFileURIWithPath: (OFString *)path
- (instancetype)initFileIRIWithPath: (OFString *)path
			isDirectory: (bool)isDirectory
{
	self = [super init];

	@try {
		void *pool = objc_autoreleasePoolPush();
		OFString *percentEncodedHost = nil;

		if (!path.absolutePath) {
			OFString *currentDirectoryPath = [OFFileManager
			    defaultManager].currentDirectoryPath;

			path = [currentDirectoryPath
			    stringByAppendingPathComponent: path];
			path = path.stringByStandardizingPath;
		}

		path = [path of_pathToURIPathWithPercentEncodedHost:
		path = [path of_pathToIRIPathWithPercentEncodedHost:
		    &percentEncodedHost];
		_percentEncodedHost = [percentEncodedHost copy];

		if (isDirectory && ![path hasSuffix: @"/"])
			path = [path stringByAppendingString: @"/"];

		_scheme = @"file";
		_percentEncodedPath = [[path
		    stringByAddingPercentEncodingWithAllowedCharacters:
		    [OFCharacterSet URIPathAllowedCharacterSet]] copy];
		    [OFCharacterSet IRIPathAllowedCharacterSet]] copy];

		objc_autoreleasePoolPop(pool);
	} @catch (id e) {
		[self release];
		@throw e;
	}

844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
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
952
953
954
955
956
957
958























959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974

975
976
977
978
979

980
981
982

983
984

985
986


987
988
989

990
991


992
993
994


995
996
997

998
999


1000
1001
1002


1003
1004
1005
1006
1007
1008
1009
1010
1011







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
















-
+




-
+


-
+

-
+

-
-
+
+

-
+

-
-
+
+

-
-
+
+

-
+

-
-
+
+

-
-
+
+







}

- (instancetype)of_init
{
	return [super init];
}

- (instancetype)initWithSerialization: (OFXMLElement *)element
{
	void *pool = objc_autoreleasePoolPush();
	OFString *stringValue;

	@try {
		if (![element.name isEqual: self.className] ||
		    ![element.namespace isEqual: OFSerializationNS])
			@throw [OFInvalidArgumentException exception];

		stringValue = element.stringValue;
	} @catch (id e) {
		[self release];
		@throw e;
	}

	self = [self initWithString: stringValue];

	objc_autoreleasePoolPop(pool);

	return self;
}

- (void)dealloc
{
	[_scheme release];
	[_percentEncodedHost release];
	[_port release];
	[_percentEncodedUser release];
	[_percentEncodedPassword release];
	[_percentEncodedPath release];
	[_percentEncodedQuery release];
	[_percentEncodedFragment release];

	[super dealloc];
}

- (bool)isEqual: (id)object
{
	OFURI *URI;
	OFIRI *IRI;

	if (object == self)
		return true;

	if (![object isKindOfClass: [OFURI class]])
	if (![object isKindOfClass: [OFIRI class]])
		return false;

	URI = object;
	IRI = object;

	if (![URI->_scheme isEqual: _scheme])
	if (![IRI->_scheme isEqual: _scheme])
		return false;
	if (URI->_percentEncodedHost != _percentEncodedHost &&
	    ![URI->_percentEncodedHost isEqual: _percentEncodedHost])
	if (IRI->_percentEncodedHost != _percentEncodedHost &&
	    ![IRI->_percentEncodedHost isEqual: _percentEncodedHost])
		return false;
	if (URI->_port != _port && ![URI->_port isEqual: _port])
	if (IRI->_port != _port && ![IRI->_port isEqual: _port])
		return false;
	if (URI->_percentEncodedUser != _percentEncodedUser &&
	    ![URI->_percentEncodedUser isEqual: _percentEncodedUser])
	if (IRI->_percentEncodedUser != _percentEncodedUser &&
	    ![IRI->_percentEncodedUser isEqual: _percentEncodedUser])
		return false;
	if (URI->_percentEncodedPassword != _percentEncodedPassword &&
	    ![URI->_percentEncodedPassword isEqual: _percentEncodedPassword])
	if (IRI->_percentEncodedPassword != _percentEncodedPassword &&
	    ![IRI->_percentEncodedPassword isEqual: _percentEncodedPassword])
		return false;
	if (![URI->_percentEncodedPath isEqual: _percentEncodedPath])
	if (![IRI->_percentEncodedPath isEqual: _percentEncodedPath])
		return false;
	if (URI->_percentEncodedQuery != _percentEncodedQuery &&
	    ![URI->_percentEncodedQuery isEqual: _percentEncodedQuery])
	if (IRI->_percentEncodedQuery != _percentEncodedQuery &&
	    ![IRI->_percentEncodedQuery isEqual: _percentEncodedQuery])
		return false;
	if (URI->_percentEncodedFragment != _percentEncodedFragment &&
	    ![URI->_percentEncodedFragment isEqual: _percentEncodedFragment])
	if (IRI->_percentEncodedFragment != _percentEncodedFragment &&
	    ![IRI->_percentEncodedFragment isEqual: _percentEncodedFragment])
		return false;

	return true;
}

- (unsigned long)hash
{
950
951
952
953
954
955
956
957

958
959
960
961
962
963
964
1035
1036
1037
1038
1039
1040
1041

1042
1043
1044
1045
1046
1047
1048
1049







-
+







- (OFString *)host
{
	if ([_percentEncodedHost hasPrefix: @"["] &&
	    [_percentEncodedHost hasSuffix: @"]"]) {
		OFString *host = [_percentEncodedHost substringWithRange:
		    OFMakeRange(1, _percentEncodedHost.length - 2)];

		if (!OFURIIsIPv6Host(host))
		if (!OFIRIIsIPv6Host(host))
			@throw [OFInvalidArgumentException exception];

		return host;
	}

	return _percentEncodedHost.stringByRemovingPercentEncoding;
}
1011
1012
1013
1014
1015
1016
1017
1018

1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039

1040
1041
1042
1043
1044
1045
1046
1096
1097
1098
1099
1100
1101
1102

1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123

1124
1125
1126
1127
1128
1129
1130
1131







-
+




















-
+







#endif
	OFMutableArray *ret;
	size_t count;

#ifdef OF_HAVE_FILES
	if (isFile) {
		OFString *path = [_percentEncodedPath
		    of_URIPathToPathWithPercentEncodedHost: nil];
		    of_IRIPathToPathWithPercentEncodedHost: nil];
		ret = [[path.pathComponents mutableCopy] autorelease];

		if (![ret.firstObject isEqual: @"/"])
			[ret insertObject: @"/" atIndex: 0];
	} else
#endif
		ret = [[[_percentEncodedPath componentsSeparatedByString: @"/"]
		    mutableCopy] autorelease];

	count = ret.count;

	if (count > 0 && [ret.firstObject length] == 0)
		[ret replaceObjectAtIndex: 0 withObject: @"/"];

	for (size_t i = 0; i < count; i++) {
		OFString *component = [ret objectAtIndex: i];

#ifdef OF_HAVE_FILES
		if (isFile)
			component =
			    [component of_pathComponentToURIPathComponent];
			    [component of_pathComponentToIRIPathComponent];
#endif

		component = component.stringByRemovingPercentEncoding;
		[ret replaceObjectAtIndex: i withObject: component];
	}

	[ret makeImmutable];
1148
1149
1150
1151
1152
1153
1154
1155

1156
1157
1158
1159
1160
1161
1162
1233
1234
1235
1236
1237
1238
1239

1240
1241
1242
1243
1244
1245
1246
1247







-
+







- (id)copy
{
	return [self retain];
}

- (id)mutableCopy
{
	OFURI *copy = [[OFMutableURI alloc] initWithScheme: _scheme];
	OFIRI *copy = [[OFMutableIRI alloc] initWithScheme: _scheme];

	@try {
		copy->_percentEncodedHost = [_percentEncodedHost copy];
		copy->_port = [_port copy];
		copy->_percentEncodedUser = [_percentEncodedUser copy];
		copy->_percentEncodedPassword = [_percentEncodedPassword copy];
		copy->_percentEncodedPath = [_percentEncodedPath copy];
1214
1215
1216
1217
1218
1219
1220
1221

1222
1223
1224
1225
1226
1227
1228
1229
1230
1231

1232
1233
1234
1235
1236




1237
1238
1239

1240
1241
1242
1243
1244
1245




1246
1247
1248

1249
1250
1251
1252
1253































1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1299
1300
1301
1302
1303
1304
1305

1306
1307
1308
1309
1310
1311
1312
1313
1314
1315

1316
1317




1318
1319
1320
1321
1322
1323

1324
1325
1326




1327
1328
1329
1330
1331
1332

1333
1334




1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
















1373







-
+









-
+

-
-
-
-
+
+
+
+


-
+


-
-
-
-
+
+
+
+


-
+

-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

	if (![_scheme isEqual: @"file"])
		@throw [OFInvalidArgumentException exception];

	if (![_percentEncodedPath hasPrefix: @"/"])
		@throw [OFInvalidFormatException exception];

	path = [self.path
	    of_URIPathToPathWithPercentEncodedHost: _percentEncodedHost];
	    of_IRIPathToPathWithPercentEncodedHost: _percentEncodedHost];

	[path retain];

	objc_autoreleasePoolPop(pool);

	return [path autorelease];
}
#endif

- (OFURI *)URIByAppendingPathComponent: (OFString *)component
- (OFIRI *)IRIByAppendingPathComponent: (OFString *)component
{
	OFMutableURI *URI = [[self mutableCopy] autorelease];
	[URI appendPathComponent: component];
	[URI makeImmutable];
	return URI;
	OFMutableIRI *IRI = [[self mutableCopy] autorelease];
	[IRI appendPathComponent: component];
	[IRI makeImmutable];
	return IRI;
}

- (OFURI *)URIByAppendingPathComponent: (OFString *)component
- (OFIRI *)IRIByAppendingPathComponent: (OFString *)component
			   isDirectory: (bool)isDirectory
{
	OFMutableURI *URI = [[self mutableCopy] autorelease];
	[URI appendPathComponent: component isDirectory: isDirectory];
	[URI makeImmutable];
	return URI;
	OFMutableIRI *IRI = [[self mutableCopy] autorelease];
	[IRI appendPathComponent: component isDirectory: isDirectory];
	[IRI makeImmutable];
	return IRI;
}

- (OFURI *)URIByStandardizingPath
- (OFIRI *)IRIByStandardizingPath
{
	OFMutableURI *URI = [[self mutableCopy] autorelease];
	[URI standardizePath];
	[URI makeImmutable];
	return URI;
	OFMutableIRI *IRI = [[self mutableCopy] autorelease];
	[IRI standardizePath];
	[IRI makeImmutable];
	return IRI;
}

- (OFIRI *)IRIByAddingPercentEncodingForUnicodeCharacters
{
	OFMutableIRI *IRI = [[self mutableCopy] autorelease];
	void *pool = objc_autoreleasePoolPush();
	OFCharacterSet *ASCII =
	    [OFCharacterSet characterSetWithRange: OFMakeRange(0, 0x80)];

	IRI.percentEncodedHost = [_percentEncodedHost
	    stringByAddingPercentEncodingWithAllowedCharacters: ASCII];
	IRI.percentEncodedUser = [_percentEncodedUser
	    stringByAddingPercentEncodingWithAllowedCharacters: ASCII];
	IRI.percentEncodedPassword = [_percentEncodedPassword
	    stringByAddingPercentEncodingWithAllowedCharacters: ASCII];
	IRI.percentEncodedPath = [_percentEncodedPath
	    stringByAddingPercentEncodingWithAllowedCharacters: ASCII];
	IRI.percentEncodedQuery = [_percentEncodedQuery
	    stringByAddingPercentEncodingWithAllowedCharacters: ASCII];
	IRI.percentEncodedFragment = [_percentEncodedFragment
	    stringByAddingPercentEncodingWithAllowedCharacters: ASCII];

	[IRI makeImmutable];

	objc_autoreleasePoolPop(pool);

	return IRI;
}

- (OFString *)description
{
	return [OFString stringWithFormat: @"<%@: %@>",
					   self.class, self.string];
}

- (OFXMLElement *)XMLElementBySerializing
{
	void *pool = objc_autoreleasePoolPush();
	OFXMLElement *element;

	element = [OFXMLElement elementWithName: self.className
				      namespace: OFSerializationNS
				    stringValue: self.string];

	[element retain];

	objc_autoreleasePoolPop(pool);

	return [element autorelease];
}
@end

Renamed and modified src/OFURIHandler.h [09864efcca] to src/OFIRIHandler.h [907c8f4d42].

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
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
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
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
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

-
+




















+

-
-
+
+


-
+

-
+

-
+


-
+



-
+

















-
+

-
-
+
+

-
+


-
+

-
+


















-
+

-
+







-
+




-
+

-
+


















-
+


-
+


-
+

-
-
+
+

+
+
+
+

-
+


-
+



-
-
+
+
+
+
+
+
+
+
+

-
+


-
+

-
-
+
+
+
+

-
+


-
+

-
-
+
+
+
+

-
+


-
+

-
+
+
+
+

-
+


-
+




-
-
+
+
+
+
+
+

-
+


-
+

-
+

-
+
+
+
+

-
+




-
+


-
+

-
-
+
+
+
+
+
+
+

-
+




-
+


-
+




-
+

+
+
+

-
+






-
+







-
+



+
+
+

-
+





-
+










+
+
+

+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 */

#import "OFFileManager.h"
#import "OFObject.h"
#import "OFString.h"

OF_ASSUME_NONNULL_BEGIN

@class OFArray OF_GENERIC(ObjectType);
@class OFData;
@class OFDate;
@class OFStream;
@class OFURI;
@class OFIRI;
@class OFStream;

/**
 * @class OFURIHandler OFURIHandler.h ObjFW/OFURIHandler.h
 * @class OFIRIHandler OFIRIHandler.h ObjFW/OFIRIHandler.h
 *
 * @brief A handler for a URI scheme.
 * @brief A handler for an IRI scheme.
 */
@interface OFURIHandler: OFObject
@interface OFIRIHandler: OFObject
{
	OFString *_scheme;
	OF_RESERVE_IVARS(OFURIHandler, 4)
	OF_RESERVE_IVARS(OFIRIHandler, 4)
}

/**
 * @brief The scheme this OFURIHandler handles.
 * @brief The scheme this OFIRIHandler handles.
 */
@property (readonly, nonatomic) OFString *scheme;

/**
 * @brief Registers the specified class as the handler for the specified scheme.
 *
 * If the same class is specified for two schemes, one instance of it is
 * created per scheme.
 *
 * @param class_ The class to register as the handler for the specified scheme
 * @param scheme The scheme for which to register the handler
 * @return Whether the class was successfully registered. If a handler for the
 *	   same scheme is already registered, registration fails.
 */
+ (bool)registerClass: (Class)class_ forScheme: (OFString *)scheme;

/**
 * @brief Returns the handler for the specified URI.
 * @brief Returns the handler for the specified IRI.
 *
 * @return The handler for the specified URI.
 * @throw OFUnsupportedProtocolException The specified URI is not supported
 * @return The handler for the specified IRI.
 * @throw OFUnsupportedProtocolException The specified IRI is not supported
 */
+ (OFURIHandler *)handlerForURI: (OFURI *)URI;
+ (OFIRIHandler *)handlerForIRI: (OFIRI *)IRI;

/**
 * @brief Opens the item at the specified URI.
 * @brief Opens the item at the specified IRI.
 *
 * @param URI The URI of the item which should be opened
 * @param IRI The IRI of the item which should be opened
 * @param mode The mode in which the file should be opened.@n
 *	       Possible modes are:
 *	       @n
 *	       Mode           | Description
 *	       ---------------|-------------------------------------
 *	       `r`            | Read-only
 *	       `r+`           | Read-write
 *	       `w`            | Write-only, create or truncate
 *	       `wx`           | Write-only, create or fail, exclusive
 *	       `w+`           | Read-write, create or truncate
 *	       `w+x`          | Read-write, create or fail, exclusive
 *	       `a`            | Write-only, create or append
 *	       `a+`           | Read-write, create or append
 *	       @n
 *	       The handler is allowed to not implement all modes and is also
 *	       allowed to implement additional, scheme-specific modes.
 * @return The opened stream if it was successfully opened
 * @throw OFOpenItemFailedException Opening the item failed
 * @throw OFUnsupportedProtocolException The specified URI is not supported
 * @throw OFUnsupportedProtocolException The specified IRI is not supported
 */
+ (OFStream *)openItemAtURI: (OFURI *)URI mode: (OFString *)mode;
+ (OFStream *)openItemAtIRI: (OFIRI *)IRI mode: (OFString *)mode;

- (instancetype)init OF_UNAVAILABLE;

/**
 * @brief Initializes the handler for the specified scheme.
 *
 * @param scheme The scheme to initialize for
 * @return An initialized URI handler
 * @return An initialized IRI handler
 */
- (instancetype)initWithScheme: (OFString *)scheme OF_DESIGNATED_INITIALIZER;

/**
 * @brief Opens the item at the specified URI.
 * @brief Opens the item at the specified IRI.
 *
 * @param URI The URI of the item which should be opened
 * @param IRI The IRI of the item which should be opened
 * @param mode The mode in which the file should be opened.@n
 *	       Possible modes are:
 *	       @n
 *	       Mode           | Description
 *	       ---------------|-------------------------------------
 *	       `r`            | Read-only
 *	       `r+`           | Read-write
 *	       `w`            | Write-only, create or truncate
 *	       `wx`           | Write-only, create or fail, exclusive
 *	       `w+`           | Read-write, create or truncate
 *	       `w+x`          | Read-write, create or fail, exclusive
 *	       `a`            | Write-only, create or append
 *	       `a+`           | Read-write, create or append
 *	       @n
 *	       The handler is allowed to not implement all modes and is also
 *	       allowed to implement additional, scheme-specific modes.
 * @return The opened stream if it was successfully opened
 * @throw OFOpenItemFailedException Opening the item failed
 * @throw OFUnsupportedProtocolException The specified URI is not supported by
 * @throw OFUnsupportedProtocolException The specified IRI is not supported by
 *					 the handler
 */
- (OFStream *)openItemAtURI: (OFURI *)URI mode: (OFString *)mode;
- (OFStream *)openItemAtIRI: (OFIRI *)IRI mode: (OFString *)mode;

/**
 * @brief Returns the attributes for the item at the specified URI.
 * @brief Returns the attributes for the item at the specified IRI.
 *
 * @param URI The URI to return the attributes for
 * @return A dictionary of attributes for the specified URI, with the keys of
 * @param IRI The IRI to return the attributes for
 * @return A dictionary of attributes for the specified IRI, with the keys of
 *	   type @ref OFFileAttributeKey
 * @throw OFGetItemAttributesFailedException Failed to get the attributes of
 *					     the item
 * @throw OFUnsupportedProtocolException The handler cannot handle the IRI's
 *					 scheme
 */
- (OFFileAttributes)attributesOfItemAtURI: (OFURI *)URI;
- (OFFileAttributes)attributesOfItemAtIRI: (OFIRI *)IRI;

/**
 * @brief Sets the attributes for the item at the specified URI.
 * @brief Sets the attributes for the item at the specified IRI.
 *
 * All attributes not part of the dictionary are left unchanged.
 *
 * @param attributes The attributes to set for the specified URI
 * @param URI The URI of the item to set the attributes for
 * @param attributes The attributes to set for the specified IRI
 * @param IRI The IRI of the item to set the attributes for
 * @@throw OFSetItemAttributesFailedException Failed to set the attributes of
 *					      the item
 * @throw OFUnsupportedProtocolException The handler cannot handle the IRI's
 *					 scheme
 * @throw OFNotImplementedException Setting one or more of the specified
 *				    attributes is not implemented for the
 *				    specified item
 */
- (void)setAttributes: (OFFileAttributes)attributes ofItemAtURI: (OFURI *)URI;
- (void)setAttributes: (OFFileAttributes)attributes ofItemAtIRI: (OFIRI *)IRI;

/**
 * @brief Checks whether a file exists at the specified URI.
 * @brief Checks whether a file exists at the specified IRI.
 *
 * @param URI The URI to check
 * @return A boolean whether there is a file at the specified URI
 * @param IRI The IRI to check
 * @return A boolean whether there is a file at the specified IRI
 * @throw OFUnsupportedProtocolException The handler cannot handle the IRI's
 *					 scheme
 */
- (bool)fileExistsAtURI: (OFURI *)URI;
- (bool)fileExistsAtIRI: (OFIRI *)IRI;

/**
 * @brief Checks whether a directory exists at the specified URI.
 * @brief Checks whether a directory exists at the specified IRI.
 *
 * @param URI The URI to check
 * @return A boolean whether there is a directory at the specified URI
 * @param IRI The IRI to check
 * @return A boolean whether there is a directory at the specified IRI
 * @throw OFUnsupportedProtocolException The handler cannot handle the IRI's
 *					 scheme
 */
- (bool)directoryExistsAtURI: (OFURI *)URI;
- (bool)directoryExistsAtIRI: (OFIRI *)IRI;

/**
 * @brief Creates a directory at the specified URI.
 * @brief Creates a directory at the specified IRI.
 *
 * @param URI The URI of the directory to create
 * @param IRI The IRI of the directory to create
 * @throw OFCreateDirectoryFailedException Creating the directory failed
 * @throw OFUnsupportedProtocolException The handler cannot handle the IRI's
 *					 scheme
 */
- (void)createDirectoryAtURI: (OFURI *)URI;
- (void)createDirectoryAtIRI: (OFIRI *)IRI;

/**
 * @brief Returns an array with the URIs of the items in the specified
 * @brief Returns an array with the IRIs of the items in the specified
 *	  directory.
 *
 * @note `.` and `..` are not part of the returned array.
 *
 * @param URI The URI to the directory whose items should be returned
 * @return An array with the URIs of the items in the specified directory
 * @param IRI The IRI to the directory whose items should be returned
 * @return An array with the IRIs of the items in the specified directory
 * @throw OFOpenItemFailedException Opening the directory failed
 * @throw OFReadFailedException Reading from the directory failed
 * @throw OFUnsupportedProtocolException The handler cannot handle the IRI's
 *					 scheme
 */
- (OFArray OF_GENERIC(OFURI *) *)contentsOfDirectoryAtURI: (OFURI *)URI;
- (OFArray OF_GENERIC(OFIRI *) *)contentsOfDirectoryAtIRI: (OFIRI *)IRI;

/**
 * @brief Removes the item at the specified URI.
 * @brief Removes the item at the specified IRI.
 *
 * If the item at the specified URI is a directory, it is removed recursively.
 * If the item at the specified IRI is a directory, it is removed recursively.
 *
 * @param URI The URI to the item which should be removed
 * @param IRI The IRI to the item which should be removed
 * @throw OFRemoveItemFailedException Removing the item failed
 * @throw OFUnsupportedProtocolException The handler cannot handle the IRI's
 *					 scheme
 */
- (void)removeItemAtURI: (OFURI *)URI;
- (void)removeItemAtIRI: (OFIRI *)IRI;

/**
 * @brief Creates a hard link for the specified item.
 *
 * The destination URI must have a full path, which means it must include the
 * The destination IRI must have a full path, which means it must include the
 * name of the item.
 *
 * This method is not available for all URIs.
 * This method is not available for all IRIs.
 *
 * @param source The URI to the item for which a link should be created
 * @param destination The URI to the item which should link to the source
 * @param source The IRI to the item for which a link should be created
 * @param destination The IRI to the item which should link to the source
 * @throw OFLinkItemFailedException Linking the item failed
 * @throw OFUnsupportedProtocolException The handler cannot handle the scheme
 *					 of one of the IRIs
 * @throw OFNotImplementedException Hardlinks are not implemented for the
 *				    specified IRI
 */
- (void)linkItemAtURI: (OFURI *)source toURI: (OFURI *)destination;
- (void)linkItemAtIRI: (OFIRI *)source toIRI: (OFIRI *)destination;

/**
 * @brief Creates a symbolic link for an item.
 *
 * The destination URI must have a full path, which means it must include the
 * The destination IRI must have a full path, which means it must include the
 * name of the item.
 *
 * This method is not available for all URIs.
 * This method is not available for all IRIs.
 *
 * @note On Windows, this requires at least Windows Vista and administrator
 *	 privileges!
 *
 * @param URI The URI to the item which should symbolically link to the target
 * @param IRI The IRI to the item which should symbolically link to the target
 * @param target The target of the symbolic link
 * @throw OFCreateSymbolicLinkFailed Creating a symbolic link failed
 * @throw OFUnsupportedProtocolException The handler cannot handle the IRI's
 *					 scheme
 */
- (void)createSymbolicLinkAtURI: (OFURI *)URI
- (void)createSymbolicLinkAtIRI: (OFIRI *)IRI
	    withDestinationPath: (OFString *)target;

/**
 * @brief Tries to efficiently copy an item. If a copy would only be possible
 *	  by reading the entire item and then writing it, it returns false.
 *
 * The destination URI must have a full path, which means it must include the
 * The destination IRI must have a full path, which means it must include the
 * name of the item.
 *
 * If an item already exists, the copy operation fails. This is also the case
 * if a directory is copied and an item already exists in the destination
 * directory.
 *
 * @param source The file, directory or symbolic link to copy
 * @param destination The destination URI
 * @param destination The destination IRI
 * @return True if an efficient copy was performed, false if an efficient copy
 *	   was not possible. Note that errors while performing a copy are
 *	   reported via exceptions and not by returning false!
 * @throw OFCopyItemFailedException Copying failed
 * @throw OFUnsupportedProtocolException The handler cannot handle the IRI's
 *					 scheme
 */
- (bool)copyItemAtURI: (OFURI *)source toURI: (OFURI *)destination;
- (bool)copyItemAtIRI: (OFIRI *)source toIRI: (OFIRI *)destination;

/**
 * @brief Tries to efficiently move an item. If a move would only be possible
 *	  by copying the source and deleting it, it returns false.
 *
 * The destination URI must have a full path, which means it must include the
 * The destination IRI must have a full path, which means it must include the
 * name of the item.
 *
 * If the destination is on a different logical device or uses a different
 * scheme, an efficient move is not possible and false is returned.
 *
 * @param source The item to rename
 * @param destination The new name for the item
 * @return True if an efficient move was performed, false if an efficient move
 *	   was not possible. Note that errors while performing a move are
 *	   reported via exceptions and not by returning false!
 * @throw OFMoveItemFailedException Moving failed
 * @throw OFUnsupportedProtocolException The handler cannot handle the IRI's
 *					 scheme
 */
- (bool)moveItemAtIRI: (OFIRI *)source toIRI: (OFIRI *)destination;
- (bool)moveItemAtURI: (OFURI *)source toURI: (OFURI *)destination;

/**
 * @brief Returns the extended attribute data for the specified name of the
 *	  item at the specified IRI.
 *
 * This method is not available for all IRIs.
 *
 * @param name The name of the extended attribute
 * @param IRI The IRI of the item to return the extended attribute from
 * @throw OFGetItemAttributesFailedException Getting the extended attribute
 *					     failed
 * @throw OFUnsupportedProtocolException The handler cannot handle the IRI's
 *					 scheme
 * @throw OFNotImplementedException Getting extended attributes is not
 *				    implemented for the specified item
 */
- (OFData *)extendedAttributeDataForName: (OFString *)name
			     ofItemAtIRI: (OFIRI *)IRI;

/**
 * @brief Sets the extended attribute data for the specified name of the item
 *	  at the specified IRI.
 *
 * This method is not available for all IRIs.
 *
 * @param data The data for the extended attribute
 * @param name The name of the extended attribute
 * @param IRI The IRI of the item to set the extended attribute on
 * @throw OFSetItemAttributesFailedException Setting the extended attribute
 *					     failed
 * @throw OFUnsupportedProtocolException The handler cannot handle the IRI's
 *					 scheme
 * @throw OFNotImplementedException Setting extended attributes is not
 *				    implemented for the specified item
 */
- (void)setExtendedAttributeData: (OFData *)data
			 forName: (OFString *)name
		     ofItemAtIRI: (OFIRI *)IRI;

/**
 * @brief Removes the extended attribute for the specified name wof the item at
 *	  the specified IRI.
 *
 * This method is not available for all IRIs.
 *
 * @param name The name of the extended attribute to remove
 * @param IRI The IRI of the item to remove the extended attribute from
 * @throw OFSetItemAttributesFailedException Removing the extended attribute
 *					     failed
 * @throw OFUnsupportedProtocolException The handler cannot handle the IRI's
 *					 scheme
 * @throw OFNotImplementedException Removing extended attributes is not
 *				    implemented for the specified item
 */
- (void)removeExtendedAttributeForName: (OFString *)name
			   ofItemAtIRI: (OFIRI *)IRI;
@end

OF_ASSUME_NONNULL_END

Renamed and modified src/OFURIHandler.m [1cc8c8dac2] to src/OFIRIHandler.m [706a9b9e6c].

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
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

-
+















-
+

-
-
+
+





-
-
+
+

-
+


-
+




-
+










-
+




-
+








-
+


-
+


-
-
+
+

-
-
-
-
+
+
+
+








-
+



















-
+

-
+





-
+







-
+




-
+

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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 "OFURIHandler.h"
#import "OFIRIHandler.h"
#import "OFDictionary.h"
#import "OFNumber.h"
#import "OFURI.h"
#import "OFIRI.h"
#import "OFNumber.h"

#ifdef OF_HAVE_THREADS
# import "OFMutex.h"
#endif

#import "OFArchiveURIHandler.h"
#import "OFEmbeddedURIHandler.h"
#import "OFArchiveIRIHandler.h"
#import "OFEmbeddedIRIHandler.h"
#ifdef OF_HAVE_FILES
# import "OFFileURIHandler.h"
# import "OFFileIRIHandler.h"
#endif
#if defined(OF_HAVE_SOCKETS) && defined(OF_HAVE_THREADS)
# import "OFHTTPURIHandler.h"
# import "OFHTTPIRIHandler.h"
#endif

#import "OFUnsupportedProtocolException.h"

static OFMutableDictionary OF_GENERIC(OFString *, OFURIHandler *) *handlers;
static OFMutableDictionary OF_GENERIC(OFString *, OFIRIHandler *) *handlers;
#ifdef OF_HAVE_THREADS
static OFMutex *mutex;

static void
releaseMutex(void)
{
	[mutex release];
}
#endif

@implementation OFURIHandler
@implementation OFIRIHandler
@synthesize scheme = _scheme;

+ (void)initialize
{
	if (self != [OFURIHandler class])
	if (self != [OFIRIHandler class])
		return;

	handlers = [[OFMutableDictionary alloc] init];
#ifdef OF_HAVE_THREADS
	mutex = [[OFMutex alloc] init];
	atexit(releaseMutex);
#endif

	[self registerClass: [OFEmbeddedURIHandler class]
	[self registerClass: [OFEmbeddedIRIHandler class]
		  forScheme: @"embedded"];
#ifdef OF_HAVE_FILES
	[self registerClass: [OFFileURIHandler class] forScheme: @"file"];
	[self registerClass: [OFFileIRIHandler class] forScheme: @"file"];
#endif
#if defined(OF_HAVE_SOCKETS) && defined(OF_HAVE_THREADS)
	[self registerClass: [OFHTTPURIHandler class] forScheme: @"http"];
	[self registerClass: [OFHTTPURIHandler class] forScheme: @"https"];
	[self registerClass: [OFHTTPIRIHandler class] forScheme: @"http"];
	[self registerClass: [OFHTTPIRIHandler class] forScheme: @"https"];
#endif
	[self registerClass: [OFArchiveURIHandler class] forScheme: @"gzip"];
	[self registerClass: [OFArchiveURIHandler class] forScheme: @"lha"];
	[self registerClass: [OFArchiveURIHandler class] forScheme: @"tar"];
	[self registerClass: [OFArchiveURIHandler class] forScheme: @"zip"];
	[self registerClass: [OFArchiveIRIHandler class] forScheme: @"gzip"];
	[self registerClass: [OFArchiveIRIHandler class] forScheme: @"lha"];
	[self registerClass: [OFArchiveIRIHandler class] forScheme: @"tar"];
	[self registerClass: [OFArchiveIRIHandler class] forScheme: @"zip"];
}

+ (bool)registerClass: (Class)class forScheme: (OFString *)scheme
{
#ifdef OF_HAVE_THREADS
	[mutex lock];
	@try {
#endif
		OFURIHandler *handler;
		OFIRIHandler *handler;

		if ([handlers objectForKey: scheme] != nil)
			return false;

		handler = [[class alloc] initWithScheme: scheme];
		@try {
			[handlers setObject: handler forKey: scheme];
		} @finally {
			[handler release];
		}
#ifdef OF_HAVE_THREADS
	} @finally {
		[mutex unlock];
	}
#endif

	return true;
}

+ (OFURIHandler *)handlerForURI: (OFURI *)URI
+ (OFIRIHandler *)handlerForIRI: (OFIRI *)IRI
{
	OF_KINDOF(OFURIHandler *) handler;
	OF_KINDOF(OFIRIHandler *) handler;

#ifdef OF_HAVE_THREADS
	[mutex lock];
	@try {
#endif
		handler = [handlers objectForKey: URI.scheme];
		handler = [handlers objectForKey: IRI.scheme];
#ifdef OF_HAVE_THREADS
	} @finally {
		[mutex unlock];
	}
#endif

	if (handler == nil)
		@throw [OFUnsupportedProtocolException exceptionWithURI: URI];
		@throw [OFUnsupportedProtocolException exceptionWithIRI: IRI];

	return handler;
}

+ (OFStream *)openItemAtURI: (OFURI *)URI mode: (OFString *)mode
+ (OFStream *)openItemAtIRI: (OFIRI *)IRI mode: (OFString *)mode
{
	return [[self handlerForURI: URI] openItemAtURI: URI mode: mode];
	return [[self handlerForIRI: IRI] openItemAtIRI: IRI mode: mode];
}

- (instancetype)init
{
	OF_INVALID_INIT_METHOD
}

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
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







-
+




-
+




-
+




-
+




-
+




-
+




-
+




-
+




-
+




-
+





+
+
+
+
-
+
+




+
+
+
+
+
-
+
+
+
+

+
+
-
+
+
+
+
+


- (void)dealloc
{
	[_scheme release];

	[super dealloc];
}

- (OFStream *)openItemAtURI: (OFURI *)URI mode: (OFString *)mode
- (OFStream *)openItemAtIRI: (OFIRI *)IRI mode: (OFString *)mode
{
	OF_UNRECOGNIZED_SELECTOR
}

- (OFFileAttributes)attributesOfItemAtURI: (OFURI *)URI
- (OFFileAttributes)attributesOfItemAtIRI: (OFIRI *)IRI
{
	OF_UNRECOGNIZED_SELECTOR
}

- (void)setAttributes: (OFFileAttributes)attributes ofItemAtURI: (OFURI *)URI
- (void)setAttributes: (OFFileAttributes)attributes ofItemAtIRI: (OFIRI *)IRI
{
	OF_UNRECOGNIZED_SELECTOR
}

- (bool)fileExistsAtURI: (OFURI *)URI
- (bool)fileExistsAtIRI: (OFIRI *)IRI
{
	OF_UNRECOGNIZED_SELECTOR
}

- (bool)directoryExistsAtURI: (OFURI *)URI
- (bool)directoryExistsAtIRI: (OFIRI *)IRI
{
	OF_UNRECOGNIZED_SELECTOR
}

- (void)createDirectoryAtURI: (OFURI *)URI
- (void)createDirectoryAtIRI: (OFIRI *)IRI
{
	OF_UNRECOGNIZED_SELECTOR
}

- (OFArray OF_GENERIC(OFURI *) *)contentsOfDirectoryAtURI: (OFURI *)URI
- (OFArray OF_GENERIC(OFIRI *) *)contentsOfDirectoryAtIRI: (OFIRI *)IRI
{
	OF_UNRECOGNIZED_SELECTOR
}

- (void)removeItemAtURI: (OFURI *)URI
- (void)removeItemAtIRI: (OFIRI *)IRI
{
	OF_UNRECOGNIZED_SELECTOR
}

- (void)linkItemAtURI: (OFURI *)source toURI: (OFURI *)destination
- (void)linkItemAtIRI: (OFIRI *)source toIRI: (OFIRI *)destination
{
	OF_UNRECOGNIZED_SELECTOR
}

- (void)createSymbolicLinkAtURI: (OFURI *)destination
- (void)createSymbolicLinkAtIRI: (OFIRI *)destination
	    withDestinationPath: (OFString *)source
{
	OF_UNRECOGNIZED_SELECTOR
}

- (bool)copyItemAtIRI: (OFIRI *)source toIRI: (OFIRI *)destination
{
	return false;
}
- (bool)copyItemAtURI: (OFURI *)source toURI: (OFURI *)destination

- (bool)moveItemAtIRI: (OFIRI *)source toIRI: (OFIRI *)destination
{
	return false;
}

- (OFData *)extendedAttributeDataForName: (OFString *)name
			     ofItemAtIRI: (OFIRI *)IRI
{
	OF_UNRECOGNIZED_SELECTOR
}
- (bool)moveItemAtURI: (OFURI *)source toURI: (OFURI *)destination

- (void)setExtendedAttributeData: (OFData *)data
			 forName: (OFString *)name
		     ofItemAtIRI: (OFIRI *)IRI
{
	OF_UNRECOGNIZED_SELECTOR
}
	return false;

- (void)removeExtendedAttributeForName: (OFString *)name
			   ofItemAtIRI: (OFIRI *)IRI
{
	OF_UNRECOGNIZED_SELECTOR
}
@end

Modified src/OFInflate64Stream.h from [2f3dc057f8] to [95b4831491].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFInflate64Stream.m from [96e65e9055] to [d53c241e14].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFInflateStream.h from [fe62e030fd] to [4379fb100c].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFInflateStream.m from [a61e69ad62] to [2767dcbcf2].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFInvertedCharacterSet.h from [d4b8559d77] to [df83d3fc6a].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFInvertedCharacterSet.m from [1e78ebb0a4] to [997128430d].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFInvocation.h from [ab7d9433d5] to [ce48bec833].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFInvocation.m from [5937b080ad] to [9633190806].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFJSONRepresentation.h from [2bd85161f3] to [45a20e67ee].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFKernelEventObserver.h from [81efdafa0c] to [3a6c883edd].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFKernelEventObserver.m from [8d008316fd] to [65045f52e2].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
44
45
46
47
48
49
50

51

52
53
54
55
56
57
58
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60







+

+







#endif

#import "OFInitializationFailedException.h"
#import "OFInvalidArgumentException.h"
#import "OFOutOfRangeException.h"

#ifdef OF_AMIGAOS
# define Class IntuitionClass
# include <proto/exec.h>
# undef Class
#endif

@implementation OFKernelEventObserver
@synthesize delegate = _delegate;
#ifdef OF_AMIGAOS
@synthesize execSignalMask = _execSignalMask;
#endif

Modified src/OFKeyValueCoding.h from [3568d90874] to [d758bb12c8].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFKqueueKernelEventObserver.h from [79cac968ba] to [e0150163de].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFKqueueKernelEventObserver.m from [12f411060e] to [8ae46a5559].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFLHAArchive.h from [038ec719a6] to [7c1ac55459].

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
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

-
+




















-
-
+
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 */

#import "OFObject.h"
#import "OFKernelEventObserver.h"
#import "OFLHAArchiveEntry.h"
#import "OFString.h"

OF_ASSUME_NONNULL_BEGIN

@class OFStream;
@class OFURI;
@class OFIRI;
@class OFStream;

/**
 * @class OFLHAArchive OFLHAArchive.h ObjFW/OFLHAArchive.h
 *
 * @brief A class for accessing and manipulating LHA files.
 */
OF_SUBCLASSING_RESTRICTED
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
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







-
+





-
+


-
-
+
+


-
-
+
+


-
+







 * @return A new, autoreleased OFLHAArchive
 */
+ (instancetype)archiveWithStream: (OFStream *)stream mode: (OFString *)mode;

/**
 * @brief Creates a new OFLHAArchive object with the specified file.
 *
 * @param URI The URI to the LHA file
 * @param IRI The IRI to the LHA file
 * @param mode The mode for the LHA file. Valid modes are "r" for reading,
 *	       "w" for creating a new file and "a" for appending to an existing
 *	       archive.
 * @return A new, autoreleased OFLHAArchive
 */
+ (instancetype)archiveWithURI: (OFURI *)URI mode: (OFString *)mode;
+ (instancetype)archiveWithIRI: (OFIRI *)IRI mode: (OFString *)mode;

/**
 * @brief Creates a URI for accessing a the specified file within the specified
 *	  LHA archive.
 * @brief Creates an IRI for accessing a the specified file within the
 *	  specified LHA archive.
 *
 * @param path The path of the file within the archive
 * @param URI The URI of the archive
 * @return A URI for accessing the specified file within the specified LHA
 * @param IRI The IRI of the archive
 * @return An IRI for accessing the specified file within the specified LHA
 *	   archive
 */
+ (OFURI *)URIForFilePath: (OFString *)path inArchiveWithURI: (OFURI *)URI;
+ (OFIRI *)IRIForFilePath: (OFString *)path inArchiveWithIRI: (OFIRI *)IRI;

- (instancetype)init OF_UNAVAILABLE;

/**
 * @brief Initializes an already allocated OFLHAArchive object with the
 *	  specified stream.
 *
96
97
98
99
100
101
102
103

104
105
106
107
108
109

110
111
112
113
114
115
116
96
97
98
99
100
101
102

103
104
105
106
107
108

109
110
111
112
113
114
115
116







-
+





-
+







- (instancetype)initWithStream: (OFStream *)stream
			  mode: (OFString *)mode OF_DESIGNATED_INITIALIZER;

/**
 * @brief Initializes an already allocated OFLHAArchive object with the
 *	  specified file.
 *
 * @param URI The URI to the LHA file
 * @param IRI The IRI to the LHA file
 * @param mode The mode for the LHA file. Valid modes are "r" for reading,
 *	       "w" for creating a new file and "a" for appending to an existing
 *	       archive.
 * @return An initialized OFLHAArchive
 */
- (instancetype)initWithURI: (OFURI *)URI mode: (OFString *)mode;
- (instancetype)initWithIRI: (OFIRI *)IRI mode: (OFString *)mode;

/**
 * @brief Returns the next entry from the LHA archive or `nil` if all entries
 *	  have been read.
 *
 * @note This is only available in read mode.
 *

Modified src/OFLHAArchive.m from [fa04eb799a] to [9e5bf54c20].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
18
19
20
21
22
23
24
25

26


27
28
29
30
31
32
33
34
35
36
37
38
39
18
19
20
21
22
23
24

25
26
27
28
29
30
31
32


33
34
35
36
37
38
39







-
+

+
+




-
-







#include "config.h"

#include <errno.h>

#import "OFLHAArchive.h"
#import "OFLHAArchiveEntry.h"
#import "OFLHAArchiveEntry+Private.h"
#import "OFArchiveURIHandler.h"
#import "OFArchiveIRIHandler.h"
#import "OFCRC16.h"
#import "OFIRI.h"
#import "OFIRIHandler.h"
#import "OFLHADecompressingStream.h"
#import "OFSeekableStream.h"
#import "OFStream.h"
#import "OFString.h"
#import "OFURI.h"
#import "OFURIHandler.h"

#import "OFChecksumMismatchException.h"
#import "OFInvalidArgumentException.h"
#import "OFNotImplementedException.h"
#import "OFNotOpenException.h"
#import "OFOutOfRangeException.h"
#import "OFTruncatedDataException.h"
84
85
86
87
88
89
90
91

92
93

94
95
96

97
98

99
100
101
102
103
104
105
84
85
86
87
88
89
90

91
92

93
94
95

96
97

98
99
100
101
102
103
104
105







-
+

-
+


-
+

-
+







@synthesize encoding = _encoding;

+ (instancetype)archiveWithStream: (OFStream *)stream mode: (OFString *)mode
{
	return [[[self alloc] initWithStream: stream mode: mode] autorelease];
}

+ (instancetype)archiveWithURI: (OFURI *)URI mode: (OFString *)mode
+ (instancetype)archiveWithIRI: (OFIRI *)IRI mode: (OFString *)mode
{
	return [[[self alloc] initWithURI: URI mode: mode] autorelease];
	return [[[self alloc] initWithIRI: IRI mode: mode] autorelease];
}

+ (OFURI *)URIForFilePath: (OFString *)path inArchiveWithURI: (OFURI *)URI
+ (OFIRI *)IRIForFilePath: (OFString *)path inArchiveWithIRI: (OFIRI *)IRI
{
	return OFArchiveURIHandlerURIForFileInArchive(@"lha", path, URI);
	return OFArchiveIRIHandlerIRIForFileInArchive(@"lha", path, IRI);
}

- (instancetype)init
{
	OF_INVALID_INIT_METHOD
}

132
133
134
135
136
137
138
139

140
141
142
143
144
145
146

147
148

149
150
151
152
153
154
155
132
133
134
135
136
137
138

139
140
141
142
143
144
145

146
147

148
149
150
151
152
153
154
155







-
+






-
+

-
+







		[self release];
		@throw e;
	}

	return self;
}

- (instancetype)initWithURI: (OFURI *)URI mode: (OFString *)mode
- (instancetype)initWithIRI: (OFIRI *)IRI mode: (OFString *)mode
{
	void *pool = objc_autoreleasePoolPush();
	OFStream *stream;

	@try {
		if ([mode isEqual: @"a"])
			stream = [OFURIHandler openItemAtURI: URI mode: @"r+"];
			stream = [OFIRIHandler openItemAtIRI: IRI mode: @"r+"];
		else
			stream = [OFURIHandler openItemAtURI: URI mode: mode];
			stream = [OFIRIHandler openItemAtIRI: IRI mode: mode];
	} @catch (id e) {
		[self release];
		@throw e;
	}

	self = [self initWithStream: stream mode: mode];

171
172
173
174
175
176
177













178
179
180
181
182
183
184
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







+
+
+
+
+
+
+
+
+
+
+
+
+







- (OFLHAArchiveEntry *)nextEntry
{
	char header[21];
	size_t headerLen;

	if (_mode != modeRead)
		@throw [OFInvalidArgumentException exception];

	if (_currentEntry != nil && _lastReturnedStream == nil) {
		/*
		 * No read stream was created since the last call to
		 * -[nextEntry]. Create it so that we can properly skip the
		 *  data.
		 */
		void *pool = objc_autoreleasePoolPush();

		[self streamForReadingCurrentEntry];

		objc_autoreleasePoolPop(pool);
	}

	[_currentEntry release];
	_currentEntry = nil;

	[(OFLHAArchiveFileReadStream *)_lastReturnedStream of_skip];
	@try {
		[_lastReturnedStream close];
198
199
200
201
202
203
204
205

206
207
208
209
210
211
212
211
212
213
214
215
216
217

218
219
220
221
222
223
224
225







-
+







			@throw [OFTruncatedDataException exception];
		}

		headerLen += [_stream readIntoBuffer: header + headerLen
					      length: 21 - headerLen];
	}

	_currentEntry= [[OFLHAArchiveEntry alloc]
	_currentEntry = [[OFLHAArchiveEntry alloc]
	    of_initWithHeader: header
		       stream: _stream
		     encoding: _encoding];

	return _currentEntry;
}

Modified src/OFLHAArchiveEntry+Private.h from [521b95b2fc] to [481462ccc6].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFLHAArchiveEntry.h from [89ea23a8c1] to [3e354e177e].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFLHAArchiveEntry.m from [b338459827] to [1e7711c5fc].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFLHADecompressingStream.h from [1061027b73] to [825738c9bf].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFLHADecompressingStream.m from [c9a31f2d2f] to [a9c8d0ec12].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFList.h from [f2ae387af6] to [e9e426b5c4].

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
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

-
+
















-







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 */

#import "OFObject.h"
#import "OFCollection.h"
#import "OFEnumerator.h"
#import "OFSerialization.h"

OF_ASSUME_NONNULL_BEGIN

/** @file */

/*
 * Make clang's -Wdocumentation shut about about using @struct on someting it
77
78
79
80
81
82
83
84

85
86
87
88
89
90
91
92
76
77
78
79
80
81
82

83

84
85
86
87
88
89
90







-
+
-







#endif

/**
 * @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,
@interface OFList OF_GENERIC(ObjectType): OFObject <OFCopying, OFCollection>
    OFSerialization>
#if !defined(OF_HAVE_GENERICS) && !defined(DOXYGEN)
# define ObjectType id
#endif
{
	OFListItem _Nullable _firstListItem;
	OFListItem _Nullable _lastListItem;
	size_t _count;

Modified src/OFList.m from [f4144af409] to [9b79071582].

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
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

-
+



















-







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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"

#include <string.h>

#import "OFList.h"
#import "OFString.h"
#import "OFXMLElement.h"
#import "OFArray.h"

#import "OFEnumerationMutationException.h"
#import "OFInvalidArgumentException.h"

struct _OFListItem {
	struct _OFListItem *previous, *next;
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
64
65
66
67
68
69
70





























71
72
73
74
75
76
77







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







@synthesize firstListItem = _firstListItem, lastListItem = _lastListItem;

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

- (instancetype)initWithSerialization: (OFXMLElement *)element
{
	self = [self init];

	@try {
		void *pool = objc_autoreleasePoolPush();

		if (![element.name isEqual: self.className] ||
		    ![element.namespace isEqual: OFSerializationNS])
			@throw [OFInvalidArgumentException exception];

		for (OFXMLElement *child in
		    [element elementsForNamespace: OFSerializationNS]) {
			void *pool2 = objc_autoreleasePoolPush();

			[self appendObject: child.objectByDeserializing];

			objc_autoreleasePoolPop(pool2);
		}

		objc_autoreleasePoolPop(pool);
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (void)dealloc
{
	OFListItem next;

	for (OFListItem iter = _firstListItem; iter != NULL; iter = next) {
		[iter->object release];
		next = iter->next;
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
339
340
341
342
343
344
345


















346
347
348
349
350
351
352







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







	[ret appendString: @"\n]"];

	[ret makeImmutable];

	return ret;
}

- (OFXMLElement *)XMLElementBySerializing
{
	OFXMLElement *element =
	    [OFXMLElement elementWithName: self.className
				namespace: OFSerializationNS];

	for (OFListItem iter = _firstListItem;
	    iter != NULL; iter = iter->next) {
		void *pool = objc_autoreleasePoolPush();

		[element addChild: [iter->object XMLElementBySerializing]];

		objc_autoreleasePoolPop(pool);
	}

	return element;
}

- (int)countByEnumeratingWithState: (OFFastEnumerationState *)state
			   objects: (id *)objects
			     count: (int)count
{
	OFListItem listItem;

	memcpy(&listItem, state->extra, sizeof(listItem));

Modified src/OFLocale.h from [ca12b9c93f] to [231ed8a762].

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
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

-
+

















+
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 */

#import "OFObject.h"
#import "OFString.h"

OF_ASSUME_NONNULL_BEGIN

@class OFIRI;

/** @file */

/**
 * @def OF_LOCALIZED
 *
 * @brief Returns the localized string for the specified ID with the specified
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
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







-



-
+

-
+
-













-



-
+

-
+
-







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

#ifdef OF_HAVE_FILES
/**
 * @brief Adds a directory to scan for localizations.
 *
 * @param path The path to the directory to scan for localizations
 * @param IRI The IRI to the directory to scan for localizations
 */
+ (void)addLocalizationDirectory: (OFString *)path;
+ (void)addLocalizationDirectoryIRI: (OFIRI *)IRI;
#endif

/**
 * @brief Initializes the current OFLocale.
 *
 * @warning This sets the locale via `setlocale()`!
 *
 * @warning You should never call this yourself, except if you do not use
 *	    @ref OFApplication. In this case, you need to allocate exactly one
 *	    instance of OFLocale, which will become the current locale, and
 *	    call this method.
 */
- (instancetype)init;

#ifdef OF_HAVE_FILES
/**
 * @brief Adds a directory to scan for localizations.
 *
 * @param path The path to the directory to scan for localizations 
 * @param IRI The IRI to the directory to scan for localizations
 */
- (void)addLocalizationDirectory: (OFString *)path;
- (void)addLocalizationDirectoryIRI: (OFIRI *)IRI;
#endif

/**
 * @brief Returns the localized string for the specified ID, using the fallback
 *	  string if it cannot be looked up or is missing.
 *
 * @note This takes a variadic argument, terminated by `nil`, that consists of
 *	 pairs of variable names and variable values, which will be replaced

Modified src/OFLocale.m from [e8b5569b76] to [7cfd367431].

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
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

-
+


















-
-
-
+
+
+

+







+



+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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"

#include <locale.h>

#import "OFLocale.h"
#import "OFString.h"
#import "OFArray.h"
#import "OFDictionary.h"
#import "OFArray.h"
#import "OFDictionary.h"
#import "OFIRI.h"
#import "OFNumber.h"
#import "OFString.h"

#import "OFInitializationFailedException.h"
#import "OFInvalidArgumentException.h"
#import "OFInvalidFormatException.h"
#import "OFOpenItemFailedException.h"

#ifdef OF_AMIGAOS
# define Class IntuitionClass
# include <proto/dos.h>
# include <proto/exec.h>
# include <proto/locale.h>
# undef Class
#endif

static OFLocale *currentLocale = nil;
static OFDictionary *operatorPrecedences = nil;

#ifndef OF_AMIGAOS
static void
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
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







-
-
+

-
+

-













+
+
+

+







}

+ (OFString *)decimalSeparator
{
	return currentLocale.decimalSeparator;
}

#ifdef OF_HAVE_FILES
+ (void)addLocalizationDirectory: (OFString *)path
+ (void)addLocalizationDirectoryIRI: (OFIRI *)IRI
{
	[currentLocale addLocalizationDirectory: path];
	[currentLocale addLocalizationDirectoryIRI: IRI];
}
#endif

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

	@try {
#ifndef OF_AMIGAOS
		char *locale, *messagesLocale = NULL;

		if (currentLocale != nil)
			@throw [OFInitializationFailedException
			    exceptionWithClass: self.class];

# ifdef OF_MSDOS
		_encoding = OFStringEncodingCodepage437;
# else
		_encoding = OFStringEncodingUTF8;
# endif
		_decimalSeparator = @".";
		_localizedStrings = [[OFMutableArray alloc] init];

		if ((locale = setlocale(LC_ALL, "")) != NULL)
			_decimalSeparator = [[OFString alloc]
			    initWithCString: localeconv()->decimal_point
				   encoding: _encoding];
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
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







-
-
+


+
-
+







-
+

-
+







	[_countryCode release];
	[_decimalSeparator release];
	[_localizedStrings release];

	[super dealloc];
}

#ifdef OF_HAVE_FILES
- (void)addLocalizationDirectory: (OFString *)path
- (void)addLocalizationDirectoryIRI: (OFIRI *)IRI
{
	void *pool;
	OFIRI *mapIRI, *localizationIRI;
	OFString *mapPath, *languageCode, *countryCode, *localizationFile;
	OFString *languageCode, *countryCode, *localizationFile;
	OFDictionary *map;

	if (_languageCode == nil)
		return;

	pool = objc_autoreleasePoolPush();

	mapPath = [path stringByAppendingPathComponent: @"localizations.json"];
	mapIRI = [IRI IRIByAppendingPathComponent: @"localizations.json"];
	@try {
		map = [[OFString stringWithContentsOfFile: mapPath]
		map = [[OFString stringWithContentsOfIRI: mapIRI]
		     objectByParsingJSON];
	} @catch (OFOpenItemFailedException *e) {
		objc_autoreleasePoolPop(pool);
		return;
	}

	languageCode = _languageCode.lowercaseString;
528
529
530
531
532
533
534
535

536
537
538
539


540
541
542
543
544
545
546
547
548
549
550
533
534
535
536
537
538
539

540
541
542


543
544
545
546
547

548
549
550
551
552
553
554







-
+


-
-
+
+



-







		    objectForKey: @""];

	if (localizationFile == nil) {
		objc_autoreleasePoolPop(pool);
		return;
	}

	localizationFile = [path stringByAppendingPathComponent:
	localizationIRI = [IRI IRIByAppendingPathComponent:
	    [localizationFile stringByAppendingString: @".json"]];

	[_localizedStrings addObject: [[OFString stringWithContentsOfFile:
	    localizationFile] objectByParsingJSON]];
	[_localizedStrings addObject: [[OFString stringWithContentsOfIRI:
	    localizationIRI] objectByParsingJSON]];

	objc_autoreleasePoolPop(pool);
}
#endif

- (OFString *)localizedStringForID: (OFConstantString *)ID
			  fallback: (id)fallback, ...
{
	OFString *ret;
	va_list args;

Modified src/OFLocking.h from [155544ed9e] to [fb6e822d44].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFMD5Hash.h from [cdd5a3515e] to [2f12b2aa8f].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFMD5Hash.m from [190d96fa7c] to [f3d5c8a60c].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFMapTable+Private.h from [34b0bddd51] to [dd6291788e].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFMapTable.h from [382835ac81] to [0187aff28b].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFMapTable.m from [2885d27493] to [fd0add4a94].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFMapTableDictionary.h from [23bbcf2cb0] to [f2de5e0f29].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFMapTableDictionary.m from [509fe49186] to [7d4c6241d2].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
17
18
19
20
21
22
23

24
25
26
27
28
29
30







-








#import "OFMapTableDictionary.h"
#import "OFArray.h"
#import "OFMapTable+Private.h"
#import "OFMapTable.h"
#import "OFMutableMapTableDictionary.h"
#import "OFString.h"
#import "OFXMLElement.h"

#import "OFEnumerationMutationException.h"
#import "OFInvalidArgumentException.h"
#import "OFInvalidFormatException.h"

static void *
copy(void *object)
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
222
223
224
225
226
227
228





















































229
230
231
232
233
234
235







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







			[_mapTable setObject: object forKey: key];
		}
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (instancetype)initWithSerialization: (OFXMLElement *)element
{
	self = [super init];

	@try {
		void *pool = objc_autoreleasePoolPush();
		OFArray *keys, *objects;
		OFEnumerator *keyEnumerator, *objectEnumerator;
		OFXMLElement *keyElement, *objectElement;

		keys = [element elementsForName: @"key"
				      namespace: OFSerializationNS];
		objects = [element elementsForName: @"object"
					 namespace: OFSerializationNS];

		if (keys.count != objects.count)
			@throw [OFInvalidFormatException exception];

		_mapTable = [[OFMapTable alloc]
		    initWithKeyFunctions: keyFunctions
			 objectFunctions: objectFunctions
				capacity: keys.count];

		keyEnumerator = [keys objectEnumerator];
		objectEnumerator = [objects objectEnumerator];
		while ((keyElement = [keyEnumerator nextObject]) != nil &&
		    (objectElement = [objectEnumerator nextObject]) != nil) {
			void *pool2 = objc_autoreleasePoolPush();
			OFXMLElement *key, *object;

			key = [keyElement elementsForNamespace:
			    OFSerializationNS].firstObject;
			object = [objectElement elementsForNamespace:
			    OFSerializationNS].firstObject;

			if (key == nil || object == nil)
				@throw [OFInvalidFormatException exception];

			[_mapTable setObject: object.objectByDeserializing
				      forKey: key.objectByDeserializing];

			objc_autoreleasePoolPop(pool2);
		}

		objc_autoreleasePoolPop(pool);
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (void)dealloc
{
	[_mapTable release];

Modified src/OFMapTableSet.h from [1664d9d036] to [98f1d6ac4b].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFMapTableSet.m from [87bc750df2] to [c087e53711].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
18
19
20
21
22
23
24

25
26
27
28
29
30
31







-







#import "OFMapTableSet.h"
#import "OFArray.h"
#import "OFCountedMapTableSet.h"
#import "OFMapTable.h"
#import "OFMapTable+Private.h"
#import "OFMutableMapTableSet.h"
#import "OFString.h"
#import "OFXMLElement.h"

#import "OFInvalidArgumentException.h"
#import "OFEnumerationMutationException.h"

static void *
retain(void *object)
{
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
173
174
175
176
177
178
179































180
181
182
183
184
185
186







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







		while ((object = va_arg(arguments, id)) != nil)
			[_mapTable setObject: (void *)1 forKey: object];
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (instancetype)initWithSerialization: (OFXMLElement *)element
{
	self = [self init];

	@try {
		void *pool = objc_autoreleasePoolPush();

		if ((![element.name isEqual: @"OFSet"] &&
		    ![element.name isEqual: @"OFMutableSet"]) ||
		    ![element.namespace isEqual: OFSerializationNS])
			@throw [OFInvalidArgumentException exception];

		for (OFXMLElement *child in
		    [element elementsForNamespace: OFSerializationNS]) {
			void *pool2  = objc_autoreleasePoolPush();

			[_mapTable setObject: (void *)1
				      forKey: [child objectByDeserializing]];

			objc_autoreleasePoolPop(pool2);
		}

		objc_autoreleasePoolPop(pool);
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (void)dealloc
{
	[_mapTable release];

Added src/OFMatrix4x4.h version [c303f1010a].





























































































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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 */

#import "OFObject.h"

OF_ASSUME_NONNULL_BEGIN

/**
 * @brief A 4x4 matrix of floats.
 */
OF_SUBCLASSING_RESTRICTED
@interface OFMatrix4x4: OFObject <OFCopying>
{
	float _values[4][4];
}

#ifdef OF_HAVE_CLASS_PROPERTIES
@property (readonly, class) OFMatrix4x4 *identityMatrix;
#endif

/**
 * @brief A 2D array of the 4x4 floats of the matrix in row-major format.
 *
 * These may be modified directly.
 */
@property (readonly, nonatomic) float (*values)[4];

/**
 * @brief Returns the 4x4 identity matrix.
 */
+ (OFMatrix4x4 *)identityMatrix;

/**
 * @brief Creates a new 4x4 matrix with the specified values.
 *
 * @param values A 2D array of 4x4 floats in row-major format
 * @return A new, autoreleased OFMatrix4x4
 */
+ (instancetype)matrixWithValues: (const float [_Nonnull 4][4])values;

/**
 * @brief Initializes an already allocated 4x4 matrix with the specified values.
 *
 * @param values A 2D array of 4x4 floats in row-major format
 * @return An initialized OFMatrix4x4
 */
- (instancetype)initWithValues: (const float [_Nonnull 4][4])values;

/**
 * @brief Mulitplies the receiver with the specified matrix on the left side
 *	  and the receiver on the right side.
 *
 * @param matrix The matrix to multiply the receiver with
 */
- (void)multiplyWithMatrix: (OFMatrix4x4 *)matrix;

/**
 * @brief Translates the matrix with the specified vector.
 *
 * @param vector The vector to translate the matrix with
 */
- (void)translateWithVector: (OFVector3D)vector;

/**
 * @brief Scales the matrix with the specified vector.
 *
 * @param vector The vector to scale the matrix with
 */
- (void)scaleWithVector: (OFVector3D)vector;

/**
 * @brief Transforms the specified vector according to the matrix.
 *
 * @param vector The vector to transform
 * @return The transformed vector
 */
- (OFVector4D)transformedVector: (OFVector4D)vector;
@end

OF_ASSUME_NONNULL_END

Added src/OFMatrix4x4.m version [77a89afbe5].






















































































































































































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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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 "OFMatrix4x4.h"
#import "OFOnce.h"
#import "OFString.h"

static const float identityValues[4][4] = {
	{ 1, 0, 0, 0 },
	{ 0, 1, 0, 0 },
	{ 0, 0, 1, 0 },
	{ 0, 0, 0, 1 }
};

@implementation OFMatrix4x4
+ (OFMatrix4x4 *)identityMatrix
{
	return [[[OFMatrix4x4 alloc]
	    initWithValues: identityValues] autorelease];
}

+ (instancetype)matrixWithValues: (const float [4][4])values
{
	return [[[self alloc] initWithValues: values] autorelease];
}

- (instancetype)initWithValues: (const float [4][4])values
{
	self = [super init];

	memcpy(_values, values, sizeof(_values));

	return self;
}

- (float (*)[4])values
{
	return _values;
}

- (instancetype)copy
{
	return [[OFMatrix4x4 alloc]
	    initWithValues: (const float (*)[4])_values];
}

- (bool)isEqual: (OFMatrix4x4 *)matrix
{
	if (![matrix isKindOfClass: [OFMatrix4x4 class]])
		return false;

	return (memcmp(_values, matrix->_values, sizeof(_values)) == 0);
}

- (unsigned long)hash
{
	unsigned long hash;

	OFHashInit(&hash);

	for (uint_fast8_t i = 0; i < 4; i++)
		for (uint_fast8_t j = 0; j < 4; j++)
			OFHashAddHash(&hash, OFFloatToRawUInt32(_values[i][j]));

	OFHashFinalize(&hash);

	return hash;
}

- (void)multiplyWithMatrix: (OFMatrix4x4 *)matrix
{
	float right[4][4];
	memcpy(right, _values, sizeof(right));

#define left matrix->_values
	_values[0][0] = left[0][0] * right[0][0] + left[0][1] * right[1][0] +
	    left[0][2] * right[2][0] + left[0][3] * right[3][0];
	_values[0][1] = left[0][0] * right[0][1] + left[0][1] * right[1][1] +
	    left[0][2] * right[2][1] + left[0][3] * right[3][1];
	_values[0][2] = left[0][0] * right[0][2] + left[0][1] * right[1][2] +
	    left[0][2] * right[2][2] + left[0][3] * right[3][2];
	_values[0][3] = left[0][0] * right[0][3] + left[0][1] * right[1][3] +
	    left[0][2] * right[2][3] + left[0][3] * right[3][3];

	_values[1][0] = left[1][0] * right[0][0] + left[1][1] * right[1][0] +
	    left[1][2] * right[2][0] + left[1][3] * right[3][0];
	_values[1][1] = left[1][0] * right[0][1] + left[1][1] * right[1][1] +
	    left[1][2] * right[2][1] + left[1][3] * right[3][1];
	_values[1][2] = left[1][0] * right[0][2] + left[1][1] * right[1][2] +
	    left[1][2] * right[2][2] + left[1][3] * right[3][2];
	_values[1][3] = left[1][0] * right[0][3] + left[1][1] * right[1][3] +
	    left[1][2] * right[2][3] + left[1][3] * right[3][3];

	_values[2][0] = left[2][0] * right[0][0] + left[2][1] * right[1][0] +
	    left[2][2] * right[2][0] + left[2][3] * right[3][0];
	_values[2][1] = left[2][0] * right[0][1] + left[2][1] * right[1][1] +
	    left[2][2] * right[2][1] + left[2][3] * right[3][1];
	_values[2][2] = left[2][0] * right[0][2] + left[2][1] * right[1][2] +
	    left[2][2] * right[2][2] + left[2][3] * right[3][2];
	_values[2][3] = left[2][0] * right[0][3] + left[2][1] * right[1][3] +
	    left[2][2] * right[2][3] + left[2][3] * right[3][3];

	_values[3][0] = left[3][0] * right[0][0] + left[3][1] * right[1][0] +
	    left[3][2] * right[2][0] + left[3][3] * right[3][0];
	_values[3][1] = left[3][0] * right[0][1] + left[3][1] * right[1][1] +
	    left[3][2] * right[2][1] + left[3][3] * right[3][1];
	_values[3][2] = left[3][0] * right[0][2] + left[3][1] * right[1][2] +
	    left[3][2] * right[2][2] + left[3][3] * right[3][2];
	_values[3][3] = left[3][0] * right[0][3] + left[3][1] * right[1][3] +
	    left[3][2] * right[2][3] + left[3][3] * right[3][3];
#undef left
}

- (void)translateWithVector: (OFVector3D)vector
{
	OFMatrix4x4 *translation = [[OFMatrix4x4 alloc] initWithValues:
	    (const float [4][4]){
		{ 1, 0, 0, vector.x },
		{ 0, 1, 0, vector.y },
		{ 0, 0, 1, vector.z },
		{ 0, 0, 0, 1 }
	    }];
	[self multiplyWithMatrix: translation];
	[translation release];
}

- (void)scaleWithVector: (OFVector3D)vector
{
	OFMatrix4x4 *scale = [[OFMatrix4x4 alloc] initWithValues:
	    (const float [4][4]){
		{ vector.x, 0, 0, 0 },
		{ 0, vector.y, 0, 0 },
		{ 0, 0, vector.z, 0 },
		{ 0, 0, 0, 1 }
	    }];
	[self multiplyWithMatrix: scale];
	[scale release];
}

- (OFVector4D)transformedVector: (OFVector4D)vector
{
	return OFMakeVector4D(
	    _values[0][0] * vector.x + _values[0][1] * vector.y +
	    _values[0][2] * vector.z + _values[0][3] * vector.w,
	    _values[1][0] * vector.x + _values[1][1] * vector.y +
	    _values[1][2] * vector.z + _values[1][3] * vector.w,
	    _values[2][0] * vector.x + _values[2][1] * vector.y +
	    _values[2][2] * vector.z + _values[2][3] * vector.w,
	    _values[3][0] * vector.x + _values[3][1] * vector.y +
	    _values[3][2] * vector.z + _values[3][3] * vector.w);
}

- (OFString *)description
{
	return [OFString stringWithFormat:
	    @"<OFMatrix4x4: {\n"
	    @"\t%g %g %g %g\n"
	    @"\t%g %g %g %g\n"
	    @"\t%g %g %g %g\n"
	    @"\t%g %g %g %g\n"
	    @"}>",
	    _values[0][0], _values[0][1], _values[0][2], _values[0][3],
	    _values[1][0], _values[1][1], _values[1][2], _values[1][3],
	    _values[2][0], _values[2][1], _values[2][2], _values[2][3],
	    _values[3][0], _values[3][1], _values[3][2], _values[3][3]];
}
@end

Modified src/OFMemoryStream.h from [173e3dc728] to [a05c6a1069].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFMemoryStream.m from [d9d07c7da0] to [6759d95698].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFMessagePackExtension.h from [99c89d24f1] to [5d5c88f0d0].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFMessagePackExtension.m from [a3971287d8] to [4478b619f8].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFMessagePackRepresentation.h from [d2e100cc65] to [933d68bfc9].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFMethodSignature.h from [996cafd8b2] to [074e9c24c2].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFMethodSignature.m from [90c71645ee] to [e8f9b47dc1].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
142
143
144
145
146
147
148

149

150
151
152
153
154
155
156
142
143
144
145
146
147
148
149

150
151
152
153
154
155
156
157







+
-
+







	(*type)++;
	(*length)--;

	return alignment;
}

static size_t
#if defined(__clang__) && __has_attribute(__optnone__) && \
#if defined(__clang__) && __clang_major__ == 3 && __clang_minor__ <= 7
    __clang_major__ == 3 && __clang_minor__ <= 7
/* Work around an ICE in Clang 3.7.0 on Windows/x86 */
__attribute__((__optnone__))
#endif
alignmentOfEncoding(const char **type, size_t *length, bool inStruct)
{
	size_t alignment;

436
437
438
439
440
441
442





443
444
445
446
447
448
449
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455







+
+
+
+
+







	(*type)++;
	(*length)--;

	return size;
}

static size_t
#if defined(__clang__) && __has_attribute(__optnone__) && \
    __clang_major__ == 3 && __clang_minor__ <= 7
/* Work around an ICE in Clang 3.7.0 on Windows/x86 */
__attribute__((__optnone__))
#endif
sizeOfEncoding(const char **type, size_t *length)
{
	size_t size;

	if (*length == 0)
		@throw [OFInvalidFormatException exception];

Modified src/OFMutableAdjacentArray.h from [def2b8877c] to [bd2f97a834].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFMutableAdjacentArray.m from [7ff7f8969c] to [da5d41d53e].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFMutableArchiveEntry.h from [ffb170561c] to [bcb41124c1].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFMutableArray.h from [43a8133fa8] to [731451be69].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
198
199
200
201
202
203
204











205
206
207
208
209
210
211
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







+
+
+
+
+
+
+
+
+
+
+







 *
 * @param selector The selector to use to sort the array. It's signature
 *		   should be the same as that of -[compare:].
 * @param options The options to use when sorting the array
 */
- (void)sortUsingSelector: (SEL)selector options: (OFArraySortOptions)options;

/**
 * @brief Sorts the array using the specified function and options.
 *
 * @param compare The function to use to sort the array
 * @param context Context passed to the function to compare
 * @param options The options to use when sorting the array
 */
- (void)sortUsingFunction: (OFCompareFunction)compare
		  context: (nullable void *)context
		  options: (OFArraySortOptions)options;

#ifdef OF_HAVE_BLOCKS
/**
 * @brief Sorts the array using the specified comparator and options.
 *
 * @param comparator The comparator to use to sort the array
 * @param options The options to use when sorting the array
 */

Modified src/OFMutableArray.m from [e0ede1483b] to [0c37234313].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
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
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







-
-
-
-
-
-
-
-
-
-

-
-
+
+


















-
+



-
+







-
+





-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-





-







static struct {
	Class isa;
} placeholder;

@interface OFMutableArrayPlaceholder: OFMutableArray
@end

static OFComparisonResult
compare(id left, id right, SEL selector)
{
	OFComparisonResult (*comparator)(id, SEL, id) =
	    (OFComparisonResult (*)(id, SEL, id))
	    [left methodForSelector: selector];

	return comparator(left, selector, right);
}

static void
quicksort(OFMutableArray *array, size_t left, size_t right, SEL selector,
    OFArraySortOptions options)
quicksort(OFMutableArray *array, size_t left, size_t right,
    OFCompareFunction compare, void *context, OFArraySortOptions options)
{
	OFComparisonResult ascending, descending;

	if (options & OFArraySortDescending) {
		ascending = OFOrderedDescending;
		descending = OFOrderedAscending;
	} else {
		ascending = OFOrderedAscending;
		descending = OFOrderedDescending;
	}

	while (left < right) {
		size_t i = left;
		size_t j = right - 1;
		id pivot = [array objectAtIndex: right];

		do {
			while (compare([array objectAtIndex: i], pivot,
			    selector) != descending && i < right)
			    context) != descending && i < right)
				i++;

			while (compare([array objectAtIndex: j], pivot,
			    selector) != ascending && j > left)
			    context) != ascending && j > left)
				j--;

			if (i < j)
				[array exchangeObjectAtIndex: i
					   withObjectAtIndex: j];
		} while (i < j);

		if (compare([array objectAtIndex: i], pivot, selector) ==
		if (compare([array objectAtIndex: i], pivot, context) ==
		    descending)
			[array exchangeObjectAtIndex: i
				   withObjectAtIndex: right];

		if (i > 0)
			quicksort(array, left, i - 1, selector, options);
			quicksort(array, left, i - 1, compare, context,

		left = i + 1;
	}
}

#ifdef OF_HAVE_BLOCKS
static void
quicksortWithBlock(OFMutableArray *array, size_t left, size_t right,
    OFComparator comparator, OFArraySortOptions options)
{
	OFComparisonResult ascending, descending;

	if (options & OFArraySortDescending) {
		ascending = OFOrderedDescending;
		descending = OFOrderedAscending;
	} else {
		ascending = OFOrderedAscending;
		descending = OFOrderedDescending;
	}

	while (left < right) {
		size_t i = left;
		size_t j = right - 1;
		id pivot = [array objectAtIndex: right];

		do {
			while (comparator([array objectAtIndex: i], pivot) !=
			    descending && i < right)
				i++;

			while (comparator([array objectAtIndex: j], pivot) !=
			    ascending && j > left)
				j--;

			if (i < j)
				[array exchangeObjectAtIndex: i
					   withObjectAtIndex: j];
		} while (i < j);

		if (comparator([array objectAtIndex: i], pivot) == descending)
			[array exchangeObjectAtIndex: i
				   withObjectAtIndex: right];

		if (i > 0)
			quicksortWithBlock(array, left, i - 1, comparator,
			    options);

		left = i + 1;
	}
}
#endif

@implementation OFMutableArrayPlaceholder
- (instancetype)init
{
	return (id)[[OFMutableAdjacentArray alloc] init];
}

176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
120
121
122
123
124
125
126






127
128
129
130
131
132
133







-
-
-
-
-
-








- (instancetype)initWithObjects: (id const *)objects count: (size_t)count
{
	return (id)[[OFMutableAdjacentArray alloc] initWithObjects: objects
							     count: count];
}

- (instancetype)initWithSerialization: (OFXMLElement *)element
{
	return (id)[[OFMutableAdjacentArray alloc]
	    initWithSerialization: element];
}

- (instancetype)retain
{
	return self;
}

- (instancetype)autorelease
{
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
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
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







+
+
+
+
+
+
+
+
+
+
+









-
+
+
+
+
+
+
+
+
+
+
+
+
+
+



+
+
+
+
+
+
+
+








-
+







	}
}

- (void)sort
{
	[self sortUsingSelector: @selector(compare:) options: 0];
}

static OFComparisonResult
selectorCompare(id left, id right, void *context)
{
	SEL selector = context;
	OFComparisonResult (*comparator)(id, SEL, id) =
	    (OFComparisonResult (*)(id, SEL, id))
	    [left methodForSelector: selector];

	return comparator(left, selector, right);
}

- (void)sortUsingSelector: (SEL)selector
		  options: (OFArraySortOptions)options
{
	size_t count = self.count;

	if (count == 0 || count == 1)
		return;

	quicksort(self, 0, count - 1, selector, options);
	quicksort(self, 0, count - 1, selectorCompare, (void *)selector,
	    options);
}

- (void)sortUsingFunction: (OFCompareFunction)compare
		  context: (void *)context
		  options: (OFArraySortOptions)options
{
	size_t count = self.count;

	if (count == 0 || count == 1)
		return;

	quicksort(self, 0, count - 1, compare, context, options);
}

#ifdef OF_HAVE_BLOCKS
static OFComparisonResult
blockCompare(id left, id right, void *context)
{
	OFComparator block = (OFComparator)context;

	return block(left, right);
}

- (void)sortUsingComparator: (OFComparator)comparator
		    options: (OFArraySortOptions)options
{
	size_t count = self.count;

	if (count == 0 || count == 1)
		return;

	quicksortWithBlock(self, 0, count - 1, comparator, options);
	quicksort(self, 0, count - 1, blockCompare, comparator, options);
}
#endif

- (void)reverse
{
	size_t i, j, count = self.count;

Modified src/OFMutableData.h from [23548715da] to [6167546110].

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
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

-
+


















-







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 */

#import "OFData.h"

OF_ASSUME_NONNULL_BEGIN

@class OFString;
@class OFURI;

/**
 * @class OFMutableData OFMutableData.h ObjFW/OFMutableData.h
 *
 * @brief A class for storing and manipulating arbitrary data in an array.
 */
@interface OFMutableData: OFData

Modified src/OFMutableData.m from [b4151ce5ed] to [ab7e0d2674].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFMutableDictionary.h from [851a8f19f7] to [368ae1527e].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFMutableDictionary.m from [459ca84c71] to [4bd030691a].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
76
77
78
79
80
81
82






83
84
85
86
87
88
89







-
-
-
-
-
-








- (instancetype)initWithKey: (id)firstKey arguments: (va_list)arguments
{
	return (id)[[OFMutableMapTableDictionary alloc] initWithKey: firstKey
							  arguments: arguments];
}

- (instancetype)initWithSerialization: (OFXMLElement *)element
{
	return (id)[[OFMutableMapTableDictionary alloc]
	    initWithSerialization: element];
}

- (instancetype)initWithCapacity: (size_t)capacity
{
	return (id)[[OFMutableMapTableDictionary alloc]
	    initWithCapacity: capacity];
}

- (instancetype)retain

Renamed and modified src/OFMutableURI.h [9400cfdc05] to src/OFMutableIRI.h [98f947461a].

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
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

-
+













-
+




-
+

-
-
+
+
+
+

-
+

-
+



-
+







-
+




-
+











-
+







-
+




-
+











-
+




-
+











-
+




-
+










-
+










-
+




-
+











-
+















-
+




-
+











-
+

-
-
+
+

-
+


-
+


-
-
+
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 */

#import "OFURI.h"
#import "OFIRI.h"

OF_ASSUME_NONNULL_BEGIN

/**
 * @class OFMutableURI OFMutableURI.h ObjFW/OFMutableURI.h
 * @class OFMutableIRI OFMutableIRI.h ObjFW/OFMutableIRI.h
 *
 * @brief A class for parsing URIs as per RFC 3986 and accessing and modifying
 *	  parts of it.
 * @brief A class for representing IRIs, URIs, URLs and URNs, for parsing them,
 *	  accessing parts of them as well as modifying them.
 *
 * This class follows RFC 3976 and RFC 3987.
 */
@interface OFMutableURI: OFURI
@interface OFMutableIRI: OFIRI
{
	OF_RESERVE_IVARS(OFMutableURI, 4)
	OF_RESERVE_IVARS(OFMutableIRI, 4)
}

/**
 * @brief The scheme part of the URI.
 * @brief The scheme part of the IRI.
 *
 * @throw OFInvalidFormatException The scheme being set is not in the correct
 *				   format
 */
@property (readwrite, copy, nonatomic) OFString *scheme;

/**
 * @brief The host part of the URI.
 * @brief The host part of the IRI.
 */
@property OF_NULLABLE_PROPERTY (readwrite, copy, nonatomic) OFString *host;

/**
 * @brief The host part of the URI in percent-encoded form.
 * @brief The host part of the IRI in percent-encoded form.
 *
 * Setting this retains the original percent-encoding used - if more characters
 * than necessary are percent-encoded, it is kept this way.
 *
 * @throw OFInvalidFormatException The host being set is not in the correct
 *				   format
 */
@property OF_NULLABLE_PROPERTY (readwrite, copy, nonatomic)
    OFString *percentEncodedHost;

/**
 * @brief The port part of the URI.
 * @brief The port part of the IRI.
 *
 * @throw OFInvalidArgumentException The port is not valid (e.g. negative or
 *				     too big)
 */
@property OF_NULLABLE_PROPERTY (readwrite, copy, nonatomic) OFNumber *port;

/**
 * @brief The user part of the URI.
 * @brief The user part of the IRI.
 */
@property OF_NULLABLE_PROPERTY (readwrite, copy, nonatomic) OFString *user;

/**
 * @brief The user part of the URI in percent-encoded form.
 * @brief The user part of the IRI in percent-encoded form.
 *
 * Setting this retains the original percent-encoding used - if more characters
 * than necessary are percent-encoded, it is kept this way.
 *
 * @throw OFInvalidFormatException The user being set is not in the correct
 *				   format
 */
@property OF_NULLABLE_PROPERTY (readwrite, copy, nonatomic)
    OFString *percentEncodedUser;

/**
 * @brief The password part of the URI.
 * @brief The password part of the IRI.
 */
@property OF_NULLABLE_PROPERTY (readwrite, copy, nonatomic) OFString *password;

/**
 * @brief The password part of the URI in URI-encoded form.
 * @brief The password part of the IRI in percent-encoded form.
 *
 * Setting this retains the original percent-encoding used - if more characters
 * than necessary are percent-encoded, it is kept this way.
 *
 * @throw OFInvalidFormatException The password being set is not in the correct
 *				   format
 */
@property OF_NULLABLE_PROPERTY (readwrite, copy, nonatomic)
    OFString *percentEncodedPassword;

/**
 * @brief The path part of the URI.
 * @brief The path part of the IRI.
 */
@property (readwrite, copy, nonatomic) OFString *path;

/**
 * @brief The path part of the URI in percent-encoded form.
 * @brief The path part of the IRI in percent-encoded form.
 *
 * Setting this retains the original percent-encoding used - if more characters
 * than necessary are percent-encoded, it is kept this way.
 *
 * @throw OFInvalidFormatException The path being set is not in the correct
 *				   format
 */
@property (readwrite, copy, nonatomic) OFString *percentEncodedPath;

/**
 * @brief The path of the URI split into components.
 * @brief The path of the IRI split into components.
 *
 * The first component must always be empty to designate the root.
 *
 * @throw OFInvalidFormatException The path components being set are not in the
 *				   correct format
 */
@property (readwrite, copy, nonatomic)
    OFArray OF_GENERIC(OFString *) *pathComponents;

/**
 * @brief The query part of the URI.
 * @brief The query part of the IRI.
 */
@property OF_NULLABLE_PROPERTY (readwrite, copy, nonatomic) OFString *query;

/**
 * @brief The query part of the URI in percent-encoded form.
 * @brief The query part of the IRI in percent-encoded form.
 *
 * Setting this retains the original percent-encoding used - if more characters
 * than necessary are percent-encoded, it is kept this way.
 *
 * @throw OFInvalidFormatException The query being set is not in the correct
 *				   format
 */
@property OF_NULLABLE_PROPERTY (readwrite, copy, nonatomic)
    OFString *percentEncodedQuery;

/**
 * @brief The query part of the URI as an array.
 * @brief The query part of the IRI as an array.
 *
 * For example, a query like `key1=value1&key2=value2` would correspond to the
 * following array:
 *
 *     @[
 *         [OFPair pairWithFirstObject: @"key1" secondObject: @"value1"],
 *         [OFPair pairWithFirstObject: @"key2" secondObject: @"value2"],
 *     ]
 *
 * @throw OFInvalidFormatException The query is not in the correct format
 */
@property OF_NULLABLE_PROPERTY (readwrite, copy, nonatomic)
    OFArray OF_GENERIC(OFPair OF_GENERIC(OFString *, OFString *) *) *queryItems;

/**
 * @brief The fragment part of the URI.
 * @brief The fragment part of the IRI.
 */
@property OF_NULLABLE_PROPERTY (readwrite, copy, nonatomic) OFString *fragment;

/**
 * @brief The fragment part of the URI in percent-encoded form.
 * @brief The fragment part of the IRI in percent-encoded form.
 *
 * Setting this retains the original percent-encoding used - if more characters
 * than necessary are percent-encoded, it is kept this way.
 *
 * @throw OFInvalidFormatException The fragment being set is not in the correct
 *				   format
 */
@property OF_NULLABLE_PROPERTY (readwrite, copy, nonatomic)
    OFString *percentEncodedFragment;

/**
 * @brief Creates a new mutable URI with the specified schemed.
 * @brief Creates a new mutable IRI with the specified schemed.
 *
 * @param scheme The scheme for the URI
 * @return A new, autoreleased OFMutableURI
 * @param scheme The scheme for the IRI
 * @return A new, autoreleased OFMutableIRI
 */
+ (instancetype)URIWithScheme: (OFString *)scheme;
+ (instancetype)IRIWithScheme: (OFString *)scheme;

/**
 * @brief Initializes an already allocated mutable URI with the specified
 * @brief Initializes an already allocated mutable IRI with the specified
 *	  schemed.
 *
 * @param scheme The scheme for the URI
 * @return An initialized OFMutableURI
 * @param scheme The scheme for the IRI
 * @return An initialized OFMutableIRI
 */
- (instancetype)initWithScheme: (OFString *)scheme;

/**
 * @brief Appends the specified path component.
 *
 * @param component The component to append
208
209
210
211
212
213
214
215

216
217
218
219
220
210
211
212
213
214
215
216

217
218
219
220
221
222







-
+






/**
 * @brief Resolves relative subpaths.
 */
- (void)standardizePath;

/**
 * @brief Converts the mutable URI to an immutable URI.
 * @brief Converts the mutable IRI to an immutable IRI.
 */
- (void)makeImmutable;
@end

OF_ASSUME_NONNULL_END

Renamed and modified src/OFMutableURI.m [375c07c449] to src/OFMutableIRI.m [0034636112].

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
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

-
+















-
-
+
+












-
+





-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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 "OFMutableURI.h"
#import "OFURI+Private.h"
#import "OFMutableIRI.h"
#import "OFIRI+Private.h"
#import "OFArray.h"
#import "OFDictionary.h"
#ifdef OF_HAVE_FILES
# import "OFFileManager.h"
#endif
#import "OFNumber.h"
#import "OFPair.h"
#import "OFString.h"

#import "OFInvalidArgumentException.h"
#import "OFInvalidFormatException.h"

@implementation OFMutableURI
@implementation OFMutableIRI
@dynamic scheme, host, percentEncodedHost, port, user, percentEncodedUser;
@dynamic password, percentEncodedPassword, path, percentEncodedPath;
@dynamic pathComponents, query, percentEncodedQuery, queryItems, fragment;
@dynamic percentEncodedFragment;

+ (instancetype)URIWithScheme: (OFString *)scheme
+ (instancetype)IRIWithScheme: (OFString *)scheme
{
	return [[[self alloc] initWithScheme: scheme] autorelease];
}

- (instancetype)initWithScheme: (OFString *)scheme
{
	self = [super of_init];
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
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







-
-
+
+













-
+





-
+












-
+



-
-
+
+







{
	void *pool = objc_autoreleasePoolPush();
	OFString *old = _scheme;

	if (scheme.length < 1 || !OFASCIIIsAlpha(*scheme.UTF8String))
		@throw [OFInvalidFormatException exception];

	OFURIVerifyIsEscaped(scheme,
	    [OFCharacterSet URISchemeAllowedCharacterSet], false);
	OFIRIVerifyIsEscaped(scheme,
	    [OFCharacterSet IRISchemeAllowedCharacterSet], false);

	_scheme = [scheme.lowercaseString copy];

	[old release];

	objc_autoreleasePoolPop(pool);
}

- (void)setHost: (OFString *)host
{
	void *pool = objc_autoreleasePoolPush();
	OFString *old = _percentEncodedHost;

	if (OFURIIsIPv6Host(host))
	if (OFIRIIsIPv6Host(host))
		_percentEncodedHost = [[OFString alloc]
		    initWithFormat: @"[%@]", host];
	else
		_percentEncodedHost = [[host
		    stringByAddingPercentEncodingWithAllowedCharacters:
		    [OFCharacterSet URIHostAllowedCharacterSet]] copy];
		    [OFCharacterSet IRIHostAllowedCharacterSet]] copy];

	[old release];

	objc_autoreleasePoolPop(pool);
}

- (void)setPercentEncodedHost: (OFString *)percentEncodedHost
{
	OFString *old;

	if ([percentEncodedHost hasPrefix: @"["] &&
	    [percentEncodedHost hasSuffix: @"]"]) {
		if (!OFURIIsIPv6Host([percentEncodedHost substringWithRange:
		if (!OFIRIIsIPv6Host([percentEncodedHost substringWithRange:
		    OFMakeRange(1, percentEncodedHost.length - 2)]))
			@throw [OFInvalidFormatException exception];
	} else if (percentEncodedHost != nil)
		OFURIVerifyIsEscaped(percentEncodedHost,
		    [OFCharacterSet URIHostAllowedCharacterSet], true);
		OFIRIVerifyIsEscaped(percentEncodedHost,
		    [OFCharacterSet IRIHostAllowedCharacterSet], true);

	old = _percentEncodedHost;
	_percentEncodedHost = [percentEncodedHost copy];
	[old release];
}

- (void)setPort: (OFNumber *)port
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
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







-
+











-
-
+
+













-
+











-
-
+
+













-
+










-
-
+
+







- (void)setUser: (OFString *)user
{
	void *pool = objc_autoreleasePoolPush();
	OFString *old = _percentEncodedUser;

	_percentEncodedUser = [[user
	    stringByAddingPercentEncodingWithAllowedCharacters:
	    [OFCharacterSet URIUserAllowedCharacterSet]] copy];
	    [OFCharacterSet IRIUserAllowedCharacterSet]] copy];

	[old release];

	objc_autoreleasePoolPop(pool);
}

- (void)setPercentEncodedUser: (OFString *)percentEncodedUser
{
	OFString *old;

	if (percentEncodedUser != nil)
		OFURIVerifyIsEscaped(percentEncodedUser,
		    [OFCharacterSet URIUserAllowedCharacterSet], true);
		OFIRIVerifyIsEscaped(percentEncodedUser,
		    [OFCharacterSet IRIUserAllowedCharacterSet], true);

	old = _percentEncodedUser;
	_percentEncodedUser = [percentEncodedUser copy];
	[old release];
}

- (void)setPassword: (OFString *)password
{
	void *pool = objc_autoreleasePoolPush();
	OFString *old = _percentEncodedPassword;

	_percentEncodedPassword = [[password
	    stringByAddingPercentEncodingWithAllowedCharacters:
	    [OFCharacterSet URIPasswordAllowedCharacterSet]] copy];
	    [OFCharacterSet IRIPasswordAllowedCharacterSet]] copy];

	[old release];

	objc_autoreleasePoolPop(pool);
}

- (void)setPercentEncodedPassword: (OFString *)percentEncodedPassword
{
	OFString *old;

	if (percentEncodedPassword != nil)
		OFURIVerifyIsEscaped(percentEncodedPassword,
		    [OFCharacterSet URIPasswordAllowedCharacterSet], true);
		OFIRIVerifyIsEscaped(percentEncodedPassword,
		    [OFCharacterSet IRIPasswordAllowedCharacterSet], true);

	old = _percentEncodedPassword;
	_percentEncodedPassword = [percentEncodedPassword copy];
	[old release];
}

- (void)setPath: (OFString *)path
{
	void *pool = objc_autoreleasePoolPush();
	OFString *old = _percentEncodedPath;

	_percentEncodedPath = [[path
	    stringByAddingPercentEncodingWithAllowedCharacters:
	    [OFCharacterSet URIPathAllowedCharacterSet]] copy];
	    [OFCharacterSet IRIPathAllowedCharacterSet]] copy];

	[old release];

	objc_autoreleasePoolPop(pool);
}

- (void)setPercentEncodedPath: (OFString *)percentEncodedPath
{
	OFString *old;

	OFURIVerifyIsEscaped(percentEncodedPath,
	    [OFCharacterSet URIPathAllowedCharacterSet], true);
	OFIRIVerifyIsEscaped(percentEncodedPath,
	    [OFCharacterSet IRIPathAllowedCharacterSet], true);

	old = _percentEncodedPath;
	_percentEncodedPath = [percentEncodedPath copy];
	[old release];
}

- (void)setPathComponents: (OFArray *)components
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
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







-
+











-
-
+
+







- (void)setQuery: (OFString *)query
{
	void *pool = objc_autoreleasePoolPush();
	OFString *old = _percentEncodedQuery;

	_percentEncodedQuery = [[query
	    stringByAddingPercentEncodingWithAllowedCharacters:
	    [OFCharacterSet URIQueryAllowedCharacterSet]] copy];
	    [OFCharacterSet IRIQueryAllowedCharacterSet]] copy];

	[old release];

	objc_autoreleasePoolPop(pool);
}

- (void)setPercentEncodedQuery: (OFString *)percentEncodedQuery
{
	OFString *old;

	if (percentEncodedQuery != nil)
		OFURIVerifyIsEscaped(percentEncodedQuery,
		    [OFCharacterSet URIQueryAllowedCharacterSet], true);
		OFIRIVerifyIsEscaped(percentEncodedQuery,
		    [OFCharacterSet IRIQueryAllowedCharacterSet], true);

	old = _percentEncodedQuery;
	_percentEncodedQuery = [percentEncodedQuery copy];
	[old release];
}

- (void)setQueryItems:
259
260
261
262
263
264
265
266

267
268
269
270
271
272
273
259
260
261
262
263
264
265

266
267
268
269
270
271
272
273







-
+







		[_percentEncodedQuery release];
		_percentEncodedQuery = nil;
		return;
	}

	pool = objc_autoreleasePoolPush();
	percentEncodedQuery = [OFMutableString string];
	characterSet = [OFCharacterSet URIQueryKeyValueAllowedCharacterSet];
	characterSet = [OFCharacterSet IRIQueryKeyValueAllowedCharacterSet];

	for (OFPair OF_GENERIC(OFString *, OFString *) *item in queryItems) {
		OFString *key = [item.firstObject
		    stringByAddingPercentEncodingWithAllowedCharacters:
		    characterSet];
		OFString *value = [item.secondObject
		    stringByAddingPercentEncodingWithAllowedCharacters:
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
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







-
+











-
-
+
+








-
+













-
+







- (void)setFragment: (OFString *)fragment
{
	void *pool = objc_autoreleasePoolPush();
	OFString *old = _percentEncodedFragment;

	_percentEncodedFragment = [[fragment
	    stringByAddingPercentEncodingWithAllowedCharacters:
	    [OFCharacterSet URIFragmentAllowedCharacterSet]] copy];
	    [OFCharacterSet IRIFragmentAllowedCharacterSet]] copy];

	[old release];

	objc_autoreleasePoolPop(pool);
}

- (void)setPercentEncodedFragment: (OFString *)percentEncodedFragment
{
	OFString *old;

	if (percentEncodedFragment != nil)
		OFURIVerifyIsEscaped(percentEncodedFragment,
		    [OFCharacterSet URIFragmentAllowedCharacterSet], true);
		OFIRIVerifyIsEscaped(percentEncodedFragment,
		    [OFCharacterSet IRIFragmentAllowedCharacterSet], true);

	old = _percentEncodedFragment;
	_percentEncodedFragment = [percentEncodedFragment copy];
	[old release];
}

- (id)copy
{
	OFMutableURI *copy = [self mutableCopy];
	OFMutableIRI *copy = [self mutableCopy];

	[copy makeImmutable];

	return copy;
}

- (void)appendPathComponent: (OFString *)component
{
	[self appendPathComponent: component isDirectory: false];

#ifdef OF_HAVE_FILES
	if ([_scheme isEqual: @"file"] &&
	    ![_percentEncodedPath hasSuffix: @"/"] &&
	    [[OFFileManager defaultManager] directoryExistsAtURI: self]) {
	    [[OFFileManager defaultManager] directoryExistsAtIRI: self]) {
		void *pool = objc_autoreleasePoolPush();
		OFString *path = [_percentEncodedPath
		    stringByAppendingString: @"/"];

		[_percentEncodedPath release];
		_percentEncodedPath = [path retain];

350
351
352
353
354
355
356
357

358
359
360
361
362
363
364
350
351
352
353
354
355
356

357
358
359
360
361
362
363
364







-
+








	if ([component isEqual: @"/"] && [_percentEncodedPath hasSuffix: @"/"])
		return;

	pool = objc_autoreleasePoolPush();
	component = [component
	    stringByAddingPercentEncodingWithAllowedCharacters:
	    [OFCharacterSet URIPathAllowedCharacterSet]];
	    [OFCharacterSet IRIPathAllowedCharacterSet]];

#if defined(OF_WINDOWS) || defined(OF_MSDOS)
	if ([_percentEncodedPath hasSuffix: @"/"] ||
	    ([_scheme isEqual: @"file"] &&
	    [_percentEncodedPath hasSuffix: @":"]))
#else
	if ([_percentEncodedPath hasSuffix: @"/"])
430
431
432
433
434
435
436
437

438
439
430
431
432
433
434
435
436

437
438
439







-
+


	self.percentEncodedPath = path;

	objc_autoreleasePoolPop(pool);
}

- (void)makeImmutable
{
	object_setClass(self, [OFURI class]);
	object_setClass(self, [OFIRI class]);
}
@end

Modified src/OFMutableLHAArchiveEntry.h from [5bfb2f1e47] to [d4cd5dd233].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFMutableLHAArchiveEntry.m from [84adbb8df8] to [5175d41deb].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFMutableMapTableDictionary.h from [e3ea116447] to [56771d5148].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFMutableMapTableDictionary.m from [eda929d7fd] to [0658abc2dc].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFMutableMapTableSet.h from [ee94211a1c] to [4eae6d1c54].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFMutableMapTableSet.m from [134371a3b6] to [3dd4e2c006].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFMutablePair.h from [fd02ba0f90] to [c1bb3c2527].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFMutablePair.m from [6901454ea9] to [81a65fa049].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFMutableSet.h from [c05177c6a6] to [3d35e08a82].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFMutableSet.m from [1675014936] to [f395937f21].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
65
66
67
68
69
70
71






72
73
74
75
76
77
78







-
-
-
-
-
-








- (instancetype)initWithObject: (id)firstObject arguments: (va_list)arguments
{
	return (id)[[OFMutableMapTableSet alloc] initWithObject: firstObject
						      arguments: arguments];
}

- (instancetype)initWithSerialization: (OFXMLElement *)element
{
	return (id)[[OFMutableMapTableSet alloc]
	    initWithSerialization: element];
}

- (instancetype)initWithCapacity: (size_t)capacity
{
	return (id)[[OFMutableMapTableSet alloc] initWithCapacity: capacity];
}

- (instancetype)retain
{

Modified src/OFMutableString.h from [f372a7a142] to [02fdd7e9ff].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFMutableString.m from [eb3bef8a08] to [6babdf726b].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
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
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







-
+

-
+


-
+



-
+



-
-
-
-
-







{
	return (id)[[OFMutableUTF8String alloc]
	    initWithContentsOfFile: path
			  encoding: encoding];
}
#endif

- (instancetype)initWithContentsOfURI: (OFURI *)URI
- (instancetype)initWithContentsOfIRI: (OFIRI *)IRI
{
	return (id)[[OFMutableUTF8String alloc] initWithContentsOfURI: URI];
	return (id)[[OFMutableUTF8String alloc] initWithContentsOfIRI: IRI];
}

- (instancetype)initWithContentsOfURI: (OFURI *)URI
- (instancetype)initWithContentsOfIRI: (OFIRI *)IRI
			     encoding: (OFStringEncoding)encoding
{
	return (id)[[OFMutableUTF8String alloc]
	    initWithContentsOfURI: URI
	    initWithContentsOfIRI: IRI
			 encoding: encoding];
}

- (instancetype)initWithSerialization: (OFXMLElement *)element
{
	return (id)[[OFMutableUTF8String alloc] initWithSerialization: element];
}

- (instancetype)retain
{
	return self;
}

- (instancetype)autorelease
{

Modified src/OFMutableTarArchiveEntry.h from [d5cbafa370] to [54f1ad9019].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFMutableTarArchiveEntry.m from [693af0fda5] to [b750314d1f].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFMutableTriple.h from [9e67514e20] to [f9820015d5].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFMutableTriple.m from [a54e7551cb] to [4a5ee4edaa].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFMutableUTF8String.h from [681d1d0ba4] to [a8a382ecd5].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFMutableUTF8String.m from [5369441523] to [0f1f1bc03e].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFMutableZIPArchiveEntry.h from [019337b54d] to [c7ff19b817].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFMutableZIPArchiveEntry.m from [6a8c882277] to [ac96625980].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFMutex.h from [60974c2165] to [9f1ab63c72].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFMutex.m from [91291c7344] to [02f32d24e6].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFNonretainedObjectValue.h from [3bd7c9c6b7] to [2d93396021].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFNonretainedObjectValue.m from [93108c2968] to [76443b4198].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFNotification.h from [c3409634e1] to [ce9c79b0e6].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFNotification.m from [d51e2a4110] to [a3ddaa4039].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFNotificationCenter.h from [2edf55e2db] to [86c8ff2ef9].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
18
19
20
21
22
23
24

25
26
27
28
29
30
31







-








OF_ASSUME_NONNULL_BEGIN

@class OFMutableDictionary OF_GENERIC(KeyType, ObjectType);
#ifdef OF_HAVE_THREADS
@class OFMutex;
#endif
@class OFNotificationCenterHandle;

#ifdef OF_HAVE_BLOCKS
/**
 * @brief A block which is called when a notification has been posted.
 *
 * @param notification The notification that has been posted
 */
60
61
62
63
64
65
66
67
68


69
70
71
72
73
74
75
59
60
61
62
63
64
65


66
67
68
69
70
71
72
73
74







-
-
+
+







+ (OFNotificationCenter *)defaultCenter;

/**
 * @brief Adds an observer for the specified notification and object.
 *
 * @param observer The object that should receive notifications
 * @param selector The selector to call on the observer on notifications. The
 *		   method must take exactly one object of type @ref
 *		   OFNotification.
 *		   method must take exactly one object of type
 *		   @ref OFNotification.
 * @param name The name of the notification to observe
 * @param object The object that should be sending the notification, or `nil`
 *		 if the object should be ignored to determine what
 *		 notifications to deliver
 */
- (void)addObserver: (id)observer
	   selector: (SEL)selector
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
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







-
-
-
-
+
+
+







-
+







 * @param name The name of the notification to observe
 * @param object The object that should be sending the notification, or `nil`
 *		 if the object should be ignored to determine what
 *		 notifications to deliver
 * @param block The block to handle notifications
 * @return An opaque object to remove the observer again
 */
- (OFNotificationCenterHandle *)
    addObserverForName: (OFNotificationName)name
		object: (nullable id)object
	    usingBlock: (OFNotificationCenterBlock)block;
- (id)addObserverForName: (OFNotificationName)name
		  object: (nullable id)object
	      usingBlock: (OFNotificationCenterBlock)block;

/**
 * @brief Removes an observer. The specified observer must be one returned by
 *	  @ref addObserver:selector:name:object:.
 *
 * @param observer The object that was returned when adding the observer
 */
- (void)removeObserver: (OFNotificationCenterHandle *)observer;
- (void)removeObserver: (id)observer;
#endif

/**
 * @brief Posts the specified notification.
 *
 * @param notification The notification to post
 */

Modified src/OFNotificationCenter.m from [a7b0a81fd8] to [bec84a1cd3].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
65
66
67
68
69
70
71
72

73
74
75
76
77
78
79
65
66
67
68
69
70
71

72
73
74
75
76
77
78
79







-
+







{
	self = [super init];

	@try {
		void *pool = objc_autoreleasePoolPush();

		_name = [name copy];
		_observer = [observer retain];
		_observer = observer;
		_selector = selector;
		_object = [object retain];

		_selectorHash = [[OFString stringWithUTF8String:
		    sel_getName(_selector)] hash];

		objc_autoreleasePoolPop(pool);
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
104
105
106
107
108
109
110

111
112
113
114
115
116
117







-







	return self;
}
#endif

- (void)dealloc
{
	[_name release];
	[_observer release];
	[_object release];
#ifdef OF_HAVE_BLOCKS
	[_block release];
#endif

	[super dealloc];
}
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
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







-
-
-
-
+
+
+


















-
+

+
+
+
+
+
+
+
-
+







						       object: object]
	    autorelease]];

	objc_autoreleasePoolPop(pool);
}

#ifdef OF_HAVE_BLOCKS
- (OFNotificationCenterHandle *)
    addObserverForName: (OFNotificationName)name
		object: (id)object
	    usingBlock: (OFNotificationCenterBlock)block
- (id)addObserverForName: (OFNotificationName)name
		  object: (id)object
	      usingBlock: (OFNotificationCenterBlock)block
{
	void *pool = objc_autoreleasePoolPush();
	OFNotificationCenterHandle *handle =
	    [[[OFNotificationCenterHandle alloc] initWithName: name
						       object: object
							block: block]
	    autorelease];

	[self of_addObserver: handle];

	[handle retain];

	objc_autoreleasePoolPop(pool);

	return [handle autorelease];
}
#endif

- (void)removeObserver: (OFNotificationCenterHandle *)handle
- (void)removeObserver: (id)handle_
{
	OFNotificationCenterHandle *handle;
	void *pool;

	if (![handle_ isKindOfClass: [OFNotificationCenterHandle class]])
		@throw [OFInvalidArgumentException exception];

	handle = handle_;
	void *pool = objc_autoreleasePoolPush();
	pool = objc_autoreleasePoolPush();

	/* {} required to avoid -Wmisleading-indentation false positive. */
	if (![handle isKindOfClass: [OFNotificationCenterHandle class]]) {
		@throw [OFInvalidArgumentException exception];
	}

#ifdef OF_HAVE_THREADS

Modified src/OFNull.h from [787aabc24c] to [08105d85ed].

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
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

-
+
















-









-
+










/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 */

#import "OFObject.h"
#import "OFJSONRepresentation.h"
#import "OFMessagePackRepresentation.h"
#import "OFSerialization.h"

OF_ASSUME_NONNULL_BEGIN

/**
 * @class OFNull OFNull.h ObjFW/OFNull.h
 *
 * @brief A class for representing null values in collections.
 */
OF_SUBCLASSING_RESTRICTED
@interface OFNull: OFObject <OFCopying, OFSerialization, OFJSONRepresentation,
@interface OFNull: OFObject <OFCopying, OFJSONRepresentation,
    OFMessagePackRepresentation>
/**
 * @brief Returns an OFNull singleton.
 *
 * @return An OFNull singleton
 */
+ (OFNull *)null;
@end

OF_ASSUME_NONNULL_END

Modified src/OFNull.m from [bf841d1a2e] to [820a727986].

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
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

-
+
















-
+
-
-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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 "OFNull.h"
#import "OFString.h"
#import "OFData.h"
#import "OFXMLElement.h"
#import "OFData.h"
#import "OFString.h"

#import "OFInvalidArgumentException.h"

@interface OFNull ()
- (OFString *)
    of_JSONRepresentationWithOptions: (OFJSONRepresentationOptions)options
			       depth: (size_t)depth;
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
36
37
38
39
40
41
42

















43
44
45
46
47
48
49
50
51
52















53
54
55
56
57
58
59







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-










-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







}

+ (OFNull *)null
{
	return null;
}

- (instancetype)initWithSerialization: (OFXMLElement *)element
{
	void *pool;

	[self release];

	pool = objc_autoreleasePoolPush();

	if (![element.name isEqual: self.className] ||
	    ![element.namespace isEqual: OFSerializationNS])
		@throw [OFInvalidArgumentException exception];

	objc_autoreleasePoolPop(pool);

	return [OFNull null];
}

- (OFString *)description
{
	return @"<null>";
}

- (id)copy
{
	return self;
}

- (OFXMLElement *)XMLElementBySerializing
{
	void *pool = objc_autoreleasePoolPush();
	OFXMLElement *element;

	element = [OFXMLElement elementWithName: self.className
				      namespace: OFSerializationNS];

	[element retain];

	objc_autoreleasePoolPop(pool);

	return [element autorelease];
}

- (OFString *)JSONRepresentation
{
	return [self of_JSONRepresentationWithOptions: 0 depth: 0];
}

- (OFString *)JSONRepresentationWithOptions:
    (OFJSONRepresentationOptions)options

Modified src/OFNumber.h from [eff21822aa] to [bb1eda01eb].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
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
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







-














-
-
+
+








#ifdef OF_HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif

#import "OFJSONRepresentation.h"
#import "OFMessagePackRepresentation.h"
#import "OFSerialization.h"
#import "OFValue.h"

OF_ASSUME_NONNULL_BEGIN

/** @file */

/**
 * @class OFNumber OFNumber.h ObjFW/OFNumber.h
 *
 * @brief Provides a way to store a number in an object.
 */
#ifndef OF_NUMBER_M
OF_SUBCLASSING_RESTRICTED
#endif
@interface OFNumber: OFValue <OFComparing, OFSerialization,
    OFJSONRepresentation, OFMessagePackRepresentation>
@interface OFNumber: OFValue <OFComparing, OFJSONRepresentation,
    OFMessagePackRepresentation>
{
	union {
		double float_;
		long long signed_;
		unsigned long long unsigned_;
	} _value;
	const char *_typeEncoding;

Modified src/OFNumber.m from [0d84e74204] to [b9b4334494].

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
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

-
+




















-
+
-
-
-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 */

#define OF_NUMBER_M

#include "config.h"

#include <math.h>

#import "OFNumber.h"
#import "OFString.h"
#import "OFData.h"
#import "OFXMLElement.h"
#import "OFXMLAttribute.h"
#import "OFData.h"
#import "OFString.h"

#import "OFInvalidArgumentException.h"
#import "OFInvalidFormatException.h"
#import "OFOutOfRangeException.h"

@interface OFNumber ()
+ (instancetype)of_alloc;
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
371
372
373
374
375
376
377





378
379
380
381
382
383
384







-
-
-
-
-







		static OFOnceControl onceControl = OFOnceControlInitValue;
		OFOnce(&onceControl, doubleZeroNumberInit);
		return (id)doubleZeroNumber;
	}

	return (id)[[OFNumber of_alloc] initWithDouble: value];
}

- (instancetype)initWithSerialization: (OFXMLElement *)element
{
	return (id)[[OFNumber of_alloc] initWithSerialization: element];
}
#ifdef __clang__
# pragma clang diagnostic pop
#endif
@end

@implementation OFNumberSingleton
- (instancetype)autorelease
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
773
774
775
776
777
778
779
















































780
781
782
783
784
785
786







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-








	_value.float_ = value;
	_typeEncoding = @encode(double);

	return self;
}

- (instancetype)initWithSerialization: (OFXMLElement *)element
{
	self = [super init];

	@try {
		void *pool = objc_autoreleasePoolPush();
		OFString *typeString;

		if (![element.name isEqual: @"OFNumber"] ||
		    ![element.namespace isEqual: OFSerializationNS])
			@throw [OFInvalidArgumentException exception];

		typeString = [element attributeForName: @"type"].stringValue;

		if ([typeString isEqual: @"bool"]) {
			OFString *stringValue = element.stringValue;
			if ([stringValue isEqual: @"true"])
				self = [self initWithBool: true];
			else if ([stringValue isEqual: @"false"])
				self = [self initWithBool: false];
			else
				@throw [OFInvalidArgumentException exception];
		} else if ([typeString isEqual: @"float"]) {
			unsigned long long value =
			    [element unsignedLongLongValueWithBase: 16];

			if (value > UINT64_MAX)
				@throw [OFOutOfRangeException exception];

			self = [self initWithDouble: OFFromBigEndianDouble(
			    OFRawUInt64ToDouble(OFToBigEndian64(value)))];
		} else if ([typeString isEqual: @"signed"])
			self = [self initWithLongLong: element.longLongValue];
		else if ([typeString isEqual: @"unsigned"])
			self = [self initWithUnsignedLongLong:
			    element.unsignedLongLongValue];
		else
			@throw [OFInvalidArgumentException exception];

		objc_autoreleasePoolPop(pool);
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (const char *)objCType
{
	return _typeEncoding;
}

- (void)getValue: (void *)value size: (size_t)size
{
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1020
1021
1022
1023
1024
1025
1026
































1027
1028
1029
1030
1031
1032
1033







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







	if (isUnsigned(self))
		return [OFString stringWithFormat: @"%llu",
						   self.unsignedLongLongValue];

	@throw [OFInvalidFormatException exception];
}

- (OFXMLElement *)XMLElementBySerializing
{
	void *pool = objc_autoreleasePoolPush();
	OFXMLElement *element;

	element = [OFXMLElement elementWithName: @"OFNumber"
				      namespace: OFSerializationNS
				    stringValue: self.description];

	if (*self.objCType == 'B')
		[element addAttributeWithName: @"type" stringValue: @"bool"];
	else if (isFloat(self)) {
		[element addAttributeWithName: @"type" stringValue: @"float"];
		element.stringValue = [OFString
		    stringWithFormat: @"%016" PRIx64,
		    OFFromBigEndian64(OFDoubleToRawUInt64(OFToBigEndianDouble(
		    self.doubleValue)))];
	} else if (isSigned(self))
		[element addAttributeWithName: @"type" stringValue: @"signed"];
	else if (isUnsigned(self))
		[element addAttributeWithName: @"type"
				  stringValue: @"unsigned"];
	else
		@throw [OFInvalidFormatException exception];

	[element retain];

	objc_autoreleasePoolPop(pool);

	return [element autorelease];
}

- (OFString *)JSONRepresentation
{
	return [self of_JSONRepresentationWithOptions: 0 depth: 0];
}

- (OFString *)JSONRepresentationWithOptions:
    (OFJSONRepresentationOptions)options

Modified src/OFObject+KeyValueCoding.h from [c0e7932d00] to [728b40f27f].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFObject+KeyValueCoding.m from [8a83d2aa9e] to [d69b59ff71].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Deleted src/OFObject+Serialization.h version [ed19e260ae].

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





































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 */

#import "OFObject.h"

OF_ASSUME_NONNULL_BEGIN

@class OFString;

#ifdef __cplusplus
extern "C" {
#endif
extern int _OFObject_Serialization_reference;
#ifdef __cplusplus
}
#endif

@interface OFObject (OFSerialization)
/**
 * @brief The object serialized as a string.
 */
@property (readonly, nonatomic) OFString *stringBySerializing;
@end

OF_ASSUME_NONNULL_END

Deleted src/OFObject+Serialization.m version [0bfdaef011].

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


























































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * 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"

#include <stdlib.h>

#import "OFObject.h"
#import "OFObject+Serialization.h"
#import "OFSerialization.h"
#import "OFString.h"
#import "OFXMLElement.h"

int _OFObject_Serialization_reference;

@implementation OFObject (Serialization)
- (OFString *)stringBySerializing
{
	void *pool;
	OFXMLElement *element;
	OFXMLElement *root;
	OFString *ret;

	if (![self conformsToProtocol: @protocol(OFSerialization)]) {
		[self doesNotRecognizeSelector: _cmd];
		abort();
	}

	pool = objc_autoreleasePoolPush();
	element = ((id <OFSerialization>)self).XMLElementBySerializing;

	root = [OFXMLElement elementWithName: @"serialization"
				   namespace: OFSerializationNS];
	[root addAttributeWithName: @"version" stringValue: @"1"];
	[root addChild: element];

	ret = [@"<?xml version='1.0' encoding='UTF-8'?>\n"
	    stringByAppendingString: [root XMLStringWithIndentation: 2]];

	[ret retain];

	objc_autoreleasePoolPop(pool);

	return [ret autorelease];
}
@end

Modified src/OFObject.h from [c53ca874a9] to [f176d35c0c].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
59
60
61
62
63
64
65











66
67
68
69
70
71
72
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







+
+
+
+
+
+
+
+
+
+
+







	OFOrderedAscending = -1,
	/** Both objects are equal */
	OFOrderedSame = 0,
	/** The left object is bigger than the right */
	OFOrderedDescending = 1
} OFComparisonResult;

/**
 * @brief A function to compare two objects.
 *
 * @param left The left object
 * @param right The right object
 * @param context Context passed along for comparing
 * @return The order of the objects
 */
typedef OFComparisonResult (*OFCompareFunction)(id _Nonnull left,
    id _Nonnull right, void *_Nullable context);

#ifdef OF_HAVE_BLOCKS
/**
 * @brief A comparator to compare two objects.
 *
 * @param left The left object
 * @param right The right object
 * @return The order of the objects
140
141
142
143
144
145
146
147

148
149
150
151
152
153
154
151
152
153
154
155
156
157

158
159
160
161
162
163
164
165







-
+







 * @brief A time interval in seconds.
 */
typedef double OFTimeInterval;

/**
 * @struct OFPoint OFObject.h ObjFW/OFObject.h
 *
 * @brief A point.
 * @brief A point in 2D space.
 */
typedef struct OF_BOXABLE {
	/** The x coordinate of the point */
	float x;
	/** The y coordinate of the point */
	float y;
} OFPoint;
277
278
279
280
281
282
283














































































































284
285
286
287
288
289
290
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
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







{
	if (!OFEqualPoints(rect1.origin, rect2.origin))
		return false;

	if (!OFEqualSizes(rect1.size, rect2.size))
		return false;

	return true;
}

/**
 * @struct OFVector3D OFObject.h ObjFW/OFObject.h
 *
 * @brief A vector in 3D space.
 */
typedef struct OF_BOXABLE {
	/** The x coordinate of the vector */
	float x;
	/** The y coordinate of the vector */
	float y;
	/** The z coordinate of the vector */
	float z;
} OFVector3D;

/**
 * @brief Creates a new OFVector3D.
 *
 * @param x The x coordinate of the vector
 * @param y The x coordinate of the vector
 * @param z The z coordinate of the vector
 * @return An OFVector3D with the specified coordinates
 */
static OF_INLINE OFVector3D OF_CONST_FUNC
OFMakeVector3D(float x, float y, float z)
{
	OFVector3D vector = { x, y, z };

	return vector;
}

/**
 * @brief Returns whether the two vectors are equal.
 *
 * @param vector1 The first vector for the comparison
 * @param vector2 The second vectors for the comparison
 * @return Whether the two vectors are equal
 */
static OF_INLINE bool
OFEqualVectors3D(OFVector3D vector1, OFVector3D vector2)
{
	if (vector1.x != vector2.x)
		return false;

	if (vector1.y != vector2.y)
		return false;

	if (vector1.z != vector2.z)
		return false;

	return true;
}

/**
 * @struct OFVector4D OFObject.h ObjFW/OFObject.h
 *
 * @brief A vector in 4D space.
 */
typedef struct OF_BOXABLE {
	/** The x coordinate of the vector */
	float x;
	/** The y coordinate of the vector */
	float y;
	/** The z coordinate of the vector */
	float z;
	/** The w coordinate of the vector */
	float w;
} OFVector4D;

/**
 * @brief Creates a new OFVector4D.
 *
 * @param x The x coordinate of the vector
 * @param y The x coordinate of the vector
 * @param z The z coordinate of the vector
 * @param w The w coordinate of the vector
 * @return An OFVector4D with the specified coordinates
 */
static OF_INLINE OFVector4D OF_CONST_FUNC
OFMakeVector4D(float x, float y, float z, float w)
{
	OFVector4D vector = { x, y, z, w };

	return vector;
}

/**
 * @brief Returns whether the two vectors are equal.
 *
 * @param vector1 The first vector for the comparison
 * @param vector2 The second vectors for the comparison
 * @return Whether the two vectors are equal
 */
static OF_INLINE bool
OFEqualVectors4D(OFVector4D vector1, OFVector4D vector2)
{
	if (vector1.x != vector2.x)
		return false;

	if (vector1.y != vector2.y)
		return false;

	if (vector1.z != vector2.z)
		return false;

	if (vector1.w != vector2.w)
		return false;

	return true;
}

/**
 * @brief Adds the specified byte to the hash.
 *
 * @param hash A pointer to a hash to add the byte to
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
776
777
778
779
780
781
782







783
784
785
786
787
788
789







-
-
-
-
-
-
-







 * @return The allocated object
 * @throw OFAllocFailedException There was not enough memory to allocate the
 *				 object
 * @throw OFInitializationFailedException The instance could not be constructed
 */
+ (instancetype)alloc;

/**
 * @brief Calls @ref alloc on `self` and then `init` on the returned object.
 *
 * @return An allocated and initialized object
 */
+ (instancetype)new;

/**
 * @brief Returns the class.
 *
 * @return The class
 */
+ (Class)class;

1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1512
1513
1514
1515
1516
1517
1518

1519
1520
1521







-




OF_ASSUME_NONNULL_END

#include "OFBlock.h"

#ifdef __OBJC__
# import "OFObject+KeyValueCoding.h"
# import "OFObject+Serialization.h"
#endif

#endif

Modified src/OFObject.m from [fa1a2c06ef] to [f38056ff53].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
60
61
62
63
64
65
66

67

68
69
70
71
72
73
74
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76







+

+







#endif

#ifdef OF_WINDOWS
# include <windows.h>
#endif

#ifdef OF_AMIGAOS
# define Class IntuitionClass
# include <proto/exec.h>
# undef Class
#endif

#ifdef OF_APPLE_RUNTIME
extern id _Nullable _objc_rootAutorelease(id _Nullable object);
#endif
#if defined(OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR)
extern id OFForward(id, SEL, ...);
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
391
392
393
394
395
396
397

398
399
400
401
402
403
404







-







}

/* References for static linking */
void
_references_to_categories_of_OFObject(void)
{
	_OFObject_KeyValueCoding_reference = 1;
	_OFObject_Serialization_reference = 1;
}

@implementation OFObject
+ (void)load
{
#if !defined(OF_APPLE_RUNTIME) || defined(__OBJC2__)
	objc_setUncaughtExceptionHandler(uncaughtExceptionHandler);
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
442
443
444
445
446
447
448





449
450
451
452
453
454
455







-
-
-
-
-







}

+ (instancetype)alloc
{
	return OFAllocObject(self, 0, 0, NULL);
}

+ (instancetype)new
{
	return [[self alloc] init];
}

+ (Class)class
{
	return self;
}

+ (OFString *)className
{
478
479
480
481
482
483
484
485
486

487
488

489
490
491
492
493
494
495
474
475
476
477
478
479
480


481


482
483
484
485
486
487
488
489







-
-
+
-
-
+







+ (bool)instancesRespondToSelector: (SEL)selector
{
	return class_respondsToSelector(self, selector);
}

+ (bool)conformsToProtocol: (Protocol *)protocol
{
	Class c;

	for (Class iter = self; iter != Nil; iter = class_getSuperclass(iter))
	for (c = self; c != Nil; c = class_getSuperclass(c))
		if (class_conformsToProtocol(c, protocol))
		if (class_conformsToProtocol(iter, protocol))
			return true;

	return false;
}

+ (IMP)instanceMethodForSelector: (SEL)selector
{
583
584
585
586
587
588
589
590

591
592
593
594
595

596
597
598
599
600
601
602
577
578
579
580
581
582
583

584
585
586
587
588

589
590
591
592
593
594
595
596







-
+




-
+







	}

	[self inheritMethodsFromClass: superclass];
}

+ (bool)resolveClassMethod: (SEL)selector
{
	return NO;
	return false;
}

+ (bool)resolveInstanceMethod: (SEL)selector
{
	return NO;
	return false;
}

- (instancetype)init
{
	return self;
}

Modified src/OFOnce.h from [6569bde484] to [f3dc36b1cf].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFOnce.m from [72d5ba7049] to [a97e7312a6].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
20
21
22
23
24
25
26

27

28
29
30
31
32
33
34
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36







+

+







#import "OFOnce.h"
#if defined(OF_HAVE_THREADS) && defined(OF_HAVE_ATOMIC_OPS)
# import "OFAtomic.h"
# import "OFPlainMutex.h"
#endif

#ifdef OF_AMIGAOS
# define Class IntuitionClass
# include <proto/exec.h>
# undef Class
#endif

void
OFOnce(OFOnceControl *control, void (*function)(void))
{
#if !defined(OF_HAVE_THREADS)
	if (*control == 0) {

Modified src/OFOptionsParser.h from [14db018626] to [b09be2069a].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFOptionsParser.m from [c0426ac296] to [814583f5b6].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFPBKDF2.h from [b9c1534ab4] to [43fe295f37].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFPBKDF2.m from [cca92e4a20] to [85eb66fd93].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFPair.h from [96e09802be] to [c7c95c202e].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFPair.m from [22c01e92c3] to [5125fc5874].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFPlainCondition.h from [fd9b66a9ca] to [f98542ce7c].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFPlainCondition.m from [b7456714c7] to [7637d6f604].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFPlainMutex.h from [e51d623af9] to [66c439c90c].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFPlainMutex.m from [0367193fde] to [84a4adfa9f].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFPlainThread.h from [312286356e] to [9c25ccf535].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
18
19
20
21
22
23
24
25

26
27
28
29
30
31
32
18
19
20
21
22
23
24

25
26
27
28
29
30
31
32







-
+







#include "platform.h"

#if !defined(OF_HAVE_THREADS) || \
    (!defined(OF_HAVE_PTHREADS) && !defined(OF_WINDOWS) && !defined(OF_AMIGAOS))
# error No threads available!
#endif

#import "macros.h"
#import "OFObject.h"

#if defined(OF_HAVE_PTHREADS)
# include <pthread.h>
typedef pthread_t OFPlainThread;
#elif defined(OF_WINDOWS)
# include <windows.h>
typedef HANDLE OFPlainThread;

Modified src/OFPlainThread.m from [ef8a973be8] to [0b4ad800cf].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFPlugin.h from [a9cf165ddb] to [a4cb307447].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFPlugin.m from [dfbf2c9e77] to [e794e6a809].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFPointValue.h from [42acb9db9a] to [fd8f67e118].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFPointValue.m from [d80a9e47ec] to [5526d367ab].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFPointerValue.h from [9280ad762d] to [343eb8ca5c].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFPointerValue.m from [0b6a62e87f] to [4e2634ad6c].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFPollKernelEventObserver.h from [1b31db8247] to [a95d7de3f8].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFPollKernelEventObserver.m from [2e609d444b] to [81141fa521].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFRIPEMD160Hash.h from [6a4a8d87d4] to [06bd946ca1].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFRIPEMD160Hash.m from [a6c68d768d] to [0dbaee2454].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFRangeCharacterSet.h from [c903dba907] to [7ccb3d0eb7].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFRangeCharacterSet.m from [4870541066] to [ae303930fe].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFRangeValue.h from [3251ae1de3] to [846202afc6].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFRangeValue.m from [72e3ffee04] to [801e11f4cf].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFRectValue.h from [83e8354a4a] to [acbebbc020].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFRectValue.m from [0064a9b262] to [8879e2c8da].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFRecursiveMutex.h from [e91aa73730] to [24a5da54a3].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFRecursiveMutex.m from [cb58226e3c] to [4be56fc602].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFRunLoop+Private.h from [1af8d65653] to [ad5e5d6c85].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFRunLoop.h from [e058e5f18b] to [575aa234f6].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFRunLoop.m from [1ed3a4a609] to [e289a6e931].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFRunLoopConstants.inc from [04d2ca961c] to [4c9d1bb8b8].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFSHA1Hash.h from [c7a73ceb16] to [1fa949fcf5].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFSHA1Hash.m from [6da836d4ff] to [47f6baacf9].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFSHA224Hash.h from [ecc593c441] to [6fe8018d4a].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFSHA224Hash.m from [5e5ae70827] to [22b08e13fc].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFSHA224Or256Hash.h from [9235d0cf7a] to [85e028cbd3].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFSHA224Or256Hash.m from [de7aa6c8f4] to [4f217678ce].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFSHA256Hash.h from [29c7ad23a9] to [0613cdc8e1].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFSHA256Hash.m from [d082eb2586] to [4ca14d156b].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFSHA384Hash.h from [7c87550526] to [1cc6c5c866].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFSHA384Hash.m from [30d7ff4a68] to [71be463222].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFSHA384Or512Hash.h from [889dffbb99] to [25ed98a55b].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFSHA384Or512Hash.m from [f0d2e79fad] to [6fba86c137].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFSHA512Hash.h from [b25fc86287] to [9f7b4b4b3e].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFSHA512Hash.m from [b08066342d] to [aaab7df59f].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFSPXSocket.h from [62171025db] to [60399680f7].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
86
87
88
89
90
91
92
93

94
95
96
97
98
99
100
86
87
88
89
90
91
92

93
94
95
96
97
98
99
100







-
+







 * @brief Connect the OFSPXSocket to the specified destination.
 *
 * @param network The network on which the node to connect to is
 * @param node The node to connect to
 * @param port The port (sometimes also called socket number) on the node to
 *	       connect to
 * @throw OFConnectSPXSocketFailedException Connecting failed
 * @throw OFAlreadyConnectedException The socket is already connected or bound
 * @throw OFAlreadyOpenException The socket is already connected or bound
 */
- (void)connectToNetwork: (uint32_t)network
		    node: (const unsigned char [_Nonnull IPX_NODE_LEN])node
		    port: (uint16_t)port;

/**
 * @brief Asynchronously connect the OFSPXSocket to the specified destination.
160
161
162
163
164
165
166
167

168
169
170
171
172
173
174
175
160
161
162
163
164
165
166

167
168
169
170
171
172
173
174
175







-
+








 * @param network The IPX network to bind to. 0 means the current network.
 * @param node The IPX network to bind to. An all zero node means the
 *	       computer's node.
 * @param port The port (sometimes called socket number) to bind to. 0 means to
 *	       pick one and return via the returned socket address.
 * @return The address on which this socket can be reached
 * @throw OFBindIPXSocketFailedException Binding failed
 * @throw OFAlreadyConnectedException The socket is already connected or bound
 * @throw OFAlreadyOpenException The socket is already connected or bound
 */
- (OFSocketAddress)
    bindToNetwork: (uint32_t)network
	     node: (const unsigned char [_Nonnull IPX_NODE_LEN])node
	     port: (uint16_t)port;
@end

OF_ASSUME_NONNULL_END

Modified src/OFSPXSocket.m from [4bb1b2f501] to [7de546d8a3].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
19
20
21
22
23
24
25
26

27
28
29
30
31
32
33
19
20
21
22
23
24
25

26
27
28
29
30
31
32
33







-
+








#import "OFSPXSocket.h"
#import "OFRunLoop.h"
#import "OFRunLoop+Private.h"
#import "OFSocket.h"
#import "OFSocket+Private.h"

#import "OFAlreadyConnectedException.h"
#import "OFAlreadyOpenException.h"
#import "OFBindIPXSocketFailedException.h"
#import "OFConnectSPXSocketFailedException.h"
#import "OFNotOpenException.h"

#ifndef NSPROTO_SPX
# define NSPROTO_SPX 0
#endif
181
182
183
184
185
186
187
188

189
190
191
192
193
194
195
181
182
183
184
185
186
187

188
189
190
191
192
193
194
195







-
+







			   errNo: (int *)errNo
{
#if SOCK_CLOEXEC == 0 && defined(HAVE_FCNTL) && defined(FD_CLOEXEC)
	int flags;
#endif

	if (_socket != OFInvalidSocketHandle)
		@throw [OFAlreadyConnectedException exceptionWithSocket: self];
		@throw [OFAlreadyOpenException exceptionWithObject: self];

	if ((_socket = socket(address->sockaddr.ipx.sipx_family,
	    SOCK_SEQPACKET | SOCK_CLOEXEC, NSPROTO_SPX)) ==
	    OFInvalidSocketHandle) {
		*errNo = OFSocketErrNo();
		return false;
	}
319
320
321
322
323
324
325
326

327
328
329
330
331
332
333
319
320
321
322
323
324
325

326
327
328
329
330
331
332
333







-
+







{
	OFSocketAddress address;
#if SOCK_CLOEXEC == 0 && defined(HAVE_FCNTL_H) && defined(FD_CLOEXEC)
	int flags;
#endif

	if (_socket != OFInvalidSocketHandle)
		@throw [OFAlreadyConnectedException exceptionWithSocket: self];
		@throw [OFAlreadyOpenException exceptionWithObject: self];

	address = OFSocketAddressMakeIPX(network, node, port);

	if ((_socket = socket(address.sockaddr.ipx.sipx_family,
	    SOCK_SEQPACKET | SOCK_CLOEXEC, NSPROTO_SPX)) ==
	    OFInvalidSocketHandle)
		@throw [OFBindIPXSocketFailedException

Modified src/OFSPXStreamSocket.h from [454aa9fc7f] to [4f8a3b42d0].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
87
88
89
90
91
92
93
94

95
96
97
98
99
100
101
87
88
89
90
91
92
93

94
95
96
97
98
99
100
101







-
+







 * @brief Connect the OFSPXStreamSocket to the specified destination.
 *
 * @param network The network on which the node to connect to is
 * @param node The node to connect to
 * @param port The port (sometimes also called socket number) on the node to
 *	       connect to
 * @throw OFConnectSPXSocketFailedException Connecting failed
 * @throw OFAlreadyConnectedException The socket is already connected or bound
 * @throw OFAlreadyOpenException The socket is already connected or bound
 */
- (void)connectToNetwork: (uint32_t)network
		    node: (const unsigned char [_Nonnull IPX_NODE_LEN])node
		    port: (uint16_t)port;

/**
 * @brief Asynchronously connect the OFSPXStreamSocket to the specified
165
166
167
168
169
170
171
172

173
174
175
176
177
178
179
180
165
166
167
168
169
170
171

172
173
174
175
176
177
178
179
180







-
+








 * @param network The IPX network to bind to. 0 means the current network.
 * @param node The IPX network to bind to. An all zero node means the
 *	       computer's node.
 * @param port The port (sometimes called socket number) to bind to. 0 means to
 *	       pick one and return via the returned socket address.
 * @return The address on which this socket can be reached
 * @throw OFBindIPXSocketFailedException Binding failed
 * @throw OFAlreadyConnectedException The socket is already connected or bound
 * @throw OFAlreadyOpenException The socket is already connected or bound
 */
- (OFSocketAddress)
    bindToNetwork: (uint32_t)network
	     node: (const unsigned char [_Nonnull IPX_NODE_LEN])node
	     port: (uint16_t)port;
@end

OF_ASSUME_NONNULL_END

Modified src/OFSPXStreamSocket.m from [3d76de2dbb] to [84fad71fcc].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
19
20
21
22
23
24
25
26

27
28
29
30
31
32
33
19
20
21
22
23
24
25

26
27
28
29
30
31
32
33







-
+








#import "OFSPXStreamSocket.h"
#import "OFRunLoop.h"
#import "OFRunLoop+Private.h"
#import "OFSocket.h"
#import "OFSocket+Private.h"

#import "OFAlreadyConnectedException.h"
#import "OFAlreadyOpenException.h"
#import "OFBindIPXSocketFailedException.h"
#import "OFConnectSPXSocketFailedException.h"
#import "OFNotOpenException.h"

#ifndef NSPROTO_SPX
# define NSPROTO_SPX 0
#endif
183
184
185
186
187
188
189
190

191
192
193
194
195
196
197
183
184
185
186
187
188
189

190
191
192
193
194
195
196
197







-
+







			   errNo: (int *)errNo
{
#if SOCK_CLOEXEC == 0 && defined(HAVE_FCNTL) && defined(FD_CLOEXEC)
	int flags;
#endif

	if (_socket != OFInvalidSocketHandle)
		@throw [OFAlreadyConnectedException exceptionWithSocket: self];
		@throw [OFAlreadyOpenException exceptionWithObject: self];

	if ((_socket = socket(address->sockaddr.ipx.sipx_family,
	    SOCK_STREAM | SOCK_CLOEXEC, NSPROTO_SPX)) ==
	    OFInvalidSocketHandle) {
		*errNo = OFSocketErrNo();
		return false;
	}
321
322
323
324
325
326
327
328

329
330
331
332
333
334
335
321
322
323
324
325
326
327

328
329
330
331
332
333
334
335







-
+







{
	OFSocketAddress address;
#if SOCK_CLOEXEC == 0 && defined(HAVE_FCNTL_H) && defined(FD_CLOEXEC)
	int flags;
#endif

	if (_socket != OFInvalidSocketHandle)
		@throw [OFAlreadyConnectedException exceptionWithSocket: self];
		@throw [OFAlreadyOpenException exceptionWithObject: self];

	address = OFSocketAddressMakeIPX(network, node, port);

	if ((_socket = socket(address.sockaddr.ipx.sipx_family,
	    SOCK_STREAM | SOCK_CLOEXEC, NSPROTO_SPX)) == OFInvalidSocketHandle)
		@throw [OFBindIPXSocketFailedException
		    exceptionWithNetwork: network

Modified src/OFSandbox.h from [021642ddcf] to [b0b31c3419].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFSandbox.m from [de6e0ab02e] to [b6906cfa7e].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFScrypt.h from [6e03e1f0df] to [63b891bfcc].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFScrypt.m from [730aa203eb] to [69a94bdd53].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFSecureData.h from [9dc679ab94] to [5deb9cb9cd].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
100
101
102
103
104
105
106
107

108
109
110
111
112
113
114
100
101
102
103
104
105
106

107
108
109
110
111
112
113
114







-
+







+ (instancetype)dataWithItemsNoCopy: (void *)items
			      count: (size_t)count
			   itemSize: (size_t)itemSize
		       freeWhenDone: (bool)freeWhenDone OF_UNAVAILABLE;
#ifdef OF_HAVE_FILES
+ (instancetype)dataWithContentsOfFile: (OFString *)path OF_UNAVAILABLE;
#endif
+ (instancetype)dataWithContentsOfURI: (OFURI *)URI OF_UNAVAILABLE;
+ (instancetype)dataWithContentsOfIRI: (OFIRI *)IRI OF_UNAVAILABLE;
+ (instancetype)dataWithStringRepresentation: (OFString *)string OF_UNAVAILABLE;
+ (instancetype)dataWithBase64EncodedString: (OFString *)string OF_UNAVAILABLE;

/**
 * @brief Initializes an already allocated OFSecureData with `count` items of
 *	  item size 1, all set to zero.
 *
146
147
148
149
150
151
152
153

154
155
156
157
158
159
160
161
162
163
146
147
148
149
150
151
152

153
154
155

156
157
158
159
160
161
162







-
+


-







- (instancetype)initWithItemsNoCopy: (void *)items
			      count: (size_t)count
			   itemSize: (size_t)itemSize
		       freeWhenDone: (bool)freeWhenDone OF_UNAVAILABLE;
#ifdef OF_HAVE_FILES
- (instancetype)initWithContentsOfFile: (OFString *)path OF_UNAVAILABLE;
#endif
- (instancetype)initWithContentsOfURI: (OFURI *)URI OF_UNAVAILABLE;
- (instancetype)initWithContentsOfIRI: (OFIRI *)IRI OF_UNAVAILABLE;
- (instancetype)initWithStringRepresentation: (OFString *)string OF_UNAVAILABLE;
- (instancetype)initWithBase64EncodedString: (OFString *)string OF_UNAVAILABLE;
- (instancetype)initWithSerialization: (OFXMLElement *)element OF_UNAVAILABLE;

/**
 * @brief Returns a specific item of the OFSecureData.
 *
 * Modifying the returned item directly is allowed and will change the contents
 * of the data array.
 *
183
184
185
186
187
188
189
190

191
192
193
194
195
182
183
184
185
186
187
188

189

190
191
192
193







-
+
-




- (void)zero;

- (OFString *)stringRepresentation OF_UNAVAILABLE;
- (OFString *)stringByBase64Encoding OF_UNAVAILABLE;
#ifdef OF_HAVE_FILES
- (void)writeToFile: (OFString *)path OF_UNAVAILABLE;
#endif
- (void)writeToURI: (OFURI *)URI OF_UNAVAILABLE;
- (void)writeToIRI: (OFIRI *)IRI OF_UNAVAILABLE;
- (OFXMLElement *)XMLElementBySerializing OF_UNAVAILABLE;
- (OFData *)messagePackRepresentation OF_UNAVAILABLE;
@end

OF_ASSUME_NONNULL_END

Modified src/OFSecureData.m from [7420c1ca0e] to [47b9727f66].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
371
372
373
374
375
376
377
378

379
380
381
382
383
384
385
371
372
373
374
375
376
377

378
379
380
381
382
383
384
385







-
+







#ifdef OF_HAVE_FILES
+ (instancetype)dataWithContentsOfFile: (OFString *)path
{
	OF_UNRECOGNIZED_SELECTOR
}
#endif

+ (instancetype)dataWithContentsOfURI: (OFURI *)URI
+ (instancetype)dataWithContentsOfIRI: (OFIRI *)IRI
{
	OF_UNRECOGNIZED_SELECTOR
}

+ (instancetype)dataWithStringRepresentation: (OFString *)string
{
	OF_UNRECOGNIZED_SELECTOR
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
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







-
+











-
-
-
-
-







#ifdef OF_HAVE_FILES
- (instancetype)initWithContentsOfFile: (OFString *)path
{
	OF_INVALID_INIT_METHOD
}
#endif

- (instancetype)initWithContentsOfURI: (OFURI *)URI
- (instancetype)initWithContentsOfIRI: (OFIRI *)IRI
{
	OF_INVALID_INIT_METHOD
}

- (instancetype)initWithStringRepresentation: (OFString *)string
{
	OF_INVALID_INIT_METHOD
}

- (instancetype)initWithBase64EncodedString: (OFString *)string
{
	OF_INVALID_INIT_METHOD
}

- (instancetype)initWithSerialization: (OFXMLElement *)element
{
	OF_INVALID_INIT_METHOD
}

- (void)dealloc
{
	[self zero];

627
628
629
630
631
632
633
634

635
636
637
638
639
640
641
642
643
644
645
646
647
648
622
623
624
625
626
627
628

629





630
631
632
633
634
635
636
637
638







-
+
-
-
-
-
-









#ifdef OF_HAVE_FILES
- (void)writeToFile: (OFString *)path
{
	OF_UNRECOGNIZED_SELECTOR
}
#endif

- (void)writeToURI: (OFURI *)URI
- (void)writeToIRI: (OFIRI *)IRI
{
	OF_UNRECOGNIZED_SELECTOR
}

- (OFXMLElement *)XMLElementBySerializing
{
	OF_UNRECOGNIZED_SELECTOR
}

- (OFData *)messagePackRepresentation
{
	OF_UNRECOGNIZED_SELECTOR
}
@end

Modified src/OFSeekableStream.h from [b1e0890846] to [68192be558].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFSeekableStream.m from [b6c980d4ae] to [2562cc911f].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFSelectKernelEventObserver.h from [87e3b347a2] to [64179882e4].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFSelectKernelEventObserver.m from [178271bdfe] to [29596447ca].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
34
35
36
37
38
39
40

41

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







+

+







#import "OFSocket+Private.h"

#import "OFInitializationFailedException.h"
#import "OFObserveKernelEventsFailedException.h"
#import "OFOutOfRangeException.h"

#ifdef OF_AMIGAOS
# define Class IntuitionClass
# include <proto/exec.h>
# undef Class
#endif

#ifdef OF_HPUX
/* FD_SET causes warnings on HP-UX/IA64. */
# pragma GCC diagnostic ignored "-Wstrict-aliasing"
#endif

Modified src/OFSequencedPacketSocket+Private.h from [779ca7e02d] to [26961b2ac6].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFSequencedPacketSocket.h from [0f03522481] to [2027150bf7].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFSequencedPacketSocket.m from [8882acf9d8] to [2cba19ddea].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Deleted src/OFSerialization.h version [6c8c4c9563].

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





















































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 */

#import "OFObject.h"

OF_ASSUME_NONNULL_BEGIN

@class OFConstantString;
@class OFXMLElement;

/**
 * @protocol OFSerialization OFSerialization.h ObjFW/OFSerialization.h
 *
 * @brief A protocol for serializing objects.
 */
@protocol OFSerialization
/**
 * @brief The object serialized into an XML element.
 */
@property (readonly, nonatomic) OFXMLElement *XMLElementBySerializing;

/**
 * @brief Initializes the object with the specified XML element serialization.
 *
 * @param element An OFXMLElement with the serialized object
 * @return An initialized object
 * @throw OFInvalidFormatException The specified element is not of the correct
 *				   serialization format
 */
- (instancetype)initWithSerialization: (OFXMLElement *)element;
@end

#ifdef __cplusplus
extern "C" {
#endif
extern OFConstantString *const OFSerializationNS;
#ifdef __cplusplus
}
#endif

OF_ASSUME_NONNULL_END

Deleted src/OFSerialization.m version [0e1e99b940].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20




















-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 */

#import "OFSerialization.h"
#import "OFString.h"

OFConstantString *const OFSerializationNS =
    @"https://objfw.nil.im/serialization";

Modified src/OFSet.h from [4c0dd3a76f] to [b6b0fc8990].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
20
21
22
23
24
25
26

27
28
29
30
31
32
33







-







# define __STDC_CONSTANT_MACROS
#endif

#include <stdarg.h>

#import "OFObject.h"
#import "OFCollection.h"
#import "OFSerialization.h"

OF_ASSUME_NONNULL_BEGIN

/** @file */

@class OFArray OF_GENERIC(ObjectType);

59
60
61
62
63
64
65
66

67
68
69
70
71
72
73
58
59
60
61
62
63
64

65
66
67
68
69
70
71
72







-
+







 * @warning Do not mutate objects that are in a set! Changing the hash of
 *	    objects in a set breaks the internal representation of the set!
 *
 * @note Subclasses must implement @ref count, @ref containsObject: and
 *	 @ref objectEnumerator.
 */
@interface OFSet OF_GENERIC(ObjectType): OFObject <OFCollection, OFCopying,
    OFMutableCopying, OFSerialization>
    OFMutableCopying>
#if !defined(OF_HAVE_GENERICS) && !defined(DOXYGEN)
# define ObjectType id
#endif
/**
 * @brief An array of all objects in the set.
 */
@property (readonly, nonatomic) OFArray OF_GENERIC(ObjectType) *allObjects;

Modified src/OFSet.m from [c2dcb9f429] to [a5c8b76a0d].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
18
19
20
21
22
23
24

25
26
27
28
29
30
31







-







#include <stdlib.h>

#import "OFSet.h"
#import "OFArray.h"
#import "OFMapTableSet.h"
#import "OFNull.h"
#import "OFString.h"
#import "OFXMLElement.h"

static struct {
	Class isa;
} placeholder;

@interface OFSetPlaceholder: OFSet
@end
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
67
68
69
70
71
72
73





74
75
76
77
78
79
80







-
-
-
-
-








- (instancetype)initWithObject: (id)firstObject arguments: (va_list)arguments
{
	return (id)[[OFMapTableSet alloc] initWithObject: firstObject
					       arguments: arguments];
}

- (instancetype)initWithSerialization: (OFXMLElement *)element
{
	return (id)[[OFMapTableSet alloc] initWithSerialization: element];
}

- (instancetype)retain
{
	return self;
}

- (instancetype)autorelease
{
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
181
182
183
184
185
186
187





188
189
190
191
192
193
194







-
-
-
-
-







	va_end(arguments);

	return ret;
}

- (instancetype)initWithObject: (id)firstObject arguments: (va_list)arguments
{
	OF_INVALID_INIT_METHOD
}

- (instancetype)initWithSerialization: (OFXMLElement *)element
{
	OF_INVALID_INIT_METHOD
}

- (size_t)count
{
	OF_UNRECOGNIZED_SELECTOR
}
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
347
348
349
350
351
352
353

























354
355
356
357
358
359
360







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







	for (id object in self)
		if ([set containsObject: object])
			return true;

	return false;
}

- (OFXMLElement *)XMLElementBySerializing
{
	void *pool = objc_autoreleasePoolPush();
	OFXMLElement *element;

	if ([self isKindOfClass: [OFMutableSet class]])
		element = [OFXMLElement elementWithName: @"OFMutableSet"
					      namespace: OFSerializationNS];
	else
		element = [OFXMLElement elementWithName: @"OFSet"
					      namespace: OFSerializationNS];

	for (id <OFSerialization> object in self) {
		void *pool2 = objc_autoreleasePoolPush();
		[element addChild: object.XMLElementBySerializing];
		objc_autoreleasePoolPop(pool2);
	}

	[element retain];

	objc_autoreleasePoolPop(pool);

	return [element autorelease];
}

- (OFSet *)setByAddingObjectsFromSet: (OFSet *)set
{
	OFMutableSet *new = [[self mutableCopy] autorelease];
	[new unionSet: set];
	[new makeImmutable];
	return new;
}

Modified src/OFSettings.h from [372d44cad4] to [6945e02ad5].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFSettings.m from [206814d076] to [ca8870c245].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFSizeValue.h from [d063d8cdb8] to [2412c94f4a].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFSizeValue.m from [86214acf8b] to [664c2dc1a6].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFSocket+Private.h from [00458f91c6] to [ba231b2658].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFSocket.h from [18fc1aa593] to [413740135d].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
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
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







-
-











+
+







#  include <wsipx.h>
# endif
# ifdef OF_HAVE_APPLETALK
#  include <atalkwsh.h>
# endif
#endif

/** @file */

#ifdef OF_WII
# include <network.h>
#endif

#ifdef OF_PSP
# include <stdint.h>
#endif

#import "macros.h"

OF_ASSUME_NONNULL_BEGIN

/** @file */

#ifndef OF_WINDOWS
typedef int OFSocketHandle;
static const OFSocketHandle OFInvalidSocketHandle = -1;
#else
typedef SOCKET OFSocketHandle;
static const OFSocketHandle OFInvalidSocketHandle = INVALID_SOCKET;
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
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







-
+

+
+







-
-
+





+
+
+






-
-
-
+
+
-

-
-
-
-
-
-
+
+
+
+
+
+
+



















+
+
+
+
+
+
+







#if !defined(OF_HAVE_UNIX_SOCKETS) && !defined(OF_MORPHOS) && !defined(OF_MINT)
struct sockaddr_un {
	sa_family_t sun_family;
	char sun_path[108];
};
#endif

#ifndef OF_HAVE_IPX
#ifndef IPX_NODE_LEN
# define IPX_NODE_LEN 6
#endif
#if !defined(OF_HAVE_IPX)
struct sockaddr_ipx {
	sa_family_t sipx_family;
	uint32_t sipx_network;
	unsigned char sipx_node[IPX_NODE_LEN];
	uint16_t sipx_port;
	uint8_t sipx_type;
};
#endif
#ifdef OF_WINDOWS
#elif defined(OF_WINDOWS)
# define IPX_NODE_LEN 6
# define sipx_family sa_family
# define sipx_network sa_netnum
# define sipx_node sa_nodenum
# define sipx_port sa_socket
#elif defined(OF_FREEBSD)
# define sipx_network sipx_addr.x_net.c_net
# define sipx_node sipx_addr.x_host.c_host
#endif

#ifndef OF_HAVE_APPLETALK
struct sockaddr_at {
	sa_family_t sat_family;
	uint8_t sat_port;
	struct at_addr {
		uint16_t s_net;
		uint8_t s_node;
	uint16_t sat_net;
	uint8_t sat_node;
	} sat_addr;
};
#endif
#ifdef OF_WINDOWS
# define sat_port sat_socket
#else
# define sat_net sat_addr.s_net
# define sat_node sat_addr.s_node
#else
# ifdef OF_WINDOWS
#  define sat_port sat_socket
# else
#  define sat_net sat_addr.s_net
#  define sat_node sat_addr.s_node
# endif
#endif

/**
 * @struct OFSocketAddress OFSocket.h ObjFW/OFSocket.h
 *
 * @brief A struct which represents a host / port pair for a socket.
 */
typedef struct OF_BOXABLE {
	OFSocketAddressFamily family;
	/*
	 * We can't use struct sockaddr as it can contain variable length
	 * arrays.
	 */
	union {
		struct sockaddr_in in;
		struct sockaddr_in6 in6;
		struct sockaddr_un un;
		struct sockaddr_ipx ipx;
		struct sockaddr_at at;
#ifdef OF_HAVE_SOCKADDR_STORAGE
		/*
		 * Required to make the ABI stable in case we want to add more
		 * address types later.
		 */
		struct sockaddr_storage storage;
#endif
	} sockaddr;
	socklen_t length;
} OFSocketAddress;

#ifdef __cplusplus
extern "C" {
#endif
276
277
278
279
280
281
282
283

284
285
286
287
288
289
290
286
287
288
289
290
291
292

293
294
295
296
297
298
299
300







-
+







extern unsigned long OFSocketAddressHash(
    const OFSocketAddress *_Nonnull address);

/**
 * @brief Converts the specified @ref OFSocketAddress to a string.
 *
 * @param address The address to convert to a string
 * @return The address as an IP string
 * @return The address as an IP string, without the port
 */
extern OFString *_Nonnull OFSocketAddressString(
    const OFSocketAddress *_Nonnull address);

/**
 * @brief Sets the IP port of the specified @ref OFSocketAddress.
 *

Modified src/OFSocket.m from [3facc57fe7] to [f0f36303c9].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
49
50
51
52
53
54
55

56

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







+

+







#import "OFUnlockFailedException.h"

#ifdef HAVE_NET_IF_H
# include <net/if.h>
#endif

#ifdef OF_AMIGAOS
# define Class IntuitionClass
# include <proto/exec.h>
# undef Class
#endif

#ifdef OF_NINTENDO_3DS
# include <3ds/types.h>
# include <3ds/services/soc.h>
#endif

426
427
428
429
430
431
432




























433
434
435
436
437
438
439
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







	number = [component unsignedLongLongValueWithBase: 16];

	if (number > UINT16_MAX)
		@throw [OFInvalidFormatException exception];

	return (uint16_t)number;
}

static OFString *
transformEmbeddedIPv4(OFString *IPv6)
{
	size_t lastColon = [IPv6
	    rangeOfString: @":"
		  options: OFStringSearchBackwards].location;
	OFString *IPv4;
	OFSocketAddress address;
	const struct sockaddr_in *addrIn;
	uint32_t addr;

	if (lastColon == OFNotFound)
		@throw [OFInvalidFormatException exception];

	IPv4 = [IPv6 substringWithRange:
	    OFMakeRange(lastColon + 1, IPv6.length - lastColon - 1)];
	IPv6 = [IPv6 substringWithRange: OFMakeRange(0, lastColon + 1)];

	address = OFSocketAddressParseIPv4(IPv4, 0);
	addrIn = &address.sockaddr.in;
	addr = OFFromBigEndian32(addrIn->sin_addr.s_addr);

	return [IPv6 stringByAppendingString:
	    [OFString stringWithFormat: @"%x%02x:%x%02x",
	    (addr & 0xFF000000) >> 24, (addr & 0x00FF0000) >> 16,
	    (addr & 0x0000FF00) >>  8, addr & 0x000000FF]];
}

OFSocketAddress
OFSocketAddressParseIPv6(OFString *IPv6, uint16_t port)
{
	void *pool = objc_autoreleasePoolPush();
	OFSocketAddress ret;
	struct sockaddr_in6 *addrIn6 = &ret.sockaddr.in6;
463
464
465
466
467
468
469



470
471
472
473
474
475
476
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509







+
+
+







			    cStringWithEncoding: [OFLocale encoding]]);
#endif
		}

		if (addrIn6->sin6_scope_id == 0)
			@throw [OFInvalidArgumentException exception];
	}

	if ([IPv6 rangeOfString: @"."].location != OFNotFound)
		IPv6 = transformEmbeddedIPv4(IPv6);

	doubleColon = [IPv6 rangeOfString: @"::"].location;
	if (doubleColon != OFNotFound) {
		OFString *left = [IPv6 substringToIndex: doubleColon];
		OFString *right = [IPv6 substringFromIndex: doubleColon + 2];
		OFArray OF_GENERIC(OFString *) *leftComponents;
		OFArray OF_GENERIC(OFString *) *rightComponents;
553
554
555
556
557
558
559



560
561
562
563
564
565
566
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602







+
+
+







		@throw [OFOutOfRangeException exception];

	memset(&ret, '\0', sizeof(ret));
	ret.family = OFSocketAddressFamilyUNIX;
	ret.length = (socklen_t)
	    (offsetof(struct sockaddr_un, sun_path) + length);

#ifdef HAVE_STRUCT_SOCKADDR_UN_SUN_LEN
	ret.sockaddr.un.sun_len = (uint8_t)length;
#endif
#ifdef AF_UNIX
	ret.sockaddr.un.sun_family = AF_UNIX;
#else
	ret.sockaddr.un.sun_family = AF_UNSPEC;
#endif
	memcpy(ret.sockaddr.un.sun_path,
	    [path cStringWithEncoding: encoding], length);
902
903
904
905
906
907
908




























909
910
911
912
913
914
915
916
917




918
919
920
921
922
923
924
938
939
940
941
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
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+









+
+
+
+







			[string appendFormat: @"%%%u", addrIn6->sin6_scope_id];
	}

	[string makeImmutable];

	return string;
}

static OFString *
IPXString(const OFSocketAddress *address)
{
	const struct sockaddr_ipx *addrIPX = &address->sockaddr.ipx;
	uint32_t network;
	uint64_t node;

	memcpy(&network, &addrIPX->sipx_network, sizeof(addrIPX->sipx_network));
	node = ((uint64_t)addrIPX->sipx_node[0] << 40) |
	    ((uint64_t)addrIPX->sipx_node[1] << 32) |
	    ((uint64_t)addrIPX->sipx_node[2] << 24) |
	    ((uint64_t)addrIPX->sipx_node[3] << 16) |
	    ((uint64_t)addrIPX->sipx_node[4] << 8) |
	    (uint64_t)addrIPX->sipx_node[5];

	return [OFString stringWithFormat: @"%X.%X",
	    OFFromBigEndian32(network), node];
}

static OFString *
appleTalkString(const OFSocketAddress *address)
{
	const struct sockaddr_at *addrAT = &address->sockaddr.at;

	return [OFString stringWithFormat: @"%d.%d",
	    OFFromBigEndian16(addrAT->sat_net), addrAT->sat_node];
}

OFString *
OFSocketAddressString(const OFSocketAddress *address)
{
	switch (address->family) {
	case OFSocketAddressFamilyIPv4:
		return IPv4String(address);
	case OFSocketAddressFamilyIPv6:
		return IPv6String(address);
	case OFSocketAddressFamilyIPX:
		return IPXString(address);
	case OFSocketAddressFamilyAppleTalk:
		return appleTalkString(address);
	default:
		@throw [OFInvalidArgumentException exception];
	}
}

void
OFSocketAddressSetIPPort(OFSocketAddress *address, uint16_t port)

Modified src/OFSortedList.h from [3a5eb28c9b] to [486e46ba06].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFSortedList.m from [8d1674288f] to [e567fdf878].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFStdIOStream+Private.h from [9900a9e7b0] to [946d085dd6].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFStdIOStream.h from [04d80731e3] to [cf87acec37].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFStdIOStream.m from [9ab60802c8] to [529c4f7d2f].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
43
44
45
46
47
48
49

50
51

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







+


+







#import "OFWriteFailedException.h"

#ifdef OF_IOS
# undef HAVE_ISATTY
#endif

#ifdef OF_AMIGAOS
# define Class IntuitionClass
# include <proto/exec.h>
# include <proto/dos.h>
# undef Class
# undef HAVE_ISATTY
#endif

#ifdef OF_WII_U
# define BOOL WUT_BOOL
# include <coreinit/debug.h>
# undef BOOL
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
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







-
+














-
+







#else
	return false;
#endif
}

- (int)columns
{
#if defined(HAVE_SYS_IOCTL_H) && defined(TIOCGWINSZ) && \
#if defined(HAVE_IOCTL) && defined(TIOCGWINSZ) && \
    !defined(OF_AMIGAOS) && !defined(OF_WII_U)
	struct winsize ws;

	if (ioctl(_fd, TIOCGWINSZ, &ws) != 0)
		return -1;

	return ws.ws_col;
#else
	return -1;
#endif
}

- (int)rows
{
#if defined(HAVE_SYS_IOCTL_H) && defined(TIOCGWINSZ) && \
#if defined(HAVE_IOCTL) && defined(TIOCGWINSZ) && \
    !defined(OF_AMIGAOS) && !defined(OF_WII_U)
	struct winsize ws;

	if (ioctl(_fd, TIOCGWINSZ, &ws) != 0)
		return -1;

	return ws.ws_row;

Modified src/OFStrPTime.h from [0432d594e4] to [5d7071f263].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFStrPTime.m from [7afa230e7d] to [998c03b4a3].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFStream+Private.h from [571ecdcdc3] to [494fcdeb75].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFStream.h from [a93512463b] to [5e35ef7c78].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFStream.m from [5428225ee7] to [15b8e35c16].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFStreamSocket+Private.h from [a23e5c50d7] to [96bc865f7e].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFStreamSocket.h from [700ee89673] to [09d6517bdb].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFStreamSocket.m from [21ea0af8b5] to [0cffca82b0].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
238
239
240
241
242
243
244
245

246
247
248
249
250
251




252
253
254
255
256
257
258
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







-
+






+
+
+
+







				  errNo: OFSocketErrNo()];

	_listening = true;
}

- (instancetype)accept
{
	OFStreamSocket *client = [[[[self class] alloc] init] autorelease];
	OFStreamSocket *client;
#if (!defined(HAVE_PACCEPT) && !defined(HAVE_ACCEPT4)) || !defined(SOCK_CLOEXEC)
# if defined(HAVE_FCNTL) && defined(FD_CLOEXEC)
	int flags;
# endif
#endif

	if (_socket == OFInvalidSocketHandle)
		@throw [OFNotOpenException exceptionWithObject: self];

	client = [[[[self class] alloc] init] autorelease];
	client->_remoteAddress.length =
	    (socklen_t)sizeof(client->_remoteAddress.sockaddr);

#if defined(HAVE_PACCEPT) && defined(SOCK_CLOEXEC)
	if ((client->_socket = paccept(_socket,
	    (struct sockaddr *)&client->_remoteAddress.sockaddr,
	    &client->_remoteAddress.length, NULL, SOCK_CLOEXEC)) ==

Modified src/OFString+CryptographicHashing.h from [63c51821ee] to [c339271bd0].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFString+CryptographicHashing.m from [30b5bea6f8] to [c8ac10a120].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFString+JSONParsing.h from [77287ce8c5] to [15a4cfdf81].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFString+JSONParsing.m from [4b9a43cc0d] to [a752f4ba41].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFString+PathAdditions.h from [01351c2d45] to [4c7a8f9d29].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
82
83
84
85
86
87
88
89

90
91

92
93

94
95
96
82
83
84
85
86
87
88

89
90

91
92

93
94
95
96







-
+

-
+

-
+



 *
 * @param extension The extension to append
 * @return A new, autoreleased OFString with the path extension appended
 */
- (OFString *)stringByAppendingPathExtension: (OFString *)extension;

- (bool)of_isDirectoryPath;
- (OFString *)of_pathToURIPathWithPercentEncodedHost:
- (OFString *)of_pathToIRIPathWithPercentEncodedHost:
    (OFString *__autoreleasing _Nullable *_Nonnull)percentEncodedHost;
- (OFString *)of_URIPathToPathWithPercentEncodedHost:
- (OFString *)of_IRIPathToPathWithPercentEncodedHost:
    (nullable OFString *)percentEncodedHost;
- (OFString *)of_pathComponentToURIPathComponent;
- (OFString *)of_pathComponentToIRIPathComponent;
@end

OF_ASSUME_NONNULL_END

Modified src/OFString+PathAdditions.m from [dfeb40c068] to [a252f81de7].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFString+PercentEncoding.h from [8762d6fc4c] to [39a0f104a2].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
32
33
34
35
36
37
38
39

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

39
40
41
42
43
44
45
46
47
48
49
50
51







-
+












 * @brief The string with percent encoding removed.
 *
 * @throw OFInvalidFormatException The string is not in proper percent encoding
 */
@property (readonly, nonatomic) OFString *stringByRemovingPercentEncoding;

/**
 * @brief Percent-encodes a string for use in a URI, but does not escape the
 * @brief Percent-encodes a string for use in an IRI, but does not escape the
 *	  specified allowed characters.
 *
 * @param allowedCharacters A character set of characters that should not be
 *			    escaped
 *
 * @return A new autoreleased string
 */
- (OFString *)stringByAddingPercentEncodingWithAllowedCharacters:
    (OFCharacterSet *)allowedCharacters;
@end

OF_ASSUME_NONNULL_END

Modified src/OFString+PercentEncoding.m from [46a599b120] to [b6b707c8fb].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFString+PropertyListParsing.h from [6aa9059d9b] to [30a54273cc].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFString+PropertyListParsing.m from [4a79f533f5] to [9065519967].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Deleted src/OFString+Serialization.h version [6689bf6870].

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










































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 */

#import "OFString.h"

OF_ASSUME_NONNULL_BEGIN

#ifdef __cplusplus
extern "C" {
#endif
extern int _OFString_Serialization_reference;
#ifdef __cplusplus
}
#endif

@interface OFString (Serialization)
/**
 * @brief The string interpreted as serialization and parsed as an object.
 *
 * @throw OFMalformedXMLException The XML was malformed
 * @throw OFUnboundNamespaceException A prefix was used that was not bound to
 *				      any namespace
 * @throw OFInvalidEncodingException The XML is not in the encoding it specified
 * @throw OFUnsupportedVersionException The serialization is in an unsupported
 *					version
 */
@property (readonly, nonatomic) id objectByDeserializing;
@end

OF_ASSUME_NONNULL_END

Deleted src/OFString+Serialization.m version [a02a87cd97].

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






























































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * 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 "OFString.h"
#import "OFString+Serialization.h"
#import "OFSerialization.h"
#import "OFArray.h"
#import "OFXMLElement.h"
#import "OFXMLAttribute.h"

#import "OFInvalidArgumentException.h"
#import "OFMalformedXMLException.h"
#import "OFUnboundNamespaceException.h"
#import "OFUnsupportedVersionException.h"

int _OFString_Serialization_reference;

@implementation OFString (Serialization)
- (id)objectByDeserializing
{
	void *pool = objc_autoreleasePoolPush();
	OFXMLElement *root;
	OFString *version;
	OFArray *elements;
	id object;

	root = [OFXMLElement elementWithXMLString: self];

	version = [root attributeForName: @"version"].stringValue;
	if (version == nil)
		@throw [OFInvalidArgumentException exception];

	if (version.unsignedLongLongValue != 1)
		@throw [OFUnsupportedVersionException
		    exceptionWithVersion: version];

	elements = [root elementsForNamespace: OFSerializationNS];

	if (elements.count != 1)
		@throw [OFInvalidArgumentException exception];

	object = [[elements.firstObject objectByDeserializing] retain];

	objc_autoreleasePoolPop(pool);

	return [object autorelease];
}
@end

Modified src/OFString+XMLEscaping.h from [5e7ff84170] to [12c720bd57].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFString+XMLEscaping.m from [32ead971e3] to [b774b5c0bf].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFString+XMLUnescaping.h from [5fc70e7ddb] to [4b295ec8c5].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFString+XMLUnescaping.m from [dd8350c1c8] to [99e235e23a].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFString.h from [780687227d] to [55ba0a041b].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
33
34
35
36
37
38
39

40
41
42
43
44
45
46







-







#include <stdint.h>
#ifdef OF_HAVE_INTTYPES_H
# include <inttypes.h>
#endif

#include "OFObject.h"
#ifdef __OBJC__
# import "OFSerialization.h"
# import "OFJSONRepresentation.h"
# import "OFMessagePackRepresentation.h"
#endif

OF_ASSUME_NONNULL_BEGIN

/** @file */
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
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







-
+







-
+












-
+







 */
typedef void (^OFStringLineEnumerationBlock)(OFString *line, bool *stop);
#endif

#ifdef __OBJC__
@class OFArray OF_GENERIC(ObjectType);
@class OFCharacterSet;
@class OFURI;
@class OFIRI;

/**
 * @class OFString OFString.h ObjFW/OFString.h
 *
 * @brief A class for handling strings.
 */
@interface OFString: OFObject <OFCopying, OFMutableCopying, OFComparing,
    OFSerialization, OFJSONRepresentation, OFMessagePackRepresentation>
    OFJSONRepresentation, OFMessagePackRepresentation>
/**
 * @brief The length of the string in Unicode codepoints.
 */
@property (readonly, nonatomic) size_t length;

/**
 * @brief The OFString as a UTF-8 encoded C string.
 *
 * The result is valid until the autorelease pool is released. If you want to
 * use the result outside the scope of the current autorelease pool, you have to
 * copy it.
 */
@property (readonly, nonatomic) const char *UTF8String OF_RETURNS_INNER_POINTER;
@property (readonly, nonatomic) const char *UTF8String;

/**
 * @brief The number of bytes the string needs in UTF-8 encoding.
 */
@property (readonly, nonatomic) size_t UTF8StringLength;

/**
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
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







-
+
-










-
+
-















-
+
-







 *
 * The result is valid until the autorelease pool is released. If you want to
 * use the result outside the scope of the current autorelease pool, you have to
 * copy it.
 *
 * The returned string is *not* null-terminated.
 */
@property (readonly, nonatomic) const OFUnichar *characters
@property (readonly, nonatomic) const OFUnichar *characters;
    OF_RETURNS_INNER_POINTER;

/**
 * @brief The string in UTF-16 encoding with native byte order.
 *
 * The result is valid until the autorelease pool is released. If you want to
 * use the result outside the scope of the current autorelease pool, you have to
 * copy it.
 *
 * The returned string is null-terminated.
 */
@property (readonly, nonatomic) const OFChar16 *UTF16String
@property (readonly, nonatomic) const OFChar16 *UTF16String;
    OF_RETURNS_INNER_POINTER;

/**
 * @brief The length of the string in UTF-16 characters.
 */
@property (readonly, nonatomic) size_t UTF16StringLength;

/**
 * @brief The string in UTF-32 encoding with native byte order.
 *
 * The result is valid until the autorelease pool is released. If you want to
 * use the result outside the scope of the current autorelease pool, you have to
 * copy it.
 *
 * The returned string is null-terminated.
 */
@property (readonly, nonatomic) const OFChar32 *UTF32String
@property (readonly, nonatomic) const OFChar32 *UTF32String;
    OF_RETURNS_INNER_POINTER;

/**
 * @brief The string with leading whitespaces deleted.
 */
@property (readonly, nonatomic) OFString *stringByDeletingLeadingWhitespaces;

/**
551
552
553
554
555
556
557
558

559
560

561
562

563
564
565
566

567
568
569
570

571
572
573

574
575
576

577
578
579
580
581

582
583
584
585
586
587
588
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

572
573
574
575
576

577
578
579
580
581
582
583
584







-
+

-
+

-
+



-
+



-
+


-
+


-
+




-
+







 * @throw OFInvalidEncodingException The string is not in the specified encoding
 */
+ (instancetype)stringWithContentsOfFile: (OFString *)path
				encoding: (OFStringEncoding)encoding;
# endif

/**
 * @brief Creates a new OFString with the contents of the specified URI.
 * @brief Creates a new OFString with the contents of the specified IRI.
 *
 * If the URI's scheme is file, it tries UTF-8 encoding.
 * If the IRI's scheme is file, it tries UTF-8 encoding.
 *
 * If the URI's scheme is http(s), it tries to detect the encoding from the HTTP
 * If the IRI's scheme is http(s), it tries to detect the encoding from the HTTP
 * headers. If it could not detect the encoding using the HTTP headers, it tries
 * UTF-8.
 *
 * @param URI The URI to the contents for the string
 * @param IRI The IRI to the contents for the string
 * @return A new autoreleased OFString
 * @throw OFInvalidEncodingException The string is not in the expected encoding
 */
+ (instancetype)stringWithContentsOfURI: (OFURI *)URI;
+ (instancetype)stringWithContentsOfIRI: (OFIRI *)IRI;

/**
 * @brief Creates a new OFString with the contents of the specified URI in the
 * @brief Creates a new OFString with the contents of the specified IRI in the
 *	  specified encoding.
 *
 * @param URI The URI to the contents for the string
 * @param IRI The IRI to the contents for the string
 * @param encoding The encoding to assume
 * @return A new autoreleased OFString
 * @throw OFInvalidEncodingException The string is not in the specified encoding
 */
+ (instancetype)stringWithContentsOfURI: (OFURI *)URI
+ (instancetype)stringWithContentsOfIRI: (OFIRI *)IRI
			       encoding: (OFStringEncoding)encoding;

/**
 * @brief Initializes an already allocated OFString from a UTF-8 encoded C
 *	  string.
 *
 * @param UTF8String A UTF-8 encoded C string to initialize the OFString with
845
846
847
848
849
850
851
852

853
854

855
856

857
858
859
860

861
862
863
864

865
866
867
868

869
870

871
872
873
874
875

876
877
878
879
880
881
882
841
842
843
844
845
846
847

848
849

850
851

852
853
854
855

856
857
858
859

860
861
862
863

864
865

866
867
868
869
870

871
872
873
874
875
876
877
878







-
+

-
+

-
+



-
+



-
+



-
+

-
+




-
+







 */
- (instancetype)initWithContentsOfFile: (OFString *)path
			      encoding: (OFStringEncoding)encoding;
# endif

/**
 * @brief Initializes an already allocated OFString with the contents of the
 *	  specified URI.
 *	  specified IRI.
 *
 * If the URI's scheme is file, it tries UTF-8 encoding.
 * If the IRI's scheme is file, it tries UTF-8 encoding.
 *
 * If the URI's scheme is http(s), it tries to detect the encoding from the HTTP
 * If the IRI's scheme is http(s), it tries to detect the encoding from the HTTP
 * headers. If it could not detect the encoding using the HTTP headers, it tries
 * UTF-8.
 *
 * @param URI The URI to the contents for the string
 * @param IRI The IRI to the contents for the string
 * @return An initialized OFString
 * @throw OFInvalidEncodingException The string is not in the expected encoding
 */
- (instancetype)initWithContentsOfURI: (OFURI *)URI;
- (instancetype)initWithContentsOfIRI: (OFIRI *)IRI;

/**
 * @brief Initializes an already allocated OFString with the contents of the
 *	  specified URI in the specified encoding.
 *	  specified IRI in the specified encoding.
 *
 * @param URI The URI to the contents for the string
 * @param IRI The IRI to the contents for the string
 * @param encoding The encoding to assume
 * @return An initialized OFString
 * @throw OFInvalidEncodingException The string is not in the specified encoding
 */
- (instancetype)initWithContentsOfURI: (OFURI *)URI
- (instancetype)initWithContentsOfIRI: (OFIRI *)IRI
			     encoding: (OFStringEncoding)encoding;

/**
 * @brief Writes the OFString into the specified C string with the specified
 *	  encoding.
 *
 * @param cString The C string to write into
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
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







-
+
-













-
+
-







 * copy it.
 *
 * @param encoding The encoding for the C string
 * @return The OFString as a C string in the specified encoding
 * @throw OFInvalidEncodingException The string cannot be represented in the
 *				     specified encoding
 */
- (const char *)cStringWithEncoding: (OFStringEncoding)encoding
- (const char *)cStringWithEncoding: (OFStringEncoding)encoding;
    OF_RETURNS_INNER_POINTER;

/**
 * @brief Returns the OFString as a C string in the specified encoding,
 *	  replacing characters that cannot be represented in the specified
 *	  encoding with a question mark.
 *
 * The result is valid until the autorelease pool is released. If you want to
 * use the result outside the scope of the current autorelease pool, you have to
 * copy it.
 *
 * @param encoding The encoding for the C string
 * @return The OFString as a C string in the specified encoding
 */
- (const char *)lossyCStringWithEncoding: (OFStringEncoding)encoding
- (const char *)lossyCStringWithEncoding: (OFStringEncoding)encoding;
    OF_RETURNS_INNER_POINTER;

/**
 * @brief Returns the number of bytes the string needs in the specified
 *	  encoding.
 *
 * @param encoding The encoding for the string
 * @return The number of bytes the string needs in the specified encoding.
1254
1255
1256
1257
1258
1259
1260
1261

1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276

1277
1278
1279
1280
1281
1282
1283
1284
1248
1249
1250
1251
1252
1253
1254

1255

1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268

1269

1270
1271
1272
1273
1274
1275
1276







-
+
-













-
+
-







 *
 * The returned string is null-terminated.
 *
 * @param byteOrder The byte order for the UTF-16 encoding
 * @return The string in UTF-16 encoding with the specified byte order
 * @throw OFInvalidEncodingException The string cannot be represented in UTF-16
 */
- (const OFChar16 *)UTF16StringWithByteOrder: (OFByteOrder)byteOrder
- (const OFChar16 *)UTF16StringWithByteOrder: (OFByteOrder)byteOrder;
    OF_RETURNS_INNER_POINTER;

/**
 * @brief Returns the string in UTF-32 encoding with the specified byte order.
 *
 * The result is valid until the autorelease pool is released. If you want to
 * use the result outside the scope of the current autorelease pool, you have to
 * copy it.
 *
 * The returned string is null-terminated.
 *
 * @param byteOrder The byte order for the UTF-32 encoding
 * @return The string in UTF-32 encoding with the specified byte order
 */
- (const OFChar32 *)UTF32StringWithByteOrder: (OFByteOrder)byteOrder
- (const OFChar32 *)UTF32StringWithByteOrder: (OFByteOrder)byteOrder;
    OF_RETURNS_INNER_POINTER;

/**
 * @brief Returns the string as OFData with the specified encoding.
 *
 * @param encoding The encoding to use for the returned OFData
 * @return The string as OFData with the specified encoding
 * @throw OFInvalidEncodingException The string cannot be represented in the
1303
1304
1305
1306
1307
1308
1309
1310

1311
1312

1313
1314

1315
1316
1317

1318
1319
1320


1321
1322
1323
1324

1325
1326
1327
1328
1329
1330
1331
1295
1296
1297
1298
1299
1300
1301

1302
1303

1304
1305

1306
1307
1308

1309
1310


1311
1312
1313
1314
1315

1316
1317
1318
1319
1320
1321
1322
1323







-
+

-
+

-
+


-
+

-
-
+
+



-
+







 * @throw OFInvalidEncodingException The string cannot be represented in the
 *				     specified encoding
 */
- (void)writeToFile: (OFString *)path encoding: (OFStringEncoding)encoding;
# endif

/**
 * @brief Writes the string to the specified URI using UTF-8 encoding.
 * @brief Writes the string to the specified IRI using UTF-8 encoding.
 *
 * @param URI The URI to write to
 * @param IRI The IRI to write to
 */
- (void)writeToURI: (OFURI *)URI;
- (void)writeToIRI: (OFIRI *)IRI;

/**
 * @brief Writes the string to the specified URI using the specified encoding.
 * @brief Writes the string to the specified IRI using the specified encoding.
 *
 * @param URI The URI to write to
 * @param encoding The encoding to use to write the string to the URI
 * @param IRI The IRI to write to
 * @param encoding The encoding to use to write the string to the IRI
 * @throw OFInvalidEncodingException The string cannot be represented in the
 *				     specified encoding
 */
- (void)writeToURI: (OFURI *)URI encoding: (OFStringEncoding)encoding;
- (void)writeToIRI: (OFIRI *)IRI encoding: (OFStringEncoding)encoding;

# ifdef OF_HAVE_BLOCKS
/**
 * Enumerates all lines in the receiver using the specified block.
 *
 * @brief block The block to call for each line
 */
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1366
1367
1368
1369
1370
1371
1372

1373
1374
1375
1376
1377
1378
1379







-







# import "OFString+CryptographicHashing.h"
# import "OFString+JSONParsing.h"
# ifdef OF_HAVE_FILES
#  import "OFString+PathAdditions.h"
# endif
# import "OFString+PercentEncoding.h"
# import "OFString+PropertyListParsing.h"
# import "OFString+Serialization.h"
# import "OFString+XMLEscaping.h"
# import "OFString+XMLUnescaping.h"
#endif

#if defined(__OBJC__) && !defined(NSINTEGER_DEFINED) && !__has_feature(modules)
/*
 * Very *ugly* hack required for string boxing literals to work.

Modified src/OFString.m from [03372dc363] to [a697442a34].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
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
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







-
+
















+
+



-
-


-







#include <ctype.h>
#include <errno.h>
#include <math.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>

#if defined(HAVE_STRTOF_L) || defined(HAVE_STRTOD_L)
#if defined(HAVE_STRTOF_L) || defined(HAVE_STRTOD_L) || defined(HAVE_USELOCALE)
# include <locale.h>
#endif
#ifdef HAVE_XLOCALE_H
# include <xlocale.h>
#endif

#import "OFString.h"
#import "OFASPrintF.h"
#import "OFArray.h"
#import "OFCharacterSet.h"
#import "OFData.h"
#import "OFDictionary.h"
#ifdef OF_HAVE_FILES
# import "OFFile.h"
# import "OFFileManager.h"
#endif
#import "OFIRI.h"
#import "OFIRIHandler.h"
#import "OFLocale.h"
#import "OFStream.h"
#import "OFSystemInfo.h"
#import "OFURI.h"
#import "OFURIHandler.h"
#import "OFUTF8String.h"
#import "OFUTF8String+Private.h"
#import "OFXMLElement.h"

#import "OFGetItemAttributesFailedException.h"
#import "OFInitializationFailedException.h"
#import "OFInvalidArgumentException.h"
#import "OFInvalidEncodingException.h"
#import "OFInvalidFormatException.h"
#import "OFNotImplementedException.h"
78
79
80
81
82
83
84
85

86
87
88
89
90
91
92
77
78
79
80
81
82
83

84
85
86
87
88
89
90
91







-
+







# define INFINITY __builtin_inf()
#endif

static struct {
	Class isa;
} placeholder;

#if defined(HAVE_STRTOF_L) || defined(HAVE_STRTOD_L)
#if defined(HAVE_STRTOF_L) || defined(HAVE_STRTOD_L) || defined(HAVE_USELOCALE)
static locale_t cLocale;
#endif

@interface OFString ()
- (size_t)of_getCString: (char *)cString
	      maxLength: (size_t)maxLength
	       encoding: (OFStringEncoding)encoding
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
130
131
132
133
134
135
136

137
138
139
140
141
142
143







-







	_OFString_CryptographicHashing_reference = 1;
	_OFString_JSONParsing_reference = 1;
#ifdef OF_HAVE_FILES
	_OFString_PathAdditions_reference = 1;
#endif
	_OFString_PercentEncoding_reference = 1;
	_OFString_PropertyListParsing_reference = 1;
	_OFString_Serialization_reference = 1;
	_OFString_XMLEscaping_reference = 1;
	_OFString_XMLUnescaping_reference = 1;
}

void
_reference_to_OFConstantString(void)
{
578
579
580
581
582
583
584
585

586
587

588
589
590

591
592
593

594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
576
577
578
579
580
581
582

583
584

585
586
587

588
589
590

591
592
593
594





595
596
597
598
599
600
601







-
+

-
+


-
+


-
+



-
-
-
-
-







			      encoding: (OFStringEncoding)encoding
{
	return (id)[[OFUTF8String alloc] initWithContentsOfFile: path
						       encoding: encoding];
}
#endif

- (instancetype)initWithContentsOfURI: (OFURI *)URI
- (instancetype)initWithContentsOfIRI: (OFIRI *)IRI
{
	return (id)[[OFUTF8String alloc] initWithContentsOfURI: URI];
	return (id)[[OFUTF8String alloc] initWithContentsOfIRI: IRI];
}

- (instancetype)initWithContentsOfURI: (OFURI *)URI
- (instancetype)initWithContentsOfIRI: (OFIRI *)IRI
			     encoding: (OFStringEncoding)encoding
{
	return (id)[[OFUTF8String alloc] initWithContentsOfURI: URI
	return (id)[[OFUTF8String alloc] initWithContentsOfIRI: IRI
						      encoding: encoding];
}

- (instancetype)initWithSerialization: (OFXMLElement *)element
{
	return (id)[[OFUTF8String alloc] initWithSerialization: element];
}

- (instancetype)retain
{
	return self;
}

- (instancetype)autorelease
{
623
624
625
626
627
628
629
630

631
632
633
634
635
636
637
616
617
618
619
620
621
622

623
624
625
626
627
628
629
630







-
+







+ (void)initialize
{
	if (self != [OFString class])
		return;

	placeholder.isa = [OFStringPlaceholder class];

#if defined(HAVE_STRTOF_L) || defined(HAVE_STRTOD_L)
#if defined(HAVE_STRTOF_L) || defined(HAVE_STRTOD_L) || defined(HAVE_USELOCALE)
	if ((cLocale = newlocale(LC_ALL_MASK, "C", NULL)) == NULL)
		@throw [OFInitializationFailedException
		    exceptionWithClass: self];
#endif
}

+ (instancetype)alloc
792
793
794
795
796
797
798
799

800
801

802
803
804

805
806
807

808
809
810
811
812
813
814
785
786
787
788
789
790
791

792
793

794
795
796

797
798
799

800
801
802
803
804
805
806
807







-
+

-
+


-
+


-
+







				encoding: (OFStringEncoding)encoding
{
	return [[[self alloc] initWithContentsOfFile: path
					    encoding: encoding] autorelease];
}
#endif

+ (instancetype)stringWithContentsOfURI: (OFURI *)URI
+ (instancetype)stringWithContentsOfIRI: (OFIRI *)IRI
{
	return [[[self alloc] initWithContentsOfURI: URI] autorelease];
	return [[[self alloc] initWithContentsOfIRI: IRI] autorelease];
}

+ (instancetype)stringWithContentsOfURI: (OFURI *)URI
+ (instancetype)stringWithContentsOfIRI: (OFIRI *)IRI
			       encoding: (OFStringEncoding)encoding
{
	return [[[self alloc] initWithContentsOfURI: URI
	return [[[self alloc] initWithContentsOfIRI: IRI
					   encoding: encoding] autorelease];
}

- (instancetype)init
{
	if ([self isMemberOfClass: [OFString class]]) {
		@try {
1045
1046
1047
1048
1049
1050
1051
1052

1053
1054

1055
1056
1057
1058

1059
1060
1061
1062
1063
1064
1065

1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1038
1039
1040
1041
1042
1043
1044

1045
1046

1047
1048
1049
1050

1051
1052
1053
1054
1055
1056
1057

1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071






























1072
1073
1074
1075
1076
1077
1078







-
+

-
+



-
+






-
+













-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







		}
	}

	return self;
}
#endif

- (instancetype)initWithContentsOfURI: (OFURI *)URI
- (instancetype)initWithContentsOfIRI: (OFIRI *)IRI
{
	return [self initWithContentsOfURI: URI
	return [self initWithContentsOfIRI: IRI
				  encoding: OFStringEncodingAutodetect];
}

- (instancetype)initWithContentsOfURI: (OFURI *)URI
- (instancetype)initWithContentsOfIRI: (OFIRI *)IRI
			     encoding: (OFStringEncoding)encoding
{
	void *pool = objc_autoreleasePoolPush();
	OFData *data;

	@try {
		data = [OFData dataWithContentsOfURI: URI];
		data = [OFData dataWithContentsOfIRI: IRI];
	} @catch (id e) {
		[self release];
		@throw e;
	}

	/* FIXME: Detect encoding where we can. */
	if (encoding == OFStringEncodingAutodetect)
		encoding = OFStringEncodingUTF8;

	self = [self initWithCString: data.items
			    encoding: encoding
			      length: data.count * data.itemSize];

	objc_autoreleasePoolPop(pool);

	return self;
}

- (instancetype)initWithSerialization: (OFXMLElement *)element
{
	void *pool = objc_autoreleasePoolPush();
	OFString *stringValue;

	@try {
		if (![element.namespace isEqual: OFSerializationNS])
			@throw [OFInvalidArgumentException exception];

		if ([self isKindOfClass: [OFMutableString class]]) {
			if (![element.name isEqual: @"OFMutableString"])
				@throw [OFInvalidArgumentException exception];
		} else {
			if (![element.name isEqual: @"OFString"])
				@throw [OFInvalidArgumentException exception];
		}

		stringValue = element.stringValue;
	} @catch (id e) {
		[self release];
		@throw e;
	}

	self = [self initWithString: stringValue];

	objc_autoreleasePoolPop(pool);

	return self;
}

- (size_t)of_getCString: (char *)cString
	      maxLength: (size_t)maxLength
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1641
1642
1643
1644
1645
1646
1647






















1648
1649
1650
1651
1652
1653
1654







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







}

- (OFString *)description
{
	return [[self copy] autorelease];
}

- (OFXMLElement *)XMLElementBySerializing
{
	void *pool = objc_autoreleasePoolPush();
	OFXMLElement *element;
	OFString *className;

	if ([self isKindOfClass: [OFMutableString class]])
		className = @"OFMutableString";
	else
		className = @"OFString";

	element = [OFXMLElement elementWithName: className
				      namespace: OFSerializationNS
				    stringValue: self];

	[element retain];

	objc_autoreleasePoolPop(pool);

	return [element autorelease];
}

- (OFString *)JSONRepresentation
{
	return [self of_JSONRepresentationWithOptions: 0 depth: 0];
}

- (OFString *)JSONRepresentationWithOptions:
    (OFJSONRepresentationOptions)options
2422
2423
2424
2425
2426
2427
2428
2429

2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445

2446




2447
2448
2449
2450
2451
2452
2453
2363
2364
2365
2366
2367
2368
2369

2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385

2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398







-
+















-
+

+
+
+
+







	    [stripped caseInsensitiveCompare: @"-INFINITY"] == OFOrderedSame)
		return -INFINITY;
	if ([stripped caseInsensitiveCompare: @"NAN"] == OFOrderedSame)
		return NAN;
	if ([stripped caseInsensitiveCompare: @"-NAN"] == OFOrderedSame)
		return -NAN;

#ifdef HAVE_STRTOF_L
#if defined(HAVE_STRTOF_L) || defined(HAVE_USELOCALE)
	const char *UTF8String = self.UTF8String;
#else
	/*
	 * If we have no strtof_l, we have no other choice but to replace "."
	 * with the locale's decimal point.
	 */
	OFString *decimalSeparator = [OFLocale decimalSeparator];
	const char *UTF8String = [self
	    stringByReplacingOccurrencesOfString: @"."
				      withString: decimalSeparator].UTF8String;
#endif
	char *endPtr = NULL;
	float value;

	errno = 0;
#ifdef HAVE_STRTOF_L
#if defined(HAVE_STRTOF_L)
	value = strtof_l(UTF8String, &endPtr, cLocale);
#elif defined(HAVE_USELOCALE)
	locale_t previousLocale = uselocale(cLocale);
	value = strtof(UTF8String, &endPtr);
	uselocale(previousLocale);
#else
	value = strtof(UTF8String, &endPtr);
#endif

	if (value == HUGE_VALF && errno == ERANGE)
		@throw [OFOutOfRangeException exception];

2475
2476
2477
2478
2479
2480
2481
2482

2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498

2499




2500
2501
2502
2503
2504
2505
2506
2420
2421
2422
2423
2424
2425
2426

2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442

2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455







-
+















-
+

+
+
+
+







	    [stripped caseInsensitiveCompare: @"-INFINITY"] == OFOrderedSame)
		return -INFINITY;
	if ([stripped caseInsensitiveCompare: @"NAN"] == OFOrderedSame)
		return NAN;
	if ([stripped caseInsensitiveCompare: @"-NAN"] == OFOrderedSame)
		return -NAN;

#ifdef HAVE_STRTOD_L
#if defined(HAVE_STRTOD_L) || defined(HAVE_USELOCALE)
	const char *UTF8String = self.UTF8String;
#else
	/*
	 * If we have no strtod_l, we have no other choice but to replace "."
	 * with the locale's decimal point.
	 */
	OFString *decimalSeparator = [OFLocale decimalSeparator];
	const char *UTF8String = [self
	    stringByReplacingOccurrencesOfString: @"."
				      withString: decimalSeparator].UTF8String;
#endif
	char *endPtr = NULL;
	double value;

	errno = 0;
#ifdef HAVE_STRTOD_L
#if defined(HAVE_STRTOD_L)
	value = strtod_l(UTF8String, &endPtr, cLocale);
#elif defined(HAVE_USELOCALE)
	locale_t previousLocale = uselocale(cLocale);
	value = strtod(UTF8String, &endPtr);
	uselocale(previousLocale);
#else
	value = strtod(UTF8String, &endPtr);
#endif

	if (value == HUGE_VAL && errno == ERANGE)
		@throw [OFOutOfRangeException exception];

2720
2721
2722
2723
2724
2725
2726
2727

2728
2729

2730
2731
2732

2733
2734
2735
2736
2737

2738
2739
2740
2741
2742
2743
2744
2669
2670
2671
2672
2673
2674
2675

2676
2677

2678
2679
2680

2681
2682
2683
2684
2685

2686
2687
2688
2689
2690
2691
2692
2693







-
+

-
+


-
+




-
+







	void *pool = objc_autoreleasePoolPush();
	OFFile *file = [OFFile fileWithPath: path mode: @"w"];
	[file writeString: self encoding: encoding];
	objc_autoreleasePoolPop(pool);
}
#endif

- (void)writeToURI: (OFURI *)URI
- (void)writeToIRI: (OFIRI *)IRI
{
	[self writeToURI: URI encoding: OFStringEncodingUTF8];
	[self writeToIRI: IRI encoding: OFStringEncodingUTF8];
}

- (void)writeToURI: (OFURI *)URI encoding: (OFStringEncoding)encoding
- (void)writeToIRI: (OFIRI *)IRI encoding: (OFStringEncoding)encoding
{
	void *pool = objc_autoreleasePoolPush();
	OFStream *stream;

	stream = [OFURIHandler openItemAtURI: URI mode: @"w"];
	stream = [OFIRIHandler openItemAtIRI: IRI mode: @"w"];
	[stream writeString: self encoding: encoding];

	objc_autoreleasePoolPop(pool);
}

#ifdef OF_HAVE_BLOCKS
- (void)enumerateLinesUsingBlock: (OFStringLineEnumerationBlock)block

Modified src/OFSubarray.h from [06376fcb2e] to [6cc244c93d].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFSubarray.m from [0aad1eac45] to [f65d24319e].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFSubprocess.h from [1691c8fd4f] to [a4c6c29f31].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFSubprocess.m from [c37900d1dc] to [9698c0f2ee].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Added src/OFSystemInfo+NetworkInterfaces.h version [0c237980b3].







































































































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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 */

#import "OFSystemInfo.h"

OF_ASSUME_NONNULL_BEGIN

/**
 * @brief A dictionary describing a network interface, as returned by
 *	  @ref networkInterfaces.
 *
 * Keys are of type @ref OFNetworkInterfaceKey.
 */
typedef OFDictionary OF_GENERIC(OFString *, id) *OFNetworkInterface;

/**
 * @brief A key of an @ref OFNetworkInterface.
 *
 * Possible values are:
 *
 *   * @ref OFNetworkInterfaceIndex
 */
typedef OFConstantString *OFNetworkInterfaceKey;

/**
 * @brief The index of a network interface.
 *
 * This maps to an @ref OFNumber.
 */
extern OFNetworkInterfaceKey OFNetworkInterfaceIndex;

/**
 * @brief The hardware address of a network interface.
 *
 * This maps to an @ref OFData.
 */
extern OFNetworkInterfaceKey OFNetworkInterfaceHardwareAddress;

/**
 * @brief The IPv4 addresses of a network interface.
 *
 * This maps to an @ref OFData of @ref OFSocketAddress.
 */
extern OFNetworkInterfaceKey OFNetworkInterfaceIPv4Addresses;

#ifdef OF_HAVE_IPV6
/**
 * @brief The IPv6 addresses of a network interface.
 *
 * This maps to an @ref OFData of @ref OFSocketAddress.
 */
extern OFNetworkInterfaceKey OFNetworkInterfaceIPv6Addresses;
#endif

#ifdef OF_HAVE_IPX
/**
 * @brief The IPX addresses of a network interface.
 *
 * This maps to an @ref OFData of @ref OFSocketAddress.
 */
extern OFNetworkInterfaceKey OFNetworkInterfaceIPXAddresses;
#endif

#ifdef OF_HAVE_APPLETALK
/**
 * @brief The AppleTalk addresses of a network interface.
 *
 * This maps to an @ref OFData of @ref OFSocketAddress.
 */
extern OFNetworkInterfaceKey OFNetworkInterfaceAppleTalkAddresses;
#endif

@interface OFSystemInfo (NetworkInterfaces)

#ifdef OF_HAVE_CLASS_PROPERTIES
@property (class, readonly, nullable, nonatomic)
    OFDictionary OF_GENERIC(OFString *, OFNetworkInterface) *networkInterfaces;
#endif

/**
 * @brief Returns the available (though not necessarily configured) network
 *	  interfaces.
 *
 * @return The available network interfaces
 */
+ (nullable OFDictionary OF_GENERIC(OFString *, OFNetworkInterface) *)
    networkInterfaces;
@end

OF_ASSUME_NONNULL_END

Added src/OFSystemInfo+NetworkInterfaces.m version [b1a1002ffe].











































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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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 "OFSystemInfo.h"

OFNetworkInterfaceKey OFNetworkInterfaceIndex = @"OFNetworkInterfaceIndex";
OFNetworkInterfaceKey OFNetworkInterfaceHardwareAddress =
    @"OFNetworkInterfaceHardwareAddress";
OFNetworkInterfaceKey OFNetworkInterfaceIPv4Addresses =
    @"OFNetworkInterfaceIPv4Addresses";
#ifdef OF_HAVE_IPV6
OFNetworkInterfaceKey OFNetworkInterfaceIPv6Addresses =
    @"OFNetworkInterfaceIPv6Addresses";
#endif
#ifdef OF_HAVE_IPX
OFNetworkInterfaceKey OFNetworkInterfaceIPXAddresses =
    @"OFNetworkInterfaceIPXAddresses";
#endif
#ifdef OF_HAVE_APPLETALK
OFNetworkInterfaceKey OFNetworkInterfaceAppleTalkAddresses =
    @"OFNetworkInterfaceAppleTalkAddresses";
#endif

#ifdef OF_WINDOWS
# include "platform/Windows/OFSystemInfo+NetworkInterfaces.m"
#else
# include "platform/POSIX/OFSystemInfo+NetworkInterfaces.m"
#endif

Modified src/OFSystemInfo.h from [8b4f866788] to [1f526bb329].

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
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

-
+


















+
-
+

















-
-
-
+
+
+


-
+

+
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 */

#import "OFObject.h"
#import "OFString.h"

OF_ASSUME_NONNULL_BEGIN

@class OFDictionary OF_GENERIC(KeyType, ObjectType);
@class OFURI;
@class OFIRI;

/**
 * @class OFSystemInfo OFSystemInfo.h ObjFW/OFSystemInfo.h
 *
 * @brief A class for querying information about the system.
 */
OF_SUBCLASSING_RESTRICTED
@interface OFSystemInfo: OFObject
#ifdef OF_HAVE_CLASS_PROPERTIES
@property (class, readonly, nonatomic) size_t pageSize;
@property (class, readonly, nonatomic) size_t numberOfCPUs;
@property (class, readonly, nonatomic) OFString *ObjFWVersion;
@property (class, readonly, nonatomic) unsigned short ObjFWVersionMajor;
@property (class, readonly, nonatomic) unsigned short ObjFWVersionMinor;
@property (class, readonly, nullable, nonatomic) OFString *operatingSystemName;
@property (class, readonly, nullable, nonatomic)
    OFString *operatingSystemVersion;
@property (class, readonly, nullable, nonatomic) OFURI *userDataURI;
@property (class, readonly, nullable, nonatomic) OFURI *userConfigURI;
@property (class, readonly, nullable, nonatomic) OFURI *temporaryDirectoryURI;
@property (class, readonly, nullable, nonatomic) OFIRI *userDataIRI;
@property (class, readonly, nullable, nonatomic) OFIRI *userConfigIRI;
@property (class, readonly, nullable, nonatomic) OFIRI *temporaryDirectoryIRI;
@property (class, readonly, nullable, nonatomic) OFString *CPUVendor;
@property (class, readonly, nullable, nonatomic) OFString *CPUModel;
# if defined(OF_X86_64) || defined(OF_X86) || defined(DOXYGEN)
# if defined(OF_AMD64) || defined(OF_X86) || defined(DOXYGEN)
@property (class, readonly, nonatomic) bool supportsMMX;
@property (class, readonly, nonatomic) bool supports3DNow;
@property (class, readonly, nonatomic) bool supportsEnhanced3DNow;
@property (class, readonly, nonatomic) bool supportsSSE;
@property (class, readonly, nonatomic) bool supportsSSE2;
@property (class, readonly, nonatomic) bool supportsSSE3;
@property (class, readonly, nonatomic) bool supportsSSSE3;
@property (class, readonly, nonatomic) bool supportsSSE41;
@property (class, readonly, nonatomic) bool supportsSSE42;
@property (class, readonly, nonatomic) bool supportsAVX;
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
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







-
+














-
+

















-
+



















-
+



-
+





+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+





-
+










-
+










-
+










-
+










-
+










-
+










-
+










-
+








-
+








-
+







 * On macOS 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.@n
 * On AmigaOS and MorphOS, it returns `PROGDIR:`.
 *
 * @return The path where user data for the application can be stored
 */
+ (nullable OFURI *)userDataURI;
+ (nullable OFIRI *)userDataIRI;

/**
 * @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 macOS 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.
 * On AmigaOS and MorphOS, it returns `PROGDIR:`.
 *
 * @return The path where user configuration for the application can be stored
 */
+ (nullable OFURI *)userConfigURI;
+ (nullable OFIRI *)userConfigIRI;

/**
 * @brief Returns a path where temporary files for can be stored.
 * 
 * If possible, returns a temporary directory for the user, otherwise returns a
 * global temporary directory.
 *
 * On UNIX systems, this adheres to the XDG Base Directory specification and
 * returns `/tmp` if `XDG_RUNTIME_DIR` is not set.@n
 * On macOS and iOS, this uses `_CS_DARWIN_USER_TEMP_DIR`, falling back to
 * `/tmp` if this fails.@n
 * On Windows, it uses `GetTempPath`.@n
 * On Haiku, it uses the `B_SYSTEM_TEMP_DIRECTORY` directory.
 * On AmigaOS and MorphOS, it returns `T:`.
 *
 * @return A path where temporary files can be stored
 */
+ (nullable OFURI *)temporaryDirectoryURI;
+ (nullable OFIRI *)temporaryDirectoryIRI;

/**
 * @brief Returns the vendor of the CPU.
 *
 * If the vendor could not be determined, `nil` is returned instead.
 *
 * @return The vendor of the CPU
 */
+ (nullable OFString *)CPUVendor;

/**
 * @brief Returns the model of the CPU.
 *
 * If the model could not be determined, `nil` is returned instead.
 *
 * @return The model of the CPU
 */
+ (nullable OFString *)CPUModel;

#if defined(OF_X86_64) || defined(OF_X86) || defined(DOXYGEN)
#if defined(OF_AMD64) || defined(OF_X86) || defined(DOXYGEN)
/**
 * @brief Returns whether the CPU supports MMX.
 *
 * @note This method is only available on x86 and x86_64.
 * @note This method is only available on AMD64 and x86.
 *
 * @return Whether the CPU supports MMX
 */
+ (bool)supportsMMX;

/**
 * @brief Returns whether the CPU supports 3DNow!.
 *
 * @note This method is only available on AMD64 and x86.
 *
 * @return Whether the CPU supports 3DNow!
 */
+ (bool)supports3DNow;

/**
 * @brief Returns whether the CPU supports enhanced 3DNow!.
 *
 * @note This method is only available on AMD64 and x86.
 *
 * @return Whether the CPU supports enhanced 3DNow!
 */
+ (bool)supportsEnhanced3DNow;

/**
 * @brief Returns whether the CPU supports SSE.
 *
 * @warning This method only checks CPU support and assumes OS support!
 *
 * @note This method is only available on x86 and x86_64.
 * @note This method is only available on AMD64 and x86.
 *
 * @return Whether the CPU supports SSE
 */
+ (bool)supportsSSE;

/**
 * @brief Returns whether the CPU supports SSE2.
 *
 * @warning This method only checks CPU support and assumes OS support!
 *
 * @note This method is only available on x86 and x86_64.
 * @note This method is only available on AMD64 and x86.
 *
 * @return Whether the CPU supports SSE2
 */
+ (bool)supportsSSE2;

/**
 * @brief Returns whether the CPU supports SSE3.
 *
 * @warning This method only checks CPU support and assumes OS support!
 *
 * @note This method is only available on x86 and x86_64.
 * @note This method is only available on AMD64 and x86.
 *
 * @return Whether the CPU supports SSE3
 */
+ (bool)supportsSSE3;

/**
 * @brief Returns whether the CPU supports SSSE3.
 *
 * @warning This method only checks CPU support and assumes OS support!
 *
 * @note This method is only available on x86 and x86_64.
 * @note This method is only available on AMD64 and x86.
 *
 * @return Whether the CPU supports SSSE3
 */
+ (bool)supportsSSSE3;

/**
 * @brief Returns whether the CPU supports SSE4.1.
 *
 * @warning This method only checks CPU support and assumes OS support!
 *
 * @note This method is only available on x86 and x86_64.
 * @note This method is only available on AMD64 and x86.
 *
 * @return Whether the CPU supports SSE4.1
 */
+ (bool)supportsSSE41;

/**
 * @brief Returns whether the CPU supports SSE4.2.
 *
 * @warning This method only checks CPU support and assumes OS support!
 *
 * @note This method is only available on x86 and x86_64.
 * @note This method is only available on AMD64 and x86.
 *
 * @return Whether the CPU supports SSE4.2
 */
+ (bool)supportsSSE42;

/**
 * @brief Returns whether the CPU supports AVX.
 *
 * @warning This method only checks CPU support and assumes OS support!
 *
 * @note This method is only available on x86 and x86_64.
 * @note This method is only available on AMD64 and x86.
 *
 * @return Whether the CPU supports AVX
 */
+ (bool)supportsAVX;

/**
 * @brief Returns whether the CPU supports AVX2.
 *
 * @warning This method only checks CPU support and assumes OS support!
 *
 * @note This method is only available on x86 and x86_64.
 * @note This method is only available on AMD64 and x86.
 *
 * @return Whether the CPU supports AVX2
 */
+ (bool)supportsAVX2;

/**
 * @brief Returns whether the CPU supports AES-NI.
 *
 * @note This method is only available on x86 and x86_64.
 * @note This method is only available on AMD64 and x86.
 *
 * @return Whether the CPU supports AES-NI
 */
+ (bool)supportsAESNI;

/**
 * @brief Returns whether the CPU supports Intel SHA Extensions.
 *
 * @note This method is only available on x86 and x86_64.
 * @note This method is only available on AMD64 and x86.
 *
 * @return Whether the CPU supports Intel SHA Extensions
 */
+ (bool)supportsSHAExtensions;
#endif

#if defined(OF_POWERPC) || defined(OF_POWERPC64)
319
320
321
322
323
324
325




340
341
342
343
344
345
346
347
348
349
350







+
+
+
+
#endif

+ (instancetype)alloc OF_UNAVAILABLE;
- (instancetype)init OF_UNAVAILABLE;
@end

OF_ASSUME_NONNULL_END

#ifdef OF_HAVE_SOCKETS
# import "OFSystemInfo+NetworkInterfaces.h"
#endif

Modified src/OFSystemInfo.m from [9f095b0c1c] to [50bc975723].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
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
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







+


+













+
+
+
+




+

+
+
+
+

+


+
-
+
+






-
-
-







# include <sys/utsname.h>
#endif
#if defined(OF_MACOS) || defined(OF_IOS) || defined(OF_NETBSD)
# include <sys/sysctl.h>
#endif

#ifdef OF_AMIGAOS
# define Class IntuitionClass
# include <exec/execbase.h>
# include <proto/exec.h>
# undef Class
#endif

#if defined(OF_AMIGAOS4)
# include <exec/exectags.h>
#elif defined(OF_MORPHOS)
# include <exec/system.h>
#endif

#ifdef OF_NINTENDO_SWITCH
# define id nx_id
# import <switch.h>
# undef nx_id
#endif

#ifdef OF_DJGPP
# include <dos.h>
#endif

#import "OFSystemInfo.h"
#import "OFApplication.h"
#import "OFArray.h"
#import "OFData.h"
#import "OFDictionary.h"
#ifdef OF_HAVE_FILES
 #import "OFFile.h"
#endif
#import "OFIRI.h"
#import "OFLocale.h"
#import "OFNumber.h"
#import "OFOnce.h"
#import "OFString.h"

#import "OFURI.h"
#import "OFInvalidFormatException.h"
#import "OFOpenItemFailedException.h"

#if defined(OF_MACOS) || defined(OF_IOS)
# ifdef HAVE_SYSDIR_H
#  include <sysdir.h>
# endif
#endif
#ifdef OF_WINDOWS
# include <windows.h>
#endif
#ifdef OF_HAIKU
# include <FindDirectory.h>
#endif
#ifdef OF_QNX
# include <sys/syspage.h>
#endif

97
98
99
100
101
102
103
104

105
106
107
108
109
110
111
108
109
110
111
112
113
114

115
116
117
118
119
120
121
122







-
+








extern NSSearchPathEnumerationState NSStartSearchPathEnumeration(
    NSSearchPathDirectory, NSSearchPathDomainMask);
extern NSSearchPathEnumerationState NSGetNextSearchPathEnumeration(
    NSSearchPathEnumerationState, char *);
#endif

#if defined(OF_X86_64) || defined(OF_X86)
#if defined(OF_AMD64) || defined(OF_X86)
struct X86Regs {
	uint32_t eax, ebx, ecx, edx;
};
#endif

static size_t pageSize = 4096;
static size_t numberOfCPUs = 1;
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
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







+
+




+
+


-
-
+
+
+
+

-
+

-
+



-
+







	operatingSystemName = @"AmigaOS";
#elif defined(OF_MORPHOS)
	operatingSystemName = @"MorphOS";
#elif defined(OF_AMIGAOS4)
	operatingSystemName = @"AmigaOS 4";
#elif defined(OF_WII)
	operatingSystemName = @"Nintendo Wii";
#elif defined(OF_WII_U)
	operatingSystemName = @"Nintendo Wii U";
#elif defined(NINTENDO_3DS)
	operatingSystemName = @"Nintendo 3DS";
#elif defined(OF_NINTENDO_DS)
	operatingSystemName = @"Nintendo DS";
#elif defined(OF_NINTENDO_SWITCH)
	operatingSystemName = @"Nintendo Switch";
#elif defined(OF_PSP)
	operatingSystemName = @"PlayStation Portable";
#elif defined(OF_MSDOS)
	operatingSystemName = @"MS-DOS";
#elif defined(OF_DJGPP)
	operatingSystemName = [[OFString alloc]
	    initWithCString: _os_flavor
		   encoding: OFStringEncodingASCII];
#elif defined(HAVE_SYS_UTSNAME_H) && defined(HAVE_UNAME)
	struct utsname utsname;
	struct utsname name;

	if (uname(&utsname) != 0)
	if (uname(&name) != 0)
		return;

	operatingSystemName = [[OFString alloc]
	    initWithCString: utsname.sysname
	    initWithCString: name.sysname
		   encoding: [OFLocale encoding]];
#endif
}

static void
initOperatingSystemVersion(void)
{
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
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







+
+
+

-
+


-
+

-
+



-
+





-
+





-
+




-
+





-
+







# endif
#elif defined(OF_ANDROID)
	/* TODO */
#elif defined(OF_AMIGAOS)
	operatingSystemVersion = [[OFString alloc]
	    initWithFormat: @"Kickstart %u.%u",
			    SysBase->LibNode.lib_Version, SysBase->SoftVer];
#elif defined(OF_DJGPP)
	operatingSystemVersion = [[OFString alloc]
	    initWithFormat: @"%u.%u", _osmajor, _osminor];
#elif defined(OF_WII) || defined(NINTENDO_3DS) || defined(OF_NINTENDO_DS) || \
    defined(OF_PSP) || defined(OF_MSDOS)
    defined(OF_PSP)
	/* Intentionally nothing */
#elif defined(HAVE_SYS_UTSNAME_H) && defined(HAVE_UNAME)
	struct utsname utsname;
	struct utsname name;

	if (uname(&utsname) != 0)
	if (uname(&name) != 0)
		return;

	operatingSystemVersion = [[OFString alloc]
	    initWithCString: utsname.release
	    initWithCString: name.release
		   encoding: [OFLocale encoding]];
#endif
}

#ifdef OF_NINTENDO_SWITCH
static OFURI *tmpFSURI = nil;
static OFIRI *tmpFSIRI = nil;

static void
mountTmpFS(void)
{
	if (R_SUCCEEDED(fsdevMountTemporaryStorage("tmpfs")))
		tmpFSURI = [[OFURI alloc] initFileURIWithPath: @"tmpfs:/"
		tmpFSIRI = [[OFIRI alloc] initFileIRIWithPath: @"tmpfs:/"
						  isDirectory: true];
}
#endif

#if defined(OF_X86_64) || defined(OF_X86)
#if defined(OF_AMD64) || defined(OF_X86)
static OF_INLINE struct X86Regs OF_CONST_FUNC
x86CPUID(uint32_t eax, uint32_t ecx)
{
	struct X86Regs regs;

# if defined(OF_X86_64) && defined(__GNUC__)
# if defined(OF_AMD64) && defined(__GNUC__)
	__asm__ (
	    "cpuid"
	    : "=a"(regs.eax), "=b"(regs.ebx), "=c"(regs.ecx), "=d"(regs.edx)
	    : "a"(eax), "c"(ecx)
	);
# elif defined(OF_X86) && defined(__GNUC__)
	/*
364
365
366
367
368
369
370
371

372
373
374
375
376
377
378
384
385
386
387
388
389
390

391
392
393
394
395
396
397
398







-
+







{
	static OFOnceControl onceControl = OFOnceControlInitValue;
	OFOnce(&onceControl, initOperatingSystemVersion);

	return operatingSystemVersion;
}

+ (OFURI *)userDataURI
+ (OFIRI *)userDataIRI
{
#ifdef OF_HAVE_FILES
# if defined(OF_MACOS) || defined(OF_IOS)
	char pathC[PATH_MAX];
	OFMutableString *path;

#  ifdef HAVE_SYSDIR_START_SEARCH_PATH_ENUMERATION
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
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







-
+







-
+







-
+


-
+



-
+




-
+








-
+



-
+






-
+








		[path deleteCharactersInRange: OFMakeRange(0, 1)];
		[path insertString: home atIndex: 0];
	}

	[path makeImmutable];

	return [OFURI fileURIWithPath: path isDirectory: true];
	return [OFIRI fileIRIWithPath: path isDirectory: true];
# elif defined(OF_WINDOWS)
	OFDictionary *env = [OFApplication environment];
	OFString *appData;

	if ((appData = [env objectForKey: @"APPDATA"]) == nil)
		return nil;

	return [OFURI fileURIWithPath: appData isDirectory: true];
	return [OFIRI fileIRIWithPath: appData isDirectory: true];
# elif defined(OF_HAIKU)
	char pathC[PATH_MAX];

	if (find_directory(B_USER_SETTINGS_DIRECTORY, 0, false,
	    pathC, PATH_MAX) != B_OK)
		return nil;

	return [OFURI fileURIWithPath: [OFString stringWithUTF8String: pathC]
	return [OFIRI fileIRIWithPath: [OFString stringWithUTF8String: pathC]
			  isDirectory: true];
# elif defined(OF_AMIGAOS)
	return [OFURI fileURIWithPath: @"PROGDIR:" isDirectory: true];
	return [OFIRI fileIRIWithPath: @"PROGDIR:" isDirectory: true];
# else
	OFDictionary *env = [OFApplication environment];
	OFString *var;
	OFURI *URI;
	OFIRI *IRI;
	void *pool;

	if ((var = [env objectForKey: @"XDG_DATA_HOME"]) != nil &&
	    var.length > 0)
		return [OFURI fileURIWithPath: var isDirectory: true];
		return [OFIRI fileIRIWithPath: var isDirectory: true];

	if ((var = [env objectForKey: @"HOME"]) == nil)
		return nil;

	pool = objc_autoreleasePoolPush();

	var = [OFString pathWithComponents: [OFArray arrayWithObjects:
	    var, @".local", @"share", nil]];
	URI = [[OFURI alloc] initFileURIWithPath: var isDirectory: true];
	IRI = [[OFIRI alloc] initFileIRIWithPath: var isDirectory: true];

	objc_autoreleasePoolPop(pool);

	return [URI autorelease];
	return [IRI autorelease];
# endif
#else
	return nil;
#endif
}

+ (OFURI *)userConfigURI
+ (OFIRI *)userConfigIRI
{
#ifdef OF_HAVE_FILES
# if defined(OF_MACOS) || defined(OF_IOS)
	char pathC[PATH_MAX];
	OFMutableString *path;

#  ifdef HAVE_SYSDIR_START_SEARCH_PATH_ENUMERATION
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
572
573
574
575
576
577
578
579

580
581
582
583
584
585
586
587

588
589
590

591
592
593
594
595
596
597

598
599

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
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

572
573
574
575
576
577

578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598

599
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
647
648
649
650
651
652







-
+







-
+







-
+


-
+






-
+






-
+






-
+








-
+





-
+




















-
+







-
+


-
+






-
+

-
+




-
+

-
-
+
+
+
+
+

+

-
+

-
+








-
+







		[path deleteCharactersInRange: OFMakeRange(0, 1)];
		[path insertString: home atIndex: 0];
	}

	[path appendString: @"/Preferences"];
	[path makeImmutable];

	return [OFURI fileURIWithPath: path isDirectory: true];
	return [OFIRI fileIRIWithPath: path isDirectory: true];
# elif defined(OF_WINDOWS)
	OFDictionary *env = [OFApplication environment];
	OFString *appData;

	if ((appData = [env objectForKey: @"APPDATA"]) == nil)
		return nil;

	return [OFURI fileURIWithPath: appData isDirectory: true];
	return [OFIRI fileIRIWithPath: appData isDirectory: true];
# elif defined(OF_HAIKU)
	char pathC[PATH_MAX];

	if (find_directory(B_USER_SETTINGS_DIRECTORY, 0, false,
	    pathC, PATH_MAX) != B_OK)
		return nil;

	return [OFURI fileURIWithPath: [OFString stringWithUTF8String: pathC]
	return [OFIRI fileIRIWithPath: [OFString stringWithUTF8String: pathC]
			  isDirectory: true];
# elif defined(OF_AMIGAOS)
	return [OFURI fileURIWithPath: @"PROGDIR:" isDirectory: true];
	return [OFIRI fileIRIWithPath: @"PROGDIR:" isDirectory: true];
# else
	OFDictionary *env = [OFApplication environment];
	OFString *var;

	if ((var = [env objectForKey: @"XDG_CONFIG_HOME"]) != nil &&
	    var.length > 0)
		return [OFURI fileURIWithPath: var isDirectory: true];
		return [OFIRI fileIRIWithPath: var isDirectory: true];

	if ((var = [env objectForKey: @"HOME"]) == nil)
		return nil;

	var = [var stringByAppendingPathComponent: @".config"];

	return [OFURI fileURIWithPath: var isDirectory: true];
	return [OFIRI fileIRIWithPath: var isDirectory: true];
# endif
#else
	return nil;
#endif
}

+ (OFURI *)temporaryDirectoryURI
+ (OFIRI *)temporaryDirectoryIRI
{
#ifdef OF_HAVE_FILES
# if defined(OF_MACOS) || defined(OF_IOS)
	char buffer[PATH_MAX];
	size_t length;
	OFString *path;

	if ((length = confstr(_CS_DARWIN_USER_TEMP_DIR, buffer, PATH_MAX)) == 0)
		return [OFURI fileURIWithPath: @"/tmp" isDirectory: true];
		return [OFIRI fileIRIWithPath: @"/tmp" isDirectory: true];

	path = [OFString stringWithCString: buffer
				  encoding: [OFLocale encoding]
				    length: length - 1];

	return [OFURI fileURIWithPath: path isDirectory: true];
	return [OFIRI fileIRIWithPath: path isDirectory: true];
# elif defined(OF_WINDOWS)
	OFString *path;

	if ([self isWindowsNT]) {
		wchar_t buffer[PATH_MAX];

		if (!GetTempPathW(PATH_MAX, buffer))
			return nil;

		path = [OFString stringWithUTF16String: buffer];
	} else {
		char buffer[PATH_MAX];

		if (!GetTempPathA(PATH_MAX, buffer))
			return nil;

		path = [OFString stringWithCString: buffer
					  encoding: [OFLocale encoding]];
	}

	return [OFURI fileURIWithPath: path isDirectory: true];
	return [OFIRI fileIRIWithPath: path isDirectory: true];
# elif defined(OF_HAIKU)
	char pathC[PATH_MAX];

	if (find_directory(B_SYSTEM_TEMP_DIRECTORY, 0, false,
	    pathC, PATH_MAX) != B_OK)
		return nil;

	return [OFURI fileURIWithPath: [OFString stringWithUTF8String: pathC]
	return [OFIRI fileIRIWithPath: [OFString stringWithUTF8String: pathC]
			  isDirectory: true];
# elif defined(OF_AMIGAOS)
	return [OFURI fileURIWithPath: @"T:" isDirectory: true];
	return [OFIRI fileIRIWithPath: @"T:" isDirectory: true];
# elif defined(OF_MSDOS)
	OFString *path = [[OFApplication environment] objectForKey: @"TEMP"];

	if (path == nil)
		return nil;

	return [OFURI fileURIWithPath: path isDirectory: true];
	return [OFIRI fileIRIWithPath: path isDirectory: true];
# elif defined(OF_MINT)
	return [OFURI fileURIWithPath: @"u:\\tmp" isDirectory: true];
	return [OFIRI fileIRIWithPath: @"u:\\tmp" isDirectory: true];
# elif defined(OF_NINTENDO_SWITCH)
	static OFOnceControl onceControl = OFOnceControlInitValue;
	OFOnce(&onceControl, mountTmpFS);

	return tmpFSURI;
	return tmpFSIRI;
# else
	OFString *path =
	    [[OFApplication environment] objectForKey: @"XDG_RUNTIME_DIR"];
	OFString *path;

	path = [[OFApplication environment] objectForKey: @"XDG_RUNTIME_DIR"];
	if (path != nil)
		return [OFIRI fileIRIWithPath: path isDirectory: true];

	path = [[OFApplication environment] objectForKey: @"TMPDIR"];
	if (path != nil)
		return [OFURI fileURIWithPath: path];
		return [OFIRI fileIRIWithPath: path isDirectory: true];

	return [OFURI fileURIWithPath: @"/tmp"];
	return [OFIRI fileIRIWithPath: @"/tmp" isDirectory: true];
# endif
#else
	return nil;
#endif
}

+ (OFString *)CPUVendor
{
#if (defined(OF_X86_64) || defined(OF_X86)) && defined(__GNUC__)
#if (defined(OF_AMD64) || defined(OF_X86)) && defined(__GNUC__)
	struct X86Regs regs = x86CPUID(0, 0);
	uint32_t buffer[3];

	if (regs.eax == 0)
		return nil;

	buffer[0] = regs.ebx;
637
638
639
640
641
642
643
644

645
646
647
648
649
650
651
661
662
663
664
665
666
667

668
669
670
671
672
673
674
675







-
+







#else
	return nil;
#endif
}

+ (OFString *)CPUModel
{
#if (defined(OF_X86_64) || defined(OF_X86)) && defined(__GNUC__)
#if (defined(OF_AMD64) || defined(OF_X86)) && defined(__GNUC__)
	struct X86Regs regs = x86CPUID(0x80000000, 0);
	uint32_t buffer[12];
	size_t i;

	if (regs.eax < 0x80000004)
		return nil;

696
697
698
699
700
701
702
703

704
705
706
707










708
709
710
711
712
713
714
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







-
+




+
+
+
+
+
+
+
+
+
+







	else
		return @"68000";
#else
	return nil;
#endif
}

#if defined(OF_X86_64) || defined(OF_X86)
#if defined(OF_AMD64) || defined(OF_X86)
+ (bool)supportsMMX
{
	return (x86CPUID(1, 0).edx & (1u << 23));
}

+ (bool)supports3DNow
{
	return (x86CPUID(0x80000001, 0).edx & (1u << 31));
}

+ (bool)supportsEnhanced3DNow
{
	return (x86CPUID(0x80000001, 0).edx & (1u << 30));
}

+ (bool)supportsSSE
{
	return (x86CPUID(1, 0).edx & (1u << 25));
}

+ (bool)supportsSSE2

Modified src/OFTCPSocket.h from [522e53453c] to [5c29465efd].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
153
154
155
156
157
158
159
160

161
162
163
164
165
166
167
153
154
155
156
157
158
159

160
161
162
163
164
165
166
167







-
+








/**
 * @brief Connects the OFTCPSocket to the specified destination.
 *
 * @param host The host to connect to
 * @param port The port on the host to connect to
 * @throw OFConnectIPSocketFailedException Connecting failed
 * @throw OFAlreadyConnectedException The socket is already connected or bound
 * @throw OFAlreadyOpenException The socket is already connected or bound
 */
- (void)connectToHost: (OFString *)host port: (uint16_t)port;

/**
 * @brief Asynchronously connects the OFTCPSocket to the specified destination.
 *
 * @param host The host to connect to
209
210
211
212
213
214
215
216

217
218

219
220

221
222
223
209
210
211
212
213
214
215

216
217

218
219

220
221
222
223







-
+

-
+

-
+



/**
 * @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.
 * @param port The port to bind to. If the port is 0, an unused port will be
 *	       chosen, which can be obtained using the return value.
 * @return The port the socket was bound to
 * @return The address the socket was bound to
 * @throw OFBindIPSocketFailedException Binding failed
 * @throw OFAlreadyConnectedException The socket is already connected or bound
 * @throw OFAlreadyOpenException The socket is already connected or bound
 */
- (uint16_t)bindToHost: (OFString *)host port: (uint16_t)port;
- (OFSocketAddress)bindToHost: (OFString *)host port: (uint16_t)port;
@end

OF_ASSUME_NONNULL_END

Modified src/OFTCPSocket.m from [bab73573da] to [dd3ca66b7b].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
39
40
41
42
43
44
45
46

47
48
49
50
51
52
53
39
40
41
42
43
44
45

46
47
48
49
50
51
52
53







-
+







#import "OFRunLoop+Private.h"
#import "OFSocket.h"
#import "OFSocket+Private.h"
#import "OFString.h"
#import "OFTCPSocketSOCKS5Connector.h"
#import "OFThread.h"

#import "OFAlreadyConnectedException.h"
#import "OFAlreadyOpenException.h"
#import "OFBindIPSocketFailedException.h"
#import "OFGetOptionFailedException.h"
#import "OFNotImplementedException.h"
#import "OFNotOpenException.h"
#import "OFSetOptionFailedException.h"

static const OFRunLoopMode connectRunLoopMode =
137
138
139
140
141
142
143
144

145
146
147
148
149
150
151
137
138
139
140
141
142
143

144
145
146
147
148
149
150
151







-
+







			    errNo: (int *)errNo
{
#if SOCK_CLOEXEC == 0 && defined(HAVE_FCNTL) && defined(FD_CLOEXEC)
	int flags;
#endif

	if (_socket != OFInvalidSocketHandle)
		@throw [OFAlreadyConnectedException exceptionWithSocket: self];
		@throw [OFAlreadyOpenException exceptionWithObject: self];

	if ((_socket = socket(
	    ((struct sockaddr *)&address->sockaddr)->sa_family,
	    SOCK_STREAM | SOCK_CLOEXEC, 0)) == OFInvalidSocketHandle) {
		*errNo = OFSocketErrNo();
		return false;
	}
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
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







-
+










-
+







			   block: (delegate == nil ? block : NULL)] autorelease]
	    startWithRunLoopMode: runLoopMode];

	objc_autoreleasePoolPop(pool);
}
#endif

- (uint16_t)bindToHost: (OFString *)host port: (uint16_t)port
- (OFSocketAddress)bindToHost: (OFString *)host port: (uint16_t)port
{
	const int one = 1;
	void *pool = objc_autoreleasePoolPush();
	OFData *socketAddresses;
	OFSocketAddress address;
#if SOCK_CLOEXEC == 0 && defined(HAVE_FCNTL) && defined(FD_CLOEXEC)
	int flags;
#endif

	if (_socket != OFInvalidSocketHandle)
		@throw [OFAlreadyConnectedException exceptionWithSocket: self];
		@throw [OFAlreadyOpenException exceptionWithObject: self];

	if (_SOCKS5Host != nil)
		@throw [OFNotImplementedException exceptionWithSelector: _cmd
								 object: self];

	socketAddresses = [[OFThread DNSResolver]
	    resolveAddressesForHost: host
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




428
429

430
431
432
433
434
435
436
437
438
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
428
429
430







-
+
-

-

















-
-
-
-
-



















-
+
+


-
+
+











-
-
-
-
+
+
+
+
-
-
+
-
-







			while (rnd < 1024)
				rnd = (uint16_t)rand();

			OFSocketAddressSetIPPort(&address, rnd);

			if ((ret = bind(_socket,
			    (struct sockaddr *)&address.sockaddr,
			    address.length)) == 0) {
			    address.length)) == 0)
				port = rnd;
				break;
			}

			if (OFSocketErrNo() != EADDRINUSE) {
				int errNo = OFSocketErrNo();

				closesocket(_socket);
				_socket = OFInvalidSocketHandle;

				@throw [OFBindIPSocketFailedException
				    exceptionWithHost: host
						 port: port
					       socket: self
						errNo: errNo];
			}
		}
	}
#endif

	objc_autoreleasePoolPop(pool);

	if (port > 0)
		return port;

#if !defined(OF_HPUX) && !defined(OF_WII) && !defined(OF_NINTENDO_3DS)
	memset(&address, 0, sizeof(address));

	address.length = (socklen_t)sizeof(address.sockaddr);
	if (OFGetSockName(_socket, (struct sockaddr *)&address.sockaddr,
	    &address.length) != 0) {
		int errNo = OFSocketErrNo();

		closesocket(_socket);
		_socket = OFInvalidSocketHandle;

		@throw [OFBindIPSocketFailedException exceptionWithHost: host
								   port: port
								 socket: self
								  errNo: errNo];
	}

	switch (((struct sockaddr *)&address.sockaddr)->sa_family) {
	case AF_INET:
		return OFFromBigEndian16(address.sockaddr.in.sin_port);
		address.family = OFSocketAddressFamilyIPv4;
		break;
# ifdef OF_HAVE_IPV6
	case AF_INET6:
		return OFFromBigEndian16(address.sockaddr.in6.sin6_port);
		address.family = OFSocketAddressFamilyIPv6;
		break;
# endif
	default:
		closesocket(_socket);
		_socket = OFInvalidSocketHandle;

		@throw [OFBindIPSocketFailedException
		    exceptionWithHost: host
				 port: port
			       socket: self
				errNo: EAFNOSUPPORT];
	}
#else
	closesocket(_socket);
	_socket = OFInvalidSocketHandle;
	@throw [OFBindIPSocketFailedException exceptionWithHost: host
#endif

	objc_autoreleasePoolPop(pool);

							   port: port
							 socket: self
	return address;
							  errNo: EADDRNOTAVAIL];
#endif
}

#if !defined(OF_WII) && !defined(OF_NINTENDO_3DS)
- (void)setSendsKeepAlives: (bool)sendsKeepAlives
{
	int v = sendsKeepAlives;

Modified src/OFTCPSocketSOCKS5Connector.h from [a83f3eec6d] to [3335bb1b05].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFTCPSocketSOCKS5Connector.m from [53af52e1d6] to [892c6ae08b].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFTLSKey.h from [daee12b5cc] to [3b323cb13b].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFTLSKey.m from [e3604d121c] to [e8197af245].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFTLSStream.h from [8cbbbbbe33] to [f204428d75].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
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
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







-
+










-
+









-
+








/**
 * @brief Asynchronously performs the TLS client handshake for the specified
 *	  host and calls the delegate afterwards.
 *
 * @param host The host to perform the handshake with
 * @throw OFTLSHandshakeFailedException The TLS handshake failed
 * @throw OFAlreadyConnectedException The handshake was already performed
 * @throw OFAlreadyOpenException The handshake was already performed
 */
- (void)asyncPerformClientHandshakeWithHost: (OFString *)host;

/**
 * @brief Asynchronously performs the TLS client handshake for the specified
 *	  host and calls the delegate afterwards.
 *
 * @param host The host to perform the handshake with
 * @param runLoopMode The run loop mode in which to perform the async handshake
 * @throw OFTLSHandshakeFailedException The TLS handshake failed
 * @throw OFAlreadyConnectedException The handshake was already performed
 * @throw OFAlreadyOpenException The handshake was already performed
 */
- (void)asyncPerformClientHandshakeWithHost: (OFString *)host
				runLoopMode: (OFRunLoopMode)runLoopMode;

/**
 * @brief Performs the TLS client handshake for the specified host.
 *
 * @param host The host to perform the handshake with
 * @throw OFTLSHandshakeFailedException The TLS handshake failed
 * @throw OFAlreadyConnectedException The handshake was already performed
 * @throw OFAlreadyOpenException The handshake was already performed
 */
- (void)performClientHandshakeWithHost: (OFString *)host;
@end

#ifdef __cplusplus
extern "C" {
#endif

Modified src/OFTLSStream.m from [01bd29e506] to [4de584ae09].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFTarArchive.h from [7f3061b033] to [753185e25e].

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
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

-
+




















-
-
+
+










-
-
-
-
-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 */

#import "OFObject.h"
#import "OFKernelEventObserver.h"
#import "OFString.h"
#import "OFTarArchiveEntry.h"

OF_ASSUME_NONNULL_BEGIN

@class OFStream;
@class OFURI;
@class OFIRI;
@class OFStream;

/**
 * @class OFTarArchive OFTarArchive.h ObjFW/OFTarArchive.h
 *
 * @brief A class for accessing and manipulating tar archives.
 */
OF_SUBCLASSING_RESTRICTED
@interface OFTarArchive: OFObject
{
	OFStream *_stream;
	enum OFTarArchiveMode {
		OFTarArchiveModeRead,
		OFTarArchiveModeWrite,
		OFTarArchiveModeAppend
	} _mode;
	uint_least8_t _mode;
	OFStringEncoding _encoding;
	OFTarArchiveEntry *_Nullable _currentEntry;
#ifdef OF_TAR_ARCHIVE_M
@public
#endif
	OFStream *_Nullable _lastReturnedStream;
}
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
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







-
+








-
+


-
-
+
+


-
-
+
+


-
+







 *				failed
 */
+ (instancetype)archiveWithStream: (OFStream *)stream mode: (OFString *)mode;

/**
 * @brief Creates a new OFTarArchive object with the specified file.
 *
 * @param URI The URI to the tar archive
 * @param IRI The IRI to the tar archive
 * @param mode The mode for the tar file. Valid modes are "r" for reading,
 *	       "w" for creating a new file and "a" for appending to an existing
 *	       archive.
 * @return A new, autoreleased OFTarArchive
 * @throw OFInvalidFormatException The archive has an invalid format
 * @throw OFSeekFailedException The archive was open in append mode and seeking
 *				failed
 */
+ (instancetype)archiveWithURI: (OFURI *)URI mode: (OFString *)mode;
+ (instancetype)archiveWithIRI: (OFIRI *)IRI mode: (OFString *)mode;

/**
 * @brief Creates a URI for accessing a the specified file within the specified
 *	  tar archive.
 * @brief Creates an IRI for accessing a the specified file within the
 *	  specified tar archive.
 *
 * @param path The path of the file within the archive
 * @param URI The URI of the archive
 * @return A URI for accessing the specified file within the specified tar
 * @param IRI The IRI of the archive
 * @return An IRI for accessing the specified file within the specified tar
 *	   archive
 */
+ (OFURI *)URIForFilePath: (OFString *)path inArchiveWithURI: (OFURI *)URI;
+ (OFIRI *)IRIForFilePath: (OFString *)path inArchiveWithIRI: (OFIRI *)IRI;

- (instancetype)init OF_UNAVAILABLE;

/**
 * @brief Initializes an already allocated OFTarArchive object with the
 *	  specified stream.
 *
109
110
111
112
113
114
115
116

117
118
119
120
121
122
123
124
125

126
127
128
129
130
131
132
105
106
107
108
109
110
111

112
113
114
115
116
117
118
119
120

121
122
123
124
125
126
127
128







-
+








-
+







- (instancetype)initWithStream: (OFStream *)stream
			  mode: (OFString *)mode OF_DESIGNATED_INITIALIZER;

/**
 * @brief Initializes an already allocated OFTarArchive object with the
 *	  specified file.
 *
 * @param URI The URI to the tar archive
 * @param IRI The IRI to the tar archive
 * @param mode The mode for the tar file. Valid modes are "r" for reading,
 *	       "w" for creating a new file and "a" for appending to an existing
 *	       archive.
 * @return An initialized OFTarArchive
 * @throw OFInvalidFormatException The archive has an invalid format
 * @throw OFSeekFailedException The archive was open in append mode and seeking
 *				failed
 */
- (instancetype)initWithURI: (OFURI *)URI mode: (OFString *)mode;
- (instancetype)initWithIRI: (OFIRI *)IRI mode: (OFString *)mode;

/**
 * @brief Returns the next entry from the tar archive or `nil` if all entries
 *	  have been read.
 *
 * @note This is only available in read mode.
 *

Modified src/OFTarArchive.m from [8086f04e85] to [0ba99f6e66].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
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
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







-
+

-
-
-
-
+
+
+
+







+
+
+
+
+
+







#include "config.h"

#include <errno.h>

#import "OFTarArchive.h"
#import "OFTarArchiveEntry.h"
#import "OFTarArchiveEntry+Private.h"
#import "OFArchiveURIHandler.h"
#import "OFArchiveIRIHandler.h"
#import "OFDate.h"
#import "OFSeekableStream.h"
#import "OFStream.h"
#import "OFURI.h"
#import "OFURIHandler.h"
#import "OFIRI.h"
#import "OFIRIHandler.h"
#import "OFSeekableStream.h"
#import "OFStream.h"

#import "OFInvalidArgumentException.h"
#import "OFInvalidFormatException.h"
#import "OFNotOpenException.h"
#import "OFOutOfRangeException.h"
#import "OFTruncatedDataException.h"
#import "OFWriteFailedException.h"

enum {
	modeRead,
	modeWrite,
	modeAppend
};

OF_DIRECT_MEMBERS
@interface OFTarArchiveFileReadStream: OFStream <OFReadyForReadingObserving>
{
	OFTarArchive *_archive;
	OFTarArchiveEntry *_entry;
	OFStream *_stream;
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
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







-
+

-
+


-
+

-
+















-
+

-
+

-
+



-
+







@synthesize encoding = _encoding;

+ (instancetype)archiveWithStream: (OFStream *)stream mode: (OFString *)mode
{
	return [[[self alloc] initWithStream: stream mode: mode] autorelease];
}

+ (instancetype)archiveWithURI: (OFURI *)URI mode: (OFString *)mode
+ (instancetype)archiveWithIRI: (OFIRI *)IRI mode: (OFString *)mode
{
	return [[[self alloc] initWithURI: URI mode: mode] autorelease];
	return [[[self alloc] initWithIRI: IRI mode: mode] autorelease];
}

+ (OFURI *)URIForFilePath: (OFString *)path inArchiveWithURI: (OFURI *)URI
+ (OFIRI *)IRIForFilePath: (OFString *)path inArchiveWithIRI: (OFIRI *)IRI
{
	return OFArchiveURIHandlerURIForFileInArchive(@"tar", path, URI);
	return OFArchiveIRIHandlerIRIForFileInArchive(@"tar", path, IRI);
}

- (instancetype)init
{
	OF_INVALID_INIT_METHOD
}

- (instancetype)initWithStream: (OFStream *)stream mode: (OFString *)mode
{
	self = [super init];

	@try {
		_stream = [stream retain];

		if ([mode isEqual: @"r"])
			_mode = OFTarArchiveModeRead;
			_mode = modeRead;
		else if ([mode isEqual: @"w"])
			_mode = OFTarArchiveModeWrite;
			_mode = modeWrite;
		else if ([mode isEqual: @"a"])
			_mode = OFTarArchiveModeAppend;
			_mode = modeAppend;
		else
			@throw [OFInvalidArgumentException exception];

		if (_mode == OFTarArchiveModeAppend) {
		if (_mode == modeAppend) {
			uint32_t buffer[1024 / sizeof(uint32_t)];
			bool empty = true;

			if (![_stream isKindOfClass: [OFSeekableStream class]])
				@throw [OFInvalidArgumentException exception];

			[(OFSeekableStream *)_stream seekToOffset: -1024
132
133
134
135
136
137
138
139

140
141
142
143
144
145
146

147
148

149
150
151
152
153
154
155
138
139
140
141
142
143
144

145
146
147
148
149
150
151

152
153

154
155
156
157
158
159
160
161







-
+






-
+

-
+







		[self release];
		@throw e;
	}

	return self;
}

- (instancetype)initWithURI: (OFURI *)URI mode: (OFString *)mode
- (instancetype)initWithIRI: (OFIRI *)IRI mode: (OFString *)mode
{
	void *pool = objc_autoreleasePoolPush();
	OFStream *stream;

	@try {
		if ([mode isEqual: @"a"])
			stream = [OFURIHandler openItemAtURI: URI mode: @"r+"];
			stream = [OFIRIHandler openItemAtIRI: IRI mode: @"r+"];
		else
			stream = [OFURIHandler openItemAtURI: URI mode: mode];
			stream = [OFIRIHandler openItemAtIRI: IRI mode: mode];
	} @catch (id e) {
		[self release];
		@throw e;
	}

	self = [self initWithStream: stream mode: mode];

168
169
170
171
172
173
174
175

176













177
178
179
180
181
182
183
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







-
+

+
+
+
+
+
+
+
+
+
+
+
+
+







}

- (OFTarArchiveEntry *)nextEntry
{
	uint32_t buffer[512 / sizeof(uint32_t)];
	bool empty = true;

	if (_mode != OFTarArchiveModeRead)
	if (_mode != modeRead)
		@throw [OFInvalidArgumentException exception];

	if (_currentEntry != nil && _lastReturnedStream == nil) {
		/*
		 * No read stream was created since the last call to
		 * -[nextEntry]. Create it so that we can properly skip the
		 *  data.
		 */
		void *pool = objc_autoreleasePoolPush();

		[self streamForReadingCurrentEntry];

		objc_autoreleasePoolPop(pool);
	}

	[_currentEntry release];
	_currentEntry = nil;

	[(OFTarArchiveFileReadStream *)_lastReturnedStream of_skip];
	@try {
		[_lastReturnedStream close];
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
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







-
+

















-
+







		     encoding: _encoding];

	return _currentEntry;
}

- (OFStream *)streamForReadingCurrentEntry
{
	if (_mode != OFTarArchiveModeRead)
	if (_mode != modeRead)
		@throw [OFInvalidArgumentException exception];

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

	_lastReturnedStream = [[[OFTarArchiveFileReadStream alloc]
	    of_initWithArchive: self
			stream: _stream
			 entry: _currentEntry] autorelease];
	[_currentEntry release];
	_currentEntry = nil;

	return _lastReturnedStream;
}

- (OFStream *)streamForWritingEntry: (OFTarArchiveEntry *)entry
{
	if (_mode != OFTarArchiveModeWrite && _mode != OFTarArchiveModeAppend)
	if (_mode != modeWrite && _mode != modeAppend)
		@throw [OFInvalidArgumentException exception];

	@try {
		[_lastReturnedStream close];
	} @catch (OFNotOpenException *e) {
		/* Might have already been closed by the user - that's fine. */
	}
260
261
262
263
264
265
266
267

268
269
270
271
272
273
274
279
280
281
282
283
284
285

286
287
288
289
290
291
292
293







-
+







	@try {
		[_lastReturnedStream close];
	} @catch (OFNotOpenException *e) {
		/* Might have already been closed by the user - that's fine. */
	}
	_lastReturnedStream = nil;

	if (_mode == OFTarArchiveModeWrite || _mode == OFTarArchiveModeAppend) {
	if (_mode == modeWrite || _mode == modeAppend) {
		char buffer[1024];
		memset(buffer, '\0', 1024);
		[_stream writeBuffer: buffer length: 1024];
	}

	[_stream release];
	_stream = nil;

Modified src/OFTarArchiveEntry+Private.h from [d7e9114597] to [f8dd59257d].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFTarArchiveEntry.h from [a18b395a59] to [6ca25b078f].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFTarArchiveEntry.m from [6add4508d8] to [2af76fe94d].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFThread+Private.h from [b87af72459] to [727172a96e].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFThread.h from [b1484db738] to [44ae8d6a81].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFThread.m from [3012eaab1d] to [4fb74cf061].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
28
29
30
31
32
33
34

35
36

37
38
39
40
41
42
43
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45







+


+







# include <sched.h>
#endif
#include "unistd_wrapper.h"

#include "platform.h"

#ifdef OF_AMIGAOS
# define Class IntuitionClass
# include <proto/exec.h>
# include <proto/dos.h>
# undef Class
#endif

#ifdef OF_WII
# define nanosleep ogc_nanosleep
# include <ogcsys.h>
# undef nanosleep
#endif

Modified src/OFTimer+Private.h from [37a8d06411] to [0f4b8327b6].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFTimer.h from [bedc280158] to [e91495b8af].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFTimer.m from [bfe36ca5fb] to [f074999bf7].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFTriple.h from [190f8c3dbc] to [dcc8ac4f6a].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFTriple.m from [51ba3c68c4] to [180ad4fb45].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFUDPSocket+Private.h from [4a674f5731] to [44155f32ea].

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
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

-
+



















-
+
-



/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 */

#import "OFUDPSocket.h"

OF_ASSUME_NONNULL_BEGIN

OF_DIRECT_MEMBERS
@interface OFUDPSocket ()
- (uint16_t)of_bindToAddress: (OFSocketAddress *)address
- (void)of_bindToAddress: (OFSocketAddress *)address extraType: (int)extraType;
		   extraType: (int)extraType;
@end

OF_ASSUME_NONNULL_END

Modified src/OFUDPSocket.h from [9190ffdfc0] to [91885680ff].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
67
68
69
70
71
72
73
74

75
76

77
78

79
80
81
67
68
69
70
71
72
73

74
75

76
77

78
79
80
81







-
+

-
+

-
+



/**
 * @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.
 * @param port The port to bind to. If the port is 0, an unused port will be
 *	       chosen, which can be obtained using the return value.
 * @return The port the socket was bound to
 * @return The address the socket was bound to
 * @throw OFBindIPSocketFailedException Binding failed
 * @throw OFAlreadyConnectedException The socket is already bound
 * @throw OFAlreadyOpenException The socket is already bound
 */
- (uint16_t)bindToHost: (OFString *)host port: (uint16_t)port;
- (OFSocketAddress)bindToHost: (OFString *)host port: (uint16_t)port;
@end

OF_ASSUME_NONNULL_END

Modified src/OFUDPSocket.m from [67c55bc52f] to [c3dd64f929].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
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
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







-
+





-
-
+
+

-
-


+
+
+
+







#import "OFUDPSocket+Private.h"
#import "OFDNSResolver.h"
#import "OFData.h"
#import "OFSocket.h"
#import "OFSocket+Private.h"
#import "OFThread.h"

#import "OFAlreadyConnectedException.h"
#import "OFAlreadyOpenException.h"
#import "OFBindIPSocketFailedException.h"

@implementation OFUDPSocket
@dynamic delegate;

- (uint16_t)of_bindToAddress: (OFSocketAddress *)address
		   extraType: (int)extraType OF_DIRECT
- (void)of_bindToAddress: (OFSocketAddress *)address
	       extraType: (int)extraType OF_DIRECT
{
	void *pool = objc_autoreleasePoolPush();
	uint16_t port;
#if SOCK_CLOEXEC == 0 && defined(HAVE_FCNTL) && defined(FD_CLOEXEC)
	int flags;
#endif
#if !defined(OF_HPUX) && !defined(OF_WII) && !defined(OF_NINTENDO_3DS)
	OFString *host;
	uint16_t port;
#endif

	if ((_socket = socket(
	    ((struct sockaddr *)&address->sockaddr)->sa_family,
	    SOCK_DGRAM | SOCK_CLOEXEC | extraType, 0)) == OFInvalidSocketHandle)
		@throw [OFBindIPSocketFailedException
		    exceptionWithHost: OFSocketAddressString(address)
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
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







-
+














-
-
-
+
+
+
-

-










-
+
-
-
-
-
+
+
+




-
+
+


-
+
+






-
-
+
+



-
-
-
-
-
-
-
-
-



-
+






-
+








-
+



-
+


			    (struct sockaddr *)&address->sockaddr,
			    address->length)) == 0)
				break;

			if (OFSocketErrNo() != EADDRINUSE) {
				int errNo = OFSocketErrNo();
				OFString *host = OFSocketAddressString(address);
				port = OFSocketAddressIPPort(address);
				uint16_t port = OFSocketAddressIPPort(address);

				closesocket(_socket);
				_socket = OFInvalidSocketHandle;

				@throw [OFBindIPSocketFailedException
				    exceptionWithHost: host
						 port: port
					       socket: self
						errNo: errNo];
			}
		}
	}
#endif

	objc_autoreleasePoolPop(pool);

	if ((port = OFSocketAddressIPPort(address)) > 0)
#if !defined(OF_HPUX) && !defined(OF_WII) && !defined(OF_NINTENDO_3DS)
	host = OFSocketAddressString(address);
	port = OFSocketAddressIPPort(address);
		return port;

#if !defined(OF_HPUX) && !defined(OF_WII) && !defined(OF_NINTENDO_3DS)
	memset(address, 0, sizeof(*address));

	address->length = (socklen_t)sizeof(address->sockaddr);
	if (OFGetSockName(_socket, (struct sockaddr *)&address->sockaddr,
	    &address->length) != 0) {
		int errNo = OFSocketErrNo();

		closesocket(_socket);
		_socket = OFInvalidSocketHandle;

		@throw [OFBindIPSocketFailedException
		@throw [OFBindIPSocketFailedException exceptionWithHost: host
		    exceptionWithHost: OFSocketAddressString(address)
				 port: OFSocketAddressIPPort(address)
			       socket: self
				errNo: errNo];
								   port: port
								 socket: self
								  errNo: errNo];
	}

	switch (((struct sockaddr *)&address->sockaddr)->sa_family) {
	case AF_INET:
		return OFFromBigEndian16(address->sockaddr.in.sin_port);
		address->family = OFSocketAddressFamilyIPv4;
		break;
# ifdef OF_HAVE_IPV6
	case AF_INET6:
		return OFFromBigEndian16(address->sockaddr.in6.sin6_port);
		address->family = OFSocketAddressFamilyIPv6;
		break;
# endif
	default:
		closesocket(_socket);
		_socket = OFInvalidSocketHandle;

		@throw [OFBindIPSocketFailedException
		    exceptionWithHost: OFSocketAddressString(address)
				 port: OFSocketAddressIPPort(address)
		    exceptionWithHost: host
				 port: port
			       socket: self
				errNo: EAFNOSUPPORT];
	}
#else
	closesocket(_socket);
	_socket = OFInvalidSocketHandle;

	@throw [OFBindIPSocketFailedException
	    exceptionWithHost: OFSocketAddressString(address)
			 port: OFSocketAddressIPPort(address)
		       socket: self
			errNo: EADDRNOTAVAIL];
#endif
}

- (uint16_t)bindToHost: (OFString *)host port: (uint16_t)port
- (OFSocketAddress)bindToHost: (OFString *)host port: (uint16_t)port
{
	void *pool = objc_autoreleasePoolPush();
	OFData *socketAddresses;
	OFSocketAddress address;

	if (_socket != OFInvalidSocketHandle)
		@throw [OFAlreadyConnectedException exceptionWithSocket: self];
		@throw [OFAlreadyOpenException exceptionWithObject: self];

	socketAddresses = [[OFThread DNSResolver]
	    resolveAddressesForHost: host
		      addressFamily: OFSocketAddressFamilyAny];

	address = *(OFSocketAddress *)[socketAddresses itemAtIndex: 0];
	OFSocketAddressSetIPPort(&address, port);

	port = [self of_bindToAddress: &address extraType: 0];
	[self of_bindToAddress: &address extraType: 0];

	objc_autoreleasePoolPop(pool);

	return port;
	return address;
}
@end

Modified src/OFUNIXDatagramSocket.h from [0a3ec7f2ad] to [e48f72b594].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
62
63
64
65
66
67
68
69

70
71
72
73
74
62
63
64
65
66
67
68

69
70
71
72
73
74







-
+






/**
 * @brief Bind the socket to the specified path.
 *
 * @param path The path to bind to
 * @return The address on which this socket can be reached
 * @throw OFBindUNIXSocketFailedException Binding failed
 * @throw OFAlreadyConnectedException The socket is already bound
 * @throw OFAlreadyOpenException The socket is already bound
 */
- (OFSocketAddress)bindToPath: (OFString *)path;
@end

OF_ASSUME_NONNULL_END

Modified src/OFUNIXDatagramSocket.m from [7203060d9a] to [8a5a642655].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
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
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







-
+













-
+







#endif

#import "OFUNIXDatagramSocket.h"
#import "OFSocket.h"
#import "OFSocket+Private.h"
#import "OFString.h"

#import "OFAlreadyConnectedException.h"
#import "OFAlreadyOpenException.h"
#import "OFBindUNIXSocketFailedException.h"

@implementation OFUNIXDatagramSocket
@dynamic delegate;

- (OFSocketAddress)bindToPath: (OFString *)path
{
	OFSocketAddress address;
#if SOCK_CLOEXEC == 0 && defined(HAVE_FCNTL_H) && defined(FD_CLOEXEC)
	int flags;
#endif

	if (_socket != OFInvalidSocketHandle)
		@throw [OFAlreadyConnectedException exceptionWithSocket: self];
		@throw [OFAlreadyOpenException exceptionWithObject: self];

	address = OFSocketAddressMakeUNIX(path);

	if ((_socket = socket(address.sockaddr.un.sun_family,
	    SOCK_DGRAM | SOCK_CLOEXEC, 0)) == OFInvalidSocketHandle)
		@throw [OFBindUNIXSocketFailedException
		    exceptionWithPath: path

Modified src/OFUNIXStreamSocket.h from [3d105f3c9b] to [4853a769a8].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
51
52
53
54
55
56
57
58

59
60
61
62
63
64
65
66
67

68
69
70
71
72
51
52
53
54
55
56
57

58
59
60
61
62
63
64
65
66

67
68
69
70
71
72







-
+








-
+





    id <OFUNIXStreamSocketDelegate> delegate;

/**
 * @brief Connects the OFUNIXStreamSocket to the specified destination.
 *
 * @param path The path to connect to
 * @throw OFConnectUNIXSocketFailedException Connecting failed
 * @throw OFAlreadyConnectedException The socket is already connected or bound
 * @throw OFAlreadyOpenException The socket is already connected or bound
 */
- (void)connectToPath: (OFString *)path;

/**
 * @brief Binds the socket to the specified host and port.
 *
 * @param path The path to bind to
 * @throw OFBindUNIXSocketFailedException Binding failed
 * @throw OFAlreadyConnectedException The socket is already connected or bound
 * @throw OFAlreadyOpenException The socket is already connected or bound
 */
- (void)bindToPath: (OFString *)path;
@end

OF_ASSUME_NONNULL_END

Modified src/OFUNIXStreamSocket.m from [ff26304fa1] to [24d3c96413].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
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
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







-
+














-
+







#endif

#import "OFUNIXStreamSocket.h"
#import "OFSocket.h"
#import "OFSocket+Private.h"
#import "OFString.h"

#import "OFAlreadyConnectedException.h"
#import "OFAlreadyOpenException.h"
#import "OFBindUNIXSocketFailedException.h"
#import "OFConnectUNIXSocketFailedException.h"

@implementation OFUNIXStreamSocket
@dynamic delegate;

- (void)connectToPath: (OFString *)path
{
	OFSocketAddress address;
#if SOCK_CLOEXEC == 0 && defined(HAVE_FCNTL) && defined(FD_CLOEXEC)
	int flags;
#endif

	if (_socket != OFInvalidSocketHandle)
		@throw [OFAlreadyConnectedException exceptionWithSocket: self];
		@throw [OFAlreadyOpenException exceptionWithObject: self];

	address = OFSocketAddressMakeUNIX(path);

	if ((_socket = socket(address.sockaddr.un.sun_family,
	    SOCK_STREAM | SOCK_CLOEXEC, 0)) == OFInvalidSocketHandle)
		@throw [OFConnectUNIXSocketFailedException
		    exceptionWithPath: path
75
76
77
78
79
80
81
82

83
84
85
86
87
88
89
75
76
77
78
79
80
81

82
83
84
85
86
87
88
89







-
+







{
	OFSocketAddress address;
#if SOCK_CLOEXEC == 0 && defined(HAVE_FCNTL) && defined(FD_CLOEXEC)
	int flags;
#endif

	if (_socket != OFInvalidSocketHandle)
		@throw [OFAlreadyConnectedException exceptionWithSocket: self];
		@throw [OFAlreadyOpenException exceptionWithObject: self];

	address = OFSocketAddressMakeUNIX(path);

	if ((_socket = socket(address.sockaddr.un.sun_family,
	    SOCK_STREAM | SOCK_CLOEXEC, 0)) == OFInvalidSocketHandle)
		@throw [OFBindUNIXSocketFailedException
		    exceptionWithPath: path

Modified src/OFUTF8String+Private.h from [a7a276ddae] to [69dc07c3f5].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFUTF8String.h from [d381d1f2a1] to [082f995832].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFUTF8String.m from [c76e8c2ef7] to [2d7393093e].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFUUID.h from [e73d2af113] to [ac563eb1fe].

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
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

-
+














-











-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 */

#import "OFObject.h"
#import "OFSerialization.h"

OF_ASSUME_NONNULL_BEGIN

@class OFString;

/**
 * @class OFUUID OFUUID.h ObjFW/OFUUID.h
 *
 * @brief A UUID conforming to RFC 4122.
 */
OF_SUBCLASSING_RESTRICTED
@interface OFUUID: OFObject <OFCopying, OFComparing, OFSerialization>
@interface OFUUID: OFObject <OFCopying, OFComparing>
{
	unsigned char _bytes[16];
}

/**
 * @brief The UUID as a string.
 */

Modified src/OFUUID.m from [3edaa624cf] to [81553fcc1d].

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
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

-
+


















-







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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 "OFUUID.h"
#import "OFArray.h"
#import "OFString.h"
#import "OFXMLElement.h"

#import "OFInvalidArgumentException.h"
#import "OFInvalidFormatException.h"
#import "OFOutOfRangeException.h"

#define bytesSize 16

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
140
141
142
143
144
145
146























147
148
149
150
151
152
153







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







		[self release];
		@throw e;
	}

	return self;
}

- (instancetype)initWithSerialization: (OFXMLElement *)element
{
	void *pool = objc_autoreleasePoolPush();
	OFString *UUIDString;

	@try {
		if (![element.name isEqual: self.className] ||
		    ![element.namespace isEqual: OFSerializationNS])
			@throw [OFInvalidArgumentException exception];

		UUIDString = element.stringValue;
	} @catch (id e) {
		[self release];
		@throw e;
	}

	self = [self initWithUUIDString: UUIDString];

	objc_autoreleasePoolPop(pool);

	return self;
}

- (bool)isEqual: (id)object
{
	OFUUID *UUID;

	if (![object isKindOfClass: [OFUUID class]])
		return false;

231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
207
208
209
210
211
212
213














214







-
-
-
-
-
-
-
-
-
-
-
-
-
-

	    _bytes[12], _bytes[13], _bytes[14], _bytes[15]];
}

- (OFString *)description
{
	return self.UUIDString;
}

- (OFXMLElement *)XMLElementBySerializing
{
	void *pool = objc_autoreleasePoolPush();
	OFXMLElement *element = [OFXMLElement elementWithName: self.className
						    namespace: OFSerializationNS
						  stringValue: self.UUIDString];

	[element retain];

	objc_autoreleasePoolPop(pool);

	return [element autorelease];
}
@end

Modified src/OFValue.h from [94dd083371] to [4f26146aa4].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFValue.m from [d37e008646] to [ed60df5d2c].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFWin32ConsoleStdIOStream.h from [d9940ccf28] to [75c92bfe32].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFWindowsRegistryKey.h from [6b1a582030] to [cb0b6108db].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFWindowsRegistryKey.m from [bf1674ca4d] to [40205f5757].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFXMLAttribute.h from [f37ed8f3fd] to [ad0369cec2].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
88
89
90
91
92
93
94
95
96
97
98
99
88
89
90
91
92
93
94


95
96
97







-
-



 * @param nameSpace The namespace of the attribute
 * @param stringValue The string value of the attribute
 * @return An initialized OFXMLAttribute with the specified parameters
 */
- (instancetype)initWithName: (OFString *)name
		   namespace: (nullable OFString *)nameSpace
		 stringValue: (OFString *)stringValue OF_DESIGNATED_INITIALIZER;

- (instancetype)initWithSerialization: (OFXMLElement *)element;
@end

OF_ASSUME_NONNULL_END

Modified src/OFXMLAttribute.m from [fef93ca0aa] to [5c47193c55].

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
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

-
+



















-







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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 "OFXMLAttribute.h"
#import "OFXMLNode+Private.h"
#import "OFString.h"
#import "OFDictionary.h"
#import "OFXMLElement.h"

#import "OFInvalidArgumentException.h"

@implementation OFXMLAttribute
@synthesize name = _name, namespace = _namespace;

+ (instancetype)attributeWithName: (OFString *)name
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
60
61
62
63
64
65
66




































67
68
69
70
71
72
73







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







		_namespace = [namespace copy];
		_stringValue = [stringValue copy];
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (instancetype)initWithSerialization: (OFXMLElement *)element
{
	void *pool;
	OFString *name, *namespace, *stringValue;

	@try {
		pool = objc_autoreleasePoolPush();

		if (![element.name isEqual: self.className] ||
		    ![element.namespace isEqual: OFSerializationNS])
			@throw [OFInvalidArgumentException exception];

		name = [element attributeForName: @"name"].stringValue;
		namespace = [element attributeForName: @"namespace"]
		    .stringValue;
		stringValue = [element attributeForName: @"stringValue"]
		    .stringValue;
	} @catch (id e) {
		[self release];
		@throw e;
	}

	self = [self initWithName: name
			namespace: namespace
		      stringValue: stringValue];

	@try {
		objc_autoreleasePoolPop(pool);
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (void)dealloc
{
	[_name release];
	[_namespace release];
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
122
123
124
125
126
127
128























129
130
131
132
133
134
135
136







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-








	OFHashAddHash(&hash, _stringValue.hash);

	OFHashFinalize(&hash);

	return hash;
}

- (OFXMLElement *)XMLElementBySerializing
{
	void *pool = objc_autoreleasePoolPush();
	OFXMLElement *element;

	element = [OFXMLElement elementWithName: self.className
				      namespace: OFSerializationNS];
	[element addAttributeWithName: @"name" stringValue: _name];

	if (_namespace != nil)
		[element addAttributeWithName: @"namespace"
				  stringValue: _namespace];

	[element addAttributeWithName: @"stringValue"
			  stringValue: _stringValue];

	[element retain];

	objc_autoreleasePoolPop(pool);

	return [element autorelease];
}

- (OFString *)description
{
	return [OFString stringWithFormat: @"<%@: name=%@, namespace=%@, "
					   @"stringValue=%@>",
					   self.class, _name, _namespace,
					   _stringValue];
}
@end

Modified src/OFXMLCDATA.h from [45c442f70d] to [0b1ca7487a].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
39
40
41
42
43
44
45
46
47
48
49
50
39
40
41
42
43
44
45


46
47
48







-
-



/**
 * @brief Initializes an already allocated OFXMLCDATA with the specified string.
 *
 * @param string The string value for the CDATA
 * @return An initialized OFXMLCDATA
 */
- (instancetype)initWithString: (OFString *)string;

- (instancetype)initWithSerialization: (OFXMLElement *)element;
@end

OF_ASSUME_NONNULL_END

Modified src/OFXMLCDATA.m from [268b8de778] to [b5a30e1981].

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
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

-
+


















-




















-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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 "OFXMLCDATA.h"
#import "OFXMLNode+Private.h"
#import "OFString.h"
#import "OFXMLElement.h"

#import "OFInvalidArgumentException.h"

@implementation OFXMLCDATA
+ (instancetype)CDATAWithString: (OFString *)string
{
	return [[[self alloc] initWithString: string] autorelease];
}

- (instancetype)initWithString: (OFString *)string
{
	self = [super of_init];

	@try {
		_CDATA = [string copy];
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (instancetype)initWithSerialization: (OFXMLElement *)element
{
	self = [super of_init];

	@try {
		void *pool = objc_autoreleasePoolPush();

		if (![element.name isEqual: self.className] ||
		    ![element.namespace isEqual: OFSerializationNS])
			@throw [OFInvalidArgumentException exception];

		_CDATA = [element.stringValue copy];

		objc_autoreleasePoolPop(pool);
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (void)dealloc
{
	[_CDATA release];

116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
93
94
95
96
97
98
99










100







-
-
-
-
-
-
-
-
-
-

	return [ret autorelease];
}

- (OFString *)description
{
	return self.XMLString;
}

- (OFXMLElement *)XMLElementBySerializing
{
	OFXMLElement *element =
	    [OFXMLElement elementWithName: self.className
				namespace: OFSerializationNS];
	[element addChild: self];

	return element;
}
@end

Modified src/OFXMLCharacters.h from [50ac8d5a7f] to [d7b0cc572e].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
40
41
42
43
44
45
46
47
48
49
50
51
40
41
42
43
44
45
46


47
48
49







-
-



 * @brief Initializes an already allocated OFXMLCharacters with the specified
 *	  string.
 *
 * @param string The string value for the characters
 * @return An initialized OFXMLCharacters
 */
- (instancetype)initWithString: (OFString *)string;

- (instancetype)initWithSerialization: (OFXMLElement *)element;
@end

OF_ASSUME_NONNULL_END

Modified src/OFXMLCharacters.m from [53e16f06bf] to [d4a7b166de].

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
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

-
+


















-




















-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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 "OFXMLCharacters.h"
#import "OFXMLNode+Private.h"
#import "OFString.h"
#import "OFXMLElement.h"

#import "OFInvalidArgumentException.h"

@implementation OFXMLCharacters
+ (instancetype)charactersWithString: (OFString *)string
{
	return [[[self alloc] initWithString: string] autorelease];
}

- (instancetype)initWithString: (OFString *)string
{
	self = [super of_init];

	@try {
		_characters = [string copy];
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (instancetype)initWithSerialization: (OFXMLElement *)element
{
	self = [super of_init];

	@try {
		void *pool = objc_autoreleasePoolPush();

		if (![element.name isEqual: self.className] ||
		    ![element.namespace isEqual: OFSerializationNS])
			@throw [OFInvalidArgumentException exception];

		_characters = [element.stringValue copy];

		objc_autoreleasePoolPop(pool);
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (void)dealloc
{
	[_characters release];

108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
85
86
87
88
89
90
91







92







-
-
-
-
-
-
-

	return _characters.stringByXMLEscaping;
}

- (OFString *)description
{
	return self.XMLString;
}

- (OFXMLElement *)XMLElementBySerializing
{
	return [OFXMLElement elementWithName: self.className
				   namespace: OFSerializationNS
				 stringValue: _characters];
}
@end

Modified src/OFXMLComment.h from [566c15f0b8] to [0ac62de2c0].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
45
46
47
48
49
50
51
52
53
54
55
56
45
46
47
48
49
50
51


52
53
54







-
-



 * @brief Initializes an already allocated OFXMLComment with the specified
 *	  text.
 *
 * @param text The text for the comment
 * @return An initialized OFXMLComment
 */
- (instancetype)initWithText: (OFString *)text;

- (instancetype)initWithSerialization: (OFXMLElement *)element;
@end

OF_ASSUME_NONNULL_END

Modified src/OFXMLComment.m from [9e48182a96] to [72a694fdfc].

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
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

-
+




















-







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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"

#include <string.h>

#import "OFXMLComment.h"
#import "OFXMLNode+Private.h"
#import "OFString.h"
#import "OFXMLElement.h"

#import "OFInvalidArgumentException.h"

@implementation OFXMLComment
@synthesize text = _text;

+ (instancetype)commentWithText: (OFString *)text
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
38
39
40
41
42
43
44






















45
46
47
48
49
50
51







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







	@try {
		_text = [text copy];
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (instancetype)initWithSerialization: (OFXMLElement *)element
{
	self = [super of_init];

	@try {
		void *pool = objc_autoreleasePoolPush();

		if (![element.name isEqual: self.className] ||
		    ![element.namespace isEqual: OFSerializationNS])
			@throw [OFInvalidArgumentException exception];

		_text = [element.stringValue copy];

		objc_autoreleasePoolPop(pool);
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (void)dealloc
{
	[_text release];

105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
82
83
84
85
86
87
88







89







-
-
-
-
-
-
-

	return [OFString stringWithFormat: @"<!--%@-->", _text];
}

- (OFString *)description
{
	return self.XMLString;
}

- (OFXMLElement *)XMLElementBySerializing
{
	return [OFXMLElement elementWithName: self.className
				   namespace: OFSerializationNS
				 stringValue: _text];
}
@end

Deleted src/OFXMLElement+Serialization.h version [fdd03ade73].

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




































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 */

#import "OFXMLElement.h"

OF_ASSUME_NONNULL_BEGIN

#ifdef __cplusplus
extern "C" {
#endif
extern int _OFXMLElement_Serialization_reference;
#ifdef __cplusplus
}
#endif

@interface OFXMLElement (OFSerialization)
/**
 * @brief The XML element interpreted as serialization and parsed into an
 *	  object.
 */
@property (readonly, nonatomic) id objectByDeserializing;
@end

OF_ASSUME_NONNULL_END

Deleted src/OFXMLElement+Serialization.m version [c71645309e].

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















































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * 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 "OFXMLElement.h"
#import "OFXMLElement+Serialization.h"
#import "OFSerialization.h"
#import "OFString.h"

#import "OFInvalidArgumentException.h"

int _OFXMLElement_Serialization_reference;

@implementation OFXMLElement (Serialization)
- (id)objectByDeserializing
{
	void *pool = objc_autoreleasePoolPush();
	Class class;
	id object;

	if ((class = objc_getClass([_name cStringWithEncoding:
	    OFStringEncodingASCII])) == Nil)
		@throw [OFInvalidArgumentException exception];

	if (![class conformsToProtocol: @protocol(OFSerialization)])
		@throw [OFInvalidArgumentException exception];

	object = [[class alloc] initWithSerialization: self];

	objc_autoreleasePoolPop(pool);

	return [object autorelease];
}
@end

Modified src/OFXMLElement.h from [0fc969c160] to [30ce632507].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
430
431
432
433
434
435
436
437
438
430
431
432
433
434
435
436









-
-
 *				      needs a prefix
 */
- (OFString *)XMLStringWithDefaultNamespace: (OFString *)defaultNS
				indentation: (unsigned int)indentation;
@end

OF_ASSUME_NONNULL_END

#import "OFXMLElement+Serialization.h"

Modified src/OFXMLElement.m from [f2bc65b077] to [b73068b828].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
34
35
36
37
38
39
40







41
42
43
44
45
46
47







-
-
-
-
-
-
-







#import "OFXMLParser.h"

#import "OFInvalidArgumentException.h"
#import "OFInvalidFormatException.h"
#import "OFMalformedXMLException.h"
#import "OFUnboundNamespaceException.h"

/* References for static linking */
void
_references_to_categories_of_OFXMLElement(void)
{
	_OFXMLElement_Serialization_reference = 1;
}

@interface OFXMLElementElementBuilderDelegate: OFObject
    <OFXMLElementBuilderDelegate>
{
@public
	OFXMLElement *_element;
}
@end
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
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
256
257
258
259
260
261
262


































































































263
264
265
266
267
268
269







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







		[_attributes release];
		_attributes = [element->_attributes retain];
		[_namespaces release];
		_namespaces = [element->_namespaces retain];
		[_children release];
		_children = [element->_children retain];

		objc_autoreleasePoolPop(pool);
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (instancetype)initWithSerialization: (OFXMLElement *)element
{
	void *pool;
	OFString *name, *namespace;

	@try {
		pool = objc_autoreleasePoolPush();

		if (![element.name isEqual: self.className] ||
		    ![element.namespace isEqual: OFSerializationNS])
			@throw [OFInvalidArgumentException exception];

		name = [element attributeForName: @"name"].stringValue;
		namespace =
		    [element attributeForName: @"namespace"].stringValue;
	} @catch (id e) {
		[self release];
		@throw e;
	}

	self = [self initWithName: name namespace: namespace];

	@try {
		OFXMLElement *attributesElement, *namespacesElement;
		OFXMLElement *childrenElement;
		OFEnumerator *keyEnumerator, *objectEnumerator;
		OFString *key, *object;

		attributesElement = [[element
		    elementForName: @"attributes"
			 namespace: OFSerializationNS]
		    elementsForNamespace: OFSerializationNS].firstObject;
		namespacesElement = [[element
		    elementForName: @"namespaces"
			 namespace: OFSerializationNS]
		    elementsForNamespace: OFSerializationNS].firstObject;
		childrenElement = [[element
		    elementForName: @"children"
			 namespace: OFSerializationNS]
		    elementsForNamespace: OFSerializationNS].firstObject;

		[_attributes release];
		_attributes = nil;
		_attributes = [attributesElement.objectByDeserializing
		    mutableCopy];

		[_namespaces release];
		_namespaces = nil;
		_namespaces = [namespacesElement.objectByDeserializing
		    mutableCopy];

		[_children release];
		_children = nil;
		_children = [childrenElement.objectByDeserializing
		    mutableCopy];

		/* Sanity checks */
		if ((_attributes != nil && ![_attributes isKindOfClass:
		    [OFMutableArray class]]) || (_namespaces != nil &&
		    ![_namespaces isKindOfClass:
		    [OFMutableDictionary class]]) || (_children != nil &&
		    ![_children isKindOfClass: [OFMutableArray class]]))
			@throw [OFInvalidArgumentException exception];

		for (OFXMLAttribute *attribute in _attributes)
			if (![attribute isKindOfClass: [OFXMLAttribute class]])
				@throw [OFInvalidArgumentException exception];

		keyEnumerator = [_namespaces keyEnumerator];
		objectEnumerator = [_namespaces objectEnumerator];
		while ((key = [keyEnumerator nextObject]) != nil &&
		    (object = [objectEnumerator nextObject]) != nil)
			if (![key isKindOfClass: [OFString class]] ||
			    ![object isKindOfClass: [OFString class]])
				@throw [OFInvalidArgumentException exception];

		for (object in _children)
			if (![object isKindOfClass: [OFXMLNode class]])
				@throw [OFInvalidArgumentException exception];

		if (_namespaces == nil)
			_namespaces = [[OFMutableDictionary alloc] init];

		[_namespaces
		    setObject: @"xml"
		       forKey: @"http://www.w3.org/XML/1998/namespace"];
		[_namespaces setObject: @"xmlns"
				forKey: @"http://www.w3.org/2000/xmlns/"];

		objc_autoreleasePoolPop(pool);
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
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
559
560
561
562
563
564
565































































566
567
568
569
570
571
572







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







{
	return [self of_XMLStringWithDefaultNS: defaultNS
				    namespaces: nil
				   indentation: indentation
					 level: 0];
}

- (OFXMLElement *)XMLElementBySerializing
{
	void *pool = objc_autoreleasePoolPush();
	OFXMLElement *element;

	element = [OFXMLElement elementWithName: self.className
				      namespace: OFSerializationNS];

	if (_name != nil)
		[element addAttributeWithName: @"name" stringValue: _name];

	if (_namespace != nil)
		[element addAttributeWithName: @"namespace"
				  stringValue: _namespace];

	if (_attributes != nil) {
		OFXMLElement *attributesElement;

		attributesElement =
		    [OFXMLElement elementWithName: @"attributes"
					namespace: OFSerializationNS];
		[attributesElement addChild:
		    _attributes.XMLElementBySerializing];
		[element addChild: attributesElement];
	}

	if (_namespaces != nil) {
		OFXMLElement *namespacesElement;
		OFMutableDictionary *namespacesCopy =
		    [[_namespaces mutableCopy] autorelease];

		[namespacesCopy removeObjectForKey:
		    @"http://www.w3.org/XML/1998/namespace"];
		[namespacesCopy removeObjectForKey:
		    @"http://www.w3.org/2000/xmlns/"];

		if (namespacesCopy.count > 0) {
			namespacesElement =
			    [OFXMLElement elementWithName: @"namespaces"
						namespace: OFSerializationNS];
			[namespacesElement addChild:
			    namespacesCopy.XMLElementBySerializing];
			[element addChild: namespacesElement];
		}
	}

	if (_children != nil) {
		OFXMLElement *childrenElement;

		childrenElement =
		    [OFXMLElement elementWithName: @"children"
					namespace: OFSerializationNS];
		[childrenElement addChild: _children.XMLElementBySerializing];
		[element addChild: childrenElement];
	}

	[element retain];

	objc_autoreleasePoolPop(pool);

	return [element autorelease];
}

- (void)addAttribute: (OFXMLAttribute *)attribute
{
	if (![attribute isKindOfClass: [OFXMLAttribute class]])
		@throw [OFInvalidArgumentException exception];

	if (_attributes == nil)
		_attributes = [[OFMutableArray alloc] init];

Modified src/OFXMLElementBuilder.h from [db177baac1] to [fc2537fa67].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFXMLElementBuilder.m from [87c5fa2116] to [c0268e256a].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFXMLNode+Private.h from [fcadbb17a0] to [a4e39bf096].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFXMLNode.h from [5f2e542386] to [ed1c4fdaa7].

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
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

-
+














-



-
-





-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 */

#import "OFObject.h"
#import "OFSerialization.h"

OF_ASSUME_NONNULL_BEGIN

@class OFXMLElement;

/**
 * @class OFXMLNode OFXMLNode.h ObjFW/OFXMLNode.h
 *
 * @brief A class which stores an XML element.
 */
@interface OFXMLNode: OFObject <OFCopying, OFSerialization>
@interface OFXMLNode: OFObject <OFCopying>
{
	OF_RESERVE_IVARS(OFXMLNode, 4)
}

/**
 * @brief The contents of the node as a string value.
 *
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
70
71
72
73
74
75
76

77
78
79
80
81
82
83







-







 * @throw OFUnboundNamespaceException The node uses a namespace that was not
 *				      bound to a prefix in a context where it
 *				      needs a prefix
 */
@property (readonly, nonatomic) OFString *XMLString;

- (instancetype)init OF_UNAVAILABLE;
- (instancetype)initWithSerialization: (OFXMLElement *)element OF_UNAVAILABLE;

/**
 * @brief The contents of the receiver as a `long long` value in the specified
 *	  base.
 *
 * @param base The base to use. If the base is 0, base 16 is assumed if the
 * 	       string starts with 0x (after stripping white spaces). If the

Modified src/OFXMLNode.m from [ae31a5d0f3] to [db9f6871fb].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
22
23
24
25
26
27
28





29
30
31
32
33
34
35







-
-
-
-
-







- (instancetype)of_init
{
	return [super init];
}

- (instancetype)init
{
	OF_INVALID_INIT_METHOD
}

- (instancetype)initWithSerialization: (OFXMLElement *)element
{
	OF_INVALID_INIT_METHOD
}

- (OFString *)stringValue
{
	OF_UNRECOGNIZED_SELECTOR
}
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
75
76
77
78
79
80
81





82
83
84
85
86







-
-
-
-
-





}

- (OFString *)description
{
	return self.XMLString;
}

- (OFXMLElement *)XMLElementBySerializing
{
	OF_UNRECOGNIZED_SELECTOR
}

- (id)copy
{
	return [self retain];
}
@end

Modified src/OFXMLParser.h from [89f07c26d5] to [e18365e7c0].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFXMLParser.m from [7be6fc7234] to [d3addaaa2c].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFXMLProcessingInstruction.h from [2e0c868afb] to [ea520587d0].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
56
57
58
59
60
61
62
63
64
65
66
67
56
57
58
59
60
61
62


63
64
65







-
-



 *
 * @param target The target for the processing instruction
 * @param text The text for the processing instruction
 * @return An initialized OFXMLProcessingInstruction
 */
- (instancetype)initWithTarget: (OFString *)target
			  text: (OFString *)text OF_DESIGNATED_INITIALIZER;

- (instancetype)initWithSerialization: (OFXMLElement *)element;
@end

OF_ASSUME_NONNULL_END

Modified src/OFXMLProcessingInstruction.m from [98f7922e9f] to [44d4bf9d3c].

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
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

-
+




















-







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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"

#include <string.h>

#import "OFXMLProcessingInstruction.h"
#import "OFString.h"
#import "OFXMLAttribute.h"
#import "OFXMLElement.h"
#import "OFXMLNode+Private.h"

#import "OFInvalidArgumentException.h"

@implementation OFXMLProcessingInstruction
@synthesize target = _target, text = _text;

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
43
44
45
46
47
48
49



























50
51
52
53
54
55
56







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







		_target = [target copy];
		_text = [text copy];
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (instancetype)initWithSerialization: (OFXMLElement *)element
{
	@try {
		void *pool = objc_autoreleasePoolPush();
		OFXMLAttribute *targetAttr;

		if (![element.name isEqual: self.className] ||
		    ![element.namespace isEqual: OFSerializationNS])
			@throw [OFInvalidArgumentException exception];

		targetAttr = [element attributeForName: @"target"
					     namespace: OFSerializationNS];
		if (targetAttr.stringValue.length == 0)
			@throw [OFInvalidArgumentException exception];

		self = [self initWithTarget: targetAttr.stringValue
				       text: element.stringValue];

		objc_autoreleasePoolPop(pool);
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (void)dealloc
{
	[_target release];
	[_text release];
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
106
107
108
109
110
111
112















113







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

		return [OFString stringWithFormat: @"<?%@?>", _target];
}

- (OFString *)description
{
	return self.XMLString;
}

- (OFXMLElement *)XMLElementBySerializing
{
	OFXMLElement *ret = [OFXMLElement elementWithName: self.className
						namespace: OFSerializationNS
					      stringValue: _text];
	void *pool = objc_autoreleasePoolPush();

	[ret addAttribute: [OFXMLAttribute attributeWithName: @"target"
						 stringValue: _target]];

	objc_autoreleasePoolPop(pool);

	return ret;
}
@end

Modified src/OFZIPArchive.h from [b8f3f259b0] to [82b11667ec].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
28
29
30
31
32
33
34
35

36
37
38
39
40
41
42
28
29
30
31
32
33
34

35
36
37
38
39
40
41
42







-
+







 * @class OFZIPArchive OFZIPArchive.h ObjFW/OFZIPArchive.h
 *
 * @brief A class for accessing and manipulating ZIP files.
 */
OF_SUBCLASSING_RESTRICTED
@interface OFZIPArchive: OFObject
{
	OFStream *_stream;
	OF_KINDOF(OFStream *) _stream;
#ifdef OF_ZIP_ARCHIVE_M
@public
#endif
	int64_t _offset;
@protected
	uint_least8_t _mode;
	uint32_t _diskNumber, _centralDirectoryDisk;
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
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







-
+






-
+


-
-
+
+


-
-
+
+


-
+







 * @throw OFInvalidFormatException The format is not that of a valid ZIP archive
 */
+ (instancetype)archiveWithStream: (OFStream *)stream mode: (OFString *)mode;

/**
 * @brief Creates a new OFZIPArchive object with the specified file.
 *
 * @param URI The URI to the ZIP file
 * @param IRI The IRI to the ZIP file
 * @param mode The mode for the ZIP file. Valid modes are "r" for reading,
 *	       "w" for creating a new file and "a" for appending to an existing
 *	       archive.
 * @return A new, autoreleased OFZIPArchive
 * @throw OFInvalidFormatException The format is not that of a valid ZIP archive
 */
+ (instancetype)archiveWithURI: (OFURI *)URI mode: (OFString *)mode;
+ (instancetype)archiveWithIRI: (OFIRI *)IRI mode: (OFString *)mode;

/**
 * @brief Creates a URI for accessing a the specified file within the specified
 *	  ZIP archive.
 * @brief Creates an IRI for accessing a the specified file within the
 *	  specified ZIP archive.
 *
 * @param path The path of the file within the archive
 * @param URI The URI of the archive
 * @return A URI for accessing the specified file within the specified ZIP
 * @param IRI The IRI of the archive
 * @return An IRI for accessing the specified file within the specified ZIP
 *	   archive
 */
+ (OFURI *)URIForFilePath: (OFString *)path inArchiveWithURI: (OFURI *)URI;
+ (OFIRI *)IRIForFilePath: (OFString *)path inArchiveWithIRI: (OFIRI *)IRI;

- (instancetype)init OF_UNAVAILABLE;

/**
 * @brief Initializes an already allocated OFZIPArchive object with the
 *	  specified stream.
 *
122
123
124
125
126
127
128
129

130
131
132
133
134
135
136

137
138
139
140
141
142
143
122
123
124
125
126
127
128

129
130
131
132
133
134
135

136
137
138
139
140
141
142
143







-
+






-
+







- (instancetype)initWithStream: (OFStream *)stream
			  mode: (OFString *)mode OF_DESIGNATED_INITIALIZER;

/**
 * @brief Initializes an already allocated OFZIPArchive object with the
 *	  specified file.
 *
 * @param URI The URI to the ZIP file
 * @param IRI The IRI to the ZIP file
 * @param mode The mode for the ZIP file. Valid modes are "r" for reading,
 *	       "w" for creating a new file and "a" for appending to an existing
 *	       archive.
 * @return An initialized OFZIPArchive
 * @throw OFInvalidFormatException The format is not that of a valid ZIP archive
 */
- (instancetype)initWithURI: (OFURI *)URI mode: (OFString *)mode;
- (instancetype)initWithIRI: (OFIRI *)IRI mode: (OFString *)mode;

/**
 * @brief Returns a stream for reading the specified file from the archive.
 *
 * @note This method is only available in read mode.
 *
 * @note The returned stream conforms to @ref OFReadyForReadingObserving if the
184
185
186
187
188
189
190
191
192
193





194
195
196
197
198
199
200
184
185
186
187
188
189
190



191
192
193
194
195
196
197
198
199
200
201
202







-
-
-
+
+
+
+
+







 *		  * The uncompressed size.
 *		  * The CRC32.
 *		  * Bit 3 and 11 of the general purpose bit flag.
 * @return A stream for writing the specified entry to the archive
 * @throw OFNotOpenException The archive is not open
 * @throw OFInvalidArgumentException The archive is not in write mode
 * @throw OFOpenItemFailedException Opening the specified file within the
 *				    archive failed. If @ref errNo is `EEXIST`,
 *				    because there is already a file with the
 *				    same name in the archive.
 *				    archive failed. If
 *				    @ref OFOpenItemFailedException#errNo is
 *				    `EEXIST`, it failed because there is
 *				    already a file with the same name in the
 *				    archive.
 * @throw OFNotImplementedException The desired compression method is not
 *				    implemented
 */
- (OFStream *)streamForWritingEntry: (OFZIPArchiveEntry *)entry;

/**
 * @brief Closes the OFZIPArchive.

Modified src/OFZIPArchive.m from [3d9576934f] to [1186bd8318].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
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
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







-
+




+
+




-
-







#include "config.h"

#include <errno.h>

#import "OFZIPArchive.h"
#import "OFZIPArchiveEntry.h"
#import "OFZIPArchiveEntry+Private.h"
#import "OFArchiveURIHandler.h"
#import "OFArchiveIRIHandler.h"
#import "OFArray.h"
#import "OFCRC32.h"
#import "OFData.h"
#import "OFDictionary.h"
#import "OFIRI.h"
#import "OFIRIHandler.h"
#import "OFInflate64Stream.h"
#import "OFInflateStream.h"
#import "OFSeekableStream.h"
#import "OFStream.h"
#import "OFURI.h"
#import "OFURIHandler.h"

#import "OFChecksumMismatchException.h"
#import "OFInvalidArgumentException.h"
#import "OFInvalidFormatException.h"
#import "OFNotImplementedException.h"
#import "OFNotOpenException.h"
#import "OFOpenItemFailedException.h"
97
98
99
100
101
102
103
104

105

106
107
108
109
110
111
112
113



114
115
116
117
118
119
120
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







-
+

+







-
+
+
+







			     entry: (OFZIPArchiveEntry *)entry;
@end

OF_DIRECT_MEMBERS
@interface OFZIPArchiveFileWriteStream: OFStream
{
	OFZIPArchive *_archive;
	OFStream *_stream;
	OF_KINDOF(OFStream *) _stream;
	uint32_t _CRC32;
	OFStreamOffset _CRC32Offset, _size64Offset;
@public
	unsigned long long _bytesWritten;
	OFMutableZIPArchiveEntry *_entry;
}

- (instancetype)of_initWithArchive: (OFZIPArchive *)archive
			    stream: (OFStream *)stream
			     entry: (OFMutableZIPArchiveEntry *)entry;
			     entry: (OFMutableZIPArchiveEntry *)entry
		       CRC32Offset: (OFStreamOffset)CRC32Offset
		      size64Offset: (OFStreamOffset)size64Offset;
@end

uint32_t
OFZIPArchiveReadField32(const uint8_t **data, uint16_t *size)
{
	uint32_t field = 0;

165
166
167
168
169
170
171
172

173
174

175
176
177

178
179

180
181
182
183
184
185
186
168
169
170
171
172
173
174

175
176

177
178
179

180
181

182
183
184
185
186
187
188
189







-
+

-
+


-
+

-
+







@synthesize archiveComment = _archiveComment;

+ (instancetype)archiveWithStream: (OFStream *)stream mode: (OFString *)mode
{
	return [[[self alloc] initWithStream: stream mode: mode] autorelease];
}

+ (instancetype)archiveWithURI: (OFURI *)URI mode: (OFString *)mode
+ (instancetype)archiveWithIRI: (OFIRI *)IRI mode: (OFString *)mode
{
	return [[[self alloc] initWithURI: URI mode: mode] autorelease];
	return [[[self alloc] initWithIRI: IRI mode: mode] autorelease];
}

+ (OFURI *)URIForFilePath: (OFString *)path inArchiveWithURI: (OFURI *)URI
+ (OFIRI *)IRIForFilePath: (OFString *)path inArchiveWithIRI: (OFIRI *)IRI
{
	return OFArchiveURIHandlerURIForFileInArchive(@"zip", path, URI);
	return OFArchiveIRIHandlerIRIForFileInArchive(@"zip", path, IRI);
}

- (instancetype)init
{
	OF_INVALID_INIT_METHOD
}

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
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







-
+


















-
+






-
+

-
+








			[self of_readZIPInfo];
			[self of_readEntries];
		}

		if (_mode == modeAppend) {
			_offset = _centralDirectoryOffset;
			seekOrThrowInvalidFormat((OFSeekableStream *)_stream,
			seekOrThrowInvalidFormat(_stream,
			    (OFStreamOffset)_offset, OFSeekSet);
		}
	} @catch (id e) {
		/*
		 * If we are in write or append mode, we do not want -[close]
		 * to write anything to it on error - after all, it might not
		 * be a ZIP file which we would destroy otherwise.
		 */
		[_stream release];
		_stream = nil;

		[self release];
		@throw e;
	}

	return self;
}

- (instancetype)initWithURI: (OFURI *)URI mode: (OFString *)mode
- (instancetype)initWithIRI: (OFIRI *)IRI mode: (OFString *)mode
{
	void *pool = objc_autoreleasePoolPush();
	OFStream *stream;

	@try {
		if ([mode isEqual: @"a"])
			stream = [OFURIHandler openItemAtURI: URI mode: @"r+"];
			stream = [OFIRIHandler openItemAtIRI: IRI mode: @"r+"];
		else
			stream = [OFURIHandler openItemAtURI: URI mode: mode];
			stream = [OFIRIHandler openItemAtIRI: IRI mode: mode];
	} @catch (id e) {
		[self release];
		@throw e;
	}

	self = [self initWithStream: stream mode: mode];

270
271
272
273
274
275
276
277
278

279
280
281
282
283
284
285
273
274
275
276
277
278
279


280
281
282
283
284
285
286
287







-
-
+







{
	void *pool = objc_autoreleasePoolPush();
	uint16_t commentLength;
	OFStreamOffset offset = -22;
	bool valid = false;

	do {
		seekOrThrowInvalidFormat((OFSeekableStream *)_stream,
		    offset, OFSeekEnd);
		seekOrThrowInvalidFormat(_stream, offset, OFSeekEnd);

		if ([_stream readLittleEndianInt32] == 0x06054B50) {
			valid = true;
			break;
		}
	} while (--offset >= -65557);

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
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







-
-
+
















-
+







	    _centralDirectoryEntriesInDisk == 0xFFFF ||
	    _centralDirectoryEntries == 0xFFFF ||
	    _centralDirectorySize == 0xFFFFFFFF ||
	    _centralDirectoryOffset == 0xFFFFFFFF) {
		int64_t offset64;
		uint64_t size;

		seekOrThrowInvalidFormat((OFSeekableStream *)_stream,
		    offset - 20, OFSeekEnd);
		seekOrThrowInvalidFormat(_stream, offset - 20, OFSeekEnd);

		if ([_stream readLittleEndianInt32] != 0x07064B50) {
			objc_autoreleasePoolPop(pool);
			return;
		}

		/*
		 * FIXME: Handle number of the disk containing ZIP64 end of
		 * central directory record.
		 */
		[_stream readLittleEndianInt32];
		offset64 = [_stream readLittleEndianInt64];

		if (offset64 < 0 || (OFStreamOffset)offset64 != offset64)
			@throw [OFOutOfRangeException exception];

		seekOrThrowInvalidFormat((OFSeekableStream *)_stream,
		seekOrThrowInvalidFormat(_stream,
		    (OFStreamOffset)offset64, OFSeekSet);

		if ([_stream readLittleEndianInt32] != 0x06064B50)
			@throw [OFInvalidFormatException exception];

		size = [_stream readLittleEndianInt64];
		if (size < 44)
361
362
363
364
365
366
367
368

369
370
371
372
373
374
375
362
363
364
365
366
367
368

369
370
371
372
373
374
375
376







-
+







{
	void *pool = objc_autoreleasePoolPush();

	if (_centralDirectoryOffset < 0 ||
	    (OFStreamOffset)_centralDirectoryOffset != _centralDirectoryOffset)
		@throw [OFOutOfRangeException exception];

	seekOrThrowInvalidFormat((OFSeekableStream *)_stream,
	seekOrThrowInvalidFormat(_stream,
	    (OFStreamOffset)_centralDirectoryOffset, OFSeekSet);

	for (size_t i = 0; i < _centralDirectoryEntries; i++) {
		OFZIPArchiveEntry *entry = [[[OFZIPArchiveEntry alloc]
		    of_initWithStream: _stream] autorelease];

		if ([_pathToEntryMap objectForKey: entry.fileName] != nil)
432
433
434
435
436
437
438
439
440

441
442
443
444
445
446
447
433
434
435
436
437
438
439


440
441
442
443
444
445
446
447







-
-
+







	}
	_lastReturnedStream = nil;

	offset64 = entry.of_localFileHeaderOffset;
	if (offset64 < 0 || (OFStreamOffset)offset64 != offset64)
		@throw [OFOutOfRangeException exception];

	seekOrThrowInvalidFormat((OFSeekableStream *)_stream,
	    (OFStreamOffset)offset64, OFSeekSet);
	seekOrThrowInvalidFormat(_stream, (OFStreamOffset)offset64, OFSeekSet);
	localFileHeader = [[[OFZIPArchiveLocalFileHeader alloc]
	    initWithStream: _stream] autorelease];

	if (![localFileHeader matchesEntry: entry])
		@throw [OFInvalidFormatException exception];

	if ((localFileHeader->_minVersionNeeded & 0xFF) > 45) {
461
462
463
464
465
466
467
468
469
470
471
472


473
474
475
476
477
478
479
461
462
463
464
465
466
467

468
469
470
471
472
473
474
475
476
477
478
479
480







-




+
+







			 entry: entry] autorelease];

	return _lastReturnedStream;
}

- (OFStream *)streamForWritingEntry: (OFZIPArchiveEntry *)entry_
{
	/* TODO: Avoid data descriptor when _stream is an OFSeekableStream */
	int64_t offsetAdd = 0;
	void *pool;
	OFMutableZIPArchiveEntry *entry;
	OFString *fileName;
	bool seekable;
	OFStreamOffset CRC32Offset = 0, size64Offset = 0;
	OFData *extraField;
	uint16_t fileNameLength, extraFieldLength;

	if (_stream == nil)
		@throw [OFNotOpenException exceptionWithObject: self];

	if (_mode != modeWrite && _mode != modeAppend)
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
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







+
+





-
+








-
+
+
+













-
+
+
+
















-
+
+
+







	fileNameLength = fileName.UTF8StringLength;
	extraField = entry.extraField;
	extraFieldLength = extraField.count;

	if (UINT16_MAX - extraFieldLength < 20)
		@throw [OFOutOfRangeException exception];

	seekable = [_stream isKindOfClass: [OFSeekableStream class]];

	entry.versionMadeBy = (entry.versionMadeBy & 0xFF00) | 45;
	entry.minVersionNeeded = (entry.minVersionNeeded & 0xFF00) | 45;
	entry.compressedSize = 0;
	entry.uncompressedSize = 0;
	entry.CRC32 = 0;
	entry.generalPurposeBitFlag |= (1u << 3) | (1u << 11);
	entry.generalPurposeBitFlag |= (seekable ? 0 : (1u << 3)) | (1u << 11);
	entry.of_localFileHeaderOffset = _offset;

	[_stream writeLittleEndianInt32: 0x04034B50];
	[_stream writeLittleEndianInt16: entry.minVersionNeeded];
	[_stream writeLittleEndianInt16: entry.generalPurposeBitFlag];
	[_stream writeLittleEndianInt16: entry.compressionMethod];
	[_stream writeLittleEndianInt16: entry.of_lastModifiedFileTime];
	[_stream writeLittleEndianInt16: entry.of_lastModifiedFileDate];
	/* We use the data descriptor */
	/* Written later or data descriptor used instead */
	if (seekable)
		CRC32Offset = [_stream seekToOffset: 0 whence: OFSeekCurrent];
	[_stream writeLittleEndianInt32: 0];
	/* We use ZIP64 */
	[_stream writeLittleEndianInt32: 0xFFFFFFFF];
	[_stream writeLittleEndianInt32: 0xFFFFFFFF];
	[_stream writeLittleEndianInt16: fileNameLength];
	[_stream writeLittleEndianInt16: extraFieldLength + 20];
	offsetAdd += 4 + (5 * 2) + (3 * 4) + (2 * 2);

	[_stream writeString: fileName];
	offsetAdd += fileNameLength;

	[_stream writeLittleEndianInt16: OFZIPArchiveEntryExtraFieldTagZIP64];
	[_stream writeLittleEndianInt16: 16];
	/* We use the data descriptor */
	/* Written later or data descriptor used instead */
	if (seekable)
		size64Offset = [_stream seekToOffset: 0 whence: OFSeekCurrent];
	[_stream writeLittleEndianInt64: 0];
	[_stream writeLittleEndianInt64: 0];
	offsetAdd += (2 * 2) + (2 * 8);

	if (extraField != nil)
		[_stream writeData: extraField];
	offsetAdd += extraFieldLength;

	if (INT64_MAX - _offset < offsetAdd)
		@throw [OFOutOfRangeException exception];

	_offset += offsetAdd;

	_lastReturnedStream = [[OFZIPArchiveFileWriteStream alloc]
	    of_initWithArchive: self
			stream: _stream
			 entry: entry];
			 entry: entry
		   CRC32Offset: CRC32Offset
		  size64Offset: size64Offset];

	objc_autoreleasePoolPop(pool);

	return [_lastReturnedStream autorelease];
}

- (void)of_writeCentralDirectory
861
862
863
864
865
866
867


868
869
870
871
872
873
874


875
876
877
878
879
880
881
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894







+
+







+
+







}
@end

@implementation OFZIPArchiveFileWriteStream
- (instancetype)of_initWithArchive: (OFZIPArchive *)archive
			    stream: (OFStream *)stream
			     entry: (OFMutableZIPArchiveEntry *)entry
		       CRC32Offset: (OFStreamOffset)CRC32Offset
		      size64Offset: (OFStreamOffset)size64Offset
{
	self = [super init];

	_archive = [archive retain];
	_stream = [stream retain];
	_entry = [entry retain];
	_CRC32 = ~0;
	_CRC32Offset = CRC32Offset;
	_size64Offset = size64Offset;

	return self;
}

- (void)dealloc
{
	if (_stream != nil)
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
948
949
950
951
952
953
954
955
956
957
932
933
934
935
936
937
938
939
940
941
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
971
972
973
974
975

976
977
978
979
980
981
982
983
984
985
986
987
988







+
+






+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
+









+
-
+












	_CRC32 = OFCRC32(_CRC32, buffer, length);

	return length;
}

- (void)close
{
	bool seekable;

	if (_stream == nil)
		@throw [OFNotOpenException exceptionWithObject: self];

	if (_bytesWritten > UINT64_MAX)
		@throw [OFOutOfRangeException exception];

	seekable = [_stream isKindOfClass: [OFSeekableStream class]];

	if (seekable) {
		OFStreamOffset offset = [_stream seekToOffset: 0
						       whence: OFSeekCurrent];

		[_stream seekToOffset: _CRC32Offset whence: OFSeekSet];
		[_stream writeLittleEndianInt32: ~_CRC32];
		[_stream seekToOffset: _size64Offset whence: OFSeekSet];
		[_stream writeLittleEndianInt64: (uint64_t)_bytesWritten];
		[_stream writeLittleEndianInt64: (uint64_t)_bytesWritten];

		[_stream seekToOffset: offset whence: OFSeekSet];
	} else {
	[_stream writeLittleEndianInt32: 0x08074B50];
	[_stream writeLittleEndianInt32: _CRC32];
	[_stream writeLittleEndianInt64: (uint64_t)_bytesWritten];
	[_stream writeLittleEndianInt64: (uint64_t)_bytesWritten];
		[_stream writeLittleEndianInt32: 0x08074B50];
		[_stream writeLittleEndianInt32: ~_CRC32];
		[_stream writeLittleEndianInt64: (uint64_t)_bytesWritten];
		[_stream writeLittleEndianInt64: (uint64_t)_bytesWritten];
	}

	[_stream release];
	_stream = nil;

	_entry.CRC32 = ~_CRC32;
	_entry.compressedSize = _bytesWritten;
	_entry.uncompressedSize = _bytesWritten;
	[_entry makeImmutable];

	if (!seekable)
	_bytesWritten += (2 * 4 + 2 * 8);
		_bytesWritten += (2 * 4 + 2 * 8);

	[_archive->_entries addObject: _entry];
	[_archive->_pathToEntryMap setObject: _entry forKey: _entry.fileName];

	if (ULLONG_MAX - _archive->_offset < _bytesWritten)
		@throw [OFOutOfRangeException exception];

	_archive->_offset += _bytesWritten;

	[super close];
}
@end

Modified src/OFZIPArchiveEntry+Private.h from [1ac3d985fc] to [086f6aeb71].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFZIPArchiveEntry.h from [463b0f575c] to [d1f5aa4803].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/OFZIPArchiveEntry.m from [87dd5a9fa3] to [b03fc597d2].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/ObjFW.h from [940f93b1b8] to [1712ca6be5].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
41
42
43
44
45
46
47
48
49
50



51
52
53
54
55
56
57
41
42
43
44
45
46
47



48
49
50
51
52
53
54
55
56
57







-
-
-
+
+
+







#import "OFNull.h"

#import "OFMethodSignature.h"
#import "OFInvocation.h"

#import "OFNumber.h"
#import "OFDate.h"
#import "OFUUID.h"
#import "OFURI.h"
#import "OFURIHandler.h"
#import "OFIRI.h"
#import "OFIRIHandler.h"
#import "OFUUID.h"
#import "OFColor.h"

#import "OFNotification.h"
#import "OFNotificationCenter.h"

#import "OFStream.h"
#import "OFSeekableStream.h"
134
135
136
137
138
139
140


141
142
143
144
145

146
147
148
149
150
151
152
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155







+
+





+







#import "OFApplication.h"
#import "OFSystemInfo.h"
#import "OFLocale.h"
#import "OFOptionsParser.h"
#import "OFTimer.h"
#import "OFRunLoop.h"

#import "OFMatrix4x4.h"

#ifdef OF_WINDOWS
# import "OFWindowsRegistryKey.h"
#endif

#import "OFAllocFailedException.h"
#import "OFAlreadyOpenException.h"
#import "OFException.h"
#import "OFChangeCurrentDirectoryFailedException.h"
#import "OFChecksumMismatchException.h"
#import "OFCopyItemFailedException.h"
#import "OFCreateDirectoryFailedException.h"
#import "OFCreateSymbolicLinkFailedException.h"
#import "OFEnumerationMutationException.h"
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
192
193
194
195
196
197
198

199
200
201
202
203
204
205







-







#import "OFUnknownXMLEntityException.h"
#import "OFUnlockFailedException.h"
#import "OFUnsupportedProtocolException.h"
#import "OFUnsupportedVersionException.h"
#import "OFWriteFailedException.h"
#ifdef OF_HAVE_SOCKETS
# import "OFAcceptSocketFailedException.h"
# import "OFAlreadyConnectedException.h"
# import "OFBindIPSocketFailedException.h"
# import "OFBindSocketFailedException.h"
# import "OFConnectIPSocketFailedException.h"
# import "OFConnectSocketFailedException.h"
# import "OFDNSQueryFailedException.h"
# import "OFHTTPRequestFailedException.h"
# import "OFListenOnSocketFailedException.h"

Modified src/bridge/NSArray+OFObject.h from [4b59b82d97] to [b99db44847].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/bridge/NSArray+OFObject.m from [a7c2336812] to [a24941e356].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/bridge/NSBridging.h from [1aa6518645] to [31e3a65c6b].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/bridge/NSDictionary+OFObject.h from [1dcde481c6] to [27c43677ad].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/bridge/NSDictionary+OFObject.m from [3bee09377c] to [ab7329e7f7].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/bridge/NSEnumerator+OFObject.h from [5e37d187b7] to [081e63b239].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/bridge/NSEnumerator+OFObject.m from [dd0762c949] to [f73545784c].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/bridge/NSNumber+OFObject.h from [bd31c0c3cd] to [a841fd4c0a].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/bridge/NSNumber+OFObject.m from [18f7ec56ae] to [6a22223677].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/bridge/NSOFArray.h from [cd8e3e0488] to [9e1424de72].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/bridge/NSOFArray.m from [41ea305080] to [5a8d48ae18].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/bridge/NSOFDictionary.h from [b628e7e6a3] to [48aa956bd2].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/bridge/NSOFDictionary.m from [e47773ee01] to [44b1da56e1].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/bridge/NSOFEnumerator.h from [fcb10c08ed] to [175dea754e].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/bridge/NSOFEnumerator.m from [ebbed84f33] to [90df0feb19].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/bridge/NSOFSet.h from [33948f6157] to [0b7d9458bc].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/bridge/NSOFSet.m from [e7387e2762] to [253ad07b78].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/bridge/NSSet+OFObject.h from [68cb6c5ccf] to [2f61036b15].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/bridge/NSSet+OFObject.m from [5daeb1bac4] to [0816befdd9].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/bridge/NSString+OFObject.h from [a30f21642d] to [f3b30cafeb].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/bridge/NSString+OFObject.m from [f6fbd9f898] to [4d66e69ce9].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/bridge/OFArray+NSObject.h from [f258ecab9a] to [1b31d59546].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/bridge/OFArray+NSObject.m from [ee4c5a25af] to [cb40f335df].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/bridge/OFBridging.h from [abe87031bc] to [242d731121].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/bridge/OFDictionary+NSObject.h from [27bfd0d589] to [98e8ad6da9].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/bridge/OFDictionary+NSObject.m from [6df9e22408] to [fa459b8956].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/bridge/OFEnumerator+NSObject.h from [cb0752d99c] to [f2f0517b85].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/bridge/OFEnumerator+NSObject.m from [a3ee1dfe29] to [5e20a33ce1].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/bridge/OFException+Swift.h from [da5307c0ad] to [2069a47d9a].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/bridge/OFException+Swift.m from [69103747b4] to [101e2e12cb].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/bridge/OFNSArray.h from [1c05dea53b] to [327efc0ae8].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/bridge/OFNSArray.m from [511fcf77df] to [41cfacf3f7].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/bridge/OFNSDictionary.h from [3699212d07] to [ce15a91bda].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/bridge/OFNSDictionary.m from [3228b094f1] to [8283af6253].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/bridge/OFNSEnumerator.h from [f60938ebf6] to [f82d33be38].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/bridge/OFNSEnumerator.m from [9f5d7028e9] to [10fcaff82a].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/bridge/OFNSSet.h from [7b3370ed57] to [109a681829].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/bridge/OFNSSet.m from [151a52ad4b] to [82092e5fca].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/bridge/OFNumber+NSObject.h from [955839af4e] to [9baf487d8e].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/bridge/OFNumber+NSObject.m from [f73968ae16] to [4d86be5fca].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/bridge/OFSet+NSObject.h from [9214bbd006] to [81ad9e84d0].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/bridge/OFSet+NSObject.m from [e5bc663707] to [4811241944].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/bridge/OFString+NSObject.h from [375ab3a6b5] to [b60d2fd3f8].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/bridge/OFString+NSObject.m from [bf4d082579] to [5476579ea3].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/bridge/ObjFWBridge.h from [1fbb08ae27] to [c9a5baf610].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/encodings/codepage-437.m from [1cc88f79fe] to [60afd41b76].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/encodings/codepage-850.m from [d9cdb5c58f] to [fe4b50f9b6].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/encodings/codepage-858.m from [402e5b0a14] to [1fe953dd7d].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/encodings/common.h from [a9b82f31be] to [705ca544ce].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/encodings/iso-8859-15.m from [8197488f98] to [a153ecf93e].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/encodings/iso-8859-2.m from [b10a788d3d] to [5b28b0778a].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/encodings/iso-8859-3.m from [57543aa317] to [042961876e].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/encodings/koi8-r.m from [e29e1b888f] to [6462336220].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/encodings/koi8-u.m from [10ad0de57d] to [d7fa32fa60].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/encodings/mac-roman.m from [5811cbe352] to [9117bc64a4].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/encodings/windows-1251.m from [b8c4870fa7] to [203730a1e1].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/encodings/windows-1252.m from [f9fc8b9676] to [845de5b368].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/Makefile from [869aa1631b] to [7a62aa941c].

1
2
3
4
5
6
7

8
9
10
11
12
13
14
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15







+







include ../../extra.mk

STATIC_PIC_LIB_NOINST = ${EXCEPTIONS_LIB_A}
STATIC_LIB_NOINST = ${EXCEPTIONS_A}
STATIC_AMIGA_LIB_NOINST = ${EXCEPTIONS_AMIGALIB_A}

SRCS = OFAllocFailedException.m				\
       OFAlreadyOpenException.m				\
       OFChecksumMismatchException.m			\
       OFCopyItemFailedException.m			\
       OFCreateDirectoryFailedException.m		\
       OFCreateSymbolicLinkFailedException.m		\
       OFEnumerationMutationException.m			\
       OFException.m					\
       OFGetItemAttributesFailedException.m		\
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
52
53
54
55
56
57
58

59
60
61
62
63
64
65







-







       ${USE_SRCS_SOCKETS}				\
       ${USE_SRCS_THREADS}				\
       ${USE_SRCS_WINDOWS}
SRCS_FILES = OFChangeCurrentDirectoryFailedException.m	\
	     OFGetCurrentDirectoryFailedException.m
SRCS_PLUGINS = OFLoadPluginFailedException.m
SRCS_SOCKETS = OFAcceptSocketFailedException.m		\
	       OFAlreadyConnectedException.m		\
	       OFBindIPSocketFailedException.m		\
	       OFBindSocketFailedException.m		\
	       OFConnectIPSocketFailedException.m	\
	       OFConnectSocketFailedException.m		\
	       OFDNSQueryFailedException.m		\
	       OFHTTPRequestFailedException.m		\
	       OFListenOnSocketFailedException.m	\

Modified src/exceptions/OFAcceptSocketFailedException.h from [e062558833] to [92391d6729].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFAcceptSocketFailedException.m from [701680e6d7] to [acff5d31b7].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFActivateSandboxFailedException.h from [97726da76a] to [9ed53939e1].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFActivateSandboxFailedException.m from [5dc1486ad8] to [c61d60ad53].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFAllocFailedException.h from [01cde7dcb3] to [8172da0757].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFAllocFailedException.m from [845ed2917e] to [35f3b6d4b6].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Renamed and modified src/exceptions/OFAlreadyConnectedException.h [ac208c2ef2] to src/exceptions/OFAlreadyOpenException.h [3da7a0a138].

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
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

-
+















-
-
-
-



-
-
+
+

-
-
+
+

-
+

-
-
+
+

+
+
+
+
+


-
-
-
-
-
-
+

-
-
+
+

-
+

+
+

-
+

-
-
+
+

+
+
-
+



/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 */

#import "OFException.h"

#ifndef OF_HAVE_SOCKETS
# error No sockets available!
#endif

OF_ASSUME_NONNULL_BEGIN

/**
 * @class OFAlreadyConnectedException \
 *	  OFAlreadyConnectedException.h ObjFW/OFAlreadyConnectedException.h
 * @class OFAlreadyOpenException \
 *	  OFAlreadyOpenException.h ObjFW/OFAlreadyOpenException.h
 *
 * @brief An exception indicating an attempt to connect or bind an already
 *        connected or bound socket.
 * @brief An exception indicating that an object is already open and thus
 *	  cannot be opened again.
 */
@interface OFAlreadyConnectedException: OFException
@interface OFAlreadyOpenException: OFException
{
	id _socket;
	OF_RESERVE_IVARS(OFAlreadyConnectedException, 4)
	id _object;
	OF_RESERVE_IVARS(OFAlreadyOpenException, 4)
}

/**
 * @brief The object which is already open.
 */
@property (readonly, nonatomic) id object;

/**
 * @brief The socket which is already connected.
 */
@property OF_NULLABLE_PROPERTY (readonly, nonatomic) id socket;

/**
 * @brief Creates a new, autoreleased already connected exception.
 * @brief Creates a new, autoreleased already open exception.
 *
 * @param socket The socket which is already connected
 * @return A new, autoreleased already connected exception
 * @param object The object which is already open
 * @return A new, autoreleased already open exception
 */
+ (instancetype)exceptionWithSocket: (nullable id)socket;
+ (instancetype)exceptionWithObject: (id)object;

+ (instancetype)exception OF_UNAVAILABLE;

/**
 * @brief Initializes an already allocated already connected exception.
 * @brief Initializes an already allocated already open exception.
 *
 * @param socket The socket which is already connected
 * @return An initialized already connected exception
 * @param object The object which is already open
 * @return An initialized already open exception
 */
- (instancetype)initWithObject: (id)object OF_DESIGNATED_INITIALIZER;

- (instancetype)initWithSocket: (nullable id)socket OF_DESIGNATED_INITIALIZER;
- (instancetype)init OF_UNAVAILABLE;
@end

OF_ASSUME_NONNULL_END

Renamed and modified src/exceptions/OFAlreadyConnectedException.m [9abd285501] to src/exceptions/OFAlreadyOpenException.m [4a1dff0be6].

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
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

-
+















-
+


-
-
+
+

-
+

-
+


-
+

-
+


-
+



-
+



+
+
+
+
+



-
+






-
-
-
-
-
+
+
+
+
-
-


/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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 "OFAlreadyConnectedException.h"
#import "OFAlreadyOpenException.h"
#import "OFString.h"

@implementation OFAlreadyConnectedException
@synthesize socket = _socket;
@implementation OFAlreadyOpenException
@synthesize object = _object;

+ (instancetype)exceptionWithSocket: (id)sock
+ (instancetype)exceptionWithObject: (id)object
{
	return [[[self alloc] initWithSocket: sock] autorelease];
	return [[[self alloc] initWithObject: object] autorelease];
}

- (instancetype)init
+ (instancetype)exception
{
	return [self initWithSocket: nil];
	OF_UNRECOGNIZED_SELECTOR
}

- (instancetype)initWithSocket: (id)sock
- (instancetype)initWithObject: (id)object
{
	self = [super init];

	_socket = [sock retain];
	_object = [object retain];

	return self;
}

- (instancetype)init
{
	OF_INVALID_INIT_METHOD
}

- (void)dealloc
{
	[_socket release];
	[_object release];

	[super dealloc];
}

- (OFString *)description
{
	if (_socket)
		return [OFString stringWithFormat:
		    @"The socket of type %@ is already connected or bound and "
		    @"thus can't be connected or bound again!",
		    [_socket class]];
	return [OFString stringWithFormat:
	    @"An object of type %@ is already open and thus cannot be opened "
	    @"again!",
	    [_object class]];
	else
		return @"A connection has already been established!";
}
@end

Modified src/exceptions/OFBindDDPSocketFailedException.h from [5a5edecbc3] to [fb6f22c1ee].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFBindDDPSocketFailedException.m from [10cafd22cd] to [bcb93d003b].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
70
71
72
73
74
75
76
77
78


79
80
81
82
70
71
72
73
74
75
76


77
78
79
80
81
82







-
-
+
+




	return self;
}

- (OFString *)description
{
	return [OFString stringWithFormat:
	    @"Binding to port %" @PRIx8 @" of node %" @PRIx8 @" on network "
	    @"%" PRIx16 @" with protocol type %" @PRIx8 @" failed in socket of "
	    @"type %@: %@",
	    @"%" PRIx16 @" with protocol type 0x%" @PRIX8 @" failed in socket "
	    @"of type %@: %@",
	    _port, _node, _network, _protocolType, [_socket class],
	    OFStrError(_errNo)];
}
@end

Modified src/exceptions/OFBindIPSocketFailedException.h from [5e1e83771b] to [41bf131d88].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFBindIPSocketFailedException.m from [f9eddfdc09] to [ce7a779b49].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFBindIPXSocketFailedException.h from [348112e28c] to [b2d0b0e45b].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFBindIPXSocketFailedException.m from [ae7cdae06b] to [9e31f1ffcc].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
76
77
78
79
80
81
82
83
84
85
86
87
88
89





90
91
76
77
78
79
80
81
82


83




84
85
86
87
88
89
90







-
-

-
-
-
-
+
+
+
+
+


- (void)getNode: (unsigned char [IPX_NODE_LEN])node
{
	memcpy(node, _node, sizeof(_node));
}

- (OFString *)description
{
	OFData *node = [OFData dataWithItems: _node count: sizeof(_node)];

	return [OFString stringWithFormat:
	    @"Binding to network %" @PRIx16 " on node %@ with port %" @PRIx16
	    @" failed for packet type %" @PRIx8 " in socket of type %@: %@",
	    _network, node, _port, _packetType, [_socket class],
	    OFStrError(_errNo)];
	    @"Binding to network %" @PRIx16 " on node "
	    @"%02X:%02X:%02X:%02X:%02X:%02X with port %" @PRIx16 @" failed for "
	    @"packet type %" @PRIx8 " in socket of type %@: %@",
	    _network, _node[0], _node[1], _node[2], _node[3], _node[4],
	    _node[5], _port, _packetType, [_socket class], OFStrError(_errNo)];
}
@end

Modified src/exceptions/OFBindSocketFailedException.h from [36c8977d2e] to [3dc58feea7].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFBindSocketFailedException.m from [6491b695d4] to [ac6a3f5432].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFBindUNIXSocketFailedException.h from [8dc7fd786c] to [ada45067d6].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFBindUNIXSocketFailedException.m from [e85a3193a3] to [a3e0e840cb].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFBroadcastConditionFailedException.h from [b5c55a5caf] to [c43763dcf1].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFBroadcastConditionFailedException.m from [aeec33aa4e] to [1e76124b1e].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFChangeCurrentDirectoryFailedException.h from [c93252d4da] to [a8996ef98d].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFChangeCurrentDirectoryFailedException.m from [7267a7e220] to [abd3da2c56].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFChecksumMismatchException.h from [5d6d269610] to [0877083770].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFChecksumMismatchException.m from [194677cc27] to [ceb4061b9d].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFConditionStillWaitingException.h from [6424437193] to [f9cd4f0df6].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFConditionStillWaitingException.m from [28d38d170f] to [6aeb872920].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFConnectIPSocketFailedException.h from [f85ab38f4c] to [d175a030f3].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFConnectIPSocketFailedException.m from [b9f4e412ce] to [b1b035056b].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFConnectSPXSocketFailedException.h from [acdfa9213b] to [fc3b94aa78].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFConnectSPXSocketFailedException.m from [35220eec8e] to [afd4b15484].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
70
71
72
73
74
75
76
77
78
79
80
81
82





83
84
70
71
72
73
74
75
76


77



78
79
80
81
82
83
84







-
-

-
-
-
+
+
+
+
+


- (void)getNode: (unsigned char [IPX_NODE_LEN])node
{
	memcpy(node, _node, sizeof(_node));
}

- (OFString *)description
{
	OFData *node = [OFData dataWithItems: _node count: sizeof(_node)];

	return [OFString stringWithFormat:
	    @"A connection to %@ port %" @PRIu16 @" on network %" @PRIX32
	    " could not be established in socket of type %@: %@",
	    node, _port, _network, [_socket class], OFStrError(_errNo)];
	    @"A connection to %02X:%02X:%02X:%02X:%02X:%02X port %" @PRIu16
	    @" on network %" @PRIX32 " could not be established in socket of "
	    @"type %@: %@",
	    _node[0], _node[1], _node[2], _node[3], _node[4], _node[5], _port,
	    _network, [_socket class], OFStrError(_errNo)];
}
@end

Modified src/exceptions/OFConnectSocketFailedException.h from [8f2d911f53] to [0223bb3646].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFConnectSocketFailedException.m from [cadbcb9d65] to [4194ad960b].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFConnectUNIXSocketFailedException.h from [9ffd06e788] to [9b501f5aa0].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFConnectUNIXSocketFailedException.m from [f1376977d4] to [9f842d2a4a].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFCopyItemFailedException.h from [123bfde77a] to [0f23b6466c].

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
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

-
+

















-
+









-
+





-
+

-
+


-
+

-
+









-
-
+
+



-
-
+
+







-
-
+
+



-
-
+
+






/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 */

#import "OFException.h"

OF_ASSUME_NONNULL_BEGIN

@class OFURI;
@class OFIRI;

/**
 * @class OFCopyItemFailedException \
 *	  OFCopyItemFailedException.h ObjFW/OFCopyItemFailedException.h
 *
 * @brief An exception indicating that copying a item failed.
 */
@interface OFCopyItemFailedException: OFException
{
	OFURI *_sourceURI, *_destinationURI;
	OFIRI *_sourceIRI, *_destinationIRI;
	int _errNo;
	OF_RESERVE_IVARS(OFCopyItemFailedException, 4)
}

/**
 * @brief The URI of the source item.
 * @brief The IRI of the source item.
 */
@property (readonly, nonatomic) OFURI *sourceURI;
@property (readonly, nonatomic) OFIRI *sourceIRI;

/**
 * @brief The destination URI.
 * @brief The destination IRI.
 */
@property (readonly, nonatomic) OFURI *destinationURI;
@property (readonly, nonatomic) OFIRI *destinationIRI;

/**
 * @brief The errno of the error that occurred.
 */
@property (readonly, nonatomic) int errNo;

/**
 * @brief Creates a new, autoreleased copy item failed exception.
 *
 * @param sourceURI The URI of the source item
 * @param destinationURI The destination URI
 * @param sourceIRI The IRI of the source item
 * @param destinationIRI The destination IRI
 * @param errNo The errno of the error that occurred
 * @return A new, autoreleased copy item failed exception
 */
+ (instancetype)exceptionWithSourceURI: (OFURI *)sourceURI
			destinationURI: (OFURI *)destinationURI
+ (instancetype)exceptionWithSourceIRI: (OFIRI *)sourceIRI
			destinationIRI: (OFIRI *)destinationIRI
				 errNo: (int)errNo;

+ (instancetype)exception OF_UNAVAILABLE;

/**
 * @brief Initializes an already allocated copy item failed exception.
 *
 * @param sourceURI The URI of the source item
 * @param destinationURI The destination URI
 * @param sourceIRI The IRI of the source item
 * @param destinationIRI The destination IRI
 * @param errNo The errno of the error that occurred
 * @return An initialized copy item failed exception
 */
- (instancetype)initWithSourceURI: (OFURI *)sourceURI
		   destinationURI: (OFURI *)destinationURI
- (instancetype)initWithSourceIRI: (OFIRI *)sourceIRI
		   destinationIRI: (OFIRI *)destinationIRI
			    errNo: (int)errNo OF_DESIGNATED_INITIALIZER;

- (instancetype)init OF_UNAVAILABLE;
@end

OF_ASSUME_NONNULL_END

Modified src/exceptions/OFCopyItemFailedException.m from [86e24afee9] to [490227f2c9].

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
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

-
+
















-
-
+
+


-
+







-
-
+
+


-
-
+
+








-
-
+
+





-
-
+
+











-
-
+
+







-
+


/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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 "OFCopyItemFailedException.h"
#import "OFString.h"
#import "OFURI.h"
#import "OFIRI.h"
#import "OFString.h"

@implementation OFCopyItemFailedException
@synthesize sourceURI = _sourceURI, destinationURI = _destinationURI;
@synthesize sourceIRI = _sourceIRI, destinationIRI = _destinationIRI;
@synthesize errNo = _errNo;

+ (instancetype)exception
{
	OF_UNRECOGNIZED_SELECTOR
}

+ (instancetype)exceptionWithSourceURI: (OFURI *)sourceURI
			destinationURI: (OFURI *)destinationURI
+ (instancetype)exceptionWithSourceIRI: (OFIRI *)sourceIRI
			destinationIRI: (OFIRI *)destinationIRI
				 errNo: (int)errNo
{
	return [[[self alloc] initWithSourceURI: sourceURI
				 destinationURI: destinationURI
	return [[[self alloc] initWithSourceIRI: sourceIRI
				 destinationIRI: destinationIRI
					  errNo: errNo] autorelease];
}

- (instancetype)init
{
	OF_INVALID_INIT_METHOD
}

- (instancetype)initWithSourceURI: (OFURI *)sourceURI
		   destinationURI: (OFURI *)destinationURI
- (instancetype)initWithSourceIRI: (OFIRI *)sourceIRI
		   destinationIRI: (OFIRI *)destinationIRI
			    errNo: (int)errNo
{
	self = [super init];

	@try {
		_sourceURI = [sourceURI copy];
		_destinationURI = [destinationURI copy];
		_sourceIRI = [sourceIRI copy];
		_destinationIRI = [destinationIRI copy];
		_errNo = errNo;
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (void)dealloc
{
	[_sourceURI release];
	[_destinationURI release];
	[_sourceIRI release];
	[_destinationIRI release];

	[super dealloc];
}

- (OFString *)description
{
	return [OFString stringWithFormat: @"Failed to copy item %@ to %@: %@",
	    _sourceURI, _destinationURI, OFStrError(_errNo)];
	    _sourceIRI, _destinationIRI, OFStrError(_errNo)];
}
@end

Modified src/exceptions/OFCreateDirectoryFailedException.h from [e16c672401] to [2138125948].

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
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

-
+

















-
+










-
+





-
+

-
+









-
+



-
+






-
+



-
+






/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 */

#import "OFException.h"

OF_ASSUME_NONNULL_BEGIN

@class OFURI;
@class OFIRI;

/**
 * @class OFCreateDirectoryFailedException \
 *	  OFCreateDirectoryFailedException.h \
 *	  ObjFW/OFCreateDirectoryFailedException.h
 *
 * @brief An exception indicating a directory couldn't be created.
 */
@interface OFCreateDirectoryFailedException: OFException
{
	OFURI *_URI;
	OFIRI *_IRI;
	int _errNo;
	OF_RESERVE_IVARS(OFCreateDirectoryFailedException, 4)
}

/**
 * @brief The URI of the directory which couldn't be created.
 * @brief The IRI of the directory which couldn't be created.
 */
@property (readonly, nonatomic) OFURI *URI;
@property (readonly, nonatomic) OFIRI *IRI;

/**
 * @brief The errno of the error that occurred.
 */
@property (readonly, nonatomic) int errNo;

/**
 * @brief Creates a new, autoreleased create directory failed exception.
 *
 * @param URI The URI of the directory which could not be created
 * @param IRI The IRI of the directory which could not be created
 * @param errNo The errno of the error that occurred
 * @return A new, autoreleased create directory failed exception
 */
+ (instancetype)exceptionWithURI: (OFURI *)URI errNo: (int)errNo;
+ (instancetype)exceptionWithIRI: (OFIRI *)IRI errNo: (int)errNo;

+ (instancetype)exception OF_UNAVAILABLE;

/**
 * @brief Initializes an already allocated create directory failed exception.
 *
 * @param URI The URI of the directory which could not be created
 * @param IRI The IRI of the directory which could not be created
 * @param errNo The errno of the error that occurred
 * @return An initialized create directory failed exception
 */
- (instancetype)initWithURI: (OFURI *)URI
- (instancetype)initWithIRI: (OFIRI *)IRI
		      errNo: (int)errNo OF_DESIGNATED_INITIALIZER;

- (instancetype)init OF_UNAVAILABLE;
@end

OF_ASSUME_NONNULL_END

Modified src/exceptions/OFCreateDirectoryFailedException.m from [cd0b53b912] to [ad692e05f8].

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
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

-
+
















-
-
+
+


-
+






-
+

-
+







-
+




-
+











-
+







-
+


/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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 "OFCreateDirectoryFailedException.h"
#import "OFString.h"
#import "OFURI.h"
#import "OFIRI.h"
#import "OFString.h"

@implementation OFCreateDirectoryFailedException
@synthesize URI = _URI, errNo = _errNo;
@synthesize IRI = _IRI, errNo = _errNo;

+ (instancetype)exception
{
	OF_UNRECOGNIZED_SELECTOR
}

+ (instancetype)exceptionWithURI: (OFURI *)URI errNo: (int)errNo
+ (instancetype)exceptionWithIRI: (OFIRI *)IRI errNo: (int)errNo
{
	return [[[self alloc] initWithURI: URI errNo: errNo] autorelease];
	return [[[self alloc] initWithIRI: IRI errNo: errNo] autorelease];
}

- (instancetype)init
{
	OF_INVALID_INIT_METHOD
}

- (instancetype)initWithURI: (OFURI *)URI errNo: (int)errNo
- (instancetype)initWithIRI: (OFIRI *)IRI errNo: (int)errNo
{
	self = [super init];

	@try {
		_URI = [URI copy];
		_IRI = [IRI copy];
		_errNo = errNo;
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (void)dealloc
{
	[_URI release];
	[_IRI release];

	[super dealloc];
}

- (OFString *)description
{
	return [OFString stringWithFormat:
	    @"Failed to create directory %@: %@", _URI, OFStrError(_errNo)];
	    @"Failed to create directory %@: %@", _IRI, OFStrError(_errNo)];
}
@end

Modified src/exceptions/OFCreateSymbolicLinkFailedException.h from [79c2f6b7ee] to [6f3ee8cfc5].

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
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

-
+

















-
+










-
+






-
+

-
+














-
+




-
+









-
+




-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 */

#import "OFException.h"

OF_ASSUME_NONNULL_BEGIN

@class OFURI;
@class OFIRI;

/**
 * @class OFCreateSymbolicLinkFailedException \
 *	  OFCreateSymbolicLinkFailedException.h \
 *	  ObjFW/OFCreateSymbolicLinkFailedException.h
 *
 * @brief An exception indicating that creating a symbolic link failed.
 */
@interface OFCreateSymbolicLinkFailedException: OFException
{
	OFURI *_URI;
	OFIRI *_IRI;
	OFString *_target;
	int _errNo;
	OF_RESERVE_IVARS(OFCreateSymbolicLinkFailedException, 4)
}

/**
 * @brief The URI at which the symlink should have been created.
 * @brief The IRI at which the symlink should have been created.
 */
@property (readonly, nonatomic) OFURI *URI;
@property (readonly, nonatomic) OFIRI *IRI;

/**
 * @brief The target for the symlink.
 */
@property (readonly, nonatomic) OFString *target;

/**
 * @brief The errno of the error that occurred.
 */
@property (readonly, nonatomic) int errNo;

/**
 * @brief Creates a new, autoreleased create symbolic link failed exception.
 *
 * @param URI The URI where the symlink should have been created
 * @param IRI The IRI where the symlink should have been created
 * @param target The target for the symbolic link
 * @param errNo The errno of the error that occurred
 * @return A new, autoreleased create symbolic link failed exception
 */
+ (instancetype)exceptionWithURI: (OFURI *)URI
+ (instancetype)exceptionWithIRI: (OFIRI *)IRI
			  target: (OFString *)target
			   errNo: (int)errNo;

+ (instancetype)exception OF_UNAVAILABLE;

/**
 * @brief Initializes an already allocated create symbolic link failed
 *	  exception.
 *
 * @param URI The URI where the symlink should have been created
 * @param IRI The IRI where the symlink should have been created
 * @param target The target for the symbolic link
 * @param errNo The errno of the error that occurred
 * @return An initialized create symbolic link failed exception
 */
- (instancetype)initWithURI: (OFURI *)URI
- (instancetype)initWithIRI: (OFIRI *)IRI
		     target: (OFString *)target
		      errNo: (int)errNo OF_DESIGNATED_INITIALIZER;

- (instancetype)init OF_UNAVAILABLE;
@end

OF_ASSUME_NONNULL_END

Modified src/exceptions/OFCreateSymbolicLinkFailedException.m from [c5e085b246] to [6e3c50256e].

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
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

-
+
















-
-
+
+


-
+






-
+



-
+









-
+






-
+












-
+









-
+


/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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 "OFCreateSymbolicLinkFailedException.h"
#import "OFString.h"
#import "OFURI.h"
#import "OFIRI.h"
#import "OFString.h"

@implementation OFCreateSymbolicLinkFailedException
@synthesize URI = _URI, target = _target, errNo = _errNo;
@synthesize IRI = _IRI, target = _target, errNo = _errNo;

+ (instancetype)exception
{
	OF_UNRECOGNIZED_SELECTOR
}

+ (instancetype)exceptionWithURI: (OFURI *)URI
+ (instancetype)exceptionWithIRI: (OFIRI *)IRI
			  target: (OFString *)target
			   errNo: (int)errNo
{
	return [[[self alloc] initWithURI: URI
	return [[[self alloc] initWithIRI: IRI
				   target: target
				    errNo: errNo] autorelease];
}

- (instancetype)init
{
	OF_INVALID_INIT_METHOD
}

- (instancetype)initWithURI: (OFURI *)URI
- (instancetype)initWithIRI: (OFIRI *)IRI
		     target: (OFString *)target
		      errNo: (int)errNo
{
	self = [super init];

	@try {
		_URI = [URI copy];
		_IRI = [IRI copy];
		_target = [target copy];
		_errNo = errNo;
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (void)dealloc
{
	[_URI release];
	[_IRI release];
	[_target release];

	[super dealloc];
}

- (OFString *)description
{
	return [OFString stringWithFormat:
	    @"Failed to create symbolic link %@ with target %@: %@",
	    _URI, _target, OFStrError(_errNo)];
	    _IRI, _target, OFStrError(_errNo)];
}
@end

Modified src/exceptions/OFCreateWindowsRegistryKeyFailedException.h from [3739e39dc2] to [ab436ceec1].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFCreateWindowsRegistryKeyFailedException.m from [3f8a5e58b7] to [b0311433b0].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFDNSQueryFailedException.h from [e0cf12b730] to [6f064421ea].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFDNSQueryFailedException.m from [d34eb3c9de] to [40cdf7475c].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFDeleteWindowsRegistryKeyFailedException.h from [7a006ec7b5] to [d71cea7258].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFDeleteWindowsRegistryKeyFailedException.m from [123f06f5d8] to [27b80ecce5].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFDeleteWindowsRegistryValueFailedException.h from [0a7f480a16] to [1f8caa4d03].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFDeleteWindowsRegistryValueFailedException.m from [efa255c388] to [a160b679a2].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFEnumerationMutationException.h from [1a130e7399] to [569ff43c60].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFEnumerationMutationException.m from [f408c0df64] to [77d89a5bb0].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFException.h from [e7c0836484] to [7e3ef17d50].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFException.m from [700714ee53] to [d70693599a].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFGetCurrentDirectoryFailedException.h from [60ae2d8910] to [2e7e7c7364].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFGetCurrentDirectoryFailedException.m from [b29d0ac295] to [c2f5d624f1].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFGetItemAttributesFailedException.h from [354af07fb2] to [489a3eb946].

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
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

-
+

















-
+










-
+





-
+

-
+









-
+



-
+







-
+



-
+






/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 */

#import "OFException.h"

OF_ASSUME_NONNULL_BEGIN

@class OFURI;
@class OFIRI;

/**
 * @class OFGetItemAttributesFailedException \
 *	  OFGetItemAttributesFailedException.h \
 *	  ObjFW/OFGetItemAttributesFailedException.h
 *
 * @brief An exception indicating an item's attributes could not be retrieved.
 */
@interface OFGetItemAttributesFailedException: OFException
{
	OFURI *_URI;
	OFIRI *_IRI;
	int _errNo;
	OF_RESERVE_IVARS(OFGetItemAttributesFailedException, 4)
}

/**
 * @brief The URI of the item whose attributes could not be retrieved.
 * @brief The IRI of the item whose attributes could not be retrieved.
 */
@property (readonly, nonatomic) OFURI *URI;
@property (readonly, nonatomic) OFIRI *IRI;

/**
 * @brief The errno of the error that occurred.
 */
@property (readonly, nonatomic) int errNo;

/**
 * @brief Creates a new, autoreleased retrieve item attributes failed exception.
 *
 * @param URI The URI of the item whose attributes could not be retrieved
 * @param IRI The IRI of the item whose attributes could not be retrieved
 * @param errNo The errno of the error that occurred
 * @return A new, autoreleased retrieve item attributes failed exception
 */
+ (instancetype)exceptionWithURI: (OFURI *)URI errNo: (int)errNo;
+ (instancetype)exceptionWithIRI: (OFIRI *)IRI errNo: (int)errNo;

+ (instancetype)exception OF_UNAVAILABLE;

/**
 * @brief Initializes an already allocated retrieve item attributes failed
 *	  exception.
 *
 * @param URI The URI of the item whose attributes could not be retrieved
 * @param IRI The IRI of the item whose attributes could not be retrieved
 * @param errNo The errno of the error that occurred
 * @return An initialized retrieve item attributes failed exception
 */
- (instancetype)initWithURI: (OFURI *)URI
- (instancetype)initWithIRI: (OFIRI *)IRI
		      errNo: (int)errNo OF_DESIGNATED_INITIALIZER;

- (instancetype)init OF_UNAVAILABLE;
@end

OF_ASSUME_NONNULL_END

Modified src/exceptions/OFGetItemAttributesFailedException.m from [db212ce8f9] to [f4915d9d19].

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
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

-
+
















-
-
+
+


-
+






-
+

-
+







-
+




-
+











-
+








-
+


/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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 "OFGetItemAttributesFailedException.h"
#import "OFString.h"
#import "OFURI.h"
#import "OFIRI.h"
#import "OFString.h"

@implementation OFGetItemAttributesFailedException
@synthesize URI = _URI, errNo = _errNo;
@synthesize IRI = _IRI, errNo = _errNo;

+ (instancetype)exception
{
	OF_UNRECOGNIZED_SELECTOR
}

+ (instancetype)exceptionWithURI: (OFURI *)URI errNo: (int)errNo
+ (instancetype)exceptionWithIRI: (OFIRI *)IRI errNo: (int)errNo
{
	return [[[self alloc] initWithURI: URI errNo: errNo] autorelease];
	return [[[self alloc] initWithIRI: IRI errNo: errNo] autorelease];
}

- (instancetype)init
{
	OF_INVALID_INIT_METHOD
}

- (instancetype)initWithURI: (OFURI *)URI errNo: (int)errNo
- (instancetype)initWithIRI: (OFIRI *)IRI errNo: (int)errNo
{
	self = [super init];

	@try {
		_URI = [URI copy];
		_IRI = [IRI copy];
		_errNo = errNo;
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (void)dealloc
{
	[_URI release];
	[_IRI release];

	[super dealloc];
}

- (OFString *)description
{
	return [OFString stringWithFormat:
	    @"Failed to get attributes for item %@: %@",
	    _URI, OFStrError(_errNo)];
	    _IRI, OFStrError(_errNo)];
}
@end

Modified src/exceptions/OFGetOptionFailedException.h from [a8c8d533b3] to [6b97dd37ec].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
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
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







-
+







-
+













-
+










-
+






 * @class OFGetOptionFailedException \
 *	  OFGetOptionFailedException.h ObjFW/OFGetOptionFailedException.h
 *
 * @brief An exception indicating that getting an option for an object failed.
 */
@interface OFGetOptionFailedException: OFException
{
	id _object;
	id _Nullable _object;
	int _errNo;
	OF_RESERVE_IVARS(OFGetOptionFailedException, 4)
}

/**
 * @brief The object for which the option could not be retrieved.
 */
@property (readonly, nonatomic) id object;
@property OF_NULLABLE_PROPERTY (readonly, nonatomic) id object;

/**
 * @brief The errno of the error that occurred.
 */
@property (readonly, nonatomic) int errNo;

/**
 * @brief Creates a new, autoreleased get option failed exception.
 *
 * @param object The object for which the option could not be retrieved
 * @param errNo The errno of the error that occurred
 * @return A new, autoreleased get option failed exception
 */
+ (instancetype)exceptionWithObject: (id)object errNo: (int)errNo;
+ (instancetype)exceptionWithObject: (nullable id)object errNo: (int)errNo;

+ (instancetype)exception OF_UNAVAILABLE;

/**
 * @brief Initializes an already allocated get option failed exception.
 *
 * @param object The object for which the option could not be retrieved
 * @param errNo The errno of the error that occurred
 * @return An initialized get option failed exception
 */
- (instancetype)initWithObject: (id)object
- (instancetype)initWithObject: (nullable id)object
			 errNo: (int)errNo OF_DESIGNATED_INITIALIZER;

- (instancetype)init OF_UNAVAILABLE;
@end

OF_ASSUME_NONNULL_END

Modified src/exceptions/OFGetOptionFailedException.m from [aeeadc602d] to [937b3d5b17].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
51
52
53
54
55
56
57

58
59
60






61
62
51
52
53
54
55
56
57
58



59
60
61
62
63
64
65
66







+
-
-
-
+
+
+
+
+
+


	[_object release];

	[super dealloc];
}

- (OFString *)description
{
	if (_object != nil)
	return [OFString stringWithFormat:
	    @"Getting an option in an object of type %@ failed: %@",
	    [_object class], OFStrError(_errNo)];
		return [OFString stringWithFormat:
		    @"Getting an option in an object of type %@ failed: %@",
		    [_object class], OFStrError(_errNo)];
	else
		return [OFString stringWithFormat:
		    @"Getting an option failed: %@", OFStrError(_errNo)];
}
@end

Modified src/exceptions/OFGetWindowsRegistryValueFailedException.h from [1bae299028] to [018a44fa26].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFGetWindowsRegistryValueFailedException.m from [57087b05b3] to [a539964e68].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFHTTPRequestFailedException.h from [d5947528d2] to [881e8f136b].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFHTTPRequestFailedException.m from [f93ff97e23] to [fd787d72c8].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
60
61
62
63
64
65
66
67
68


69
70
60
61
62
63
64
65
66


67
68
69
70







-
-
+
+


}

- (OFString *)description
{
	const char *method = OFHTTPRequestMethodName(_request.method);

	return [OFString stringWithFormat:
	    @"An HTTP %s request with URI %@ failed with code %hd!", method,
	    _request.URI, _response.statusCode];
	    @"An HTTP %s request with IRI %@ failed with code %hd!", method,
	    _request.IRI, _response.statusCode];
}
@end

Modified src/exceptions/OFHashAlreadyCalculatedException.h from [0455e7b89e] to [81236b3dd2].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFHashAlreadyCalculatedException.m from [cf2d8e44b5] to [b38e8e165c].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFHashNotCalculatedException.h from [e76b9886eb] to [3147e4cc7e].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFHashNotCalculatedException.m from [3e84cb3642] to [eb7236ee33].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFInitializationFailedException.h from [280997dfe1] to [9098d2a276].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFInitializationFailedException.m from [cfa23bb7fe] to [601d4266f8].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFInvalidArgumentException.h from [835c000126] to [058bcfe239].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFInvalidArgumentException.m from [70957802ed] to [eae0889491].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFInvalidEncodingException.h from [36e737e07d] to [08178f5611].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFInvalidEncodingException.m from [7e85cac169] to [35e8ad45e2].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFInvalidFormatException.h from [7bd0078c9f] to [89e8ba004c].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFInvalidFormatException.m from [f3d13d03ab] to [c562e9cc9c].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFInvalidJSONException.h from [a9bef800fe] to [ca07739c54].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFInvalidJSONException.m from [973f5127bd] to [bb151cfc83].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFInvalidServerResponseException.h from [8680d9915b] to [f4a34d156a].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFInvalidServerResponseException.m from [8436f85f3d] to [7137fec4e8].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFJoinThreadFailedException.h from [b841fb7f6d] to [b99a648195].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFJoinThreadFailedException.m from [7e2f0f00c7] to [343ea360f3].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFLinkItemFailedException.h from [bc4e6321e5] to [63f36b110c].

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
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

-
+

















-
+









-
+





-
+

-
+


-
+

-
+









-
-
+
+



-
-
+
+







-
-
+
+



-
-
+
+






/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 */

#import "OFException.h"

OF_ASSUME_NONNULL_BEGIN

@class OFURI;
@class OFIRI;

/**
 * @class OFLinkItemFailedException \
 *	  OFLinkItemFailedException.h ObjFW/OFLinkItemFailedException.h
 *
 * @brief An exception indicating that creating a link failed.
 */
@interface OFLinkItemFailedException: OFException
{
	OFURI *_sourceURI, *_destinationURI;
	OFIRI *_sourceIRI, *_destinationIRI;
	int _errNo;
	OF_RESERVE_IVARS(OFLinkItemFailedException, 4)
}

/**
 * @brief A URI with the source for the link.
 * @brief An IRI with the source for the link.
 */
@property (readonly, nonatomic) OFURI *sourceURI;
@property (readonly, nonatomic) OFIRI *sourceIRI;

/**
 * @brief A URI with the destination for the link.
 * @brief An IRI with the destination for the link.
 */
@property (readonly, nonatomic) OFURI *destinationURI;
@property (readonly, nonatomic) OFIRI *destinationIRI;

/**
 * @brief The errno of the error that occurred.
 */
@property (readonly, nonatomic) int errNo;

/**
 * @brief Creates a new, autoreleased link failed exception.
 *
 * @param sourceURI The source for the link
 * @param destinationURI The destination for the link
 * @param sourceIRI The source for the link
 * @param destinationIRI The destination for the link
 * @param errNo The errno of the error that occurred
 * @return A new, autoreleased link failed exception
 */
+ (instancetype)exceptionWithSourceURI: (OFURI *)sourceURI
			destinationURI: (OFURI *)destinationURI
+ (instancetype)exceptionWithSourceIRI: (OFIRI *)sourceIRI
			destinationIRI: (OFIRI *)destinationIRI
				 errNo: (int)errNo;

+ (instancetype)exception OF_UNAVAILABLE;

/**
 * @brief Initializes an already allocated link failed exception.
 *
 * @param sourceURI The source for the link
 * @param destinationURI The destination for the link
 * @param sourceIRI The source for the link
 * @param destinationIRI The destination for the link
 * @param errNo The errno of the error that occurred
 * @return An initialized link failed exception
 */
- (instancetype)initWithSourceURI: (OFURI*)sourceURI
		   destinationURI: (OFURI *)destinationURI
- (instancetype)initWithSourceIRI: (OFIRI*)sourceIRI
		   destinationIRI: (OFIRI *)destinationIRI
			    errNo: (int)errNo OF_DESIGNATED_INITIALIZER;

- (instancetype)init OF_UNAVAILABLE;
@end

OF_ASSUME_NONNULL_END

Modified src/exceptions/OFLinkItemFailedException.m from [3033895110] to [d3fcfa178d].

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
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

-
+
















-
-
+
+


-
+







-
-
+
+


-
-
+
+








-
-
+
+





-
-
+
+











-
-
+
+







-
+


/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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 "OFLinkItemFailedException.h"
#import "OFString.h"
#import "OFURI.h"
#import "OFIRI.h"
#import "OFString.h"

@implementation OFLinkItemFailedException
@synthesize sourceURI = _sourceURI, destinationURI = _destinationURI;
@synthesize sourceIRI = _sourceIRI, destinationIRI = _destinationIRI;
@synthesize errNo = _errNo;

+ (instancetype)exception
{
	OF_UNRECOGNIZED_SELECTOR
}

+ (instancetype)exceptionWithSourceURI: (OFURI *)sourceURI
			destinationURI: (OFURI *)destinationURI
+ (instancetype)exceptionWithSourceIRI: (OFIRI *)sourceIRI
			destinationIRI: (OFIRI *)destinationIRI
				 errNo: (int)errNo
{
	return [[[self alloc] initWithSourceURI: sourceURI
				 destinationURI: destinationURI
	return [[[self alloc] initWithSourceIRI: sourceIRI
				 destinationIRI: destinationIRI
					  errNo: errNo] autorelease];
}

- (instancetype)init
{
	OF_INVALID_INIT_METHOD
}

- (instancetype)initWithSourceURI: (OFURI *)sourceURI
		   destinationURI: (OFURI *)destinationURI
- (instancetype)initWithSourceIRI: (OFIRI *)sourceIRI
		   destinationIRI: (OFIRI *)destinationIRI
			    errNo: (int)errNo
{
	self = [super init];

	@try {
		_sourceURI = [sourceURI copy];
		_destinationURI = [destinationURI copy];
		_sourceIRI = [sourceIRI copy];
		_destinationIRI = [destinationIRI copy];
		_errNo = errNo;
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (void)dealloc
{
	[_sourceURI release];
	[_destinationURI release];
	[_sourceIRI release];
	[_destinationIRI release];

	[super dealloc];
}

- (OFString *)description
{
	return [OFString stringWithFormat: @"Failed to link file %@ to %@: %@",
	    _sourceURI, _destinationURI, OFStrError(_errNo)];
	    _sourceIRI, _destinationIRI, OFStrError(_errNo)];
}
@end

Modified src/exceptions/OFListenOnSocketFailedException.h from [98d11c8685] to [8c9f4f48a1].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFListenOnSocketFailedException.m from [5b45bde80b] to [eeecb3b4f2].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFLoadPluginFailedException.h from [bb70233a5c] to [1f0b8a6d47].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFLoadPluginFailedException.m from [73caeab9c3] to [e0a8b5e271].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFLockFailedException.h from [58545dfa42] to [56c9fb143e].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFLockFailedException.m from [77b32492ca] to [db38fe8872].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFMalformedXMLException.h from [d319798b44] to [32cf6d452c].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFMalformedXMLException.m from [f5ceb7c800] to [25f4ffc59c].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFMoveItemFailedException.h from [f2cc0cdf02] to [3f95d4e4e7].

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
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

-
+

















-
+









-
+





-
+

-
+


-
+

-
+









-
-
+
+



-
-
+
+







-
-
+
+



-
-
+
+






/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 */

#import "OFException.h"

OF_ASSUME_NONNULL_BEGIN

@class OFURI;
@class OFIRI;

/**
 * @class OFMoveItemFailedException \
 *	  OFMoveItemFailedException.h ObjFW/OFMoveItemFailedException.h
 *
 * @brief An exception indicating that moving an item failed.
 */
@interface OFMoveItemFailedException: OFException
{
	OFURI *_sourceURI, *_destinationURI;
	OFIRI *_sourceIRI, *_destinationIRI;
	int _errNo;
	OF_RESERVE_IVARS(OFMoveItemFailedException, 4)
}

/**
 * @brief The original URI.
 * @brief The original IRI.
 */
@property (readonly, nonatomic) OFURI *sourceURI;
@property (readonly, nonatomic) OFIRI *sourceIRI;

/**
 * @brief The new URI.
 * @brief The new IRI.
 */
@property (readonly, nonatomic) OFURI *destinationURI;
@property (readonly, nonatomic) OFIRI *destinationIRI;

/**
 * @brief The errno of the error that occurred.
 */
@property (readonly, nonatomic) int errNo;

/**
 * @brief Creates a new, autoreleased move item failed exception.
 *
 * @param sourceURI The original URI
 * @param destinationURI The new URI
 * @param sourceIRI The original IRI
 * @param destinationIRI The new IRI
 * @param errNo The errno of the error that occurred
 * @return A new, autoreleased move item failed exception
 */
+ (instancetype)exceptionWithSourceURI: (OFURI *)sourceURI
			destinationURI: (OFURI *)destinationURI
+ (instancetype)exceptionWithSourceIRI: (OFIRI *)sourceIRI
			destinationIRI: (OFIRI *)destinationIRI
				 errNo: (int)errNo;

+ (instancetype)exception OF_UNAVAILABLE;

/**
 * @brief Initializes an already allocated move item failed exception.
 *
 * @param sourceURI The original URI
 * @param destinationURI The new URI
 * @param sourceIRI The original IRI
 * @param destinationIRI The new IRI
 * @param errNo The errno of the error that occurred
 * @return An initialized move item failed exception
 */
- (instancetype)initWithSourceURI: (OFURI *)sourceURI
		   destinationURI: (OFURI *)destinationURI
- (instancetype)initWithSourceIRI: (OFIRI *)sourceIRI
		   destinationIRI: (OFIRI *)destinationIRI
			    errNo: (int)errNo OF_DESIGNATED_INITIALIZER;

- (instancetype)init OF_UNAVAILABLE;
@end

OF_ASSUME_NONNULL_END

Modified src/exceptions/OFMoveItemFailedException.m from [7df7241c06] to [379d799059].

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
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

-
+
















-
-
+
+


-
+







-
-
+
+


-
-
+
+








-
-
+
+





-
-
+
+











-
-
+
+








-
+


/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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 "OFMoveItemFailedException.h"
#import "OFString.h"
#import "OFURI.h"
#import "OFIRI.h"
#import "OFString.h"

@implementation OFMoveItemFailedException
@synthesize sourceURI = _sourceURI, destinationURI = _destinationURI;
@synthesize sourceIRI = _sourceIRI, destinationIRI = _destinationIRI;
@synthesize errNo = _errNo;

+ (instancetype)exception
{
	OF_UNRECOGNIZED_SELECTOR
}

+ (instancetype)exceptionWithSourceURI: (OFURI *)sourceURI
			destinationURI: (OFURI *)destinationURI
+ (instancetype)exceptionWithSourceIRI: (OFIRI *)sourceIRI
			destinationIRI: (OFIRI *)destinationIRI
				 errNo: (int)errNo
{
	return [[[self alloc] initWithSourceURI: sourceURI
				 destinationURI: destinationURI
	return [[[self alloc] initWithSourceIRI: sourceIRI
				 destinationIRI: destinationIRI
					  errNo: errNo] autorelease];
}

- (instancetype)init
{
	OF_INVALID_INIT_METHOD
}

- (instancetype)initWithSourceURI: (OFURI *)sourceURI
		   destinationURI: (OFURI *)destinationURI
- (instancetype)initWithSourceIRI: (OFIRI *)sourceIRI
		   destinationIRI: (OFIRI *)destinationIRI
			    errNo: (int)errNo
{
	self = [super init];

	@try {
		_sourceURI = [sourceURI copy];
		_destinationURI = [destinationURI copy];
		_sourceIRI = [sourceIRI copy];
		_destinationIRI = [destinationIRI copy];
		_errNo = errNo;
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (void)dealloc
{
	[_sourceURI release];
	[_destinationURI release];
	[_sourceIRI release];
	[_destinationIRI release];

	[super dealloc];
}

- (OFString *)description
{
	return [OFString stringWithFormat:
	    @"Failed to move item at %@ to %@: %@",
	    _sourceURI, _destinationURI, OFStrError(_errNo)];
	    _sourceIRI, _destinationIRI, OFStrError(_errNo)];
}
@end

Modified src/exceptions/OFNotImplementedException.h from [f0426204c4] to [5804df8acf].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFNotImplementedException.m from [c04e46d7c8] to [2f57db336d].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFNotOpenException.h from [5a826ad61e] to [25a32489f9].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFNotOpenException.m from [b0a200e662] to [bc94f442af].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFObserveKernelEventsFailedException.h from [a11562c534] to [f5779833f9].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFObserveKernelEventsFailedException.m from [1f89b66175] to [5cff98e757].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFOpenItemFailedException.h from [fe988003bf] to [98dffdfb7b].

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
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

-
+

















-
+









-
+







-
+

-
+



















-
+




-
+




















-
+




-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 */

#import "OFException.h"

OF_ASSUME_NONNULL_BEGIN

@class OFURI;
@class OFIRI;

/**
 * @class OFOpenItemFailedException \
 *	  OFOpenItemFailedException.h ObjFW/OFOpenItemFailedException.h
 *
 * @brief An exception indicating an item could not be opened.
 */
@interface OFOpenItemFailedException: OFException
{
	OFURI *_Nullable _URI;
	OFIRI *_Nullable _IRI;
	OFString *_Nullable _path;
	OFString *_mode;
	int _errNo;
	OF_RESERVE_IVARS(OFOpenItemFailedException, 4)
}

/**
 * @brief The URI of the item which could not be opened.
 * @brief The IRI of the item which could not be opened.
 */
@property OF_NULLABLE_PROPERTY (readonly, nonatomic) OFURI *URI;
@property OF_NULLABLE_PROPERTY (readonly, nonatomic) OFIRI *IRI;

/**
 * @brief The path of the item which could not be opened.
 */
@property OF_NULLABLE_PROPERTY (readonly, nonatomic) OFString *path;

/**
 * @brief The mode in which the item should have been opened.
 */
@property OF_NULLABLE_PROPERTY (readonly, nonatomic) OFString *mode;

/**
 * @brief The errno of the error that occurred.
 */
@property (readonly, nonatomic) int errNo;

/**
 * @brief Creates a new, autoreleased open item failed exception.
 *
 * @param URI The URI of the item which could not be opened
 * @param IRI The IRI of the item which could not be opened
 * @param mode A string with the mode in which the item should have been opened
 * @param errNo The errno of the error that occurred
 * @return A new, autoreleased open item failed exception
 */
+ (instancetype)exceptionWithURI: (OFURI *)URI
+ (instancetype)exceptionWithIRI: (OFIRI *)IRI
			    mode: (nullable OFString *)mode
			   errNo: (int)errNo;

/**
 * @brief Creates a new, autoreleased open item failed exception.
 *
 * @param path The path of the item which could not be opened
 * @param mode A string with the mode in which the item should have been opened
 * @param errNo The errno of the error that occurred
 * @return A new, autoreleased open item failed exception
 */
+ (instancetype)exceptionWithPath: (OFString *)path
			     mode: (nullable OFString *)mode
			    errNo: (int)errNo;

+ (instancetype)exception OF_UNAVAILABLE;

/**
 * @brief Initializes an already allocated open item failed exception.
 *
 * @param URI The URI of the item which could not be opened
 * @param IRI The IRI of the item which could not be opened
 * @param mode A string with the mode in which the item should have been opened
 * @param errNo The errno of the error that occurred
 * @return An initialized open item failed exception
 */
- (instancetype)initWithURI: (OFURI *)URI
- (instancetype)initWithIRI: (OFIRI *)IRI
		       mode: (nullable OFString *)mode
		      errNo: (int)errNo;

/**
 * @brief Initializes an already allocated open item failed exception.
 *
 * @param path The path of the item which could not be opened

Modified src/exceptions/OFOpenItemFailedException.m from [7129cdf836] to [4d2dfe89d0].

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
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

-
+
















-
-
+
+


-
+

-
+



-
+


















-
+






-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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 "OFOpenItemFailedException.h"
#import "OFString.h"
#import "OFURI.h"
#import "OFIRI.h"
#import "OFString.h"

@implementation OFOpenItemFailedException
@synthesize URI = _URI, path = _path, mode = _mode, errNo = _errNo;
@synthesize IRI = _IRI, path = _path, mode = _mode, errNo = _errNo;

+ (instancetype)exceptionWithURI: (OFURI *)URI
+ (instancetype)exceptionWithIRI: (OFIRI *)IRI
			    mode: (OFString *)mode
			   errNo: (int)errNo
{
	return [[[self alloc] initWithURI: URI
	return [[[self alloc] initWithIRI: IRI
				     mode: mode
				    errNo: errNo] autorelease];
}

+ (instancetype)exceptionWithPath: (OFString *)path
			     mode: (OFString *)mode
			    errNo: (int)errNo
{
	return [[[self alloc] initWithPath: path
				      mode: mode
				     errNo: errNo] autorelease];
}

+ (instancetype)exception
{
	OF_UNRECOGNIZED_SELECTOR
}

- (instancetype)initWithURI: (OFURI *)URI
- (instancetype)initWithIRI: (OFIRI *)IRI
		       mode: (OFString *)mode
		      errNo: (int)errNo
{
	self = [super init];

	@try {
		_URI = [URI copy];
		_IRI = [IRI copy];
		_mode = [mode copy];
		_errNo = errNo;
	} @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
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







-
+










-
-
+
+












- (instancetype)init
{
	OF_INVALID_INIT_METHOD
}

- (void)dealloc
{
	[_URI release];
	[_IRI release];
	[_path release];
	[_mode release];

	[super dealloc];
}

- (OFString *)description
{
	id item = nil;

	if (_URI != nil)
		item = _URI;
	if (_IRI != nil)
		item = _IRI;
	else if (_path != nil)
		item = _path;

	if (_mode != nil)
		return [OFString stringWithFormat:
		    @"Failed to open file %@ with mode %@: %@",
		    item, _mode, OFStrError(_errNo)];
	else
		return [OFString stringWithFormat:
		    @"Failed to open item %@: %@", item, OFStrError(_errNo)];
}
@end

Modified src/exceptions/OFOpenWindowsRegistryKeyFailedException.h from [36fb64cf1a] to [2296f6f1a7].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFOpenWindowsRegistryKeyFailedException.m from [64b24e1261] to [c53408c44c].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFOutOfMemoryException.h from [f5654732f6] to [eb4224bf73].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFOutOfMemoryException.m from [f0195e5a54] to [9811b1c64b].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFOutOfRangeException.h from [f8a5e124cb] to [dfda0a2a7e].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFOutOfRangeException.m from [42dae12fbe] to [ed7053daa3].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFReadFailedException.h from [1ab276c5fd] to [965f8ad292].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFReadFailedException.m from [0a38835e23] to [abd7a3f3a5].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFReadOrWriteFailedException.h from [2c37db7aa0] to [9789b3f76a].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFReadOrWriteFailedException.m from [02ef4afd0b] to [ddb8831317].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFRemoveItemFailedException.h from [18b7b9ee6b] to [6dae53250f].

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
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

-
+

















-
+









-
+





-
+

-
+









-
+



-
+






-
+



-
+






/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 */

#import "OFException.h"

OF_ASSUME_NONNULL_BEGIN

@class OFURI;
@class OFIRI;

/**
 * @class OFRemoveItemFailedException \
 *	  OFRemoveItemFailedException.h ObjFW/OFRemoveItemFailedException.h
 *
 * @brief An exception indicating that removing an item failed.
 */
@interface OFRemoveItemFailedException: OFException
{
	OFURI *_URI;
	OFIRI *_IRI;
	int _errNo;
	OF_RESERVE_IVARS(OFRemoveItemFailedException, 4)
}

/**
 * @brief The URI of the item which could not be removed.
 * @brief The IRI of the item which could not be removed.
 */
@property (readonly, nonatomic) OFURI *URI;
@property (readonly, nonatomic) OFIRI *IRI;

/**
 * @brief The errno of the error that occurred.
 */
@property (readonly, nonatomic) int errNo;

/**
 * @brief Creates a new, autoreleased remove failed exception.
 *
 * @param URI The URI of the item which could not be removed
 * @param IRI The IRI of the item which could not be removed
 * @param errNo The errno of the error that occurred
 * @return A new, autoreleased remove item failed exception
 */
+ (instancetype)exceptionWithURI: (OFURI *)URI errNo: (int)errNo;
+ (instancetype)exceptionWithIRI: (OFIRI *)IRI errNo: (int)errNo;

+ (instancetype)exception OF_UNAVAILABLE;

/**
 * @brief Initializes an already allocated remove failed exception.
 *
 * @param URI The URI of the item which could not be removed
 * @param IRI The IRI of the item which could not be removed
 * @param errNo The errno of the error that occurred
 * @return An initialized remove item failed exception
 */
- (instancetype)initWithURI: (OFURI *)URI
- (instancetype)initWithIRI: (OFIRI *)IRI
		      errNo: (int)errNo OF_DESIGNATED_INITIALIZER;

- (instancetype)init OF_UNAVAILABLE;
@end

OF_ASSUME_NONNULL_END

Modified src/exceptions/OFRemoveItemFailedException.m from [790fd92540] to [70232d7087].

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
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

-
+
















-
-
+
+


-
+






-
+

-
+







-
+




-
+











-
+







-
+


/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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 "OFRemoveItemFailedException.h"
#import "OFString.h"
#import "OFURI.h"
#import "OFIRI.h"
#import "OFString.h"

@implementation OFRemoveItemFailedException
@synthesize URI = _URI, errNo = _errNo;
@synthesize IRI = _IRI, errNo = _errNo;

+ (instancetype)exception
{
	OF_UNRECOGNIZED_SELECTOR
}

+ (instancetype)exceptionWithURI: (OFURI *)URI errNo: (int)errNo
+ (instancetype)exceptionWithIRI: (OFIRI *)IRI errNo: (int)errNo
{
	return [[[self alloc] initWithURI: URI errNo: errNo] autorelease];
	return [[[self alloc] initWithIRI: IRI errNo: errNo] autorelease];
}

- (instancetype)init
{
	OF_INVALID_INIT_METHOD
}

- (instancetype)initWithURI: (OFURI *)URI errNo: (int)errNo
- (instancetype)initWithIRI: (OFIRI *)IRI errNo: (int)errNo
{
	self = [super init];

	@try {
		_URI = [URI copy];
		_IRI = [IRI copy];
		_errNo = errNo;
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (void)dealloc
{
	[_URI release];
	[_IRI release];

	[super dealloc];
}

- (OFString *)description
{
	return [OFString stringWithFormat:
	    @"Failed to remove item at URI %@: %@", _URI, OFStrError(_errNo)];
	    @"Failed to remove item at IRI %@: %@", _IRI, OFStrError(_errNo)];
}
@end

Modified src/exceptions/OFResolveHostFailedException.h from [983add21d8] to [f2ee40aacb].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFResolveHostFailedException.m from [a81a110c2f] to [998654820c].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFSeekFailedException.h from [2132111c3a] to [b626de4db2].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFSeekFailedException.m from [20812553c7] to [1ab4c78784].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFSetItemAttributesFailedException.h from [4b245f8a54] to [81347440ef].

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
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

-
+














-
+



-
+










-
+







-
+

-
+



















-
+






-
+









-
+






-
+








/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 */

#import "OFException.h"
#import "OFURIHandler.h"
#import "OFIRIHandler.h"

OF_ASSUME_NONNULL_BEGIN

@class OFURI;
@class OFIRI;

/**
 * @class OFSetItemAttributesFailedException \
 *	  OFSetItemAttributesFailedException.h \
 *	  ObjFW/OFSetItemAttributesFailedException.h
 *
 * @brief An exception indicating an item's attributes could not be set.
 */
@interface OFSetItemAttributesFailedException: OFException
{
	OFURI *_URI;
	OFIRI *_IRI;
	OFFileAttributes _attributes;
	OFFileAttributeKey _failedAttribute;
	int _errNo;
	OF_RESERVE_IVARS(OFSetItemAttributesFailedException, 4)
}

/**
 * @brief The URI of the item whose attributes could not be set.
 * @brief The IRI of the item whose attributes could not be set.
 */
@property (readonly, nonatomic) OFURI *URI;
@property (readonly, nonatomic) OFIRI *IRI;

/**
 * @brief The errno of the error that occurred.
 */
@property (readonly, nonatomic) int errNo;

/**
 * @brief The attributes that should have been set.
 */
@property (readonly, nonatomic) OFFileAttributes attributes;

/**
 * @brief The first attribute that could not be set.
 */
@property (readonly, nonatomic) OFFileAttributeKey failedAttribute;

/**
 * @brief Creates a new, autoreleased set item attributes failed exception.
 *
 * @param URI The URI of the item whose attributes could not be set
 * @param IRI The IRI of the item whose attributes could not be set
 * @param attributes The attributes that should have been set for the specified
 *		     item.
 * @param failedAttribute The first attribute that could not be set
 * @param errNo The errno of the error that occurred
 * @return A new, autoreleased set item attributes failed exception
 */
+ (instancetype)exceptionWithURI: (OFURI *)URI
+ (instancetype)exceptionWithIRI: (OFIRI *)IRI
		      attributes: (OFFileAttributes)attributes
		 failedAttribute: (OFFileAttributeKey)failedAttribute
			   errNo: (int)errNo;

+ (instancetype)exception OF_UNAVAILABLE;

/**
 * @brief Initializes an already allocated set item attributes failed exception.
 *
 * @param URI The URI of the item whose attributes could not be set
 * @param IRI The IRI of the item whose attributes could not be set
 * @param attributes The attributes that should have been set for the specified
 *		     item.
 * @param failedAttribute The first attribute that could not be set
 * @param errNo The errno of the error that occurred
 * @return An initialized set item attributes failed exception
 */
- (instancetype)initWithURI: (OFURI *)URI
- (instancetype)initWithIRI: (OFIRI *)IRI
		 attributes: (OFFileAttributes)attributes
	    failedAttribute: (OFFileAttributeKey)failedAttribute
		      errNo: (int)errNo OF_DESIGNATED_INITIALIZER;

- (instancetype)init OF_UNAVAILABLE;
@end

OF_ASSUME_NONNULL_END

Modified src/exceptions/OFSetItemAttributesFailedException.m from [419b3c1aff] to [8b65a824a7].

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
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

-
+
















-
-
+
+


-
+







-
+




-
+










-
+







-
+













-
+










-
+


/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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 "OFSetItemAttributesFailedException.h"
#import "OFString.h"
#import "OFURI.h"
#import "OFIRI.h"
#import "OFString.h"

@implementation OFSetItemAttributesFailedException
@synthesize URI = _URI, attributes = _attributes;
@synthesize IRI = _IRI, attributes = _attributes;
@synthesize failedAttribute = _failedAttribute, errNo = _errNo;

+ (instancetype)exception
{
	OF_UNRECOGNIZED_SELECTOR
}

+ (instancetype)exceptionWithURI: (OFURI *)URI
+ (instancetype)exceptionWithIRI: (OFIRI *)IRI
		      attributes: (OFFileAttributes)attributes
		 failedAttribute: (OFFileAttributeKey)failedAttribute
			   errNo: (int)errNo
{
	return [[[self alloc] initWithURI: URI
	return [[[self alloc] initWithIRI: IRI
			       attributes: attributes
			  failedAttribute: failedAttribute
				    errNo: errNo] autorelease];
}

- (instancetype)init
{
	OF_INVALID_INIT_METHOD
}

- (instancetype)initWithURI: (OFURI *)URI
- (instancetype)initWithIRI: (OFIRI *)IRI
		 attributes: (OFFileAttributes)attributes
	    failedAttribute: (OFFileAttributeKey)failedAttribute
		      errNo: (int)errNo
{
	self = [super init];

	@try {
		_URI = [URI copy];
		_IRI = [IRI copy];
		_attributes = [attributes copy];
		_failedAttribute = [failedAttribute copy];
		_errNo = errNo;
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (void)dealloc
{
	[_URI release];
	[_IRI release];
	[_attributes release];
	[_failedAttribute release];

	[super dealloc];
}

- (OFString *)description
{
	return [OFString stringWithFormat:
	    @"Failed to set attribute %@ for item %@: %@",
	    _failedAttribute, _URI, OFStrError(_errNo)];
	    _failedAttribute, _IRI, OFStrError(_errNo)];
}
@end

Modified src/exceptions/OFSetOptionFailedException.h from [2fa10041b9] to [daab9b6b5c].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
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
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







-
+







-
+













-
+










-
+






 * @class OFSetOptionFailedException \
 *	  OFSetOptionFailedException.h ObjFW/OFSetOptionFailedException.h
 *
 * @brief An exception indicating that setting an option for an object failed.
 */
@interface OFSetOptionFailedException: OFException
{
	id _object;
	id _Nullable _object;
	int _errNo;
	OF_RESERVE_IVARS(OFSetOptionFailedException, 4)
}

/**
 * @brief The object for which the option could not be set.
 */
@property (readonly, nonatomic) id object;
@property OF_NULLABLE_PROPERTY (readonly, nonatomic) id object;

/**
 * @brief The errno of the error that occurred.
 */
@property (readonly, nonatomic) int errNo;

/**
 * @brief Creates a new, autoreleased set option failed exception.
 *
 * @param object The object for which the option could not be set
 * @param errNo The errno of the error that occurred
 * @return A new, autoreleased set option failed exception
 */
+ (instancetype)exceptionWithObject: (id)object errNo: (int)errNo;
+ (instancetype)exceptionWithObject: (nullable id)object errNo: (int)errNo;

+ (instancetype)exception OF_UNAVAILABLE;

/**
 * @brief Initializes an already allocated set option failed exception.
 *
 * @param object The object for which the option could not be set
 * @param errNo The errno of the error that occurred
 * @return An initialized set option failed exception
 */
- (instancetype)initWithObject: (id)object
- (instancetype)initWithObject: (nullable id)object
			 errNo: (int)errNo OF_DESIGNATED_INITIALIZER;

- (instancetype)init OF_UNAVAILABLE;
@end

OF_ASSUME_NONNULL_END

Modified src/exceptions/OFSetOptionFailedException.m from [8f19f7dfbc] to [7495460b21].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
51
52
53
54
55
56
57

58
59
60






61
62
51
52
53
54
55
56
57
58



59
60
61
62
63
64
65
66







+
-
-
-
+
+
+
+
+
+


	[_object release];

	[super dealloc];
}

- (OFString *)description
{
	if (_object != nil)
	return [OFString stringWithFormat:
	    @"Setting an option in an object of type %@ failed: %@",
	    [_object class], OFStrError(_errNo)];
		return [OFString stringWithFormat:
		    @"Setting an option in an object of type %@ failed: %@",
		    [_object class], OFStrError(_errNo)];
	else
		return [OFString stringWithFormat:
		    @"Setting an option failed: %@", OFStrError(_errNo)];
}
@end

Modified src/exceptions/OFSetWindowsRegistryValueFailedException.h from [88eed12b7b] to [fe7aba15cd].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFSetWindowsRegistryValueFailedException.m from [e6d28eef78] to [51126001e8].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFSignalConditionFailedException.h from [abb9bfa0ca] to [8e4da43fb7].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFSignalConditionFailedException.m from [f5f3ff967a] to [04b7ec52d0].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFStartThreadFailedException.h from [e0e650ae0d] to [1fd467d6f6].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFStartThreadFailedException.m from [9dcf5912d6] to [ef15b41cc4].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFStillLockedException.h from [da104224a4] to [66bd44c6a8].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFStillLockedException.m from [3bdcf688e2] to [83e35c4b65].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFTLSHandshakeFailedException.h from [f9e2ae9630] to [c185a526b4].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFTLSHandshakeFailedException.m from [9f825e73f8] to [4b3f02cc47].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFThreadStillRunningException.h from [8cadaadd37] to [be8a4a9c9f].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFThreadStillRunningException.m from [08b6a2fa91] to [e1be5f7279].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFTruncatedDataException.h from [c355984cb5] to [62ccfb06a8].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFTruncatedDataException.m from [d3465afc55] to [6e19bde17d].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFUnboundNamespaceException.h from [782770074b] to [94a1cadf29].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFUnboundNamespaceException.m from [8d26c2cfa6] to [2277f17f8f].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFUnboundPrefixException.h from [c1eaadb13e] to [da8310264b].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFUnboundPrefixException.m from [09d3302162] to [bb52097057].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFUndefinedKeyException.h from [1b1bc72e6f] to [d2579a3557].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFUndefinedKeyException.m from [fa0cc877cd] to [6134ab4456].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFUnknownXMLEntityException.h from [effb41465b] to [6abc0d91ce].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFUnknownXMLEntityException.m from [87056195a2] to [17867a761e].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFUnlockFailedException.h from [2273de4dc6] to [757a4dc21c].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFUnlockFailedException.m from [68e65cd613] to [f100ac5cc3].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFUnsupportedProtocolException.h from [229fefef5c] to [e93c4c1e05].

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
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

-
+

















-
+






-
+




-
+




-
+

-
+




-
+


-
+




-
+


-
+



/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 */

#import "OFException.h"

OF_ASSUME_NONNULL_BEGIN

@class OFURI;
@class OFIRI;

/**
 * @class OFUnsupportedProtocolException \
 *	  OFUnsupportedProtocolException.h \
 *	  ObjFW/OFUnsupportedProtocolException.h
 *
 * @brief An exception indicating that the protocol specified by the URI is not
 * @brief An exception indicating that the protocol specified by the IRI is not
 *	  supported.
 */
@interface OFUnsupportedProtocolException: OFException
{
	OFURI *_Nullable _URI;
	OFIRI *_Nullable _IRI;
	OF_RESERVE_IVARS(OFUnsupportedProtocolException, 4)
}

/**
 * @brief The URI whose protocol is unsupported.
 * @brief The IRI whose protocol is unsupported.
 */
@property OF_NULLABLE_PROPERTY (readonly, nonatomic) OFURI *URI;
@property OF_NULLABLE_PROPERTY (readonly, nonatomic) OFIRI *IRI;

/**
 * @brief Creates a new, autoreleased unsupported protocol exception.
 *
 * @param URI The URI whose protocol is unsupported
 * @param IRI The IRI whose protocol is unsupported
 * @return A new, autoreleased unsupported protocol exception
 */
+ (instancetype)exceptionWithURI: (nullable OFURI*)URI;
+ (instancetype)exceptionWithIRI: (nullable OFIRI*)IRI;

/**
 * @brief Initializes an already allocated unsupported protocol exception
 *
 * @param URI The URI whose protocol is unsupported
 * @param IRI The IRI whose protocol is unsupported
 * @return An initialized unsupported protocol exception
 */
- (instancetype)initWithURI: (nullable OFURI*)URI OF_DESIGNATED_INITIALIZER;
- (instancetype)initWithIRI: (nullable OFIRI*)IRI OF_DESIGNATED_INITIALIZER;
@end

OF_ASSUME_NONNULL_END

Modified src/exceptions/OFUnsupportedProtocolException.m from [a391485837] to [d3a87779b9].

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
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

-
+
















-
-
+
+


-
+

-
+

-
+


-
+



-
+






-
+






-
+

-
+




/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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 "OFUnsupportedProtocolException.h"
#import "OFString.h"
#import "OFURI.h"
#import "OFIRI.h"
#import "OFString.h"

@implementation OFUnsupportedProtocolException
@synthesize URI = _URI;
@synthesize IRI = _IRI;

+ (instancetype)exceptionWithURI: (OFURI *)URI
+ (instancetype)exceptionWithIRI: (OFIRI *)IRI
{
	return [[[self alloc] initWithURI: URI] autorelease];
	return [[[self alloc] initWithIRI: IRI] autorelease];
}

- (instancetype)initWithURI: (OFURI *)URI
- (instancetype)initWithIRI: (OFIRI *)IRI
{
	self = [super init];

	_URI = [URI retain];
	_IRI = [IRI retain];

	return self;
}

- (void)dealloc
{
	[_URI release];
	[_IRI release];

	[super dealloc];
}

- (OFString *)description
{
	if (_URI != nil)
	if (_IRI != nil)
		return [OFString stringWithFormat:
		    @"The protocol of URI %@ is not supported!", _URI];
		    @"The protocol of IRI %@ is not supported!", _IRI];
	else
		return @"The requested protocol is unsupported!";
}
@end

Modified src/exceptions/OFUnsupportedVersionException.h from [2da3b1eaf2] to [55060a35a5].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFUnsupportedVersionException.m from [ae8969b353] to [6ae3ab9f48].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFWaitForConditionFailedException.h from [a1e587c621] to [9d943d52d6].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFWaitForConditionFailedException.m from [e419f3f9dc] to [fde9e1c16a].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFWriteFailedException.h from [6dee61073a] to [dc1c240c5b].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/exceptions/OFWriteFailedException.m from [1eca55cb4e] to [1f29864403].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Renamed and modified src/forwarding/apple-forwarding-x86_64.S [1324ab08b0] to src/forwarding/apple-forwarding-amd64.S [9954d86ee8].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/forwarding/apple-forwarding-arm.S from [638359a9cd] to [3ab429edb9].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/forwarding/apple-forwarding-arm64.S from [d2adf305f5] to [63e754588e].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/forwarding/apple-forwarding-powerpc.S from [8f7b914664] to [d8e9e96515].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Renamed and modified src/forwarding/apple-forwarding-i386.S [11f716a457] to src/forwarding/apple-forwarding-x86.S [d8d4e2afa9].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Renamed and modified src/forwarding/forwarding-x86_64-elf.S [9ea0cb41b3] to src/forwarding/forwarding-amd64-elf.S [3465a8f0c9].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
216
217
218
219
220
221
222
223

224
225
216
217
218
219
220
221
222

223
224
225







-
+


	.quad 0, sel_forwardingTargetForSelector_
	.short 0, 0
	.long 0
	.quad 0
module:
	.quad 8, 32, 0, symtab

#ifdef OF_LINUX
#if defined(OF_LINUX) || defined(OF_HURD)
.section .note.GNU-stack, "", %progbits
#endif

Renamed and modified src/forwarding/forwarding-x86_64-macho.S [0e975fcfd2] to src/forwarding/forwarding-amd64-macho.S [3f0c2bdab8].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Renamed and modified src/forwarding/forwarding-x86_64-win64.S [74c1db404c] to src/forwarding/forwarding-amd64-win64.S [ae09f773a9].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/forwarding/forwarding-arm-elf.S from [ebb3f926fa] to [bde319f807].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
164
165
166
167
168
169
170
171

172
173
164
165
166
167
168
169
170

171
172
173







-
+


	.long 0, sel_forwardingTargetForSelector_
	.short 0, 0
	.long 0
	.long 0
module:
	.long 8, 16, 0, symtab

#ifdef OF_LINUX
#if defined(OF_LINUX) || defined(OF_HURD)
.section .note.GNU-stack, "", %progbits
#endif

Modified src/forwarding/forwarding-arm64-elf.S from [81775de57c] to [82ae5367bb].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
122
123
124
125
126
127
128
129

130
131
122
123
124
125
126
127
128

129
130
131







-
+


	.xword 0, sel_forwardingTargetForSelector_
	.short 0, 0
	.long 4
	.xword 0
module:
	.xword 8, 32, 0, symtab

#ifdef OF_LINUX
#if defined(OF_LINUX) || defined(OF_HURD)
.section .note.GNU-stack, "", %progbits
#endif

Modified src/forwarding/forwarding-mips-elf.S from [e03d5d5039] to [7bd6ca0e97].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
320
321
322
323
324
325
326
327

328
329
320
321
322
323
324
325
326

327
328
329







-
+


	.long 0, sel_forwardingTargetForSelector_
	.short 0, 0
	.long 0
	.long 0
module:
	.long 8, 16, 0, symtab

#ifdef OF_LINUX
#if defined(OF_LINUX) || defined(OF_HURD)
.section .note.GNU-stack, "", %progbits
#endif

Modified src/forwarding/forwarding-powerpc-elf.S from [65258e67de] to [744c6a3cb8].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
353
354
355
356
357
358
359
360

361
362
353
354
355
356
357
358
359

360
361
362







-
+


	.long sel_forwardingTargetForSelector_
.Lgot_OFMethodNotFound:
	.long OFMethodNotFound
.Lgot_OFMethodNotFound_stret:
	.long OFMethodNotFound_stret
#endif

#ifdef OF_LINUX
#if defined(OF_LINUX) || defined(OF_HURD)
.section .note.GNU-stack, "", @progbits
#endif

Modified src/forwarding/forwarding-sparc-elf.S from [8ec3e64b89] to [88387a31bb].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
186
187
188
189
190
191
192
193

194
195
186
187
188
189
190
191
192

193
194
195







-
+


	.word 0, sel_forwardingTargetForSelector_
	.half 0, 0
	.word 0
	.word 0
module:
	.word 8, 16, 0, symtab

#ifdef OF_LINUX
#if defined(OF_LINUX) || defined(OF_HURD)
.section .note.GNU-stack, "", %progbits
#endif

Modified src/forwarding/forwarding-sparc64-elf.S from [5ae72e6aac] to [591e0b9534].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
246
247
248
249
250
251
252
253

254
255
246
247
248
249
250
251
252

253
254
255







-
+


	.xword 0, sel_forwardingTargetForSelector_
	.half 0, 0
	.word 0
	.xword 0
module:
	.xword 8, 32, 0, symtab

#ifdef OF_LINUX
#if defined(OF_LINUX) || defined(OF_HURD)
.section .note.GNU-stack, "", %progbits
#endif

Modified src/forwarding/forwarding-x86-elf.S from [a55d3f40d7] to [8e73449724].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
24
25
26
27
28
29
30
31

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

31
32
33
34
35
36
37
38







-
+







OFForward:
	pushl	%ebp
	movl	%esp, %ebp

	pushl	%ebx
	subl	$20, %esp

	call	get_eip
	call	getEIP
	addl	$_GLOBAL_OFFSET_TABLE_, %ebx

	movl	8(%ebp), %eax
	movl	%eax, (%esp)
	call	object_getClass@PLT

	movl	%eax, (%esp)
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
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







-
+
















-
+







	addl	$20, %esp
	popl	%ebx
	popl	%ebp

	jmp	*%eax

0:
	leal	OFMethodNotFound@GOTOFF(%ebx), %eax
	movl	OFMethodNotFound@GOT(%ebx), %eax

	addl	$20, %esp
	popl	%ebx
	popl	%ebp

	jmp	*%eax
.type OFForward, %function
.size OFForward, .-OFForward

OFForward_stret:
	pushl	%ebp
	movl	%esp, %ebp

	pushl	%ebx
	subl	$20, %esp

	call	get_eip
	call	getEIP
	addl	$_GLOBAL_OFFSET_TABLE_, %ebx

	movl	12(%ebp), %eax
	movl	%eax, (%esp)
	call	object_getClass@PLT

	movl	%eax, (%esp)
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
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







-
+
















-
+











-
+







	addl	$20, %esp
	popl	%ebx
	popl	%ebp

	jmp	*%eax

0:
	leal	OFMethodNotFound_stret@GOTOFF(%ebx), %eax
	movl	OFMethodNotFound_stret@GOT(%ebx), %eax

	addl	$20, %esp
	popl	%ebx
	popl	%ebp

	jmp	*%eax
.type OFForward_stret, %function
.size OFForward_stret, .-OFForward_stret

init:
	pushl	%ebp
	movl	%esp, %ebp

	pushl	%ebx
	subl	$4, %esp

	call	get_eip
	call	getEIP
	addl	$_GLOBAL_OFFSET_TABLE_, %ebx

	leal	module@GOTOFF(%ebx), %eax
	movl	%eax, (%esp)
	call	__objc_exec_class@PLT

	addl	$4, %esp
	popl	%ebx
	popl	%ebp
	ret

get_eip:
getEIP:
	movl	(%esp), %ebx
	ret

#ifdef OF_SOLARIS
.section .init_array, "aw"
#else
.section .ctors, "aw", %progbits
191
192
193
194
195
196
197
198

199
200
191
192
193
194
195
196
197

198
199
200







-
+


	.long 0, sel_forwardingTargetForSelector_
	.short 0, 0
	.long 0
	.long 0
module:
	.long 8, 16, 0, symtab

#ifdef OF_LINUX
#if defined(OF_LINUX) || defined(OF_HURD)
.section .note.GNU-stack, "", %progbits
#endif

Modified src/forwarding/forwarding-x86-win32.S from [7c90db9737] to [ad61e372be].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/forwarding/forwarding.S from [0a5e45dea8] to [2a272f6c14].

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
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

-
+


















-
-
+
+

-
+









-
-
+
+
















-
-
+
+


-
-
+
+





/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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"

#include "platform.h"

#ifdef OF_APPLE_RUNTIME
# if defined(OF_X86_64)
#  include "apple-forwarding-x86_64.S"
# if defined(OF_AMD64)
#  include "apple-forwarding-amd64.S"
# elif defined(OF_X86)
#  include "apple-forwarding-i386.S"
#  include "apple-forwarding-x86.S"
# elif defined(OF_ARM64)
#  include "apple-forwarding-arm64.S"
# elif defined(OF_ARM)
#  include "apple-forwarding-arm.S"
# elif defined(OF_POWERPC)
#  include "apple-forwarding-powerpc.S"
# endif
#else
# if defined(OF_ELF)
#  if defined(OF_X86_64)
#   include "forwarding-x86_64-elf.S"
#  if defined(OF_AMD64)
#   include "forwarding-amd64-elf.S"
#  elif defined(OF_X86)
#   include "forwarding-x86-elf.S"
#  elif defined(OF_ARM64)
#   include "forwarding-arm64-elf.S"
#  elif defined(OF_ARM)
#   include "forwarding-arm-elf.S"
#  elif defined(OF_POWERPC)
#   include "forwarding-powerpc-elf.S"
#  elif defined(OF_MIPS)
#   include "forwarding-mips-elf.S"
#  elif defined(OF_SPARC64)
#   include "forwarding-sparc64-elf.S"
#  elif defined(OF_SPARC)
#   include "forwarding-sparc-elf.S"
#  endif
# elif defined(OF_MACH_O)
#  if defined(OF_X86_64)
#   include "forwarding-x86_64-macho.S"
#  if defined(OF_AMD64)
#   include "forwarding-amd64-macho.S"
#  endif
# elif defined(OF_WINDOWS)
#  if defined(OF_X86_64)
#   include "forwarding-x86_64-win64.S"
#  if defined(OF_AMD64)
#   include "forwarding-amd64-win64.S"
#  elif defined(OF_X86)
#   include "forwarding-x86-win32.S"
#  endif
# endif
#endif

Modified src/libbases.m from [295705f47a] to [c35b640cb7].

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
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

-
+















+

+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#define Class IntuitionClass
#include <proto/exec.h>
#undef Class

#import "OFInitializationFailedException.h"

#import "macros.h"

#ifdef OF_COMPILING_AMIGA_LIBRARY
struct Library *DOSBase;

Modified src/macros.h from [20d23907ce] to [f7fda82d09].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
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
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







-
+






-
+








-
+






-
+







#ifdef OF_COMPILING_AMIGA_LIBRARY
# undef errno
extern int *_Nonnull OFErrNo(void);
# define errno (*OFErrNo())
#endif

#ifdef OF_APPLE_RUNTIME
# if defined(OF_X86_64) || defined(OF_X86) || defined(OF_ARM64) || \
# if defined(OF_AMD64) || defined(OF_X86) || defined(OF_ARM64) || \
    defined(OF_ARM) || defined(OF_POWERPC)
#  define OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR
#  define OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR_STRET
# endif
#else
# if defined(OF_ELF)
#  if defined(OF_X86_64) || defined(OF_X86) || \
#  if defined(OF_AMD64) || defined(OF_X86) || \
    defined(OF_ARM64) || defined(OF_ARM) || defined(OF_POWERPC) || \
    defined(OF_MIPS) || defined(OF_SPARC64) || defined(OF_SPARC)
#   define OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR
#   if __OBJFW_RUNTIME_ABI__ >= 800
#    define OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR_STRET
#   endif
#  endif
# elif defined(OF_MACH_O)
#  if defined(OF_X86_64)
#  if defined(OF_AMD64)
#   define OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR
#   if __OBJFW_RUNTIME_ABI__ >= 800
#    define OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR_STRET
#   endif
#  endif
# elif defined(OF_WINDOWS)
#  if defined(OF_X86_64) || defined(OF_X86)
#  if defined(OF_AMD64) || defined(OF_X86)
#   define OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR
#   if __OBJFW_RUNTIME_ABI__ >= 800
#    define OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR_STRET
#   endif
#  endif
# endif
#endif
452
453
454
455
456
457
458
459

460
461
462
463
464
465
466
452
453
454
455
456
457
458

459
460
461
462
463
464
465
466







-
+







}

static OF_INLINE uint16_t OF_CONST_FUNC
OFByteSwap16NonConst(uint16_t i)
{
#if defined(OF_HAVE_BUILTIN_BSWAP16)
	return __builtin_bswap16(i);
#elif (defined(OF_X86_64) || defined(OF_X86)) && defined(__GNUC__)
#elif (defined(OF_AMD64) || defined(OF_X86)) && defined(__GNUC__)
	__asm__ (
	    "xchgb	%h0, %b0"
	    : "=Q"(i)
	    : "0"(i)
	);
#elif defined(OF_POWERPC) && defined(__GNUC__)
	__asm__ (
482
483
484
485
486
487
488
489

490
491
492
493
494
495
496
482
483
484
485
486
487
488

489
490
491
492
493
494
495
496







-
+







}

static OF_INLINE uint32_t OF_CONST_FUNC
OFByteSwap32NonConst(uint32_t i)
{
#if defined(OF_HAVE_BUILTIN_BSWAP32)
	return __builtin_bswap32(i);
#elif (defined(OF_X86_64) || defined(OF_X86)) && defined(__GNUC__)
#elif (defined(OF_AMD64) || defined(OF_X86)) && defined(__GNUC__)
	__asm__ (
	    "bswap	%0"
	    : "=q"(i)
	    : "0"(i)
	);
#elif defined(OF_POWERPC) && defined(__GNUC__)
	__asm__ (
514
515
516
517
518
519
520
521

522
523
524
525
526
527
528
514
515
516
517
518
519
520

521
522
523
524
525
526
527
528







-
+







}

static OF_INLINE uint64_t OF_CONST_FUNC
OFByteSwap64NonConst(uint64_t i)
{
#if defined(OF_HAVE_BUILTIN_BSWAP64)
	return __builtin_bswap64(i);
#elif defined(OF_X86_64) && defined(__GNUC__)
#elif defined(OF_AMD64) && defined(__GNUC__)
	__asm__ (
	    "bswap	%0"
	    : "=r"(i)
	    : "0"(i)
	);
#elif defined(OF_X86) && defined(__GNUC__)
	__asm__ (

Modified src/objfw-defs.h.in from [281bf4782f] to [5a8629e6a6].

1
2

3
4
5
6
7
8
9
1
2
3
4
5
6
7
8
9
10


+







#undef OF_APPLE_RUNTIME
#undef OF_BIG_ENDIAN
#undef OF_CLASSIC_MACOS
#undef OF_FLOAT_BIG_ENDIAN
#undef OF_HAVE_AFUNIX_H
#undef OF_HAVE_APPLETALK
#undef OF_HAVE_ATOMIC_BUILTINS
#undef OF_HAVE_ATOMIC_OPS
#undef OF_HAVE_BUILTIN_BSWAP16
#undef OF_HAVE_BUILTIN_BSWAP32
27
28
29
30
31
32
33

34
35
36
37
38
39
40
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42







+







#undef OF_HAVE_PIPE
#undef OF_HAVE_PLEDGE
#undef OF_HAVE_PLUGINS
#undef OF_HAVE_PTHREADS
#undef OF_HAVE_PTHREAD_SPINLOCKS
#undef OF_HAVE_RECURSIVE_PTHREAD_MUTEXES
#undef OF_HAVE_SCHED_YIELD
#undef OF_HAVE_SOCKADDR_STORAGE
#undef OF_HAVE_SOCKETS
#undef OF_HAVE_STDNORETURN
#undef OF_HAVE_SUBPROCESSES
#undef OF_HAVE_SYMLINK
#undef OF_HAVE_SYNC_BUILTINS
#undef OF_HAVE_SYS_SOCKET_H
#undef OF_HAVE_SYS_TYPES_H

Modified src/platform.h from [927be68827] to [d6a36db1b5].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
22
23
24
25
26
27
28
29

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

29
30
31
32
33
34
35
36







-
+







#  define OF_FLOAT_BIG_ENDIAN
# elif !__LITTLE_ENDIAN__
#  error OF_UNIVERSAL defined, but neither __BIG_ENDIAN__ nor __LITTLE_ENDIAN__!
# endif
#endif

#if defined(__x86_64__) || defined(__amd64__)
# define OF_X86_64
# define OF_AMD64
#elif defined(__i386__)
# define OF_X86
#elif defined(__powerpc64__) || defined(__ppc64__) || defined(__PPC64__)
# define OF_POWERPC64
#elif defined(__powerpc__) || defined(__ppc__) || defined(__PPC__)
# define OF_POWERPC
#elif defined(__arm64__) || defined(__aarch64__) || defined(__ARM64_ARCH_8__)
147
148
149
150
151
152
153






154
155
156
157
158
159
160
161
162
163
164
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170







+
+
+
+
+
+











#elif defined(__DJGPP__)
# define OF_DJGPP
# define OF_MSDOS
#elif defined(__riscos__)
# define OF_ACORN_RISC_OS
#elif defined(__MINT__)
# define OF_MINT
#elif defined(__gnu_hurd__)
# define OF_HURD
#endif

#ifdef __GLIBC__
# define OF_GLIBC
#endif

#if defined(__ELF__)
# define OF_ELF
#elif defined(__MACH__)
# define OF_MACH_O
#endif

#if defined(__PIC__) || defined(__pic__)
# define OF_PIC
#endif

Modified src/platform/AmigaOS/OFPlainCondition.m from [b17297ed32] to [adff92d333].

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
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

-
+



















+





+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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"

#include <errno.h>

#import "OFPlainCondition.h"

#define Class IntuitionClass
#include <proto/exec.h>
#include <devices/timer.h>
#ifndef OF_AMIGAOS4
# include <clib/alib_protos.h>
#endif
#undef Class

int
OFPlainConditionNew(OFPlainCondition *condition)
{
	condition->waitingTasks = NULL;

	return 0;

Modified src/platform/AmigaOS/OFPlainMutex.m from [635aa59c59] to [c178d9a4d1].

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
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

-
+



















+

+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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"

#include <errno.h>

#import "OFPlainMutex.h"

#define Class IntuitionClass
#include <proto/exec.h>
#undef Class

int
OFPlainMutexNew(OFPlainMutex *mutex)
{
	InitSemaphore(mutex);

	return 0;

Modified src/platform/AmigaOS/OFPlainThread.m from [b331f7b6f5] to [764b8104d2].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
18
19
20
21
22
23
24

25
26
27

28
29
30
31
32
33
34
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36







+



+







#include <errno.h>

#import "OFPlainThread.h"
#import "OFData.h"
#import "OFString.h"
#import "OFTLSKey.h"

#define Class IntuitionClass
#include <dos/dostags.h>
#include <proto/dos.h>
#include <proto/exec.h>
#undef Class

#ifndef OF_MORPHOS
extern void OFTLSKeyThreadExited(void);
#endif
static OFTLSKey threadKey;

OF_CONSTRUCTOR()

Modified src/platform/AmigaOS/OFString+PathAdditions.m from [60752aa5d1] to [afe1214925].

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
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

-
+

















-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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 "OFString+PathAdditions.h"
#import "OFArray.h"
#import "OFFileURIHandler.h"
#import "OFFileIRIHandler.h"

#import "OFOutOfRangeException.h"

int _OFString_PathAdditions_reference;

@implementation OFString (PathAdditions)
+ (OFString *)pathWithComponents: (OFArray *)components
289
290
291
292
293
294
295
296

297
298
299

300
301
302
303
304
305
306
289
290
291
292
293
294
295

296
297
298

299
300
301
302
303
304
305
306







-
+


-
+







	} else
		return [self stringByAppendingFormat: @".%@", extension];
}

- (bool)of_isDirectoryPath
{
	return ([self hasSuffix: @"/"] || [self hasSuffix: @":"] ||
	    [OFFileURIHandler of_directoryExistsAtPath: self]);
	    [OFFileIRIHandler of_directoryExistsAtPath: self]);
}

- (OFString *)of_pathToURIPathWithPercentEncodedHost:
- (OFString *)of_pathToIRIPathWithPercentEncodedHost:
    (OFString **)percentEncodedHost
{
	OFArray OF_GENERIC(OFString *) *components = self.pathComponents;
	OFMutableString *ret = [OFMutableString string];

	for (OFString *component in components) {
		if (component.length == 0)
315
316
317
318
319
320
321
322

323
324
325
326
327
328
329
315
316
317
318
319
320
321

322
323
324
325
326
327
328
329







-
+







	}

	[ret makeImmutable];

	return ret;
}

- (OFString *)of_URIPathToPathWithPercentEncodedHost:
- (OFString *)of_IRIPathToPathWithPercentEncodedHost:
    (OFString *)percentEncodedHost
{
	OFString *path = self;

	if (path.length > 1 && [path hasSuffix: @"/"])
		path = [path substringToIndex: path.length - 1];

349
350
351
352
353
354
355
356

357
358
359
360
349
350
351
352
353
354
355

356
357
358
359
360







-
+




		if ([component isEqual: @".."])
			[components replaceObjectAtIndex: i withObject: @"/"];
	}

	return [OFString pathWithComponents: components];
}

- (OFString *)of_pathComponentToURIPathComponent
- (OFString *)of_pathComponentToIRIPathComponent
{
	return self;
}
@end

Modified src/platform/AmigaOS/OFTLSKey.m from [7115be10da] to [a12f7662fd].

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
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

-
+

















+


+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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 "OFTLSKey.h"

#define Class IntuitionClass
#include <exec/semaphores.h>
#include <proto/exec.h>
#undef Class

/*
 * As we use this file in both the runtime and ObjFW, and since AmigaOS always
 * has the runtime, use the hashtable from the runtime.
 */
#import "runtime/private.h"

Modified src/platform/GCC4.7/OFAtomic.h from [3a2198950d] to [383c86ffb9].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/platform/GCC4/OFAtomic.h from [46ae36c82b] to [44e663e978].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/platform/MorphOS/OFTLSKey.m from [f46c8d88c6] to [aee9f4378a].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/platform/POSIX/OFPlainCondition.m from [d0abcf1839] to [54b2ad82e7].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/platform/POSIX/OFPlainMutex.m from [bcf658e6be] to [41337b80a3].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/platform/POSIX/OFPlainThread.m from [7bbb313eb6] to [d1d5239270].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/platform/POSIX/OFString+PathAdditions.m from [d1f51523cf] to [0c2531bfb6].

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
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

-
+

















-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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 "OFString+PathAdditions.h"
#import "OFArray.h"
#import "OFFileURIHandler.h"
#import "OFFileIRIHandler.h"

#import "OFOutOfRangeException.h"

int _OFString_PathAdditions_reference;

@implementation OFString (PathAdditions)
+ (OFString *)pathWithComponents: (OFArray *)components
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
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







-
+


-
+





-
+










-
+




	} else
		return [self stringByAppendingFormat: @".%@", extension];
}

- (bool)of_isDirectoryPath
{
	return ([self hasSuffix: @"/"] ||
	    [OFFileURIHandler of_directoryExistsAtPath: self]);
	    [OFFileIRIHandler of_directoryExistsAtPath: self]);
}

- (OFString *)of_pathToURIPathWithPercentEncodedHost:
- (OFString *)of_pathToIRIPathWithPercentEncodedHost:
    (OFString **)percentEncodedHost
{
	return self;
}

- (OFString *)of_URIPathToPathWithPercentEncodedHost:
- (OFString *)of_IRIPathToPathWithPercentEncodedHost:
    (OFString *)percentEncodedHost
{
	OFString *path = self;

	if (path.length > 1 && [path hasSuffix: @"/"])
		path = [path substringToIndex: path.length - 1];

	return path;
}

- (OFString *)of_pathComponentToURIPathComponent
- (OFString *)of_pathComponentToIRIPathComponent
{
	return self;
}
@end

Modified src/platform/POSIX/OFSubprocess.m from [9ff417c581] to [bb0f04408f].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
37
38
39
40
41
42
43
44

45
46
47
48
49
50
51
37
38
39
40
41
42
43

44
45
46
47
48
49
50
51







-
+








#import "OFInitializationFailedException.h"
#import "OFNotOpenException.h"
#import "OFOutOfRangeException.h"
#import "OFReadFailedException.h"
#import "OFWriteFailedException.h"

#ifndef HAVE_POSIX_SPAWNP
#if !defined(HAVE_POSIX_SPAWNP) || !defined(HAVE_SPAWN_H)
extern char **environ;
#endif

@interface OFSubprocess ()
- (void)of_getArgv: (char ***)argv
    forProgramName: (OFString *)programName
      andArguments: (OFArray *)arguments;
139
140
141
142
143
144
145
146

147
148
149
150
151
152
153
139
140
141
142
143
144
145

146
147
148
149
150
151
152
153







-
+







		path = [program cStringWithEncoding: [OFLocale encoding]];
		[self of_getArgv: &argv
		  forProgramName: programName
		    andArguments: arguments];

		@try {
			env = [self of_environmentForDictionary: environment];
#ifdef HAVE_POSIX_SPAWNP
#if defined(HAVE_POSIX_SPAWNP) && defined(HAVE_SPAWN_H)
			posix_spawn_file_actions_t actions;
			posix_spawnattr_t attr;

			if (posix_spawn_file_actions_init(&actions) != 0)
				@throw [OFInitializationFailedException
				    exceptionWithClass: self.class];

Added src/platform/POSIX/OFSystemInfo+NetworkInterfaces.m version [5833caf501].


































































































































































































































































































































































































































































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
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
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
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
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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"

#ifdef HAVE_SYS_IOCTL_H
# include <sys/ioctl.h>
#endif
#ifdef OF_HAVE_SYS_SOCKET_H
# include <sys/socket.h>
#endif
#ifdef HAVE_NET_IF_H
# include <net/if.h>
#endif
#ifdef HAVE_NET_IF_ARP_H
# include <net/if_arp.h>
#endif
#ifdef HAVE_NET_IF_DL_H
# include <net/if_dl.h>
#endif
#ifdef HAVE_NET_IF_TYPES_H
# include <net/if_types.h>
#endif

#import "OFSystemInfo.h"
#import "OFSystemInfo+NetworkInterfaces.h"
#import "OFArray.h"
#import "OFData.h"
#import "OFDictionary.h"
#ifdef OF_HAVE_FILES
 #import "OFFile.h"
#endif
#import "OFLocale.h"
#import "OFNumber.h"
#import "OFSocket.h"
#import "OFSocket+Private.h"
#import "OFString.h"

#import "OFInvalidFormatException.h"
#import "OFOpenItemFailedException.h"

@implementation OFSystemInfo (NetworkInterfaces)
static bool
queryNetworkInterfaceIndices(OFMutableDictionary *ret)
{
#ifdef HAVE_IF_NAMEINDEX
	OFStringEncoding encoding = [OFLocale encoding];
	struct if_nameindex *nameindex = if_nameindex();

	if (nameindex == NULL)
		return false;

	@try {
		for (size_t i = 0; nameindex[i].if_index != 0; i++) {
			OFString *name = [OFString
			    stringWithCString: nameindex[i].if_name
				     encoding: encoding];
			OFNumber *index = [OFNumber
			    numberWithUnsignedInt: nameindex[i].if_index];
			OFMutableDictionary *interface =
			    [ret objectForKey: name];

			if (interface == nil) {
				interface = [OFMutableDictionary dictionary];
				[ret setObject: interface forKey: name];
			}

			[interface setObject: index
				      forKey: OFNetworkInterfaceIndex];
		}
	} @finally {
		if_freenameindex(nameindex);
	}

	return true;
#else
	return false;
#endif
}

#if defined(HAVE_IOCTL) && defined(HAVE_NET_IF_H)
static bool
queryNetworkInterfaceAddresses(OFMutableDictionary *ret,
    OFNetworkInterfaceKey key, OFSocketAddressFamily addressFamily, int family,
    size_t sockaddrSize)
{
	OFStringEncoding encoding = [OFLocale encoding];
	int sock = socket(family, SOCK_DGRAM, 0);
	struct ifconf ifc;
	struct ifreq *ifrs;
	OFMutableDictionary *interface;
	OFEnumerator *enumerator;

	if (sock < 0)
		return false;

	ifrs = malloc(128 * sizeof(struct ifreq));
	if (ifrs == NULL) {
		closesocket(sock);
		return false;
	}

	@try {
		char *buffer;

		memset(&ifc, 0, sizeof(ifc));
		ifc.ifc_buf = (void *)ifrs;
		ifc.ifc_len = 128 * sizeof(struct ifreq);
		if (ioctl(sock, SIOCGIFCONF, &ifc) < 0)
			return false;

		buffer = ifc.ifc_buf;
		while (buffer < (char *)ifc.ifc_buf + ifc.ifc_len) {
			struct ifreq *current = (struct ifreq *)(void *)buffer;
			OFString *name;
			OFMutableData *addresses;
			OFSocketAddress address;

			if (current->ifr_addr.sa_family != family)
				goto next;

			name = [OFString stringWithCString: current->ifr_name
						  encoding: encoding];
			if ((interface = [ret objectForKey: name]) == nil) {
				interface = [OFMutableDictionary dictionary];
				[ret setObject: interface forKey: name];
			}

			addresses = [interface objectForKey: key];
			if (addresses == nil) {
				addresses = [OFMutableData
				    dataWithItemSize: sizeof(OFSocketAddress)];
				[interface setObject: addresses forKey: key];
			}

			memset(&address, 0, sizeof(address));
			address.family = addressFamily;
			memcpy(&address.sockaddr.in, &current->ifr_addr,
			    sockaddrSize);

			[addresses addItem: &address];

next:
# ifdef _SIZEOF_ADDR_IFREQ
			buffer += _SIZEOF_ADDR_IFREQ(*current);
# else
			buffer += sizeof(struct ifreq);
# endif
		}
	} @finally {
		free(ifrs);
		closesocket(sock);
	}

	enumerator = [ret objectEnumerator];
	while ((interface = [enumerator nextObject]) != nil)
		[[interface objectForKey: key] makeImmutable];

	return true;
}
#endif

static bool
queryNetworkInterfaceIPv4Addresses(OFMutableDictionary *ret)
{
#if defined(HAVE_IOCTL) && defined(HAVE_NET_IF_H)
	return queryNetworkInterfaceAddresses(ret,
	    OFNetworkInterfaceIPv4Addresses, OFSocketAddressFamilyIPv4,
	    AF_INET, sizeof(struct sockaddr_in));
#else
	return false;
#endif
}

#ifdef OF_HAVE_IPV6
static bool
queryNetworkInterfaceIPv6Addresses(OFMutableDictionary *ret)
{
# if defined(OF_LINUX) && defined(OF_HAVE_FILES)
	OFFile *file;
	OFString *line;
	OFMutableDictionary *interface;
	OFEnumerator *enumerator;

	@try {
		file = [OFFile fileWithPath: @"/proc/net/if_inet6" mode: @"r"];
	} @catch (OFOpenItemFailedException *e) {
		return false;
	}

	while ((line = [file readLine]) != nil) {
		OFArray *components = [line
		    componentsSeparatedByString: @" "
					options: OFStringSkipEmptyComponents];
		OFString *addressString, *name;
		OFSocketAddress address;
		OFMutableData *addresses;

		if (components.count < 6)
			continue;

		addressString = [components objectAtIndex: 0];
		name = [components objectAtIndex: 5];

		if (addressString.length != 32)
			continue;

		if ((interface = [ret objectForKey: name]) == nil) {
			interface = [OFMutableDictionary dictionary];
			[ret setObject: interface forKey: name];
		}

		memset(&address, 0, sizeof(address));
		address.family = OFSocketAddressFamilyIPv6;

		for (size_t i = 0; i < 32; i += 2) {
			unsigned long long byte;

			@try {
				byte = [[addressString
				    substringWithRange: OFMakeRange(i, 2)]
				    unsignedLongLongValueWithBase: 16];
			} @catch (OFInvalidFormatException *e) {
				goto next_line;
			}

			if (byte > 0xFF)
				goto next_line;

			address.sockaddr.in6.sin6_addr.s6_addr[i / 2] =
			    (unsigned char)byte;
		}

		if ((addresses = [interface
		    objectForKey: OFNetworkInterfaceIPv6Addresses]) == nil) {
			addresses = [OFMutableData
			    dataWithItemSize: sizeof(OFSocketAddress)];
			[interface setObject: addresses
				      forKey: OFNetworkInterfaceIPv6Addresses];
		}

		[addresses addItem: &address];

next_line:
		continue;
	}

	enumerator = [ret objectEnumerator];
	while ((interface = [enumerator nextObject]) != nil)
		[[interface objectForKey: OFNetworkInterfaceIPv6Addresses]
		    makeImmutable];

	return false;
# elif defined(HAVE_IOCTL) && defined(HAVE_NET_IF_H)
	return queryNetworkInterfaceAddresses(ret,
	    OFNetworkInterfaceIPv6Addresses, OFSocketAddressFamilyIPv6,
	    AF_INET6, sizeof(struct sockaddr_in6));
# else
	return false;
# endif
}
#endif

#ifdef OF_HAVE_IPX
static bool
queryNetworkInterfaceIPXAddresses(OFMutableDictionary *ret)
{
# if defined(HAVE_IOCTL) && defined(HAVE_NET_IF_H)
	return queryNetworkInterfaceAddresses(ret,
	    OFNetworkInterfaceIPXAddresses, OFSocketAddressFamilyIPX,
	    AF_IPX, sizeof(struct sockaddr_ipx));
# else
	return false;
# endif
}
#endif

#ifdef OF_HAVE_APPLETALK
static bool
queryNetworkInterfaceAppleTalkAddresses(OFMutableDictionary *ret)
{
# if defined(HAVE_IOCTL) && defined(HAVE_NET_IF_H)
	return queryNetworkInterfaceAddresses(ret,
	    OFNetworkInterfaceAppleTalkAddresses,
	    OFSocketAddressFamilyAppleTalk, AF_APPLETALK,
	    sizeof(struct sockaddr_at));
# else
	return false;
# endif
}
#endif

static bool
queryNetworkInterfaceHardwareAddress(OFMutableDictionary *ret)
{
#if defined(HAVE_IOCTL) && defined(HAVE_NET_IF_H) && defined(SIOCGIFHWADDR)
	OFStringEncoding encoding = [OFLocale encoding];
	int sock = socket(AF_INET, SOCK_DGRAM, 0);

	if (sock < 0)
		return false;

	for (OFString *name in ret) {
		size_t nameLength = [name cStringLengthWithEncoding: encoding];
		struct ifreq ifr;
		OFData *hardwareAddress;

		if (nameLength > IFNAMSIZ)
			continue;

		memset(&ifr, 0, sizeof(ifr));
		memcpy(&ifr.ifr_name, [name cStringWithEncoding: encoding],
		    nameLength);

		if (ioctl(sock, SIOCGIFHWADDR, &ifr) < 0)
			continue;

		if (ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER)
			continue;

		hardwareAddress = [OFData dataWithItems: ifr.ifr_hwaddr.sa_data
						  count: 6];
		[[ret objectForKey: name]
		    setObject: hardwareAddress
		       forKey: OFNetworkInterfaceHardwareAddress];
	}

	return true;
#elif defined(HAVE_IOCTL) && defined(HAVE_NET_IF_H) && \
    defined(HAVE_STRUCT_SOCKADDR_DL)
	OFStringEncoding encoding = [OFLocale encoding];
	int sock = socket(AF_INET, SOCK_DGRAM, 0);
	struct ifconf ifc;
	struct ifreq *ifrs;

	if (sock < 0)
		return false;

	ifrs = malloc(128 * sizeof(struct ifreq));
	if (ifrs == NULL) {
		closesocket(sock);
		return false;
	}

	@try {
		char *buffer;

		memset(&ifc, 0, sizeof(ifc));
		ifc.ifc_buf = (void *)ifrs;
		ifc.ifc_len = 128 * sizeof(struct ifreq);
		if (ioctl(sock, SIOCGIFCONF, &ifc) < 0)
			return false;

		buffer = ifc.ifc_buf;
		while (buffer < (char *)ifc.ifc_buf + ifc.ifc_len) {
			struct ifreq *current = (struct ifreq *)(void *)buffer;
			struct sockaddr_dl *sdl;
			OFString *name;
			OFMutableDictionary *interface;
			OFData *hardwareAddress;

			if (current->ifr_addr.sa_family != AF_LINK)
				goto next;

			sdl = (struct sockaddr_dl *)(void *)&current->ifr_addr;
			if (sdl->sdl_type != IFT_ETHER)
				goto next;

			name = [OFString stringWithCString: current->ifr_name
						  encoding: encoding];
			if ((interface = [ret objectForKey: name]) == nil) {
				interface = [OFMutableDictionary dictionary];
				[ret setObject: interface forKey: name];
			}

			hardwareAddress = [OFData dataWithItems: LLADDR(sdl)
							  count: sdl->sdl_alen];
			[interface
			    setObject: hardwareAddress
			       forKey: OFNetworkInterfaceHardwareAddress];

next:
# ifdef _SIZEOF_ADDR_IFREQ
			buffer += _SIZEOF_ADDR_IFREQ(*current);
# else
			buffer += sizeof(struct ifreq);
# endif
		}
	} @finally {
		free(ifrs);
		closesocket(sock);
	}

	return true;
#else
	return false;
#endif
}

+ (OFDictionary OF_GENERIC(OFString *, OFNetworkInterface) *)networkInterfaces
{
	void *pool = objc_autoreleasePoolPush();
	OFMutableDictionary *ret = [OFMutableDictionary dictionary];
	bool success = false;
	OFEnumerator *enumerator;
	OFMutableDictionary *interface;

	success |= queryNetworkInterfaceIndices(ret);
	success |= queryNetworkInterfaceIPv4Addresses(ret);
#ifdef OF_HAVE_IPV6
	success |= queryNetworkInterfaceIPv6Addresses(ret);
#endif
#ifdef OF_HAVE_IPX
	success |= queryNetworkInterfaceIPXAddresses(ret);
#endif
#ifdef OF_HAVE_APPLETALK
	success |= queryNetworkInterfaceAppleTalkAddresses(ret);
#endif
	success |= queryNetworkInterfaceHardwareAddress(ret);

	if (!success) {
		objc_autoreleasePoolPop(pool);
		return nil;
	}

	enumerator = [ret objectEnumerator];
	while ((interface = [enumerator nextObject]) != nil)
		[interface makeImmutable];

	[ret makeImmutable];
	[ret retain];

	objc_autoreleasePoolPop(pool);

	return [ret autorelease];
}
@end

Modified src/platform/POSIX/OFTLSKey.m from [e854931fa2] to [85c5aab083].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/platform/PowerPC/OFAtomic.h from [d8964b5a28] to [70aa2844b9].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/platform/Windows/OFPlainCondition.m from [cd952f15d7] to [4a7403c948].

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
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

-
+


















+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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"

#include <errno.h>

#import "OFPlainCondition.h"
#import "OFConstantString.h"

#include <windows.h>

int
OFPlainConditionNew(OFPlainCondition *condition)
{
	condition->count = 0;

Modified src/platform/Windows/OFPlainMutex.m from [f924adddc3] to [27464a8886].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/platform/Windows/OFPlainThread.m from [d2bc6a9806] to [b7a41fe84f].

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
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

-
+


















-
-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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"

#include <errno.h>

#import "OFPlainThread.h"

#import "macros.h"
#import "OFConstantString.h"

#include <windows.h>

struct ThreadContext {
	void (*function)(id);
	id object;
};

Modified src/platform/Windows/OFString+PathAdditions.m from [ec08b34f89] to [b5ca306e27].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
18
19
20
21
22
23
24
25
26


27
28
29
30
31
32
33
18
19
20
21
22
23
24


25
26
27
28
29
30
31
32
33







-
-
+
+







 * Windows-specific parts!
 */

#include "config.h"

#import "OFString+PathAdditions.h"
#import "OFArray.h"
#import "OFFileURIHandler.h"
#import "OFURI.h"
#import "OFFileIRIHandler.h"
#import "OFIRI.h"

#import "OFInvalidFormatException.h"
#import "OFOutOfRangeException.h"

int _OFString_PathAdditions_reference;

@implementation OFString (PathAdditions)
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

375
376
377
378
379
380
381
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
375
376
377
378
379
380
381







-
+


-
+












-
+











-
+







	} else
		return [self stringByAppendingFormat: @".%@", extension];
}

- (bool)of_isDirectoryPath
{
	return ([self hasSuffix: @"\\"] || [self hasSuffix: @"/"] ||
	    [OFFileURIHandler of_directoryExistsAtPath: self]);
	    [OFFileIRIHandler of_directoryExistsAtPath: self]);
}

- (OFString *)of_pathToURIPathWithPercentEncodedHost:
- (OFString *)of_pathToIRIPathWithPercentEncodedHost:
    (OFString **)percentEncodedHost
{
	OFString *path = self;

	if ([path hasPrefix: @"\\\\"]) {
		OFArray *components = path.pathComponents;

		if (components.count < 2)
			@throw [OFInvalidFormatException exception];

		*percentEncodedHost = [[components objectAtIndex: 1]
		     stringByAddingPercentEncodingWithAllowedCharacters:
		     [OFCharacterSet URIHostAllowedCharacterSet]];
		     [OFCharacterSet IRIHostAllowedCharacterSet]];
		path = [OFString pathWithComponents: [components
		    objectsInRange: OFMakeRange(2, components.count - 2)]];
	}

	path = [path stringByReplacingOccurrencesOfString: @"\\"
					       withString: @"/"];
	path = [@"/" stringByAppendingString: path];

	return path;
}

- (OFString *)of_URIPathToPathWithPercentEncodedHost:
- (OFString *)of_IRIPathToPathWithPercentEncodedHost:
    (OFString *)percentEncodedHost
{
	OFString *path = self;

	if (path.length > 1 && [path hasSuffix: @"/"] &&
	    ![path hasSuffix: @":/"])
		path = [path substringToIndex: path.length - 1];
394
395
396
397
398
399
400
401

402
403
404
405
406
394
395
396
397
398
399
400

401
402
403
404
405
406







-
+





			path = [OFString stringWithFormat: @"\\\\%@\\%@",
							   host, path];
	}

	return path;
}

- (OFString *)of_pathComponentToURIPathComponent
- (OFString *)of_pathComponentToIRIPathComponent
{
	return [self stringByReplacingOccurrencesOfString: @"\\"
					       withString: @"/"];
}
@end

Modified src/platform/Windows/OFSubprocess.m from [bef5ba2521] to [a7d2548aa0].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Added src/platform/Windows/OFSystemInfo+NetworkInterfaces.m version [0c6d28d689].













































































































































































































































































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
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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 "OFSystemInfo.h"
#import "OFSystemInfo+NetworkInterfaces.h"
#import "OFData.h"
#import "OFDictionary.h"
#import "OFLocale.h"
#import "OFNumber.h"
#import "OFOnce.h"
#import "OFSocket.h"
#import "OFString.h"

#include <windows.h>
#define interface struct
#include <iphlpapi.h>
#undef interface

static WINAPI ULONG (*GetAdaptersAddressesFuncPtr)(ULONG, ULONG, PVOID,
    PIP_ADAPTER_ADDRESSES, PULONG);

static void
init(void)
{
	HMODULE module;

	if ((module = LoadLibrary("iphlpapi.dll")) != NULL)
		GetAdaptersAddressesFuncPtr = (WINAPI ULONG (*)(ULONG, ULONG,
		    PVOID, PIP_ADAPTER_ADDRESSES, PULONG))
		    GetProcAddress(module, "GetAdaptersAddresses");

}

static OFMutableDictionary OF_GENERIC(OFString *, OFNetworkInterface) *
networkInterfacesFromGetAdaptersAddresses(void)
{
	OFMutableDictionary *ret = [OFMutableDictionary dictionary];
	OFStringEncoding encoding = [OFLocale encoding];
	ULONG adapterAddressesSize = sizeof(IP_ADAPTER_ADDRESSES);
	PIP_ADAPTER_ADDRESSES adapterAddresses;

	if ((adapterAddresses = malloc(adapterAddressesSize)) == NULL)
		return nil;

	@try {
		ULONG error = GetAdaptersAddressesFuncPtr(AF_UNSPEC, 0, NULL,
		    adapterAddresses, &adapterAddressesSize);

		if (error == ERROR_BUFFER_OVERFLOW) {
			PIP_ADAPTER_ADDRESSES newAdapterAddresses =
			    realloc(adapterAddresses, adapterAddressesSize);

			if (newAdapterAddresses == NULL)
				return nil;

			adapterAddresses = newAdapterAddresses;
			error = GetAdaptersAddressesFuncPtr(AF_UNSPEC, 0, NULL,
			    adapterAddresses, &adapterAddressesSize);
		}

		if (error != ERROR_SUCCESS)
			return nil;

		for (PIP_ADAPTER_ADDRESSES iter = adapterAddresses;
		    iter != NULL; iter = iter->Next) {
			OFString *name;
			OFMutableDictionary *interface;
			OFNumber *index;

			name = [OFString stringWithCString: iter->AdapterName
						  encoding: encoding];

			if ((interface = [ret objectForKey: name]) == nil) {
				interface = [OFMutableDictionary dictionary];
				[ret setObject: interface forKey: name];
			}

			index = [OFNumber numberWithUnsignedInt: iter->IfIndex];
			[interface setObject: index
				      forKey: OFNetworkInterfaceIndex];

			if (iter->PhysicalAddressLength > 0) {
				const OFNetworkInterfaceKey key =
				    OFNetworkInterfaceHardwareAddress;
				OFData *address = [OFData
				    dataWithItems: iter->PhysicalAddress
					    count: iter->PhysicalAddressLength];
				[interface setObject: address forKey: key];
			}

			for (PIP_ADAPTER_UNICAST_ADDRESS_LH addrIter =
			    iter->FirstUnicastAddress; addrIter != NULL;
			    addrIter = addrIter->Next) {
				OFSocketAddress address;
				int length;
				OFNetworkInterfaceKey key;
				OFMutableData *addresses;

				length = (int)sizeof(address.sockaddr);
				if (length > addrIter->Address.iSockaddrLength)
					length =
					    addrIter->Address.iSockaddrLength;

				memset(&address, 0, sizeof(OFSocketAddress));
				memcpy(&address.sockaddr,
				    addrIter->Address.lpSockaddr,
				    (size_t)length);

				switch (address.sockaddr.in.sin_family) {
				case AF_INET:
					address.family =
					    OFSocketAddressFamilyIPv4;
					key = OFNetworkInterfaceIPv4Addresses;
					break;
				case AF_INET6:
					address.family =
					    OFSocketAddressFamilyIPv6;
					key = OFNetworkInterfaceIPv6Addresses;
					break;
				default:
					continue;
				}

				addresses = [interface objectForKey: key];
				if (addresses == nil) {
					addresses = [OFMutableData
					    dataWithItemSize:
					    sizeof(OFSocketAddress)];
					[interface setObject: addresses
						      forKey: key];
				}

				[addresses addItem: &address];
			}

			[[interface objectForKey:
			    OFNetworkInterfaceIPv4Addresses] makeImmutable];
			[[interface objectForKey:
			    OFNetworkInterfaceIPv6Addresses] makeImmutable];
		}
	} @finally {
		free(adapterAddresses);
	}

	return ret;
}

static OFMutableDictionary OF_GENERIC(OFString *, OFNetworkInterface) *
networkInterfacesFromGetAdaptersInfo(void)
{
	OFMutableDictionary *ret = [OFMutableDictionary dictionary];
	OFStringEncoding encoding = [OFLocale encoding];
	ULONG adapterInfoSize = sizeof(IP_ADAPTER_INFO);
	PIP_ADAPTER_INFO adapterInfo;

	if ((adapterInfo = malloc(adapterInfoSize)) == NULL)
		return nil;

	@try {
		ULONG error = GetAdaptersInfo(adapterInfo, &adapterInfoSize);

		if (error == ERROR_BUFFER_OVERFLOW) {
			PIP_ADAPTER_INFO newAdapterInfo =
			    realloc(adapterInfo, adapterInfoSize);

			if (newAdapterInfo == NULL)
				return nil;

			adapterInfo = newAdapterInfo;
			error = GetAdaptersInfo(adapterInfo, &adapterInfoSize);
		}

		if (error != ERROR_SUCCESS)
			return nil;

		for (PIP_ADAPTER_INFO iter = adapterInfo; iter != NULL;
		    iter = iter->Next) {
			OFMutableDictionary *interface;
			OFString *name, *IPString;
			OFNumber *index;
			OFSocketAddress IPv4Address;
			OFData *addresses;

			name = [OFString stringWithCString: iter->AdapterName
						  encoding: encoding];

			if ((interface = [ret objectForKey: name]) == nil) {
				interface = [OFMutableDictionary dictionary];
				[ret setObject: interface forKey: name];
			}

			index = [OFNumber numberWithUnsignedInt: iter->Index];
			[interface setObject: index
				      forKey: OFNetworkInterfaceIndex];

			if (iter->AddressLength > 0) {
				const OFNetworkInterfaceKey key =
				    OFNetworkInterfaceHardwareAddress;
				OFData *address = [OFData
				    dataWithItems: iter->Address
					    count: iter->AddressLength];
				[interface setObject: address forKey: key];
			}

			IPString = [OFString
			    stringWithCString: iter->IpAddressList.IpAddress
						   .String
				     encoding: encoding];

			if ([IPString isEqual: @"0.0.0.0"])
				continue;

			IPv4Address = OFSocketAddressParseIPv4(IPString, 0);
			addresses = [OFData dataWithItems: &IPv4Address
						    count: 1
						 itemSize: sizeof(IPv4Address)];
			[interface setObject: addresses
				      forKey: OFNetworkInterfaceIPv4Addresses];
		}
	} @finally {
		free(adapterInfo);
	}

	return ret;
}

@implementation OFSystemInfo (NetworkInterfaces)
+ (OFDictionary OF_GENERIC(OFString *, OFNetworkInterface) *)networkInterfaces
{
	static OFOnceControl onceControl = OFOnceControlInitValue;
	void *pool = objc_autoreleasePoolPush();
	OFMutableDictionary *ret;
	OFEnumerator *enumerator;
	OFMutableDictionary *interface;

	OFOnce(&onceControl, init);

	if (GetAdaptersAddressesFuncPtr != NULL)
		ret = networkInterfacesFromGetAdaptersAddresses();
	else
		ret = networkInterfacesFromGetAdaptersInfo();

	enumerator = [ret objectEnumerator];
	while ((interface = [enumerator nextObject]) != nil)
		[interface makeImmutable];

	[ret makeImmutable];
	[ret retain];

	objc_autoreleasePoolPop(pool);

	return [ret autorelease];
}
@end

Modified src/platform/Windows/OFTLSKey.m from [819b78979d] to [1dcaec43c5].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/platform/Windows/OFWin32ConsoleStdIOStream.m from [0e3a4cbb4c] to [67f3e85bf4].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/platform/libfat/OFString+PathAdditions.m from [6647377f7a] to [a795f4353d].

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
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

-
+

















-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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 "OFString+PathAdditions.h"
#import "OFArray.h"
#import "OFFileURIHandler.h"
#import "OFFileIRIHandler.h"

#import "OFOutOfRangeException.h"

int _OFString_PathAdditions_reference;

@implementation OFString (PathAdditions)
+ (OFString *)pathWithComponents: (OFArray *)components
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
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







-
+


-
+





-
+










-
+




	} else
		return [self stringByAppendingFormat: @".%@", extension];
}

- (bool)of_isDirectoryPath
{
	return ([self hasSuffix: @"/"] ||
	    [OFFileURIHandler of_directoryExistsAtPath: self]);
	    [OFFileIRIHandler of_directoryExistsAtPath: self]);
}

- (OFString *)of_pathToURIPathWithPercentEncodedHost:
- (OFString *)of_pathToIRIPathWithPercentEncodedHost:
    (OFString **)percentEncodedHost
{
	return [@"/" stringByAppendingString: self];
}

- (OFString *)of_URIPathToPathWithPercentEncodedHost:
- (OFString *)of_IRIPathToPathWithPercentEncodedHost:
    (OFString *)percentEncodedHost
{
	OFString *path = self;

	if (path.length > 1 && [path hasSuffix: @"/"])
		path = [path substringToIndex: path.length - 1];

	return [path substringFromIndex: 1];
}

- (OFString *)of_pathComponentToURIPathComponent
- (OFString *)of_pathComponentToIRIPathComponent
{
	return self;
}
@end

Modified src/platform/macOS/OFAtomic.h from [af25398c26] to [5904558453].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/platform/x86/OFAtomic.h from [db489edc3a] to [07765f0312].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
22
23
24
25
26
27
28
29

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

29
30
31
32
33
34
35
36







-
+







		__asm__ __volatile__ (
		    "lock\n\t"
		    "xaddl	%0, %2\n\t"
		    "addl	%1, %0"
		    : "+&r"(i)
		    : "r"(i), "m"(*p)
		);
#ifdef OF_X86_64
#ifdef OF_AMD64
	else if (sizeof(int) == 8)
		__asm__ __volatile__ (
		    "lock\n\t"
		    "xaddq	%0, %2\n\t"
		    "addq	%1, %0"
		    : "+&r"(i)
		    : "r"(i), "m"(*p)
55
56
57
58
59
60
61
62

63
64
65
66
67
68
69
55
56
57
58
59
60
61

62
63
64
65
66
67
68
69







-
+








	return i;
}

static OF_INLINE void *_Nullable
OFAtomicPointerAdd(void *volatile _Nullable *_Nonnull p, intptr_t i)
{
#if defined(OF_X86_64)
#if defined(OF_AMD64)
	__asm__ __volatile__ (
	    "lock\n\t"
	    "xaddq	%0, %2\n\t"
	    "addq	%1, %0"
	    : "+&r"(i)
	    : "r"(i), "m"(*p)
	);
90
91
92
93
94
95
96
97

98
99
100
101
102
103
104
90
91
92
93
94
95
96

97
98
99
100
101
102
103
104







-
+







		    "negl	%0\n\t"
		    "lock\n\t"
		    "xaddl	%0, %2\n\t"
		    "subl	%1, %0"
		    : "+&r"(i)
		    : "r"(i), "m"(*p)
		);
#ifdef OF_X86_64
#ifdef OF_AMD64
	else if (sizeof(int) == 8)
		__asm__ __volatile__ (
		    "negq	%0\n\t"
		    "lock\n\t"
		    "xaddq	%0, %2\n\t"
		    "subq	%1, %0"
		    : "+&r"(i)
125
126
127
128
129
130
131
132

133
134
135
136
137
138
139
125
126
127
128
129
130
131

132
133
134
135
136
137
138
139







-
+








	return i;
}

static OF_INLINE void *_Nullable
OFAtomicPointerSubtract(void *volatile _Nullable *_Nonnull p, intptr_t i)
{
#if defined(OF_X86_64)
#if defined(OF_AMD64)
	__asm__ __volatile__ (
	    "negq	%0\n\t"
	    "lock\n\t"
	    "xaddq	%0, %2\n\t"
	    "subq	%1, %0"
	    : "+&r"(i)
	    : "r"(i), "m"(*p)
165
166
167
168
169
170
171
172

173
174
175
176
177
178
179
165
166
167
168
169
170
171

172
173
174
175
176
177
178
179







-
+







		    "incl	%0\n\t"
		    "lock\n\t"
		    "xaddl	%0, %1\n\t"
		    "incl	%0"
		    : "=&r"(i)
		    : "m"(*p)
		);
#ifdef OF_X86_64
#ifdef OF_AMD64
	else if (sizeof(int) == 8)
		__asm__ __volatile__ (
		    "xorq	%0, %0\n\t"
		    "incq	%0\n\t"
		    "lock\n\t"
		    "xaddq	%0, %1\n\t"
		    "incq	%0"
216
217
218
219
220
221
222
223

224
225
226
227
228
229
230
216
217
218
219
220
221
222

223
224
225
226
227
228
229
230







-
+







		    "decl	%0\n\t"
		    "lock\n\t"
		    "xaddl	%0, %1\n\t"
		    "decl	%0"
		    : "=&r"(i)
		    : "m"(*p)
		);
#ifdef OF_X86_64
#ifdef OF_AMD64
	else if (sizeof(int) == 8)
		__asm__ __volatile__ (
		    "xorq	%0, %0\n\t"
		    "decq	%0\n\t"
		    "lock\n\t"
		    "xaddq	%0, %1\n\t"
		    "decq	%0"
268
269
270
271
272
273
274
275

276
277
278
279
280
281
282
268
269
270
271
272
273
274

275
276
277
278
279
280
281
282







-
+







		    "lock\n\t"
		    "cmpxchg	%0, %2\n\t"
		    "jne	0b"
		    : "=&r"(i)
		    : "r"(i), "m"(*p)
		    : "eax", "cc"
		);
#ifdef OF_X86_64
#ifdef OF_AMD64
	else if (sizeof(int) == 8)
		__asm__ __volatile__ (
		    "0:\n\t"
		    "movq	%2, %0\n\t"
		    "movq	%0, %%rax\n\t"
		    "orq	%1, %0\n\t"
		    "lock\n\t"
324
325
326
327
328
329
330
331

332
333
334
335
336
337
338
324
325
326
327
328
329
330

331
332
333
334
335
336
337
338







-
+







		    "lock\n\t"
		    "cmpxchg	%0, %2\n\t"
		    "jne	0b"
		    : "=&r"(i)
		    : "r"(i), "m"(*p)
		    : "eax", "cc"
		);
#ifdef OF_X86_64
#ifdef OF_AMD64
	else if (sizeof(int) == 8)
		__asm__ __volatile__ (
		    "0:\n\t"
		    "movq	%2, %0\n\t"
		    "movq	%0, %%rax\n\t"
		    "andq	%1, %0\n\t"
		    "lock\n\t"
380
381
382
383
384
385
386
387

388
389
390
391
392
393
394
380
381
382
383
384
385
386

387
388
389
390
391
392
393
394







-
+







		    "lock\n\t"
		    "cmpxchg	%0, %2\n\t"
		    "jne	0b"
		    : "=&r"(i)
		    : "r"(i), "m"(*p)
		    : "eax", "cc"
		);
#ifdef OF_X86_64
#ifdef OF_AMD64
	else if (sizeof(int) == 8)
		__asm__ __volatile__ (
		    "0:\n\t"
		    "movq	%2, %0\n\t"
		    "movq	%0, %%rax\n\t"
		    "xorq	%1, %0\n\t"
		    "lock\n\t"
478
479
480
481
482
483
484

485
486

487





488
489
490
491
492
493
494
478
479
480
481
482
483
484
485
486

487
488
489
490
491
492
493
494
495
496
497
498
499
500







+

-
+

+
+
+
+
+








	return r;
}

static OF_INLINE void
OFMemoryBarrier(void)
{
#ifdef OF_AMD64
	__asm__ __volatile__ (
	    "mfence" ::: "memory"
	    "lock orq	$0, (%%rsp)" ::: "memory", "cc"
	);
#else
	__asm__ __volatile__ (
	    "lock orl	$0, (%%esp)" ::: "memory", "cc"
	);
#endif
}

static OF_INLINE void
OFAcquireMemoryBarrier(void)
{
	__asm__ __volatile__ ("" ::: "memory");
}

Modified src/runtime/OFOnce.m from [9cc54fa246] to [4007f33455].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/runtime/OFPlainMutex.m from [1b4abcc3c8] to [f85f274b85].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/runtime/OFTLSKey.m from [c512b1fdd8] to [072f63a552].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/runtime/ObjFWRT.h from [87156bda73] to [44336ac424].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/runtime/amiga-end.m from [103c98442e] to [7705a6abc9].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/runtime/amiga-funcarray.inc from [820bef97bb] to [bada144937].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/runtime/amiga-glue.h from [fd3cbd6fa6] to [3ae1db3125].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/runtime/amiga-glue.m from [57058c9f24] to [152fcd7850].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/runtime/amiga-library.m from [6f3d8829a2] to [0623161cd3].

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
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

-
+




















+




+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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 "ObjFWRT.h"
#import "private.h"

#import "amiga-glue.h"

#define Class IntuitionClass
#include <exec/libraries.h>
#include <exec/nodes.h>
#include <exec/resident.h>
#include <proto/exec.h>
#undef Class

#define CONCAT_VERSION2(major, minor) #major "." #minor
#define CONCAT_VERSION(major, minor) CONCAT_VERSION2(major, minor)
#define VERSION_STRING CONCAT_VERSION(OBJFWRT_LIB_MAJOR, OBJFWRT_LIB_MINOR)

#if defined(OF_AMIGAOS_M68K)
# define DATA_OFFSET 0x7FFE
591
592
593
594
595
596
597
598

599
600
601
602
603
604
605
593
594
595
596
597
598
599

600
601
602
603
604
605
606
607







-
+







#endif
	    ,
	.rt_Version = OBJFWRT_LIB_MAJOR,
	.rt_Type = NT_LIBRARY,
	.rt_Pri = 0,
	.rt_Name = (char *)OBJFWRT_AMIGA_LIB,
	.rt_IdString = (char *)"ObjFWRT " VERSION_STRING
	    " \xA9 2008-2022 Jonathan Schleifer",
	    " \xA9 2008-2023 Jonathan Schleifer",
	.rt_Init = &init_table,
#ifdef OF_MORPHOS
	.rt_Revision = OBJFWRT_LIB_MINOR,
	.rt_Tags = NULL,
#endif
};

Modified src/runtime/arc.m from [262fd1b7bb] to [e761109ae6].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/runtime/autorelease.m from [a652114a4e] to [2df304f6dc].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/runtime/category.m from [7faaa519d3] to [124e17c696].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/runtime/class.m from [4cb79aa414] to [c32cd0bfe5].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
54
55
56
57
58
59
60
61

62
63
64
65
66
67
68

69
70
71
72
73
74
75
54
55
56
57
58
59
60

61
62
63
64
65
66
67

68
69
70
71
72
73
74
75







-
+






-
+







class_registerAlias_np(Class class, const char *name)
{
	objc_globalMutex_lock();

	if (classes == NULL) {
		objc_globalMutex_unlock();

		return NO;
		return false;
	}

	objc_hashtable_set(classes, name, (Class)((uintptr_t)class | 1));

	objc_globalMutex_unlock();

	return YES;
	return true;
}

static void
registerSelectors(Class class)
{
	struct objc_method_list *iter;
	unsigned int i;
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
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







-
+




-
+





-
-
-
-
+
+
+
+







		return Nil;

	/*
	 * Fast path
	 *
	 * Instead of looking up the string in a dictionary, which needs
	 * locking, we use a sparse array to look up the pointer. If
	 * objc_classname_to_class() gets called a lot, it is most likely that
	 * objc_classnameToClass() gets called a lot, it is most likely that
	 * the GCC ABI is used, which always calls into objc_lookup_class(), or
	 * that it is used in a loop by the user. In both cases, it is very
	 * likely that the same string pointer is passed again and again.
	 *
	 * This is not used before objc_classname_to_class() has been called a
	 * This is not used before objc_classnameToClass() has been called a
	 * certain amount of times, so that no memory is wasted if it is only
	 * used rarely, for example if the ObjFW ABI is used and the user does
	 * not call it in a loop.
	 *
	 * Runtime internal usage does not use the fast path and does not count
	 * as a call into objc_classname_to_class(). The reason for this is
	 * that if the runtime calls into objc_classname_to_class(), it already
	 * has the lock and thus the performance gain would be small, but it
	 * would waste memory.
	 * as a call into objc_classnameToClass(). The reason for this is that
	 * if the runtime calls into objc_classnameToClass(), it already has
	 * the lock and thus the performance gain would be small, but it would
	 * waste memory.
	 */
	if (cache && fastPath != NULL) {
		class = objc_sparsearray_get(fastPath, (uintptr_t)name);

		if (class != Nil)
			return class;
	}
776
777
778
779
780
781
782

783

784
785
786
787
788
789
790
776
777
778
779
780
781
782
783

784
785
786
787
788
789
790
791







+
-
+








	class->methodList = methodList;

	objc_updateDTable(class);
}

Method
#if defined(__clang__) && __has_attribute(__optnone__) && \
#if defined(__clang__) && __clang_major__ == 3 && __clang_minor__ <= 7
    __clang_major__ == 3 && __clang_minor__ <= 7
/* Work around an ICE in Clang 3.7.0 on Windows/x86 */
__attribute__((__optnone__))
#endif
class_getInstanceMethod(Class class, SEL selector)
{
	Method method;
	Class superclass;

Modified src/runtime/dtable.m from [f0602aa5e2] to [94219a6e40].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/runtime/exception.m from [ba2a43d17f] to [aa18b3eafc].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/runtime/hashtable.m from [4617c1e6d6] to [60630dc910].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/runtime/init.m from [bad26900aa] to [a4c85992b9].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/runtime/instance.m from [bb4ce37e30] to [9d0f3fb306].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/runtime/ivar.m from [9c027bf0b1] to [e25e0b7280].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/runtime/linklib/init.m from [aee4e3c855] to [0c588847ed].

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
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

-
+




















+


+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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 "ObjFWRT.h"
#import "private.h"
#import "amiga-library.h"

#define USE_INLINE_STDARG
#define Class IntuitionClass
#include <proto/exec.h>
#include <proto/intuition.h>
#undef Class

#include <stdio.h>
#include <stdlib.h>

#if defined(OF_AMIGAOS_M68K)
# include <stabs.h>
#elif defined(OF_MORPHOS)

Modified src/runtime/linklib/linklib.m from [6ac36a70a4] to [d67f38e0d7].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Renamed and modified src/runtime/lookup-asm/lookup-asm-x86_64-elf.S [63daf9ee68] to src/runtime/lookup-asm/lookup-asm-amd64-elf.S [c64d3f82a3].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
89
90
91
92
93
94
95
96

97
98
89
90
91
92
93
94
95

96
97
98







-
+


	leaq	nilMethod(%rip), %rax
	ret

nilMethod:
	xorq	%rax, %rax
	ret

#ifdef OF_LINUX
#if defined(OF_LINUX) || defined(OF_HURD)
.section .note.GNU-stack, "", %progbits
#endif

Renamed and modified src/runtime/lookup-asm/lookup-asm-x86_64-macho.S [1e72bfb083] to src/runtime/lookup-asm/lookup-asm-amd64-macho.S [f313fe156e].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Renamed and modified src/runtime/lookup-asm/lookup-asm-x86_64-win64.S [bb874856c9] to src/runtime/lookup-asm/lookup-asm-amd64-win64.S [13eae8467e].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/runtime/lookup-asm/lookup-asm-arm-elf.S from [f0e5b05f4e] to [ef1c429a04].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
111
112
113
114
115
116
117
118

119
120
111
112
113
114
115
116
117

118
119
120







-
+


	adr	r0, nilMethod
	bx	lr

nilMethod:
	mov	r0, #0
	bx	lr

#ifdef OF_LINUX
#if defined(OF_LINUX) || defined(OF_HURD)
.section .note.GNU-stack, "", %progbits
#endif

Modified src/runtime/lookup-asm/lookup-asm-arm64-elf.S from [ad3c36fa42] to [da24cfc12d].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
89
90
91
92
93
94
95
96

97
98
89
90
91
92
93
94
95

96
97
98







-
+


	adr	x0, nilMethod
	ret

nilMethod:
	mov	x0, #0
	ret

#ifdef OF_LINUX
#if defined(OF_LINUX) || defined(OF_HURD)
.section .note.GNU-stack, "", %progbits
#endif

Modified src/runtime/lookup-asm/lookup-asm-mips-elf.S from [c727ce9d5a] to [f31e7b899e].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
150
151
152
153
154
155
156
157

158
159
150
151
152
153
154
155
156

157
158
159







-
+


GENERATE_LOOKUP_SUPER objc_msg_lookup_super objc_msg_lookup
GENERATE_LOOKUP_SUPER objc_msg_lookup_super_stret objc_msg_lookup_stret

nilMethod:
	move	$v0, $zero
	jr	$ra

#ifdef OF_LINUX
#if defined(OF_LINUX) || defined(OF_HURD)
.section .note.GNU-stack, "", %progbits
#endif

Modified src/runtime/lookup-asm/lookup-asm-mips64-n64-elf.S from [53637868a6] to [2cfdbef557].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
130
131
132
133
134
135
136
137

138
139
130
131
132
133
134
135
136

137
138
139







-
+


GENERATE_LOOKUP_SUPER objc_msg_lookup_super objc_msg_lookup
GENERATE_LOOKUP_SUPER objc_msg_lookup_super_stret objc_msg_lookup_stret

nilMethod:
	move	$v0, $zero
	jr	$ra

#ifdef OF_LINUX
#if defined(OF_LINUX) || defined(OF_HURD)
.section .note.GNU-stack, "", %progbits
#endif

Modified src/runtime/lookup-asm/lookup-asm-powerpc-elf.S from [134bfef460] to [97b8fd704a].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
164
165
166
167
168
169
170
171

172
173
164
165
166
167
168
169
170

171
172
173







-
+


	.long objc_methodNotFound_stret
.Lgot_objc_taggedPointerSecret:
	.long objc_taggedPointerSecret
.Lgot_objc_taggedPointerClasses:
	.long objc_taggedPointerClasses
#endif

#ifdef OF_LINUX
#if defined(OF_LINUX) || defined(OF_HURD)
.section .note.GNU-stack, "", @progbits
#endif

Modified src/runtime/lookup-asm/lookup-asm-powerpc64-elf.S from [8516ac090f] to [2a2bbd4d55].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
154
155
156
157
158
159
160
161

162
163
154
155
156
157
158
159
160

161
162
163







-
+


#endif
.Lbegin_nilMethod:
	li	%r3, 0
	blr
.type nilMethod, @function
.size nilMethod, .-.Lbegin_nilMethod

#ifdef OF_LINUX
#if defined(OF_LINUX) || defined(OF_HURD)
.section .note.GNU-stack, "", @progbits
#endif

Modified src/runtime/lookup-asm/lookup-asm-sparc-elf.S from [52b9093b5b] to [891512ba88].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
140
141
142
143
144
145
146
147

148
149
140
141
142
143
144
145
146

147
148
149







-
+


	 or	%o0, %lo(nilMethod), %o0
#endif

nilMethod:
	retl
	 clr	%o0

#ifdef OF_LINUX
#if defined(OF_LINUX) || defined(OF_HURD)
.section .note.GNU-stack, "", %progbits
#endif

Modified src/runtime/lookup-asm/lookup-asm-sparc64-elf.S from [1e61b50ef6] to [6533df3a9f].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
137
138
139
140
141
142
143
144

145
146
137
138
139
140
141
142
143

144
145
146







-
+


	 or	%o0, %lo(nilMethod), %o0
#endif

nilMethod:
	retl
	 clr	%o0

#ifdef OF_LINUX
#if defined(OF_LINUX) || defined(OF_HURD)
.section .note.GNU-stack, "", %progbits
#endif

Modified src/runtime/lookup-asm/lookup-asm-x86-elf.S from [fe04c47c7f] to [735d83d15c].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
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
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







-
+






-
+




-
+







	jz	0f

	ret

0:
	call	getEIP
	addl	$_GLOBAL_OFFSET_TABLE_, %eax
	lea	\notFound@GOTOFF(%eax), %eax
	movl	\notFound@GOT(%eax), %eax
	jmp	*%eax

.LtaggedPointer_\name:
	call	getEIP
	addl	$_GLOBAL_OFFSET_TABLE_, %eax

	leal	objc_taggedPointerSecret@GOTOFF(%eax), %ecx
	movl	objc_taggedPointerSecret@GOT(%eax), %ecx
	xorl	(%ecx), %edx
	andb	$0xE, %dl
	movzbl	%dl, %edx

	leal	objc_taggedPointerClasses@GOTOFF(%eax), %eax
	movl	objc_taggedPointerClasses@GOT(%eax), %eax
	movl	(%eax,%edx,2), %edx
	movl	32(%edx), %edx

	jmp	.Lmain_\name
.type \name, %function
.size \name, .-\name
.endm
106
107
108
109
110
111
112
113

114
115
106
107
108
109
110
111
112

113
114
115







-
+


	xorl	%eax, %eax
	ret

getEIP:
	movl	(%esp), %eax
	ret

#ifdef OF_LINUX
#if defined(OF_LINUX) || defined(OF_HURD)
.section .note.GNU-stack, "", %progbits
#endif

Modified src/runtime/lookup-asm/lookup-asm-x86-win32.S from [0d663a9140] to [bbc35eaa38].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/runtime/lookup-asm/lookup-asm.S from [31f647ad96] to [59fd89901b].

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
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

-
+


















-
-
+
+




















-
-
+
+


-
-
+
+




/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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"

#include "platform.h"

#if defined(OF_ELF)
# if defined(OF_X86_64)
#  include "lookup-asm-x86_64-elf.S"
# if defined(OF_AMD64)
#  include "lookup-asm-amd64-elf.S"
# elif defined(OF_X86)
#  include "lookup-asm-x86-elf.S"
# elif defined(OF_ARM64)
#  include "lookup-asm-arm64-elf.S"
# elif defined(OF_ARM)
#  include "lookup-asm-arm-elf.S"
# elif defined(OF_POWERPC64)
#  include "lookup-asm-powerpc64-elf.S"
# elif defined(OF_POWERPC)
#  include "lookup-asm-powerpc-elf.S"
# elif defined(OF_MIPS64_N64)
#  include "lookup-asm-mips64-n64-elf.S"
# elif defined(OF_MIPS)
#  include "lookup-asm-mips-elf.S"
# elif defined(OF_SPARC64)
#  include "lookup-asm-sparc64-elf.S"
# elif defined(OF_SPARC)
#  include "lookup-asm-sparc-elf.S"
# endif
#elif defined(OF_MACH_O)
# if defined(OF_X86_64)
#  include "lookup-asm-x86_64-macho.S"
# if defined(OF_AMD64)
#  include "lookup-asm-amd64-macho.S"
# endif
#elif defined(OF_WINDOWS)
# if defined(OF_X86_64)
#  include "lookup-asm-x86_64-win64.S"
# if defined(OF_AMD64)
#  include "lookup-asm-amd64-win64.S"
# elif defined(OF_X86)
#  include "lookup-asm-x86-win32.S"
# endif
#endif

Modified src/runtime/lookup.m from [620b9cc132] to [bc901bdb0e].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/runtime/method.m from [82646e77ef] to [8b4eb13221].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/runtime/misc.m from [6b0956b061] to [ca99efcb2f].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
23
24
25
26
27
28
29

30
31
32
33
34
35
36
37


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

35


36
37
38
39
40
41
42
43
44







+




-

-
-
+
+







#include "private.h"

#ifdef OF_WINDOWS
# include <windows.h>
#endif

#ifdef OF_AMIGAOS
# define Class IntuitionClass
# define USE_INLINE_STDARG
# include <proto/exec.h>
# include <clib/debug_protos.h>
# define __NOLIBBASE__
# define Class IntuitionClass
# include <proto/intuition.h>
# undef Class
# undef __NOLIBBASE__
# undef __NOLIBBASE__
# undef Class
#endif

static objc_enumeration_mutation_handler enumerationMutationHandler = NULL;

void
objc_enumerationMutation(id object)
{

Modified src/runtime/private.h from [41cb53cb64] to [309bc9f429].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
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
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







-
+







-
+



-
+







extern void OF_NO_RETURN_FUNC objc_error(const char *_Nonnull title,
    const char *_Nonnull format, ...);
#define OBJC_ERROR(...)							\
	objc_error("ObjFWRT @ " __FILE__ ":" OF_STRINGIFY(__LINE__),	\
	    __VA_ARGS__)

#if defined(OF_ELF)
# if defined(OF_X86_64) || defined(OF_X86) || \
# if defined(OF_AMD64) || defined(OF_X86) || \
    defined(OF_POWERPC64) || defined(OF_POWERPC) || \
    defined(OF_ARM64) || defined(OF_ARM) || \
    defined(OF_MIPS64_N64) || defined(OF_MIPS) || \
    defined(OF_SPARC64) || defined(OF_SPARC)
#  define OF_ASM_LOOKUP
# endif
#elif defined(OF_MACH_O)
# if defined(OF_X86_64)
# if defined(OF_AMD64)
#  define OF_ASM_LOOKUP
# endif
#elif defined(OF_WINDOWS)
# if defined(OF_X86_64) || defined(OF_X86)
# if defined(OF_AMD64) || defined(OF_X86)
#  define OF_ASM_LOOKUP
# endif
#endif

@interface DummyObject
{
	Class _Nonnull isa;

Modified src/runtime/property.m from [822a1641e1] to [b313b3c6cb].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/runtime/protocol.m from [30a1ffceef] to [99bc00ce9a].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/runtime/selector.m from [9a44ebdc88] to [ea6ec466b1].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/runtime/sparsearray.m from [5acb08c6c8] to [56f5910910].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/runtime/static-instances.m from [7d72566e27] to [3d6759633a].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/runtime/synchronized.m from [2eb69df2c4] to [d09172eb0d].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/runtime/tagged-pointer.m from [747427397b] to [b8247a8caf].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/runtime/threading.m from [f4000ae0f7] to [05de45146b].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/runtime/versioninfo.rc from [6986fc8cab] to [22bb23756b].

10
11
12
13
14
15
16
17

18
19
20
21
22
23
24
25
26
27
10
11
12
13
14
15
16

17
18
19
20
21
22
23
24
25
26
27







-
+










	BLOCK "StringFileInfo" {
		BLOCK "040904E4" {
			VALUE "ProductName", "ObjFW Runtime"
			VALUE "ProductVersion", PACKAGE_VERSION
			VALUE "FileVersion", OBJFWRT_LIB_VERSION
			VALUE "FileDescription", "Objective-C runtime"
			VALUE "LegalCopyright",
			    "(c) 2008-2022 Jonathan Schleifer"
			    "(c) 2008-2023 Jonathan Schleifer"
			VALUE "InternalName", "ObjFWRT"
			VALUE "OriginalFilename", OBJFWRT_SHARED_LIB
		}

	}

	BLOCK "VarFileInfo" {
		VALUE "Translation", 0x409, 1252
	}
}

Modified src/tls/OFGnuTLSTLSStream.h from [d33b11b9cb] to [c3164e0c8e].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/tls/OFGnuTLSTLSStream.m from [fad8797bf6] to [b0bb2b39ec].

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
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

-
+




















-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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"

#include <errno.h>

#import "OFGnuTLSTLSStream.h"
#import "OFData.h"

#import "OFAlreadyConnectedException.h"
#import "OFAlreadyOpenException.h"
#import "OFInitializationFailedException.h"
#import "OFNotOpenException.h"
#import "OFReadFailedException.h"
#import "OFTLSHandshakeFailedException.h"
#import "OFWriteFailedException.h"

int _ObjFWTLS_reference;
198
199
200
201
202
203
204
205

206
207
208
209
210
211
212
198
199
200
201
202
203
204

205
206
207
208
209
210
211
212







-
+







{
	static const OFTLSStreamErrorCode initFailedErrorCode =
	    OFTLSStreamErrorCodeInitializationFailed;
	id exception = nil;
	int status;

	if (_initialized)
		@throw [OFAlreadyConnectedException exceptionWithSocket: self];
		@throw [OFAlreadyOpenException exceptionWithObject: self];

	if (gnutls_init(&_session, GNUTLS_CLIENT | GNUTLS_NONBLOCK |
	    GNUTLS_SAFE_PADDING_CHECK) != GNUTLS_E_SUCCESS)
		@throw [OFTLSHandshakeFailedException
		    exceptionWithStream: self
				   host: host
			      errorCode: initFailedErrorCode];

Modified src/tls/OFOpenSSLTLSStream.h from [5bdb0a26b6] to [8fa7194d49].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/tls/OFOpenSSLTLSStream.m from [faf6205c5a] to [df13b43daa].

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
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

-
+




















-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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"

#include <errno.h>

#import "OFOpenSSLTLSStream.h"
#import "OFData.h"

#import "OFAlreadyConnectedException.h"
#import "OFAlreadyOpenException.h"
#import "OFInitializationFailedException.h"
#import "OFNotOpenException.h"
#import "OFReadFailedException.h"
#import "OFTLSHandshakeFailedException.h"
#import "OFWriteFailedException.h"

#define bufferSize OFOpenSSLTLSStreamBufferSize
203
204
205
206
207
208
209
210

211
212
213
214
215
216
217
203
204
205
206
207
208
209

210
211
212
213
214
215
216
217







-
+







{
	static const OFTLSStreamErrorCode initFailedErrorCode =
	    OFTLSStreamErrorCodeInitializationFailed;
	id exception = nil;
	int status;

	if (_SSL != NULL)
		@throw [OFAlreadyConnectedException exceptionWithSocket: self];
		@throw [OFAlreadyOpenException exceptionWithObject: self];

	if ((_readBIO = BIO_new(BIO_s_mem())) == NULL)
		@throw [OFTLSHandshakeFailedException
		    exceptionWithStream: self
				   host: host
			      errorCode: initFailedErrorCode];

Modified src/tls/OFSecureTransportTLSStream.h from [6f1a3f10c3] to [b71a694796].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/tls/OFSecureTransportTLSStream.m from [d93ffbbd51] to [c722ef4615].

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
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

-
+



















-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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"

#include <errno.h>

#import "OFSecureTransportTLSStream.h"

#import "OFAlreadyConnectedException.h"
#import "OFAlreadyOpenException.h"
#import "OFNotOpenException.h"
#import "OFReadFailedException.h"
#import "OFTLSHandshakeFailedException.h"
#import "OFWriteFailedException.h"

int _ObjFWTLS_reference;

184
185
186
187
188
189
190
191

192
193
194
195
196
197
198
184
185
186
187
188
189
190

191
192
193
194
195
196
197
198







-
+







{
	static const OFTLSStreamErrorCode initFailedErrorCode =
	    OFTLSStreamErrorCodeInitializationFailed;
	id exception = nil;
	OSStatus status;

	if (_context != NULL)
		@throw [OFAlreadyConnectedException exceptionWithSocket: self];
		@throw [OFAlreadyOpenException exceptionWithObject: self];

#ifdef HAVE_SSLCREATECONTEXT
	if ((_context = SSLCreateContext(kCFAllocatorDefault, kSSLClientSide,
	    kSSLStreamType)) == NULL)
#else
	if (SSLNewContext(false, &_context) != noErr)
#endif

Modified src/tls/ObjFWTLS.h from [498108c5a2] to [653f0ace6f].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/unicode.h from [2eea427f38] to [5afacb875e].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/unicode.m from [1934fadafb] to [25e90b64b1].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/unistd_wrapper.h from [10576ea4f7] to [f8597c03ef].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified src/versioninfo.rc from [ec5c3868fe] to [f0b083dad4].

10
11
12
13
14
15
16
17

18
19
20
21
22
23
24
25
26
27
10
11
12
13
14
15
16

17
18
19
20
21
22
23
24
25
26
27







-
+










	BLOCK "StringFileInfo" {
		BLOCK "040904E4" {
			VALUE "ProductName", "ObjFW"
			VALUE "ProductVersion", PACKAGE_VERSION
			VALUE "FileVersion", OBJFW_LIB_VERSION
			VALUE "FileDescription", "Objective-C framework"
			VALUE "LegalCopyright",
			    "(c) 2008-2022 Jonathan Schleifer"
			    "(c) 2008-2023 Jonathan Schleifer"
			VALUE "InternalName", "ObjFW"
			VALUE "OriginalFilename", OBJFW_SHARED_LIB
		}

	}

	BLOCK "VarFileInfo" {
		VALUE "Translation", 0x409, 1252
	}
}

Modified tests/ForwardingTests.m from [de62832427] to [7652642520].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified tests/ImportTest.m from [50763ee365] to [4f66c2123d].

1
2

3
4
5
6
7
8
9
10
11
12
13
14
15
16

1

2
3
4
5
6
7
8
9
10
11
12
13
14
15

16

-
+













-
+
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 */

#import <ObjFW/ObjFW.h>
@import ObjFW;

Modified tests/Makefile from [8ee3ecfd5f] to [fb1cdc4884].

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
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












-










+





+





+














-




-












-







include ../extra.mk

SUBDIRS = ${TESTPLUGIN}	\
	  ${OBJC_SYNC}	\
	  terminal

CLEAN = EBOOT.PBP		\
	boot.dol		\
	${PROG_NOINST}.arm9	\
	${PROG_NOINST}.nds	\
	${PROG_NOINST}.nro	\
	${PROG_NOINST}.rpx	\
	serialization_xml.m	\
	testfile_bin.m		\
	testfile_ini.m
DISTCLEAN = Info.plist

PROG_NOINST = tests${PROG_SUFFIX}
STATIC_LIB_NOINST = ${TESTS_STATIC_LIB}
SRCS = ForwardingTests.m		\
       OFArrayTests.m			\
       ${OF_BLOCK_TESTS_M}		\
       OFCharacterSetTests.m		\
       OFColorTests.m			\
       OFDataTests.m			\
       OFDateTests.m			\
       OFDictionaryTests.m		\
       OFHMACTests.m			\
       OFINIFileTests.m			\
       OFIRITests.m			\
       OFInvocationTests.m		\
       OFJSONTests.m			\
       OFListTests.m			\
       OFLocaleTests.m			\
       OFMD5HashTests.m			\
       OFMatrix4x4Tests.m		\
       OFMemoryStreamTests.m		\
       OFMethodSignatureTests.m		\
       OFNotificationCenterTests.m	\
       OFNumberTests.m			\
       OFObjectTests.m			\
       OFPBKDF2Tests.m			\
       OFPropertyListTests.m		\
       OFRIPEMD160HashTests.m		\
       OFSHA1HashTests.m		\
       OFSHA224HashTests.m		\
       OFSHA256HashTests.m		\
       OFSHA384HashTests.m		\
       OFSHA512HashTests.m		\
       OFScryptTests.m			\
       OFSerializationTests.m		\
       OFSetTests.m			\
       OFStreamTests.m			\
       OFStringTests.m			\
       OFSystemInfoTests.m		\
       OFURITests.m			\
       OFValueTests.m			\
       OFXMLElementBuilderTests.m	\
       OFXMLNodeTests.m			\
       OFXMLParserTests.m		\
       RuntimeTests.m			\
       ${RUNTIME_ARC_TESTS_M}		\
       TestsAppDelegate.m		\
       ${USE_SRCS_FILES}		\
       ${USE_SRCS_PLUGINS}		\
       ${USE_SRCS_SOCKETS}		\
       ${USE_SRCS_THREADS}		\
       ${USE_SRCS_WINDOWS}		\
       serialization_xml.m		\
       testfile_bin.m			\
       testfile_ini.m
SRCS_PLUGINS = OFPluginTests.m
SRCS_SOCKETS = OFDNSResolverTests.m		\
	       ${OF_HTTP_CLIENT_TESTS_M}	\
	       OFHTTPCookieTests.m		\
	       OFHTTPCookieManagerTests.m	\
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
87
88
89
90
91
92
93


94
95
96
97
98
99
100







-
-







SRCS_WINDOWS = OFWindowsRegistryKeyTests.m

IOS_USER ?= mobile
IOS_TMP ?= /tmp/objfw-test

include ../buildsys.mk

serialization_xml.m: serialization.xml
	${SHELL} ../utils/objfw-embed serialization.xml serialization.xml $@
testfile_bin.m: testfile.bin
	${SHELL} ../utils/objfw-embed testfile.bin testfile.bin $@
testfile_ini.m: testfile.ini
	${SHELL} ../utils/objfw-embed testfile.ini testfile.ini $@

.PHONY: run run-on-ios run-on-android
run:

Modified tests/OFArrayTests.m from [cc2ce2f7d0] to [08824c3292].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
427
428
429
430
431
432
433
434
435
436



437
438
439
440
441
442
443



444
445
446
447
448
449
450
427
428
429
430
431
432
433



434
435
436
437
438
439
440



441
442
443
444
445
446
447
448
449
450







-
-
-
+
+
+




-
-
-
+
+
+







	    valueForKey: @"length"] isEqual:
	    [arrayClass arrayWithObjects: [OFNumber numberWithInt: 3],
	    [OFNumber numberWithInt: 3], [OFNumber numberWithInt: 6], nil]] &&
	    [[[arrayClass arrayWithObjects: @"1", @"2", nil]
	    valueForKey: @"@count"] isEqual: [OFNumber numberWithInt: 2]])

	mutableArray1 = [mutableArrayClass arrayWithObjects:
	    [OFMutableURI URIWithString: @"http://foo.bar/"],
	    [OFMutableURI URIWithString: @"http://bar.qux/"],
	    [OFMutableURI URIWithString: @"http://qux.quxqux/"], nil];
	    [OFMutableIRI IRIWithString: @"http://foo.bar/"],
	    [OFMutableIRI IRIWithString: @"http://bar.qux/"],
	    [OFMutableIRI IRIWithString: @"http://qux.quxqux/"], nil];
	TEST(@"-[setValue:forKey:]",
	    R([mutableArray1 setValue: [OFNumber numberWithShort: 1234]
			       forKey: @"port"]) &&
	    [mutableArray1 isEqual: [arrayClass arrayWithObjects:
	    [OFURI URIWithString: @"http://foo.bar:1234/"],
	    [OFURI URIWithString: @"http://bar.qux:1234/"],
	    [OFURI URIWithString: @"http://qux.quxqux:1234/"], nil]])
	    [OFIRI IRIWithString: @"http://foo.bar:1234/"],
	    [OFIRI IRIWithString: @"http://bar.qux:1234/"],
	    [OFIRI IRIWithString: @"http://qux.quxqux:1234/"], nil]])

	objc_autoreleasePoolPop(pool);
}

- (void)arrayTests
{
	module = @"OFArray";

Modified tests/OFBlockTests.m from [d2cc5b8a58] to [0ba4bbb116].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
25
26
27
28
29
30
31


32

33
34
35
36
37
38
39
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42







+
+

+







extern struct objc_class _NSConcreteMallocBlock;
#elif defined(OF_APPLE_RUNTIME)
extern void *_NSConcreteStackBlock;
extern void *_NSConcreteGlobalBlock;
extern void *_NSConcreteMallocBlock;
#endif

/* Clang on Win32 generates broken code that crashes for global blocks. */
#if !defined(OF_WINDOWS) || !defined(OF_X86) || !defined(__clang__)
static void (^globalBlock)(void) = ^ {};
#endif

static int
(^returnStackBlock(void))(void)
{
	__block int i = 42;

	return [Block_copy(^ int { return ++i; }) autorelease];
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
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







-
+
-
-
-
-




















+


+









+

+








	void (^mallocBlock)(void);
	int (^voidBlock)(void);

	TEST(@"Class of stack block",
	    (Class)&_NSConcreteStackBlock == objc_getClass("OFStackBlock") &&
	    [stackBlock isKindOfClass: [OFBlock class]])

#if !defined(OF_WINDOWS) || !defined(__clang__) || !defined(OF_NO_SHARED)
#if !defined(OF_WINDOWS) || !defined(OF_X86) || !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") &&
	    [globalBlock isKindOfClass: [OFBlock class]])
#endif

	TEST(@"Class of a malloc block",
	    (Class)&_NSConcreteMallocBlock == objc_getClass("OFMallocBlock"))

	TEST(@"Copying a stack block",
	    (mallocBlock = [[stackBlock copy] autorelease]) &&
	    [mallocBlock class] == objc_getClass("OFMallocBlock") &&
	    [mallocBlock isKindOfClass: [OFBlock class]])

	TEST(@"Copying a stack block and referencing its variable",
	    forwardTest() == 5)

	TEST(@"Copying a stack block and using its copied variable",
	    (voidBlock = returnStackBlock()) && voidBlock() == 43 &&
	    voidBlock() == 44 && voidBlock() == 45)

#if !defined(OF_WINDOWS) || !defined(OF_X86) || !defined(__clang__)
	TEST(@"Copying a global block",
	    (id)globalBlock == [[globalBlock copy] autorelease])
#endif

#ifndef __clang_analyzer__
	TEST(@"Copying a malloc block",
	    (id)mallocBlock == [mallocBlock copy] &&
	    [mallocBlock retainCount] == 2)
#endif

	TEST(@"Autorelease a stack block", R([stackBlock autorelease]))

#if !defined(OF_WINDOWS) || !defined(OF_X86) || !defined(__clang__)
	TEST(@"Autorelease a global block", R([globalBlock autorelease]))
#endif

#ifndef __clang_analyzer__
	TEST(@"Autorelease a malloc block", R([mallocBlock autorelease]))
#endif

	objc_autoreleasePoolPop(pool);
}
@end

Modified tests/OFCharacterSetTests.m from [9bcb0257c8] to [6a932f9fba].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Added tests/OFColorTests.m version [c0f67501f7].
















































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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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 "TestsAppDelegate.h"

static OFString *const module = @"OFColor";

@implementation TestsAppDelegate (OFColorTests)
- (void)colorTests
{
	void *pool = objc_autoreleasePoolPush();
	OFColor *color;
	float red, green, blue, alpha;

	TEST(@"+[colorWithRed:green:blue:alpha:]",
	    (color = [OFColor colorWithRed: 63.f / 255
				     green: 127.f / 255
				      blue: 1
				     alpha: 1]))

#ifdef OF_OBJFW_RUNTIME
	TEST(@"+[colorWithRed:green:blue:alpha:] returns tagged pointer",
	    object_isTaggedPointer(color))
#endif

	TEST(@"-[getRed:green:blue:alpha:]",
	    R([color getRed: &red green: &green blue: &blue alpha: &alpha]) &&
	    red == 63.f / 255 && green == 127.f / 255 && blue == 1 &&
	    alpha == 1)

	objc_autoreleasePoolPop(pool);
}
@end

Modified tests/OFDDPSocketTests.m from [7798ad31e7] to [030a88638b].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
36
37
38
39
40
41
42

43
44
45
46
47
48
49
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50







+







		    R(address1 = [sock bindToNetwork: 0
						node: 0
						port: 0
					protocolType: 11]))
	} @catch (OFBindSocketFailedException *e) {
		switch (e.errNo) {
		case EAFNOSUPPORT:
		case EPROTONOSUPPORT:
			[OFStdOut setForegroundColor: [OFColor lime]];
			[OFStdOut writeLine:
			    @"\r[OFDDPSocket] -[bindToNetwork:node:port:"
			    @"protocolType:] AppleTalk unsupported, skipping "
			    @"tests"];
			break;
		case EADDRNOTAVAIL:

Modified tests/OFDNSResolverTests.m from [b7997ffc05] to [90e052eb2c].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
55
56
57
58
59
60
61
62
63


64
65
66
67
68
69
70
71
55
56
57
58
59
60
61


62
63
64
65
66
67
68
69
70
71







-
-
+
+








	[OFStdOut writeFormat: @"[OFDNSResolver] Max attempts: %u\n",
	    resolver.maxAttempts];

	[OFStdOut writeFormat:
	    @"[OFDNSResolver] Min number of dots in absolute name: %u\n",
	    resolver.minNumberOfDotsInAbsoluteName];

	[OFStdOut writeFormat: @"[OFDNSResolver] Uses TCP: %u\n",
	    resolver.usesTCP];
	[OFStdOut writeFormat: @"[OFDNSResolver] Forces TCP: %u\n",
	    resolver.forcesTCP];

	[OFStdOut writeFormat:
	    @"[OFDNSResolver] Config reload interval: %lf\n",
	    resolver.configReloadInterval];

	objc_autoreleasePoolPop(pool);
}
@end

Modified tests/OFDataTests.m from [ffac8c7aa2] to [316bad9cbb].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified tests/OFDateTests.m from [f110295df2] to [23aa5adafc].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified tests/OFDictionaryTests.m from [856ca278b2] to [a12b4aaa0c].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified tests/OFHMACTests.m from [dc8ace4048] to [a66cd6bc37].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
47
48
49
50
51
52
53
54
55


56
57
58
59
60
61
62
47
48
49
50
51
52
53


54
55
56
57
58
59
60
61
62







-
-
+
+







    "\x61\xB3\xF9\x1A\xE3\x09\x43\xA6\x5B\x85\xB1\x50\x5B\xCB\x1A\x2E"
    "\xB7\xE8\x87\xC1\x73\x19\x63\xF6\xA2\x91\x8D\x7E\x2E\xCC\xEC\x99";

@implementation TestsAppDelegate (OFHMACTests)
- (void)HMACTests
{
	void *pool = objc_autoreleasePoolPush();
	OFURI *URI = [OFURI URIWithString: @"embedded:testfile.bin"];
	OFStream *file = [OFURIHandler openItemAtURI: URI mode: @"r"];
	OFIRI *IRI = [OFIRI IRIWithString: @"embedded:testfile.bin"];
	OFStream *file = [OFIRIHandler openItemAtIRI: IRI mode: @"r"];
	OFHMAC *HMACMD5, *HMACSHA1, *HMACRMD160;
	OFHMAC *HMACSHA256, *HMACSHA384, *HMACSHA512;

	TEST(@"+[HMACWithHashClass:] with MD5",
	    (HMACMD5 = [OFHMAC HMACWithHashClass: [OFMD5Hash class]
			   allowsSwappableMemory: true]))
	TEST(@"+[HMACWithHashClass:] with SHA-1",

Modified tests/OFHTTPClientTests.m from [64ad652a21] to [0f28ab76f2].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
34
35
36
37
38
39
40

41
42
43
44
45
46


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

47
48
49
50
51
52
53
54
55







+





-
+
+







}
@end

@implementation HTTPClientTestsServer
- (id)main
{
	OFTCPSocket *listener, *client;
	OFSocketAddress address;
	char buffer[5];

	[condition lock];

	listener = [OFTCPSocket socket];
	_port = [listener bindToHost: @"127.0.0.1" port: 0];
	address = [listener bindToHost: @"127.0.0.1" port: 0];
	_port = OFSocketAddressIPPort(&address);
	[listener listen];

	[condition signal];
	[condition unlock];

	client = [listener accept];

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
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







-
+














-
+





-
+







	[[OFRunLoop mainRunLoop] stop];
}

- (void)HTTPClientTests
{
	void *pool = objc_autoreleasePoolPush();
	HTTPClientTestsServer *server;
	OFURI *URI;
	OFIRI *IRI;
	OFHTTPClient *client;
	OFHTTPRequest *request;
	OFData *data;

	condition = [OFCondition condition];
	[condition lock];

	server = [[[HTTPClientTestsServer alloc] init] autorelease];
	server.supportsSockets = true;
	[server start];

	[condition wait];
	[condition unlock];

	URI = [OFURI URIWithString:
	IRI = [OFIRI IRIWithString:
	    [OFString stringWithFormat: @"http://127.0.0.1:%" @PRIu16 "/foo",
					server->_port]];

	TEST(@"-[asyncPerformRequest:]",
	    (client = [OFHTTPClient client]) && (client.delegate = self) &&
	    (request = [OFHTTPRequest requestWithURI: URI]) &&
	    (request = [OFHTTPRequest requestWithIRI: IRI]) &&
	    (request.headers =
	    [OFDictionary dictionaryWithObject: @"5"
					forKey: @"Content-Length"]) &&
	    R([client asyncPerformRequest: request]))

	[[OFRunLoop mainRunLoop] runUntilDate:
	    [OFDate dateWithTimeIntervalSinceNow: 2]];

Modified tests/OFHTTPCookieManagerTests.m from [fc980e6e00] to [d3b9e948fc].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
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
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







-
+


-
-
-
-
+
+
+
+




-
-
+
+

-
-
+
+





-
-
+
+

-
-
+
+

-
+





-
-
+
+

-
-
+
+

-
+






-
-
+
+

-
-
+
+

-
+





-
-
+
+

-
-
+
+

-
+












static OFString *const module = @"OFHTTPCookieManager";

@implementation TestsAppDelegate (OFHTTPCookieManagerTests)
- (void)HTTPCookieManagerTests
{
	void *pool = objc_autoreleasePoolPush();
	OFHTTPCookieManager *manager = [OFHTTPCookieManager manager];
	OFURI *URI1, *URI2, *URI3, *URI4;
	OFIRI *IRI1, *IRI2, *IRI3, *IRI4;
	OFHTTPCookie *cookie1, *cookie2, *cookie3, *cookie4, *cookie5;

	URI1 = [OFURI URIWithString: @"http://nil.im/foo"];
	URI2 = [OFURI URIWithString: @"https://nil.im/foo/bar"];
	URI3 = [OFURI URIWithString: @"https://test.nil.im/foo/bar"];
	URI4 = [OFURI URIWithString: @"http://webkeks.org/foo/bar"];
	IRI1 = [OFIRI IRIWithString: @"http://nil.im/foo"];
	IRI2 = [OFIRI IRIWithString: @"https://nil.im/foo/bar"];
	IRI3 = [OFIRI IRIWithString: @"https://test.nil.im/foo/bar"];
	IRI4 = [OFIRI IRIWithString: @"http://webkeks.org/foo/bar"];

	cookie1 = [OFHTTPCookie cookieWithName: @"test"
					 value: @"1"
					domain: @"nil.im"];
	TEST(@"-[addCookie:forURI:] #1",
	    R([manager addCookie: cookie1 forURI: URI1]))
	TEST(@"-[addCookie:forIRI:] #1",
	    R([manager addCookie: cookie1 forIRI: IRI1]))

	TEST(@"-[cookiesForURI:] #1",
	    [[manager cookiesForURI: URI1] isEqual:
	TEST(@"-[cookiesForIRI:] #1",
	    [[manager cookiesForIRI: IRI1] isEqual:
	    [OFArray arrayWithObject: cookie1]])

	cookie2 = [OFHTTPCookie cookieWithName: @"test"
					 value: @"2"
					domain: @"webkeks.org"];
	TEST(@"-[addCookie:forURI:] #2",
	    R([manager addCookie: cookie2 forURI: URI1]))
	TEST(@"-[addCookie:forIRI:] #2",
	    R([manager addCookie: cookie2 forIRI: IRI1]))

	TEST(@"-[cookiesForURI:] #2",
	    [[manager cookiesForURI: URI1] isEqual:
	TEST(@"-[cookiesForIRI:] #2",
	    [[manager cookiesForIRI: IRI1] isEqual:
	    [OFArray arrayWithObject: cookie1]] &&
	    [[manager cookiesForURI: URI4] isEqual: [OFArray array]])
	    [[manager cookiesForIRI: IRI4] isEqual: [OFArray array]])

	cookie3 = [OFHTTPCookie cookieWithName: @"test"
					 value: @"3"
					domain: @"nil.im"];
	cookie3.secure = true;
	TEST(@"-[addCookie:forURI:] #3",
	    R([manager addCookie: cookie3 forURI: URI2]))
	TEST(@"-[addCookie:forIRI:] #3",
	    R([manager addCookie: cookie3 forIRI: IRI2]))

	TEST(@"-[cookiesForURI:] #3",
	    [[manager cookiesForURI: URI2] isEqual:
	TEST(@"-[cookiesForIRI:] #3",
	    [[manager cookiesForIRI: IRI2] isEqual:
	    [OFArray arrayWithObject: cookie3]] &&
	    [[manager cookiesForURI: URI1] isEqual: [OFArray array]])
	    [[manager cookiesForIRI: IRI1] isEqual: [OFArray array]])

	cookie3.expires = [OFDate dateWithTimeIntervalSinceNow: -1];
	cookie4 = [OFHTTPCookie cookieWithName: @"test"
					 value: @"4"
					domain: @"nil.im"];
	cookie4.domain = @".nil.im";
	TEST(@"-[addCookie:forURI:] #4",
	    R([manager addCookie: cookie4 forURI: URI2]))
	TEST(@"-[addCookie:forIRI:] #4",
	    R([manager addCookie: cookie4 forIRI: IRI2]))

	TEST(@"-[cookiesForURI:] #4",
	    [[manager cookiesForURI: URI2] isEqual:
	TEST(@"-[cookiesForIRI:] #4",
	    [[manager cookiesForIRI: IRI2] isEqual:
	    [OFArray arrayWithObject: cookie4]] &&
	    [[manager cookiesForURI: URI3] isEqual:
	    [[manager cookiesForIRI: IRI3] isEqual:
	    [OFArray arrayWithObject: cookie4]])

	cookie5 = [OFHTTPCookie cookieWithName: @"bar"
					 value: @"5"
					domain: @"test.nil.im"];
	TEST(@"-[addCookie:forURI:] #5",
	    R([manager addCookie: cookie5 forURI: URI1]))
	TEST(@"-[addCookie:forIRI:] #5",
	    R([manager addCookie: cookie5 forIRI: IRI1]))

	TEST(@"-[cookiesForURI:] #5",
	    [[manager cookiesForURI: URI1] isEqual:
	TEST(@"-[cookiesForIRI:] #5",
	    [[manager cookiesForIRI: IRI1] isEqual:
	    [OFArray arrayWithObject: cookie4]] &&
	    [[manager cookiesForURI: URI3] isEqual:
	    [[manager cookiesForIRI: IRI3] isEqual:
	    [OFArray arrayWithObjects: cookie4, cookie5, nil]])

	TEST(@"-[purgeExpiredCookies]",
	    [manager.cookies isEqual:
	    [OFArray arrayWithObjects: cookie3, cookie4, cookie5, nil]] &&
	    R([manager purgeExpiredCookies]) &&
	    [manager.cookies isEqual:
	    [OFArray arrayWithObjects: cookie4, cookie5, nil]])

	objc_autoreleasePoolPop(pool);
}
@end

Modified tests/OFHTTPCookieTests.m from [beb8a32ced] to [5a5210bc98].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
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
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







-
+






-
+


-
+





-
+


-
+











-
+





-
+











static OFString *const module = @"OFHTTPCookie";

@implementation TestsAppDelegate (OFHTTPCookieTests)
- (void)HTTPCookieTests
{
	void *pool = objc_autoreleasePoolPush();
	OFURI *URI = [OFURI URIWithString: @"http://nil.im"];
	OFIRI *IRI = [OFIRI IRIWithString: @"http://nil.im"];
	OFHTTPCookie *cookie1, *cookie2;
	OFArray OF_GENERIC(OFHTTPCookie *) *cookies;

	cookie1 = [OFHTTPCookie cookieWithName: @"foo"
					 value: @"bar"
					domain: @"nil.im"];
	TEST(@"+[cookiesWithResponseHeaderFields:forURI:] #1",
	TEST(@"+[cookiesWithResponseHeaderFields:forIRI:] #1",
	    [[OFHTTPCookie cookiesWithResponseHeaderFields: [OFDictionary
	    dictionaryWithObject: @"foo=bar"
	    forKey: @"Set-Cookie"] forURI: URI]
	    forKey: @"Set-Cookie"] forIRI: IRI]
	    isEqual: [OFArray arrayWithObject: cookie1]])

	cookie2 = [OFHTTPCookie cookieWithName: @"qux"
					 value: @"cookie"
					domain: @"nil.im"];
	TEST(@"+[cookiesWithResponseHeaderFields:forURI:] #2",
	TEST(@"+[cookiesWithResponseHeaderFields:forIRI:] #2",
	    [[OFHTTPCookie cookiesWithResponseHeaderFields: [OFDictionary
	    dictionaryWithObject: @"foo=bar,qux=cookie"
	    forKey: @"Set-Cookie"] forURI: URI]
	    forKey: @"Set-Cookie"] forIRI: IRI]
	    isEqual: [OFArray arrayWithObjects: cookie1, cookie2, nil]])

	cookie1.expires = [OFDate dateWithTimeIntervalSince1970: 1234567890];
	cookie2.expires = [OFDate dateWithTimeIntervalSince1970: 1234567890];
	cookie1.path = @"/x";
	cookie2.domain = @"webkeks.org";
	cookie2.path = @"/objfw";
	cookie2.secure = true;
	cookie2.HTTPOnly = true;
	[cookie2.extensions addObject: @"foo"];
	[cookie2.extensions addObject: @"bar"];
	TEST(@"+[cookiesWithResponseHeaderFields:forURI:] #3",
	TEST(@"+[cookiesWithResponseHeaderFields:forIRI:] #3",
	    [(cookies = [OFHTTPCookie cookiesWithResponseHeaderFields:
	    [OFDictionary dictionaryWithObject:
	    @"foo=bar; Expires=Fri, 13 Feb 2009 23:31:30 GMT; Path=/x,"
	    @"qux=cookie; Expires=Fri, 13 Feb 2009 23:31:30 GMT; "
	    @"Domain=webkeks.org; Path=/objfw; Secure; HTTPOnly; foo; bar"
	    forKey: @"Set-Cookie"] forURI: URI]) isEqual:
	    forKey: @"Set-Cookie"] forIRI: IRI]) isEqual:
	    [OFArray arrayWithObjects: cookie1, cookie2, nil]])

	TEST(@"+[requestHeaderFieldsWithCookies:]",
	    [[OFHTTPCookie requestHeaderFieldsWithCookies: cookies] isEqual:
	    [OFDictionary dictionaryWithObject: @"foo=bar; qux=cookie"
					forKey: @"Cookie"]])

	objc_autoreleasePoolPop(pool);
}
@end

Modified tests/OFINIFileTests.m from [18e2931d0e] to [ba10e4092f].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
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
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







-
+




-
+




-
-
-
+
+
+







	    @"[types]\r\n"
	    @"integer=16\r\n"
	    @"bool=false\r\n"
	    @"float=0.25\r\n"
	    @"array1=foo\r\n"
	    @"array1=bar\r\n"
	    @"double=0.75\r\n";
	OFURI *URI;
	OFIRI *IRI;
	OFINIFile *file;
	OFINICategory *tests, *foobar, *types;
	OFArray *array;
#if defined(OF_HAVE_FILES) && !defined(OF_NINTENDO_DS)
	OFURI *writeURI;
	OFIRI *writeIRI;
#endif

	module = @"OFINIFile";

	URI = [OFURI URIWithString: @"embedded:testfile.ini"];
	TEST(@"+[fileWithURI:encoding:]",
	    (file = [OFINIFile fileWithURI: URI
	IRI = [OFIRI IRIWithString: @"embedded:testfile.ini"];
	TEST(@"+[fileWithIRI:encoding:]",
	    (file = [OFINIFile fileWithIRI: IRI
				  encoding: OFStringEncodingCodepage437]))

	tests = [file categoryForName: @"tests"];
	foobar = [file categoryForName: @"foobar"];
	types = [file categoryForName: @"types"];
	TEST(@"-[categoryForName:]",
	    tests != nil && foobar != nil && types != nil)
112
113
114
115
116
117
118
119
120
121





122
123

124
125

126
127
128

129
130
131
132
133
134
135
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







-
-
-
+
+
+
+
+

-
+

-
+


-
+







	    R([foobar removeValueForKey: @"quxqux "]) &&
	    R([types removeValueForKey: @"array2"]))

	module = @"OFINIFile";

	/* FIXME: Find a way to write files on Nintendo DS */
#if defined(OF_HAVE_FILES) && !defined(OF_NINTENDO_DS)
	writeURI = [[OFSystemInfo temporaryDirectoryURI]
	    URIByAppendingPathComponent: @"objfw-tests.ini"
			    isDirectory: false];
	writeIRI = [OFSystemInfo temporaryDirectoryIRI];
	if (writeIRI == nil)
		writeIRI = [[OFFileManager defaultManager] currentDirectoryIRI];
	writeIRI = [writeIRI IRIByAppendingPathComponent: @"objfw-tests.ini"
					     isDirectory: false];
	TEST(@"-[writeToFile:encoding:]",
	    R([file writeToURI: writeURI
	    R([file writeToIRI: writeIRI
		      encoding: OFStringEncodingCodepage437]) &&
	    [[OFString stringWithContentsOfURI: writeURI
	    [[OFString stringWithContentsOfIRI: writeIRI
				      encoding: OFStringEncodingCodepage437]
	    isEqual: output])
	[[OFFileManager defaultManager] removeItemAtURI: writeURI];
	[[OFFileManager defaultManager] removeItemAtIRI: writeIRI];
#else
	(void)output;
#endif

	objc_autoreleasePoolPop(pool);
}
@end

Modified tests/OFIPXSocketTests.m from [abf65b2714] to [9fd6f1a7eb].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
24
25
26
27
28
29
30

31
32

33
34
35
36
37
38
39
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41







+


+







@implementation TestsAppDelegate (OFIPXSocketTests)
- (void)IPXSocketTests
{
	const unsigned char zeroNode[IPX_NODE_LEN] = { 0 };
	void *pool = objc_autoreleasePoolPush();
	OFIPXSocket *sock;
	OFSocketAddress address1, address2;
	OFDictionary *networkInterfaces;
	char buffer[5];
	unsigned char node1[IPX_NODE_LEN], node2[IPX_NODE_LEN];
	unsigned char node[IPX_NODE_LEN];

	TEST(@"+[socket]", (sock = [OFIPXSocket socket]))

	@try {
		TEST(@"-[bindToNetwork:node:port:packetType:]",
		R(address1 = [sock bindToNetwork: 0
					    node: zeroNode
57
58
59
60
61
62
63































64
65
66
67
68
69
70
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







		default:
			@throw e;
		}

		objc_autoreleasePoolPop(pool);
		return;
	}

	/*
	 * Find any network interface with IPX and send to it. Any should be
	 * fine since we bound to 0.0.
	 */
	networkInterfaces = [OFSystemInfo networkInterfaces];
	for (OFString *name in networkInterfaces) {
		OFNetworkInterface interface = [networkInterfaces
		    objectForKey: name];
		OFData *addresses = [interface
		    objectForKey: OFNetworkInterfaceIPXAddresses];

		if (addresses.count == 0)
			continue;

		OFSocketAddressSetIPXNetwork(&address1,
		    OFSocketAddressIPXNetwork([addresses itemAtIndex: 0]));
		OFSocketAddressGetIPXNode([addresses itemAtIndex: 0], node);
		OFSocketAddressSetIPXNode(&address1, node);
	}

	OFSocketAddressGetIPXNode(&address1, node);
	if (OFSocketAddressIPXNetwork(&address1) == 0 &&
	    memcmp(node, zeroNode, 6) == 0) {
		[OFStdOut setForegroundColor: [OFColor lime]];
		[OFStdOut writeLine:
		    @"[OFIPXSocket] -[sendBuffer:length:receiver:]: "
		    @"Could not determine own address, skipping tests"];
		objc_autoreleasePoolPop(pool);
		return;
	}

	TEST(@"-[sendBuffer:length:receiver:]",
	    R([sock sendBuffer: "Hello" length: 5 receiver: &address1]))

	TEST(@"-[receiveIntoBuffer:length:sender:]",
	    [sock receiveIntoBuffer: buffer length: 5 sender: &address2] == 5 &&
	    memcmp(buffer, "Hello", 5) == 0 &&

Renamed and modified tests/OFURITests.m [e9cb46977b] to tests/OFIRITests.m [96d1dc951e].

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
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
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
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
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
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
359
360
361
362
363
364
365
366
367
368
369
370
371

-
+

















-
-
+
+


-
-
+
+


-
-
-
+
+
+

-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

+
+
+
+
-
-
+
+

-
-
+
+

-
-
+
+

-
-
-
-
+
+
+
+

-
-
+
+



-
+

-
+


-
+

-
+


-
+

-
+


-
+

-
+


-
-
+
+




-
-
-
+
+
+





-
-
+
+




-
+







-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+


-
-
+
+
+

-
-
+
+

-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+

-
-
-
-
-
+
+
+
+
+
+

-
+

-
+

-
+


-
+

-
+

-
+

-
+

-
+

-
-
+
+
+

-
+



-
-
-
+
+
+

-
+

-
-
+
+

-
+


-
+

+
+
+
+
-
+



-
+


-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+


-
-
-
-
-
-
+
+
+
+
+
+




-
+




-
+




-
+


-
-
+
+


-
-
+
+




-
+


-
-
+
+


-
-
+
+




-
+


-
-
+
+


-
-
+
+




-
+


-
-
+
+


-
-
+
+




-
+


-
+


-
+



-
-
+
+


-
-
+
+




-
+

-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+




/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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 "TestsAppDelegate.h"

static OFString *const module = @"OFURI";
static OFString *URIString = @"ht+tp://us%3Aer:p%40w@ho%3Ast:1234/"
static OFString *const module = @"OFIRI";
static OFString *IRIString = @"ht+tp://us%3Aer:p%40w@ho%3Ast:1234/"
    @"pa%3Fth?que%23ry=1&f%26oo=b%3dar#frag%23ment";

@implementation TestsAppDelegate (OFURITests)
- (void)URITests
@implementation TestsAppDelegate (OFIRITests)
- (void)IRITests
{
	void *pool = objc_autoreleasePoolPush();
	OFURI *URI1, *URI2, *URI3, *URI4, *URI5, *URI6, *URI7, *URI8, *URI9;
	OFURI *URI10;
	OFMutableURI *mutableURI;
	OFIRI *IRI1, *IRI2, *IRI3, *IRI4, *IRI5, *IRI6, *IRI7, *IRI8, *IRI9;
	OFIRI *IRI10, *IRI11;
	OFMutableIRI *mutableIRI;

	TEST(@"+[URIWithString:]",
	    R(URI1 = [OFURI URIWithString: URIString]) &&
	    R(URI2 = [OFURI URIWithString: @"http://foo:80"]) &&
	    R(URI3 = [OFURI URIWithString: @"http://bar/"]) &&
	    R(URI4 = [OFURI URIWithString: @"file:///etc/passwd"]) &&
	    R(URI5 = [OFURI URIWithString: @"http://foo/bar/qux/foo%2fbar"]) &&
	    R(URI6 = [OFURI URIWithString: @"https://[12:34::56:abcd]/"]) &&
	    R(URI7 = [OFURI URIWithString: @"https://[12:34::56:abcd]:234/"]) &&
	    R(URI8 = [OFURI URIWithString: @"urn:qux:foo"]) &&
	    R(URI9 = [OFURI URIWithString: @"file:/foo?query#frag"]) &&
	    R(URI10 = [OFURI URIWithString: @"file:foo@bar/qux?query#frag"]))
	TEST(@"+[IRIWithString:]",
	    R(IRI1 = [OFIRI IRIWithString: IRIString]) &&
	    R(IRI2 = [OFIRI IRIWithString: @"http://foo:80"]) &&
	    R(IRI3 = [OFIRI IRIWithString: @"http://bar/"]) &&
	    R(IRI4 = [OFIRI IRIWithString: @"file:///etc/passwd"]) &&
	    R(IRI5 = [OFIRI IRIWithString: @"http://foo/bar/qux/foo%2fbar"]) &&
	    R(IRI6 = [OFIRI IRIWithString: @"https://[12:34::56:abcd]/"]) &&
	    R(IRI7 = [OFIRI IRIWithString: @"https://[12:34::56:abcd]:234/"]) &&
	    R(IRI8 = [OFIRI IRIWithString: @"urn:qux:foo"]) &&
	    R(IRI9 = [OFIRI IRIWithString: @"file:/foo?query#frag"]) &&
	    R(IRI10 = [OFIRI IRIWithString: @"file:foo@bar/qux?query#frag"]) &&
	    R(IRI11 = [OFIRI IRIWithString: @"http://ä/ö?ü"]))

	EXPECT_EXCEPTION(@"+[URIWithString:] fails with invalid characters #1",
	EXPECT_EXCEPTION(@"+[IRIWithString:] fails with invalid characters #1",
	    OFInvalidFormatException,
	    [OFURI URIWithString: @"ht,tp://foo"])
	    [OFIRI IRIWithString: @"ht,tp://foo"])

	EXPECT_EXCEPTION(@"+[URIWithString:] fails with invalid characters #2",
	EXPECT_EXCEPTION(@"+[IRIWithString:] fails with invalid characters #2",
	    OFInvalidFormatException,
	    [OFURI URIWithString: @"http://f`oo"])
	    [OFIRI IRIWithString: @"http://f`oo"])

	EXPECT_EXCEPTION(@"+[URIWithString:] fails with invalid characters #3",
	EXPECT_EXCEPTION(@"+[IRIWithString:] fails with invalid characters #3",
	    OFInvalidFormatException,
	    [OFURI URIWithString: @"http://foo/`"])
	    [OFIRI IRIWithString: @"http://foo/`"])

	EXPECT_EXCEPTION(@"+[URIWithString:] fails with invalid characters #4",
	EXPECT_EXCEPTION(@"+[IRIWithString:] fails with invalid characters #4",
	    OFInvalidFormatException,
	    [OFURI URIWithString: @"http://foo/foo?`"])
	    [OFIRI IRIWithString: @"http://foo/foo?`"])

	EXPECT_EXCEPTION(@"+[URIWithString:] fails with invalid characters #5",
	EXPECT_EXCEPTION(@"+[IRIWithString:] fails with invalid characters #5",
	    OFInvalidFormatException,
	    [OFURI URIWithString: @"http://foo/foo?foo#`"])
	    [OFIRI IRIWithString: @"http://foo/foo?foo#`"])

	EXPECT_EXCEPTION(@"+[URIWithString:] fails with invalid characters #6",
	EXPECT_EXCEPTION(@"+[IRIWithString:] fails with invalid characters #6",
	    OFInvalidFormatException,
	    [OFURI URIWithString: @"https://[g]/"])
	    [OFIRI IRIWithString: @"https://[g]/"])

	EXPECT_EXCEPTION(@"+[URIWithString:] fails with invalid characters #7",
	EXPECT_EXCEPTION(@"+[IRIWithString:] fails with invalid characters #7",
	    OFInvalidFormatException,
	    [OFURI URIWithString: @"https://[f]:/"])
	    [OFIRI IRIWithString: @"https://[f]:/"])

	EXPECT_EXCEPTION(@"+[URIWithString:] fails with invalid characters #8",
	EXPECT_EXCEPTION(@"+[IRIWithString:] fails with invalid characters #8",
	    OFInvalidFormatException,
	    [OFURI URIWithString: @"https://[f]:f/"])
	    [OFIRI IRIWithString: @"https://[f]:f/"])

	EXPECT_EXCEPTION(@"+[IRIWithString:] fails with invalid characters #9",
	    OFInvalidFormatException,
	    [OFIRI IRIWithString: @"foo:"])

	TEST(@"+[URIWithString:relativeToURI:]",
	    [[[OFURI URIWithString: @"/foo" relativeToURI: URI1] string]
	TEST(@"+[IRIWithString:relativeToIRI:]",
	    [[[OFIRI IRIWithString: @"/foo" relativeToIRI: IRI1] string]
	    isEqual: @"ht+tp://us%3Aer:p%40w@ho%3Ast:1234/foo"] &&
	    [[[OFURI URIWithString: @"foo/bar?q"
		     relativeToURI: [OFURI URIWithString: @"http://h/qux/quux"]]
	    [[[OFIRI IRIWithString: @"foo/bar?q"
		     relativeToIRI: [OFIRI IRIWithString: @"http://h/qux/quux"]]
	    string] isEqual: @"http://h/qux/foo/bar?q"] &&
	    [[[OFURI URIWithString: @"foo/bar"
		     relativeToURI: [OFURI URIWithString: @"http://h/qux/?x"]]
	    [[[OFIRI IRIWithString: @"foo/bar"
		     relativeToIRI: [OFIRI IRIWithString: @"http://h/qux/?x"]]
	    string] isEqual: @"http://h/qux/foo/bar"] &&
	    [[[OFURI URIWithString: @"http://foo/?q"
		     relativeToURI: URI1] string] isEqual: @"http://foo/?q"] &&
	    [[[OFURI URIWithString: @"foo"
		     relativeToURI: [OFURI URIWithString: @"http://foo/bar"]]
	    [[[OFIRI IRIWithString: @"http://foo/?q"
		     relativeToIRI: IRI1] string] isEqual: @"http://foo/?q"] &&
	    [[[OFIRI IRIWithString: @"foo"
		     relativeToIRI: [OFIRI IRIWithString: @"http://foo/bar"]]
	    string] isEqual: @"http://foo/foo"] &&
	    [[[OFURI URIWithString: @"foo"
		     relativeToURI: [OFURI URIWithString: @"http://foo"]]
	    [[[OFIRI IRIWithString: @"foo"
		     relativeToIRI: [OFIRI IRIWithString: @"http://foo"]]
	    string] isEqual: @"http://foo/foo"])

	EXPECT_EXCEPTION(
	    @"+[URIWithString:relativeToURI:] fails with invalid characters #1",
	    @"+[IRIWithString:relativeToIRI:] fails with invalid characters #1",
	    OFInvalidFormatException,
	    [OFURI URIWithString: @"`" relativeToURI: URI1])
	    [OFIRI IRIWithString: @"`" relativeToIRI: IRI1])

	EXPECT_EXCEPTION(
	    @"+[URIWithString:relativeToURI:] fails with invalid characters #2",
	    @"+[IRIWithString:relativeToIRI:] fails with invalid characters #2",
	    OFInvalidFormatException,
	    [OFURI URIWithString: @"/`" relativeToURI: URI1])
	    [OFIRI IRIWithString: @"/`" relativeToIRI: IRI1])

	EXPECT_EXCEPTION(
	    @"+[URIWithString:relativeToURI:] fails with invalid characters #3",
	    @"+[IRIWithString:relativeToIRI:] fails with invalid characters #3",
	    OFInvalidFormatException,
	    [OFURI URIWithString: @"?`" relativeToURI: URI1])
	    [OFIRI IRIWithString: @"?`" relativeToIRI: IRI1])

	EXPECT_EXCEPTION(
	    @"+[URIWithString:relativeToURI:] fails with invalid characters #4",
	    @"+[IRIWithString:relativeToIRI:] fails with invalid characters #4",
	    OFInvalidFormatException,
	    [OFURI URIWithString: @"#`" relativeToURI: URI1])
	    [OFIRI IRIWithString: @"#`" relativeToIRI: IRI1])

#ifdef OF_HAVE_FILES
	TEST(@"+[fileURIWithPath:]",
	    [[[OFURI fileURIWithPath: @"testfile.txt"] fileSystemRepresentation]
	TEST(@"+[fileIRIWithPath:]",
	    [[[OFIRI fileIRIWithPath: @"testfile.txt"] fileSystemRepresentation]
	    isEqual: [[OFFileManager defaultManager].currentDirectoryPath
	    stringByAppendingPathComponent: @"testfile.txt"]])

# if defined(OF_WINDOWS) || defined(OF_MSDOS)
	OFURI *tmp;
	TEST(@"+[fileURIWithPath:] for c:\\",
	    (tmp = [OFURI fileURIWithPath: @"c:\\"]) &&
	OFIRI *tmp;
	TEST(@"+[fileIRIWithPath:] for c:\\",
	    (tmp = [OFIRI fileIRIWithPath: @"c:\\"]) &&
	    [tmp.string isEqual: @"file:/c:/"] &&
	    [tmp.fileSystemRepresentation isEqual: @"c:\\"])
# endif

# ifdef OF_WINDOWS
	TEST(@"+[fileURIWithPath:] with UNC",
	    (tmp = [OFURI fileURIWithPath: @"\\\\foo\\bar"
	TEST(@"+[fileIRIWithPath:] with UNC",
	    (tmp = [OFIRI fileIRIWithPath: @"\\\\foo\\bar"
			      isDirectory: false]) &&
	    [tmp.host isEqual: @"foo"] && [tmp.path isEqual: @"/bar"] &&
	    [tmp.string isEqual: @"file://foo/bar"] &&
	    [tmp.fileSystemRepresentation isEqual: @"\\\\foo\\bar"] &&
	    (tmp = [OFURI fileURIWithPath: @"\\\\test" isDirectory: true]) &&
	    (tmp = [OFIRI fileIRIWithPath: @"\\\\test" isDirectory: true]) &&
	    [tmp.host isEqual: @"test"] && [tmp.path isEqual: @"/"] &&
	    [tmp.string isEqual: @"file://test/"] &&
	    [tmp.fileSystemRepresentation isEqual: @"\\\\test"])
# endif
#endif

	TEST(@"-[string]",
	    [URI1.string isEqual: URIString] &&
	    [URI2.string isEqual: @"http://foo:80"] &&
	    [URI3.string isEqual: @"http://bar/"] &&
	    [URI4.string isEqual: @"file:///etc/passwd"] &&
	    [URI5.string isEqual: @"http://foo/bar/qux/foo%2fbar"] &&
	    [URI6.string isEqual: @"https://[12:34::56:abcd]/"] &&
	    [URI7.string isEqual: @"https://[12:34::56:abcd]:234/"] &&
	    [URI8.string isEqual: @"urn:qux:foo"] &&
	    [URI9.string isEqual: @"file:/foo?query#frag"] &&
	    [URI10.string isEqual: @"file:foo@bar/qux?query#frag"])
	    [IRI1.string isEqual: IRIString] &&
	    [IRI2.string isEqual: @"http://foo:80"] &&
	    [IRI3.string isEqual: @"http://bar/"] &&
	    [IRI4.string isEqual: @"file:///etc/passwd"] &&
	    [IRI5.string isEqual: @"http://foo/bar/qux/foo%2fbar"] &&
	    [IRI6.string isEqual: @"https://[12:34::56:abcd]/"] &&
	    [IRI7.string isEqual: @"https://[12:34::56:abcd]:234/"] &&
	    [IRI8.string isEqual: @"urn:qux:foo"] &&
	    [IRI9.string isEqual: @"file:/foo?query#frag"] &&
	    [IRI10.string isEqual: @"file:foo@bar/qux?query#frag"] &&
	    [IRI11.string isEqual: @"http://ä/ö?ü"])

	TEST(@"-[scheme]",
	    [URI1.scheme isEqual: @"ht+tp"] && [URI4.scheme isEqual: @"file"] &&
	    [URI9.scheme isEqual: @"file"] && [URI10.scheme isEqual: @"file"])
	    [IRI1.scheme isEqual: @"ht+tp"] && [IRI4.scheme isEqual: @"file"] &&
	    [IRI9.scheme isEqual: @"file"] && [IRI10.scheme isEqual: @"file"] &&
	    [IRI11.scheme isEqual: @"http"])

	TEST(@"-[user]", [URI1.user isEqual: @"us:er"] && URI4.user == nil &&
	    URI10.user == nil)
	TEST(@"-[user]", [IRI1.user isEqual: @"us:er"] && IRI4.user == nil &&
	    IRI10.user == nil && IRI11.user == nil)
	TEST(@"-[password]",
	    [URI1.password isEqual: @"p@w"] && URI4.password == nil &&
	    URI10.password == nil)
	TEST(@"-[host]", [URI1.host isEqual: @"ho:st"] &&
	    [URI6.host isEqual: @"12:34::56:abcd"] &&
	    [URI7.host isEqual: @"12:34::56:abcd"] &&
	    URI8.host == nil && URI9.host == nil && URI10.host == nil)
	TEST(@"-[port]", URI1.port.unsignedShortValue == 1234 &&
	    [URI4 port] == nil && URI7.port.unsignedShortValue == 234 &&
	    URI8.port == nil && URI9.port == nil && URI10.port == nil)
	    [IRI1.password isEqual: @"p@w"] && IRI4.password == nil &&
	    IRI10.password == nil && IRI11.password == nil)
	TEST(@"-[host]", [IRI1.host isEqual: @"ho:st"] &&
	    [IRI6.host isEqual: @"12:34::56:abcd"] &&
	    [IRI7.host isEqual: @"12:34::56:abcd"] &&
	    IRI8.host == nil && IRI9.host == nil && IRI10.host == nil &&
	    [IRI11.host isEqual: @"ä"])
	TEST(@"-[port]", IRI1.port.unsignedShortValue == 1234 &&
	    [IRI4 port] == nil && IRI7.port.unsignedShortValue == 234 &&
	    IRI8.port == nil && IRI9.port == nil && IRI10.port == nil &&
	    IRI11.port == nil)
	TEST(@"-[path]",
	    [URI1.path isEqual: @"/pa?th"] &&
	    [URI4.path isEqual: @"/etc/passwd"] &&
	    [URI8.path isEqual: @"qux:foo"] &&
	    [URI9.path isEqual: @"/foo"] &&
	    [URI10.path isEqual: @"foo@bar/qux"])
	    [IRI1.path isEqual: @"/pa?th"] &&
	    [IRI4.path isEqual: @"/etc/passwd"] &&
	    [IRI8.path isEqual: @"qux:foo"] &&
	    [IRI9.path isEqual: @"/foo"] &&
	    [IRI10.path isEqual: @"foo@bar/qux"] &&
	    [IRI11.path isEqual: @"/ö"])
	TEST(@"-[pathComponents]",
	    [URI1.pathComponents isEqual:
	    [IRI1.pathComponents isEqual:
	    [OFArray arrayWithObjects: @"/", @"pa?th", nil]] &&
	    [URI4.pathComponents isEqual:
	    [IRI4.pathComponents isEqual:
	    [OFArray arrayWithObjects: @"/", @"etc", @"passwd", nil]] &&
	    [URI5.pathComponents isEqual:
	    [IRI5.pathComponents isEqual:
	    [OFArray arrayWithObjects: @"/", @"bar", @"qux", @"foo/bar", nil]])
	TEST(@"-[lastPathComponent]",
	    [[[OFURI URIWithString: @"http://host/foo//bar/baz"]
	    [[[OFIRI IRIWithString: @"http://host/foo//bar/baz"]
	    lastPathComponent] isEqual: @"baz"] &&
	    [[[OFURI URIWithString: @"http://host/foo//bar/baz/"]
	    [[[OFIRI IRIWithString: @"http://host/foo//bar/baz/"]
	    lastPathComponent] isEqual: @"baz"] &&
	    [[[OFURI URIWithString: @"http://host/foo/"]
	    [[[OFIRI IRIWithString: @"http://host/foo/"]
	    lastPathComponent] isEqual: @"foo"] &&
	    [[[OFURI URIWithString: @"http://host/"]
	    [[[OFIRI IRIWithString: @"http://host/"]
	    lastPathComponent] isEqual: @"/"] &&
	    [URI5.lastPathComponent isEqual: @"foo/bar"])
	    [IRI5.lastPathComponent isEqual: @"foo/bar"])
	TEST(@"-[query]",
	    [URI1.query isEqual: @"que#ry=1&f&oo=b=ar"] && URI4.query == nil &&
	    [URI9.query isEqual: @"query"] && [URI10.query isEqual: @"query"])
	    [IRI1.query isEqual: @"que#ry=1&f&oo=b=ar"] && IRI4.query == nil &&
	    [IRI9.query isEqual: @"query"] && [IRI10.query isEqual: @"query"] &&
	    [IRI11.query isEqual: @"ü"])
	TEST(@"-[queryItems]",
	    [URI1.queryItems isEqual: [OFArray arrayWithObjects:
	    [IRI1.queryItems isEqual: [OFArray arrayWithObjects:
	    [OFPair pairWithFirstObject: @"que#ry" secondObject: @"1"],
	    [OFPair pairWithFirstObject: @"f&oo" secondObject: @"b=ar"], nil]]);
	TEST(@"-[fragment]",
	    [URI1.fragment isEqual: @"frag#ment"] && URI4.fragment == nil &&
	    [URI9.fragment isEqual: @"frag"] &&
	    [URI10.fragment isEqual: @"frag"])
	    [IRI1.fragment isEqual: @"frag#ment"] && IRI4.fragment == nil &&
	    [IRI9.fragment isEqual: @"frag"] &&
	    [IRI10.fragment isEqual: @"frag"])

	TEST(@"-[copy]", R(URI4 = [[URI1 copy] autorelease]))
	TEST(@"-[copy]", R(IRI4 = [[IRI1 copy] autorelease]))

	TEST(@"-[isEqual:]", [URI1 isEqual: URI4] && ![URI2 isEqual: URI3] &&
	    [[OFURI URIWithString: @"HTTP://bar/"] isEqual: URI3])
	TEST(@"-[isEqual:]", [IRI1 isEqual: IRI4] && ![IRI2 isEqual: IRI3] &&
	    [[OFIRI IRIWithString: @"HTTP://bar/"] isEqual: IRI3])

	TEST(@"-[hash:]", URI1.hash == URI4.hash && URI2.hash != URI3.hash)
	TEST(@"-[hash:]", IRI1.hash == IRI4.hash && IRI2.hash != IRI3.hash)

	EXPECT_EXCEPTION(@"Detection of invalid format",
	    OFInvalidFormatException, [OFURI URIWithString: @"http"])
	    OFInvalidFormatException, [OFIRI IRIWithString: @"http"])

	TEST(@"-[IRIByAddingPercentEncodingForUnicodeCharacters]",
	    [IRI11.IRIByAddingPercentEncodingForUnicodeCharacters
	    isEqual: [OFIRI IRIWithString: @"http://%C3%A4/%C3%B6?%C3%BC"]])

	mutableURI = [OFMutableURI URIWithScheme: @"dummy"];
	mutableIRI = [OFMutableIRI IRIWithScheme: @"dummy"];

	EXPECT_EXCEPTION(
	    @"-[setPercentEncodedScheme:] with invalid characters fails",
	    OFInvalidFormatException, mutableURI.scheme = @"%20")
	    OFInvalidFormatException, mutableIRI.scheme = @"%20")

	TEST(@"-[setHost:]",
	    (mutableURI.host = @"ho:st") &&
	    [mutableURI.percentEncodedHost isEqual: @"ho%3Ast"] &&
	    (mutableURI.host = @"12:34:ab") &&
	    [mutableURI.percentEncodedHost isEqual: @"[12:34:ab]"] &&
	    (mutableURI.host = @"12:34:aB") &&
	    [mutableURI.percentEncodedHost isEqual: @"[12:34:aB]"] &&
	    (mutableURI.host = @"12:34:g") &&
	    [mutableURI.percentEncodedHost isEqual: @"12%3A34%3Ag"])
	    (mutableIRI.host = @"ho:st") &&
	    [mutableIRI.percentEncodedHost isEqual: @"ho%3Ast"] &&
	    (mutableIRI.host = @"12:34:ab") &&
	    [mutableIRI.percentEncodedHost isEqual: @"[12:34:ab]"] &&
	    (mutableIRI.host = @"12:34:aB") &&
	    [mutableIRI.percentEncodedHost isEqual: @"[12:34:aB]"] &&
	    (mutableIRI.host = @"12:34:g") &&
	    [mutableIRI.percentEncodedHost isEqual: @"12%3A34%3Ag"])

	TEST(@"-[setPercentEncodedHost:]",
	    (mutableURI.percentEncodedHost = @"ho%3Ast") &&
	    [mutableURI.host isEqual: @"ho:st"] &&
	    (mutableURI.percentEncodedHost = @"[12:34]") &&
	    [mutableURI.host isEqual: @"12:34"] &&
	    (mutableURI.percentEncodedHost = @"[12::ab]") &&
	    [mutableURI.host isEqual: @"12::ab"])
	    (mutableIRI.percentEncodedHost = @"ho%3Ast") &&
	    [mutableIRI.host isEqual: @"ho:st"] &&
	    (mutableIRI.percentEncodedHost = @"[12:34]") &&
	    [mutableIRI.host isEqual: @"12:34"] &&
	    (mutableIRI.percentEncodedHost = @"[12::ab]") &&
	    [mutableIRI.host isEqual: @"12::ab"])

	EXPECT_EXCEPTION(
	    @"-[setPercentEncodedHost:] with invalid characters fails #1",
	    OFInvalidFormatException,
	    mutableURI.percentEncodedHost = @"/")
	    mutableIRI.percentEncodedHost = @"/")

	EXPECT_EXCEPTION(
	    @"-[setPercentEncodedHost:] with invalid characters fails #2",
	    OFInvalidFormatException,
	    mutableURI.percentEncodedHost = @"[12:34")
	    mutableIRI.percentEncodedHost = @"[12:34")

	EXPECT_EXCEPTION(
	    @"-[setPercentEncodedHost:] with invalid characters fails #3",
	    OFInvalidFormatException,
	    mutableURI.percentEncodedHost = @"[a::g]")
	    mutableIRI.percentEncodedHost = @"[a::g]")

	TEST(@"-[setUser:]",
	    (mutableURI.user = @"us:er") &&
	    [mutableURI.percentEncodedUser isEqual: @"us%3Aer"])
	    (mutableIRI.user = @"us:er") &&
	    [mutableIRI.percentEncodedUser isEqual: @"us%3Aer"])

	TEST(@"-[setPercentEncodedUser:]",
	    (mutableURI.percentEncodedUser = @"us%3Aer") &&
	    [mutableURI.user isEqual: @"us:er"])
	    (mutableIRI.percentEncodedUser = @"us%3Aer") &&
	    [mutableIRI.user isEqual: @"us:er"])

	EXPECT_EXCEPTION(
	    @"-[setPercentEncodedUser:] with invalid characters fails",
	    OFInvalidFormatException,
	    mutableURI.percentEncodedHost = @"/")
	    mutableIRI.percentEncodedHost = @"/")

	TEST(@"-[setPassword:]",
	    (mutableURI.password = @"pass:word") &&
	    [mutableURI.percentEncodedPassword isEqual: @"pass%3Aword"])
	    (mutableIRI.password = @"pass:word") &&
	    [mutableIRI.percentEncodedPassword isEqual: @"pass%3Aword"])

	TEST(@"-[setPercentEncodedPassword:]",
	    (mutableURI.percentEncodedPassword = @"pass%3Aword") &&
	    [mutableURI.password isEqual: @"pass:word"])
	    (mutableIRI.percentEncodedPassword = @"pass%3Aword") &&
	    [mutableIRI.password isEqual: @"pass:word"])

	EXPECT_EXCEPTION(
	    @"-[setPercentEncodedPassword:] with invalid characters fails",
	    OFInvalidFormatException,
	    mutableURI.percentEncodedPassword = @"/")
	    mutableIRI.percentEncodedPassword = @"/")

	TEST(@"-[setPath:]",
	    (mutableURI.path = @"pa/th@?") &&
	    [mutableURI.percentEncodedPath isEqual: @"pa/th@%3F"])
	    (mutableIRI.path = @"pa/th@?") &&
	    [mutableIRI.percentEncodedPath isEqual: @"pa/th@%3F"])

	TEST(@"-[setPercentEncodedPath:]",
	    (mutableURI.percentEncodedPath = @"pa/th@%3F") &&
	    [mutableURI.path isEqual: @"pa/th@?"])
	    (mutableIRI.percentEncodedPath = @"pa/th@%3F") &&
	    [mutableIRI.path isEqual: @"pa/th@?"])

	EXPECT_EXCEPTION(
	    @"-[setPercentEncodedPath:] with invalid characters fails",
	    OFInvalidFormatException,
	    mutableURI.percentEncodedPath = @"?")
	    mutableIRI.percentEncodedPath = @"?")

	TEST(@"-[setQuery:]",
	    (mutableURI.query = @"que/ry?#") &&
	    [mutableURI.percentEncodedQuery isEqual: @"que/ry?%23"])
	    (mutableIRI.query = @"que/ry?#") &&
	    [mutableIRI.percentEncodedQuery isEqual: @"que/ry?%23"])

	TEST(@"-[setPercentEncodedQuery:]",
	    (mutableURI.percentEncodedQuery = @"que/ry?%23") &&
	    [mutableURI.query isEqual: @"que/ry?#"])
	    (mutableIRI.percentEncodedQuery = @"que/ry?%23") &&
	    [mutableIRI.query isEqual: @"que/ry?#"])

	EXPECT_EXCEPTION(
	    @"-[setPercentEncodedQuery:] with invalid characters fails",
	    OFInvalidFormatException,
	    mutableURI.percentEncodedQuery = @"`")
	    mutableIRI.percentEncodedQuery = @"`")

	TEST(@"-[setQueryItems:]",
	    (mutableURI.queryItems = [OFArray arrayWithObjects:
	    (mutableIRI.queryItems = [OFArray arrayWithObjects:
	    [OFPair pairWithFirstObject: @"foo&bar" secondObject: @"baz=qux"],
	    [OFPair pairWithFirstObject: @"f=oobar" secondObject: @"b&azqux"],
	    nil]) && [mutableURI.percentEncodedQuery isEqual:
	    nil]) && [mutableIRI.percentEncodedQuery isEqual:
	    @"foo%26bar=baz%3Dqux&f%3Doobar=b%26azqux"])

	TEST(@"-[setFragment:]",
	    (mutableURI.fragment = @"frag/ment?#") &&
	    [mutableURI.percentEncodedFragment isEqual: @"frag/ment?%23"])
	    (mutableIRI.fragment = @"frag/ment?#") &&
	    [mutableIRI.percentEncodedFragment isEqual: @"frag/ment?%23"])

	TEST(@"-[setPercentEncodedFragment:]",
	    (mutableURI.percentEncodedFragment = @"frag/ment?%23") &&
	    [mutableURI.fragment isEqual: @"frag/ment?#"])
	    (mutableIRI.percentEncodedFragment = @"frag/ment?%23") &&
	    [mutableIRI.fragment isEqual: @"frag/ment?#"])

	EXPECT_EXCEPTION(
	    @"-[setPercentEncodedFragment:] with invalid characters fails",
	    OFInvalidFormatException,
	    mutableURI.percentEncodedFragment = @"`")
	    mutableIRI.percentEncodedFragment = @"`")

	TEST(@"-[URIByAppendingPathComponent:isDirectory:]",
	    [[[OFURI URIWithString: @"file:///foo/bar"]
	    URIByAppendingPathComponent: @"qux" isDirectory: false] isEqual:
	    [OFURI URIWithString: @"file:///foo/bar/qux"]] &&
	    [[[OFURI URIWithString: @"file:///foo/bar/"]
	    URIByAppendingPathComponent: @"qux" isDirectory: false] isEqual:
	    [OFURI URIWithString: @"file:///foo/bar/qux"]] &&
	    [[[OFURI URIWithString: @"file:///foo/bar/"]
	    URIByAppendingPathComponent: @"qu?x" isDirectory: false] isEqual:
	    [OFURI URIWithString: @"file:///foo/bar/qu%3Fx"]] &&
	    [[[OFURI URIWithString: @"file:///foo/bar/"]
	    URIByAppendingPathComponent: @"qu?x" isDirectory: true] isEqual:
	    [OFURI URIWithString: @"file:///foo/bar/qu%3Fx/"]])
	TEST(@"-[IRIByAppendingPathComponent:isDirectory:]",
	    [[[OFIRI IRIWithString: @"file:///foo/bar"]
	    IRIByAppendingPathComponent: @"qux" isDirectory: false] isEqual:
	    [OFIRI IRIWithString: @"file:///foo/bar/qux"]] &&
	    [[[OFIRI IRIWithString: @"file:///foo/bar/"]
	    IRIByAppendingPathComponent: @"qux" isDirectory: false] isEqual:
	    [OFIRI IRIWithString: @"file:///foo/bar/qux"]] &&
	    [[[OFIRI IRIWithString: @"file:///foo/bar/"]
	    IRIByAppendingPathComponent: @"qu?x" isDirectory: false] isEqual:
	    [OFIRI IRIWithString: @"file:///foo/bar/qu%3Fx"]] &&
	    [[[OFIRI IRIWithString: @"file:///foo/bar/"]
	    IRIByAppendingPathComponent: @"qu?x" isDirectory: true] isEqual:
	    [OFIRI IRIWithString: @"file:///foo/bar/qu%3Fx/"]])

	TEST(@"-[URIByStandardizingPath]",
	    [[[OFURI URIWithString: @"http://foo/bar/.."]
	    URIByStandardizingPath] isEqual:
	    [OFURI URIWithString: @"http://foo/"]] &&
	    [[[OFURI URIWithString: @"http://foo/bar/%2E%2E/../qux/"]
	    URIByStandardizingPath] isEqual:
	    [OFURI URIWithString: @"http://foo/bar/qux/"]] &&
	    [[[OFURI URIWithString: @"http://foo/bar/./././qux/./"]
	    URIByStandardizingPath] isEqual:
	    [OFURI URIWithString: @"http://foo/bar/qux/"]] &&
	    [[[OFURI URIWithString: @"http://foo/bar/../../qux"]
	    URIByStandardizingPath] isEqual:
	    [OFURI URIWithString: @"http://foo/../qux"]])
	TEST(@"-[IRIByStandardizingPath]",
	    [[[OFIRI IRIWithString: @"http://foo/bar/.."]
	    IRIByStandardizingPath] isEqual:
	    [OFIRI IRIWithString: @"http://foo/"]] &&
	    [[[OFIRI IRIWithString: @"http://foo/bar/%2E%2E/../qux/"]
	    IRIByStandardizingPath] isEqual:
	    [OFIRI IRIWithString: @"http://foo/bar/qux/"]] &&
	    [[[OFIRI IRIWithString: @"http://foo/bar/./././qux/./"]
	    IRIByStandardizingPath] isEqual:
	    [OFIRI IRIWithString: @"http://foo/bar/qux/"]] &&
	    [[[OFIRI IRIWithString: @"http://foo/bar/../../qux"]
	    IRIByStandardizingPath] isEqual:
	    [OFIRI IRIWithString: @"http://foo/../qux"]])

	objc_autoreleasePoolPop(pool);
}
@end

Modified tests/OFInvocationTests.m from [3c3f2f66f1] to [0b0e05bf26].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified tests/OFJSONTests.m from [330199594e] to [cf63bd9e05].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified tests/OFKernelEventObserverTests.m from [cec268df6c] to [25c104eb19].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
49
50
51
52
53
54
55
56

57
58
59
60
61

62
63
64
65


66
67
68
69
70
71
72
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







-
+




-
+



-
+
+








@implementation ObserverTest
- (instancetype)initWithTestsAppDelegate: (TestsAppDelegate *)testsAppDelegate
{
	self = [super init];

	@try {
		uint16_t port;
		OFSocketAddress address;

		_testsAppDelegate = testsAppDelegate;

		_server = [[OFTCPSocket alloc] init];
		port = [_server bindToHost: @"127.0.0.1" port: 0];
		address = [_server bindToHost: @"127.0.0.1" port: 0];
		[_server listen];

		_client = [[OFTCPSocket alloc] init];
		[_client connectToHost: @"127.0.0.1" port: port];
		[_client connectToHost: @"127.0.0.1"
				  port: OFSocketAddressIPPort(&address)];
		[_client writeBuffer: "0" length: 1];
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;

Modified tests/OFListTests.m from [43f56ef79d] to [3ea276b9af].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified tests/OFLocaleTests.m from [a51f4edb4e] to [ad85bb38c7].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified tests/OFMD5HashTests.m from [5005b07061] to [b6ff11bd7a].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
25
26
27
28
29
30
31
32
33


34
35
36
37
38
39
40
25
26
27
28
29
30
31


32
33
34
35
36
37
38
39
40







-
-
+
+







    "\x00\x8B\x9D\x1B\x58\xDF\xF8\xFE\xEE\xF3\xAE\x8D\xBB\x68\x2D\x38";

@implementation TestsAppDelegate (OFMD5HashTests)
- (void)MD5HashTests
{
	void *pool = objc_autoreleasePoolPush();
	OFMD5Hash *MD5, *MD5Copy;
	OFURI *URI = [OFURI URIWithString: @"embedded:testfile.bin"];
	OFStream *file = [OFURIHandler openItemAtURI: URI mode: @"r"];
	OFIRI *IRI = [OFIRI IRIWithString: @"embedded:testfile.bin"];
	OFStream *file = [OFIRIHandler openItemAtIRI: IRI mode: @"r"];

	TEST(@"+[hashWithAllowsSwappableMemory:]",
	    (MD5 = [OFMD5Hash hashWithAllowsSwappableMemory: true]))

	while (!file.atEndOfStream) {
		char buffer[64];
		size_t length = [file readIntoBuffer: buffer length: 64];

Added tests/OFMatrix4x4Tests.m version [953b65c5c6].








































































































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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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 "TestsAppDelegate.h"

static OFString *const module = @"OFMatrix4x4Tests";

@implementation TestsAppDelegate (OFMatrix4x4Tests)
- (void)matrix4x4Tests
{
	void *pool = objc_autoreleasePoolPush();
	OFMatrix4x4 *matrix, *matrix2;
	OFVector4D point;

	TEST(@"+[identityMatrix]",
	    memcmp([[OFMatrix4x4 identityMatrix] values], (const float [4][4]){
		{ 1, 0, 0, 0 },
		{ 0, 1, 0, 0 },
		{ 0, 0, 1, 0 },
		{ 0, 0, 0, 1 }
	    }, 16 * sizeof(float)) == 0)

	TEST(@"+[matrixWithValues:]",
	    (matrix = [OFMatrix4x4 matrixWithValues: (const float [4][4]){
		{  1,  2,  3,  4 },
		{  5,  6,  7,  8 },
		{  9, 10, 11, 12 },
		{ 13, 14, 15, 16 }
	    }]))

	TEST(@"-[description]",
	    [matrix.description isEqual: @"<OFMatrix4x4: {\n"
					 @"\t1 2 3 4\n"
					 @"\t5 6 7 8\n"
					 @"\t9 10 11 12\n"
					 @"\t13 14 15 16\n"
					 @"}>"])

	TEST(@"-[isEqual:]", [[OFMatrix4x4 identityMatrix] isEqual:
	    [OFMatrix4x4 matrixWithValues: (const float [4][4]){
		{ 1, 0, 0, 0 },
		{ 0, 1, 0, 0 },
		{ 0, 0, 1, 0 },
		{ 0, 0, 0, 1 }
	    }]])

	TEST(@"-[copy]", (matrix2 = [matrix copy]) && [matrix2 isEqual: matrix])

	TEST(@"-[multiplyWithMatrix:] #1",
	    R([matrix2 multiplyWithMatrix: [OFMatrix4x4 identityMatrix]]) &&
	    [matrix2 isEqual: matrix])

	matrix2 = [OFMatrix4x4 matrixWithValues: (const float [4][4]){
		{  100,  200,  300,  400 },
		{  500,  600,  700,  800 },
		{  900, 1000, 1100, 1200 },
		{ 1300, 1400, 1500, 1600 }
	}];
	TEST(@"-[multiplyWithMatrix:] #2",
	    R([matrix2 multiplyWithMatrix: matrix]) &&
	    [matrix2 isEqual:
	    [OFMatrix4x4 matrixWithValues: (const float [4][4]){
		{  9000, 10000, 11000, 12000 },
		{ 20200, 22800, 25400, 28000 },
		{ 31400, 35600, 39800, 44000 },
		{ 42600, 48400, 54200, 60000 }
	    }]])

	TEST(@"[-translateWithVector:]",
	    (matrix2 = [OFMatrix4x4 identityMatrix]) &&
	    R([matrix2 translateWithVector: OFMakeVector3D(1, 2, 3)]) &&
	    R(point =
	    [matrix2 transformedVector: OFMakeVector4D(2, 3, 4, 1)]) &&
	    point.x == 3 && point.y == 5 && point.z == 7 && point.w == 1)

	TEST(@"-[scaleWithVector:]",
	    R([matrix2 scaleWithVector: OFMakeVector3D(-1, 0.5f, 2)]) &&
	    R(point =
	    [matrix2 transformedVector: OFMakeVector4D(2, 3, 4, 1)]) &&
	    point.x == -3 && point.y == 2.5 && point.z == 14 && point.w == 1)

	TEST(@"-[transformedVector:]",
	    R((point =
	    [matrix transformedVector: OFMakeVector4D(1, 2, 3, 1)])) &&
	    point.x == 18 && point.y == 46 && point.z == 74 && point.w == 102)

	objc_autoreleasePoolPop(pool);
}
@end

Modified tests/OFMemoryStreamTests.m from [14fae61fb2] to [cba1b4b943].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified tests/OFMethodSignatureTests.m from [8b3d41a60c] to [69305b012d].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified tests/OFNotificationCenterTests.m from [4d3ddfb6ba] to [773c0131fc].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
105
106
107
108
109
110
111
112

113
114
115
116
117
118
119
105
106
107
108
109
110
111

112
113
114
115
116
117
118
119







-
+







	TEST(@"-[postNotification:] #3",
	    R([center postNotification: notification]) &&
	    test1->_received == 1 && test2->_received == 3 &&
	    test3->_received == 0 && test4->_received == 0)

#ifdef OF_HAVE_BLOCKS
	__block bool received = false;
	OFNotificationCenterHandle *handle;
	id handle;

	notification = [OFNotification notificationWithName: notificationName
						     object: self];
	TEST(@"-[addObserverForName:object:usingBlock:]",
	    (handle = [center addObserverForName: notificationName
					  object: self
				      usingBlock: ^ (OFNotification *notif) {

Modified tests/OFNumberTests.m from [c4180587af] to [c53861096d].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified tests/OFObjectTests.m from [fcfeee4a72] to [90104a8b4d].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified tests/OFPBKDF2Tests.m from [9316c48e09] to [a5c5b18510].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified tests/OFPluginTests.m from [bb55705657] to [5080d0ec07].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified tests/OFPropertyListTests.m from [6b258c8840] to [69bc23946b].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified tests/OFRIPEMD160HashTests.m from [c46510efe0] to [858f40a7a7].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
26
27
28
29
30
31
32
33
34


35
36
37
38
39
40
41
26
27
28
29
30
31
32


33
34
35
36
37
38
39
40
41







-
-
+
+







	"\xE6\x08\x8B";

@implementation TestsAppDelegate (OFRIPEMD160HashTests)
- (void)RIPEMD160HashTests
{
	void *pool = objc_autoreleasePoolPush();
	OFRIPEMD160Hash *RIPEMD160, *RIPEMD160Copy;
	OFURI *URI = [OFURI URIWithString: @"embedded:testfile.bin"];
	OFStream *file = [OFURIHandler openItemAtURI: URI mode: @"r"];
	OFIRI *IRI = [OFIRI IRIWithString: @"embedded:testfile.bin"];
	OFStream *file = [OFIRIHandler openItemAtIRI: IRI mode: @"r"];

	TEST(@"+[hashWithAllowsSwappableMemory:]",
	    (RIPEMD160 = [OFRIPEMD160Hash hashWithAllowsSwappableMemory: true]))

	while (!file.atEndOfStream) {
		char buffer[64];
		size_t length = [file readIntoBuffer: buffer length: 64];

Modified tests/OFSHA1HashTests.m from [76d8541713] to [bf9bbc4a89].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
26
27
28
29
30
31
32
33
34


35
36
37
38
39
40
41
26
27
28
29
30
31
32


33
34
35
36
37
38
39
40
41







-
-
+
+







	"\x94\xE7\x17";

@implementation TestsAppDelegate (SHA1HashTests)
- (void)SHA1HashTests
{
	void *pool = objc_autoreleasePoolPush();
	OFSHA1Hash *SHA1, *SHA1Copy;
	OFURI *URI = [OFURI URIWithString: @"embedded:testfile.bin"];
	OFStream *file = [OFURIHandler openItemAtURI: URI mode: @"r"];
	OFIRI *IRI = [OFIRI IRIWithString: @"embedded:testfile.bin"];
	OFStream *file = [OFIRIHandler openItemAtIRI: IRI mode: @"r"];

	TEST(@"+[hashWithAllowsSwappableMemory:]",
	    (SHA1 = [OFSHA1Hash hashWithAllowsSwappableMemory: true]))

	while (!file.atEndOfStream) {
		char buffer[64];
		size_t length = [file readIntoBuffer: buffer length: 64];

Modified tests/OFSHA224HashTests.m from [a723282b7a] to [080a439b7a].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
26
27
28
29
30
31
32
33
34


35
36
37
38
39
40
41
26
27
28
29
30
31
32


33
34
35
36
37
38
39
40
41







-
-
+
+







	"\x5F\x4F\x20\x02\x4D\x15\xED\x1C\x61\x1F\xF7";

@implementation TestsAppDelegate (SHA224HashTests)
- (void)SHA224HashTests
{
	void *pool = objc_autoreleasePoolPush();
	OFSHA224Hash *SHA224, *SHA224Copy;
	OFURI *URI = [OFURI URIWithString: @"embedded:testfile.bin"];
	OFStream *file = [OFURIHandler openItemAtURI: URI mode: @"r"];
	OFIRI *IRI = [OFIRI IRIWithString: @"embedded:testfile.bin"];
	OFStream *file = [OFIRIHandler openItemAtIRI: IRI mode: @"r"];

	TEST(@"+[hashWithAllowsSwappableMemory:]",
	    (SHA224 = [OFSHA224Hash hashWithAllowsSwappableMemory: true]))

	while (!file.atEndOfStream) {
		char buffer[64];
		size_t length = [file readIntoBuffer: buffer length: 64];

Modified tests/OFSHA256HashTests.m from [ea4a5936cb] to [761e7c7553].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
26
27
28
29
30
31
32
33
34


35
36
37
38
39
40
41
26
27
28
29
30
31
32


33
34
35
36
37
38
39
40
41







-
-
+
+







	"\x67\x93\x8F\x0F\x44\x90\xB8\xF5\x35\x89\xF0\x5A\x23\x7F\x69";

@implementation TestsAppDelegate (SHA256HashTests)
- (void)SHA256HashTests
{
	void *pool = objc_autoreleasePoolPush();
	OFSHA256Hash *SHA256, *SHA256Copy;
	OFURI *URI = [OFURI URIWithString: @"embedded:testfile.bin"];
	OFStream *file = [OFURIHandler openItemAtURI: URI mode: @"r"];
	OFIRI *IRI = [OFIRI IRIWithString: @"embedded:testfile.bin"];
	OFStream *file = [OFIRIHandler openItemAtIRI: IRI mode: @"r"];

	TEST(@"+[hashWithAllowsSwappableMemory:]",
	    (SHA256 = [OFSHA256Hash hashWithAllowsSwappableMemory: true]))

	while (!file.atEndOfStream) {
		char buffer[64];
		size_t length = [file readIntoBuffer: buffer length: 64];

Modified tests/OFSHA384HashTests.m from [4335e4cd7c] to [f2b425bf26].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
27
28
29
30
31
32
33
34
35


36
37
38
39
40
41
42
27
28
29
30
31
32
33


34
35
36
37
38
39
40
41
42







-
-
+
+







	"\xE9\x1A\xB3\x51\x70\x8C\x1F\x3F\x56\x12\x44\x01\x91\x54";

@implementation TestsAppDelegate (SHA384HashTests)
- (void)SHA384HashTests
{
	void *pool = objc_autoreleasePoolPush();
	OFSHA384Hash *SHA384, *SHA384Copy;
	OFURI *URI = [OFURI URIWithString: @"embedded:testfile.bin"];
	OFStream *file = [OFURIHandler openItemAtURI: URI mode: @"r"];
	OFIRI *IRI = [OFIRI IRIWithString: @"embedded:testfile.bin"];
	OFStream *file = [OFIRIHandler openItemAtIRI: IRI mode: @"r"];

	TEST(@"+[hashWithAllowsSwappableMemory:]",
	    (SHA384 = [OFSHA384Hash hashWithAllowsSwappableMemory: true]))

	while (!file.atEndOfStream) {
		char buffer[128];
		size_t length = [file readIntoBuffer: buffer length: 128];

Modified tests/OFSHA512HashTests.m from [9748b0700b] to [07e4804b8a].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
28
29
30
31
32
33
34
35
36


37
38
39
40
41
42
43
28
29
30
31
32
33
34


35
36
37
38
39
40
41
42
43







-
-
+
+







	"\xA1\x8A\x41\x64\x33\x69\x21\x8C\x2A\x44\x6D\xF2\xA0";

@implementation TestsAppDelegate (SHA512HashTests)
- (void)SHA512HashTests
{
	void *pool = objc_autoreleasePoolPush();
	OFSHA512Hash *SHA512, *SHA512Copy;
	OFURI *URI = [OFURI URIWithString: @"embedded:testfile.bin"];
	OFStream *file = [OFURIHandler openItemAtURI: URI mode: @"r"];
	OFIRI *IRI = [OFIRI IRIWithString: @"embedded:testfile.bin"];
	OFStream *file = [OFIRIHandler openItemAtIRI: IRI mode: @"r"];

	TEST(@"+[hashWithAllowsSwappableMemory:]",
	    (SHA512 = [OFSHA512Hash hashWithAllowsSwappableMemory: true]))

	while (!file.atEndOfStream) {
		char buffer[128];
		size_t length = [file readIntoBuffer: buffer length: 128];

Modified tests/OFSPXSocketTests.m from [951eb7a23c] to [69c423c289].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
75
76
77
78
79
80
81

82
83
84
85
86
87
88
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89







+







	void *pool = objc_autoreleasePoolPush();
	OFSPXSocket *sockClient, *sockServer = nil, *sockAccepted;
	OFSocketAddress address1;
	const OFSocketAddress *address2;
	uint32_t network;
	unsigned char node[IPX_NODE_LEN], node2[IPX_NODE_LEN];
	uint16_t port;
	OFDictionary *networkInterfaces;
	char buffer[5];
	SPXSocketDelegate *delegate;

	TEST(@"+[socket]", (sockClient = [OFSPXSocket socket]) &&
	    (sockServer = [OFSPXSocket socket]))

	@try {
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
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+















-







	}

	network = OFSocketAddressIPXNetwork(&address1);
	OFSocketAddressGetIPXNode(&address1, node);
	port = OFSocketAddressIPXPort(&address1);

	TEST(@"-[listen]", R([sockServer listen]))

	/*
	 * Find any network interface with IPX and send to it. Any should be
	 * fine since we bound to 0.0.
	 */
	networkInterfaces = [OFSystemInfo networkInterfaces];
	for (OFString *name in networkInterfaces) {
		OFNetworkInterface interface = [networkInterfaces
		    objectForKey: name];
		OFData *addresses = [interface
		    objectForKey: OFNetworkInterfaceIPXAddresses];

		if (addresses.count == 0)
			continue;

		network = OFSocketAddressIPXNetwork([addresses itemAtIndex: 0]);
		OFSocketAddressGetIPXNode([addresses itemAtIndex: 0], node);
	}

	TEST(@"-[connectToNetwork:node:port:]",
	    R([sockClient connectToNetwork: network node: node port: port]))

	TEST(@"-[accept]", (sockAccepted = [sockServer accept]))

	TEST(@"-[sendBuffer:length:]",
	    R([sockAccepted sendBuffer: "Hello" length: 5]))

	TEST(@"-[receiveIntoBuffer:length:]",
	    [sockClient receiveIntoBuffer: buffer length: 5] == 5 &&
	    memcmp(buffer, "Hello", 5) == 0)

	TEST(@"-[remoteAddress]",
	    (address2 = sockAccepted.remoteAddress) &&
	    OFSocketAddressIPXNetwork(address2) == network &&
	    R(OFSocketAddressGetIPXNode(address2, node2)) &&
	    memcmp(node, node2, IPX_NODE_LEN) == 0)

	delegate = [[[SPXSocketDelegate alloc] init] autorelease];

	sockServer = [OFSPXSocket socket];
	delegate->_expectedServerSocket = sockServer;
169
170
171
172
173
174
175







176
177
178
179
180
181
182
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207







+
+
+
+
+
+
+








		[[OFRunLoop mainRunLoop] runUntilDate:
		    [OFDate dateWithTimeIntervalSinceNow: 2]];

		TEST(@"-[asyncAccept] & -[asyncConnectToNetwork:node:port:]",
		    delegate->_accepted && delegate->_connected)
	} @catch (OFObserveKernelEventsFailedException *e) {
		/*
		 * Make sure it doesn't stay in the run loop and throws again
		 * next time we run the run loop.
		 */
		[sockClient cancelAsyncRequests];
		[sockServer cancelAsyncRequests];

		switch (e.errNo) {
		case ENOTSOCK:
			[OFStdOut setForegroundColor: [OFColor lime]];
			[OFStdOut writeLine:
			    @"\r[OFSPXSocket] -[asyncAccept] & "
			    @"-[asyncConnectToNetwork:node:port:]: select() "
			    @"not supported for SPX, skipping test"];

Modified tests/OFSPXStreamSocketTests.m from [ca6bf9ee77] to [d4fba2f103].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
75
76
77
78
79
80
81

82
83
84
85
86
87
88
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89







+







	void *pool = objc_autoreleasePoolPush();
	OFSPXStreamSocket *sockClient, *sockServer = nil, *sockAccepted;
	OFSocketAddress address1;
	const OFSocketAddress *address2;
	uint32_t network;
	unsigned char node[IPX_NODE_LEN], node2[IPX_NODE_LEN];
	uint16_t port;
	OFDictionary *networkInterfaces;
	char buffer[5];
	SPXStreamSocketDelegate *delegate;

	TEST(@"+[socket]", (sockClient = [OFSPXStreamSocket socket]) &&
	    (sockServer = [OFSPXStreamSocket socket]))

	@try {
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
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


















-







	}

	network = OFSocketAddressIPXNetwork(&address1);
	OFSocketAddressGetIPXNode(&address1, node);
	port = OFSocketAddressIPXPort(&address1);

	TEST(@"-[listen]", R([sockServer listen]))

	/*
	 * Find any network interface with IPX and send to it. Any should be
	 * fine since we bound to 0.0.
	 */
	networkInterfaces = [OFSystemInfo networkInterfaces];
	for (OFString *name in networkInterfaces) {
		OFNetworkInterface interface = [networkInterfaces
		    objectForKey: name];
		OFData *addresses = [interface
		    objectForKey: OFNetworkInterfaceIPXAddresses];

		if (addresses.count == 0)
			continue;

		network = OFSocketAddressIPXNetwork([addresses itemAtIndex: 0]);
		OFSocketAddressGetIPXNode([addresses itemAtIndex: 0], node);
	}

	TEST(@"-[connectToNetwork:node:port:]",
	    R([sockClient connectToNetwork: network node: node port: port]))

	TEST(@"-[accept]", (sockAccepted = [sockServer accept]))

	/* Test reassembly (this would not work with OFSPXSocket) */
	TEST(@"-[writeBuffer:length:]",
	    R([sockAccepted writeBuffer: "Hello" length: 5]))

	TEST(@"-[readIntoBuffer:length:]",
	    [sockClient readIntoBuffer: buffer length: 2] == 2 &&
	    memcmp(buffer, "He", 2) == 0 &&
	    [sockClient readIntoBuffer: buffer length: 3] == 3 &&
	    memcmp(buffer, "llo", 3) == 0)

	TEST(@"-[remoteAddress]",
	    (address2 = sockAccepted.remoteAddress) &&
	    OFSocketAddressIPXNetwork(address2) == network &&
	    R(OFSocketAddressGetIPXNode(address2, node2)) &&
	    memcmp(node, node2, IPX_NODE_LEN) == 0)

	delegate = [[[SPXStreamSocketDelegate alloc] init] autorelease];

	sockServer = [OFSPXStreamSocket socket];
	delegate->_expectedServerSocket = sockServer;
173
174
175
176
177
178
179







180
181
182
183
184
185
186
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211







+
+
+
+
+
+
+








		[[OFRunLoop mainRunLoop] runUntilDate:
		    [OFDate dateWithTimeIntervalSinceNow: 2]];

		TEST(@"-[asyncAccept] & -[asyncConnectToNetwork:node:port:]",
		    delegate->_accepted && delegate->_connected)
	} @catch (OFObserveKernelEventsFailedException *e) {
		/*
		 * Make sure it doesn't stay in the run loop and throws again
		 * next time we run the run loop.
		 */
		[sockClient cancelAsyncRequests];
		[sockServer cancelAsyncRequests];

		switch (e.errNo) {
		case ENOTSOCK:
			[OFStdOut setForegroundColor: [OFColor lime]];
			[OFStdOut writeLine:
			    @"\r[OFSPXStreamSocket] -[asyncAccept] & "
			    @"-[asyncConnectToNetwork:node:port:]: select() "
			    @"not supported for SPX, skipping test"];

Modified tests/OFScryptTests.m from [b11c7bebe9] to [08a61d3f40].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Deleted tests/OFSerializationTests.m version [d36329ce8f].

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








































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * 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 "TestsAppDelegate.h"

static OFString *const module = @"OFSerialization";

@implementation TestsAppDelegate (OFSerializationTests)
- (void)serializationTests
{
	void *pool = objc_autoreleasePoolPush();
	OFMutableDictionary *dict = [OFMutableDictionary dictionary];
	OFMutableArray *array = [OFMutableArray array];
	OFList *list = [OFList list];
	OFData *data;
	OFString *string;
	OFUUID *UUID;

	[array addObject: @"Qu\"xbar\ntest"];
	[array addObject: [OFNumber numberWithInt: 1234]];
	[array addObject: [OFNumber numberWithDouble: 1234.5678]];
	[array addObject: [OFMutableString stringWithString: @"asd"]];
	[array addObject: [OFDate dateWithTimeIntervalSince1970: 1234.5678]];

	[dict setObject: @"Hello" forKey: array];
	[dict setObject: @"B\"la" forKey: @"Blub"];

	[list appendObject: @"Hello"];
	[list appendObject: @"Wo\rld!\nHow are you?"];
	[list appendObject: [OFURI URIWithString: @"https://objfw.nil.im/"]];
	[list appendObject:
	    [OFXMLElement elementWithXMLString: @"<x><y/><![CDATA[<]]></x>"]];
	[list appendObject:
	    [OFSet setWithObjects: @"foo", @"foo", @"bar", nil]];
	[list appendObject:
	    [OFCountedSet setWithObjects: @"foo", @"foo", @"bar", nil]];

	[dict setObject: @"list" forKey: list];

	data = [OFData dataWithItems: "0123456789:;<ABCDEFGHJIKLMNOPQRSTUVWXYZ"
			       count: 39];
	[dict setObject: @"data" forKey: data];

	UUID = [OFUUID
	    UUIDWithUUIDString: @"01234567-89AB-CDEF-FEDC-BA9876543210"];
	[dict setObject: @"uuid" forKey: UUID];

	TEST(@"-[stringBySerializing]",
	    (string = dict.stringBySerializing) && [string isEqual:
	    [OFString stringWithContentsOfURI:
	    [OFURI URIWithString: @"embedded:serialization.xml"]]])

	TEST(@"-[objectByDeserializing]",
	    [string.objectByDeserializing isEqual: dict])

	objc_autoreleasePoolPop(pool);
}
@end

Modified tests/OFSetTests.m from [d6c98b6473] to [bc79bd72ed].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified tests/OFSocketTests.m from [efb70d49d6] to [4114d19b90].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
117
118
119
120
121
122
123










124
125
126
127
128
129
130
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140







+
+
+
+
+
+
+
+
+
+








	TEST(@"Parsing an IPv6 #6",
	    R(addr = OFSocketAddressParseIP(@"fd00::1%123", 1234)) &&
	    COMPARE_V6(addr, 0xFD00, 0, 0, 0, 0, 0, 0, 1) &&
	    OFFromBigEndian16(addr.sockaddr.in6.sin6_port) == 1234 &&
	    addr.sockaddr.in6.sin6_scope_id == 123)

	TEST(@"Parsing an IPv6 #7",
	    R(addr = OFSocketAddressParseIP(@"::ffff:127.0.0.1", 1234)) &&
	    COMPARE_V6(addr, 0, 0, 0, 0, 0, 0xFFFF, 0x7F00, 1) &&
	    OFFromBigEndian16(addr.sockaddr.in6.sin6_port) == 1234)

	TEST(@"Parsing an IPv6 #8",
	    R(addr = OFSocketAddressParseIP(@"64:ff9b::127.0.0.1", 1234)) &&
	    COMPARE_V6(addr, 0x64, 0xFF9B, 0, 0, 0, 0, 0x7F00, 1) &&
	    OFFromBigEndian16(addr.sockaddr.in6.sin6_port) == 1234)

	EXPECT_EXCEPTION(@"Refusing invalid IPv6 #1", OFInvalidFormatException,
	    OFSocketAddressParseIP(@"1:::2", 1234))

	EXPECT_EXCEPTION(@"Refusing invalid IPv6 #2", OFInvalidFormatException,
	    OFSocketAddressParseIP(@"1: ::2", 1234))

	EXPECT_EXCEPTION(@"Refusing invalid IPv6 #3", OFInvalidFormatException,

Modified tests/OFStreamTests.m from [12c9753c4d] to [c45325de0e].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified tests/OFStringTests.m from [10adf25aaa] to [4230f34f7e].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
353
354
355
356
357
358
359
360
361


362
363
364
365
366
367
368
353
354
355
356
357
358
359


360
361
362
363
364
365
366
367
368







-
-
+
+








#ifdef OF_HAVE_FILES
	TEST(@"+[stringWithContentsOfFile:encoding]", (string = [stringClass
	    stringWithContentsOfFile: @"testfile.txt"
			    encoding: OFStringEncodingISO8859_1]) &&
	    [string isEqual: @"testäöü"])

	TEST(@"+[stringWithContentsOfURI:encoding]", (string = [stringClass
	    stringWithContentsOfURI: [OFURI fileURIWithPath: @"testfile.txt"]
	TEST(@"+[stringWithContentsOfIRI:encoding]", (string = [stringClass
	    stringWithContentsOfIRI: [OFIRI fileIRIWithPath: @"testfile.txt"]
			   encoding: OFStringEncodingISO8859_1]) &&
	    [string isEqual: @"testäöü"])
#endif

	TEST(@"-[appendUTFString:length:]",
	    R([mutableString1 appendUTF8String: "\xEF\xBB\xBF" "barqux"
					length: 6]) &&
1152
1153
1154
1155
1156
1157
1158
1159

1160
1161
1162
1163
1164
1165
1166
1152
1153
1154
1155
1156
1157
1158

1159
1160
1161
1162
1163
1164
1165
1166







-
+







#else
/* Android, Solaris, HP-UX, DJGPP and AmigaOS 3 do not accept 0x for strtod() */
# if (!defined(OF_SOLARIS) || !defined(OF_X86)) && !defined(OF_AMIGAOS_M68K)
#  define INPUT @"\t-0.123456789 "
#  define EXPECTED -0.123456789
# else
/*
 * Solaris' strtod() has weird rounding on x86, but not on x86_64.
 * Solaris' strtod() has weird rounding on x86, but not on AMD64.
 * AmigaOS 3 with libnix has weird rounding as well.
 */
#  define INPUT @"\t-0.125 "
#  define EXPECTED -0.125
# endif
#endif
	TEST(@"-[doubleValue]",

Modified tests/OFSystemInfoTests.m from [5b9edfd152] to [a3f524d376].

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
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

-
+
















+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+





+
+
+
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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 "TestsAppDelegate.h"

#ifdef OF_HAVE_SOCKETS
static void
printAddresses(OFData *addresses, bool *firstAddress)
{
	size_t count = addresses.count;

	for (size_t i = 0; i < count; i++) {
		const OFSocketAddress *address = [addresses itemAtIndex: i];

		if (!*firstAddress)
			[OFStdOut writeString: @", "];

		*firstAddress = false;

		[OFStdOut writeString: OFSocketAddressString(address)];
	}
}
#endif

@implementation TestsAppDelegate (OFSystemInfoTests)
- (void)systemInfoTests
{
	void *pool = objc_autoreleasePoolPush();
#ifdef OF_HAVE_SOCKETS
	OFDictionary *networkInterfaces;
	bool firstInterface = true;
#endif

	[OFStdOut setForegroundColor: [OFColor lime]];

	[OFStdOut writeFormat: @"[OFSystemInfo] Page size: %zd\n",
	    [OFSystemInfo pageSize]];

	[OFStdOut writeFormat: @"[OFSystemInfo] Number of CPUs: %zd\n",
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
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







-
-
+
+

-
-
+
+

-
-
+
+










+
+
+
+
+
+







	[OFStdOut writeFormat: @"[OFSystemInfo] Operating system name: %@\n",
	    [OFSystemInfo operatingSystemName]];

	[OFStdOut writeFormat:
	    @"[OFSystemInfo] Operating system version: %@\n",
	    [OFSystemInfo operatingSystemVersion]];

	[OFStdOut writeFormat: @"[OFSystemInfo] User config URI: %@\n",
	    [OFSystemInfo userConfigURI].string];
	[OFStdOut writeFormat: @"[OFSystemInfo] User config IRI: %@\n",
	    [OFSystemInfo userConfigIRI].string];

	[OFStdOut writeFormat: @"[OFSystemInfo] User data URI: %@\n",
	    [OFSystemInfo userDataURI].string];
	[OFStdOut writeFormat: @"[OFSystemInfo] User data IRI: %@\n",
	    [OFSystemInfo userDataIRI].string];

	[OFStdOut writeFormat: @"[OFSystemInfo] Temporary directory URI: %@\n",
	    [OFSystemInfo temporaryDirectoryURI].string];
	[OFStdOut writeFormat: @"[OFSystemInfo] Temporary directory IRI: %@\n",
	    [OFSystemInfo temporaryDirectoryIRI].string];

	[OFStdOut writeFormat: @"[OFSystemInfo] CPU vendor: %@\n",
	    [OFSystemInfo CPUVendor]];

	[OFStdOut writeFormat: @"[OFSystemInfo] CPU model: %@\n",
	    [OFSystemInfo CPUModel]];

#if defined(OF_X86_64) || defined(OF_X86)
	[OFStdOut writeFormat: @"[OFSystemInfo] Supports MMX: %d\n",
	    [OFSystemInfo supportsMMX]];

	[OFStdOut writeFormat: @"[OFSystemInfo] Supports 3DNow!: %d\n",
	    [OFSystemInfo supports3DNow]];

	[OFStdOut writeFormat: @"[OFSystemInfo] Supports enhanced 3DNow!: %d\n",
	    [OFSystemInfo supportsEnhanced3DNow]];

	[OFStdOut writeFormat: @"[OFSystemInfo] Supports SSE: %d\n",
	    [OFSystemInfo supportsSSE]];

	[OFStdOut writeFormat: @"[OFSystemInfo] Supports SSE2: %d\n",
	    [OFSystemInfo supportsSSE2]];

96
97
98
99
100
101
102
103






















































104
105
106
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








+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



	    [OFSystemInfo supportsSHAExtensions]];
#endif

#ifdef OF_POWERPC
	[OFStdOut writeFormat: @"[OFSystemInfo] Supports AltiVec: %d\n",
	    [OFSystemInfo supportsAltiVec]];
#endif

#ifdef OF_HAVE_SOCKETS
	networkInterfaces = [OFSystemInfo networkInterfaces];
	[OFStdOut writeString: @"[OFSystemInfo] Network interfaces: "];
	for (OFString *name in networkInterfaces) {
		bool firstAddress = true;
		OFNetworkInterface interface;
		OFData *hardwareAddress;

		if (!firstInterface)
			[OFStdOut writeString: @"; "];

		firstInterface = false;

		[OFStdOut writeFormat: @"%@(", name];

		interface = [networkInterfaces objectForKey: name];

		printAddresses([interface objectForKey:
		    OFNetworkInterfaceIPv4Addresses], &firstAddress);
# ifdef OF_HAVE_IPV6
		printAddresses([interface objectForKey:
		    OFNetworkInterfaceIPv6Addresses], &firstAddress);
# endif
# ifdef OF_HAVE_IPX
		printAddresses([interface objectForKey:
		    OFNetworkInterfaceIPXAddresses], &firstAddress);
# endif
# ifdef OF_HAVE_APPLETALK
		printAddresses([interface objectForKey:
		    OFNetworkInterfaceAppleTalkAddresses], &firstAddress);
# endif

		hardwareAddress = [interface
		    objectForKey: OFNetworkInterfaceHardwareAddress];
		if (hardwareAddress != nil) {
			const unsigned char *bytes = hardwareAddress.items;
			size_t length = hardwareAddress.count;

			if (!firstAddress)
				[OFStdOut writeString: @", "];

			for (size_t i = 0; i < length; i++) {
				if (i > 0)
					[OFStdOut writeString: @":"];

				[OFStdOut writeFormat: @"%02X", bytes[i]];
			}
		}

		[OFStdOut writeString: @")"];
	}
	[OFStdOut writeString: @"\n"];
#endif

	objc_autoreleasePoolPop(pool);
}
@end

Modified tests/OFTCPSocketTests.m from [e205251e21] to [b8d81237e5].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
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
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







-
+






-
+




-
+
+







static OFString *const module = @"OFTCPSocket";

@implementation TestsAppDelegate (OFTCPSocketTests)
- (void)TCPSocketTests
{
	void *pool = objc_autoreleasePoolPush();
	OFTCPSocket *server, *client = nil, *accepted;
	uint16_t port;
	OFSocketAddress address;
	char buffer[6];

	TEST(@"+[socket]", (server = [OFTCPSocket socket]) &&
	    (client = [OFTCPSocket socket]))

	TEST(@"-[bindToHost:port:]",
	    (port = [server bindToHost: @"127.0.0.1" port: 0]))
	    R(address = [server bindToHost: @"127.0.0.1" port: 0]))

	TEST(@"-[listen]", R([server listen]))

	TEST(@"-[connectToHost:port:]",
	    R([client connectToHost: @"127.0.0.1" port: port]))
	    R([client connectToHost: @"127.0.0.1"
			       port: OFSocketAddressIPPort(&address)]))

	TEST(@"-[accept]", (accepted = [server accept]))

	TEST(@"-[remoteAddress]",
	    [OFSocketAddressString(accepted.remoteAddress)
	    isEqual: @"127.0.0.1"])

Modified tests/OFThreadTests.m from [3abe7860ab] to [46a94ca5e1].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified tests/OFUDPSocketTests.m from [435a3297c3] to [8fc77398a2].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
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
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







-






-
+
-
-








-
+

-
+
+

-
-
-
-











static OFString *const module = @"OFUDPSocket";

@implementation TestsAppDelegate (OFUDPSocketTests)
- (void)UDPSocketTests
{
	void *pool = objc_autoreleasePoolPush();
	OFUDPSocket *sock;
	uint16_t port1;
	OFSocketAddress addr1, addr2, addr3;
	char buf[6];

	TEST(@"+[socket]", (sock = [OFUDPSocket socket]))

	TEST(@"-[bindToHost:port:]",
	    (port1 = [sock bindToHost: @"127.0.0.1" port: 0]))
	    R(addr1 = [sock bindToHost: @"127.0.0.1" port: 0]))

	addr1 = OFSocketAddressParseIP(@"127.0.0.1", port1);

	TEST(@"-[sendBuffer:length:receiver:]",
	    R([sock sendBuffer: "Hello" length: 6 receiver: &addr1]))

	TEST(@"-[receiveIntoBuffer:length:sender:]",
	    [sock receiveIntoBuffer: buf length: 6 sender: &addr2] == 6 &&
	    !memcmp(buf, "Hello", 6) &&
	    [OFSocketAddressString(&addr2) isEqual: @"127.0.0.1"] &&
	    OFSocketAddressIPPort(&addr2) == port1)
	    OFSocketAddressIPPort(&addr2) == OFSocketAddressIPPort(&addr1))

	addr3 = OFSocketAddressParseIP(@"127.0.0.1", port1 + 1);
	addr3 = OFSocketAddressParseIP(@"127.0.0.1",
	    OFSocketAddressIPPort(&addr1) + 1);

	/*
	 * TODO: Move those tests elsewhere as soon as the DNS resolving part
	 *	 is no longer in OFUDPSocket.
	 */
	TEST(@"OFSocketAddressEqual()",
	    OFSocketAddressEqual(&addr1, &addr2) &&
	    !OFSocketAddressEqual(&addr1, &addr3))

	TEST(@"OFSocketAddressHash()",
	    OFSocketAddressHash(&addr1) == OFSocketAddressHash(&addr2) &&
	    OFSocketAddressHash(&addr1) != OFSocketAddressHash(&addr3))

	objc_autoreleasePoolPop(pool);
}
@end

Modified tests/OFUNIXDatagramSocketTests.m from [61f9f2c60c] to [68f26bf09c].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
27
28
29
30
31
32
33
34
35


36
37
38
39
40
41
42

43
44
45
46
47
48
49
27
28
29
30
31
32
33


34
35
36
37
38
39
40
41

42
43
44
45
46
47
48
49







-
-
+
+






-
+







	void *pool = objc_autoreleasePoolPush();
	OFString *path;
	OFUNIXDatagramSocket *sock;
	OFSocketAddress address1, address2;
	char buffer[5];

#if defined(OF_HAVE_FILES) && !defined(OF_IOS)
	path = [[OFSystemInfo temporaryDirectoryURI]
	    URIByAppendingPathComponent: [[OFUUID UUID] UUIDString]]
	path = [[OFSystemInfo temporaryDirectoryIRI]
	    IRIByAppendingPathComponent: [[OFUUID UUID] UUIDString]]
	    .fileSystemRepresentation;
#else
	/*
	 * We can have sockets, including UNIX sockets, while file support is
	 * disabled.
	 *
	 * We also use this code path for iOS, as the temporaryDirectoryURI is
	 * We also use this code path for iOS, as the temporaryDirectoryIRI is
	 * too long on the iOS simulator.
	 */
	path = [OFString stringWithFormat: @"/tmp/%@",
					   [[OFUUID UUID] UUIDString]];
#endif

	TEST(@"+[socket]", (sock = [OFUNIXDatagramSocket socket]))

Modified tests/OFUNIXStreamSocketTests.m from [cebf3c029f] to [d941ba25ca].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
26
27
28
29
30
31
32
33
34


35
36
37
38
39
40
41

42
43
44
45
46
47
48
26
27
28
29
30
31
32


33
34
35
36
37
38
39
40

41
42
43
44
45
46
47
48







-
-
+
+






-
+







{
	void *pool = objc_autoreleasePoolPush();
	OFString *path;
	OFUNIXStreamSocket *sockClient, *sockServer, *sockAccepted;
	char buffer[5];

#if defined(OF_HAVE_FILES) && !defined(OF_IOS)
	path = [[OFSystemInfo temporaryDirectoryURI]
	    URIByAppendingPathComponent: [[OFUUID UUID] UUIDString]]
	path = [[OFSystemInfo temporaryDirectoryIRI]
	    IRIByAppendingPathComponent: [[OFUUID UUID] UUIDString]]
	    .fileSystemRepresentation;
#else
	/*
	 * We can have sockets, including UNIX sockets, while file support is
	 * disabled.
	 *
	 * We also use this code path for iOS, as the temporaryDirectoryURI is
	 * We also use this code path for iOS, as the temporaryDirectory:RI is
	 * too long on the iOS simulator.
	 */
	path = [OFString stringWithFormat: @"/tmp/%@",
					   [[OFUUID UUID] UUIDString]];
#endif

	TEST(@"+[socket]", (sockClient = [OFUNIXStreamSocket socket]) &&

Modified tests/OFValueTests.m from [f614b296d4] to [cbc9e9bd57].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified tests/OFWindowsRegistryKeyTests.m from [ddf274227c] to [e84856abac].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified tests/OFXMLElementBuilderTests.m from [82fd282c44] to [8eec07c305].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified tests/OFXMLNodeTests.m from [29eb2048b3] to [a651605864].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified tests/OFXMLParserTests.m from [dc6afcdede] to [a95ddb457c].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified tests/RuntimeARCTests.m from [62782bae47] to [1d4afa03f7].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified tests/RuntimeTests.m from [9aa59cf983] to [3005f6eb59].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified tests/TestsAppDelegate.h from [1f4a8a0dc4] to [c08d2cfc07].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
66
67
68
69
70
71
72




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







+
+
+
+







@interface TestsAppDelegate (OFBlockTests)
- (void)blockTests;
@end

@interface TestsAppDelegate (OFCharacterSetTests)
- (void)characterSetTests;
@end

@interface TestsAppDelegate (OFColorTests)
- (void)colorTests;
@end

@interface TestsAppDelegate (OFDDPSocketTests)
- (void)DDPSocketTests;
@end

@interface TestsAppDelegate (OFDNSResolverTests)
- (void)DNSResolverTests;
106
107
108
109
110
111
112




113
114
115
116
117
118
119
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127







+
+
+
+







@interface TestsAppDelegate (OFHTTPCookieManagerTests)
- (void)HTTPCookieManagerTests;
@end

@interface TestsAppDelegate (OFINIFileTests)
- (void)INIFileTests;
@end

@interface TestsAppDelegate (OFIRITests)
- (void)IRITests;
@end

@interface TestsAppDelegate (OFIPXSocketTests)
- (void)IPXSocketTests;
@end

@interface TestsAppDelegate (OFInvocationTests)
- (void)invocationTests;
138
139
140
141
142
143
144




145
146
147
148
149
150
151
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163







+
+
+
+







@interface TestsAppDelegate (OFLocaleTests)
- (void)localeTests;
@end

@interface TestsAppDelegate (OFMD5HashTests)
- (void)MD5HashTests;
@end

@interface TestsAppDelegate (OFMatrix4x4Tests)
- (void)matrix4x4Tests;
@end

@interface TestsAppDelegate  (OFMemoryStreamTests)
- (void)memoryStreamTests;
@end

@interface TestsAppDelegate (OFMethodSignatureTests)
- (void)methodSignatureTests;
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
227
228
229
230
231
232
233




234
235
236
237
238
239
240







-
-
-
-







- (void)SPXSocketTests;
@end

@interface TestsAppDelegate (OFSPXStreamSocketTests)
- (void)SPXStreamSocketTests;
@end

@interface TestsAppDelegate (OFSerializationTests)
- (void)serializationTests;
@end

@interface TestsAppDelegate (OFSetTests)
- (void)setTests;
@end

@interface TestsAppDelegate (OFSystemInfoTests)
- (void)systemInfoTests;
@end
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
267
268
269
270
271
272
273




274
275
276
277
278
279
280







-
-
-
-







- (void)UNIXDatagramSocketTests;
@end

@interface TestsAppDelegate (OFUNIXStreamSocketTests)
- (void)UNIXStreamSocketTests;
@end

@interface TestsAppDelegate (OFURITests)
- (void)URITests;
@end

@interface TestsAppDelegate (OFValueTests)
- (void)valueTests;
@end

@interface TestsAppDelegate (OFWindowsRegistryKeyTests)
- (void)windowsRegistryKeyTests;
@end

Modified tests/TestsAppDelegate.m from [38bbd5a2a3] to [f47a4fc271].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
395
396
397
398
399
400
401

402
403
404
405
406
407
408
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409







+







	[self arrayTests];
	[self dictionaryTests];
	[self listTests];
	[self setTests];
	[self dateTests];
	[self valueTests];
	[self numberTests];
	[self colorTests];
	[self streamTests];
	[self memoryStreamTests];
	[self notificationCenterTests];
	[self MD5HashTests];
	[self RIPEMD160HashTests];
	[self SHA1HashTests];
	[self SHA224HashTests];
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
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







-
+










-


+
+







	[self DDPSocketTests];
# endif
	[self kernelEventObserverTests];
#endif
#ifdef OF_HAVE_THREADS
	[self threadTests];
#endif
	[self URITests];
	[self IRITests];
#if defined(OF_HAVE_SOCKETS) && defined(OF_HAVE_THREADS)
	[self HTTPClientTests];
#endif
#ifdef OF_HAVE_SOCKETS
	[self HTTPCookieTests];
	[self HTTPCookieManagerTests];
#endif
	[self XMLParserTests];
	[self XMLNodeTests];
	[self XMLElementBuilderTests];
	[self serializationTests];
	[self JSONTests];
	[self propertyListTests];
	[self matrix4x4Tests];

#if defined(OF_HAVE_PLUGINS)
	[self pluginTests];
#endif
#ifdef OF_WINDOWS
	[self windowsRegistryKeyTests];
#endif

Modified tests/iOS.xcodeproj/project.pbxproj from [2c6fcc5e96] to [ac2dd7d645].

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
9
10
11
12
13
14
15

16
17
18
19
20
21
22







-







/* Begin PBXBuildFile section */
		4B6AB9CD202BA431007BAC7D /* TestPlugin.bundle in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4B6AB9CA202BA408007BAC7D /* TestPlugin.bundle */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
		4BC7FD07201394F300280496 /* ObjFW.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4BC7FD06201394F300280496 /* ObjFW.framework */; };
		4BC7FD092013954B00280496 /* tests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4BC7FD082013954B00280496 /* tests.a */; };
		4BC7FD0B2013956D00280496 /* ObjFW.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4BC7FD06201394F300280496 /* ObjFW.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
		4BC7FD102013960600280496 /* testfile.txt in Resources */ = {isa = PBXBuildFile; fileRef = 4BC7FD0C2013960600280496 /* testfile.txt */; };
		4BC7FD112013960600280496 /* testfile.bin in Resources */ = {isa = PBXBuildFile; fileRef = 4BC7FD0D2013960600280496 /* testfile.bin */; };
		4BC7FD122013960600280496 /* serialization.xml in Resources */ = {isa = PBXBuildFile; fileRef = 4BC7FD0E2013960600280496 /* serialization.xml */; };
		4BC7FD132013960600280496 /* testfile.ini in Resources */ = {isa = PBXBuildFile; fileRef = 4BC7FD0F2013960600280496 /* testfile.ini */; };
		4BEBFB6E2013934E002E8710 /* ImportTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BEBFB6D2013934E002E8710 /* ImportTest.m */; };
/* End PBXBuildFile section */

/* Begin PBXCopyFilesBuildPhase section */
		4B6AB9CC202BA428007BAC7D /* CopyFiles */ = {
			isa = PBXCopyFilesBuildPhase;
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
42
43
44
45
46
47
48

49
50
51
52
53
54
55







-








/* Begin PBXFileReference section */
		4B6AB9CA202BA408007BAC7D /* TestPlugin.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; name = TestPlugin.bundle; path = plugin/TestPlugin.bundle; sourceTree = "<group>"; };
		4BC7FD06201394F300280496 /* ObjFW.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ObjFW.framework; path = ../src/ObjFW.framework; sourceTree = "<group>"; };
		4BC7FD082013954B00280496 /* tests.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = tests.a; sourceTree = "<group>"; };
		4BC7FD0C2013960600280496 /* testfile.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = testfile.txt; sourceTree = "<group>"; };
		4BC7FD0D2013960600280496 /* testfile.bin */ = {isa = PBXFileReference; lastKnownFileType = archive.macbinary; path = testfile.bin; sourceTree = "<group>"; };
		4BC7FD0E2013960600280496 /* serialization.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = serialization.xml; sourceTree = "<group>"; };
		4BC7FD0F2013960600280496 /* testfile.ini */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = testfile.ini; sourceTree = "<group>"; };
		4BEBFB5B2013934E002E8710 /* tests.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = tests.app; sourceTree = BUILT_PRODUCTS_DIR; };
		4BEBFB6C2013934E002E8710 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = SOURCE_ROOT; };
		4BEBFB6D2013934E002E8710 /* ImportTest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ImportTest.m; sourceTree = SOURCE_ROOT; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
93
94
95
96
97
98
99

100
101
102
103
104
105
106







-







			sourceTree = "<group>";
		};
		4BEBFB5D2013934E002E8710 /* tests */ = {
			isa = PBXGroup;
			children = (
				4BEBFB6C2013934E002E8710 /* Info.plist */,
				4BEBFB6D2013934E002E8710 /* ImportTest.m */,
				4BC7FD0E2013960600280496 /* serialization.xml */,
				4BC7FD0D2013960600280496 /* testfile.bin */,
				4BC7FD0F2013960600280496 /* testfile.ini */,
				4BC7FD0C2013960600280496 /* testfile.txt */,
			);
			name = tests;
			sourceTree = "<group>";
		};
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
161
162
163
164
165
166
167

168
169
170
171
172
173
174







-








/* Begin PBXResourcesBuildPhase section */
		4BEBFB592013934E002E8710 /* Resources */ = {
			isa = PBXResourcesBuildPhase;
			buildActionMask = 2147483647;
			files = (
				4BC7FD102013960600280496 /* testfile.txt in Resources */,
				4BC7FD122013960600280496 /* serialization.xml in Resources */,
				4BC7FD132013960600280496 /* testfile.ini in Resources */,
				4BC7FD112013960600280496 /* testfile.bin in Resources */,
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
/* End PBXResourcesBuildPhase section */

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
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







-
+



















-
+







				FRAMEWORK_SEARCH_PATHS = "$(PROJECT_DIR)/../src";
				INFOPLIST_FILE = Info.plist;
				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
				LIBRARY_SEARCH_PATHS = (
					"$(inherited)",
					"$(PROJECT_DIR)",
				);
				OTHER_LDFLAGS = "-ObjC";
				OTHER_LDFLAGS = "-all_load";
				PRODUCT_BUNDLE_IDENTIFIER = im.nil.objfw.tests;
				PRODUCT_NAME = "$(TARGET_NAME)";
				TARGETED_DEVICE_FAMILY = "1,2";
			};
			name = Debug;
		};
		4BEBFB732013934E002E8710 /* Release */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
				CODE_SIGN_STYLE = Automatic;
				DEVELOPMENT_TEAM = MXKNFCKFL6;
				FRAMEWORK_SEARCH_PATHS = "$(PROJECT_DIR)/../src";
				INFOPLIST_FILE = Info.plist;
				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
				LIBRARY_SEARCH_PATHS = (
					"$(inherited)",
					"$(PROJECT_DIR)",
				);
				OTHER_LDFLAGS = "-ObjC";
				OTHER_LDFLAGS = "-all_load";
				PRODUCT_BUNDLE_IDENTIFIER = im.nil.objfw.tests;
				PRODUCT_NAME = "$(TARGET_NAME)";
				TARGETED_DEVICE_FAMILY = "1,2";
			};
			name = Release;
		};
/* End XCBuildConfiguration section */

Modified tests/objc_sync/test.m from [1f28b08c51] to [f189364c7f].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified tests/plugin/TestPlugin.h from [2f9aa9b796] to [f408f40092].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified tests/plugin/TestPlugin.m from [5616dbe160] to [6e0c1c45c1].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Deleted tests/serialization.xml version [ea3d1a36ad].

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



































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
<?xml version='1.0' encoding='UTF-8'?>
<serialization xmlns='https://objfw.nil.im/serialization' version='1'>
  <OFMutableDictionary>
    <key>
      <OFUUID>01234567-89ab-cdef-fedc-ba9876543210</OFUUID>
    </key>
    <object>
      <OFString>uuid</OFString>
    </object>
    <key>
      <OFString>Blub</OFString>
    </key>
    <object>
      <OFString>B&quot;la</OFString>
    </object>
    <key>
      <OFList>
        <OFString>Hello</OFString>
        <OFString>Wo&#xD;ld!
How are you?</OFString>
        <OFURI>https://objfw.nil.im/</OFURI>
        <OFXMLElement name='x'>
          <children>
            <OFMutableArray>
              <OFXMLElement name='y'/>
              <OFXMLCDATA><![CDATA[<]]></OFXMLCDATA>
            </OFMutableArray>
          </children>
        </OFXMLElement>
        <OFSet>
          <OFString>bar</OFString>
          <OFString>foo</OFString>
        </OFSet>
        <OFCountedSet>
          <object count='1'>
            <OFString>bar</OFString>
          </object>
          <object count='2'>
            <OFString>foo</OFString>
          </object>
        </OFCountedSet>
      </OFList>
    </key>
    <object>
      <OFString>list</OFString>
    </object>
    <key>
      <OFData>MDEyMzQ1Njc4OTo7PEFCQ0RFRkdISklLTE1OT1BRUlNUVVZXWFla</OFData>
    </key>
    <object>
      <OFString>data</OFString>
    </object>
    <key>
      <OFArray>
        <OFString>Qu&quot;xbar
test</OFString>
        <OFNumber type='signed'>1234</OFNumber>
        <OFNumber type='float'>40934a456d5cfaad</OFNumber>
        <OFMutableString>asd</OFMutableString>
        <OFDate encoding='hex'>40934a456d5cfaad</OFDate>
      </OFArray>
    </key>
    <object>
      <OFString>Hello</OFString>
    </object>
  </OFMutableDictionary>
</serialization>

Modified tests/terminal/TerminalTests.m from [98d7249eb5] to [8cf6546584].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified utils/Makefile from [d5d46e8aaf] to [66810ae4c9].

1
2
3
4
5
6
7





8
9
10
11
12
13
14
15
1
2





3
4
5
6
7

8
9
10
11
12
13
14


-
-
-
-
-
+
+
+
+
+
-







include ../extra.mk

SUBDIRS += ${OBJFW_NEW}	\
	   ${OFARC}	\
	   ${OFDNS}	\
	   ${OFHASH}	\
	   ${OFHTTP}	\
SUBDIRS += ${OBJFW_NEW}		\
	   ${OFARC}		\
	   ${OFDNS}		\
	   ${OFHASH}		\
	   ${OFHTTP}
	   completions

include ../buildsys.mk

DISTCLEAN = objfw-config

install-extra: objfw-config objfw-compile objfw-embed
	for i in objfw-config objfw-compile objfw-embed; do \

Deleted utils/completions/Makefile version [53ed45f23f].

1
2
3
4
5





-
-
-
-
-
include ../../extra.mk

SUBDIRS = ${FISH_COMPLETIONS}

include ../../buildsys.mk

Deleted utils/completions/fish/Makefile version [6569e87046].

1
2
3
4
5
6
7
8
9
10










-
-
-
-
-
-
-
-
-
-
DATA = objfw-compile.fish	\
       objfw-config.fish	\
       ofarc.fish		\
       ofdns.fish		\
       ofhash.fish		\
       ofhttp.fish

include ../../../buildsys.mk

PACKAGE_NAME = fish/vendor_completions.d

Deleted utils/completions/fish/objfw-compile.fish version [e113a8c395].

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




























-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
complete -c objfw-compile -s o -x -d 'Specify the output name (not file name!)'
complete -c objfw-compile -l arc -d 'Use automatic reference counting'
complete -c objfw-compile -l lib -x -d \
    'Compile a library (with the specified version) instead of an application'
complete -c objfw-compile -l plugin \
    -d 'Compile a plugin instead of an application'
complete -c objfw-compile -l package -x -d 'Use the specified package'
complete -c objfw-compile -l builddir -r \
    -d 'Place built objects into the specified directory'
complete -c objfw-compile -s D -x -d 'Pass the specified define to the compiler'
complete -c objfw-compile -o framework -x \
    -d 'Pass the specified -framework argument to the linker (macOS / iOS only)'
# -f* cannot be represented.
complete -c objfw-compile -s F -x \
    -d 'Pass the specified -F flag to the linker (macOS / iOS only)'
# -g* cannot be represented.
complete -c objfw-compile -s I -x \
    -d 'Pass the specified -I flag to the compiler'
complete -c objfw-compile -s l -x -d 'Pass the specified -l flag to the linker'
complete -c objfw-compile -s L -x -d 'Pass the specified -L flag to the linker'
# -m* cannot be represented.
# -O* cannot be represented.
complete -c objfw-compile -o pthread \
    -d 'Pass -pthread to the compiler and linker'
# -std=* cannot be represented.
# -Wl,* cannot be represented.
# -W* cannot be represented.
complete -c objfw-compile -l help -d 'Show this help'

Deleted utils/completions/fish/objfw-config.fish version [a2dae654a7].

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

































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
complete -c objfw-config -l all -d 'Outputs all flags + libs'
complete -c objfw-config -l arc -d 'Outputs the required OBJCFLAGS to use ARC'
complete -c objfw-config -l cflags -d 'Outputs the required CFLAGS'
complete -c objfw-config -l cppflags -d 'Outputs the required CPPFLAGS'
complete -c objfw-config -l cxxflags -d 'Outputs the required CXXFLAGS'
complete -c objfw-config -l framework-libs \
    -d 'Outputs the required LIBS, preferring frameworks'
complete -c objfw-config -l help -d 'Print help'
complete -c objfw-config -l ldflags -d 'Outputs the required LDFLAGS'
complete -c objfw-config -l libs -d 'Outputs the required LIBS'
complete -c objfw-config -l lib-cflags \
    -d 'Outputs CFLAGS for building a library'
complete -c objfw-config -l lib-ldflags \
    -d 'Outputs LDFLAGS for building a library'
complete -c objfw-config -l lib-prefix -d 'Outputs the prefix for libraries'
complete -c objfw-config -l lib-suffix -d 'Outputs the suffix for libraries'
complete -c objfw-config -l objc -d 'Outputs the OBJC used to compile ObjFW'
complete -c objfw-config -l objcflags -d 'Outputs the required OBJCFLAGS'
complete -c objfw-config -l package -x \
    -d 'Additionally outputs the flags for the specified package'
complete -c objfw-config -l packages-dir \
    -d 'Outputs the directory where flags for packages are stored'
complete -c objfw-config -l plugin-cflags \
    -d 'Outputs CFLAGS for building a plugin'
complete -c objfw-config -l plugin-ldflags \
    -d 'Outputs LDFLAGS for building a plugin'
complete -c objfw-config -l plugin-suffix -d 'Outputs the suffix for plugins'
complete -c objfw-config -l prog-suffix -d 'Outputs the suffix for binaries'
complete -c objfw-config -l reexport -d 'Outputs LDFLAGS to reexport ObjFW'
complete -c objfw-config -l rpath -d 'Outputs LDFLAGS for using rpath'
complete -c objfw-config -l static-libs \
    -d 'Outputs the required LIBS to link ObjFW statically'
complete -c objfw-config -l version -d 'Outputs the installed version'

Deleted utils/completions/fish/ofarc.fish version [1ed287a4cf].

1
2
3
4
5
6
7
8
9
10
11
12
13
14














-
-
-
-
-
-
-
-
-
-
-
-
-
-
complete -c ofarc -s a -l append -d 'Append to archive'
complete -c ofarc -s c -l create -d 'Create archive'
complete -c ofarc -s C -l directory -r -d 'Extract into the specified directory'
complete -c ofarc -s E -l encoding -x \
    -d 'The encoding used by the archive (only tar files)'
complete -c ofarc -s f -l force -d 'Force / overwrite files'
complete -c ofarc -s h -l help -d 'Show help'
complete -c ofarc -s l -l list -d 'List all files in the archive'
complete -c ofarc -s n -l no-clobber -d 'Never overwrite files'
complete -c ofarc -s p -l print -d 'Print one or more files from the archive'
complete -c ofarc -s q -l quiet -d 'Quiet mode (no output, except errors)'
complete -c ofarc -s t -l type -x -a 'gz lha tar tgz zip' -d 'Archive type'
complete -c ofarc -s v -l verbose -d 'Verbose output for file list'
complete -c ofarc -s x -l extract -d 'Extract files'

Deleted utils/completions/fish/ofdns.fish version [5080d1ffbb].

1
2
3
4
5





-
-
-
-
-
complete -c ofdns -s c -l class -x -d 'The DNS class to query (defaults to IN)'
complete -c ofdns -s h -l help -d 'Show help'
complete -c ofdns -s s -l server -x -d 'The server to query'
complete -c ofdns -s t -l type -x \
    -d 'The record type to query (defaults to ALL, can be repeated)'

Deleted utils/completions/fish/ofhash.fish version [ffdc6cdbcf].

1
2
3
4
5
6
7







-
-
-
-
-
-
-
complete -c ofhash --long-option md5
complete -c ofhash --long-option ripemd160
complete -c ofhash --long-option sha1
complete -c ofhash --long-option sha224
complete -c ofhash --long-option sha256
complete -c ofhash --long-option sha384
complete -c ofhash --long-option sha256

Deleted utils/completions/fish/ofhttp.fish version [99fd9b7109].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15















-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
complete -c ofhttp -x
complete -c ofhttp -s b -l body -r -d 'Specify the file to send as body'
complete -c ofhttp -s c -l continue -d 'Continue download of existing file'
complete -c ofhttp -s f -l force -d 'Force / overwrite existing file'
complete -c ofhttp -s h -l help -d 'Show help'
complete -c ofhttp -s H -l header -x -d 'Add a header (e.g. X-Foo:Bar)'
complete -c ofhttp -s m -l method -x -d 'Set the method of the HTTP request'
complete -c ofhttp -s o -l output -r -d 'Specify output file name'
complete -c ofhttp -s O -l detect-filename \
    -d 'Do a HEAD request to detect the file name'
complete -c ofhttp -s P -l proxy -x -d 'Specify SOCKS5 proxy'
complete -c ofhttp -s q -l quiet -d 'Quiet mode (no output, except errors)'
complete -c ofhttp -s v -l verbose -d 'Verbose mode (print headers)'
complete -c ofhttp -l insecure \
    -d 'Ignore TLS errors and allow insecure redirects'

Modified utils/objfw-compile from [ffd05ad528] to [898b15eff7].

1
2
3

4
5
6
7
8
9
10
1
2

3
4
5
6
7
8
9
10


-
+







#!/bin/sh
#
#  Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
#  Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
#
#  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.
#

Modified utils/objfw-config.in from [06e5d8db3c] to [1ad3420f7b].

1
2
3

4
5
6
7
8
9
10
1
2

3
4
5
6
7
8
9
10


-
+







#!/bin/sh
#
#  Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
#  Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
#
#  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.
#

Modified utils/objfw-embed from [3a281e6a17] to [9ca9ee2bd1].

1
2
3
4
5
6
7
8
9
10
11
12
13
14

15
16

17
18
19
20
21
22
23
1
2
3
4
5
6
7
8
9
10
11
12
13

14
15

16
17
18
19
20
21
22
23













-
+

-
+







#!/bin/sh
if test $# != 3; then
	echo "Usage: $0 source_file filename output.m" 1>&2
	exit 1
fi

exec 1>$3

cat <<EOF
#include <stddef.h>
#include <stdint.h>

#ifdef OF_COMPILING_OBJFW
# import "OFEmbeddedURIHandler.h"
# import "OFEmbeddedIRIHandler.h"
#else
# import <ObjFW/OFEmbeddedURIHandler.h>
# import <ObjFW/OFEmbeddedIRIHandler.h>
#endif

static const uint8_t bytes[] = {
EOF
od -vtx1 $1 | sed -e '/^[^ ][^ ]*$/d;s/  */ /g' -e 's/ $//g;s/^[^ ][^ ]* //' -e 's/ /, 0x/g' -e 's/^/	0x/' -e 's/$/,/'
cat <<EOF
};

Modified utils/objfw-new/NewApp.m from [47a07d5858] to [89654a3c8b].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified utils/objfw-new/NewClass.m from [13b11d77d3] to [8ec18dd2f5].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified utils/objfw-new/ObjFWNew.m from [e1d195ab36] to [3a185096d3].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified utils/objfw-new/Property.h from [e9facd5dfc] to [a9df9e14b6].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified utils/objfw-new/Property.m from [101e199c45] to [5d1264c1a3].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified utils/ofarc/Archive.h from [c57fe80fee] to [5ec6829033].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified utils/ofarc/GZIPArchive.h from [384191029a] to [a3747b86e9].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified utils/ofarc/GZIPArchive.m from [2e682cb46c] to [f819d2f5e4].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified utils/ofarc/LHAArchive.h from [5ad6942309] to [12c1585db9].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified utils/ofarc/LHAArchive.m from [7f7a619844] to [f59c7fc9d2].

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
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

-
+














+
+












+
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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"

#include <errno.h>

#import "OFApplication.h"
#import "OFDate.h"
#import "OFFileManager.h"
#import "OFLocale.h"
#import "OFNumber.h"
#import "OFSet.h"
#import "OFStdIOStream.h"
#import "OFString.h"

#import "LHAArchive.h"
#import "OFArc.h"

#import "OFSetItemAttributesFailedException.h"

static OFArc *app;

static OFString *
indent(OFString *string)
{
	return [string stringByReplacingOccurrencesOfString: @"\n"
59
60
61
62
63
64
65

66
67






68
69
70
71
72
73
74
63
64
65
66
67
68
69
70


71
72
73
74
75
76
77
78
79
80
81
82
83







+
-
-
+
+
+
+
+
+








static void
setModificationDate(OFString *path, OFLHAArchiveEntry *entry)
{
	OFFileAttributes attributes = [OFDictionary
	    dictionaryWithObject: entry.modificationDate
			  forKey: OFFileModificationDate];
	@try {
	[[OFFileManager defaultManager] setAttributes: attributes
					 ofItemAtPath: path];
		[[OFFileManager defaultManager] setAttributes: attributes
						 ofItemAtPath: path];
	} @catch (OFSetItemAttributesFailedException *e) {
		if (e.errNo != EISDIR)
			@throw e;
	}
}

@implementation LHAArchive
+ (void)initialize
{
	if (self == [LHAArchive class])
		app = (OFArc *)[OFApplication sharedApplication].delegate;

Modified utils/ofarc/OFArc.h from [926be48eea] to [f9aed0d4ad].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified utils/ofarc/OFArc.m from [1abc9749ff] to [eb89655310].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
17
18
19
20
21
22
23

24
25
26
27
28
29
30
31
32
33
34
35
17
18
19
20
21
22
23
24
25
26
27
28

29
30
31
32
33
34
35







+




-








#include <string.h>

#import "OFApplication.h"
#import "OFArray.h"
#import "OFFile.h"
#import "OFFileManager.h"
#import "OFIRI.h"
#import "OFLocale.h"
#import "OFOptionsParser.h"
#import "OFSandbox.h"
#import "OFStdIOStream.h"
#import "OFURI.h"

#import "OFArc.h"
#import "GZIPArchive.h"
#import "LHAArchive.h"
#import "TarArchive.h"
#import "ZIPArchive.h"

203
204
205
206
207
208
209
210


211
212
213


214
215
216
217
218
219
220
203
204
205
206
207
208
209

210
211
212


213
214
215
216
217
218
219
220
221







-
+
+

-
-
+
+







	/* Dropped after parsing options */
	sandbox.allowsUnveil = true;

	[OFApplication of_activateSandbox: sandbox];
#endif

#ifndef OF_AMIGAOS
	[OFLocale addLocalizationDirectory: @LOCALIZATION_DIR];
	[OFLocale addLocalizationDirectoryIRI:
	    [OFIRI fileIRIWithPath: @LOCALIZATION_DIR]];
#else
	[OFLocale addLocalizationDirectory:
	    @"PROGDIR:/share/ofarc/localization"];
	[OFLocale addLocalizationDirectoryIRI:
	    [OFIRI fileIRIWithPath: @"PROGDIR:/share/ofarc/localization"]];
#endif

	optionsParser = [OFOptionsParser parserWithOptions: options];
	while ((option = [optionsParser nextOption]) != '\0') {
		switch (option) {
		case 'f':
			if (_overwrite < 0)
458
459
460
461
462
463
464
465

466
467
468
469
470
471
472
459
460
461
462
463
464
465

466
467
468
469
470
471
472
473







-
+







			OFString *error = [OFString
			    stringWithCString: strerror(e.errNo)
				     encoding: [OFLocale encoding]];
			[OFStdErr writeString: @"\r"];
			[OFStdErr writeLine: OF_LOCALIZED(
			    @"failed_to_create_directory",
			    @"Failed to create directory %[dir]: %[error]",
			    @"dir", e.URI.fileSystemRepresentation,
			    @"dir", e.IRI.fileSystemRepresentation,
			    @"error", error)];
			_exitStatus = 1;
		} @catch (OFOpenItemFailedException *e) {
			OFString *error = [OFString
			    stringWithCString: strerror(e.errNo)
				     encoding: [OFLocale encoding]];
			[OFStdErr writeString: @"\r"];

Modified utils/ofarc/TarArchive.h from [5ee57845a6] to [4fe79f6b42].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified utils/ofarc/TarArchive.m from [1feea72626] to [9bead949cb].

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
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

-
+














+
+












+
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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"

#include <errno.h>

#import "OFApplication.h"
#import "OFDate.h"
#import "OFFileManager.h"
#import "OFLocale.h"
#import "OFNumber.h"
#import "OFSet.h"
#import "OFStdIOStream.h"
#import "OFString.h"

#import "TarArchive.h"
#import "OFArc.h"

#import "OFSetItemAttributesFailedException.h"

static OFArc *app;

static void
setPermissions(OFString *path, OFTarArchiveEntry *entry)
{
#ifdef OF_FILE_MANAGER_SUPPORTS_PERMISSIONS
52
53
54
55
56
57
58

59
60






61
62
63
64
65
66
67
56
57
58
59
60
61
62
63


64
65
66
67
68
69
70
71
72
73
74
75
76







+
-
-
+
+
+
+
+
+








	if (modificationDate == nil)
		return;

	attributes = [OFDictionary
	    dictionaryWithObject: modificationDate
			  forKey: OFFileModificationDate];
	@try {
	[[OFFileManager defaultManager] setAttributes: attributes
					 ofItemAtPath: path];
		[[OFFileManager defaultManager] setAttributes: attributes
						 ofItemAtPath: path];
	} @catch (OFSetItemAttributesFailedException *e) {
		if (e.errNo != EISDIR)
			@throw e;
	}
}

@implementation TarArchive
+ (void)initialize
{
	if (self == [TarArchive class])
		app = (OFArc *)[OFApplication sharedApplication].delegate;

Modified utils/ofarc/ZIPArchive.h from [8566715690] to [1c079ef618].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified utils/ofarc/ZIPArchive.m from [cefb3af267] to [110299511c].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *
29
30
31
32
33
34
35

36
37
38
39
40
41
42
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43







+








#import "ZIPArchive.h"
#import "OFArc.h"

#import "OFInvalidFormatException.h"
#import "OFOpenItemFailedException.h"
#import "OFOutOfRangeException.h"
#import "OFSetItemAttributesFailedException.h"

static OFArc *app;

static void
setPermissions(OFString *path, OFZIPArchiveEntry *entry)
{
#ifdef OF_FILE_MANAGER_SUPPORTS_PERMISSIONS
62
63
64
65
66
67
68

69
70






71
72
73
74
75
76
77
63
64
65
66
67
68
69
70


71
72
73
74
75
76
77
78
79
80
81
82
83







+
-
-
+
+
+
+
+
+








	if (modificationDate == nil)
		return;

	attributes = [OFDictionary
	    dictionaryWithObject: modificationDate
			  forKey: OFFileModificationDate];
	@try {
	[[OFFileManager defaultManager] setAttributes: attributes
					 ofItemAtPath: path];
		[[OFFileManager defaultManager] setAttributes: attributes
						 ofItemAtPath: path];
	} @catch (OFSetItemAttributesFailedException *e) {
		if (e.errNo != EISDIR)
			@throw e;
	}
}

@implementation ZIPArchive
+ (void)initialize
{
	if (self == [ZIPArchive class])
		app = (OFArc *)[OFApplication sharedApplication].delegate;

Modified utils/ofdns/OFDNS.m from [32af1e7083] to [202b18cab3].

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
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

-
+


















+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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 "OFApplication.h"
#import "OFArray.h"
#import "OFDNSResolver.h"
#import "OFIRI.h"
#import "OFLocale.h"
#import "OFOptionsParser.h"
#import "OFSandbox.h"
#import "OFStdIOStream.h"

@interface OFDNS: OFObject <OFApplicationDelegate, OFDNSResolverQueryDelegate>
{
48
49
50
51
52
53
54
55



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

56
57
58
59
60
61
62
63
64
65







-
+
+
+







		    @"  The DNS class to query (defaults to IN)\n    "
		    @"-h  --help  "
		    @"  Show this help\n    "
		    @"-s  --server"
		    @"  The server to query\n    "
		    @"-t  --type  "
		    @"  The record type to query (defaults to ALL, can be "
		    @"repeated)")];
		    @"repeated)\n    "
		    @"    --tcp   "
		    @"  Force using TCP for the query")];
	}

	[OFApplication terminateWithStatus: status];
}

@implementation OFDNS
-  (void)resolver: (OFDNSResolver *)resolver
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
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







+





+











-
+
+

-
-
+
+







	if (_inFlight == 0)
		[OFApplication terminateWithStatus: _errors];
}

- (void)applicationDidFinishLaunching: (OFNotification *)notification
{
	OFString *DNSClassString, *server;
	bool forceTCP;
	const OFOptionsParserOption options[] = {
		{ 'c', @"class", 1, NULL, &DNSClassString },
		{ 'h', @"help", 0, NULL, NULL },
		{ 's', @"server", 1, NULL, &server },
		{ 't', @"type", 1, NULL, NULL },
		{ '\0', @"tcp", 0, &forceTCP, NULL },
		{ '\0', nil, 0, NULL, NULL }
	};
	OFMutableArray OF_GENERIC(OFString *) *recordTypes;
	OFOptionsParser *optionsParser;
	OFUnichar option;
	OFArray OF_GENERIC(OFString *) *remainingArguments;
	OFDNSResolver *resolver;
	OFDNSClass DNSClass;

#ifdef OF_HAVE_FILES
# ifndef OF_AMIGAOS
	[OFLocale addLocalizationDirectory: @LOCALIZATION_DIR];
	[OFLocale addLocalizationDirectoryIRI:
	    [OFIRI fileIRIWithPath: @LOCALIZATION_DIR]];
# else
	[OFLocale addLocalizationDirectory:
	    @"PROGDIR:/share/ofdns/localization"];
	[OFLocale addLocalizationDirectoryIRI:
	    [OFIRI fileIRIWithPath: @"PROGDIR:/share/ofdns/localization"]];
# endif
#endif

#ifdef OF_HAVE_SANDBOX
	OFSandbox *sandbox = [[OFSandbox alloc] init];
	@try {
		sandbox.allowsStdIO = 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
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







+
+
+






-
+
-

-








	remainingArguments = optionsParser.remainingArguments;

	if (remainingArguments.count < 1)
		help(OFStdErr, false, 1);

	resolver = [OFDNSResolver resolver];
	resolver.configReloadInterval = 0;
	resolver.forcesTCP = forceTCP;

	DNSClass = (DNSClassString != nil
	    ? OFDNSClassParseName(DNSClassString) : OFDNSClassIN);

	if (recordTypes.count == 0)
		[recordTypes addObject: @"ALL"];

	if (server != nil) {
	if (server != nil)
		resolver.configReloadInterval = 0;
		resolver.nameServers = [OFArray arrayWithObject: server];
	}

	for (OFString *domainName in remainingArguments) {
		for (OFString *recordTypeString in recordTypes) {
			OFDNSRecordType recordType =
			    OFDNSRecordTypeParseName(recordTypeString);
			OFDNSQuery *query =
			    [OFDNSQuery queryWithDomainName: domainName

Modified utils/ofdns/localization/de.json from [a2dd6e542b] to [86f1735865].

1
2
3
4
5
6
7
8
9


10
11
12
13
14
15
16
17
18
1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
16
17
18
19








-
+
+









{
    "usage": "Benutzung: %[prog] -[chst] domain1 [domain2 ...]",
    "full_usage": [
        "Optionen:\n",
        "    -c  --class   Die anzufragende DNS-Klasse (standardmäßig IN)\n",
        "    -h  --help    Diese Hilfe anzeigen\n",
        "    -s  --server  Der abzufragende Server\n",
        "    -t  --type    Der anzufragende Record-Typ (standardmäßig ALL,\n",
        "                  kann wiederholt werden)"
        "                  kann wiederholt werden)\n",
        "        --tcp     Benutzung von TCP erzwingen"
    ],
    "long_option_requires_argument": [
        "%[prog]: Option --%[opt] benötigt ein Argument"
    ],
    "option_requires_argument": "%[prog]: Option -%[opt] benötigt ein Argument",
    "unknown_long_option": "%[prog]: Unbekannte Option: --%[opt]",
    "unknown_option": "%[prog]: Unbekannte Option: -%[opt]",
    "failed_to_resolve": "Auflösen fehlgeschlagen: %[exception]"
}

Modified utils/ofhash/OFHash.m from [8b4892a5e2] to [5b3e61635c].

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
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

-
+


















+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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 "OFApplication.h"
#import "OFArray.h"
#import "OFFile.h"
#import "OFIRI.h"
#import "OFLocale.h"
#import "OFMD5Hash.h"
#import "OFOptionsParser.h"
#import "OFRIPEMD160Hash.h"
#import "OFSHA1Hash.h"
#import "OFSHA224Hash.h"
#import "OFSHA256Hash.h"
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
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







-
+
+

-
-
+
+













-
+







	OFSHA1Hash *SHA1Hash = nil;
	OFSHA224Hash *SHA224Hash = nil;
	OFSHA256Hash *SHA256Hash = nil;
	OFSHA384Hash *SHA384Hash = nil;
	OFSHA512Hash *SHA512Hash = nil;

#ifndef OF_AMIGAOS
	[OFLocale addLocalizationDirectory: @LOCALIZATION_DIR];
	[OFLocale addLocalizationDirectoryIRI:
	    [OFIRI fileIRIWithPath: @LOCALIZATION_DIR]];
#else
	[OFLocale addLocalizationDirectory:
	    @"PROGDIR:/share/ofhash/localization"];
	[OFLocale addLocalizationDirectoryIRI:
	    [OFIRI fileIRIWithPath: @"PROGDIR:/share/ofhash/localization"]];
#endif

	while ((option = [optionsParser nextOption]) != '\0') {
		switch (option) {
		case '?':
			if (optionsParser.lastLongOption != nil)
				[OFStdErr writeLine:
				    OF_LOCALIZED(@"unknown_long_option",
				    @"%[prog]: Unknown option: --%[opt]",
				    @"prog", [OFApplication programName],
				    @"opt", optionsParser.lastLongOption)];
			else {
				OFString *optStr = [OFString stringWithFormat:
				    @"%c", optionsParser.lastOption];
				    @"%C", optionsParser.lastOption];
				[OFStdErr writeLine:
				    OF_LOCALIZED(@"unknown_option",
				    @"%[prog]: Unknown option: -%[opt]",
				    @"prog", [OFApplication programName],
				    @"opt", optStr)];
			}

Modified utils/ofhttp/OFHTTP.m from [4bdf3b8ffc] to [22d5583cf6].

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
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

-
+


















+






+










-















+












-
-
+
+















-
+

















-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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 "OFApplication.h"
#import "OFArray.h"
#import "OFData.h"
#import "OFDate.h"
#import "OFDictionary.h"
#import "OFFile.h"
#import "OFFileManager.h"
#import "OFHTTPClient.h"
#import "OFHTTPRequest.h"
#import "OFHTTPResponse.h"
#import "OFIRI.h"
#import "OFLocale.h"
#import "OFOptionsParser.h"
#ifdef OF_HAVE_PLUGINS
# import "OFPlugin.h"
#endif
#import "OFSandbox.h"
#import "OFStdIOStream.h"
#import "OFSystemInfo.h"
#import "OFTCPSocket.h"
#import "OFTLSStream.h"
#import "OFURI.h"

#ifdef HAVE_TLS_SUPPORT
# import "ObjFWTLS.h"
#endif

#import "OFConnectSocketFailedException.h"
#import "OFGetItemAttributesFailedException.h"
#import "OFHTTPRequestFailedException.h"
#import "OFInvalidArgumentException.h"
#import "OFInvalidFormatException.h"
#import "OFInvalidServerResponseException.h"
#import "OFOpenItemFailedException.h"
#import "OFOutOfRangeException.h"
#import "OFReadFailedException.h"
#import "OFResolveHostFailedException.h"
#import "OFSetItemAttributesFailedException.h"
#import "OFUnsupportedProtocolException.h"
#import "OFWriteFailedException.h"

#import "ProgressBar.h"

#define GIBIBYTE (1024 * 1024 * 1024)
#define MEBIBYTE (1024 * 1024)
#define KIBIBYTE (1024)

@interface OFHTTP: OFObject <OFApplicationDelegate, OFHTTPClientDelegate,
    OFStreamDelegate>
{
	OFArray OF_GENERIC(OFString *) *_URIs;
	size_t _URIIndex;
	OFArray OF_GENERIC(OFString *) *_IRIs;
	size_t _IRIIndex;
	int _errorCode;
	OFString *_outputPath, *_currentFileName;
	bool _continue, _force, _detectFileName, _detectFileNameRequest;
	bool _detectedFileName, _quiet, _verbose, _insecure, _ignoreStatus;
	bool _useUnicode;
	OFStream *_body;
	OFHTTPRequestMethod _method;
	OFMutableDictionary *_clientHeaders;
	OFHTTPClient *_HTTPClient;
	char *_buffer;
	OFStream *_output;
	unsigned long long _received, _length, _resumedFrom;
	ProgressBar *_progressBar;
}

- (void)downloadNextURI;
- (void)downloadNextIRI;
@end

#ifdef HAVE_TLS_SUPPORT
void
_reference_to_ObjFWTLS(void)
{
	_ObjFWTLS_reference = 1;
}
#endif

OF_APPLICATION_DELEGATE(OFHTTP)

static void
help(OFStream *stream, bool full, int status)
{
	[OFStdErr writeLine:
	    OF_LOCALIZED(@"usage",
	    @"Usage: %[prog] -[cehHmoOPqv] uri1 [uri2 ...]",
	    @"Usage: %[prog] -[cehHmoOPqv] iri1 [iri2 ...]",
	    @"prog", [OFApplication programName])];

	if (full) {
		[stream writeString: @"\n"];
		[stream writeLine: OF_LOCALIZED(@"full_usage",
		    @"Options:\n    "
		    @"-b  --body           "
447
448
449
450
451
452
453
454


455
456
457


458
459
460
461
462
463
464
449
450
451
452
453
454
455

456
457
458


459
460
461
462
463
464
465
466
467







-
+
+

-
-
+
+







	/* Dropped after parsing options */
	sandbox.allowsUnveil = true;

	[OFApplication of_activateSandbox: sandbox];
#endif

#ifndef OF_AMIGAOS
	[OFLocale addLocalizationDirectory: @LOCALIZATION_DIR];
	[OFLocale addLocalizationDirectoryIRI:
	    [OFIRI fileIRIWithPath: @LOCALIZATION_DIR]];
#else
	[OFLocale addLocalizationDirectory:
	    @"PROGDIR:/share/ofhttp/localization"];
	[OFLocale addLocalizationDirectoryIRI:
	    [OFIRI fileIRIWithPath: @"PROGDIR:/share/ofhttp/localization"]];
#endif

	optionsParser = [OFOptionsParser parserWithOptions: options];
	while ((option = [optionsParser nextOption]) != '\0') {
		switch (option) {
		case 'b':
			[self setBody: optionsParser.argument];
481
482
483
484
485
486
487
488

489
490
491
492
493
494
495
484
485
486
487
488
489
490

491
492
493
494
495
496
497
498







-
+







				    OF_LOCALIZED(@"long_argument_missing",
				    @"%[prog]: Argument for option --%[opt] "
				    @"missing"
				    @"prog", [OFApplication programName],
				    @"opt", optionsParser.lastLongOption)];
			else {
				OFString *optStr = [OFString
				    stringWithFormat: @"%c",
				    stringWithFormat: @"%C",
				    optionsParser.lastOption];
				[OFStdErr writeLine:
				    OF_LOCALIZED(@"argument_missing",
				    @"%[prog]: Argument for option -%[opt] "
				    @"missing",
				    @"prog", [OFApplication programName],
				    @"opt", optStr)];
511
512
513
514
515
516
517
518

519
520
521
522
523
524
525
514
515
516
517
518
519
520

521
522
523
524
525
526
527
528







-
+







				[OFStdErr writeLine:
				    OF_LOCALIZED(@"unknown_long_option",
				    @"%[prog]: Unknown option: --%[opt]",
				    @"prog", [OFApplication programName],
				    @"opt", optionsParser.lastLongOption)];
			else {
				OFString *optStr = [OFString
				    stringWithFormat: @"%c",
				    stringWithFormat: @"%C",
				    optionsParser.lastOption];
				[OFStdErr writeLine:
				    OF_LOCALIZED(@"unknown_option",
				    @"%[prog]: Unknown option: -%[opt]",
				    @"prog", [OFApplication programName],
				    @"opt", optStr)];
			}
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

572
573
574


575
576
577
578
579
580
581
582
583
584
585
586
587
588
589

590
591
592
593
594
595
596
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
572
573

574
575


576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591

592
593
594
595
596
597
598
599







-
+

-
+



















-
+

-
-
+
+














-
+







	[sandbox unveilPath: @"/etc/ssl" permissions: @"r"];

	sandbox.allowsUnveil = false;
	[OFApplication of_activateSandbox: sandbox];
#endif

	_outputPath = [outputPath copy];
	_URIs = [optionsParser.remainingArguments copy];
	_IRIs = [optionsParser.remainingArguments copy];

	if (_URIs.count < 1)
	if (_IRIs.count < 1)
		help(OFStdErr, false, 1);

	if (_quiet && _verbose) {
		[OFStdErr writeLine: OF_LOCALIZED(@"quiet_xor_verbose",
		    @"%[prog]: -q / --quiet and -v / --verbose are mutually "
		    @"exclusive!",
		    @"prog", [OFApplication programName])];
		[OFApplication terminateWithStatus: 1];
	}

	if (_outputPath != nil && _detectFileName) {
		[OFStdErr writeLine: OF_LOCALIZED(
		    @"output_xor_detect_filename",
		    @"%[prog]: -o / --output and -O / --detect-filename are "
		    @"mutually exclusive!",
		    @"prog", [OFApplication programName])];
		[OFApplication terminateWithStatus: 1];
	}

	if (_outputPath != nil && _URIs.count > 1) {
	if (_outputPath != nil && _IRIs.count > 1) {
		[OFStdErr writeLine:
		    OF_LOCALIZED(@"output_only_with_one_uri",
		    @"%[prog]: Cannot use -o / --output when more than one URI "
		    OF_LOCALIZED(@"output_only_with_one_iri",
		    @"%[prog]: Cannot use -o / --output when more than one IRI "
		    @"has been specified!",
		    @"prog", [OFApplication programName])];
		[OFApplication terminateWithStatus: 1];
	}

	if (_insecure)
		_HTTPClient.allowsInsecureRedirects = true;

#ifdef OF_WINDOWS
	_useUnicode = [OFSystemInfo isWindowsNT];
#else
	_useUnicode = ([OFLocale encoding] == OFStringEncodingUTF8);
#endif

	[self performSelector: @selector(downloadNextURI) afterDelay: 0];
	[self performSelector: @selector(downloadNextIRI) afterDelay: 0];
}

-	(void)client: (OFHTTPClient *)client
  didCreateTLSStream: (OFTLSStream *)stream
	     request: (OFHTTPRequest *)request
{
	/* Use setter instead of property access to work around GCC bug. */
606
607
608
609
610
611
612
613

614
615
616
617
618
619
620
609
610
611
612
613
614
615

616
617
618
619
620
621
622
623







-
+







		char buffer[4096];
		size_t length = [_body readIntoBuffer: buffer length: 4096];
		[body writeBuffer: buffer length: length];
	}
}

-	       (bool)client: (OFHTTPClient *)client
  shouldFollowRedirectToURI: (OFURI *)URI
  shouldFollowRedirectToIRI: (OFIRI *)IRI
		 statusCode: (short)statusCode
		    request: (OFHTTPRequest *)request
		   response: (OFHTTPResponse *)response
{
	if (_verbose) {
		void *pool = objc_autoreleasePoolPush();
		OFDictionary OF_GENERIC(OFString *, OFString *) *headers =
628
629
630
631
632
633
634
635

636
637

638
639
640
641
642
643
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
676
677
678
679
680
681
631
632
633
634
635
636
637

638
639

640
641
642
643
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
676

677
678
679
680
681
682
683
684







-
+

-
+













-
+












-
+


-
+


-
+



-
+







			[OFStdOut writeFormat: @"  %@: %@\n", key, object];

		objc_autoreleasePoolPop(pool);
	}

	if (!_quiet) {
		if (_useUnicode)
			[OFStdOut writeFormat: @"☇ %@", URI.string];
			[OFStdOut writeFormat: @"☇ %@", IRI.string];
		else
			[OFStdOut writeFormat: @"< %@", URI.string];
			[OFStdOut writeFormat: @"< %@", IRI.string];
	}

	_length = 0;

	return true;
}

-      (bool)stream: (OFStream *)response
  didReadIntoBuffer: (void *)buffer
	     length: (size_t)length
	  exception: (id)exception
{
	if (exception != nil) {
		OFString *URI;
		OFString *IRI;

		[_progressBar stop];
		[_progressBar draw];
		[_progressBar release];
		_progressBar = nil;

		if (!_quiet) {
			[OFStdOut writeString: @"\n  "];
			[OFStdOut writeLine: OF_LOCALIZED(@"download_error",
			    @"Error!")];
		}

		URI = [_URIs objectAtIndex: _URIIndex - 1];
		IRI = [_IRIs objectAtIndex: _IRIIndex - 1];
		[OFStdErr writeLine: OF_LOCALIZED(
		    @"download_failed_exception",
		    @"%[prog]: Failed to download <%[uri]>!\n"
		    @"%[prog]: Failed to download <%[iri]>!\n"
		    @"  %[exception]",
		    @"prog", [OFApplication programName],
		    @"uri", URI,
		    @"iri", IRI,
		    @"exception", exception)];

		_errorCode = 1;
		[self performSelector: @selector(downloadNextURI)
		[self performSelector: @selector(downloadNextIRI)
			   afterDelay: 0];
		return false;
	}

	[_output writeBuffer: buffer length: length];

	_received += length;
689
690
691
692
693
694
695
696

697
698
699
700
701
702
703
692
693
694
695
696
697
698

699
700
701
702
703
704
705
706







-
+








		if (!_quiet) {
			[OFStdOut writeString: @"\n  "];
			[OFStdOut writeLine:
			    OF_LOCALIZED(@"download_done", @"Done!")];
		}

		[self performSelector: @selector(downloadNextURI)
		[self performSelector: @selector(downloadNextIRI)
			   afterDelay: 0];
		return false;
	}

	return true;
}

813
814
815
816
817
818
819
820

821
822
823

824
825
826
827
828
829
830
831
832

833
834
835

836
837
838
839
840
841
842
843
844

845
846
847

848
849
850
851
852
853
854
816
817
818
819
820
821
822

823
824
825

826
827
828
829
830
831
832
833
834

835
836
837

838
839
840
841
842
843
844
845
846

847
848
849

850
851
852
853
854
855
856
857







-
+


-
+








-
+


-
+








-
+


-
+







		if ([exception isKindOfClass:
		    [OFResolveHostFailedException class]]) {
			if (!_quiet)
				[OFStdOut writeString: @"\n"];

			[OFStdErr writeLine:
			    OF_LOCALIZED(@"download_resolve_host_failed",
			    @"%[prog]: Failed to download <%[uri]>!\n"
			    @"%[prog]: Failed to download <%[iri]>!\n"
			    @"  Failed to resolve host: %[exception]",
			    @"prog", [OFApplication programName],
			    @"uri", request.URI.string,
			    @"iri", request.IRI.string,
			    @"exception", exception)];
		} else if ([exception isKindOfClass:
		    [OFConnectSocketFailedException class]]) {
			if (!_quiet)
				[OFStdOut writeString: @"\n"];

			[OFStdErr writeLine:
			    OF_LOCALIZED(@"download_failed_connection_failed",
			    @"%[prog]: Failed to download <%[uri]>!\n"
			    @"%[prog]: Failed to download <%[iri]>!\n"
			    @"  Connection failed: %[exception]",
			    @"prog", [OFApplication programName],
			    @"uri", request.URI.string,
			    @"iri", request.IRI.string,
			    @"exception", exception)];
		} else if ([exception isKindOfClass:
		    [OFInvalidServerResponseException class]]) {
			if (!_quiet)
				[OFStdOut writeString: @"\n"];

			[OFStdErr writeLine: OF_LOCALIZED(
			    @"download_failed_invalid_server_response",
			    @"%[prog]: Failed to download <%[uri]>!\n"
			    @"%[prog]: Failed to download <%[iri]>!\n"
			    @"  Invalid server response!",
			    @"prog", [OFApplication programName],
			    @"uri", request.URI.string)];
			    @"iri", request.IRI.string)];
		} else if ([exception isKindOfClass:
		    [OFUnsupportedProtocolException class]]) {
			if (!_quiet)
				[OFStdOut writeString: @"\n"];

			[OFStdErr writeLine: OF_LOCALIZED(@"no_tls_support",
			    @"%[prog]: No TLS support in ObjFW!\n"
877
878
879
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
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







-
+


-
+
















-
+


-
+





-
+














-
-
+
+

-
+







				error = OF_LOCALIZED(
				    @"download_failed_read_or_write_failed_"
				    @"write",
				    @"Write failed");

			[OFStdErr writeLine: OF_LOCALIZED(
			    @"download_failed_read_or_write_failed",
			    @"%[prog]: Failed to download <%[uri]>!\n"
			    @"%[prog]: Failed to download <%[iri]>!\n"
			    @"  %[error]: %[exception]",
			    @"prog", [OFApplication programName],
			    @"uri", request.URI.string,
			    @"iri", request.IRI.string,
			    @"error", error,
			    @"exception", exception)];
		} else if ([exception isKindOfClass:
		    [OFHTTPRequestFailedException class]]) {
			short statusCode;
			OFString *codeString;

			if (_ignoreStatus) {
				exception = nil;
				goto after_exception_handling;
			}

			statusCode = response.statusCode;
			codeString = [OFString stringWithFormat: @"%hd %@",
			    statusCode, OFHTTPStatusCodeString(statusCode)];
			[OFStdErr writeLine: OF_LOCALIZED(@"download_failed",
			    @"%[prog]: Failed to download <%[uri]>!\n"
			    @"%[prog]: Failed to download <%[iri]>!\n"
			    @"  HTTP status code: %[code]",
			    @"prog", [OFApplication programName],
			    @"uri", request.URI.string,
			    @"iri", request.IRI.string,
			    @"code", codeString)];
		} else
			@throw exception;

		_errorCode = 1;
		[self performSelector: @selector(downloadNextURI)
		[self performSelector: @selector(downloadNextIRI)
			   afterDelay: 0];
		return;
	}

after_exception_handling:
	if (_method == OFHTTPRequestMethodHead)
		goto next;

	if (_detectFileNameRequest) {
		_currentFileName = [fileNameFromContentDisposition(
		    [response.headers objectForKey: @"Content-Disposition"])
		    copy];
		_detectedFileName = true;

		/* Handle this URI on the next -[downloadNextURI] call */
		_URIIndex--;
		/* Handle this IRI on the next -[downloadNextIRI] call */
		_IRIIndex--;

		[self performSelector: @selector(downloadNextURI)
		[self performSelector: @selector(downloadNextIRI)
			   afterDelay: 0];
		return;
	}

	if ([_outputPath isEqual: @"-"])
		_output = [OFStdOut copy];
	else {
961
962
963
964
965
966
967

































968
969
970
971
972
973
974
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







			    @"prog", [OFApplication programName],
			    @"filename", _currentFileName,
			    @"exception", e)];

			_errorCode = 1;
			goto next;
		}

#ifdef OF_LINUX
		@try {
			OFString *IRIString = request.IRI.string;
			OFData *downloadedFromData = [OFData
			    dataWithItems: IRIString.UTF8String
				    count: IRIString.UTF8StringLength + 1];
			[[OFFileManager defaultManager]
			    setExtendedAttributeData: downloadedFromData
					     forName: @"user.ofhttp."
						      @"downloaded_from"
					ofItemAtPath: _currentFileName];
		} @catch (OFSetItemAttributesFailedException *) {
			/* Ignore */
		}
#endif

#ifdef OF_MACOS
		@try {
			OFString *quarantine = [OFString stringWithFormat:
			    @"0000;%08" @PRIx64 @";ofhttp;",
			    (uint64_t)[[OFDate date] timeIntervalSince1970]];
			OFData *quarantineData = [OFData
			    dataWithItems: quarantine.UTF8String
				    count: quarantine.UTF8StringLength];
			[[OFFileManager defaultManager]
			    setExtendedAttributeData: quarantineData
					     forName: @"com.apple.quarantine"
					ofItemAtPath: _currentFileName];
		} @catch (OFSetItemAttributesFailedException *e) {
			/* Ignore */
		}
#endif
	}

	if (!_quiet) {
		_progressBar = [[ProgressBar alloc]
		    initWithLength: _length
		       resumedFrom: _resumedFrom
			useUnicode: _useUnicode];
983
984
985
986
987
988
989
990

991
992
993

994
995
996


997
998
999
1000
1001
1002
1003
1004
1005
1006

1007
1008
1009
1010
1011


1012
1013
1014


1015
1016

1017
1018
1019
1020
1021
1022

1023
1024

1025
1026

1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037

1038
1039

1040
1041
1042

1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061

1062
1063
1064
1065
1066
1067
1068
1019
1020
1021
1022
1023
1024
1025

1026
1027
1028

1029
1030


1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041

1042
1043
1044
1045


1046
1047
1048


1049
1050
1051

1052
1053
1054
1055
1056
1057

1058
1059

1060
1061

1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072

1073
1074

1075
1076
1077

1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096

1097
1098
1099
1100
1101
1102
1103
1104







-
+


-
+

-
-
+
+









-
+



-
-
+
+

-
-
+
+

-
+





-
+

-
+

-
+










-
+

-
+


-
+


















-
+







	[response asyncReadIntoBuffer: _buffer length: [OFSystemInfo pageSize]];
	return;

next:
	[_currentFileName release];
	_currentFileName = nil;

	[self performSelector: @selector(downloadNextURI) afterDelay: 0];
	[self performSelector: @selector(downloadNextIRI) afterDelay: 0];
}

- (void)downloadNextURI
- (void)downloadNextIRI
{
	OFString *URIString = nil;
	OFURI *URI;
	OFString *IRIString = nil;
	OFIRI *IRI;
	OFMutableDictionary *clientHeaders;
	OFHTTPRequest *request;

	_received = _length = _resumedFrom = 0;

	if (_output != OFStdOut)
		[_output release];
	_output = nil;

	if (_URIIndex >= _URIs.count)
	if (_IRIIndex >= _IRIs.count)
		[OFApplication terminateWithStatus: _errorCode];

	@try {
		URIString = [_URIs objectAtIndex: _URIIndex++];
		URI = [OFURI URIWithString: URIString];
		IRIString = [_IRIs objectAtIndex: _IRIIndex++];
		IRI = [OFIRI IRIWithString: IRIString];
	} @catch (OFInvalidFormatException *e) {
		[OFStdErr writeLine: OF_LOCALIZED(@"invalid_uri",
		    @"%[prog]: Invalid URI: <%[uri]>!",
		[OFStdErr writeLine: OF_LOCALIZED(@"invalid_iri",
		    @"%[prog]: Invalid IRI: <%[iri]>!",
		    @"prog", [OFApplication programName],
		    @"uri", URIString)];
		    @"iri", IRIString)];

		_errorCode = 1;
		goto next;
	}

	if (![URI.scheme isEqual: @"http"] && ![URI.scheme isEqual: @"https"]) {
	if (![IRI.scheme isEqual: @"http"] && ![IRI.scheme isEqual: @"https"]) {
		[OFStdErr writeLine: OF_LOCALIZED(@"invalid_scheme",
		    @"%[prog]: Invalid scheme: <%[uri]>!",
		    @"%[prog]: Invalid scheme: <%[iri]>!",
		    @"prog", [OFApplication programName],
		    @"uri", URIString)];
		    @"iri", IRIString)];

		_errorCode = 1;
		goto next;
	}

	clientHeaders = [[_clientHeaders mutableCopy] autorelease];

	if (_detectFileName && !_detectedFileName) {
		if (!_quiet) {
			if (_useUnicode)
				[OFStdOut writeFormat: @"⠒ %@", URI.string];
				[OFStdOut writeFormat: @"⠒ %@", IRI.string];
			else
				[OFStdOut writeFormat: @"? %@", URI.string];
				[OFStdOut writeFormat: @"? %@", IRI.string];
		}

		request = [OFHTTPRequest requestWithURI: URI];
		request = [OFHTTPRequest requestWithIRI: IRI];
		request.headers = clientHeaders;
		request.method = OFHTTPRequestMethodHead;

		_detectFileNameRequest = true;
		[_HTTPClient asyncPerformRequest: request];
		return;
	}

	if (!_detectedFileName) {
		[_currentFileName release];
		_currentFileName = nil;
	} else
		_detectedFileName = false;

	if (_currentFileName == nil)
		_currentFileName = [_outputPath copy];

	if (_currentFileName == nil)
		_currentFileName = [URI.path.lastPathComponent copy];
		_currentFileName = [IRI.path.lastPathComponent copy];

	if ([_currentFileName isEqual: @"/"]) {
		[_currentFileName release];
		_currentFileName = nil;
	}

	if (_currentFileName == nil)
1085
1086
1087
1088
1089
1090
1091
1092

1093
1094

1095
1096
1097

1098
1099
1100
1101
1102
1103
1104
1105
1106

1107
1108
1121
1122
1123
1124
1125
1126
1127

1128
1129

1130
1131
1132

1133
1134
1135
1136
1137
1138
1139
1140
1141

1142
1143
1144







-
+

-
+


-
+








-
+


			[clientHeaders setObject: range forKey: @"Range"];
		} @catch (OFGetItemAttributesFailedException *e) {
		}
	}

	if (!_quiet) {
		if (_useUnicode)
			[OFStdOut writeFormat: @"⇣ %@", URI.string];
			[OFStdOut writeFormat: @"⇣ %@", IRI.string];
		else
			[OFStdOut writeFormat: @"< %@", URI.string];
			[OFStdOut writeFormat: @"< %@", IRI.string];
	}

	request = [OFHTTPRequest requestWithURI: URI];
	request = [OFHTTPRequest requestWithIRI: IRI];
	request.headers = clientHeaders;
	request.method = _method;

	_detectFileNameRequest = false;
	[_HTTPClient asyncPerformRequest: request];
	return;

next:
	[self performSelector: @selector(downloadNextURI) afterDelay: 0];
	[self performSelector: @selector(downloadNextIRI) afterDelay: 0];
}
@end

Modified utils/ofhttp/ProgressBar.h from [be2c97fe71] to [c16c6906dc].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified utils/ofhttp/ProgressBar.m from [9a2768256d] to [234c4e6655].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * 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.
 *

Modified utils/ofhttp/localization/de.json from [839a028930] to [d50b9e554d].

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







{
    "usage": "Benutzung: %[prog] -[cehHmoOPqv] uri1 [uri2 ...]",
    "usage": "Benutzung: %[prog] -[cehHmoOPqv] iri1 [iri2 ...]",
    "full_usage": [
        "Optionen:\n",
        "    -b  --body             Angegebene Datei als Body übergeben\n",
        "                           (- für Standard-Eingabe)\n",
        "    -c  --continue         Download von existierender Datei ",
        "fortsetzen\n",
        "    -f  --force            Existierende Datei überschreiben\n",
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
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







-
-
+
+



-
+



-
+



-
+














-
+



-
+




-
+



-
-
+
+







        "%[prog]: -q / --quiet und -v / --verbose schließen sich gegenseitig ",
        "aus!"
    ],
    "output_xor_detect_filename": [
        "%[prog]: -o / --output und -O / --detect-filename schließen sich ",
        "gegenseitig aus!"
    ],
    "output_only_with_one_uri": [
        "%[prog]: -o / --output kann nicht mit mehr als einer URI benutzt ",
    "output_only_with_one_iri": [
        "%[prog]: -o / --output kann nicht mit mehr als einer IRI benutzt ",
        "werden!"
    ],
    "download_resolve_host_failed": [
        "%[prog]: Fehler beim Download von <%[uri]>!\n",
        "%[prog]: Fehler beim Download von <%[iri]>!\n",
        "  Host auflösen fehlgeschlagen: %[exception]"
    ],
    "download_failed_connection_failed": [
        "%[prog]: Fehler beim Download von <%[uri]>!\n",
        "%[prog]: Fehler beim Download von <%[iri]>!\n",
        "  Verbindung fehlgeschlagen: %[exception]"
    ],
    "download_failed_invalid_server_response": [
        "%[prog]: Fehler beim Download von <%[uri]>!\n",
        "%[prog]: Fehler beim Download von <%[iri]>!\n",
        "  Ungültige Antwort vom Server!"
    ],
    "no_tls_support": [
        "%[prog]: Keine TLS-Unterstützung in ObjFW!\n",
        "  Um via HTTPS runterzuladen müssen Sie entweder ObjFW mit TLS-",
        "Unterstützung\n",
        "  kompilieren oder eine Bibliothek mittels „preload” laden, welche ",
        "TLS-Support\n",
        "  zu ObjFW hinzufügt!"
    ],
    "download_failed_read_or_write_failed_any": "Lesen oder Schreiben",
    "download_failed_read_or_write_failed_read": "Lesen",
    "download_failed_read_or_write_failed_write": "Schreiben",
    "download_failed_read_or_write_failed": [
        "%[prog]: Fehler beim Download von <%[uri]>!\n",
        "%[prog]: Fehler beim Download von <%[iri]>!\n",
        "  %[error]: %[exception]"
    ],
    "download_failed": [
        "%[prog]: Fehler beim Download von <%[uri]>!\n",
        "%[prog]: Fehler beim Download von <%[iri]>!\n",
        "  HTTP Status-Code: %[code]"
    ],
    "download_error": "Fehler!",
    "download_failed_exception": [
        "%[prog]: Fehler beim Download von <%[uri]>!\n",
        "%[prog]: Fehler beim Download von <%[iri]>!\n",
        "  %[exception]"
    ],
    "download_done": "Fertig!",
    "invalid_uri": "%[prog]: Ungültige URI: <%[uri]>!",
    "invalid_scheme": "%[prog]: Ungültiges Schema: <%[uri]>!",
    "invalid_iri": "%[prog]: Ungültige IRI: <%[iri]>!",
    "invalid_scheme": "%[prog]: Ungültiges Schema: <%[iri]>!",
    "type_unknown": "unbekannt",
    "size_gib": "%[num] GiB",
    "size_mib": "%[num] MiB",
    "size_kib": "%[num] KiB",
    "size_bytes": [
        [
            {"num == 1": "1 Byte"},