ObjFW  Check-in [bf4b06cecd]

Overview
Comment:Merge branch "objfwtest" into "asn1"
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | asn1
Files: files | file ages | folders
SHA3-256: bf4b06cecd01048cc1d350e56a9790278ccb4f06ad5c757486f511601b25b9b1
User & Date: js on 2024-02-11 22:43:20
Other Links: branch diff | manifest | tags
Context
2024-02-11
23:48
Migrate OFASN1DERParsingTests to ObjFWTest check-in: 26368c00c5 user: js tags: asn1
22:43
Merge branch "objfwtest" into "asn1" check-in: bf4b06cecd user: js tags: asn1
22:32
Migrate OFINIFileTests to ObjFWTest check-in: cc7c76d3c2 user: js tags: objfwtest
2024-01-14
18:06
ObjFW.h: Remove leftover #import check-in: 7125cf2eaa user: js tags: asn1
Changes

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

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
config.log
config.status
configure
docs
extra.mk
generators/library/gen_libraries
generators/unicode/gen_tables












src/Info.plist
src/bridge/Info.plist
src/libobjfw.*
src/objfw-defs.h
src/runtime/Info.plist
src/runtime/libobjfwrt.*

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/terminal/terminal_tests
tests/testfile_bin.m
tests/testfile_ini.m
tests/tests
tests/tests.3dsx
tests/tests.arm9
tests/tests.nds
tests/tests.nro
tests/tests.rpx
utils/objfw-config
utils/objfw-new/objfw-new
utils/ofarc/ofarc
utils/ofdns/ofdns
utils/ofhash/ofhash
utils/ofhttp/ofhttp







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






>

>





<

<
<












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
config.log
config.status
configure
docs
extra.mk
generators/library/gen_libraries
generators/unicode/gen_tables
new_tests/EBOOT.PBP
new_tests/PARAM.SFO
new_tests/plugin/Info.plist
new_tests/subprocess/subprocess
new_tests/testfile_bin.m
new_tests/testfile_ini.m
new_tests/tests
new_tests/tests.3dsx
new_tests/tests.arm9
new_tests/tests.nds
new_tests/tests.nro
new_tests/tests.rpx
src/Info.plist
src/bridge/Info.plist
src/libobjfw.*
src/objfw-defs.h
src/runtime/Info.plist
src/runtime/libobjfwrt.*
src/test/libobjfwtest.a
src/tls/Info.plist
src/tls/libobjfwtls.*
tests/DerivedData
tests/EBOOT.PBP
tests/Info.plist
tests/PARAM.SFO
tests/objc_sync/objc_sync

tests/terminal/terminal_tests


tests/tests
tests/tests.3dsx
tests/tests.arm9
tests/tests.nds
tests/tests.nro
tests/tests.rpx
utils/objfw-config
utils/objfw-new/objfw-new
utils/ofarc/ofarc
utils/ofdns/ofdns
utils/ofhash/ofhash
utils/ofhttp/ofhttp

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

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
config.log
config.status
configure
docs
extra.mk
generators/library/gen_libraries
generators/unicode/gen_tables












src/Info.plist
src/bridge/Info.plist
src/libobjfw.*
src/objfw-defs.h
src/runtime/Info.plist
src/runtime/libobjfwrt.*

src/tls/Info.plist

tests/DerivedData
tests/EBOOT.PBP
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/terminal/terminal_tests
tests/testfile_bin.m
tests/testfile_ini.m
tests/tests
tests/tests.3dsx
tests/tests.arm9
tests/tests.nds
tests/tests.nro
tests/tests.rpx
utils/objfw-config
utils/objfw-new/objfw-new
utils/ofarc/ofarc
utils/ofdns/ofdns
utils/ofhash/ofhash
utils/ofhttp/ofhttp







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






>

>








<

<
<












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
config.log
config.status
configure
docs
extra.mk
generators/library/gen_libraries
generators/unicode/gen_tables
new_tests/EBOOT.PBP
new_tests/PARAM.SFO
new_tests/plugin/Info.plist
new_tests/subprocess/subprocess
new_tests/testfile_bin.m
new_tests/testfile_ini.m
new_tests/tests
new_tests/tests.3dsx
new_tests/tests.arm9
new_tests/tests.nds
new_tests/tests.nro
new_tests/tests.rpx
src/Info.plist
src/bridge/Info.plist
src/libobjfw.*
src/objfw-defs.h
src/runtime/Info.plist
src/runtime/libobjfwrt.*
src/test/libobjfwtest.a
src/tls/Info.plist
src/tls/libobjfwtls.*
tests/DerivedData
tests/EBOOT.PBP
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/terminal/terminal_tests


tests/tests
tests/tests.3dsx
tests/tests.arm9
tests/tests.nds
tests/tests.nro
tests/tests.rpx
utils/objfw-config
utils/objfw-new/objfw-new
utils/ofarc/ofarc
utils/ofdns/ofdns
utils/ofhash/ofhash
utils/ofhttp/ofhttp

Added .github/workflows/dragonflybsd.yml version [6c0eaab5cb].



















































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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: ubuntu-latest
    strategy:
      matrix:
        configure_flags:
          -
          - --disable-shared
          - --with-tls=gnutls
    steps:
    - uses: actions/checkout@v4
    - uses: vmactions/dragonflybsd-vm@v1
      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 [4657fe9002].



















































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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: ubuntu-latest
    strategy:
      matrix:
        configure_flags:
          -
          - --disable-shared
          - --with-tls=gnutls
    steps:
    - uses: actions/checkout@v4
    - uses: vmactions/freebsd-vm@v1
      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 [9108c5901d].



















































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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: ubuntu-latest
    strategy:
      matrix:
        configure_flags:
          -
          - --disable-shared
          - --with-tls=gnutls
    steps:
    - uses: actions/checkout@v4
    - uses: vmactions/netbsd-vm@v1
      with:
        usesh: true
        copyback: false
        prepare: |
          /usr/sbin/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 [5d6e9c60e9].



















































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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: ubuntu-latest
    strategy:
      matrix:
        configure_flags:
          -
          - --disable-shared
          - --with-tls=gnutls
    steps:
    - uses: actions/checkout@v4
    - uses: vmactions/netbsd-vm@v1
      with:
        usesh: true
        copyback: false
        prepare: |
          /usr/sbin/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 [a810b5a14b].



















































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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: ubuntu-latest
    strategy:
      matrix:
        configure_flags:
          -
          - --disable-shared
          - --with-tls=gnutls
    steps:
    - uses: actions/checkout@v4
    - uses: vmactions/openbsd-vm@v1
      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 .github/workflows/ubuntu-latest-gcc.yml from [b7ca4731c5] to [aebb3c6867].

17
18
19
20
21
22
23


24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
          - --disable-sockets --disable-files
          - --disable-files
          - --disable-shared
          - --disable-shared --enable-seluid24
          - --disable-compiler-tls --disable-threads
          - --with-tls=gnutls
          - --with-tls=gnutls --disable-shared


    steps:
    - name: Install dependencies
      run: |
        sudo apt-get update
        sudo apt-get install gobjc libssl-dev gnutls-dev
    - uses: actions/checkout@v4
    - name: autogen.sh
      run: ./autogen.sh
    - name: configure
      run: ./configure OBJC="gcc" ${{ matrix.configure_flags }}
    - name: make
      run: make -j$(nproc)
    - name: make check
      run: make check
    - name: make install
      run: sudo make install







>
>




|











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
          - --disable-sockets --disable-files
          - --disable-files
          - --disable-shared
          - --disable-shared --enable-seluid24
          - --disable-compiler-tls --disable-threads
          - --with-tls=gnutls
          - --with-tls=gnutls --disable-shared
          - --with-tls=mbedtls
          - --with-tls=mbedtls --disable-shared
    steps:
    - name: Install dependencies
      run: |
        sudo apt-get update
        sudo apt-get install gobjc libssl-dev gnutls-dev libmbedtls-dev
    - uses: actions/checkout@v4
    - name: autogen.sh
      run: ./autogen.sh
    - name: configure
      run: ./configure OBJC="gcc" ${{ matrix.configure_flags }}
    - name: make
      run: make -j$(nproc)
    - name: make check
      run: make check
    - name: make install
      run: sudo make install

Modified .github/workflows/ubuntu-latest.yml from [316b987874] to [c0481fd267].

17
18
19
20
21
22
23


24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
          - --disable-sockets --disable-files
          - --disable-files
          - --disable-shared
          - --disable-shared --enable-seluid24
          - --disable-compiler-tls --disable-threads
          - --with-tls=gnutls
          - --with-tls=gnutls --disable-shared


    steps:
    - name: Install dependencies
      run: |
        sudo apt-get update
        sudo apt-get install libssl-dev gnutls-dev
    - uses: actions/checkout@v4
    - name: autogen.sh
      run: ./autogen.sh
    - name: configure
      run: ./configure ${{ matrix.configure_flags }}
    - name: make
      run: make -j$(nproc)
    - name: make check
      run: make check
    - name: make install
      run: sudo make install







>
>




|











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
          - --disable-sockets --disable-files
          - --disable-files
          - --disable-shared
          - --disable-shared --enable-seluid24
          - --disable-compiler-tls --disable-threads
          - --with-tls=gnutls
          - --with-tls=gnutls --disable-shared
          - --with-tls=mbedtls
          - --with-tls=mbedtls --disable-shared
    steps:
    - name: Install dependencies
      run: |
        sudo apt-get update
        sudo apt-get install libssl-dev gnutls-dev libmbedtls-dev
    - uses: actions/checkout@v4
    - name: autogen.sh
      run: ./autogen.sh
    - name: configure
      run: ./configure ${{ matrix.configure_flags }}
    - name: make
      run: make -j$(nproc)
    - name: make check
      run: make check
    - name: make install
      run: sudo make install

Modified .gitignore from [9fa51c850c] to [fdf5c85348].

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
config.log
config.status
configure
docs
extra.mk
generators/library/gen_libraries
generators/unicode/gen_tables












src/Info.plist
src/bridge/Info.plist
src/libobjfw.*
src/objfw-defs.h
src/runtime/Info.plist
src/runtime/libobjfwrt.*

src/tls/Info.plist

tests/DerivedData
tests/EBOOT.PBP
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/terminal/terminal_tests
tests/testfile_bin.m
tests/testfile_ini.m
tests/tests
tests/tests.3dsx
tests/tests.arm9
tests/tests.nds
tests/tests.nro
tests/tests.rpx
utils/objfw-config
utils/objfw-new/objfw-new
utils/ofarc/ofarc
utils/ofdns/ofdns
utils/ofhash/ofhash
utils/ofhttp/ofhttp







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






>

>








<

<
<












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
config.log
config.status
configure
docs
extra.mk
generators/library/gen_libraries
generators/unicode/gen_tables
new_tests/EBOOT.PBP
new_tests/PARAM.SFO
new_tests/plugin/Info.plist
new_tests/subprocess/subprocess
new_tests/testfile_bin.m
new_tests/testfile_ini.m
new_tests/tests
new_tests/tests.3dsx
new_tests/tests.arm9
new_tests/tests.nds
new_tests/tests.nro
new_tests/tests.rpx
src/Info.plist
src/bridge/Info.plist
src/libobjfw.*
src/objfw-defs.h
src/runtime/Info.plist
src/runtime/libobjfwrt.*
src/test/libobjfwtest.a
src/tls/Info.plist
src/tls/libobjfwtls.*
tests/DerivedData
tests/EBOOT.PBP
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/terminal/terminal_tests


tests/tests
tests/tests.3dsx
tests/tests.arm9
tests/tests.nds
tests/tests.nro
tests/tests.rpx
utils/objfw-config
utils/objfw-new/objfw-new
utils/ofarc/ofarc
utils/ofdns/ofdns
utils/ofhash/ofhash
utils/ofhttp/ofhttp

Modified ChangeLog from [0196990ba7] to [400b1b6d53].

1
2
3
4
5
6

















7
8
9
10
11
12
13
Legend:
 * Changes of existing features or bugfixes
 + New features

This file only contains the most significant changes.


















ObjFW 1.0.4 -> ObjFW 1.0.5, 2023-11-05
 * Fixes the calculation of the extra alignment in OFAllocObject()
 * Fixes +[OFSystemInfo networkInterfaces] on OpenBSD and Windows 98
 * Fixes OFSocketAddressString() for AppleTalk addresses
 * Uses GetModuleHandle() instead of LoadLibrary() where possible on Windows
 * Disables tests for global blocks on Win64 due to broken compilers
 * Adds PGP keys to verify tarballs and commits in the code repository






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







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
Legend:
 * Changes of existing features or bugfixes
 + New features

This file only contains the most significant changes.

ObjFW 1.0.7 -> ObjFW 1.0.8, 2024-01-21
 * Fixes compilation on NetBSD, OpenBSD, OpenIndiana etc. which was broken by
   1.0.7.

ObjFW 1.0.6 -> ObjFW 1.0.7, 2024-01-21
 * Fixes inheriting the environment in OFSubprocess.
 * Fixes dealloc in OFSubprocess when -[closeForWriting] was called.
 + Adds tests for OFSubprocess.
 * Changes the key for +[OFSystemInfo networkInterfaces] to the adapter name
   on Windows XP and newer to avoid a possible collission on the adapter index.
 * Fixes compilation with old MinGW versions.
 * Fixes the documentation for OFSRVDNSResourceRecord.

ObjFW 1.0.5 -> ObjFW 1.0.6, 2024-01-15
 * Fixes compatibility with autoconf 2.72.
 * Fixes OFDNSResolver's handling of types, classes and lengths > 255.

ObjFW 1.0.4 -> ObjFW 1.0.5, 2023-11-05
 * Fixes the calculation of the extra alignment in OFAllocObject()
 * Fixes +[OFSystemInfo networkInterfaces] on OpenBSD and Windows 98
 * Fixes OFSocketAddressString() for AppleTalk addresses
 * Uses GetModuleHandle() instead of LoadLibrary() where possible on Windows
 * Disables tests for global blocks on Win64 due to broken compilers
 * Adds PGP keys to verify tarballs and commits in the code repository

Modified Makefile from [a04c0a2490] to [3b78119a83].

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
include extra.mk

SUBDIRS = src utils tests
DISTCLEAN = Info.plist		\
	    aclocal.m4		\
	    autom4te.cache	\
	    buildsys.mk		\
	    config.h		\
	    config.log		\
	    config.status	\
	    extra.mk

include buildsys.mk

.PHONY: check docs release

utils tests: src

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


docs:
	rm -fr docs
	doxygen >/dev/null

release: docs
	echo "Generating tarball for version ${PACKAGE_VERSION}..."


|













|

|

>







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
include extra.mk

SUBDIRS = src utils tests new_tests
DISTCLEAN = Info.plist		\
	    aclocal.m4		\
	    autom4te.cache	\
	    buildsys.mk		\
	    config.h		\
	    config.log		\
	    config.status	\
	    extra.mk

include buildsys.mk

.PHONY: check docs release

utils tests new_tests: src

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

docs:
	rm -fr docs
	doxygen >/dev/null

release: docs
	echo "Generating tarball for version ${PACKAGE_VERSION}..."

Modified configure.ac from [17ac08d8ed] to [724633f612].

437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
])

AC_DEFINE_UNQUOTED(PLUGIN_SUFFIX, "$PLUGIN_SUFFIX", [Suffix for plugins])
AS_IF([test x"$enable_files" != x"no" -a x"$PLUGIN_SUFFIX" != x""], [
	AC_SUBST(USE_SRCS_PLUGINS, '${SRCS_PLUGINS}')
	AC_SUBST(TESTPLUGIN, "plugin")
	AC_DEFINE(OF_HAVE_PLUGINS, 1, [Whether we have plugin support])
	AC_CONFIG_FILES(tests/plugin/Info.plist)

	AS_IF([test x"$build_framework" = x"yes"], [
		TESTPLUGIN_LIBS="-F../../src -F../../src/runtime"
		TESTPLUGIN_LIBS="$TESTPLUGIN_LIBS -framework ObjFW"
		TESTPLUGIN_LIBS="$TESTPLUGIN_LIBS \${RUNTIME_FRAMEWORK_LIBS}"
	], [
		TESTPLUGIN_LIBS="-L../../src -L../../src/runtime"







|







437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
])

AC_DEFINE_UNQUOTED(PLUGIN_SUFFIX, "$PLUGIN_SUFFIX", [Suffix for plugins])
AS_IF([test x"$enable_files" != x"no" -a x"$PLUGIN_SUFFIX" != x""], [
	AC_SUBST(USE_SRCS_PLUGINS, '${SRCS_PLUGINS}')
	AC_SUBST(TESTPLUGIN, "plugin")
	AC_DEFINE(OF_HAVE_PLUGINS, 1, [Whether we have plugin support])
	AC_CONFIG_FILES(new_tests/plugin/Info.plist)

	AS_IF([test x"$build_framework" = x"yes"], [
		TESTPLUGIN_LIBS="-F../../src -F../../src/runtime"
		TESTPLUGIN_LIBS="$TESTPLUGIN_LIBS -framework ObjFW"
		TESTPLUGIN_LIBS="$TESTPLUGIN_LIBS \${RUNTIME_FRAMEWORK_LIBS}"
	], [
		TESTPLUGIN_LIBS="-L../../src -L../../src/runtime"
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
			dnl Disable default action-if-not-found, which exits
			dnl configure with an error.
			:
		])
	])

	AS_IF([test x"$with_tls" = x"mbedtls"], [
		AC_ARG_WITH(mbedtls-ca-path,
			AS_HELP_STRING([path to CA file for Mbed TLS]))

		AS_IF([test x"$with_mbedtls_ca_path" = x""], [
			AC_MSG_ERROR([--mbedtls-ca-path needs to be specified!])
		])
		AC_DEFINE_UNQUOTED(OF_MBEDTLS_CA_PATH, "$with_mbedtls_ca_path",
			[Path to CA file for Mbed TLS])

		AC_CHECK_LIB(mbedtls, mbedtls_net_init, [
			AC_CHECK_HEADER(mbedtls/ssl.h, [
				tls_support="Mbed TLS"
				TLS_LIBS="-lmbedx509 -lmbedcrypto $TLS_LIBS"
				TLS_LIBS="-lmbedtls $TLS_LIBS"

				AC_SUBST(OF_MBEDTLS_TLS_STREAM_M,







<
<
<
<
<
<
<
<
<







1851
1852
1853
1854
1855
1856
1857









1858
1859
1860
1861
1862
1863
1864
			dnl Disable default action-if-not-found, which exits
			dnl configure with an error.
			:
		])
	])

	AS_IF([test x"$with_tls" = x"mbedtls"], [









		AC_CHECK_LIB(mbedtls, mbedtls_net_init, [
			AC_CHECK_HEADER(mbedtls/ssl.h, [
				tls_support="Mbed TLS"
				TLS_LIBS="-lmbedx509 -lmbedcrypto $TLS_LIBS"
				TLS_LIBS="-lmbedtls $TLS_LIBS"

				AC_SUBST(OF_MBEDTLS_TLS_STREAM_M,
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
			AC_SUBST(OBJFWTLS_FRAMEWORK, "ObjFWTLS.framework")
		])
	])

	AS_IF([test x"$with_tls" != x"no" -a x"$tls_support" = x"no"], [
		AC_MSG_ERROR(m4_normalize([
			No TLS implementation was found. Please install OpenSSL,
			GnuTLS or use --without-tls.
		]))
	])

	AS_IF([test x"$enable_threads" != x"no"], [
		AC_SUBST(OF_HTTP_CLIENT_TESTS_M, "OFHTTPClientTests.m")
	])








|







1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
			AC_SUBST(OBJFWTLS_FRAMEWORK, "ObjFWTLS.framework")
		])
	])

	AS_IF([test x"$with_tls" != x"no" -a x"$tls_support" = x"no"], [
		AC_MSG_ERROR(m4_normalize([
			No TLS implementation was found. Please install OpenSSL,
			GnuTLS, Mbed TLS or use --without-tls.
		]))
	])

	AS_IF([test x"$enable_threads" != x"no"], [
		AC_SUBST(OF_HTTP_CLIENT_TESTS_M, "OFHTTPClientTests.m")
	])

1986
1987
1988
1989
1990
1991
1992

1993
1994
1995
1996
1997
1998
1999
2000
			])
		], [
			break
		])
	])
])
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(ioctl isatty)

AC_CHECK_FUNC(pledge, [







>
|







1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
			])
		], [
			break
		])
	])
])
AS_IF([test x"$have_subprocesses" = x"yes"], [
	AC_SUBST(USE_SRCS_SUBPROCESSES, '${SRCS_SUBPROCESSES}')
	AC_SUBST(SUBPROCESS, "subprocess")
	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(ioctl isatty)

AC_CHECK_FUNC(pledge, [

Modified extra.mk.in from [b53f574989] to [5cc5b370f7].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
OBJFW_SHARED_LIB = @OBJFW_SHARED_LIB@
OBJFW_STATIC_LIB = @OBJFW_STATIC_LIB@
OBJFW_FRAMEWORK = @OBJFW_FRAMEWORK@
OBJFW_LIB_MAJOR = 1
OBJFW_LIB_MINOR = 1
OBJFW_LIB_PATCH = 0
OBJFW_LIB_MAJOR_MINOR = ${OBJFW_LIB_MAJOR}.${OBJFW_LIB_MINOR}

OBJFWRT_SHARED_LIB = @OBJFWRT_SHARED_LIB@
OBJFWRT_STATIC_LIB = @OBJFWRT_STATIC_LIB@
OBJFWRT_FRAMEWORK = @OBJFWRT_FRAMEWORK@
OBJFWRT_LIB_MAJOR = 1
OBJFWRT_LIB_MINOR = 0
OBJFWRT_LIB_PATCH = 0
OBJFWRT_LIB_MAJOR_MINOR = ${OBJFWRT_LIB_MAJOR}.${OBJFWRT_LIB_MINOR}

OBJFWBRIDGE_SHARED_LIB = @OBJFWBRIDGE_SHARED_LIB@
OBJFWBRIDGE_STATIC_LIB = @OBJFWBRIDGE_STATIC_LIB@
OBJFWBRIDGE_FRAMEWORK = @OBJFWBRIDGE_FRAMEWORK@
OBJFWBRIDGE_LIB_MAJOR = 1












|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
OBJFW_SHARED_LIB = @OBJFW_SHARED_LIB@
OBJFW_STATIC_LIB = @OBJFW_STATIC_LIB@
OBJFW_FRAMEWORK = @OBJFW_FRAMEWORK@
OBJFW_LIB_MAJOR = 1
OBJFW_LIB_MINOR = 1
OBJFW_LIB_PATCH = 0
OBJFW_LIB_MAJOR_MINOR = ${OBJFW_LIB_MAJOR}.${OBJFW_LIB_MINOR}

OBJFWRT_SHARED_LIB = @OBJFWRT_SHARED_LIB@
OBJFWRT_STATIC_LIB = @OBJFWRT_STATIC_LIB@
OBJFWRT_FRAMEWORK = @OBJFWRT_FRAMEWORK@
OBJFWRT_LIB_MAJOR = 1
OBJFWRT_LIB_MINOR = 1
OBJFWRT_LIB_PATCH = 0
OBJFWRT_LIB_MAJOR_MINOR = ${OBJFWRT_LIB_MAJOR}.${OBJFWRT_LIB_MINOR}

OBJFWBRIDGE_SHARED_LIB = @OBJFWBRIDGE_SHARED_LIB@
OBJFWBRIDGE_STATIC_LIB = @OBJFWBRIDGE_STATIC_LIB@
OBJFWBRIDGE_FRAMEWORK = @OBJFWBRIDGE_FRAMEWORK@
OBJFWBRIDGE_LIB_MAJOR = 1
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
OF_HTTP_CLIENT_TESTS_M = @OF_HTTP_CLIENT_TESTS_M@
OF_KQUEUE_KERNEL_EVENT_OBSERVER_M = @OF_KQUEUE_KERNEL_EVENT_OBSERVER_M@
OF_MBEDTLS_TLS_STREAM_M = @OF_MBEDTLS_TLS_STREAM_M@
OF_OPENSSL_TLS_STREAM_M = @OF_OPENSSL_TLS_STREAM_M@
OF_POLL_KERNEL_EVENT_OBSERVER_M = @OF_POLL_KERNEL_EVENT_OBSERVER_M@
OF_SECURE_TRANSPORT_TLS_STREAM_M = @OF_SECURE_TRANSPORT_TLS_STREAM_M@
OF_SELECT_KERNEL_EVENT_OBSERVER_M = @OF_SELECT_KERNEL_EVENT_OBSERVER_M@
OF_SUBPROCESS_M = @OF_SUBPROCESS_M@
REEXPORT_RUNTIME = @REEXPORT_RUNTIME@
REEXPORT_RUNTIME_FRAMEWORK = @REEXPORT_RUNTIME_FRAMEWORK@
RUNTIME = @RUNTIME@
RUNTIME_ARC_TESTS_M = @RUNTIME_ARC_TESTS_M@
RUNTIME_AUTORELEASE_M = @RUNTIME_AUTORELEASE_M@
RUNTIME_FRAMEWORK_LIBS = @RUNTIME_FRAMEWORK_LIBS@
RUNTIME_INSTANCE_M = @RUNTIME_INSTANCE_M@
RUNTIME_LIBS = @RUNTIME_LIBS@
SFDC_INLINE_H = @SFDC_INLINE_H@
SFDC_TARGET = @SFDC_TARGET@
SFD_FILE = @SFD_FILE@
TESTPLUGIN = @TESTPLUGIN@
TESTPLUGIN_LIBS = @TESTPLUGIN_LIBS@
TESTS_LIBS = @TESTS_LIBS@
TESTS_STATIC_LIB = @TESTS_STATIC_LIB@
TLS = @TLS@
TLS_CPPFLAGS = @TLS_CPPFLAGS@
TLS_LIBS = @TLS_LIBS@
UNICODE_M = @UNICODE_M@
USE_INCLUDES_ATOMIC = @USE_INCLUDES_ATOMIC@
USE_SRCS_APPLETALK = @USE_SRCS_APPLETALK@
USE_SRCS_FILES = @USE_SRCS_FILES@
USE_SRCS_IPX = @USE_SRCS_IPX@
USE_SRCS_PLUGINS = @USE_SRCS_PLUGINS@
USE_SRCS_SOCKETS = @USE_SRCS_SOCKETS@

USE_SRCS_TAGGED_POINTERS = @USE_SRCS_TAGGED_POINTERS@
USE_SRCS_THREADS = @USE_SRCS_THREADS@
USE_SRCS_UNIX_SOCKETS = @USE_SRCS_UNIX_SOCKETS@
USE_SRCS_WINDOWS = @USE_SRCS_WINDOWS@
WRAPPER = @WRAPPER@







<








<
<
|














>





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
OF_HTTP_CLIENT_TESTS_M = @OF_HTTP_CLIENT_TESTS_M@
OF_KQUEUE_KERNEL_EVENT_OBSERVER_M = @OF_KQUEUE_KERNEL_EVENT_OBSERVER_M@
OF_MBEDTLS_TLS_STREAM_M = @OF_MBEDTLS_TLS_STREAM_M@
OF_OPENSSL_TLS_STREAM_M = @OF_OPENSSL_TLS_STREAM_M@
OF_POLL_KERNEL_EVENT_OBSERVER_M = @OF_POLL_KERNEL_EVENT_OBSERVER_M@
OF_SECURE_TRANSPORT_TLS_STREAM_M = @OF_SECURE_TRANSPORT_TLS_STREAM_M@
OF_SELECT_KERNEL_EVENT_OBSERVER_M = @OF_SELECT_KERNEL_EVENT_OBSERVER_M@

REEXPORT_RUNTIME = @REEXPORT_RUNTIME@
REEXPORT_RUNTIME_FRAMEWORK = @REEXPORT_RUNTIME_FRAMEWORK@
RUNTIME = @RUNTIME@
RUNTIME_ARC_TESTS_M = @RUNTIME_ARC_TESTS_M@
RUNTIME_AUTORELEASE_M = @RUNTIME_AUTORELEASE_M@
RUNTIME_FRAMEWORK_LIBS = @RUNTIME_FRAMEWORK_LIBS@
RUNTIME_INSTANCE_M = @RUNTIME_INSTANCE_M@
RUNTIME_LIBS = @RUNTIME_LIBS@


SUBPROCESS = @SUBPROCESS@
TESTPLUGIN = @TESTPLUGIN@
TESTPLUGIN_LIBS = @TESTPLUGIN_LIBS@
TESTS_LIBS = @TESTS_LIBS@
TESTS_STATIC_LIB = @TESTS_STATIC_LIB@
TLS = @TLS@
TLS_CPPFLAGS = @TLS_CPPFLAGS@
TLS_LIBS = @TLS_LIBS@
UNICODE_M = @UNICODE_M@
USE_INCLUDES_ATOMIC = @USE_INCLUDES_ATOMIC@
USE_SRCS_APPLETALK = @USE_SRCS_APPLETALK@
USE_SRCS_FILES = @USE_SRCS_FILES@
USE_SRCS_IPX = @USE_SRCS_IPX@
USE_SRCS_PLUGINS = @USE_SRCS_PLUGINS@
USE_SRCS_SOCKETS = @USE_SRCS_SOCKETS@
USE_SRCS_SUBPROCESSES = @USE_SRCS_SUBPROCESSES@
USE_SRCS_TAGGED_POINTERS = @USE_SRCS_TAGGED_POINTERS@
USE_SRCS_THREADS = @USE_SRCS_THREADS@
USE_SRCS_UNIX_SOCKETS = @USE_SRCS_UNIX_SOCKETS@
USE_SRCS_WINDOWS = @USE_SRCS_WINDOWS@
WRAPPER = @WRAPPER@

Added new_tests/Makefile version [48e7adec2e].













































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
include ../extra.mk

SUBDIRS = ${TESTPLUGIN} ${SUBPROCESS}

CLEAN = EBOOT.PBP		\
	boot.dol		\
	${PROG_NOINST}.arm9	\
	${PROG_NOINST}.nds	\
	${PROG_NOINST}.nro	\
	${PROG_NOINST}.rpx	\
	testfile_bin.m		\
	testfile_ini.m

PROG_NOINST = tests${PROG_SUFFIX}
SRCS = OFArrayTests.m			\
       OFCharacterSetTests.m		\
       OFColorTests.m			\
       OFConcreteArrayTests.m		\
       OFConcreteMutableArrayTests.m	\
       OFCryptographicHashTests.m	\
       OFDateTests.m			\
       OFHMACTests.m			\
       OFINIFileTests.m			\
       OFIRITests.m			\
       OFInvocationTests.m		\
       OFJSONTests.m			\
       OFMatrix4x4Tests.m		\
       OFMethodSignatureTests.m		\
       OFMutableArrayTests.m		\
       OFNumberTests.m			\
       OFPBKDF2Tests.m			\
       OFPropertyListTests.m		\
       OFScryptTests.m			\
       ${USE_SRCS_PLUGINS}		\
       ${USE_SRCS_SOCKETS}		\
       ${USE_SRCS_SUBPROCESSES}		\
       ${USE_SRCS_THREADS}		\
       testfile_bin.m			\
       testfile_ini.m
SRCS_PLUGINS = OFPluginTests.m
SRCS_SOCKETS = OFSocketTests.m
SRCS_SUBPROCESSES = OFSubprocessTests.m
SRCS_THREADS = OFThreadTests.m

include ../buildsys.mk

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:
	rm -f libobjfw.so.${OBJFW_LIB_MAJOR}
	rm -f libobjfw.so.${OBJFW_LIB_MAJOR_MINOR}
	rm -f objfw${OBJFW_LIB_MAJOR}.dll libobjfw.${OBJFW_LIB_MAJOR}.dylib
	rm -f libobjfwrt.so.${OBJFWRT_LIB_MAJOR}
	rm -f libobjfwrt.so.${OBJFWRT_LIB_MAJOR_MINOR}
	rm -f objfwrt${OBJFWRT_LIB_MAJOR}.dll
	rm -f libobjfwrt.${OBJFWRT_LIB_MAJOR}.dylib
	if test -f ../src/libobjfw.so; then \
		${LN_S} ../src/libobjfw.so libobjfw.so.${OBJFW_LIB_MAJOR}; \
		${LN_S} ../src/libobjfw.so \
		    libobjfw.so.${OBJFW_LIB_MAJOR_MINOR}; \
	elif test -f ../src/libobjfw.so.${OBJFW_LIB_MAJOR_MINOR}; then \
		${LN_S} ../src/libobjfw.so.${OBJFW_LIB_MAJOR_MINOR} \
		    libobjfw.so.${OBJFW_LIB_MAJOR_MINOR}; \
	fi
	if test -f ../src/objfw${OBJFW_LIB_MAJOR}.dll; then \
		${LN_S} ../src/objfw${OBJFW_LIB_MAJOR}.dll \
			objfw${OBJFW_LIB_MAJOR}.dll; \
	fi
	if test -f ../src/libobjfw.dylib; then \
		${LN_S} ../src/libobjfw.dylib \
		    libobjfw.${OBJFW_LIB_MAJOR}.dylib; \
	fi
	if test -f ../src/runtime/libobjfwrt.so; then \
		${LN_S} ../src/runtime/libobjfwrt.so \
		    libobjfwrt.so.${OBJFWRT_LIB_MAJOR}; \
		${LN_S} ../src/runtime/libobjfwrt.so \
		    libobjfwrt.so.${OBJFWRT_LIB_MAJOR_MINOR}; \
	elif test -f ../src/runtime/libobjfwrt.so.${OBJFWRT_LIB_MAJOR_MINOR}; then \
		${LN_S} ../src/runtime/libobjfwrt.so.${OBJFWRT_LIB_MAJOR_MINOR} libobjfwrt.so.${OBJFWRT_LIB_MAJOR_MINOR}; \
	fi
	if test -f ../src/runtime/objfwrt${OBJFWRT_LIB_MAJOR}.dll; then \
		${LN_S} ../src/runtime/objfwrt${OBJFWRT_LIB_MAJOR}.dll \
			objfwrt${OBJFWRT_LIB_MAJOR}.dll; \
	fi
	if test -f ../src/runtime/libobjfwrt.dylib; then \
		${LN_S} ../src/runtime/libobjfwrt.dylib \
		    libobjfwrt.${OBJFWRT_LIB_MAJOR}.dylib; \
	fi
	LD_LIBRARY_PATH=.$${LD_LIBRARY_PATH+:}$$LD_LIBRARY_PATH \
	DYLD_FRAMEWORK_PATH=../src:../src/runtime$${DYLD_FRAMEWORK_PATH+:}$$DYLD_FRAMEWORK_PATH \
	DYLD_LIBRARY_PATH=.$${DYLD_LIBRARY_PATH+:}$$DYLD_LIBRARY_PATH \
	LIBRARY_PATH=.$${LIBRARY_PATH+:}$$LIBRARY_PATH \
	ASAN_OPTIONS=allocator_may_return_null=1 \
	${WRAPPER} ./${PROG_NOINST}; EXIT=$$?; \
	rm -f libobjfw.so.${OBJFW_LIB_MAJOR}; \
	rm -f libobjfw.so.${OBJFW_LIB_MAJOR_MINOR}; \
	rm -f objfw${OBJFW_LIB_MAJOR}.dll; \
	rm -f libobjfw.${OBJFW_LIB_MAJOR}.dylib; \
	rm -f libobjfwrt.so.${OBJFWRT_LIB_MAJOR}; \
	rm -f libobjfwrt.so.${OBJFWRT_LIB_MAJOR_MINOR}; \
	rm -f objfwrt${OBJFWRT_LIB_MAJOR}.dll; \
	rm -f libobjfwrt.${OBJFWRT_LIB_MAJOR}.dylib; \
	exit $$EXIT

run-on-android: all
	echo "Uploading files to Android device..."
	if test -f ../src/libobjfw.so; then \
		adb push ../src/libobjfw.so \
		    /data/local/tmp/objfw/libobjfw.so.${OBJFW_LIB_MAJOR}; \
	fi
	if test -f ../src/runtime/libobjfwrt.so; then \
		adb push ../src/runtime/libobjfwrt.so \
		    /data/local/tmp/objfw/libobjfwrt.so.${OBJFWRT_LIB_MAJOR}; \
	fi
	adb push tests /data/local/tmp/objfw/tests
	adb push testfile.txt /data/local/tmp/objfw/testfile.txt
	if test -f plugin/TestPlugin.so; then \
		adb push plugin/TestPlugin.so \
		    /data/local/tmp/objfw/plugin/TestPlugin.so; \
	fi
	echo "Running tests binary on Android device..."
	adb shell 'cd /data/local/tmp/objfw && LD_LIBRARY_PATH=. exec ${WRAPPER} ./tests'

EBOOT.PBP: ${PROG_NOINST}
	psp-fixup-imports ${PROG_NOINST}
	mksfo "ObjFW Tests" PARAM.SFO
	psp-strip ${PROG_NOINST}
	pack-pbp $@ PARAM.SFO NULL NULL NULL NULL NULL ${PROG_NOINST} NULL

boot.dol: ${PROG_NOINST}
	elf2dol ${PROG_NOINST} $@

${PROG_NOINST}: ${LIBOBJFW_DEP} ${LIBOBJFWRT_DEP} ../src/test/libobjfwtest.a

${PROG_NOINST}.3dsx: ${PROG_NOINST}
	3dsxtool $< $@

${PROG_NOINST}.arm9: ${PROG_NOINST}
	arm-none-eabi-objcopy -O binary $< $@

${PROG_NOINST}.nds: ${PROG_NOINST}.arm9 testfile.txt
	rm -fr nds-data
	mkdir -p nds-data
	cp testfile.txt nds-data
	ndstool -c $@ -9 ${PROG_NOINST} -d nds-data
	rm -fr nds-data

${PROG_NOINST}.nro: ${PROG_NOINST} testfile.txt
	rm -fr romfs
	mkdir -p romfs
	cp testfile.txt romfs
	nacptool --create "ObjFW tests" "Jonathan Schleifer" \
		"${PACKAGE_VERSION}" tests.nacp
	elf2nro ${PROG_NOINST} $@ --nacp=tests.nacp --romfsdir=romfs
	rm -fr romfs tests.nacp

${PROG_NOINST}.rpx: ${PROG_NOINST}
	elf2rpl $< $@

CPPFLAGS += -I../src				\
	    -I../src/exceptions			\
	    -I../src/runtime			\
	    -I../src/test			\
	    -I..				\
	    -DOBJFWTEST_LOCAL_INCLUDES		\
	    -DPROG_SUFFIX=\"${PROG_SUFFIX}\"
# Repetition is required for Wii U, as otherwise it cannot find main. Just
# moving -lobjfwtest later doesn't work either, as then the linker cannot find
# ObjFW symbols. So the only solution is to list everything twice.
LIBS := -L../src/test	\
	-lobjfwtest	\
	${TESTS_LIBS}	\
	${LIBS}		\
	-lobjfwtest	\
	${TESTS_LIBS}	\
	${LIBS}
LDFLAGS += ${MAP_LDFLAGS}
LD = ${OBJC}

Added new_tests/OFArrayTests.h version [418a1a5a2c].



















































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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-2024 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the 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.h"
#import "ObjFWTest.h"

@interface OFArrayTests: OTTestCase
{
	OFArray *_array;
}

- (Class)arrayClass;
@end

Renamed and modified tests/OFArrayTests.m [1024ac5260] to new_tests/OFArrayTests.m [82ed4031a9].

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
 * 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 *module;
static OFString *const cArray[] = {
	@"Foo",
	@"Bar",
	@"Baz"
};






@interface SimpleArray: OFArray

{

	OFMutableArray *_array;



}
@end














































































































@interface SimpleMutableArray: OFMutableArray

{










	OFMutableArray *_array;











































































































}
@end

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

	@try {
		_array = [[OFMutableArray alloc] init];
	} @catch (id e) {







|

>
>
>
>
>
|






>
>
>
>
>
|
>

>
|
>
>
>

|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
>

>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>



|







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
 * 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 "OFArrayTests.h"

@interface CustomArray: OFArray
{
	OFMutableArray *_array;
}
@end

static OFString *const cArray[] = {
	@"Foo",
	@"Bar",
	@"Baz"
};

@implementation OFArrayTests
- (Class)arrayClass
{
	return [CustomArray class];
}

- (void)setUp
{
	[super setUp];

	_array = [[self.arrayClass alloc]
	    initWithObjects: cArray
		      count: sizeof(cArray) / sizeof(*cArray)];
}

- (void)dealloc
{
	[_array release];

	[super dealloc];
}

- (void)testArray
{
	OFArray *array = [self.arrayClass array];

	OTAssertNotNil(array);
	OTAssertEqual(array.count, 0);
}

- (void)testArrayWithObjects
{
	OFArray *array = [self.arrayClass arrayWithObjects:
	    @"Foo", @"Bar", @"Baz", nil];

	OTAssertNotNil(array);
	OTAssertEqual(array.count, 3);
	OTAssertEqualObjects([array objectAtIndex: 0], @"Foo");
	OTAssertEqualObjects([array objectAtIndex: 1], @"Bar");
	OTAssertEqualObjects([array objectAtIndex: 2], @"Baz");
}

- (void)testArrayWithObjectsCount
{
	OFArray *array1 = [self.arrayClass arrayWithObjects:
	    @"Foo", @"Bar", @"Baz", nil];
	OFArray *array2 = [self.arrayClass arrayWithObjects: cArray count: 3];

	OTAssertEqualObjects(array1, array2);
}

- (void)testDescription
{
	OTAssertEqualObjects(_array.description,
	    @"(\n\tFoo,\n\tBar,\n\tBaz\n)");
}

- (void)testCount
{
	OTAssertEqual(_array.count, 3);
}

- (void)testIsEqual
{
	OFArray *array = [self.arrayClass arrayWithObjects: cArray count: 3];

	OTAssertEqualObjects(array, _array);
	OTAssertNotEqual(array, _array);
}

- (void)testObjectAtIndex
{
	OTAssertEqualObjects([_array objectAtIndex: 0], cArray[0]);
	OTAssertEqualObjects([_array objectAtIndex: 1], cArray[1]);
	OTAssertEqualObjects([_array objectAtIndex: 2], cArray[2]);
}

- (void)testObjectAtIndexFailsWhenOutOfRange
{
	OTAssertThrowsSpecific([_array objectAtIndex: _array.count],
	    OFOutOfRangeException);
}

- (void)testContainsObject
{
	OTAssertTrue([_array containsObject: cArray[1]]);
	OTAssertFalse([_array containsObject: @"nonexistent"]);
}

- (void)testContainsObjectIdenticalTo
{
	OTAssertTrue([_array containsObjectIdenticalTo: cArray[1]]);
	OTAssertFalse([_array containsObjectIdenticalTo:
	    [OFString stringWithString: cArray[1]]]);
}

- (void)testIndexOfObject
{
	OTAssertEqual([_array indexOfObject: cArray[1]], 1);
	OTAssertEqual([_array indexOfObject: @"nonexistent"], OFNotFound);
}

- (void)testIndexOfObjectIdenticalTo
{
	OTAssertEqual([_array indexOfObjectIdenticalTo: cArray[1]], 1);
	OTAssertEqual([_array indexOfObjectIdenticalTo:
	    [OFString stringWithString: cArray[1]]],
	    OFNotFound);
}

- (void)objectsInRange
{
	OTAssertEqualObjects([_array objectsInRange: OFMakeRange(1, 2)],
	    ([self.arrayClass arrayWithObjects: cArray[1], cArray[2], nil]));
}

- (void)testEnumerator
{
	OFEnumerator *enumerator = [_array objectEnumerator];

	OTAssertEqualObjects([enumerator nextObject], cArray[0]);
	OTAssertEqualObjects([enumerator nextObject], cArray[1]);
	OTAssertEqualObjects([enumerator nextObject], cArray[2]);
	OTAssertNil([enumerator nextObject]);
}

- (void)testFastEnumeration
{
	size_t i = 0;

	for (OFString *object in _array) {
		OTAssert(i < 3);
		OTAssertEqualObjects(object, cArray[i++]);
	}
}

- (void)testComponentsJoinedByString
{
	OFArray *array;

	array = [self.arrayClass arrayWithObjects: @"", @"a", @"b", @"c", nil];
	OTAssertEqualObjects([array componentsJoinedByString: @" "],
	    @" a b c");

	array = [self.arrayClass arrayWithObject: @"foo"];
	OTAssertEqualObjects([array componentsJoinedByString: @" "], @"foo");
}

- (void)testComponentsJoinedByStringOptions
{
	OFArray *array;

	array = [self.arrayClass
	    arrayWithObjects: @"", @"foo", @"", @"", @"bar", @"", nil];
	OTAssertEqualObjects(
	    [array componentsJoinedByString: @" "
				    options: OFArraySkipEmptyComponents],
	    @"foo bar");
}

- (void)testSortedArray
{
	OFArray *array = [_array arrayByAddingObjectsFromArray:
	    [OFArray arrayWithObjects: @"0", @"z", nil]];

	OTAssertEqualObjects([array sortedArray],
	    ([OFArray arrayWithObjects: @"0", @"Bar", @"Baz", @"Foo", @"z",
	    nil]));

	OTAssertEqualObjects(
	    [array sortedArrayUsingSelector: @selector(compare:)
				    options: OFArraySortDescending],
	    ([OFArray arrayWithObjects: @"z", @"Foo", @"Baz", @"Bar", @"0",
	    nil]));
}

- (void)testReversedArray
{
	OTAssertEqualObjects(_array.reversedArray,
	    ([OFArray arrayWithObjects: cArray[2], cArray[1], cArray[0], nil]));
}

#ifdef OF_HAVE_BLOCKS
- (void)testEnumerateObjectsUsingBlock
{
	__block size_t i = 0;

	[_array enumerateObjectsUsingBlock:
	    ^ (id object, size_t idx, bool *stop) {
		OTAssertEqualObjects(object, [_array objectAtIndex: i++]);
	}];

	OTAssertEqual(i, _array.count);
}

- (void)testMappedArrayUsingBlock
{
	OTAssertEqualObjects(
	    [_array mappedArrayUsingBlock: ^ id (id object, size_t idx) {
		switch (idx) {
		case 0:
			return @"foobar";
		case 1:
			return @"qux";
		}

		return @"";
	    }].description,
	    @"(\n\tfoobar,\n\tqux,\n\t\n)");
}

- (void)testFilteredArrayUsingBlock
{
	OTAssertEqualObjects(
	    [_array filteredArrayUsingBlock: ^ bool (id object, size_t idx) {
		return [object isEqual: @"Foo"];
	    }].description,
	    @"(\n\tFoo\n)");

}

- (void)testFoldUsingBlock
{
	OTAssertEqualObjects(
	    [([self.arrayClass arrayWithObjects: [OFMutableString string],
						 @"foo", @"bar", @"baz", nil])
	    foldUsingBlock: ^ id (id left, id right) {
		[left appendString: right];
		return left;
	    }],
	    @"foobarbaz");
}
#endif

- (void)testValueForKey
{
	OTAssertEqualObjects(
	    [([self.arrayClass arrayWithObjects: @"foo", @"bar", @"quxqux",
	    nil]) valueForKey: @"length"],
	    ([self.arrayClass arrayWithObjects: [OFNumber numberWithInt: 3],
	    [OFNumber numberWithInt: 3], [OFNumber numberWithInt: 6], nil]));

	OTAssertEqualObjects(
	    [([self.arrayClass arrayWithObjects: @"1", @"2", nil])
	    valueForKey: @"@count"],
	    [OFNumber numberWithInt: 2]);
}
@end

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

	@try {
		_array = [[OFMutableArray alloc] init];
	} @catch (id e) {
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
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
450
451
452
453
454
455
456
457
458
	return [_array objectAtIndex: idx];
}

- (size_t)count
{
	return [_array count];
}
@end

@implementation SimpleMutableArray
+ (void)initialize
{
	if (self == [SimpleMutableArray class])
		[self inheritMethodsFromClass: [SimpleArray class]];
}

- (void)insertObject: (id)object atIndex: (size_t)idx
{
	[_array insertObject: object atIndex: idx];
}

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

- (void)removeObjectAtIndex: (size_t)idx
{
	[_array removeObjectAtIndex: idx];
}
@end

@implementation TestsAppDelegate (OFArrayTests)
- (void)arrayTestsWithClass: (Class)arrayClass
	       mutableClass: (Class)mutableArrayClass
{
	void *pool = objc_autoreleasePoolPush();
	OFArray *array1, *array2;
	OFMutableArray *mutableArray1, *mutableArray2;
	OFEnumerator *enumerator;
	id object;
	bool ok;
	size_t i;

	TEST(@"+[array]", (mutableArray1 = [mutableArrayClass array]))

	TEST(@"+[arrayWithObjects:]",
	    (array1 =
	    [arrayClass arrayWithObjects: @"Foo", @"Bar", @"Baz", nil]))

	TEST(@"+[arrayWithObjects:count:]",
	    (array2 = [arrayClass arrayWithObjects: cArray count: 3]) &&
	    [array2 isEqual: array1])

	TEST(@"-[description]",
	    [array1.description isEqual: @"(\n\tFoo,\n\tBar,\n\tBaz\n)"])

	TEST(@"-[addObject:]",
	    R([mutableArray1 addObject: cArray[0]]) &&
	    R([mutableArray1 addObject: cArray[2]]))

	TEST(@"-[insertObject:atIndex:]",
	    R([mutableArray1 insertObject: cArray[1] atIndex: 1]))

	TEST(@"-[count]",
	    mutableArray1.count == 3 && array1.count == 3 && array2.count == 3)

	TEST(@"-[isEqual:]",
	    [mutableArray1 isEqual: array1] && [array1 isEqual: array2])

	TEST(@"-[objectAtIndex:]",
	    [[mutableArray1 objectAtIndex: 0] isEqual: cArray[0]] &&
	    [[mutableArray1 objectAtIndex: 1] isEqual: cArray[1]] &&
	    [[mutableArray1 objectAtIndex: 2] isEqual: cArray[2]] &&
	    [[array1 objectAtIndex: 0] isEqual: cArray[0]] &&
	    [[array1 objectAtIndex: 1] isEqual: cArray[1]] &&
	    [[array1 objectAtIndex: 2] isEqual: cArray[2]] &&
	    [[array2 objectAtIndex: 0] isEqual: cArray[0]] &&
	    [[array2 objectAtIndex: 1] isEqual: cArray[1]] &&
	    [[array2 objectAtIndex: 2] isEqual: cArray[2]])

	TEST(@"-[containsObject:]",
	    [array1 containsObject: cArray[1]] &&
	    ![array1 containsObject: @"nonexistent"])

	TEST(@"-[containsObjectIdenticalTo:]",
	    [array1 containsObjectIdenticalTo: cArray[1]] &&
	    ![array1 containsObjectIdenticalTo:
	    [OFString stringWithString: cArray[1]]])

	TEST(@"-[indexOfObject:]", [array1 indexOfObject: cArray[1]] == 1)

	TEST(@"-[indexOfObjectIdenticalTo:]",
	    [array2 indexOfObjectIdenticalTo: cArray[1]] == 1)

	TEST(@"-[objectsInRange:]",
	    [[array1 objectsInRange: OFMakeRange(1, 2)] isEqual:
	    [arrayClass arrayWithObjects: cArray[1], cArray[2], nil]])

	TEST(@"-[replaceObject:withObject:]",
	    R([mutableArray1 replaceObject: cArray[1] withObject: cArray[0]]) &&
	    [[mutableArray1 objectAtIndex: 0] isEqual: cArray[0]] &&
	    [[mutableArray1 objectAtIndex: 1] isEqual: cArray[0]] &&
	    [[mutableArray1 objectAtIndex: 2] isEqual: cArray[2]])

	TEST(@"-[replaceObject:identicalTo:]",
	    R([mutableArray1 replaceObjectIdenticalTo: cArray[0]
					   withObject: cArray[1]]) &&
	    [[mutableArray1 objectAtIndex: 0] isEqual: cArray[1]] &&
	    [[mutableArray1 objectAtIndex: 1] isEqual: cArray[0]] &&
	    [[mutableArray1 objectAtIndex: 2] isEqual: cArray[2]])

	TEST(@"-[replaceObjectAtIndex:withObject:]",
	    R([mutableArray1 replaceObjectAtIndex: 0 withObject: cArray[0]]) &&
	    [[mutableArray1 objectAtIndex: 0] isEqual: cArray[0]] &&
	    [[mutableArray1 objectAtIndex: 1] isEqual: cArray[0]] &&
	    [[mutableArray1 objectAtIndex: 2] isEqual: cArray[2]])

	TEST(@"-[removeObject:]",
	    R([mutableArray1 removeObject: cArray[0]]) &&
	    mutableArray1.count == 1)

	[mutableArray1 addObject: cArray[0]];

	TEST(@"-[removeObjectIdenticalTo:]",
	    R([mutableArray1 removeObjectIdenticalTo: cArray[2]]) &&
	    mutableArray1.count == 1)

	mutableArray2 = [[array1 mutableCopy] autorelease];
	TEST(@"-[removeObjectAtIndex:]",
	    R([mutableArray2 removeObjectAtIndex: 1]) &&
	    mutableArray2.count == 2 &&
	    [[mutableArray2 objectAtIndex: 1] isEqual: cArray[2]])

	mutableArray2 = [[array1 mutableCopy] autorelease];
	TEST(@"-[removeObjectsInRange:]",
	    R([mutableArray2 removeObjectsInRange: OFMakeRange(0, 2)]) &&
	    mutableArray2.count == 1 &&
	    [[mutableArray2 objectAtIndex: 0] isEqual: cArray[2]])

	mutableArray2 = [[array1 mutableCopy] autorelease];
	[mutableArray2 addObject: @"qux"];
	[mutableArray2 addObject: @"last"];
	TEST(@"-[reverse]",
	    R([mutableArray2 reverse]) &&
	    [mutableArray2 isEqual: [arrayClass arrayWithObjects:
	    @"last", @"qux", @"Baz", @"Bar", @"Foo", nil]])

	mutableArray2 = [[array1 mutableCopy] autorelease];
	[mutableArray2 addObject: @"qux"];
	[mutableArray2 addObject: @"last"];
	TEST(@"-[reversedArray]",
	    [[mutableArray2 reversedArray] isEqual:
	    [arrayClass arrayWithObjects:
	    @"last", @"qux", @"Baz", @"Bar", @"Foo", nil]])

	mutableArray2 = [[array1 mutableCopy] autorelease];
	[mutableArray2 addObject: @"0"];
	[mutableArray2 addObject: @"z"];
	TEST(@"-[sortedArray]",
	    [[mutableArray2 sortedArray] isEqual: [arrayClass arrayWithObjects:
	    @"0", @"Bar", @"Baz", @"Foo", @"z", nil]] &&
	    [[mutableArray2 sortedArrayUsingSelector: @selector(compare:)
					     options: OFArraySortDescending]
	    isEqual: [arrayClass arrayWithObjects:
	    @"z", @"Foo", @"Baz", @"Bar", @"0", nil]])

	EXPECT_EXCEPTION(@"Detect out of range in -[objectAtIndex:]",
	    OFOutOfRangeException, [array1 objectAtIndex: array1.count])

	EXPECT_EXCEPTION(@"Detect out of range in -[removeObjectsInRange:]",
	    OFOutOfRangeException, [mutableArray1 removeObjectsInRange:
		OFMakeRange(0, mutableArray1.count + 1)])

	TEST(@"-[componentsJoinedByString:]",
	    (array2 = [arrayClass arrayWithObjects: @"", @"a", @"b", @"c",
	    nil]) &&
	    [[array2 componentsJoinedByString: @" "] isEqual: @" a b c"] &&
	    (array2 = [arrayClass arrayWithObject: @"foo"]) &&
	    [[array2 componentsJoinedByString: @" "] isEqual: @"foo"])

	TEST(@"-[componentsJoinedByString:options]",
	    (array2 = [arrayClass arrayWithObjects: @"", @"foo", @"", @"",
	    @"bar", @"", nil]) &&
	    [[array2 componentsJoinedByString: @" "
				      options: OFArraySkipEmptyComponents]
	    isEqual: @"foo bar"])

	mutableArray1 = [[array1 mutableCopy] autorelease];
	ok = true;
	i = 0;

	TEST(@"-[objectEnumerator]",
	    (enumerator = [mutableArray1 objectEnumerator]))

	while ((object = [enumerator nextObject]) != nil) {
		if (![object isEqual: cArray[i]])
			ok = false;
		[mutableArray1 replaceObjectAtIndex: i withObject: @""];
		i++;
	}

	if (mutableArray1.count != i)
		ok = false;

	TEST(@"OFEnumerator's -[nextObject]", ok)

	[mutableArray1 removeObjectAtIndex: 0];

	EXPECT_EXCEPTION(@"Detection of mutation during enumeration",
	    OFEnumerationMutationException, [enumerator nextObject])

	mutableArray1 = [[array1 mutableCopy] autorelease];
	ok = true;
	i = 0;

	for (OFString *string in mutableArray1) {
		if (![string isEqual: cArray[i]])
			ok = false;
		[mutableArray1 replaceObjectAtIndex: i withObject: @""];
		i++;
	}

	if (mutableArray1.count != i)
		ok = false;

	TEST(@"Fast Enumeration", ok)

	[mutableArray1 replaceObjectAtIndex: 0 withObject: cArray[0]];
	[mutableArray1 replaceObjectAtIndex: 1 withObject: cArray[1]];
	[mutableArray1 replaceObjectAtIndex: 2 withObject: cArray[2]];

	ok = false;
	i = 0;
	@try {
		for (OFString *string in mutableArray1) {
			(void)string;

			if (i == 0)
				[mutableArray1 addObject: @""];

			i++;
		}
	} @catch (OFEnumerationMutationException *e) {
		ok = true;
	}

	TEST(@"Detection of mutation during Fast Enumeration", ok)

	[mutableArray1 removeLastObject];

#ifdef OF_HAVE_BLOCKS
	{
		__block bool blockOK = true;
		__block size_t count = 0;
		OFArray *compareArray = array1;
		OFMutableArray *mutableArray3;

		mutableArray1 = [[array1 mutableCopy] autorelease];
		[mutableArray1 enumerateObjectsUsingBlock:
		    ^ (id object_, size_t idx, bool *stop) {
			count++;
			if (![object_ isEqual:
			    [compareArray objectAtIndex: idx]])
				blockOK = false;
		}];

		if (count != compareArray.count)
			blockOK = false;

		TEST(@"Enumeration using blocks", blockOK)

		blockOK = false;
		mutableArray3 = mutableArray1;
		@try {
			[mutableArray3 enumerateObjectsUsingBlock:
			    ^ (id object_, size_t idx, bool *stop) {
				[mutableArray3 removeObjectAtIndex: idx];
			}];
		} @catch (OFEnumerationMutationException *e) {
			blockOK = true;
		} @catch (OFOutOfRangeException *e) {
			/*
			 * Out of bounds access due to enumeration not being
			 * detected.
			 */
		}

		TEST(@"Detection of mutation during enumeration using blocks",
		    blockOK)
	}

	TEST(@"-[replaceObjectsUsingBlock:]",
	    R([mutableArray1 replaceObjectsUsingBlock:
		^ id (id object_, size_t idx) {
		    switch (idx) {
		    case 0:
			    return @"foo";
		    case 1:
			    return @"bar";
		    }

		    return nil;
	    }]) && [mutableArray1.description isEqual: @"(\n\tfoo,\n\tbar\n)"])

	TEST(@"-[mappedArrayUsingBlock:]",
	    [[mutableArray1 mappedArrayUsingBlock:
		^ id (id object_, size_t idx) {
		    switch (idx) {
		    case 0:
			    return @"foobar";
		    case 1:
			    return @"qux";
		    }

		    return nil;
	    }].description isEqual: @"(\n\tfoobar,\n\tqux\n)"])

	TEST(@"-[filteredArrayUsingBlock:]",
	    [[mutableArray1 filteredArrayUsingBlock:
		^ bool (id object_, size_t idx) {
		    return [object_ isEqual: @"foo"];
	    }].description isEqual: @"(\n\tfoo\n)"])

	TEST(@"-[foldUsingBlock:]",
	    [[arrayClass arrayWithObjects: [OFMutableString string], @"foo",
	    @"bar", @"baz", nil] foldUsingBlock: ^ id (id left, id right) {
		    [left appendString: right];
		    return left;
	    }])
#endif

	TEST(@"-[valueForKey:]",
	    [[[arrayClass arrayWithObjects: @"foo", @"bar", @"quxqux", nil]
	    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:
	    [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:
	    [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";
	[self arrayTestsWithClass: [SimpleArray class]
		     mutableClass: [SimpleMutableArray class]];

	module = @"OFArray_adjacent";
	[self arrayTestsWithClass: [OFArray class]
		     mutableClass: [OFMutableArray class]];
}
@end








<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
335
336
337
338
339
340
341
342






































































































































































































































































































































































	return [_array objectAtIndex: idx];
}

- (size_t)count
{
	return [_array count];
}
@end






































































































































































































































































































































































Renamed and modified tests/OFCharacterSetTests.m [cbaf41131b] to new_tests/OFCharacterSetTests.m [2ac90291b5].

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


#import "OFCharacterSet.h"
#import "OFBitSetCharacterSet.h"
#import "OFRangeCharacterSet.h"

static OFString *module;


@interface SimpleCharacterSet: OFCharacterSet
@end

@implementation SimpleCharacterSet
- (bool)characterIsMember: (OFUnichar)character
{
	return (character % 2 == 0);
}
@end

@implementation TestsAppDelegate (OFCharacterSetTests)
- (void)characterSetTests
{
	void *pool = objc_autoreleasePoolPush();
	OFCharacterSet *characterSet, *invertedCharacterSet;
	bool ok;

	module = @"OFCharacterSet";

	characterSet = [[[SimpleCharacterSet alloc] init] autorelease];

	ok = true;
	for (OFUnichar c = 0; c < 65536; c++) {
		if (c % 2 == 0) {
			if (![characterSet characterIsMember: c])
				ok = false;
		} else if ([characterSet characterIsMember: c])
			ok = false;
	}
	TEST(@"-[characterIsMember:]", ok);

	module = @"OFBitSetCharacterSet";

	TEST(@"+[characterSetWithCharactersInString:]",
	    (characterSet = [OFCharacterSet characterSetWithCharactersInString:
	    @"0123456789"]) &&

	    [characterSet isKindOfClass: [OFBitSetCharacterSet class]])

	ok = true;
	for (OFUnichar c = 0; c < 65536; c++) {
		if (c >= '0' && c <= '9') {
			if (![characterSet characterIsMember: c])
				ok = false;
		} else if ([characterSet characterIsMember: c])


			ok = false;




	}
	TEST(@"-[characterIsMember:]", ok);

	module = @"OFRangeCharacterSet";

	TEST(@"+[characterSetWithRange:]",
	    (characterSet = [OFCharacterSet
	    characterSetWithRange: OFMakeRange('0', 10)]) &&
	    [characterSet isKindOfClass: [OFRangeCharacterSet class]])

	ok = true;
	for (OFUnichar c = 0; c < 65536; c++) {
		if (c >= '0' && c <= '9') {
			if (![characterSet characterIsMember: c])
				ok = false;
		} else if ([characterSet characterIsMember: c])
			ok = false;
	}
	TEST(@"-[characterIsMember:]", ok);


	ok = true;

	invertedCharacterSet = characterSet.invertedSet;
	for (OFUnichar c = 0; c < 65536; c++) {
		if (c >= '0' && c <= '9') {
			if ([invertedCharacterSet characterIsMember: c])
				ok = false;
		} else if (![invertedCharacterSet characterIsMember: c])
			ok = false;
	}
	TEST(@"-[invertedSet]", ok);


	TEST(@"Inverting -[invertedSet] returns original set",
	    invertedCharacterSet.invertedSet == characterSet)


	objc_autoreleasePoolPop(pool);

}
@end







|
>





|
>

|


|






|
|

<
|
<
<
<
<
|

<
|
|
|
|
|
<
|
<

|
|
|
|
|
>
|

<
|
|
|
<
|
>
>
|
>
>
>
>
|
<
|
<
<
<
<
<
|

<
|
|
|
|
|
<
|
|
>
|
|
>
|
|
|
|
|
|
<
|
|
>
|
<
|
>

<
>


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
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#import "ObjFW.h"
#import "ObjFWTest.h"

#import "OFCharacterSet.h"
#import "OFBitSetCharacterSet.h"
#import "OFRangeCharacterSet.h"

@interface OFCharacterSetTests: OTTestCase
@end

@interface CustomCharacterSet: OFCharacterSet
@end

@implementation CustomCharacterSet
- (bool)characterIsMember: (OFUnichar)character
{
	return (character % 2 == 0);
}
@end

@implementation OFCharacterSetTests
- (void)testCustomCharacterSet
{

	OFCharacterSet *characterSet =




	    [[[CustomCharacterSet alloc] init] autorelease];


	for (OFUnichar c = 0; c < 65536; c++)
		if (c % 2 == 0)
			OTAssertTrue([characterSet characterIsMember: c]);
		else
			OTAssertFalse([characterSet characterIsMember: c]);

}


- (void)testBitSetCharacterSet
{
	OFCharacterSet *characterSet =
	    [OFCharacterSet characterSetWithCharactersInString: @"0123456789"];

	OTAssertTrue(
	    [characterSet isKindOfClass: [OFBitSetCharacterSet class]]);


	for (OFUnichar c = 0; c < 65536; c++)
		if (c >= '0' && c <= '9')
			OTAssertTrue([characterSet characterIsMember: c]);

		else if ([characterSet characterIsMember: c])
			OTAssertFalse([characterSet characterIsMember: c]);
}

- (void)testRangeCharacterSet
{
	OFCharacterSet *characterSet =
	    [OFCharacterSet characterSetWithRange: OFMakeRange('0', 10)];


	OTAssertTrue(





	    [characterSet isKindOfClass: [OFRangeCharacterSet class]]);


	for (OFUnichar c = 0; c < 65536; c++)
		if (c >= '0' && c <= '9')
			OTAssertTrue([characterSet characterIsMember: c]);
		else
			OTAssertFalse([characterSet characterIsMember: c]);

}

- (void)testInvertedCharacterSet
{
	OFCharacterSet *characterSet = [[OFCharacterSet
	    characterSetWithRange: OFMakeRange('0', 10)] invertedSet];

	for (OFUnichar c = 0; c < 65536; c++)
		if (c >= '0' && c <= '9')
			OTAssertFalse([characterSet characterIsMember: c]);
		else
			OTAssertTrue([characterSet characterIsMember: c]);

}

- (void)testInvertingInvertedSetReturnsOriginal
{

	OFCharacterSet *characterSet =
	    [OFCharacterSet characterSetWithRange: OFMakeRange('0', 10)];


	OTAssertEqual(characterSet, characterSet.invertedSet.invertedSet);
}
@end

Renamed and modified tests/OFColorTests.m [43c0fcb4d4] to new_tests/OFColorTests.m [f2116a7a9c].

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







|
>

>
>
|
|
>
>
|
|

<
|
<

<
|
|
|
|
|
>
>
>
>
>
>
>
>

|
>
|
>


>
>
>
|
|
>
|
|
|
<


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
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#import "ObjFW.h"
#import "ObjFWTest.h"

@interface OFColorTests: OTTestCase
{
	OFColor *_color;
}
@end

@implementation OFColorTests
- (void)setUp
{

	[super setUp];



	_color = [[OFColor alloc] initWithRed: 63.f / 255
					green: 127.f / 255
					 blue: 1
					alpha: 1];
}

- (void)dealloc
{
	[_color release];

	[super dealloc];
}

#ifdef OF_OBJFW_RUNTIME
- (void)testReturnsTaggedPointer
{
	OTAssertTrue(object_isTaggedPointer(_color));
}
#endif

- (void)testGetRedGreenBlueAlpha
{
	float red, green, blue, alpha;

	[_color getRed: &red green: &green blue: &blue alpha: &alpha];
	OTAssertEqual(red, 63.f / 255);
	OTAssertEqual(green, 127.f / 255);
	OTAssertEqual(blue, 1);
	OTAssertEqual(alpha, 1);

}
@end

Added new_tests/OFConcreteArrayTests.m version [70542429e0].





























































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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-2024 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the 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 "OFArrayTests.h"

#import "OFConcreteArray.h"

@interface OFConcreteArrayTests: OFArrayTests
@end

@implementation OFConcreteArrayTests
- (Class)arrayClass
{
	return [OFConcreteArray class];
}
@end

Added new_tests/OFConcreteMutableArrayTests.m version [b38f014238].



















































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
/*
 * Copyright (c) 2008-2024 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the 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 "OFMutableArrayTests.h"

#import "OFConcreteMutableArray.h"

@interface OFConcreteMutableArrayTests: OFMutableArrayTests
@end

static OFString *const cArray[] = {
	@"Foo",
	@"Bar",
	@"Baz"
};

@implementation OFConcreteMutableArrayTests
- (Class)arrayClass
{
	return [OFConcreteMutableArray class];
}

- (void)testDetectMutationDuringEnumeration
{
	OFEnumerator *enumerator = [_mutableArray objectEnumerator];
	OFString *object;
	size_t i;

	i = 0;
	while ((object = [enumerator nextObject]) != nil) {
		OTAssertEqualObjects(object, cArray[i]);

		[_mutableArray replaceObjectAtIndex: i withObject: @""];
		i++;
	}
	OTAssertEqual(i, _mutableArray.count);

	[_mutableArray removeObjectAtIndex: 0];
	OTAssertThrowsSpecific([enumerator nextObject],
	    OFEnumerationMutationException);
}

- (void)testDetectMutationDuringFastEnumeration
{
	bool detected = false;
	size_t i;

	i = 0;
	for (OFString *object in _mutableArray) {
		OTAssertEqualObjects(object, cArray[i]);

		[_mutableArray replaceObjectAtIndex: i withObject: @""];
		i++;
	}
	OTAssertEqual(i, _mutableArray.count);

	@try {
		for (OFString *object in _mutableArray) {
			(void)object;
			[_mutableArray removeObjectAtIndex: 0];
		}
	} @catch (OFEnumerationMutationException *e) {
		detected = true;
	}
	OTAssertTrue(detected);
}

#ifdef OF_HAVE_BLOCKS
- (void)testDetectMutationDuringEnumerateObjectsUsingBlock
{
	__block size_t i;

	i = 0;
	[_mutableArray enumerateObjectsUsingBlock:
	    ^ (id object, size_t idx, bool *stop) {
		OTAssertEqualObjects(object, cArray[idx]);

		[_mutableArray replaceObjectAtIndex: idx withObject: @""];
		i++;
	}];
	OTAssertEqual(i, _mutableArray.count);

	OTAssertThrowsSpecific(
	    [_mutableArray enumerateObjectsUsingBlock:
	    ^ (id object, size_t idx, bool *stop) {
		[_mutableArray removeObjectAtIndex: 0];
	    }],
	    OFEnumerationMutationException);
}
#endif
@end

Added new_tests/OFCryptographicHashTests.m version [9a95ece37d].

























































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
/*
 * Copyright (c) 2008-2024 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the 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 "ObjFW.h"
#import "ObjFWTest.h"

@interface OFCryptographicHashTests: OTTestCase
{
	OFStream *_stream;
}
@end

const unsigned char testFileMD5[16] =
    "\x00\x8B\x9D\x1B\x58\xDF\xF8\xFE\xEE\xF3\xAE\x8D\xBB\x68\x2D\x38";
const unsigned char testFileRIPEMD160[20] =
    "\x46\x02\x97\xF5\x85\xDF\xB9\x21\x00\xC8\xF9\x87\xC6\xEC\x84\x0D"
    "\xCE\xE6\x08\x8B";
const unsigned char testFileSHA1[20] =
    "\xC9\x9A\xB8\x7E\x1E\xC8\xEC\x65\xD5\xEB\xE4\x2E\x0D\xA6\x80\x96"
    "\xF5\x94\xE7\x17";
const unsigned char testFileSHA224[28] =
    "\x27\x69\xD8\x04\x2D\x0F\xCA\x84\x6C\xF1\x62\x44\xBA\x0C\xBD\x46"
    "\x64\x5F\x4F\x20\x02\x4D\x15\xED\x1C\x61\x1F\xF7";
const unsigned char testFileSHA256[32] =
    "\x1A\x02\xD6\x46\xF5\xA6\xBA\xAA\xFF\x7F\xD5\x87\xBA\xC3\xF6\xC6"
    "\xB5\x67\x93\x8F\x0F\x44\x90\xB8\xF5\x35\x89\xF0\x5A\x23\x7F\x69";
const unsigned char testFileSHA384[48] =
    "\x7E\xDE\x62\xE2\x10\xA5\x1E\x18\x8A\x11\x7F\x78\xD7\xC7\x55\xB6"
    "\x43\x94\x1B\xD2\x78\x5C\xCF\xF3\x8A\xB8\x98\x22\xC7\x0E\xFE\xF1"
    "\xEC\x53\xE9\x1A\xB3\x51\x70\x8C\x1F\x3F\x56\x12\x44\x01\x91\x54";
const unsigned char testFileSHA512[64] =
    "\x8F\x36\x6E\x3C\x19\x4B\xBB\xC7\x82\xAA\xCD\x7D\x55\xA2\xD3\x29"
    "\x29\x97\x6A\x3F\xEB\x9B\xB2\xCB\x75\xC9\xEC\xC8\x10\x07\xD6\x07"
    "\x31\x4A\xB1\x30\x97\x82\x58\xA5\x1F\x71\x42\xE6\x56\x07\x99\x57"
    "\xB2\xB8\x3B\xA1\x8A\x41\x64\x33\x69\x21\x8C\x2A\x44\x6D\xF2\xA0";

@implementation OFCryptographicHashTests
- (void)setUp
{
	OFIRI *IRI;

	[super setUp];

	IRI = [OFIRI IRIWithString: @"embedded:testfile.bin"];
	_stream = [[OFIRIHandler openItemAtIRI: IRI mode: @"r"] retain];
}

- (void)tearDown
{
	[_stream close];

	[super tearDown];
}

- (void)dealloc
{
	[_stream release];

	[super dealloc];
}

- (void)testHash: (Class)hashClass
  expectedDigest: (const unsigned char *)expectedDigest
{
	id <OFCryptographicHash> hash =
	    [hashClass hashWithAllowsSwappableMemory: true];
	id <OFCryptographicHash> copy;

	OTAssertNotNil(hash);

	while (!_stream.atEndOfStream) {
		char buffer[64];
		size_t length = [_stream readIntoBuffer: buffer length: 64];
		[hash updateWithBuffer: buffer length: length];
	}

	copy = [[hash copy] autorelease];

	[hash calculate];
	[copy calculate];

	OTAssertEqual(memcmp(hash.digest, expectedDigest, hash.digestSize), 0);
	OTAssertEqual(memcmp(hash.digest, expectedDigest, hash.digestSize), 0);

	OTAssertThrowsSpecific([hash updateWithBuffer: "" length: 1],
	    OFHashAlreadyCalculatedException);
}

- (void)testMD5
{
	[self testHash: [OFMD5Hash class] expectedDigest: testFileMD5];
}

- (void)testRIPEMD160
{
	[self	  testHash: [OFRIPEMD160Hash class]
	    expectedDigest: testFileRIPEMD160];
}

- (void)testSHA1
{
	[self testHash: [OFSHA1Hash class] expectedDigest: testFileSHA1];
}

- (void)testSHA224
{
	[self testHash: [OFSHA224Hash class] expectedDigest: testFileSHA224];
}

- (void)testSHA256
{
	[self testHash: [OFSHA256Hash class] expectedDigest: testFileSHA256];
}

- (void)testSHA384
{
	[self testHash: [OFSHA384Hash class] expectedDigest: testFileSHA384];
}

- (void)testSHA512
{
	[self testHash: [OFSHA512Hash class] expectedDigest: testFileSHA512];
}
@end

Renamed and modified tests/OFDateTests.m [a09d2c22e2] to new_tests/OFDateTests.m [f4f700dfaa].

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
 * file.
 */

#include "config.h"

#include <time.h>

#import "TestsAppDelegate.h"


#import "OFStrPTime.h"



static OFString *const module = @"OFDate";



@implementation TestsAppDelegate (OFDateTests)









- (void)dateTests
{


	void *pool = objc_autoreleasePoolPush();


	OFDate *date1, *date2;


	struct tm tm;
	int16_t tz;
	const char *dstr = "Wed, 09 Jun 2021 +0200x";
	TEST(@"OFStrPTime()",
	    OFStrPTime(dstr, "%a, %d %b %Y %z", &tm, &tz) == dstr + 22 &&

	    tm.tm_wday == 3 && tm.tm_mday == 9 && tm.tm_mon == 5 &&


	    tm.tm_year == 2021 - 1900 && tz == 2 * 60)


	TEST(@"+[dateWithTimeIntervalSince1970:]",
	    (date1 = [OFDate dateWithTimeIntervalSince1970: 0]))

	TEST(@"-[dateByAddingTimeInterval:]",


	    (date2 = [date1 dateByAddingTimeInterval: 3600 * 25 + 5.000002]))



	TEST(@"-[description]",

	    [date1.description isEqual: @"1970-01-01T00:00:00Z"] &&
	    [date2.description isEqual: @"1970-01-02T01:00:05Z"])


	TEST(@"+[dateWithDateString:format:]",


	    [[[OFDate dateWithDateString: @"2000-06-20T12:34:56+0200"
				  format: @"%Y-%m-%dT%H:%M:%S%z"] description]
	    isEqual: @"2000-06-20T10:34:56Z"]);

	EXPECT_EXCEPTION(@"Detection of unparsed in "
	    @"+[dateWithDateString:format:]", OFInvalidFormatException,


	    [OFDate dateWithDateString: @"2000-06-20T12:34:56+0200x"
				format: @"%Y-%m-%dT%H:%M:%S%z"])



	TEST(@"+[dateWithLocalDateString:format:]",


	    [[[OFDate dateWithLocalDateString: @"2000-06-20T12:34:56"
				       format: @"%Y-%m-%dT%H:%M:%S"]
	    localDateStringWithFormat: @"%Y-%m-%dT%H:%M:%S"]
	    isEqual: @"2000-06-20T12:34:56"]);

	TEST(@"+[dateWithLocalDateString:format:]",

	    [[[OFDate dateWithLocalDateString: @"2000-06-20T12:34:56-0200"
				       format: @"%Y-%m-%dT%H:%M:%S%z"]

	    description] isEqual: @"2000-06-20T14:34:56Z"]);

	EXPECT_EXCEPTION(@"Detection of unparsed in "
	    @"+[dateWithLocalDateString:format:] #1", OFInvalidFormatException,


	    [OFDate dateWithLocalDateString: @"2000-06-20T12:34:56x"
				     format: @"%Y-%m-%dT%H:%M:%S"])


	EXPECT_EXCEPTION(@"Detection of unparsed in "
	    @"+[dateWithLocalDateString:format:] #2", OFInvalidFormatException,

	    [OFDate dateWithLocalDateString: @"2000-06-20T12:34:56+0200x"
				     format: @"%Y-%m-%dT%H:%M:%S%z"])


	TEST(@"-[isEqual:]",



	    [date1 isEqual: [OFDate dateWithTimeIntervalSince1970: 0]] &&


	    ![date1 isEqual: [OFDate dateWithTimeIntervalSince1970: 0.0000001]])

	TEST(@"-[compare:]", [date1 compare: date2] == OFOrderedAscending)




	TEST(@"-[second]", date1.second == 0 && date2.second == 5)






	TEST(@"-[microsecond]",

	    date1.microsecond == 0 && date2.microsecond == 2)


	TEST(@"-[minute]", date1.minute == 0 && date2.minute == 0)





	TEST(@"-[hour]", date1.hour == 0 && date2.hour == 1)





	TEST(@"-[dayOfMonth]", date1.dayOfMonth == 1 && date2.dayOfMonth == 2)






	TEST(@"-[monthOfYear]",

	    date1.monthOfYear == 1 && date2.monthOfYear == 1)


	TEST(@"-[year]", date1.year == 1970 && date2.year == 1970)





	TEST(@"-[dayOfWeek]", date1.dayOfWeek == 4 && date2.dayOfWeek == 5)


	TEST(@"-[dayOfYear]", date1.dayOfYear == 1 && date2.dayOfYear == 2)


	TEST(@"-[earlierDate:]", [[date1 earlierDate: date2] isEqual: date1])





	TEST(@"-[laterDate:]", [[date1 laterDate: date2] isEqual: date2])




	objc_autoreleasePoolPop(pool);



}
@end







|
>
>


>
>
|
|
>
>
|
>
>
>
>
>
>
>
>
>
|

>
>
|
>
>
|
>
|

|
|
|
|
>
|
>
>
|
>
|
<
<

|
>
>
|
>
|
>
|
>
|
|
|
>
|
>
>
|
|
|
|
|
|
>
>

|
>
|
>
|
>
>
|
|
|
|

<
>
|
|
>
|
|
|
|
>
>

|
>

<
<
>

|
>
|
|
>
>
>
|
>
>
|
|
|
>
|
>
>
|
>
|
>
>
>
>
|
>
|
>
|
|
>
|
>
>
>
|
>
>
>
>
|
|
>
|
>
>
>
>
|
>
|
>
|
|
>
|
>
>
>
|
>
|
|
>
|
|
>
|
>
>
>
|
>
|
>
>
|
>
>
>


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
 * file.
 */

#include "config.h"

#include <time.h>

#import "ObjFW.h"
#import "ObjFWTest.h"

#import "OFStrPTime.h"

@interface OFDateTests: OTTestCase
{
	OFDate *_date[2];
}
@end

@implementation OFDateTests
- (void)setUp
{
	[super setUp];

	_date[0] = [[OFDate alloc] initWithTimeIntervalSince1970: 0];
	_date[1] = [[OFDate alloc]
	    initWithTimeIntervalSince1970: 3600 * 25 + 5.000002];
}

- (void)dealloc
{
	[_date[0] release];
	[_date[1] release];

	[super dealloc];
}

- (void)testStrPTime
{
	struct tm tm;
	int16_t timeZone;
	const char *dateString = "Wed, 09 Jun 2021 +0200x";

	OTAssertEqual(OFStrPTime(dateString, "%a, %d %b %Y %z", &tm, &timeZone),
	    dateString + 22);
	OTAssertEqual(tm.tm_wday, 3);
	OTAssertEqual(tm.tm_mday, 9);
	OTAssertEqual(tm.tm_mon, 5);
	OTAssertEqual(tm.tm_year, 2021 - 1900);
	OTAssertEqual(timeZone, 2 * 60);
}



- (void)testDateByAddingTimeInterval
{
	OTAssertEqualObjects(
	    [_date[0] dateByAddingTimeInterval: 3600 * 25 + 5.000002],
	    _date[1]);
}

- (void)testDescription
{
	OTAssertEqualObjects(_date[0].description, @"1970-01-01T00:00:00Z");
	OTAssertEqualObjects(_date[1].description, @"1970-01-02T01:00:05Z");
}

- (void)testDateWithDateStringFormat
{
	OTAssertEqualObjects(
	    [[OFDate dateWithDateString: @"2000-06-20T12:34:56+0200"
				 format: @"%Y-%m-%dT%H:%M:%S%z"] description],
	    @"2000-06-20T10:34:56Z");
}

- (void)testDateWithDateStringFormatFailsWithTrailingCharacters
{
	OTAssertThrowsSpecific(
	    [OFDate dateWithDateString: @"2000-06-20T12:34:56+0200x"
				format: @"%Y-%m-%dT%H:%M:%S%z"],
	    OFInvalidFormatException);
}

- (void)testDateWithLocalDateStringFormatFormat
{
	OTAssertEqualObjects(
	    [[OFDate dateWithLocalDateString: @"2000-06-20T12:34:56"
				      format: @"%Y-%m-%dT%H:%M:%S"]
	    localDateStringWithFormat: @"%Y-%m-%dT%H:%M:%S"],
	    @"2000-06-20T12:34:56");


	OTAssertEqualObjects(
	    [[OFDate dateWithLocalDateString: @"2000-06-20T12:34:56-0200"
				      format: @"%Y-%m-%dT%H:%M:%S%z"]
	    description],
	    @"2000-06-20T14:34:56Z");
}

- (void)testDateWithLocalDateStringFormatFailsWithTrailingCharacters
{
	OTAssertThrowsSpecific(
	    [OFDate dateWithLocalDateString: @"2000-06-20T12:34:56x"
				     format: @"%Y-%m-%dT%H:%M:%S"],
	    OFInvalidFormatException);



	OTAssertThrowsSpecific(
	    [OFDate dateWithLocalDateString: @"2000-06-20T12:34:56+0200x"
				     format: @"%Y-%m-%dT%H:%M:%S%z"],
	    OFInvalidFormatException);
}

- (void)testIsEqual
{
	OTAssertEqualObjects(_date[0],
	    [OFDate dateWithTimeIntervalSince1970: 0]);

	OTAssertNotEqualObjects(_date[0],
	    [OFDate dateWithTimeIntervalSince1970: 0.0000001]);
}

- (void)testCompare
{
	OTAssertEqual([_date[0] compare: _date[1]], OFOrderedAscending);
}

- (void)testSecond
{
	OTAssertEqual(_date[0].second, 0);
	OTAssertEqual(_date[1].second, 5);
}

- (void)testMicrosecond
{
	OTAssertEqual(_date[0].microsecond, 0);
	OTAssertEqual(_date[1].microsecond, 2);
}

- (void)testMinute
{
	OTAssertEqual(_date[0].minute, 0);
	OTAssertEqual(_date[1].minute, 0);
}

- (void)testHour
{
	OTAssertEqual(_date[0].hour, 0);
	OTAssertEqual(_date[1].hour, 1);
}

- (void)testDayOfMonth
{
	OTAssertEqual(_date[0].dayOfMonth, 1);
	OTAssertEqual(_date[1].dayOfMonth, 2);
}

- (void)testMonthOfYear
{
	OTAssertEqual(_date[0].monthOfYear, 1);
	OTAssertEqual(_date[1].monthOfYear, 1);
}

- (void)testYear
{
	OTAssertEqual(_date[0].year, 1970);
	OTAssertEqual(_date[1].year, 1970);
}

- (void)testDayOfWeek
{
	OTAssertEqual(_date[0].dayOfWeek, 4);
	OTAssertEqual(_date[1].dayOfWeek, 5);
}

- (void)testDayOfYear
{
	OTAssertEqual(_date[0].dayOfYear, 1);
	OTAssertEqual(_date[1].dayOfYear, 2);
}

- (void)testEarlierDate
{
	OTAssertEqualObjects([_date[0] earlierDate: _date[1]], _date[0]);
}

- (void)testLaterDate
{
	OTAssertEqualObjects([_date[0] laterDate: _date[1]], _date[1]);
}
@end

Renamed and modified tests/OFHMACTests.m [b03d7ee96c] to new_tests/OFHMACTests.m [726dca6e51].

13
14
15
16
17
18
19
20

21





22
23
24
25
26
27
28
29
 * file.
 */

#include "config.h"

#include <string.h>

#import "TestsAppDelegate.h"







static OFString *const module = @"OFHMAC";
static const uint8_t key[] =
    "yM9h8K6IWnJRvxC/0F8XRWG7RnACDBz8wqK2tbXrYVLoKC3vPLeJikyJSM47tVHc"
    "DlXHww9zULAC2sJUlm2Kg1z4oz2aXY3Y1PQSB4VkC/m0DQ7hCI6cAg4TWnKdzWTy"
    "cvYGX+Y6HWeDY79/PGSd8fNItme6I8w4HDBqU7BP2sum3jbePJqoiSnhcyJZQTeZ"
    "jw0ZXoyrfHgOYD2M+NsTDaGpLblFtQ7n5CczjKtafG40PkEwx1dcrd46U9i3GyTK";
static const size_t keyLength = sizeof(key);
static const uint8_t MD5Digest[] =







|
>

>
>
>
>
>
|







13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
 * file.
 */

#include "config.h"

#include <string.h>

#import "ObjFW.h"
#import "ObjFWTest.h"

@interface OFHMACTests: OTTestCase
{
	OFStream *_stream;
}
@end

static const uint8_t key[] =
    "yM9h8K6IWnJRvxC/0F8XRWG7RnACDBz8wqK2tbXrYVLoKC3vPLeJikyJSM47tVHc"
    "DlXHww9zULAC2sJUlm2Kg1z4oz2aXY3Y1PQSB4VkC/m0DQ7hCI6cAg4TWnKdzWTy"
    "cvYGX+Y6HWeDY79/PGSd8fNItme6I8w4HDBqU7BP2sum3jbePJqoiSnhcyJZQTeZ"
    "jw0ZXoyrfHgOYD2M+NsTDaGpLblFtQ7n5CczjKtafG40PkEwx1dcrd46U9i3GyTK";
static const size_t keyLength = sizeof(key);
static const uint8_t MD5Digest[] =
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
    "\x14\x52\x33\x4B\x9C\x5F\xD8\x07\x4E\x98\xAE\x97\x46\x29\x24\xB4";
static const uint8_t SHA512Digest[] =
    "\xF5\x8C\x3F\x9C\xA2\x2F\x0A\xF3\x26\xD8\xC0\x7E\x20\x63\x88\x61"
    "\xC9\xE1\x1F\xD7\xC7\xE5\x59\x33\xD5\x2F\xAF\x56\x1C\x94\xC8\xA4"
    "\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();


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


	    (HMACSHA1 = [OFHMAC HMACWithHashClass: [OFSHA1Hash class]
			    allowsSwappableMemory: true]))


	TEST(@"+[HMACWithHashClass:] with RIPEMD-160",
	    (HMACRMD160 = [OFHMAC HMACWithHashClass: [OFRIPEMD160Hash class]
			      allowsSwappableMemory: true]))

	TEST(@"+[HMACWithHashClass:] with SHA-256",
	    (HMACSHA256 = [OFHMAC HMACWithHashClass: [OFSHA256Hash class]
			      allowsSwappableMemory: true]))
	TEST(@"+[HMACWithHashClass:] with SHA-384",


	    (HMACSHA384 = [OFHMAC HMACWithHashClass: [OFSHA384Hash class]
			      allowsSwappableMemory: true]))
	TEST(@"+[HMACWithHashClass:] with SHA-512",
	    (HMACSHA512 = [OFHMAC HMACWithHashClass: [OFSHA512Hash class]
			      allowsSwappableMemory: true]))

	EXPECT_EXCEPTION(@"Detection of missing key",

	    OFInvalidArgumentException,
	    [HMACMD5 updateWithBuffer: "" length: 0])

	TEST(@"-[setKey:length:] with MD5",
	    R([HMACMD5 setKey: key length: keyLength]))
	TEST(@"-[setKey:length:] with SHA-1",
	    R([HMACSHA1 setKey: key length: keyLength]))
	TEST(@"-[setKey:length:] with RIPEMD-160",
	    R([HMACRMD160 setKey: key length: keyLength]))
	TEST(@"-[setKey:length:] with SHA-256",
	    R([HMACSHA256 setKey: key length: keyLength]))
	TEST(@"-[setKey:length:] with SHA-384",
	    R([HMACSHA384 setKey: key length: keyLength]))
	TEST(@"-[setKey:length:] with SHA-512",
	    R([HMACSHA512 setKey: key length: keyLength]))

	while (!file.atEndOfStream) {
		char buffer[64];
		size_t length = [file readIntoBuffer: buffer length: 64];
		[HMACMD5 updateWithBuffer: buffer length: length];

		[HMACSHA1 updateWithBuffer: buffer length: length];
		[HMACRMD160 updateWithBuffer: buffer length: length];
		[HMACSHA256 updateWithBuffer: buffer length: length];


		[HMACSHA384 updateWithBuffer: buffer length: length];
		[HMACSHA512 updateWithBuffer: buffer length: length];


	}
	[file close];


	TEST(@"-[calculate] with MD5", R([HMACMD5 calculate]))
	TEST(@"-[calculate] with SHA-1", R([HMACSHA1 calculate]))

	TEST(@"-[calculate] with RIPEMD-160", R([HMACRMD160 calculate]))

	TEST(@"-[calculate] with SHA-256", R([HMACSHA256 calculate]))
	TEST(@"-[calculate] with SHA-384", R([HMACSHA384 calculate]))
	TEST(@"-[calculate] with SHA-512", R([HMACSHA512 calculate]))


	TEST(@"-[digest] with MD5",
	    memcmp(HMACMD5.digest, MD5Digest, HMACMD5.digestSize) == 0)
	TEST(@"-[digest] with SHA-1",
	    memcmp(HMACSHA1.digest, SHA1Digest, HMACSHA1.digestSize) == 0)

	TEST(@"-[digest] with RIPEMD-160",
	    memcmp(HMACRMD160.digest, RIPEMD160Digest,

	    HMACRMD160.digestSize) == 0)
	TEST(@"-[digest] with SHA-256",

	    memcmp(HMACSHA256.digest, SHA256Digest, HMACSHA256.digestSize) == 0)
	TEST(@"-[digest] with SHA-384",


	    memcmp(HMACSHA384.digest, SHA384Digest, HMACSHA384.digestSize) == 0)

	TEST(@"-[digest] with SHA-512",
	    memcmp(HMACSHA512.digest, SHA512Digest, HMACSHA512.digestSize) == 0)

	objc_autoreleasePoolPop(pool);


}
@end







|
|

>
|
>
>
|
|
<
<
|
|
<
|
>
>
|
>
>
|
|
>
>
|
<
|
>
|
<
<
|
>
>
|
|
|
|
<

<
>
|
<

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

|

|
|
>
|
|
|
>
>
|
|
>
>
|
|
>
|
<
<
>
|
>
|
<
<
>
|
<
<
<
|
>
|
|
>
|
|
>
|
|
>
>
|
>
|
|
|
<
>
>


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
    "\x14\x52\x33\x4B\x9C\x5F\xD8\x07\x4E\x98\xAE\x97\x46\x29\x24\xB4";
static const uint8_t SHA512Digest[] =
    "\xF5\x8C\x3F\x9C\xA2\x2F\x0A\xF3\x26\xD8\xC0\x7E\x20\x63\x88\x61"
    "\xC9\xE1\x1F\xD7\xC7\xE5\x59\x33\xD5\x2F\xAF\x56\x1C\x94\xC8\xA4"
    "\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 OFHMACTests
- (void)setUp
{
	OFIRI *IRI;

	[super setUp];

	IRI = [OFIRI IRIWithString: @"embedded:testfile.bin"];
	_stream = [[OFIRIHandler openItemAtIRI: IRI mode: @"r"] retain];


}


- (void)tearDown
{
	[_stream close];

	[super tearDown];
}

- (void)dealloc
{
	[_stream release];


	[super dealloc];
}



- (void)testWithHashClass: (Class)hashClass
	   expectedDigest: (const unsigned char *)expectedDigest
{
	OFHMAC *HMAC = [OFHMAC HMACWithHashClass: hashClass
			   allowsSwappableMemory: true];

	OTAssertNotNil(HMAC);



	OTAssertThrowsSpecific([HMAC updateWithBuffer: "" length: 0],
	    OFInvalidArgumentException);



	[HMAC setKey: key length: keyLength];











	while (!_stream.atEndOfStream) {
		char buffer[64];
		size_t length = [_stream readIntoBuffer: buffer length: 64];
		[HMAC updateWithBuffer: buffer length: length];
	}

	[HMAC calculate];

	OTAssertEqual(memcmp(HMAC.digest, expectedDigest, HMAC.digestSize), 0);
}

- (void)testHMACWithMD5
{
	[self testWithHashClass: [OFMD5Hash class] expectedDigest: MD5Digest];
}

- (void)testHMACWithRIPEMD160
{


	[self testWithHashClass: [OFRIPEMD160Hash class]
		 expectedDigest: RIPEMD160Digest];
}



- (void)testHMACWithSHA1
{



	[self testWithHashClass: [OFSHA1Hash class] expectedDigest: SHA1Digest];
}

- (void)testHMACWithSHA256
{
	[self testWithHashClass: [OFSHA256Hash class]
		 expectedDigest: SHA256Digest];
}

- (void)testHMACWithSHA384
{
	[self testWithHashClass: [OFSHA384Hash class]
		 expectedDigest: SHA384Digest];
}

- (void)testHMACWithSHA512
{

	[self testWithHashClass: [OFSHA512Hash class]
		 expectedDigest: SHA512Digest];
}
@end

Renamed and modified tests/OFINIFileTests.m [793add569b] to new_tests/OFINIFileTests.m [878892df10].

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
 * 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 *module;





@implementation TestsAppDelegate (OFINIFileTests)
- (void)INIFileTests
{

	void *pool = objc_autoreleasePoolPush();












































































	OFString *output = @"[tests]\r\n"
	    @"foo=baz\r\n"
	    @"foobar=baz\r\n"
	    @";comment\r\n"
	    @"new=new\r\n"
	    @"\r\n"
	    @"[foobar]\r\n"
	    @";foobarcomment\r\n"
	    @"qux=\" asd\"\r\n"
	    @"quxquxqux=\"hello\\\"wörld\"\r\n"
	    @"qux2=\"a\\f\"\r\n"
	    @"qux3=a\fb\r\n"
	    @"\r\n"
	    @"[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";
	OFIRI *IRI;
	OFINIFile *file;
	OFINICategory *tests, *foobar, *types;


	OFArray *array;
#if defined(OF_HAVE_FILES) && !defined(OF_NINTENDO_DS)
	OFIRI *writeIRI;
#endif

	module = @"OFINIFile";

	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)

	module = @"OFINICategory";

	TEST(@"-[stringValueForKey:]",
	    [[tests stringValueForKey: @"foo"] isEqual: @"bar"] &&
	    [[foobar stringValueForKey: @"quxquxqux"] isEqual: @"hello\"wörld"])

	TEST(@"-[setStringValue:forKey:]",
	    R([tests setStringValue: @"baz" forKey: @"foo"]) &&
	    R([tests setStringValue: @"new" forKey: @"new"]) &&
	    R([foobar setStringValue: @"a\fb" forKey: @"qux3"]))

	TEST(@"-[longLongValueForKey:defaultValue:]",
	    [types longLongValueForKey: @"integer" defaultValue: 2] == 0x20)

	TEST(@"-[setLongLongValue:forKey:]",
	    R([types setLongLongValue: 0x10 forKey: @"integer"]))

	TEST(@"-[boolValueForKey:defaultValue:]",
	    [types boolValueForKey: @"bool" defaultValue: false] == true)

	TEST(@"-[setBoolValue:forKey:]",
	    R([types setBoolValue: false forKey: @"bool"]))

	TEST(@"-[floatValueForKey:defaultValue:]",
	    [types floatValueForKey: @"float" defaultValue: 1] == 0.5f)

	TEST(@"-[setFloatValue:forKey:]",
	    R([types setFloatValue: 0.25f forKey: @"float"]))

	TEST(@"-[doubleValueForKey:defaultValue:]",
	    [types doubleValueForKey: @"double" defaultValue: 3] == 0.25)

	TEST(@"-[setDoubleValue:forKey:]",
	    R([types setDoubleValue: 0.75 forKey: @"double"]))

	array = [OFArray arrayWithObjects: @"1", @"2", nil];
	TEST(@"-[arrayValueForKey:]",
	    [[types arrayValueForKey: @"array1"] isEqual: array] &&
	    [[types arrayValueForKey: @"array2"] isEqual: array] &&
	    [[types arrayValueForKey: @"array3"] isEqual: [OFArray array]])

	array = [OFArray arrayWithObjects: @"foo", @"bar", nil];
	TEST(@"-[setArrayValue:forKey:]",
	    R([types setArrayValue: array forKey: @"array1"]))

	TEST(@"-[removeValueForKey:]",
	    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)
	writeIRI = [OFSystemInfo temporaryDirectoryIRI];
	if (writeIRI == nil)
		writeIRI = [[OFFileManager defaultManager] currentDirectoryIRI];
	writeIRI = [writeIRI IRIByAppendingPathComponent: @"objfw-tests.ini"
					     isDirectory: false];
	TEST(@"-[writeToFile:encoding:]",
	    R([file writeToIRI: writeIRI
		      encoding: OFStringEncodingCodepage437]) &&



	    [[OFString stringWithContentsOfIRI: writeIRI
				      encoding: OFStringEncodingCodepage437]
	    isEqual: output])

	[[OFFileManager defaultManager] removeItemAtIRI: writeIRI];

#else
	(void)output;
#endif

	objc_autoreleasePoolPop(pool);
}
@end







|
>

|
|
>
>
>
>
|
|

>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|



















<
<
|
>
>
|




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

<
|
|
<
<








|
|
|
>
>
>
|
|
|
>
|
>

|

|
<
<

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
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#import "ObjFW.h"
#import "ObjFWTest.h"

@interface OFINIFileTests: OTTestCase
{
	OFINIFile *_file;
}
@end

@implementation OFINIFileTests
- (void)setUp
{
	OFIRI *IRI;

	[super setUp];

	IRI = [OFIRI IRIWithString: @"embedded:testfile.ini"];
	_file = [[OFINIFile alloc] initWithIRI: IRI
				      encoding: OFStringEncodingISO8859_1];
}

- (void)dealloc
{
	[_file release];

	[super dealloc];
}

- (void)testCategoryForName
{
	OTAssertNotNil([_file categoryForName: @"tests"]);
	OTAssertNotNil([_file categoryForName: @"foobar"]);
	OTAssertNotNil([_file categoryForName: @"types"]);
}

- (void)testStringValueForKey
{
	OTAssertEqualObjects(
	    [[_file categoryForName: @"tests"] stringValueForKey: @"foo"],
	    @"bar");

	OTAssertEqualObjects([[_file categoryForName: @"foobar"]
	    stringValueForKey: @"quxquxqux"],
	    @"hello\"wörld");
}

- (void)testLongLongValueForKeyDefaultValue
{
	OTAssertEqual([[_file categoryForName: @"types"]
	    longLongValueForKey: @"integer"
		   defaultValue: 2],
	    0x20);
}

- (void)testBoolValueForKeyDefaultValue
{
	OTAssertTrue([[_file categoryForName: @"types"]
	    boolValueForKey: @"bool"
	       defaultValue: false]);
}

- (void)testFloatValueForKeyDefaultValue
{
	OTAssertEqual([[_file categoryForName: @"types"]
	    floatValueForKey: @"float"
		defaultValue: 1],
	    0.5f);
}

- (void)testDoubleValueForKeyDefaultValue
{
	OTAssertEqual([[_file categoryForName: @"types"]
	    doubleValueForKey: @"double"
		 defaultValue: 3],
	    0.25);
}

- (void)testArrayValueForKey
{
	OFINICategory *types = [_file categoryForName: @"types"];
	OFArray *array = [OFArray arrayWithObjects: @"1", @"2", nil];

	OTAssertEqualObjects([types arrayValueForKey: @"array1"], array);
	OTAssertEqualObjects([types arrayValueForKey: @"array2"], array);
	OTAssertEqualObjects([types arrayValueForKey: @"array3"],
	    [OFArray array]);
}

- (void)testWriteToIRIEncoding
{
	OFString *expectedOutput = @"[tests]\r\n"
	    @"foo=baz\r\n"
	    @"foobar=baz\r\n"
	    @";comment\r\n"
	    @"new=new\r\n"
	    @"\r\n"
	    @"[foobar]\r\n"
	    @";foobarcomment\r\n"
	    @"qux=\" asd\"\r\n"
	    @"quxquxqux=\"hello\\\"wörld\"\r\n"
	    @"qux2=\"a\\f\"\r\n"
	    @"qux3=a\fb\r\n"
	    @"\r\n"
	    @"[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";


	OFINICategory *tests = [_file categoryForName: @"tests"];
	OFINICategory *foobar = [_file categoryForName: @"foobar"];
	OFINICategory *types = [_file categoryForName: @"types"];
	OFArray *array = [OFArray arrayWithObjects: @"foo", @"bar", nil];
#if defined(OF_HAVE_FILES) && !defined(OF_NINTENDO_DS)
	OFIRI *writeIRI;
#endif





















	[tests setStringValue: @"baz" forKey: @"foo"];
	[tests setStringValue: @"new" forKey: @"new"];
	[foobar setStringValue: @"a\fb" forKey: @"qux3"];





	[types setLongLongValue: 0x10 forKey: @"integer"];





	[types setBoolValue: false forKey: @"bool"];





	[types setFloatValue: 0.25f forKey: @"float"];





	[types setDoubleValue: 0.75 forKey: @"double"];









	[types setArrayValue: array forKey: @"array1"];


	[foobar removeValueForKey: @"quxqux "];
	[types removeValueForKey: @"array2"];



	/* FIXME: Find a way to write files on Nintendo DS */
#if defined(OF_HAVE_FILES) && !defined(OF_NINTENDO_DS)
	writeIRI = [OFSystemInfo temporaryDirectoryIRI];
	if (writeIRI == nil)
		writeIRI = [[OFFileManager defaultManager] currentDirectoryIRI];
	writeIRI = [writeIRI IRIByAppendingPathComponent: @"objfw-tests.ini"
					     isDirectory: false];

	[_file writeToIRI: writeIRI
		 encoding: OFStringEncodingISO8859_1];

	@try {
		OTAssertEqualObjects([OFString
		    stringWithContentsOfIRI: writeIRI
				   encoding: OFStringEncodingISO8859_1],
		    expectedOutput);
	} @finally {
		[[OFFileManager defaultManager] removeItemAtIRI: writeIRI];
	}
#else
	(void)expectedOutput;
#endif
}


@end

Renamed and modified tests/OFIRITests.m [3036a831f2] to new_tests/OFIRITests.m [f4eb7c532e].

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
 * 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 = @"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 (OFIRITests)
- (void)IRITests
{
	void *pool = objc_autoreleasePoolPush();
	OFIRI *IRI1, *IRI2, *IRI3, *IRI4, *IRI5, *IRI6, *IRI7, *IRI8, *IRI9;
	OFIRI *IRI10, *IRI11;
	OFMutableIRI *mutableIRI;

	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(@"+[IRIWithString:] fails with invalid characters #1",




	    OFInvalidFormatException,
	    [OFIRI IRIWithString: @"ht,tp://foo"])

	EXPECT_EXCEPTION(@"+[IRIWithString:] fails with invalid characters #2",

	    OFInvalidFormatException,
	    [OFIRI IRIWithString: @"http://f`oo"])

	EXPECT_EXCEPTION(@"+[IRIWithString:] fails with invalid characters #3",
	    OFInvalidFormatException,
	    [OFIRI IRIWithString: @"http://foo/`"])

	EXPECT_EXCEPTION(@"+[IRIWithString:] fails with invalid characters #4",
	    OFInvalidFormatException,

	    [OFIRI IRIWithString: @"http://foo/foo?`"])


	EXPECT_EXCEPTION(@"+[IRIWithString:] fails with invalid characters #5",
	    OFInvalidFormatException,

	    [OFIRI IRIWithString: @"http://foo/foo?foo#`"])


	EXPECT_EXCEPTION(@"+[IRIWithString:] fails with invalid characters #6",
	    OFInvalidFormatException,
	    [OFIRI IRIWithString: @"https://[g]/"])

	EXPECT_EXCEPTION(@"+[IRIWithString:] fails with invalid characters #7",
	    OFInvalidFormatException,

	    [OFIRI IRIWithString: @"https://[f]:/"])


	EXPECT_EXCEPTION(@"+[IRIWithString:] fails with invalid characters #8",
	    OFInvalidFormatException,
	    [OFIRI IRIWithString: @"https://[f]:f/"])

	EXPECT_EXCEPTION(@"+[IRIWithString:] fails with invalid characters #9",
	    OFInvalidFormatException,
	    [OFIRI IRIWithString: @"foo:"])

	TEST(@"+[IRIWithString:relativeToIRI:]",
	    [[[OFIRI IRIWithString: @"/foo" relativeToIRI: IRI1] string]
	    isEqual: @"ht+tp://us%3Aer:p%40w@ho%3Ast:1234/foo"] &&


	    [[[OFIRI IRIWithString: @"foo/bar?q"
		     relativeToIRI: [OFIRI IRIWithString: @"http://h/qux/quux"]]

	    string] isEqual: @"http://h/qux/foo/bar?q"] &&


	    [[[OFIRI IRIWithString: @"foo/bar"
		     relativeToIRI: [OFIRI IRIWithString: @"http://h/qux/?x"]]

	    string] isEqual: @"http://h/qux/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"] &&


	    [[[OFIRI IRIWithString: @"foo"
		     relativeToIRI: [OFIRI IRIWithString: @"http://foo"]]

	    string] isEqual: @"http://foo/foo"])

	EXPECT_EXCEPTION(
	    @"+[IRIWithString:relativeToIRI:] fails with invalid characters #1",
	    OFInvalidFormatException,
	    [OFIRI IRIWithString: @"`" relativeToIRI: IRI1])

	EXPECT_EXCEPTION(

	    @"+[IRIWithString:relativeToIRI:] fails with invalid characters #2",
	    OFInvalidFormatException,
	    [OFIRI IRIWithString: @"/`" relativeToIRI: IRI1])

	EXPECT_EXCEPTION(

	    @"+[IRIWithString:relativeToIRI:] fails with invalid characters #3",
	    OFInvalidFormatException,
	    [OFIRI IRIWithString: @"?`" relativeToIRI: IRI1])

	EXPECT_EXCEPTION(
	    @"+[IRIWithString:relativeToIRI:] fails with invalid characters #4",
	    OFInvalidFormatException,


	    [OFIRI IRIWithString: @"#`" relativeToIRI: IRI1])



#ifdef OF_HAVE_FILES
	TEST(@"+[fileIRIWithPath:]",


	    [[[OFIRI fileIRIWithPath: @"testfile.txt"] fileSystemRepresentation]
	    isEqual: [[OFFileManager defaultManager].currentDirectoryPath
	    stringByAppendingPathComponent: @"testfile.txt"]])


# if defined(OF_WINDOWS) || defined(OF_MSDOS)
	OFIRI *tmp;
	TEST(@"+[fileIRIWithPath:] for c:\\",

	    (tmp = [OFIRI fileIRIWithPath: @"c:\\"]) &&
	    [tmp.string isEqual: @"file:/c:/"] &&
	    [tmp.fileSystemRepresentation isEqual: @"c:\\"])

# endif

# ifdef OF_WINDOWS
	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 = [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]",

	    [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]",








	    [IRI1.scheme isEqual: @"ht+tp"] && [IRI4.scheme isEqual: @"file"] &&







	    [IRI9.scheme isEqual: @"file"] && [IRI10.scheme isEqual: @"file"] &&







	    [IRI11.scheme isEqual: @"http"])



















































	TEST(@"-[user]", [IRI1.user isEqual: @"us:er"] && IRI4.user == nil &&
	    IRI10.user == nil && IRI11.user == nil)
	TEST(@"-[password]",
	    [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]",
	    [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]",
	    [IRI1.pathComponents isEqual:
	    [OFArray arrayWithObjects: @"/", @"pa?th", nil]] &&
	    [IRI4.pathComponents isEqual:
	    [OFArray arrayWithObjects: @"/", @"etc", @"passwd", nil]] &&
	    [IRI5.pathComponents isEqual:
	    [OFArray arrayWithObjects: @"/", @"bar", @"qux", @"foo/bar", nil]])
	TEST(@"-[lastPathComponent]",
	    [[[OFIRI IRIWithString: @"http://host/foo//bar/baz"]
	    lastPathComponent] isEqual: @"baz"] &&

	    [[[OFIRI IRIWithString: @"http://host/foo//bar/baz/"]
	    lastPathComponent] isEqual: @"baz"] &&
	    [[[OFIRI IRIWithString: @"http://host/foo/"]
	    lastPathComponent] isEqual: @"foo"] &&
	    [[[OFIRI IRIWithString: @"http://host/"]
	    lastPathComponent] isEqual: @"/"] &&

	    [IRI5.lastPathComponent isEqual: @"foo/bar"])
	TEST(@"-[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]",


	    [IRI1.queryItems isEqual: [OFArray arrayWithObjects:
	    [OFPair pairWithFirstObject: @"que#ry" secondObject: @"1"],
	    [OFPair pairWithFirstObject: @"f&oo" secondObject: @"b=ar"], nil]]);


	TEST(@"-[fragment]",

	    [IRI1.fragment isEqual: @"frag#ment"] && IRI4.fragment == nil &&
	    [IRI9.fragment isEqual: @"frag"] &&



	    [IRI10.fragment isEqual: @"frag"])


	TEST(@"-[copy]", R(IRI4 = [[IRI1 copy] autorelease]))

	TEST(@"-[isEqual:]", [IRI1 isEqual: IRI4] && ![IRI2 isEqual: IRI3] &&




	    [[OFIRI IRIWithString: @"HTTP://bar/"] isEqual: IRI3])

	TEST(@"-[hash:]", IRI1.hash == IRI4.hash && IRI2.hash != IRI3.hash)





	EXPECT_EXCEPTION(@"Detection of invalid format",



	    OFInvalidFormatException, [OFIRI IRIWithString: @"http"])

	TEST(@"-[IRIByAddingPercentEncodingForUnicodeCharacters]",
	    [IRI11.IRIByAddingPercentEncodingForUnicodeCharacters
	    isEqual: [OFIRI IRIWithString: @"http://%C3%A4/%C3%B6?%C3%BC"]])

	mutableIRI = [OFMutableIRI IRIWithScheme: @"dummy"];

	EXPECT_EXCEPTION(
	    @"-[setPercentEncodedScheme:] with invalid characters fails",
	    OFInvalidFormatException, mutableIRI.scheme = @"%20")


	TEST(@"-[setHost:]",








	    (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:]",
	    (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,
	    mutableIRI.percentEncodedHost = @"/")


	EXPECT_EXCEPTION(
	    @"-[setPercentEncodedHost:] with invalid characters fails #2",


	    OFInvalidFormatException,
	    mutableIRI.percentEncodedHost = @"[12:34")

	EXPECT_EXCEPTION(
	    @"-[setPercentEncodedHost:] with invalid characters fails #3",
	    OFInvalidFormatException,

	    mutableIRI.percentEncodedHost = @"[a::g]")


	TEST(@"-[setUser:]",


	    (mutableIRI.user = @"us:er") &&
	    [mutableIRI.percentEncodedUser isEqual: @"us%3Aer"])


	TEST(@"-[setPercentEncodedUser:]",

	    (mutableIRI.percentEncodedUser = @"us%3Aer") &&
	    [mutableIRI.user isEqual: @"us:er"])

	EXPECT_EXCEPTION(
	    @"-[setPercentEncodedUser:] with invalid characters fails",


	    OFInvalidFormatException,
	    mutableIRI.percentEncodedHost = @"/")


	TEST(@"-[setPassword:]",

	    (mutableIRI.password = @"pass:word") &&
	    [mutableIRI.percentEncodedPassword isEqual: @"pass%3Aword"])



	TEST(@"-[setPercentEncodedPassword:]",

	    (mutableIRI.percentEncodedPassword = @"pass%3Aword") &&
	    [mutableIRI.password isEqual: @"pass:word"])

	EXPECT_EXCEPTION(
	    @"-[setPercentEncodedPassword:] with invalid characters fails",


	    OFInvalidFormatException,
	    mutableIRI.percentEncodedPassword = @"/")

	TEST(@"-[setPath:]",


	    (mutableIRI.path = @"pa/th@?") &&
	    [mutableIRI.percentEncodedPath isEqual: @"pa/th@%3F"])


	TEST(@"-[setPercentEncodedPath:]",

	    (mutableIRI.percentEncodedPath = @"pa/th@%3F") &&
	    [mutableIRI.path isEqual: @"pa/th@?"])

	EXPECT_EXCEPTION(
	    @"-[setPercentEncodedPath:] with invalid characters fails",


	    OFInvalidFormatException,
	    mutableIRI.percentEncodedPath = @"?")


	TEST(@"-[setQuery:]",

	    (mutableIRI.query = @"que/ry?#") &&
	    [mutableIRI.percentEncodedQuery isEqual: @"que/ry?%23"])


	TEST(@"-[setPercentEncodedQuery:]",

	    (mutableIRI.percentEncodedQuery = @"que/ry?%23") &&
	    [mutableIRI.query isEqual: @"que/ry?#"])

	EXPECT_EXCEPTION(
	    @"-[setPercentEncodedQuery:] with invalid characters fails",


	    OFInvalidFormatException,
	    mutableIRI.percentEncodedQuery = @"`")


	TEST(@"-[setQueryItems:]",

	    (mutableIRI.queryItems = [OFArray arrayWithObjects:
	    [OFPair pairWithFirstObject: @"foo&bar" secondObject: @"baz=qux"],
	    [OFPair pairWithFirstObject: @"f=oobar" secondObject: @"b&azqux"],

	    nil]) && [mutableIRI.percentEncodedQuery isEqual:
	    @"foo%26bar=baz%3Dqux&f%3Doobar=b%26azqux"])


	TEST(@"-[setFragment:]",

	    (mutableIRI.fragment = @"frag/ment?#") &&
	    [mutableIRI.percentEncodedFragment isEqual: @"frag/ment?%23"])



	TEST(@"-[setPercentEncodedFragment:]",

	    (mutableIRI.percentEncodedFragment = @"frag/ment?%23") &&
	    [mutableIRI.fragment isEqual: @"frag/ment?#"])

	EXPECT_EXCEPTION(
	    @"-[setPercentEncodedFragment:] with invalid characters fails",


	    OFInvalidFormatException,
	    mutableIRI.percentEncodedFragment = @"`")


	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(@"-[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







|
>

>
>
>
>
>
>
|
|


|
|

|
<
<
<

<
|
|
|
|
>
|
|
>
|
|
|
>
|
|

>
>
|
>
>
>
>
|
|

|
>
|
|
|
|
|
<

|
|
>
|
>

|
|
>
|
>

|
|
<

|
|
>
|
>

|
|
<
|
|
<
|
|
|
|
|
>
>
|
|
>
|
>
>
|
|
>
|
>
|
>
|
>
>
|
|
>
|
>
>
|
|
>
|
|
|
<
<
|
|
<
>
|
|
<

<
>
|
|
<

|
|
|
>
>
|
>
>


|
>
>
|
|
|
|
>

<
|
>
|
|
|
>



|
>
>
>
|
|
|
|
|
>
|
|
>
|
|
>



|
>
|
|
|
|
|
|
|
|
|
|
|
|
|
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

<
<
<
<
<
<
|
<
<
|
<
<
<
|
|
|
|
|
|
|
|
<
<
<
<
<
<
<
<
<
|
>
|
<
<
<
<
|
>
|
|
>
|
>
|
>
>
>
|
|
>
>
|

|
>
>
|
>
|
|
>
>
>
|
>
|
|
|
|
>
>
>
>
|
|
|
>
|
>
>
>
|
>
>
>
|
|
|
|
<
|
<
|
<
|
<
>
|
|
>
>
>
>
>
>
>
>
|
|
>
|
|
|
<
|
|

<
<
|
|
>
|
>
>
|
|

<
|
>
|
|
>
|
|
|
>
>
|
<

<
|
|
>
|
>
|
|
>
>
|
|
|
>
|
>
|
|
|
|
|
>
>
|
<
|
>
|
>
|
|
>
|
>
|
>
|
|
|
|
|
>
>
|
<
|
|
>
>
|
|
|
>
|
>
|
|
|
|
|
>
>
|
<
|
>
|
>
|
|
|
>
|
>
|
|
|
|
|
>
>
|
<
|
>
|
>
|


>
|
|
|
>
|
>
|
|
>
|
>
|
>
|
|
|
|
|
>
>
|
<
|
>
|
>
|
|
>
|
>
|
>
|
|
>
|
|
>
|
>
|
|
>
|
|
>
|
>
|
|
|
>
>
|
|
|
>
>
|
|
|
>
|
|
|
<
<


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
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
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#import "ObjFW.h"
#import "ObjFWTest.h"

@interface OFIRITests: OTTestCase
{
	OFIRI *_IRI[11];
	OFMutableIRI *_mutableIRI;
}
@end

static OFString *IRI0String = @"ht+tp://us%3Aer:p%40w@ho%3Ast:1234/"
    @"pa%3Fth?que%23ry=1&f%26oo=b%3dar#frag%23ment";

@implementation OFIRITests
- (void)setUp
{
	[super setUp];





	_IRI[0] = [[OFIRI alloc] initWithString: IRI0String];
	_IRI[1] = [[OFIRI alloc] initWithString: @"http://foo:80"];
	_IRI[2] = [[OFIRI alloc] initWithString: @"http://bar/"];
	_IRI[3] = [[OFIRI alloc] initWithString: @"file:///etc/passwd"];
	_IRI[4] = [[OFIRI alloc]
	    initWithString: @"http://foo/bar/qux/foo%2fbar"];
	_IRI[5] = [[OFIRI alloc] initWithString: @"https://[12:34::56:abcd]/"];
	_IRI[6] = [[OFIRI alloc]
	    initWithString: @"https://[12:34::56:abcd]:234/"];
	_IRI[7] = [[OFIRI alloc] initWithString: @"urn:qux:foo"];
	_IRI[8] = [[OFIRI alloc] initWithString: @"file:/foo?query#frag"];
	_IRI[9] = [[OFIRI alloc]
	    initWithString: @"file:foo@bar/qux?query#frag"];
	_IRI[10] = [[OFIRI alloc] initWithString: @"http://ä/ö?ü"];

	_mutableIRI = [[OFMutableIRI alloc] initWithScheme: @"dummy"];
}

- (void)dealloc
{
	for (uint_fast8_t i = 0; i < 11; i++)
		[_IRI[i] release];

	[_mutableIRI release];

	[super dealloc];
}

- (void)testIRIWithStringFailsWithInvalidCharacters
{
	OTAssertThrowsSpecific([OFIRI IRIWithString: @"ht,tp://foo"],
	    OFInvalidFormatException);


	OTAssertThrowsSpecific([OFIRI IRIWithString: @"http://f`oo"],
	    OFInvalidFormatException);

	OTAssertThrowsSpecific([OFIRI IRIWithString: @"http://foo/`"],
	    OFInvalidFormatException);

	OTAssertThrowsSpecific([OFIRI IRIWithString: @"http://foo/foo?`"],
	    OFInvalidFormatException);

	OTAssertThrowsSpecific([OFIRI IRIWithString: @"http://foo/foo?foo#`"],
	    OFInvalidFormatException);

	OTAssertThrowsSpecific([OFIRI IRIWithString: @"https://[g]/"],
	    OFInvalidFormatException);


	OTAssertThrowsSpecific([OFIRI IRIWithString: @"https://[f]:/"],
	    OFInvalidFormatException);

	OTAssertThrowsSpecific([OFIRI IRIWithString: @"https://[f]:f/"],
	    OFInvalidFormatException);

	OTAssertThrowsSpecific([OFIRI IRIWithString: @"foo:"],
	    OFInvalidFormatException);

}


- (void)testIRIWithStringRelativeToIRI
{
	OTAssertEqualObjects([[OFIRI IRIWithString: @"/foo"
				     relativeToIRI: _IRI[0]] string],
	    @"ht+tp://us%3Aer:p%40w@ho%3Ast:1234/foo");

	OTAssertEqualObjects(
	    [[OFIRI IRIWithString: @"foo/bar?q"
		    relativeToIRI: [OFIRI IRIWithString: @"http://h/qux/quux"]]
	    string],
	    @"http://h/qux/foo/bar?q");

	OTAssertEqualObjects(
	    [[OFIRI IRIWithString: @"foo/bar"
		    relativeToIRI: [OFIRI IRIWithString: @"http://h/qux/?x"]]
	    string],
	    @"http://h/qux/foo/bar");

	OTAssertEqualObjects([[OFIRI IRIWithString: @"http://foo/?q"
				     relativeToIRI: _IRI[0]] string],
	    @"http://foo/?q");

	OTAssertEqualObjects(
	    [[OFIRI IRIWithString: @"foo"
		    relativeToIRI: [OFIRI IRIWithString: @"http://foo/bar"]]
	    string],
	    @"http://foo/foo");

	OTAssertEqualObjects(
	    [[OFIRI IRIWithString: @"foo"
		    relativeToIRI: [OFIRI IRIWithString: @"http://foo"]]
	    string],
	    @"http://foo/foo");
}



- (void)testIRIWithStringRelativeToIRIFailsWithInvalidCharacters
{

	OTAssertThrowsSpecific(
	    [OFIRI IRIWithString: @"`" relativeToIRI: _IRI[0]],
	    OFInvalidFormatException);



	OTAssertThrowsSpecific(
	    [OFIRI IRIWithString: @"/`" relativeToIRI: _IRI[0]],
	    OFInvalidFormatException);


	OTAssertThrowsSpecific(
	    [OFIRI IRIWithString: @"?`" relativeToIRI: _IRI[0]],
	    OFInvalidFormatException);

	OTAssertThrowsSpecific(
	    [OFIRI IRIWithString: @"#`" relativeToIRI: _IRI[0]],
	    OFInvalidFormatException);
}

#ifdef OF_HAVE_FILES
- (void)testFileIRIWithPath
{
	OTAssertEqualObjects(
	    [[OFIRI fileIRIWithPath: @"testfile.txt"] fileSystemRepresentation],
	    [[OFFileManager defaultManager].currentDirectoryPath
	    stringByAppendingPathComponent: @"testfile.txt"]);
}

# if defined(OF_WINDOWS) || defined(OF_MSDOS)

- (void)testFileIRWithPathC
{
	OFIRI *IRI = [OFIRI fileIRIWithPath: @"c:\\"];
	OTAssertEqualObjects(IRI.string, @"file:/c:/");
	OTAssertEqualObjects(IRI.fileSystemRepresentation, @"c:\\");
}
# endif

# ifdef OF_WINDOWS
- (void)testFileIRIWithPathUNC
{
	OFIRI *IRI;

	IRI = [OFIRI fileIRIWithPath: @"\\\\foo\\bar" isDirectory: false];
	OTAssertEqualObjects(IRI.host, @"foo");
	OTAssertEqualObjects(IRI.path, @"/bar");
	OTAssertEqualObjects(IRI.string, @"file://foo/bar");
	OTAssertEqualObjects(IRI.fileSystemRepresentation, @"\\\\foo\\bar");

	IRI = [OFIRI fileIRIWithPath: @"\\\\test" isDirectory: true];
	OTAssertEqualObjects(IRI.host, @"test");
	OTAssertEqualObjects(IRI.path, @"/");
	OTAssertEqualObjects(IRI.string, @"file://test/");
	OTAssertEqualObjects(IRI.fileSystemRepresentation, @"\\\\test");
}
# endif
#endif

- (void)testString
{
	OTAssertEqualObjects(_IRI[0].string, IRI0String);
	OTAssertEqualObjects(_IRI[1].string, @"http://foo:80");
	OTAssertEqualObjects(_IRI[2].string, @"http://bar/");
	OTAssertEqualObjects(_IRI[3].string, @"file:///etc/passwd");
	OTAssertEqualObjects(_IRI[4].string, @"http://foo/bar/qux/foo%2fbar");
	OTAssertEqualObjects(_IRI[5].string, @"https://[12:34::56:abcd]/");
	OTAssertEqualObjects(_IRI[6].string, @"https://[12:34::56:abcd]:234/");
	OTAssertEqualObjects(_IRI[7].string, @"urn:qux:foo");
	OTAssertEqualObjects(_IRI[8].string, @"file:/foo?query#frag");
	OTAssertEqualObjects(_IRI[9].string, @"file:foo@bar/qux?query#frag");
	OTAssertEqualObjects(_IRI[10].string, @"http://ä/ö?ü");
}

- (void)testScheme
{
	OTAssertEqualObjects(_IRI[0].scheme, @"ht+tp");
	OTAssertEqualObjects(_IRI[3].scheme, @"file");
	OTAssertEqualObjects(_IRI[8].scheme, @"file");
	OTAssertEqualObjects(_IRI[9].scheme, @"file");
	OTAssertEqualObjects(_IRI[10].scheme, @"http");
}

- (void)testUser
{
	OTAssertEqualObjects(_IRI[0].user, @"us:er");
	OTAssertNil(_IRI[3].user);
	OTAssertNil(_IRI[9].user);
	OTAssertNil(_IRI[10].user);
}

- (void)testPassword
{
	OTAssertEqualObjects(_IRI[0].password, @"p@w");
	OTAssertNil(_IRI[3].password);
	OTAssertNil(_IRI[9].password);
	OTAssertNil(_IRI[10].password);
}

- (void)testHost
{
	OTAssertEqualObjects(_IRI[0].host, @"ho:st");
	OTAssertEqualObjects(_IRI[5].host, @"12:34::56:abcd");
	OTAssertEqualObjects(_IRI[6].host, @"12:34::56:abcd");
	OTAssertNil(_IRI[7].host);
	OTAssertNil(_IRI[8].host);
	OTAssertNil(_IRI[9].host);
	OTAssertEqualObjects(_IRI[10].host, @"ä");
}

- (void)testPort
{
	OTAssertEqual(_IRI[0].port.unsignedShortValue, 1234);
	OTAssertNil(_IRI[3].port);
	OTAssertEqual(_IRI[6].port.unsignedShortValue, 234);
	OTAssertNil(_IRI[7].port);
	OTAssertNil(_IRI[8].port);
	OTAssertNil(_IRI[9].port);
	OTAssertNil(_IRI[10].port);
}

- (void)testPath
{
	OTAssertEqualObjects(_IRI[0].path, @"/pa?th");
	OTAssertEqualObjects(_IRI[3].path, @"/etc/passwd");
	OTAssertEqualObjects(_IRI[7].path, @"qux:foo");
	OTAssertEqualObjects(_IRI[8].path, @"/foo");
	OTAssertEqualObjects(_IRI[9].path, @"foo@bar/qux");
	OTAssertEqualObjects(_IRI[10].path, @"/ö");
}

- (void)testPathComponents
{
	OTAssertEqualObjects(_IRI[0].pathComponents,
	    ([OFArray arrayWithObjects: @"/", @"pa?th", nil]));

	OTAssertEqualObjects(_IRI[3].pathComponents,
	    ([OFArray arrayWithObjects: @"/", @"etc", @"passwd", nil]));

	OTAssertEqualObjects(_IRI[4].pathComponents,
	    ([OFArray arrayWithObjects: @"/", @"bar", @"qux", @"foo/bar",
	    nil]));
}

- (void)testLastPathComponent
{
	OTAssertEqualObjects([[OFIRI IRIWithString: @"http://host/foo//bar/baz"]
	    lastPathComponent],
	    @"baz");







	OTAssertEqualObjects(


	    [[OFIRI IRIWithString: @"http://host/foo//bar/baz/"]



	    lastPathComponent],
	    @"baz");

	OTAssertEqualObjects([[OFIRI IRIWithString: @"http://host/foo/"]
	    lastPathComponent],
	    @"foo");

	OTAssertEqualObjects([[OFIRI IRIWithString: @"http://host/"]









	    lastPathComponent],
	    @"/");





	OTAssertEqualObjects(_IRI[4].lastPathComponent, @"foo/bar");
}

- (void)testQuery
{
	OTAssertEqualObjects(_IRI[0].query, @"que#ry=1&f&oo=b=ar");
	OTAssertNil(_IRI[3].query);
	OTAssertEqualObjects(_IRI[8].query, @"query");
	OTAssertEqualObjects(_IRI[9].query, @"query");
	OTAssertEqualObjects(_IRI[10].query, @"ü");
}

- (void)testQueryItems
{
	OTAssertEqualObjects(_IRI[0].queryItems,
	    ([OFArray arrayWithObjects:
	    [OFPair pairWithFirstObject: @"que#ry" secondObject: @"1"],
	    [OFPair pairWithFirstObject: @"f&oo" secondObject: @"b=ar"], nil]));
}

- (void)testFragment
{
	OTAssertEqualObjects(_IRI[0].fragment, @"frag#ment");
	OTAssertNil(_IRI[3].fragment);
	OTAssertEqualObjects(_IRI[8].fragment, @"frag");
	OTAssertEqualObjects(_IRI[9].fragment, @"frag");
}

- (void)testCopy
{
	OTAssertEqualObjects(_IRI[0], [[_IRI[0] copy] autorelease]);
}

- (void)testIsEqual
{
	OTAssertEqualObjects(_IRI[0], [OFIRI IRIWithString: IRI0String]);
	OTAssertNotEqualObjects(_IRI[1], _IRI[2]);
	OTAssertEqualObjects([OFIRI IRIWithString: @"HTTP://bar/"], _IRI[2]);
}

- (void)testHash
{
	OTAssertEqual(_IRI[0].hash, [[OFIRI IRIWithString: IRI0String] hash]);
	OTAssertNotEqual(_IRI[1].hash, _IRI[2].hash);
}

- (void)testIRIWithStringFailsWithInvalidFormat
{
	OTAssertThrowsSpecific([OFIRI IRIWithString: @"http"],
	    OFInvalidFormatException);
}

- (void)testIRIByAddingPercentEncodingForUnicodeCharacters

{

	OTAssertEqualObjects(

	    _IRI[10].IRIByAddingPercentEncodingForUnicodeCharacters,

	    [OFIRI IRIWithString: @"http://%C3%A4/%C3%B6?%C3%BC"]);
}

- (void)testSetPercentEncodedSchemeFailsWithInvalidCharacters
{
	OTAssertThrowsSpecific(_mutableIRI.scheme = @"%20",
	    OFInvalidFormatException);
}

- (void)testSetHost
{
	_mutableIRI.host = @"ho:st";
	OTAssertEqualObjects(_mutableIRI.percentEncodedHost, @"ho%3Ast");

	_mutableIRI.host = @"12:34:ab";
	OTAssertEqualObjects(_mutableIRI.percentEncodedHost, @"[12:34:ab]");


	_mutableIRI.host = @"12:34:aB";
	OTAssertEqualObjects(_mutableIRI.percentEncodedHost, @"[12:34:aB]");



	_mutableIRI.host = @"12:34:g";
	OTAssertEqualObjects(_mutableIRI.percentEncodedHost, @"12%3A34%3Ag");
}

- (void)testSetPercentEncodedHost
{
	_mutableIRI.percentEncodedHost = @"ho%3Ast";
	OTAssertEqualObjects(_mutableIRI.host, @"ho:st");


	_mutableIRI.percentEncodedHost = @"[12:34]";
	OTAssertEqualObjects(_mutableIRI.host, @"12:34");

	_mutableIRI.percentEncodedHost = @"[12::ab]";
	OTAssertEqualObjects(_mutableIRI.host, @"12::ab");
}

- (void)testSetPercentEncodedHostFailsWithInvalidCharacters
{
	OTAssertThrowsSpecific(_mutableIRI.percentEncodedHost = @"/",
	    OFInvalidFormatException);



	OTAssertThrowsSpecific(_mutableIRI.percentEncodedHost = @"[12:34",
	    OFInvalidFormatException);

	OTAssertThrowsSpecific(_mutableIRI.percentEncodedHost = @"[a::g]",
	    OFInvalidFormatException);
}

- (void)testSetUser
{
	_mutableIRI.user = @"us:er";
	OTAssertEqualObjects(_mutableIRI.percentEncodedUser, @"us%3Aer");
}

- (void)testSetPercentEncodedUser
{
	_mutableIRI.percentEncodedUser = @"us%3Aer";
	OTAssertEqualObjects(_mutableIRI.user, @"us:er");
}

- (void)testSetPercentEncodedUserFailsWithInvalidCharacters
{
	OTAssertThrowsSpecific(_mutableIRI.percentEncodedHost = @"/",
	    OFInvalidFormatException);

}

- (void)testSetPassword
{
	_mutableIRI.password = @"pass:word";
	OTAssertEqualObjects(_mutableIRI.percentEncodedPassword,
	    @"pass%3Aword");
}

- (void)testSetPercentEncodedPassword
{
	_mutableIRI.percentEncodedPassword = @"pass%3Aword";
	OTAssertEqualObjects(_mutableIRI.password, @"pass:word");
}

- (void)testSetPercentEncodedPasswordFailsWithInvalidCharacters
{
	OTAssertThrowsSpecific(_mutableIRI.percentEncodedPassword = @"/",
	    OFInvalidFormatException);

}

- (void)testSetPath
{
	_mutableIRI.path = @"pa/th@?";
	OTAssertEqualObjects(_mutableIRI.percentEncodedPath, @"pa/th@%3F");
}

- (void)testSetPercentEncodedPath
{
	_mutableIRI.percentEncodedPath = @"pa/th@%3F";
	OTAssertEqualObjects(_mutableIRI.path, @"pa/th@?");
}

- (void)testSetPercentEncodedPathFailsWithInvalidCharacters
{
	OTAssertThrowsSpecific(_mutableIRI.percentEncodedPath = @"?",
	    OFInvalidFormatException);

}

- (void)testSetQuery
{
	_mutableIRI.query = @"que/ry?#";
	OTAssertEqualObjects(_mutableIRI.percentEncodedQuery, @"que/ry?%23");
}

- (void)testSetPercentEncodedQuery
{
	_mutableIRI.percentEncodedQuery = @"que/ry?%23";
	OTAssertEqualObjects(_mutableIRI.query, @"que/ry?#");
}

- (void)testSetPercentEncodedQueryFailsWithInvalidCharacters
{
	OTAssertThrowsSpecific(_mutableIRI.percentEncodedQuery = @"`",
	    OFInvalidFormatException);

}

- (void)testSetQueryItems
{
	_mutableIRI.queryItems = [OFArray arrayWithObjects:
	    [OFPair pairWithFirstObject: @"foo&bar" secondObject: @"baz=qux"],
	    [OFPair pairWithFirstObject: @"f=oobar" secondObject: @"b&azqux"],
	    nil];
	OTAssertEqualObjects(_mutableIRI.percentEncodedQuery,
	    @"foo%26bar=baz%3Dqux&f%3Doobar=b%26azqux");
}

- (void)testSetFragment
{
	_mutableIRI.fragment = @"frag/ment?#";
	OTAssertEqualObjects(_mutableIRI.percentEncodedFragment,
	    @"frag/ment?%23");
}

- (void)testSetPercentEncodedFragment
{
	_mutableIRI.percentEncodedFragment = @"frag/ment?%23";
	OTAssertEqualObjects(_mutableIRI.fragment, @"frag/ment?#");
}

- (void)testSetPercentEncodedFragmentFailsWithInvalidCharacters
{
	OTAssertThrowsSpecific(_mutableIRI.percentEncodedFragment = @"`",
	    OFInvalidFormatException);

}

-(void)testIRIByAppendingPathComponentIsDirectory
{
	OTAssertEqualObjects([[OFIRI IRIWithString: @"file:///foo/bar"]
	    IRIByAppendingPathComponent: @"qux"
			    isDirectory: false],
	    [OFIRI IRIWithString: @"file:///foo/bar/qux"]);

	OTAssertEqualObjects([[OFIRI IRIWithString: @"file:///foo/bar/"]
	    IRIByAppendingPathComponent: @"qux"
			    isDirectory: false],
	    [OFIRI IRIWithString: @"file:///foo/bar/qux"]);

	OTAssertEqualObjects([[OFIRI IRIWithString: @"file:///foo/bar/"]
	    IRIByAppendingPathComponent: @"qu?x"
			    isDirectory: false],
	    [OFIRI IRIWithString: @"file:///foo/bar/qu%3Fx"]);

	OTAssertEqualObjects([[OFIRI IRIWithString: @"file:///foo/bar/"]
	    IRIByAppendingPathComponent: @"qu?x"
			    isDirectory: true],
	    [OFIRI IRIWithString: @"file:///foo/bar/qu%3Fx/"]);
}

- (void)testIRIByStandardizingPath
{
	OTAssertEqualObjects([[OFIRI IRIWithString: @"http://foo/bar/.."]
	    IRIByStandardizingPath],
	    [OFIRI IRIWithString: @"http://foo/"]);

	OTAssertEqualObjects(
	    [[OFIRI IRIWithString: @"http://foo/bar/%2E%2E/../qux/"]
	    IRIByStandardizingPath],
	    [OFIRI IRIWithString: @"http://foo/bar/qux/"]);

	OTAssertEqualObjects(
	    [[OFIRI IRIWithString: @"http://foo/bar/./././qux/./"]
	    IRIByStandardizingPath],
	    [OFIRI IRIWithString: @"http://foo/bar/qux/"]);

	OTAssertEqualObjects([[OFIRI IRIWithString: @"http://foo/bar/../../qux"]
	    IRIByStandardizingPath],
	    [OFIRI IRIWithString: @"http://foo/../qux"]);


}
@end

Renamed and modified tests/OFInvocationTests.m [23f57f7d3a] to new_tests/OFInvocationTests.m [11b71f5c4f].

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

#include <string.h>

#if defined(HAVE_COMPLEX_H) && !defined(__STDC_NO_COMPLEX__)
# include <complex.h>
#endif

#import "TestsAppDelegate.h"




static OFString *const module = @"OFInvocation";



struct TestStruct {
	unsigned char c;
	unsigned int i;
};

@implementation TestsAppDelegate (OFInvocationTests)
- (struct TestStruct)invocationTestMethod1: (unsigned char)c
					  : (unsigned int)i
					  : (struct TestStruct *)ptr
					  : (struct TestStruct)st
{
	return st;
}

- (void)invocationTests
{

	void *pool = objc_autoreleasePoolPush();
	SEL selector = @selector(invocationTestMethod1::::);

	OFMethodSignature *sig = [self methodSignatureForSelector: selector];






	OFInvocation *invocation;






	struct TestStruct st, st2, *stp = &st, *stp2;














	unsigned const char c = 0xAA;
	unsigned char c2;
	const unsigned int i = 0x55555555;
	unsigned int i2;

	memset(&st, '\xFF', sizeof(st));
	st.c = 0x55;
	st.i = 0xAAAAAAAA;

	TEST(@"+[invocationWithMethodSignature:]",
	    (invocation = [OFInvocation invocationWithMethodSignature: sig]))

	TEST(@"-[setReturnValue]", R([invocation setReturnValue: &st]))

	TEST(@"-[getReturnValue]", R([invocation getReturnValue: &st2]) &&
	    memcmp(&st, &st2, sizeof(st)) == 0)

	memset(&st2, '\0', sizeof(st2));

	TEST(@"-[setArgument:atIndex:] #1",
	    R([invocation setArgument: &c atIndex: 2]))

	TEST(@"-[setArgument:atIndex:] #2",
	    R([invocation setArgument: &i atIndex: 3]))

	TEST(@"-[setArgument:atIndex:] #3",
	    R([invocation setArgument: &stp atIndex: 4]))

	TEST(@"-[setArgument:atIndex:] #4",
	    R([invocation setArgument: &st atIndex: 5]))

	TEST(@"-[getArgument:atIndex:] #1",
	    R([invocation getArgument: &c2 atIndex: 2]) && c == c2)


	TEST(@"-[getArgument:atIndex:] #2",
	    R([invocation getArgument: &i2 atIndex: 3]) && i == i2)


	TEST(@"-[getArgument:atIndex:] #3",
	    R([invocation getArgument: &stp2 atIndex: 4]) && stp == stp2)


	TEST(@"-[getArgument:atIndex:] #4",
	    R([invocation getArgument: &st2 atIndex: 5]) &&
	    memcmp(&st, &st2, sizeof(st)) == 0)

	objc_autoreleasePoolPop(pool);
}
@end







|
>

>
>
|
>
>






|


|
|

|


|

>
|

>
|
>
>
>
>
>
>
|
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>





|
|
|

<
<
|
<

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

<
|
>

<
|
>

<
|
>

<
|
<
|
<


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

#include <string.h>

#if defined(HAVE_COMPLEX_H) && !defined(__STDC_NO_COMPLEX__)
# include <complex.h>
#endif

#import "ObjFW.h"
#import "ObjFWTest.h"

@interface OFInvocationTests: OTTestCase
{
	OFInvocation *_invocation;
}
@end

struct TestStruct {
	unsigned char c;
	unsigned int i;
};

@implementation OFInvocationTests
- (struct TestStruct)invocationTestMethod1: (unsigned char)c
					  : (unsigned int)i
					  : (struct TestStruct *)testStructPtr
					  : (struct TestStruct)testStruct
{
	return testStruct;
}

- (void)setUp
{
	[super setUp];

	SEL selector = @selector(invocationTestMethod1::::);
	OFMethodSignature *signature =
	    [self methodSignatureForSelector: selector];

	_invocation = [[OFInvocation alloc] initWithMethodSignature: signature];
}

- (void)dealloc
{
	[_invocation release];

	[super dealloc];
}

- (void)testSetAndGetReturnValue
{
	struct TestStruct testStruct, testStruct2;

	memset(&testStruct, 0xFF, sizeof(testStruct));
	testStruct.c = 0x55;
	testStruct.i = 0xAAAAAAAA;

	[_invocation setReturnValue: &testStruct];
	[_invocation getReturnValue: &testStruct2];
	OTAssertEqual(memcmp(&testStruct, &testStruct2, sizeof(testStruct)), 0);
}

- (void)testSetAndGetArgumentAtIndex
{
	struct TestStruct testStruct, testStruct2;
	struct TestStruct *testStructPtr = &testStruct, *testStructPtr2;
	unsigned const char c = 0xAA;
	unsigned char c2;
	const unsigned int i = 0x55555555;
	unsigned int i2;

	memset(&testStruct, 0xFF, sizeof(testStruct));
	testStruct.c = 0x55;
	testStruct.i = 0xAAAAAAAA;



	memset(&testStruct2, 0, sizeof(testStruct2));








	[_invocation setArgument: &c atIndex: 2];


	[_invocation setArgument: &i atIndex: 3];


	[_invocation setArgument: &testStructPtr atIndex: 4];


	[_invocation setArgument: &testStruct atIndex: 5];


	[_invocation getArgument: &c2 atIndex: 2];
	OTAssertEqual(c, c2);


	[_invocation getArgument: &i2 atIndex: 3];
	OTAssertEqual(i, i2);


	[_invocation getArgument: &testStructPtr2 atIndex: 4];
	OTAssertEqual(testStructPtr, testStructPtr2);


	[_invocation getArgument: &testStruct2 atIndex: 5];

	OTAssertEqual(memcmp(&testStruct, &testStruct2, sizeof(testStruct)), 0);

}
@end

Renamed and modified tests/OFJSONTests.m [92f1f602a7] to new_tests/OFJSONTests.m [125230cf82].

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
 * 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 = @"OFJSON";


@implementation TestsAppDelegate (JSONTests)

- (void)JSONTests
{

	void *pool = objc_autoreleasePoolPush();
	OFString *string = @"{\"foo\"\t:'b\\na\\r', \"x\":/*foo*/ [.5\r,0xF,"
	    @"null//bar\n,\"foo\",false]}";
	OFDictionary *dict = [OFDictionary dictionaryWithKeysAndObjects:









	    @"foo", @"b\na\r",
	    @"x", [OFArray arrayWithObjects:
		[OFNumber numberWithFloat: .5f],
		[OFNumber numberWithInt: 0xF],
		[OFNull null],
		@"foo",
		[OFNumber numberWithBool: false],
		nil],
	    nil];
















	TEST(@"-[objectByParsingJSON] #1",

	    [string.objectByParsingJSON isEqual: dict])


	TEST(@"-[JSONRepresentation]",

	    [[dict JSONRepresentation] isEqual:
	    @"{\"x\":[0.5,15,null,\"foo\",false],\"foo\":\"b\\na\\r\"}"])


	TEST(@"OFJSONRepresentationOptionPretty",

	    [[dict JSONRepresentationWithOptions:
	    OFJSONRepresentationOptionPretty] isEqual:
	    @"{\n\t\"x\": [\n\t\t0.5,\n\t\t15,\n\t\tnull,\n\t\t"
	    @"\"foo\",\n\t\tfalse\n\t],\n\t\"foo\": \"b\\na\\r\"\n}"])


	TEST(@"OFJSONRepresentationOptionJSON5",

	    [[dict JSONRepresentationWithOptions:
	    OFJSONRepresentationOptionJSON5] isEqual:
	    @"{x:[0.5,15,null,\"foo\",false],foo:\"b\\\na\\r\"}"])

	EXPECT_EXCEPTION(@"-[objectByParsingJSON] #2", OFInvalidJSONException,


	    [@"{" objectByParsingJSON])
	EXPECT_EXCEPTION(@"-[objectByParsingJSON] #3", OFInvalidJSONException,

	    [@"]" objectByParsingJSON])
	EXPECT_EXCEPTION(@"-[objectByParsingJSON] #4", OFInvalidJSONException,

	    [@"bar" objectByParsingJSON])
	EXPECT_EXCEPTION(@"-[objectByParsingJSON] #5", OFInvalidJSONException,

	    [@"[\"a\" \"b\"]" objectByParsingJSON])



	TEST(@"-[objectByParsingJSON] #6",


	    [@"[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[{}]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]"
	    .objectByParsingJSON isEqual: [OFArray arrayWithObject:

	    [OFArray arrayWithObject: [OFArray arrayWithObject:
	    [OFArray arrayWithObject: [OFArray arrayWithObject:
	    [OFArray arrayWithObject: [OFArray arrayWithObject:
	    [OFArray arrayWithObject: [OFArray arrayWithObject:
	    [OFArray arrayWithObject: [OFArray arrayWithObject:
	    [OFArray arrayWithObject: [OFArray arrayWithObject:
	    [OFArray arrayWithObject: [OFArray arrayWithObject:
	    [OFArray arrayWithObject: [OFArray arrayWithObject:
	    [OFArray arrayWithObject: [OFArray arrayWithObject:
	    [OFArray arrayWithObject: [OFArray arrayWithObject:
	    [OFArray arrayWithObject: [OFArray arrayWithObject:
	    [OFArray arrayWithObject: [OFArray arrayWithObject:
	    [OFArray arrayWithObject: [OFArray arrayWithObject:
	    [OFArray arrayWithObject: [OFArray arrayWithObject:
	    [OFArray arrayWithObject:
	    [OFDictionary dictionary]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]])

	EXPECT_EXCEPTION(@"-[objectByParsingJSON] #7", OFInvalidJSONException,



	    [@"[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[{}]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]"
	    objectByParsingJSON])

	objc_autoreleasePoolPop(pool);
}
@end







|
>

|
|
>
|
>
|
|
>
|
|
|
|
>
>
>
>
>
>
>
>
>









|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
|
|
>
|
>
|
|
|
>
|
>
|
|

|
|
>
|
>
|
|
|
|
|
>
>
|
|
>
|
|
>
|
|
>
|
>
|
>
|
>
>
|
|
>















|
|
|
>
>
>

|
|
<


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
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#import "ObjFW.h"
#import "ObjFWTest.h"

@interface OFJSONTests: OTTestCase
{
	unsigned long long _hashSeed;
	OFDictionary *_dictionary;
}
@end

extern unsigned long long OFHashSeed;

static OFString *string = @"{\"foo\"\t:'b\\na\\r', \"x\":/*foo*/ [.5\r,0xF,"
    @"null//bar\n,\"foo\",false]}";

@implementation OFJSONTests
- (void)setUp
{
	[super setUp];

	_hashSeed = OFHashSeed;
	OFHashSeed = 0;

	_dictionary = [[OFDictionary alloc] initWithKeysAndObjects:
	    @"foo", @"b\na\r",
	    @"x", [OFArray arrayWithObjects:
		[OFNumber numberWithFloat: .5f],
		[OFNumber numberWithInt: 0xF],
		[OFNull null],
		@"foo",
		[OFNumber numberWithBool: false],
		nil],
	    nil];
}

- (void)tearDown
{
	OFHashSeed = _hashSeed;

	[super tearDown];
}

- (void)dealloc
{
	[_dictionary release];

	[super dealloc];
}

- (void)testObjectByParsingJSON
{
	OTAssertEqualObjects(string.objectByParsingJSON, _dictionary);
}

- (void)testJSONRepresentation
{
	OTAssertEqualObjects(_dictionary.JSONRepresentation,
	    @"{\"x\":[0.5,15,null,\"foo\",false],\"foo\":\"b\\na\\r\"}");
}

- (void)testPrettyJSONRepresentation
{
	OTAssertEqualObjects([_dictionary JSONRepresentationWithOptions:
	    OFJSONRepresentationOptionPretty],
	    @"{\n\t\"x\": [\n\t\t0.5,\n\t\t15,\n\t\tnull,\n\t\t"
	    @"\"foo\",\n\t\tfalse\n\t],\n\t\"foo\": \"b\\na\\r\"\n}");
}

- (void)testJSON5Representation
{
	OTAssertEqualObjects([_dictionary JSONRepresentationWithOptions:
	    OFJSONRepresentationOptionJSON5],
	    @"{x:[0.5,15,null,\"foo\",false],foo:\"b\\\na\\r\"}");
}

- (void)testObjectByParsingJSONFailsWithInvalidJSON
{
	OTAssertThrowsSpecific([@"{" objectByParsingJSON],
	    OFInvalidJSONException);

	OTAssertThrowsSpecific([@"]" objectByParsingJSON],
	    OFInvalidJSONException);

	OTAssertThrowsSpecific([@"bar" objectByParsingJSON],
	    OFInvalidJSONException);

	OTAssertThrowsSpecific([@"[\"a\" \"b\"]" objectByParsingJSON],
	    OFInvalidJSONException);
}

- (void)testObjectByParsingJSONWithDeepNesting
{
	OTAssertEqualObjects(
	    @"[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[{}]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]"
	    .objectByParsingJSON,
	    [OFArray arrayWithObject:
	    [OFArray arrayWithObject: [OFArray arrayWithObject:
	    [OFArray arrayWithObject: [OFArray arrayWithObject:
	    [OFArray arrayWithObject: [OFArray arrayWithObject:
	    [OFArray arrayWithObject: [OFArray arrayWithObject:
	    [OFArray arrayWithObject: [OFArray arrayWithObject:
	    [OFArray arrayWithObject: [OFArray arrayWithObject:
	    [OFArray arrayWithObject: [OFArray arrayWithObject:
	    [OFArray arrayWithObject: [OFArray arrayWithObject:
	    [OFArray arrayWithObject: [OFArray arrayWithObject:
	    [OFArray arrayWithObject: [OFArray arrayWithObject:
	    [OFArray arrayWithObject: [OFArray arrayWithObject:
	    [OFArray arrayWithObject: [OFArray arrayWithObject:
	    [OFArray arrayWithObject: [OFArray arrayWithObject:
	    [OFArray arrayWithObject: [OFArray arrayWithObject:
	    [OFArray arrayWithObject:
	    [OFDictionary dictionary]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]);
}

- (void)testObjectByParsingJSONFailsWithTooDeepNesting
{
	OTAssertThrowsSpecific(
	    [@"[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[{}]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]"
	    objectByParsingJSON],
	    OFInvalidJSONException);

}
@end

Renamed and modified tests/OFMatrix4x4Tests.m [29d0338fbf] to new_tests/OFMatrix4x4Tests.m [53d6e8ba9c].

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
 * 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;
	OFVector4D points[2] = {{ 1, 2, 3, 1 }, { 7, 8, 9, 2 }};


	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] autorelease]) &&

	    [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(@"-[transformVectors:count:]",
	    R([matrix transformVectors: points count: 2]) &&
	    points[0].x == 18 && points[0].y == 46 && points[0].z == 74 &&




	    points[0].w == 102 && points[1].x == 58 && points[1].y == 162 &&
	    points[1].z == 266 && points[1].w == 370)

	objc_autoreleasePoolPop(pool);
}
@end







|
|
<

<
|

<
|
<
<
|
>
|
|
<
<
<
<
<
>
|
>
|
|




|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
|
|
|
|
|
|
|
>
>
>
|
|




|
|
|
>
|
>
|
>
>
>
|
>
>
>
>
|
|

|





<
|
|
|




|
|
>
|
>
|
>
>
|
|
|
|
>
>
>
|
>
|
>
>
>
>
>
|
|
|
>
>
>
>
>
|
>
|
>
|
|
|
>
>
>
>
|
|
|
|


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
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#import "ObjFW.h"
#import "ObjFWTest.h"



@interface OFMatrix4x4Tests: OTTestCase
{

	OFMatrix4x4 *_matrix;


}
@end

@implementation OFMatrix4x4Tests





- (void)setUp
{
	[super setUp];

	_matrix = [[OFMatrix4x4 alloc] initWithValues: (const float [4][4]){
		{  1,  2,  3,  4 },
		{  5,  6,  7,  8 },
		{  9, 10, 11, 12 },
		{ 13, 14, 15, 16 }
	}];
}

- (void)dealloc
{
	[_matrix release];

	[super dealloc];
}

- (void)testIdentityMatrix
{
	OTAssertEqual(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);
}

- (void)testDescription
{
	OTAssertEqualObjects(_matrix.description,
	    @"<OFMatrix4x4: {\n"
	    @"\t1 2 3 4\n"
	    @"\t5 6 7 8\n"
	    @"\t9 10 11 12\n"
	    @"\t13 14 15 16\n"
	    @"}>");
}

- (void)testIsEqual
{
	OTAssertEqualObjects([OFMatrix4x4 identityMatrix],
	    ([OFMatrix4x4 matrixWithValues: (const float [4][4]){
		{ 1, 0, 0, 0 },
		{ 0, 1, 0, 0 },
		{ 0, 0, 1, 0 },
		{ 0, 0, 0, 1 }
	    }]));
}

/* TODO: testHash */

- (void)testCopy
{
	OTAssertEqualObjects(_matrix, [[_matrix copy] autorelease]);
}

- (void)testMultiplyWithMatrix
{
	OFMatrix4x4 *matrix;

	matrix = [[_matrix copy] autorelease];
	[matrix multiplyWithMatrix: [OFMatrix4x4 identityMatrix]];
	OTAssertEqualObjects(matrix, _matrix);

	matrix = [OFMatrix4x4 matrixWithValues: (const float [4][4]){
		{  100,  200,  300,  400 },
		{  500,  600,  700,  800 },
		{  900, 1000, 1100, 1200 },
		{ 1300, 1400, 1500, 1600 }
	}];

	[matrix multiplyWithMatrix: _matrix];
	OTAssertEqualObjects(matrix,
	    ([OFMatrix4x4 matrixWithValues: (const float [4][4]){
		{  9000, 10000, 11000, 12000 },
		{ 20200, 22800, 25400, 28000 },
		{ 31400, 35600, 39800, 44000 },
		{ 42600, 48400, 54200, 60000 }
	    }]));
}

- (void)testTranslateWithVector
{
	OFMatrix4x4 *matrix = [OFMatrix4x4 identityMatrix];
	OFVector4D point;

	[matrix translateWithVector: OFMakeVector3D(1, 2, 3)];

	point = [matrix transformedVector: OFMakeVector4D(2, 3, 4, 1)];
	OTAssertEqual(point.x, 3);
	OTAssertEqual(point.y, 5);
	OTAssertEqual(point.z, 7);
	OTAssertEqual(point.w, 1);
}

- (void)testScaleWithVector
{
	OFMatrix4x4 *matrix = [OFMatrix4x4 identityMatrix];
	OFVector4D point;

	[matrix translateWithVector: OFMakeVector3D(1, 2, 3)];
	[matrix scaleWithVector: OFMakeVector3D(-1, 0.5f, 2)];

	point = [matrix transformedVector: OFMakeVector4D(2, 3, 4, 1)];
	OTAssertEqual(point.x, -3);
	OTAssertEqual(point.y, 2.5);
	OTAssertEqual(point.z, 14);
	OTAssertEqual(point.w, 1);
}

- (void)testTransformVectorsCount
{
	OFVector4D points[2] = {{ 1, 2, 3, 1 }, { 7, 8, 9, 2 }};

	[_matrix transformVectors: points count: 2];

	OTAssertEqual(points[0].x, 18);
	OTAssertEqual(points[0].y, 46);
	OTAssertEqual(points[0].z, 74);
	OTAssertEqual(points[0].w, 102);
	OTAssertEqual(points[1].x, 58);
	OTAssertEqual(points[1].y, 162);
	OTAssertEqual(points[1].z, 266);
	OTAssertEqual(points[1].w, 370);
}
@end

Renamed and modified tests/OFMethodSignatureTests.m [f874f8bb5c] to new_tests/OFMethodSignatureTests.m [27f044c8f7].

17
18
19
20
21
22
23
24

25
26

27
28
29
30
31
32
33

#include <string.h>

#if !defined(__STDC_NO_COMPLEX__) && defined(HAVE_COMPLEX_H)
# include <complex.h>
#endif

#import "TestsAppDelegate.h"


static OFString *const module = @"OFMethodSignature";


struct Test1Struct {
	char c;
	int i;
	char d;
};








|
>

|
>







17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

#include <string.h>

#if !defined(__STDC_NO_COMPLEX__) && defined(HAVE_COMPLEX_H)
# include <complex.h>
#endif

#import "ObjFW.h"
#import "ObjFWTest.h"

@interface OFMethodSignatureTests: OTTestCase
@end

struct Test1Struct {
	char c;
	int i;
	char d;
};

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
	int i;
	union {
		float f;
		double d;
	} u;
};

@implementation TestsAppDelegate (OFMethodSignatureTests)
- (void)methodSignatureTests
{
	void *pool = objc_autoreleasePoolPush();
	OFMethodSignature *methodSignature;

	TEST(@"-[signatureWithObjCTypes:] #1",
	    (methodSignature = [OFMethodSignature signatureWithObjCTypes:
	    "i28@0:8S16*20"]) &&
	    methodSignature.numberOfArguments == 4 &&
	    strcmp(methodSignature.methodReturnType, "i") == 0 &&
	    strcmp([methodSignature argumentTypeAtIndex: 0], "@") == 0 &&
	    strcmp([methodSignature argumentTypeAtIndex: 1], ":") == 0 &&
	    strcmp([methodSignature argumentTypeAtIndex: 2], "S") == 0 &&
	    strcmp([methodSignature argumentTypeAtIndex: 3], "*") == 0 &&
	    methodSignature.frameLength == 28 &&
	    [methodSignature argumentOffsetAtIndex: 0] == 0 &&
	    [methodSignature argumentOffsetAtIndex: 1] == 8 &&
	    [methodSignature argumentOffsetAtIndex: 2] == 16 &&
	    [methodSignature argumentOffsetAtIndex: 3] == 20)

	TEST(@"-[signatureWithObjCTypes:] #2",
	    (methodSignature = [OFMethodSignature signatureWithObjCTypes:
	    "{s0=csi(u1={s2=iii{s3=(u4=ic^v*)}})}24@0:8"
	    "^{s0=csi(u1={s2=iii{s3=(u4=ic^v*)}})}16"]) &&
	    methodSignature.numberOfArguments == 3 &&
	    strcmp(methodSignature.methodReturnType,
	    "{s0=csi(u1={s2=iii{s3=(u4=ic^v*)}})}") == 0 &&
	    strcmp([methodSignature argumentTypeAtIndex: 0], "@") == 0 &&
	    strcmp([methodSignature argumentTypeAtIndex: 1], ":") == 0 &&
	    strcmp([methodSignature argumentTypeAtIndex: 2],
	    "^{s0=csi(u1={s2=iii{s3=(u4=ic^v*)}})}") == 0 &&
	    methodSignature.frameLength == 24 &&
	    [methodSignature argumentOffsetAtIndex: 0] == 0 &&
	    [methodSignature argumentOffsetAtIndex: 1] == 8 &&
	    [methodSignature argumentOffsetAtIndex: 2] == 16)

	EXPECT_EXCEPTION(@"-[signatureWithObjCTypes:] #3",
	    OFInvalidFormatException,
	    [OFMethodSignature signatureWithObjCTypes: "{ii"])


	EXPECT_EXCEPTION(@"-[signatureWithObjCTypes:] #4",
	    OFInvalidFormatException,
	    [OFMethodSignature signatureWithObjCTypes: ""])

	EXPECT_EXCEPTION(@"-[signatureWithObjCTypes:] #5",
	    OFInvalidFormatException,
	    [OFMethodSignature signatureWithObjCTypes: "0"])

	EXPECT_EXCEPTION(@"-[signatureWithObjCTypes:] #6",
	    OFInvalidFormatException,


	    [OFMethodSignature signatureWithObjCTypes: "{{}0"])



	TEST(@"OFSizeOfTypeEncoding() #1",

	    OFSizeOfTypeEncoding(@encode(struct Test1Struct)) ==
	    sizeof(struct Test1Struct))

	TEST(@"OFSizeOfTypeEncoding() #2",
	    OFSizeOfTypeEncoding(@encode(struct Test2Struct)) ==
	    sizeof(struct Test2Struct))

#if !defined(__STDC_NO_COMPLEX__) && defined(HAVE_COMPLEX_H) && \
    OF_GCC_VERSION >= 402
	TEST(@"OFSizeOfTypeEncoding() #3",
	    OFSizeOfTypeEncoding(@encode(struct Test3Struct)) ==
	    sizeof(struct Test3Struct))
#endif

	TEST(@"OFSizeOfTypeEncoding() #4",
	    OFSizeOfTypeEncoding(@encode(union Test3Union)) ==
	    sizeof(union Test3Union))

	TEST(@"OFSizeOfTypeEncoding() #5",
	    OFSizeOfTypeEncoding(@encode(union Test4Union)) ==
	    sizeof(union Test4Union))

	TEST(@"OFSizeOfTypeEncoding() #6",
	    OFSizeOfTypeEncoding(@encode(struct Test1Struct [5])) ==
	    sizeof(struct Test1Struct [5]))


	TEST(@"OFAlignmentOfTypeEncoding() #1",

	    OFAlignmentOfTypeEncoding(@encode(struct Test1Struct)) ==
	    OF_ALIGNOF(struct Test1Struct))

	TEST(@"OFAlignmentOfTypeEncoding() #2",
	    OFAlignmentOfTypeEncoding(@encode(struct Test2Struct)) ==
	    OF_ALIGNOF(struct Test2Struct))

#if !defined(__STDC_NO_COMPLEX__) && defined(HAVE_COMPLEX_H) && \
    OF_GCC_VERSION >= 402
	TEST(@"OFAlignmentOfTypeEncoding() #3",
	    OFAlignmentOfTypeEncoding(@encode(struct Test3Struct)) ==
	    OF_ALIGNOF(struct Test3Struct))
#endif

	TEST(@"OFAlignmentOfTypeEncoding() #4",
	    OFAlignmentOfTypeEncoding(@encode(union Test3Union)) ==
	    OF_ALIGNOF(union Test3Union))

	TEST(@"OFAlignmentOfTypeEncoding() #5",
	    OFAlignmentOfTypeEncoding(@encode(union Test4Union)) ==
	    OF_ALIGNOF(union Test4Union))

	TEST(@"OFAlignmentOfTypeEncoding() #6",

	    OFAlignmentOfTypeEncoding(@encode(struct Test1Struct [5])) ==
	    OF_ALIGNOF(struct Test1Struct [5]))

	objc_autoreleasePoolPop(pool);
}
@end







|
|

<


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

<
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
<
|
|
>
|
|
<

|
|
<

|
|
>
>
|
>
|
>
|
>
|
|

<
|
|



<
|
|


<
|
|

<
|
|

<
|
|
|
>
|
>
|
|

<
|
|



<
|
|


<
|
|

<
|
|

<
>
|
|
<
<


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
	int i;
	union {
		float f;
		double d;
	} u;
};

@implementation OFMethodSignatureTests
- (void)testSignatureWithObjCTypes
{

	OFMethodSignature *methodSignature;

	methodSignature =
	    [OFMethodSignature signatureWithObjCTypes: "i28@0:8S16*20"];

	OTAssertEqual(methodSignature.numberOfArguments, 4);
	OTAssertEqual(strcmp(methodSignature.methodReturnType, "i"), 0);
	OTAssertEqual(strcmp([methodSignature argumentTypeAtIndex: 0], "@"), 0);
	OTAssertEqual(strcmp([methodSignature argumentTypeAtIndex: 1], ":"), 0);
	OTAssertEqual(strcmp([methodSignature argumentTypeAtIndex: 2], "S"), 0);
	OTAssertEqual(strcmp([methodSignature argumentTypeAtIndex: 3], "*"), 0);
	OTAssertEqual(methodSignature.frameLength, 28);
	OTAssertEqual([methodSignature argumentOffsetAtIndex: 0], 0);
	OTAssertEqual([methodSignature argumentOffsetAtIndex: 1], 8);
	OTAssertEqual([methodSignature argumentOffsetAtIndex: 2], 16);
	OTAssertEqual([methodSignature argumentOffsetAtIndex: 3], 20);


	methodSignature = [OFMethodSignature signatureWithObjCTypes:
	    "{s0=csi(u1={s2=iii{s3=(u4=ic^v*)}})}24@0:8"
	    "^{s0=csi(u1={s2=iii{s3=(u4=ic^v*)}})}16"];
	OTAssertEqual(methodSignature.numberOfArguments, 3);
	OTAssertEqual(strcmp(methodSignature.methodReturnType,
	    "{s0=csi(u1={s2=iii{s3=(u4=ic^v*)}})}"), 0);
	OTAssertEqual(strcmp([methodSignature argumentTypeAtIndex: 0], "@"), 0);
	OTAssertEqual(strcmp([methodSignature argumentTypeAtIndex: 1], ":"), 0);
	OTAssertEqual(strcmp([methodSignature argumentTypeAtIndex: 2],
	    "^{s0=csi(u1={s2=iii{s3=(u4=ic^v*)}})}"), 0);
	OTAssertEqual(methodSignature.frameLength, 24);
	OTAssertEqual([methodSignature argumentOffsetAtIndex: 0], 0);
	OTAssertEqual([methodSignature argumentOffsetAtIndex: 1], 8);
	OTAssertEqual([methodSignature argumentOffsetAtIndex: 2], 16);
}


- (void)testSignatureWithObjCTypesFailsWithInvalidFormat
{
	OTAssertThrowsSpecific(
	    [OFMethodSignature signatureWithObjCTypes: "{ii"],
	    OFInvalidFormatException);


	OTAssertThrowsSpecific([OFMethodSignature signatureWithObjCTypes: ""],
	    OFInvalidFormatException);


	OTAssertThrowsSpecific([OFMethodSignature signatureWithObjCTypes: "0"],
	    OFInvalidFormatException);

	OTAssertThrowsSpecific(
	    [OFMethodSignature signatureWithObjCTypes: "{{}0"],
	    OFInvalidFormatException);
}

- (void)testSizeOfTypeEncoding
{
	OTAssertEqual(OFSizeOfTypeEncoding(@encode(struct Test1Struct)),
	    sizeof(struct Test1Struct));


	OTAssertEqual(OFSizeOfTypeEncoding(@encode(struct Test2Struct)),
	    sizeof(struct Test2Struct));

#if !defined(__STDC_NO_COMPLEX__) && defined(HAVE_COMPLEX_H) && \
    OF_GCC_VERSION >= 402

	OTAssertEqual(OFSizeOfTypeEncoding(@encode(struct Test3Struct)),
	    sizeof(struct Test3Struct));
#endif


	OTAssertEqual(OFSizeOfTypeEncoding(@encode(union Test3Union)),
	    sizeof(union Test3Union));


	OTAssertEqual(OFSizeOfTypeEncoding(@encode(union Test4Union)),
	    sizeof(union Test4Union));


	OTAssertEqual(OFSizeOfTypeEncoding(@encode(struct Test1Struct [5])),
	    sizeof(struct Test1Struct [5]));
}

- (void)testAlignmentOfTypeEncoding
{
	OTAssertEqual(OFAlignmentOfTypeEncoding(@encode(struct Test1Struct)),
	    OF_ALIGNOF(struct Test1Struct));


	OTAssertEqual(OFAlignmentOfTypeEncoding(@encode(struct Test2Struct)),
	    OF_ALIGNOF(struct Test2Struct));

#if !defined(__STDC_NO_COMPLEX__) && defined(HAVE_COMPLEX_H) && \
    OF_GCC_VERSION >= 402

	OTAssertEqual(OFAlignmentOfTypeEncoding(@encode(struct Test3Struct)),
	    OF_ALIGNOF(struct Test3Struct));
#endif


	OTAssertEqual(OFAlignmentOfTypeEncoding(@encode(union Test3Union)),
	    OF_ALIGNOF(union Test3Union));


	OTAssertEqual(OFAlignmentOfTypeEncoding(@encode(union Test4Union)),
	    OF_ALIGNOF(union Test4Union));


	OTAssertEqual(
	    OFAlignmentOfTypeEncoding(@encode(struct Test1Struct [5])),
	    OF_ALIGNOF(struct Test1Struct [5]));


}
@end

Added new_tests/OFMutableArrayTests.h version [5ae96e61d9].













































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/*
 * Copyright (c) 2008-2024 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the 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 "OFArrayTests.h"

@interface OFMutableArrayTests: OFArrayTests
{
	OFMutableArray *_mutableArray;
}
@end

Added new_tests/OFMutableArrayTests.m version [55585061e4].

























































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
/*
 * Copyright (c) 2008-2024 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the 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 "OFMutableArrayTests.h"

#import "OFArray+Private.h"

@interface CustomMutableArray: OFMutableArray
{
	OFMutableArray *_array;
}
@end

static OFString *const cArray[] = {
	@"Foo",
	@"Bar",
	@"Baz"
};

@implementation OFMutableArrayTests
- (Class)arrayClass
{
	return [CustomMutableArray class];
}

- (void)setUp
{
	[super setUp];

	_mutableArray = [[self.arrayClass alloc]
	    initWithObjects: cArray
		      count: sizeof(cArray) / sizeof(*cArray)];
}

- (void)dealloc
{
	[_mutableArray release];

	[super dealloc];
}

- (void)testAddObject
{
	[_mutableArray addObject: cArray[0]];
	[_mutableArray addObject: cArray[2]];

	OTAssertEqualObjects(_mutableArray,
	    ([OFArray arrayWithObjects: @"Foo", @"Bar", @"Baz", @"Foo", @"Baz",
	    nil]));
}

- (void)testInsertObjectAtIndex
{
	[_mutableArray insertObject: cArray[1] atIndex: 1];

	OTAssertEqualObjects(_mutableArray,
	    ([OFArray arrayWithObjects: @"Foo", @"Bar", @"Bar", @"Baz", nil]));
}

- (void)testReplaceObjectWithObject
{
	[_mutableArray insertObject: cArray[1] atIndex: 1];
	[_mutableArray replaceObject: cArray[1] withObject: cArray[0]];

	OTAssertEqualObjects(_mutableArray,
	    ([OFArray arrayWithObjects: @"Foo", @"Foo", @"Foo", @"Baz", nil]));
}

- (void)testReplaceObjectIdenticalToWithObject
{
	[_mutableArray insertObject: [[cArray[1] mutableCopy] autorelease]
			    atIndex: 1];
	[_mutableArray replaceObjectIdenticalTo: cArray[1]
				     withObject: cArray[0]];

	OTAssertEqualObjects(_mutableArray,
	    ([OFArray arrayWithObjects: @"Foo", @"Bar", @"Foo", @"Baz", nil]));
}

- (void)testReplaceObjectAtIndexWithObject
{
	[_mutableArray replaceObjectAtIndex: 1
				 withObject: cArray[0]];

	OTAssertEqualObjects(_mutableArray,
	    ([OFArray arrayWithObjects: @"Foo", @"Foo", @"Baz", nil]));
}

- (void)testRemoveObject
{
	[_mutableArray removeObject: cArray[1]];

	OTAssertEqualObjects(_mutableArray,
	    ([OFArray arrayWithObjects: @"Foo", @"Baz", nil]));
}

- (void)testRemoveObjectIdenticalTo
{
	[_mutableArray removeObjectIdenticalTo: cArray[1]];

	OTAssertEqualObjects(_mutableArray,
	    ([OFArray arrayWithObjects: @"Foo", @"Baz", nil]));
}

- (void)testRemoveObjectAtIndex
{
	[_mutableArray removeObjectAtIndex: 1];

	OTAssertEqualObjects(_mutableArray,
	    ([OFArray arrayWithObjects: @"Foo", @"Baz", nil]));
}

- (void)testRemoveObjectsInRange
{
	[_mutableArray removeObjectsInRange: OFMakeRange(1, 2)];

	OTAssertEqualObjects(_mutableArray, [OFArray arrayWithObject: @"Foo"]);
}

- (void)testRemoveObjectsInRangeFailsWhenOutOfRange
{
	OTAssertThrowsSpecific([_mutableArray removeObjectsInRange:
	    OFMakeRange(0, _mutableArray.count + 1)], OFOutOfRangeException);
}

- (void)testReverse
{
	[_mutableArray reverse];

	OTAssertEqualObjects(_mutableArray,
	    ([OFArray arrayWithObjects: @"Baz", @"Bar", @"Foo", nil]));
}

#ifdef OF_HAVE_BLOCKS
- (void)testReplaceObjectsUsingBlock
{
	[_mutableArray replaceObjectsUsingBlock: ^ id (id object, size_t idx) {
		return [object lowercaseString];
	}];

	OTAssertEqualObjects(_mutableArray,
	    ([OFArray arrayWithObjects: @"foo", @"bar", @"baz", nil]));
}
#endif

- (void)testSetValueForKey
{
	OFMutableArray *array = [self.arrayClass arrayWithObjects:
	    [OFMutableIRI IRIWithString: @"http://foo.bar/"],
	    [OFMutableIRI IRIWithString: @"http://bar.qux/"],
	    [OFMutableIRI IRIWithString: @"http://qux.quxqux/"], nil];

	[array setValue: [OFNumber numberWithShort: 1234]
		 forKey: @"port"];
	OTAssertEqualObjects(array, ([OFArray arrayWithObjects:
	    [OFIRI IRIWithString: @"http://foo.bar:1234/"],
	    [OFIRI IRIWithString: @"http://bar.qux:1234/"],
	    [OFIRI IRIWithString: @"http://qux.quxqux:1234/"], nil]));
}
@end

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

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

	return self;
}

- (instancetype)initWithObject: (id)object arguments: (va_list)arguments
{
	self = [super init];

	@try {
		_array = [[OFMutableArray alloc] initWithObject: object
						      arguments: arguments];
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (instancetype)initWithObjects: (id const *)objects count: (size_t)count
{
	self = [super init];

	@try {
		_array = [[OFMutableArray alloc] initWithObjects: objects
							   count: count];
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (void)dealloc
{
	[_array release];

	[super dealloc];
}

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

- (size_t)count
{
	return [_array count];
}

- (void)insertObject: (id)object atIndex: (size_t)idx
{
	[_array insertObject: object atIndex: idx];
}

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

- (void)removeObjectAtIndex: (size_t)idx
{
	[_array removeObjectAtIndex: idx];
}
@end

Renamed and modified tests/OFNumberTests.m [8e6e4b486d] to new_tests/OFNumberTests.m [03fbf0fe79].

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
 * 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 = @"OFNumber";


@implementation TestsAppDelegate (OFNumberTests)
- (void)numberTests
{
	void *pool = objc_autoreleasePoolPush();
	OFNumber *number;


	TEST(@"+[numberWithLongLong:]",





	    (number = [OFNumber numberWithLongLong: 123456789]))





	TEST(@"-[isEqual:]",
	    [number isEqual: [OFNumber numberWithLong: 123456789]])




	TEST(@"-[hash]", number.hash == 0x82D8BC42)

	TEST(@"-[charValue]", number.charValue == 21)



	TEST(@"-[doubleValue]", number.doubleValue == 123456789.L)

	TEST(@"signed char minimum & maximum unmodified",


	    (number = [OFNumber numberWithChar: SCHAR_MIN]) &&
	    number.charValue == SCHAR_MIN &&
	    (number = [OFNumber numberWithChar: SCHAR_MAX]) &&
	    number.charValue == SCHAR_MAX)

	TEST(@"short minimum & maximum unmodified",


	    (number = [OFNumber numberWithShort: SHRT_MIN]) &&
	    number.shortValue == SHRT_MIN &&
	    (number = [OFNumber numberWithShort: SHRT_MAX]) &&
	    number.shortValue == SHRT_MAX)

	TEST(@"int minimum & maximum unmodified",


	    (number = [OFNumber numberWithInt: INT_MIN]) &&
	    number.intValue == INT_MIN &&
	    (number = [OFNumber numberWithInt: INT_MAX]) &&
	    number.intValue == INT_MAX)

	TEST(@"long minimum & maximum unmodified",


	    (number = [OFNumber numberWithLong: LONG_MIN]) &&
	    number.longValue == LONG_MIN &&
	    (number = [OFNumber numberWithLong: LONG_MAX]) &&
	    number.longValue == LONG_MAX)

	TEST(@"long long minimum & maximum unmodified",


	    (number = [OFNumber numberWithLongLong: LLONG_MIN]) &&
	    number.longLongValue == LLONG_MIN &&
	    (number = [OFNumber numberWithLongLong: LLONG_MAX]) &&
	    number.longLongValue == LLONG_MAX)




	TEST(@"unsigned char maximum unmodified",
	    (number = [OFNumber numberWithUnsignedChar: UCHAR_MAX]) &&
	    number.unsignedCharValue == UCHAR_MAX)

	TEST(@"unsigned short maximum unmodified",


	    (number = [OFNumber numberWithUnsignedShort: USHRT_MAX]) &&
	    number.unsignedShortValue == USHRT_MAX)

	TEST(@"unsigned int maximum unmodified",


	    (number = [OFNumber numberWithUnsignedInt: UINT_MAX]) &&
	    number.unsignedIntValue == UINT_MAX)

	TEST(@"unsigned long maximum unmodified",


	    (number = [OFNumber numberWithUnsignedLong: ULONG_MAX]) &&
	    number.unsignedLongValue == ULONG_MAX)

	TEST(@"unsigned long long maximum unmodified",
	    (number = [OFNumber numberWithUnsignedLongLong: ULLONG_MAX]) &&
	    number.unsignedLongLongValue == ULLONG_MAX)

	objc_autoreleasePoolPop(pool);


}
@end







|
>

>
>
|
>

|
|

<
|
>
|
|
>
>
>
>
>
|
>
>
>
>
|
<
<

>
>
>
|
|
|
>
|
>
|
|
|
>
>
|
|
|
|
|
|
>
>
|
|
|
|
|
|
>
>
|
<
|
<
|
|
>
>
|
|
|
|
|
|
>
>
|
|
|
|
>
>
>
|
<
|
|
|
|
>
>
|
|
|
|
>
>
|
|
|
|
>
>
|
|
|
|
<
|
|
<
>
>


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
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#import "ObjFW.h"
#import "ObjFWTest.h"

@interface OFNumberTests: OTTestCase
@end

extern unsigned long long OFHashSeed;

@implementation OFNumberTests
- (void)testIsEqual
{

	OFNumber *number = [OFNumber numberWithLongLong: 123456789];
	OTAssertEqualObjects(number, [OFNumber numberWithLong: 123456789]);
}

- (void)testHash
{
	unsigned long long hashSeed = OFHashSeed;
	OFHashSeed = 0;
	@try {
		OFNumber *number = [OFNumber numberWithLongLong: 123456789];
		OTAssertEqual(number.hash, 0x82D8BC42);
	} @finally {
		OFHashSeed = hashSeed;
	};
}



- (void)testCharValue
{
	OFNumber *number = [OFNumber numberWithLongLong: 123456789];
	OTAssertEqual(number.charValue, 21);
}

- (void)testDoubleValue
{
	OFNumber *number = [OFNumber numberWithLongLong: 123456789];
	OTAssertEqual(number.doubleValue, 123456789.L);
}

- (void)testSignedCharMinAndMaxUnmodified
{
	OTAssertEqual([[OFNumber numberWithChar: SCHAR_MIN] charValue],
	    SCHAR_MIN);
	OTAssertEqual([[OFNumber numberWithChar: SCHAR_MAX] charValue],
	    SCHAR_MAX);
}

- (void)testShortMinAndMaxUnmodified
{
	OTAssertEqual([[OFNumber numberWithShort: SHRT_MIN] shortValue],
	    SHRT_MIN);
	OTAssertEqual([[OFNumber numberWithShort: SHRT_MAX] shortValue],
	    SHRT_MAX);
}

- (void)testIntMinAndMaxUnmodified
{
	OTAssertEqual([[OFNumber numberWithInt: INT_MIN] intValue], INT_MIN);

	OTAssertEqual([[OFNumber numberWithInt: INT_MAX] intValue], INT_MAX);

}

- (void)testLongMinAndMaxUnmodified
{
	OTAssertEqual([[OFNumber numberWithLong: LONG_MIN] longValue],
	    LONG_MIN);
	OTAssertEqual([[OFNumber numberWithLong: LONG_MAX] longValue],
	    LONG_MAX);;
}

- (void)testLongLongMinAndMaxUnmodified
{
	OTAssertEqual([[OFNumber numberWithLongLong: LLONG_MIN] longLongValue],
	    LLONG_MIN);
	OTAssertEqual([[OFNumber numberWithLongLong: LLONG_MAX] longLongValue],
	    LLONG_MAX);
}

- (void)testUnsignedCharMaxUnmodified
{

	OTAssertEqual([[OFNumber numberWithUnsignedChar: UCHAR_MAX]
	    unsignedCharValue], UCHAR_MAX);
}

- (void)testUnsignedShortMaxUnmodified
{
	OTAssertEqual([[OFNumber numberWithUnsignedShort: USHRT_MAX]
	    unsignedShortValue], USHRT_MAX);
}

- (void)testUnsignedIntMaxUnmodified
{
	OTAssertEqual([[OFNumber numberWithUnsignedInt: UINT_MAX]
	    unsignedIntValue], UINT_MAX);
}

- (void)testUnsignedLongMaxUnmodified
{
	OTAssertEqual([[OFNumber numberWithUnsignedLong: ULONG_MAX]
	    unsignedLongValue], ULONG_MAX);
}


- (void)testUnsignedLongLongMaxUnmodified
{

	OTAssertEqual([[OFNumber numberWithUnsignedLongLong: ULLONG_MAX]
	    unsignedLongLongValue], ULLONG_MAX);
}
@end

Renamed and modified tests/OFPBKDF2Tests.m [2febb34313] to new_tests/OFPBKDF2Tests.m [cd8293bb12].

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
 * file.
 */

#include "config.h"

#include <string.h>

#import "TestsAppDelegate.h"


static OFString *const module = @"OFPBKDF2";





@implementation TestsAppDelegate (OFPBKDF2Tests)
- (void)PBKDF2Tests
{

	void *pool = objc_autoreleasePoolPush();
	OFHMAC *HMAC = [OFHMAC HMACWithHashClass: [OFSHA1Hash class]
			   allowsSwappableMemory: true];

	unsigned char key[25];







	/* Test vectors from RFC 6070 */




	TEST(@"PBKDF2-SHA1, 1 iteration",
	    R(OFPBKDF2((OFPBKDF2Parameters){
		.HMAC                  = HMAC,
		.iterations            = 1,
		.salt                  = (unsigned char *)"salt",
		.saltLength            = 4,
		.password              = "password",
		.passwordLength        = 8,
		.key                   = key,
		.keyLength             = 20,
		.allowsSwappableMemory = true


	    })) && memcmp(key, "\x0C\x60\xC8\x0F\x96\x1F\x0E\x71\xF3\xA9\xB5"
		"\x24\xAF\x60\x12\x06\x2F\xE0\x37\xA6", 20) == 0)

	TEST(@"PBKDF2-SHA1, 2 iterations",




	    R(OFPBKDF2((OFPBKDF2Parameters){
		.HMAC                  = HMAC,
		.iterations            = 2,
		.salt                  = (unsigned char *)"salt",
		.saltLength            = 4,
		.password              = "password",
		.passwordLength        = 8,
		.key                   = key,
		.keyLength             = 20,
		.allowsSwappableMemory = true


	    })) && memcmp(key, "\xEA\x6C\x01\x4D\xC7\x2D\x6F\x8C\xCD\x1E\xD9"
	        "\x2A\xCE\x1D\x41\xF0\xD8\xDE\x89\x57", 20) == 0)

	TEST(@"PBKDF2-SHA1, 4096 iterations",




	    R(OFPBKDF2((OFPBKDF2Parameters){
		.HMAC                  = HMAC,
		.iterations            = 4096,
		.salt                  = (unsigned char *)"salt",
		.saltLength            = 4,
		.password              = "password",
		.passwordLength        = 8,
		.key                   = key,
		.keyLength             = 20,
		.allowsSwappableMemory = true


	    })) && memcmp(key, "\x4B\x00\x79\x01\xB7\x65\x48\x9A\xBE\xAD\x49"
	        "\xD9\x26\xF7\x21\xD0\x65\xA4\x29\xC1", 20) == 0)

	/* This test takes too long, even on a fast machine. */
#if 0




	TEST(@"PBKDF2-SHA1, 16777216 iterations",
	    R(OFPBKDF2((OFPBKDF2Parameters){
		.HMAC                  = HMAC,
		.iterations            = 16777216,
		.salt                  = (unsigned char *)"salt",
		.saltLength            = 4,
		.password              = "password",
		.passwordLength        = 8,
		.key                   = key,
		.keyLength             = 20,
		.allowsSwappableMemory = true


	    })) && memcmp(key, "\xEE\xFE\x3D\x61\xCD\x4D\xA4\xE4\xE9\x94\x5B"
	        "\x3D\x6B\xA2\x15\x8C\x26\x34\xE9\x84", 20) == 0)

#endif




	TEST(@"PBKDF2-SHA1, 4096 iterations, key > 1 block",
	    R(OFPBKDF2((OFPBKDF2Parameters){
		.HMAC                  = HMAC,
		.iterations            = 4096,
		.salt                  = (unsigned char *)"saltSALTsaltSALTsalt"
		                         "SALTsaltSALTsalt",
		.saltLength            = 36,
		.password              = "passwordPASSWORDpassword",
		.passwordLength        = 24,
		.key                   = key,
		.keyLength             = 25,
		.allowsSwappableMemory = true
	    })) &&

	    memcmp(key, "\x3D\x2E\xEC\x4F\xE4\x1C\x84\x9B\x80\xC8\xD8\x36\x62"
	        "\xC0\xE4\x4A\x8B\x29\x1A\x96\x4C\xF2\xF0\x70\x38", 25) == 0)

	TEST(@"PBKDF2-SHA1, 4096 iterations, key < 1 block",




	    R(OFPBKDF2((OFPBKDF2Parameters){
		.HMAC                  = HMAC,
		.iterations            = 4096,
		.salt                  = (unsigned char *)"sa\0lt",
		.saltLength            = 5,
		.password              = "pass\0word",
		.passwordLength        = 9,
		.key                   = key,
		.keyLength             = 16,
		.allowsSwappableMemory = true


	    })) && memcmp(key, "\x56\xFA\x6A\xA7\x55\x48\x09\x9D\xCC\x37\xD7"
	        "\xF0\x34\x25\xE0\xC3", 16) == 0)

	objc_autoreleasePoolPop(pool);
}
@end







|
>

|
|
>
>
>
>
|
|

>
|
|
|
>
|
>
|
>
>
>
>
>
|

>
>
>
|
|
|








>
>
|
|
|
|
>
>
>
>
|
|








>
>
|
|
|
|
>
>
>
>
|
|








>
>
|
|
|
|

>
>
>
>
|
|
|








>
>
|
|
>


>
>
>
|
|
|


|






|
>
|
|
|
|
>
>
>
>
|
|








>
>
|
|
|
<
<

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
 * file.
 */

#include "config.h"

#include <string.h>

#import "ObjFW.h"
#import "ObjFWTest.h"

@interface OFPBKDF2Tests: OTTestCase
{
	OFHMAC *_HMAC;
}
@end

@implementation OFPBKDF2Tests
- (void)setUp
{
	[super setUp];

	_HMAC = [[OFHMAC alloc] initWithHashClass: [OFSHA1Hash class]
			    allowsSwappableMemory: true];
}

- (void)dealloc
{
	[_HMAC release];

	[super dealloc];
}

/* Test vectors from RFC 6070 */

- (void)testRFC6070TestVector1
{
	unsigned char key[25];

	OFPBKDF2((OFPBKDF2Parameters){
		.HMAC                  = _HMAC,
		.iterations            = 1,
		.salt                  = (unsigned char *)"salt",
		.saltLength            = 4,
		.password              = "password",
		.passwordLength        = 8,
		.key                   = key,
		.keyLength             = 20,
		.allowsSwappableMemory = true
	});

	OTAssertEqual(memcmp(key, "\x0C\x60\xC8\x0F\x96\x1F\x0E\x71\xF3\xA9\xB5"
	    "\x24\xAF\x60\x12\x06\x2F\xE0\x37\xA6", 20), 0);
}

- (void)testRFC6070TestVector2
{
	unsigned char key[25];

	OFPBKDF2((OFPBKDF2Parameters){
		.HMAC                  = _HMAC,
		.iterations            = 2,
		.salt                  = (unsigned char *)"salt",
		.saltLength            = 4,
		.password              = "password",
		.passwordLength        = 8,
		.key                   = key,
		.keyLength             = 20,
		.allowsSwappableMemory = true
	});

	OTAssertEqual(memcmp(key, "\xEA\x6C\x01\x4D\xC7\x2D\x6F\x8C\xCD\x1E\xD9"
	    "\x2A\xCE\x1D\x41\xF0\xD8\xDE\x89\x57", 20), 0);
}

- (void)testRFC6070TestVector3
{
	unsigned char key[25];

	OFPBKDF2((OFPBKDF2Parameters){
		.HMAC                  = _HMAC,
		.iterations            = 4096,
		.salt                  = (unsigned char *)"salt",
		.saltLength            = 4,
		.password              = "password",
		.passwordLength        = 8,
		.key                   = key,
		.keyLength             = 20,
		.allowsSwappableMemory = true
	});

	OTAssertEqual(memcmp(key, "\x4B\x00\x79\x01\xB7\x65\x48\x9A\xBE\xAD\x49"
	    "\xD9\x26\xF7\x21\xD0\x65\xA4\x29\xC1", 20), 0);
}

#if 0
/* This test takes too long, even on a fast machine. */
- (void)testRFC6070TestVector4
{
	unsigned char key[25];

	OFPBKDF2((OFPBKDF2Parameters){
		.HMAC                  = _HMAC,
		.iterations            = 16777216,
		.salt                  = (unsigned char *)"salt",
		.saltLength            = 4,
		.password              = "password",
		.passwordLength        = 8,
		.key                   = key,
		.keyLength             = 20,
		.allowsSwappableMemory = true
	});

	OTAssertEqual(memcmp(key, "\xEE\xFE\x3D\x61\xCD\x4D\xA4\xE4\xE9\x94\x5B"
	    "\x3D\x6B\xA2\x15\x8C\x26\x34\xE9\x84", 20), 0);
}
#endif

- (void)testRFC6070TestVector5
{
	unsigned char key[25];

	OFPBKDF2((OFPBKDF2Parameters){
		.HMAC                  = _HMAC,
		.iterations            = 4096,
		.salt                  = (unsigned char *)"saltSALTsaltSALTsalt"
					 "SALTsaltSALTsalt",
		.saltLength            = 36,
		.password              = "passwordPASSWORDpassword",
		.passwordLength        = 24,
		.key                   = key,
		.keyLength             = 25,
		.allowsSwappableMemory = true
	});

	OTAssertEqual(memcmp(key, "\x3D\x2E\xEC\x4F\xE4\x1C\x84\x9B\x80\xC8\xD8"
	    "\x36\x62\xC0\xE4\x4A\x8B\x29\x1A\x96\x4C\xF2\xF0\x70\x38", 25), 0);
}

- (void)testRFC6070TestVector6
{
	unsigned char key[25];

	OFPBKDF2((OFPBKDF2Parameters){
		.HMAC                  = _HMAC,
		.iterations            = 4096,
		.salt                  = (unsigned char *)"sa\0lt",
		.saltLength            = 5,
		.password              = "pass\0word",
		.passwordLength        = 9,
		.key                   = key,
		.keyLength             = 16,
		.allowsSwappableMemory = true
	});

	OTAssertEqual(memcmp(key, "\x56\xFA\x6A\xA7\x55\x48\x09\x9D\xCC\x37\xD7"
	    "\xF0\x34\x25\xE0\xC3", 16), 0);
}


@end

Renamed and modified tests/OFPluginTests.m [278848818e] to new_tests/OFPluginTests.m [b4655165af].

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


#import "plugin/TestPlugin.h"

#ifndef OF_IOS
static OFString *const pluginName = @"plugin/TestPlugin";
#else
static OFString *const pluginName = @"PlugIns/TestPlugin";
#endif

static OFString *const module = @"OFPlugin";

@implementation TestsAppDelegate (OFPluginTests)
- (void)pluginTests
{
	void *pool = objc_autoreleasePoolPush();

	OFString *path;
	OFPlugin *plugin;
	Class (*class)(void);
	TestPlugin *test;


	TEST(@"+[pathForName:]", (path = [OFPlugin pathForName: pluginName]))





	TEST(@"+[pluginWithPath:]", (plugin = [OFPlugin pluginWithPath: path]))


	TEST(@"-[addressForSymbol:]",
	    (class = (Class (*)(void))(uintptr_t)
	    [plugin addressForSymbol: @"class"]))

	test = [[class() alloc] init];
	@try {

		TEST(@"TestPlugin's -[test:]", [test test: 1234] == 2468)
	} @finally {
		[test release];
	}

	objc_autoreleasePoolPop(pool);
}
@end







|
>



<
|
<
<
|

<
<
|
|

<
>



<

>
|
>
>
>
>

|
>

<
|
|

<

>
|



|
<
<

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
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#import "ObjFW.h"
#import "ObjFWTest.h"

#import "plugin/TestPlugin.h"


@interface OFPluginTests: OTTestCase


@end



@implementation OFPluginTests
- (void)testPlugin
{

	TestPlugin *test = nil;
	OFString *path;
	OFPlugin *plugin;
	Class (*class)(void);


#ifndef OF_IOS
	path = [OFPlugin pathForName: @"plugin/TestPlugin"];
#else
	path = [OFPlugin pathForName: @"PlugIns/TestPlugin"];
#endif
	OTAssertNotNil(path);

	plugin = [OFPlugin pluginWithPath: path];
	OTAssertNotNil(plugin);


	class = (Class (*)(void))(uintptr_t)[plugin addressForSymbol: @"class"];
	OTAssert(class != NULL);


	@try {
		test = [[class() alloc] init];
		OTAssertEqual([test test: 1234], 2468);
	} @finally {
		[test release];
	}
}


@end

Renamed and modified tests/OFPropertyListTests.m [f48a04b761] to new_tests/OFPropertyListTests.m [2c2f0ce2a0].

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





#define PLIST(x)							\
	@"<?xml version=\"1.0\" encoding=\"UTF-8\"?>"			\
	@"<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" "	\
	@"\"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">"		\
	@"<plist version=\"1.0\">\n"					\
	x @"\n"								\
	@"</plist>"

static OFString *const module = @"OFPropertyList";
static OFString *const PLIST1 = PLIST(@"<string>Hello</string>");
static OFString *const PLIST2 = PLIST(
    @"<array>"
    @" <string>Hello</string>"
    @" <data>V29ybGQh</data>"
    @" <date>2018-03-14T12:34:56Z</date>"
    @" <true/>"
    @" <false/>"
    @" <real>12.25</real>"
    @" <integer>-10</integer>"
    @"</array>");
static OFString *const PLIST3 = PLIST(
    @"<dict>"
    @" <key>array</key>"
    @" <array>"
    @"  <string>Hello</string>"
    @"  <data>V29ybGQh</data>"
    @"  <date>2018-03-14T12:34:56Z</date>"
    @"  <true/>"
    @"  <false/>"
    @"  <real>12.25</real>"
    @"  <integer>-10</integer>"
    @" </array>"
    @" <key>foo</key>"
    @" <string>bar</string>"
    @"</dict>");

@implementation TestsAppDelegate (OFPLISTParser)
- (void)propertyListTests
{
	void *pool = objc_autoreleasePoolPush();
	OFArray *array = [OFArray arrayWithObjects:
	    @"Hello",
	    [OFData dataWithItems: "World!" count: 6],
	    [OFDate dateWithTimeIntervalSince1970: 1521030896],
	    [OFNumber numberWithBool: true],
	    [OFNumber numberWithBool: false],
	    [OFNumber numberWithFloat: 12.25f],
	    [OFNumber numberWithInt: -10],
	    nil];


	TEST(@"-[objectByParsingPropertyList:] #1",
	    [PLIST1.objectByParsingPropertyList isEqual: @"Hello"])









	TEST(@"-[objectByParsingPropertyList:] #2",
	    [PLIST2.objectByParsingPropertyList isEqual: array])














	TEST(@"-[objectByParsingPropertyList:] #3",
	    [PLIST3.objectByParsingPropertyList isEqual:
	    [OFDictionary dictionaryWithKeysAndObjects:
	    @"array", array,
	    @"foo", @"bar",
	    nil]])

	EXPECT_EXCEPTION(@"Detecting unsupported version",
	    OFUnsupportedVersionException,



	    [[PLIST(@"<string/>") stringByReplacingOccurrencesOfString: @"1.0"
							    withString: @"1.1"]
	    objectByParsingPropertyList])


	EXPECT_EXCEPTION(
	    @"-[objectByParsingPropertyList] detecting invalid format #1",
	    OFInvalidFormatException,
	    [PLIST(@"<string x='b'/>") objectByParsingPropertyList])

	EXPECT_EXCEPTION(

	    @"-[objectByParsingPropertyList] detecting invalid format #2",
	    OFInvalidFormatException,
	    [PLIST(@"<string xmlns='foo'/>") objectByParsingPropertyList])

	EXPECT_EXCEPTION(

	    @"-[objectByParsingPropertyList] detecting invalid format #3",
	    OFInvalidFormatException,
	    [PLIST(@"<dict count='0'/>") objectByParsingPropertyList])

	EXPECT_EXCEPTION(
	    @"-[objectByParsingPropertyList] detecting invalid format #4",
	    OFInvalidFormatException,


	    [PLIST(@"<dict><key/><string/><key/></dict>")
	    objectByParsingPropertyList])


	EXPECT_EXCEPTION(
	    @"-[objectByParsingPropertyList] detecting invalid format #5",
	    OFInvalidFormatException,

	    [PLIST(@"<dict><key x='x'/><string/></dict>")
	    objectByParsingPropertyList])

	objc_autoreleasePoolPop(pool);
}
@end







|
>
>
>
>









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

<










>
|
|
|
>
>
>
>
>
>
>
>
|
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
|
<
|


|
|
|
|
>
>
>
|
|
|
>
|
|
<
|
<
|
<
>
|
|
<

<
>
|
|
<

|
|
|
>
>

|
>

<
<
<
>

|
|
<


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
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#import "ObjFW.h"
#import "ObjFWTest.h"

@interface OFPropertyListTests: OTTestCase
@end

#define PLIST(x)							\
	@"<?xml version=\"1.0\" encoding=\"UTF-8\"?>"			\
	@"<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" "	\
	@"\"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">"		\
	@"<plist version=\"1.0\">\n"					\
	x @"\n"								\
	@"</plist>"

@implementation OFPropertyListTests


























- (void)testObjectByParsingPropertyList


{

	OFArray *array = [OFArray arrayWithObjects:
	    @"Hello",
	    [OFData dataWithItems: "World!" count: 6],
	    [OFDate dateWithTimeIntervalSince1970: 1521030896],
	    [OFNumber numberWithBool: true],
	    [OFNumber numberWithBool: false],
	    [OFNumber numberWithFloat: 12.25f],
	    [OFNumber numberWithInt: -10],
	    nil];

	OTAssertEqualObjects([PLIST(
	    @"<string>Hello</string>") objectByParsingPropertyList],
	    @"Hello");
	OTAssertEqualObjects([PLIST(
	    @"<array>"
	    @" <string>Hello</string>"
	    @" <data>V29ybGQh</data>"
	    @" <date>2018-03-14T12:34:56Z</date>"
	    @" <true/>"
	    @" <false/>"
	    @" <real>12.25</real>"
	    @" <integer>-10</integer>"
	    @"</array>") objectByParsingPropertyList],
	    array);
	OTAssertEqualObjects([PLIST(
	    @"<dict>"
	    @" <key>array</key>"
	    @" <array>"
	    @"  <string>Hello</string>"
	    @"  <data>V29ybGQh</data>"
	    @"  <date>2018-03-14T12:34:56Z</date>"
	    @"  <true/>"
	    @"  <false/>"
	    @"  <real>12.25</real>"
	    @"  <integer>-10</integer>"
	    @" </array>"
	    @" <key>foo</key>"
	    @" <string>bar</string>"
	    @"</dict>") objectByParsingPropertyList],

	    ([OFDictionary dictionaryWithKeysAndObjects:
	    @"array", array,
	    @"foo", @"bar",
	    nil]));
}

- (void)testDetectUnsupportedVersion
{
	OTAssertThrowsSpecific(
	    [[PLIST(@"<string/>")
	    stringByReplacingOccurrencesOfString: @"1.0"
				      withString: @"1.1"]
	    objectByParsingPropertyList],
	    OFUnsupportedVersionException);
}


- (void)testDetectInvalidFormat

{

	OTAssertThrowsSpecific(
	    [PLIST(@"<string x='b'/>") objectByParsingPropertyList],
	    OFInvalidFormatException);



	OTAssertThrowsSpecific(
	    [PLIST(@"<string xmlns='foo'/>") objectByParsingPropertyList],
	    OFInvalidFormatException);


	OTAssertThrowsSpecific(
	    [PLIST(@"<dict count='0'/>") objectByParsingPropertyList],
	    OFInvalidFormatException);

	OTAssertThrowsSpecific(
	    [PLIST(@"<dict><key/><string/><key/></dict>")
	    objectByParsingPropertyList],
	    OFInvalidFormatException);




	OTAssertThrowsSpecific(
	    [PLIST(@"<dict><key x='x'/><string/></dict>")
	    objectByParsingPropertyList],
	    OFInvalidFormatException);

}
@end

Renamed and modified tests/OFScryptTests.m [3717bd0eab] to new_tests/OFScryptTests.m [0924135d9a].

13
14
15
16
17
18
19
20

21


22
23
24
25
26
27
28
29
 * file.
 */

#include "config.h"

#include <string.h>

#import "TestsAppDelegate.h"




static OFString *const module = @"OFScrypt";
/* Test vectors form RFC 7914 */
static const unsigned char salsa20Input[64] = {
	0x7E, 0x87, 0x9A, 0x21, 0x4F, 0x3E, 0xC9, 0x86, 0x7C, 0xA9, 0x40, 0xE6,
	0x41, 0x71, 0x8F, 0x26, 0xBA, 0xEE, 0x55, 0x5B, 0x8C, 0x61, 0xC1, 0xB5,
	0x0D, 0xF8, 0x46, 0x11, 0x6D, 0xCD, 0x3B, 0x1D, 0xEE, 0x24, 0xF3, 0x19,
	0xDF, 0x9B, 0x3D, 0x85, 0x14, 0x12, 0x1E, 0x4B, 0x5A, 0xC5, 0xAA, 0x32,
	0x76, 0x02, 0x1D, 0x29, 0x09, 0xC7, 0x48, 0x29, 0xED, 0xEB, 0xC6, 0x8D,







|
>

>
>
|







13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
 * file.
 */

#include "config.h"

#include <string.h>

#import "ObjFW.h"
#import "ObjFWTest.h"

@interface OFScryptTests: OTTestCase
@end

/* Test vectors form RFC 7914 */
static const unsigned char salsa20Input[64] = {
	0x7E, 0x87, 0x9A, 0x21, 0x4F, 0x3E, 0xC9, 0x86, 0x7C, 0xA9, 0x40, 0xE6,
	0x41, 0x71, 0x8F, 0x26, 0xBA, 0xEE, 0x55, 0x5B, 0x8C, 0x61, 0xC1, 0xB5,
	0x0D, 0xF8, 0x46, 0x11, 0x6D, 0xCD, 0x3B, 0x1D, 0xEE, 0x24, 0xF3, 0x19,
	0xDF, 0x9B, 0x3D, 0x85, 0x14, 0x12, 0x1E, 0x4B, 0x5A, 0xC5, 0xAA, 0x32,
	0x76, 0x02, 0x1D, 0x29, 0x09, 0xC7, 0x48, 0x29, 0xED, 0xEB, 0xC6, 0x8D,
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
	0xAB, 0xE5, 0xEE, 0x98, 0x20, 0xAD, 0xAA, 0x47, 0x8E, 0x56, 0xFD, 0x8F,
	0x4B, 0xA5, 0xD0, 0x9F, 0xFA, 0x1C, 0x6D, 0x92, 0x7C, 0x40, 0xF4, 0xC3,
	0x37, 0x30, 0x40, 0x49, 0xE8, 0xA9, 0x52, 0xFB, 0xCB, 0xF4, 0x5C, 0x6F,
	0xA7, 0x7A, 0x41, 0xA4
};
#endif

@implementation TestsAppDelegate (OFScryptTests)
- (void)scryptTests
{
	void *pool = objc_autoreleasePoolPush();
	uint32_t salsa20Buffer[16];
	uint32_t blockMixBuffer[32];
	uint32_t ROMixBuffer[32], ROMixTmp[17 * 32];
	unsigned char output[64];

	TEST(@"Salsa20/8 Core",
	    R(memcpy(salsa20Buffer, salsa20Input, 64)) &&
	    R(OFSalsa20_8Core(salsa20Buffer)) &&
	    memcmp(salsa20Buffer, salsa20Output, 64) == 0)

	TEST(@"Block mix",




	    R(OFScryptBlockMix(blockMixBuffer, blockMixInput.u32, 1)) &&
	    memcmp(blockMixBuffer, blockMixOutput, 128) == 0)

	TEST(@"ROMix",




	    R(memcpy(ROMixBuffer, ROMixInput, 128)) &&
	    R(OFScryptROMix(ROMixBuffer, 1, 16, ROMixTmp)) &&
	    memcmp(ROMixBuffer, ROMixOutput, 128) == 0)

	TEST(@"scrypt test vector #1",




	    R(OFScrypt((OFScryptParameters){
		.blockSize             = 1,
		.costFactor            = 16,
		.parallelization       = 1,
		.salt                  = (unsigned char *)"",
		.saltLength            = 0,
		.password              = "",
		.passwordLength        = 0,
		.key                   = output,
		.keyLength             = 64,
		.allowsSwappableMemory = true


	    })) && memcmp(output, testVector1, 64) == 0)

	TEST(@"scrypt test vector #2",




	    R(OFScrypt((OFScryptParameters){
		.blockSize             = 8,
		.costFactor            = 1024,
		.parallelization       = 16,
		.salt                  = (unsigned char *)"NaCl",
		.saltLength            = 4,
		.password              = "password",
		.passwordLength        = 8,
		.key                   = output,
		.keyLength             = 64,
		.allowsSwappableMemory = true


	    })) && memcmp(output, testVector2, 64) == 0)


	/* The third test vector is too expensive for m68k. */
#ifndef OF_M68K



	TEST(@"scrypt test vector #3",
	    R(OFScrypt((OFScryptParameters){
		.blockSize             = 8,
		.costFactor            = 16384,
		.parallelization       = 1,
		.salt                  = (unsigned char *)"SodiumChloride",
		.saltLength            = 14,
		.password              = "pleaseletmein",
		.passwordLength        = 13,
		.key                   = output,
		.keyLength             = 64,
		.allowsSwappableMemory = true


	    })) && memcmp(output, testVector3, 64) == 0)

#endif

	/* The forth test vector is too expensive to include it in the tests. */
#if 0



	TEST(@"scrypt test vector #4",
	    R(OFScrypt((OFScryptParameters){
		.blockSize             = 8,
		.costFactor            = 1048576,
		.parallelization       = 1,
		.salt                  = (unsigned char *)"SodiumChloride",
		.saltLength            = 14,
		.password              = "pleaseletmein",
		.passwordLength        = 13,
		.key                   = output,
		.keyLength             = 64,
		.allowsSwappableMemory = true
	    })) && memcmp(output, testVector4, 64) == 0)
#endif

	objc_autoreleasePoolPop(pool);

}

@end







|
|

<

<
<
<

<
|
|
|
|
|
>
>
>
>
|
|
|
|
>
>
>
>
|
|
|
|
|
>
>
>
>
|










>
>
|
|
|
>
>
>
>
|










>
>
|
|
>
|

>
>
>
|
|










>
>
|
>


|

>
>
>
|
|










|
<

<
>

>

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
	0xAB, 0xE5, 0xEE, 0x98, 0x20, 0xAD, 0xAA, 0x47, 0x8E, 0x56, 0xFD, 0x8F,
	0x4B, 0xA5, 0xD0, 0x9F, 0xFA, 0x1C, 0x6D, 0x92, 0x7C, 0x40, 0xF4, 0xC3,
	0x37, 0x30, 0x40, 0x49, 0xE8, 0xA9, 0x52, 0xFB, 0xCB, 0xF4, 0x5C, 0x6F,
	0xA7, 0x7A, 0x41, 0xA4
};
#endif

@implementation OFScryptTests
- (void)testSalsa20_8Core
{

	uint32_t salsa20Buffer[16];





	memcpy(salsa20Buffer, salsa20Input, 64);
	OFSalsa20_8Core(salsa20Buffer);
	OTAssertEqual(memcmp(salsa20Buffer, salsa20Output, 64), 0);
}

- (void)testBlockMix
{
	uint32_t blockMixBuffer[32];

	OFScryptBlockMix(blockMixBuffer, blockMixInput.u32, 1);
	OTAssertEqual(memcmp(blockMixBuffer, blockMixOutput, 128), 0);
}

- (void)testROMix
{
	uint32_t ROMixBuffer[32], ROMixTmp[17 * 32];

	memcpy(ROMixBuffer, ROMixInput, 128);
	OFScryptROMix(ROMixBuffer, 1, 16, ROMixTmp);
	OTAssertEqual(memcmp(ROMixBuffer, ROMixOutput, 128), 0);
}

- (void)testRFC7941TestVector1
{
	unsigned char output[64];

	OFScrypt((OFScryptParameters){
		.blockSize             = 1,
		.costFactor            = 16,
		.parallelization       = 1,
		.salt                  = (unsigned char *)"",
		.saltLength            = 0,
		.password              = "",
		.passwordLength        = 0,
		.key                   = output,
		.keyLength             = 64,
		.allowsSwappableMemory = true
	});

	OTAssertEqual(memcmp(output, testVector1, 64), 0);
}

- (void)testRFC7941TestVector2
{
	unsigned char output[64];

	OFScrypt((OFScryptParameters){
		.blockSize             = 8,
		.costFactor            = 1024,
		.parallelization       = 16,
		.salt                  = (unsigned char *)"NaCl",
		.saltLength            = 4,
		.password              = "password",
		.passwordLength        = 8,
		.key                   = output,
		.keyLength             = 64,
		.allowsSwappableMemory = true
	});

	OTAssertEqual(memcmp(output, testVector2, 64), 0);
}

/* The third test vector is too expensive for m68k. */
#ifndef OF_M68K
- (void)testRFC7941TestVector3
{
	unsigned char output[64];

	OFScrypt((OFScryptParameters){
		.blockSize             = 8,
		.costFactor            = 16384,
		.parallelization       = 1,
		.salt                  = (unsigned char *)"SodiumChloride",
		.saltLength            = 14,
		.password              = "pleaseletmein",
		.passwordLength        = 13,
		.key                   = output,
		.keyLength             = 64,
		.allowsSwappableMemory = true
	});

	OTAssertEqual(memcmp(output, testVector3, 64), 0);
}
#endif

/* The forth test vector is too expensive to include it in the tests. */
#if 0
- (void)testRFC7941TestVector4
{
	unsigned char output[64];

	OFScrypt((OFScryptParameters){
		.blockSize             = 8,
		.costFactor            = 1048576,
		.parallelization       = 1,
		.salt                  = (unsigned char *)"SodiumChloride",
		.saltLength            = 14,
		.password              = "pleaseletmein",
		.passwordLength        = 13,
		.key                   = output,
		.keyLength             = 64,
		.allowsSwappableMemory = true
	});



	OTAssertEqual(memcmp(output, testVector4, 64), 0);
}
#endif
@end

Renamed and modified tests/OFSocketTests.m [2289bf230f] to new_tests/OFSocketTests.m [b6fe3d8b77].

11
12
13
14
15
16
17
18




19
20
21
22
23
24
25
 * 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"





#define COMPARE_V6(a, a0, a1, a2, a3, a4, a5, a6, a7)		\
	(a.sockaddr.in6.sin6_addr.s6_addr[0] == (a0 >> 8) &&	\
	a.sockaddr.in6.sin6_addr.s6_addr[1] == (a0 & 0xFF) &&	\
	a.sockaddr.in6.sin6_addr.s6_addr[2] == (a1 >> 8) &&	\
	a.sockaddr.in6.sin6_addr.s6_addr[3] == (a1 & 0xFF) &&	\
	a.sockaddr.in6.sin6_addr.s6_addr[4] == (a2 >> 8) &&	\







|
>
>
>
>







11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#import "ObjFW.h"
#import "ObjFWTest.h"

@interface OFSocketTests: OTTestCase
@end

#define COMPARE_V6(a, a0, a1, a2, a3, a4, a5, a6, a7)		\
	(a.sockaddr.in6.sin6_addr.s6_addr[0] == (a0 >> 8) &&	\
	a.sockaddr.in6.sin6_addr.s6_addr[1] == (a0 & 0xFF) &&	\
	a.sockaddr.in6.sin6_addr.s6_addr[2] == (a1 >> 8) &&	\
	a.sockaddr.in6.sin6_addr.s6_addr[3] == (a1 & 0xFF) &&	\
	a.sockaddr.in6.sin6_addr.s6_addr[4] == (a2 >> 8) &&	\
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
	a.sockaddr.in6.sin6_addr.s6_addr[10] = a5 >> 8;		\
	a.sockaddr.in6.sin6_addr.s6_addr[11] = a5 & 0xFF;	\
	a.sockaddr.in6.sin6_addr.s6_addr[12] = a6 >> 8;		\
	a.sockaddr.in6.sin6_addr.s6_addr[13] = a6 & 0xFF;	\
	a.sockaddr.in6.sin6_addr.s6_addr[14] = a7 >> 8;		\
	a.sockaddr.in6.sin6_addr.s6_addr[15] = a7 & 0xFF;

static OFString *const module = @"OFSocket";

@implementation TestsAppDelegate (OFSocketTests)
- (void)socketTests
{
	void *pool = objc_autoreleasePoolPush();
	OFSocketAddress addr;

	TEST(@"Parsing an IPv4",
	    R(addr = OFSocketAddressParseIP(@"127.0.0.1", 1234)) &&
	    OFFromBigEndian32(addr.sockaddr.in.sin_addr.s_addr) == 0x7F000001 &&

	    OFFromBigEndian16(addr.sockaddr.in.sin_port) == 1234)

	EXPECT_EXCEPTION(@"Refusing invalid IPv4 #1", OFInvalidFormatException,


	    OFSocketAddressParseIP(@"127.0.0.0.1", 1234))


	EXPECT_EXCEPTION(@"Refusing invalid IPv4 #2", OFInvalidFormatException,
	    OFSocketAddressParseIP(@"127.0.0.256", 1234))


	EXPECT_EXCEPTION(@"Refusing invalid IPv4 #3", OFInvalidFormatException,
	    OFSocketAddressParseIP(@"127.0.0. 1", 1234))


	EXPECT_EXCEPTION(@"Refusing invalid IPv4 #4", OFInvalidFormatException,
	    OFSocketAddressParseIP(@" 127.0.0.1", 1234))



	EXPECT_EXCEPTION(@"Refusing invalid IPv4 #5", OFInvalidFormatException,

	    OFSocketAddressParseIP(@"127.0.a.1", 1234))


	EXPECT_EXCEPTION(@"Refusing invalid IPv4 #6", OFInvalidFormatException,


	    OFSocketAddressParseIP(@"127.0..1", 1234))

	TEST(@"Port of an IPv4 address", OFSocketAddressIPPort(&addr) == 1234)

	TEST(@"Converting an IPv4 to a string",




	    [OFSocketAddressString(&addr) isEqual: @"127.0.0.1"])

	TEST(@"Parsing an IPv6 #1",




	    R(addr = OFSocketAddressParseIP(
	    @"1122:3344:5566:7788:99aa:bbCc:ddee:ff00", 1234)) &&
	    COMPARE_V6(addr,
	    0x1122, 0x3344, 0x5566, 0x7788, 0x99AA, 0xBBCC, 0xDDEE, 0xFF00) &&
	    OFFromBigEndian16(addr.sockaddr.in6.sin6_port) == 1234)

	TEST(@"Parsing an IPv6 #2",
	    R(addr = OFSocketAddressParseIP(@"::", 1234)) &&
	    COMPARE_V6(addr, 0, 0, 0, 0, 0, 0, 0, 0) &&
	    OFFromBigEndian16(addr.sockaddr.in6.sin6_port) == 1234)

	TEST(@"Parsing an IPv6 #3",
	    R(addr = OFSocketAddressParseIP(@"aaAa::bBbb", 1234)) &&
	    COMPARE_V6(addr, 0xAAAA, 0, 0, 0, 0, 0, 0, 0xBBBB) &&
	    OFFromBigEndian16(addr.sockaddr.in6.sin6_port) == 1234)

	TEST(@"Parsing an IPv6 #4",
	    R(addr = OFSocketAddressParseIP(@"aaAa::", 1234)) &&
	    COMPARE_V6(addr, 0xAAAA, 0, 0, 0, 0, 0, 0, 0) &&
	    OFFromBigEndian16(addr.sockaddr.in6.sin6_port) == 1234)

	TEST(@"Parsing an IPv6 #5",
	    R(addr = OFSocketAddressParseIP(@"::aaAa", 1234)) &&
	    COMPARE_V6(addr, 0, 0, 0, 0, 0, 0, 0, 0xAAAA) &&
	    OFFromBigEndian16(addr.sockaddr.in6.sin6_port) == 1234)

	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,
	    OFSocketAddressParseIP(@"1:: :2", 1234))


	EXPECT_EXCEPTION(@"Refusing invalid IPv6 #4", OFInvalidFormatException,
	    OFSocketAddressParseIP(@"1::2::3", 1234))


	EXPECT_EXCEPTION(@"Refusing invalid IPv6 #5", OFInvalidFormatException,
	    OFSocketAddressParseIP(@"10000::1", 1234))



	EXPECT_EXCEPTION(@"Refusing invalid IPv6 #6", OFInvalidFormatException,
	    OFSocketAddressParseIP(@"::10000", 1234))

	EXPECT_EXCEPTION(@"Refusing invalid IPv6 #7", OFInvalidFormatException,
	    OFSocketAddressParseIP(@"::1::", 1234))


	EXPECT_EXCEPTION(@"Refusing invalid IPv6 #8", OFInvalidFormatException,
	    OFSocketAddressParseIP(@"1:2:3:4:5:6:7:", 1234))



	EXPECT_EXCEPTION(@"Refusing invalid IPv6 #9", OFInvalidFormatException,

	    OFSocketAddressParseIP(@"1:2:3:4:5:6:7::", 1234))


	EXPECT_EXCEPTION(@"Refusing invalid IPv6 #10", OFInvalidFormatException,


	    OFSocketAddressParseIP(@"1:2", 1234))

	TEST(@"Port of an IPv6 address", OFSocketAddressIPPort(&addr) == 1234)

	addr.sockaddr.in6.sin6_scope_id = 0;



	SET_V6(addr, 0, 0, 0, 0, 0, 0, 0, 0)
	TEST(@"Converting an IPv6 to a string #1",
	    [OFSocketAddressString(&addr) isEqual: @"::"])

	SET_V6(addr, 0, 0, 0, 0, 0, 0, 0, 1)
	TEST(@"Converting an IPv6 to a string #2",
	    [OFSocketAddressString(&addr) isEqual: @"::1"])

	SET_V6(addr, 1, 0, 0, 0, 0, 0, 0, 0)
	TEST(@"Converting an IPv6 to a string #3",
	    [OFSocketAddressString(&addr) isEqual: @"1::"])

	SET_V6(addr,
	    0x1122, 0x3344, 0x5566, 0x7788, 0x99AA, 0xBBCC, 0xDDEE, 0xFF00)
	TEST(@"Converting an IPv6 to a string #4",
	    [OFSocketAddressString(&addr)
	    isEqual: @"1122:3344:5566:7788:99aa:bbcc:ddee:ff00"])


	SET_V6(addr, 0x1122, 0x3344, 0x5566, 0x7788, 0x99AA, 0xBBCC, 0xDDEE, 0)
	TEST(@"Converting an IPv6 to a string #5",
	    [OFSocketAddressString(&addr)
	    isEqual: @"1122:3344:5566:7788:99aa:bbcc:ddee:0"])

	SET_V6(addr, 0x1122, 0x3344, 0x5566, 0x7788, 0x99AA, 0xBBCC, 0, 0)
	TEST(@"Converting an IPv6 to a string #6",
	    [OFSocketAddressString(&addr)
	    isEqual: @"1122:3344:5566:7788:99aa:bbcc::"])


	SET_V6(addr, 0, 0x3344, 0x5566, 0x7788, 0x99AA, 0xBBCC, 0xDDEE, 0xFF00)
	TEST(@"Converting an IPv6 to a string #7",
	    [OFSocketAddressString(&addr)
	    isEqual: @"0:3344:5566:7788:99aa:bbcc:ddee:ff00"])

	SET_V6(addr, 0, 0, 0x5566, 0x7788, 0x99AA, 0xBBCC, 0xDDEE, 0xFF00)
	TEST(@"Converting an IPv6 to a string #8",
	    [OFSocketAddressString(&addr)
	    isEqual: @"::5566:7788:99aa:bbcc:ddee:ff00"])

	SET_V6(addr, 0, 0, 0x5566, 0, 0, 0, 0xDDEE, 0xFF00)
	TEST(@"Converting an IPv6 to a string #9",

	    [OFSocketAddressString(&addr) isEqual: @"0:0:5566::ddee:ff00"])

	SET_V6(addr, 0, 0, 0x5566, 0x7788, 0x99AA, 0xBBCC, 0, 0)
	TEST(@"Converting an IPv6 to a string #10",
	    [OFSocketAddressString(&addr)
	    isEqual: @"::5566:7788:99aa:bbcc:0:0"])

	objc_autoreleasePoolPop(pool);



}
@end







<
<
|
|

<
|

<
<
|
>
|
|
|
>
>
|
>

<
|
>

<
|
>

<
|
>

>
|
>
|
>
|
|
>
>
|

|
|
|
>
>
>
>
|
|
|
>
>
>
>
|
|
|
|
|

<
|
|
|

<
|
|
|

<
|
|
|

<
|
|
|

<
|
|
|
|

<
|
|
|

<
|
|
|
|
|
>
>
|
>

<
|
>

<
|
>

<
|
>

<
|
>

>
|
<

<
|
>

<
|
>

>
|
>
|
>
|
|
>
>
|

|
|
|
>
|
>
|
<
|

|
<
|

|
<
|

|

<
|
|

>
|
<
|
|

|
<
|
|

>
|
<
|
|

|
<
|
|

|
<
>
|

|
<
|
|

<
>
>
>


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
	a.sockaddr.in6.sin6_addr.s6_addr[10] = a5 >> 8;		\
	a.sockaddr.in6.sin6_addr.s6_addr[11] = a5 & 0xFF;	\
	a.sockaddr.in6.sin6_addr.s6_addr[12] = a6 >> 8;		\
	a.sockaddr.in6.sin6_addr.s6_addr[13] = a6 & 0xFF;	\
	a.sockaddr.in6.sin6_addr.s6_addr[14] = a7 >> 8;		\
	a.sockaddr.in6.sin6_addr.s6_addr[15] = a7 & 0xFF;



@implementation OFSocketTests
- (void)testParseIPv4
{

	OFSocketAddress address = OFSocketAddressParseIP(@"127.0.0.1", 1234);



	OTAssertEqual(OFFromBigEndian32(address.sockaddr.in.sin_addr.s_addr),
	    0x7F000001);
	OTAssertEqual(OFFromBigEndian16(address.sockaddr.in.sin_port), 1234);
}

- (void)testParseRejectsInvalidIPv4
{
	OTAssertThrowsSpecific(OFSocketAddressParseIP(@"127.0.0.0.1", 1234),
	    OFInvalidFormatException);


	OTAssertThrowsSpecific(OFSocketAddressParseIP(@"127.0.0.256", 1234),
	    OFInvalidFormatException);


	OTAssertThrowsSpecific(OFSocketAddressParseIP(@"127.0.0. 1", 1234),
	    OFInvalidFormatException);


	OTAssertThrowsSpecific(OFSocketAddressParseIP(@" 127.0.0.1", 1234),
	    OFInvalidFormatException);

	OTAssertThrowsSpecific(OFSocketAddressParseIP(@"127.0.a.1", 1234),
	    OFInvalidFormatException);

	OTAssertThrowsSpecific(OFSocketAddressParseIP(@"127.0..1", 1234),
	    OFInvalidFormatException);
}

- (void)testPortForIPv4
{
	OFSocketAddress address = OFSocketAddressParseIP(@"127.0.0.1", 1234);

	OTAssertEqual(OFSocketAddressIPPort(&address), 1234);
}

- (void)testStringForIPv4
{
	OFSocketAddress address = OFSocketAddressParseIP(@"127.0.0.1", 1234);

	OTAssertEqualObjects(OFSocketAddressString(&address), @"127.0.0.1");
}

- (void)testParseIPv6
{
	OFSocketAddress address;

	address = OFSocketAddressParseIP(
	    @"1122:3344:5566:7788:99aa:bbCc:ddee:ff00", 1234);
	OTAssert(COMPARE_V6(address,
	    0x1122, 0x3344, 0x5566, 0x7788, 0x99AA, 0xBBCC, 0xDDEE, 0xFF00));
	OTAssertEqual(OFFromBigEndian16(address.sockaddr.in6.sin6_port), 1234);


	address = OFSocketAddressParseIP(@"::", 1234);
	OTAssert(COMPARE_V6(address, 0, 0, 0, 0, 0, 0, 0, 0));
	OTAssertEqual(OFFromBigEndian16(address.sockaddr.in6.sin6_port), 1234);


	address = OFSocketAddressParseIP(@"aaAa::bBbb", 1234);
	OTAssert(COMPARE_V6(address, 0xAAAA, 0, 0, 0, 0, 0, 0, 0xBBBB));
	OTAssertEqual(OFFromBigEndian16(address.sockaddr.in6.sin6_port), 1234);


	address = OFSocketAddressParseIP(@"aaAa::", 1234);
	OTAssert(COMPARE_V6(address, 0xAAAA, 0, 0, 0, 0, 0, 0, 0));
	OTAssertEqual(OFFromBigEndian16(address.sockaddr.in6.sin6_port), 1234);


	address = OFSocketAddressParseIP(@"::aaAa", 1234);
	OTAssert(COMPARE_V6(address, 0, 0, 0, 0, 0, 0, 0, 0xAAAA));
	OTAssertEqual(OFFromBigEndian16(address.sockaddr.in6.sin6_port), 1234);


	address = OFSocketAddressParseIP(@"fd00::1%123", 1234);
	OTAssert(COMPARE_V6(address, 0xFD00, 0, 0, 0, 0, 0, 0, 1));
	OTAssertEqual(OFFromBigEndian16(address.sockaddr.in6.sin6_port), 1234);
	OTAssertEqual(address.sockaddr.in6.sin6_scope_id, 123);


	address = OFSocketAddressParseIP(@"::ffff:127.0.0.1", 1234);
	OTAssert(COMPARE_V6(address, 0, 0, 0, 0, 0, 0xFFFF, 0x7F00, 1));
	OTAssertEqual(OFFromBigEndian16(address.sockaddr.in6.sin6_port), 1234);


	address = OFSocketAddressParseIP(@"64:ff9b::127.0.0.1", 1234);
	OTAssert(COMPARE_V6(address, 0x64, 0xFF9B, 0, 0, 0, 0, 0x7F00, 1));
	OTAssertEqual(OFFromBigEndian16(address.sockaddr.in6.sin6_port), 1234);
}

- (void)testParseRejectsInvalidIPv6
{
	OTAssertThrowsSpecific(OFSocketAddressParseIP(@"1:::2", 1234),
	    OFInvalidFormatException);


	OTAssertThrowsSpecific(OFSocketAddressParseIP(@"1: ::2", 1234),
	    OFInvalidFormatException);


	OTAssertThrowsSpecific(OFSocketAddressParseIP(@"1:: :2", 1234),
	    OFInvalidFormatException);


	OTAssertThrowsSpecific(OFSocketAddressParseIP(@"1::2::3", 1234),
	    OFInvalidFormatException);


	OTAssertThrowsSpecific(OFSocketAddressParseIP(@"10000::1", 1234),
	    OFInvalidFormatException);

	OTAssertThrowsSpecific(OFSocketAddressParseIP(@"::10000", 1234),
	    OFInvalidFormatException);



	OTAssertThrowsSpecific(OFSocketAddressParseIP(@"::1::", 1234),
	    OFInvalidFormatException);


	OTAssertThrowsSpecific(OFSocketAddressParseIP(@"1:2:3:4:5:6:7:", 1234),
	    OFInvalidFormatException);

	OTAssertThrowsSpecific(OFSocketAddressParseIP(@"1:2:3:4:5:6:7::", 1234),
	    OFInvalidFormatException);

	OTAssertThrowsSpecific(OFSocketAddressParseIP(@"1:2", 1234),
	    OFInvalidFormatException);
}

- (void)testPortForIPv6
{
	OFSocketAddress address = OFSocketAddressParseIP(@"::", 1234);

	OTAssertEqual(OFSocketAddressIPPort(&address), 1234);
}

- (void)testStringForIPv6
{
	OFSocketAddress address = OFSocketAddressParseIP(@"::", 1234);


	OTAssertEqualObjects(OFSocketAddressString(&address), @"::");

	SET_V6(address, 0, 0, 0, 0, 0, 0, 0, 1)

	OTAssertEqualObjects(OFSocketAddressString(&address), @"::1");

	SET_V6(address, 1, 0, 0, 0, 0, 0, 0, 0)

	OTAssertEqualObjects(OFSocketAddressString(&address), @"1::");

	SET_V6(address,
	    0x1122, 0x3344, 0x5566, 0x7788, 0x99AA, 0xBBCC, 0xDDEE, 0xFF00)

	OTAssertEqualObjects(OFSocketAddressString(&address),
	    @"1122:3344:5566:7788:99aa:bbcc:ddee:ff00");

	SET_V6(address,
	    0x1122, 0x3344, 0x5566, 0x7788, 0x99AA, 0xBBCC, 0xDDEE, 0)

	OTAssertEqualObjects(OFSocketAddressString(&address),
	    @"1122:3344:5566:7788:99aa:bbcc:ddee:0");

	SET_V6(address, 0x1122, 0x3344, 0x5566, 0x7788, 0x99AA, 0xBBCC, 0, 0)

	OTAssertEqualObjects(OFSocketAddressString(&address),
	    @"1122:3344:5566:7788:99aa:bbcc::");

	SET_V6(address,
	    0, 0x3344, 0x5566, 0x7788, 0x99AA, 0xBBCC, 0xDDEE, 0xFF00)

	OTAssertEqualObjects(OFSocketAddressString(&address),
	    @"0:3344:5566:7788:99aa:bbcc:ddee:ff00");

	SET_V6(address, 0, 0, 0x5566, 0x7788, 0x99AA, 0xBBCC, 0xDDEE, 0xFF00)

	OTAssertEqualObjects(OFSocketAddressString(&address),
	    @"::5566:7788:99aa:bbcc:ddee:ff00");

	SET_V6(address, 0, 0, 0x5566, 0, 0, 0, 0xDDEE, 0xFF00)

	OTAssertEqualObjects(OFSocketAddressString(&address),
	    @"0:0:5566::ddee:ff00");

	SET_V6(address, 0, 0, 0x5566, 0x7788, 0x99AA, 0xBBCC, 0, 0)

	OTAssertEqualObjects(OFSocketAddressString(&address),
	    @"::5566:7788:99aa:bbcc:0:0");


	address.sockaddr.in6.sin6_scope_id = 123;
	OTAssertEqualObjects(OFSocketAddressString(&address),
	    @"::5566:7788:99aa:bbcc:0:0%123");
}
@end

Added new_tests/OFSubprocessTests.m version [bf448d2b80].









































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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-2024 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#import "ObjFW.h"
#import "ObjFWTest.h"

@interface OFSubprocessTests: OTTestCase
@end

@implementation OFSubprocessTests
- (void)testSubprocess
{
#ifdef OF_HAVE_FILES
	OFString *program = [@"subprocess" stringByAppendingPathComponent:
	    @"subprocess" @PROG_SUFFIX];
#else
	OFString *program = @"subprocess/subprocess" @PROG_SUFFIX;
#endif
	OFArray *arguments = [OFArray arrayWithObjects: @"tést", @"123", nil];
	OFMutableDictionary *environment =
	    [[[OFApplication environment] mutableCopy] autorelease];
	OFSubprocess *subprocess;

	[environment setObject: @"yés" forKey: @"tëst"];

	subprocess = [OFSubprocess subprocessWithProgram: program
					     programName: program
					       arguments: arguments
					     environment: environment];

	[subprocess writeLine: @"Hellö world!"];
	OTAssertEqualObjects([subprocess readLine], @"HELLÖ WORLD!");

	[subprocess closeForWriting];

	OTAssertEqual([subprocess waitForTermination], 0);
}
@end

Renamed and modified tests/OFThreadTests.m [bbeb8a5fbf] to new_tests/OFThreadTests.m [b2b1434e44].

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
 * 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 = @"OFThread";


@interface TestThread: OFThread
@end

@implementation TestThread
- (id)main
{
	[[OFThread threadDictionary] setObject: @"bar" forKey: @"foo"];
	OFEnsure([[[OFThread threadDictionary]
	    objectForKey: @"foo"] isEqual: @"bar"]);

	return @"success";
}
@end

@implementation TestsAppDelegate (OFThreadTests)
- (void)threadTests
{
	void *pool = objc_autoreleasePoolPush();
	TestThread *thread;

	TEST(@"+[thread]", (thread = [TestThread thread]))

	TEST(@"-[start]", R([thread start]))

	TEST(@"-[join]", [[thread join] isEqual: @"success"])

	TEST(@"-[threadDictionary]",
	    [[OFThread threadDictionary] objectForKey: @"foo"] == nil)

	objc_autoreleasePoolPop(pool);
}
@end







|
>

|
>















|
|

<
|

<
<
|

<
|
<
|
|
<
<

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
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#import "ObjFW.h"
#import "ObjFWTest.h"

@interface OFThreadTests: OTTestCase
@end

@interface TestThread: OFThread
@end

@implementation TestThread
- (id)main
{
	[[OFThread threadDictionary] setObject: @"bar" forKey: @"foo"];
	OFEnsure([[[OFThread threadDictionary]
	    objectForKey: @"foo"] isEqual: @"bar"]);

	return @"success";
}
@end

@implementation OFThreadTests
- (void)testThread
{

	TestThread *thread = [TestThread thread];



	[thread start];


	OTAssertEqualObjects([thread join], @"success");

	OTAssertNil([[OFThread threadDictionary] objectForKey: @"foo"]);
}


@end

Name change from tests/plugin/Info.plist.in to new_tests/plugin/Info.plist.in.

Name change from tests/plugin/Makefile to new_tests/plugin/Makefile.

Name change from tests/plugin/TestPlugin.h to new_tests/plugin/TestPlugin.h.

Name change from tests/plugin/TestPlugin.m to new_tests/plugin/TestPlugin.m.

Added new_tests/subprocess/Makefile version [0c326652cc].



















>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
PROG_NOINST = subprocess${PROG_SUFFIX}
SRCS = Subprocess.m

include ../../buildsys.mk
include ../../extra.mk

CPPFLAGS += -I../../src -I../../src/exceptions -I../../src/runtime -I../..
LIBS := -L../../src -lobjfw -L../../src/runtime ${RUNTIME_LIBS} ${LIBS}
LD = ${OBJC}

Added new_tests/subprocess/Subprocess.m version [31a1046120].























































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
/*
 * Copyright (c) 2008-2024 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#import "ObjFW.h"

@interface Subprocess: OFObject <OFApplicationDelegate>
@end

OF_APPLICATION_DELEGATE(Subprocess)

@implementation Subprocess
- (void)applicationDidFinishLaunching: (OFNotification *)notification
{
	OFString *line;

	if (![[OFApplication arguments] isEqual:
	    [OFArray arrayWithObjects: @"tést", @"123", nil]])
		[OFApplication terminateWithStatus: 1];

	if (![[[OFApplication environment] objectForKey: @"tëst"]
	    isEqual: @"yés"])
		[OFApplication terminateWithStatus: 2];

	while ((line = [OFStdIn readLine]) != nil)
		[OFStdOut writeLine: line.uppercaseString];

	[OFApplication terminate];
}
@end

Added new_tests/testfile.bin version [ac78121630].

cannot compute difference between binary files

Renamed and modified tests/testfile.ini [70f0fff498] to new_tests/testfile.ini [9e2ef2dc1a].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
[tests]
foo = bar
foobar=baz
;comment

[foobar]
;foobarcomment
qux=" asd"
"quxqux " = asd
quxquxqux="hello\"w”rld"
qux2="a\f"

[types]
integer = 0x20
bool = true
float = 0.5
array1 = 1
array2 = 1
double = 0.25
array1 = 2
array2 = 2









|











1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
[tests]
foo = bar
foobar=baz
;comment

[foobar]
;foobarcomment
qux=" asd"
"quxqux " = asd
quxquxqux="hello\"rld"
qux2="a\f"

[types]
integer = 0x20
bool = true
float = 0.5
array1 = 1
array2 = 1
double = 0.25
array1 = 2
array2 = 2

Modified src/Makefile from [4b678f2acf] to [f68b2dbc03].

1
2
3
4
5
6
7
8
9
10
11
include ../extra.mk

SUBDIRS = ${RUNTIME} exceptions encodings forwarding
SUBDIRS_AFTER = ${BRIDGE} ${TLS}
DISTCLEAN = Info.plist objfw-defs.h

SHARED_LIB = ${OBJFW_SHARED_LIB}
STATIC_LIB = ${OBJFW_STATIC_LIB}
FRAMEWORK = ${OBJFW_FRAMEWORK}
LIB_MAJOR = ${OBJFW_LIB_MAJOR}
LIB_MINOR = ${OBJFW_LIB_MINOR}



|







1
2
3
4
5
6
7
8
9
10
11
include ../extra.mk

SUBDIRS = ${RUNTIME} exceptions encodings forwarding
SUBDIRS_AFTER = ${BRIDGE} ${TLS} test
DISTCLEAN = Info.plist objfw-defs.h

SHARED_LIB = ${OBJFW_SHARED_LIB}
STATIC_LIB = ${OBJFW_STATIC_LIB}
FRAMEWORK = ${OBJFW_FRAMEWORK}
LIB_MAJOR = ${OBJFW_LIB_MAJOR}
LIB_MINOR = ${OBJFW_LIB_MINOR}
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
       OFString.m			\
       OFString+CryptographicHashing.m	\
       OFString+JSONParsing.m		\
       OFString+PercentEncoding.m	\
       OFString+PropertyListParsing.m	\
       OFString+XMLEscaping.m		\
       OFString+XMLUnescaping.m		\
       ${OF_SUBPROCESS_M}		\
       OFSystemInfo.m			\
       OFTarArchive.m			\
       OFTarArchiveEntry.m		\
       OFThread.m			\
       OFTimer.m			\
       OFTriple.m			\
       OFUUID.m				\







<







94
95
96
97
98
99
100

101
102
103
104
105
106
107
       OFString.m			\
       OFString+CryptographicHashing.m	\
       OFString+JSONParsing.m		\
       OFString+PercentEncoding.m	\
       OFString+PropertyListParsing.m	\
       OFString+XMLEscaping.m		\
       OFString+XMLUnescaping.m		\

       OFSystemInfo.m			\
       OFTarArchive.m			\
       OFTarArchiveEntry.m		\
       OFThread.m			\
       OFTimer.m			\
       OFTriple.m			\
       OFUUID.m				\
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
       OFXMLParser.m			\
       OFXMLProcessingInstruction.m	\
       OFZIPArchive.m			\
       OFZIPArchiveEntry.m		\
       ${USE_SRCS_FILES}		\
       ${USE_SRCS_PLUGINS}		\
       ${USE_SRCS_SOCKETS}		\

       ${USE_SRCS_THREADS}		\
       ${USE_SRCS_WINDOWS}
SRCS_FILES = OFFile.m			\
	     OFString+PathAdditions.m
SRCS_PLUGINS = OFPlugin.m



SRCS_SOCKETS = OFDNSQuery.m			\
	       OFDNSResolver.m			\
	       OFDNSResourceRecord.m		\
	       OFDNSResponse.m			\
	       OFDatagramSocket.m		\

	       OFHTTPClient.m			\
	       OFHTTPCookie.m			\
	       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
SRCS_IPX = OFIPXSocket.m	\
	   OFSPXSocket.m	\
	   OFSPXStreamSocket.m
SRCS_UNIX_SOCKETS = OFUNIXDatagramSocket.m	\
		    OFUNIXStreamSocket.m

SRCS_THREADS = OFCondition.m		\
	       OFMutex.m		\
	       OFPlainCondition.m	\
	       OFPlainMutex.m		\
	       OFPlainThread.m		\
	       OFRecursiveMutex.m	\
	       OFTLSKey.m







>





>
>
>
|




>






>
>
>
>
>
>
>






>

>









>







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
       OFXMLParser.m			\
       OFXMLProcessingInstruction.m	\
       OFZIPArchive.m			\
       OFZIPArchiveEntry.m		\
       ${USE_SRCS_FILES}		\
       ${USE_SRCS_PLUGINS}		\
       ${USE_SRCS_SOCKETS}		\
       ${USE_SRCS_SUBPROCESSES}		\
       ${USE_SRCS_THREADS}		\
       ${USE_SRCS_WINDOWS}
SRCS_FILES = OFFile.m			\
	     OFString+PathAdditions.m
SRCS_PLUGINS = OFPlugin.m
SRCS_SOCKETS = OFAAAADNSResourceRecord.m	\
	       OFADNSResourceRecord.m		\
	       OFCNAMEDNSResourceRecord.m	\
	       OFDNSQuery.m			\
	       OFDNSResolver.m			\
	       OFDNSResourceRecord.m		\
	       OFDNSResponse.m			\
	       OFDatagramSocket.m		\
	       OFHINFODNSResourceRecord.m	\
	       OFHTTPClient.m			\
	       OFHTTPCookie.m			\
	       OFHTTPCookieManager.m		\
	       OFHTTPRequest.m			\
	       OFHTTPResponse.m			\
	       OFHTTPServer.m			\
	       OFLOCDNSResourceRecord.m		\
	       OFMXDNSResourceRecord.m		\
	       OFNSDNSResourceRecord.m		\
	       OFPTRDNSResourceRecord.m		\
	       OFRPDNSResourceRecord.m		\
	       OFSOADNSResourceRecord.m		\
	       OFSRVDNSResourceRecord.m		\
	       OFSequencedPacketSocket.m	\
	       OFSocket.m			\
	       OFStreamSocket.m			\
	       OFSystemInfo+NetworkInterfaces.m	\
	       OFTCPSocket.m			\
	       OFTLSStream.m			\
	       OFTXTDNSResourceRecord.m		\
	       OFUDPSocket.m			\
	       OFURIDNSResourceRecord.m		\
	       ${USE_SRCS_APPLETALK}		\
	       ${USE_SRCS_IPX}			\
	       ${USE_SRCS_UNIX_SOCKETS}
SRCS_APPLETALK = OFDDPSocket.m
SRCS_IPX = OFIPXSocket.m	\
	   OFSPXSocket.m	\
	   OFSPXStreamSocket.m
SRCS_UNIX_SOCKETS = OFUNIXDatagramSocket.m	\
		    OFUNIXStreamSocket.m
SRCS_SUBPROCESSES = OFSubprocess.m
SRCS_THREADS = OFCondition.m		\
	       OFMutex.m		\
	       OFPlainCondition.m	\
	       OFPlainMutex.m		\
	       OFPlainThread.m		\
	       OFRecursiveMutex.m	\
	       OFTLSKey.m

Added src/OFAAAADNSResourceRecord.h version [df140be2a8].

















































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
/*
 * Copyright (c) 2008-2024 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the 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 "OFDNSResourceRecord.h"

OF_ASSUME_NONNULL_BEGIN

/**
 * @class OFAAAADNSResourceRecord \
 *	  OFDNSResourceRecord.h ObjFW/OFDNSResourceRecord.h
 *
 * @brief A class representing a DNS resource record.
 */
OF_SUBCLASSING_RESTRICTED
@interface OFAAAADNSResourceRecord: OFDNSResourceRecord
{
	OFSocketAddress _address;
}

/**
 * @brief The IPv6 address of the resource record.
 */
@property (readonly, nonatomic) const OFSocketAddress *address;

- (instancetype)initWithName: (OFString *)name
		    DNSClass: (OFDNSClass)DNSClass
		  recordType: (OFDNSRecordType)recordType
			 TTL: (uint32_t)TTL OF_UNAVAILABLE;

/**
 * @brief Initializes an already allocated OFAAAADNSResourceRecord with the
 *	  specified name, class, address and time to live.
 *
 * @param name The name for the resource record
 * @param address The address for the resource record
 * @param TTL The time to live for the resource record
 * @return An initialized OFAAAADNSResourceRecord
 */
- (instancetype)initWithName: (OFString *)name
		     address: (const OFSocketAddress *)address
			 TTL: (uint32_t)TTL OF_DESIGNATED_INITIALIZER;
@end

OF_ASSUME_NONNULL_END

Added src/OFAAAADNSResourceRecord.m version [2d5bfd748d].















































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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-2024 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the 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 "OFAAAADNSResourceRecord.h"

@implementation OFAAAADNSResourceRecord
- (instancetype)initWithName: (OFString *)name
		    DNSClass: (OFDNSClass)DNSClass
		  recordType: (OFDNSRecordType)recordType
			 TTL: (uint32_t)TTL
{
	OF_INVALID_INIT_METHOD
}

- (instancetype)initWithName: (OFString *)name
		     address: (const OFSocketAddress *)address
			 TTL: (uint32_t)TTL
{
	self = [super initWithName: name
			  DNSClass: OFDNSClassIN
			recordType: OFDNSRecordTypeAAAA
			       TTL: TTL];

	_address = *address;

	return self;
}

- (const OFSocketAddress *)address
{
	return &_address;
}

- (bool)isEqual: (id)object
{
	OFAAAADNSResourceRecord *record;

	if (object == self)
		return true;

	if (![object isKindOfClass: [OFAAAADNSResourceRecord class]])
		return false;

	record = object;

	if (record->_name != _name && ![record->_name isEqual: _name])
		return false;

	if (record->_DNSClass != _DNSClass)
		return false;

	if (record->_recordType != _recordType)
		return false;

	if (!OFSocketAddressEqual(&record->_address, &_address))
		return false;

	return true;
}

- (unsigned long)hash
{
	unsigned long hash;

	OFHashInit(&hash);

	OFHashAddHash(&hash, _name.hash);
	OFHashAddByte(&hash, _DNSClass >> 8);
	OFHashAddByte(&hash, _DNSClass);
	OFHashAddByte(&hash, _recordType >> 8);
	OFHashAddByte(&hash, _recordType);
	OFHashAddHash(&hash, OFSocketAddressHash(&_address));

	OFHashFinalize(&hash);

	return hash;
}

- (OFString *)description
{
	return [OFString stringWithFormat:
	    @"<%@:\n"
	    @"\tName = %@\n"
	    @"\tAddress = %@\n"
	    @"\tTTL = %" PRIu32 "\n"
	    @">",
	    self.className, _name, OFSocketAddressString(&_address), _TTL];
}
@end

Added src/OFADNSResourceRecord.h version [5165cfa9be].















































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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-2024 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the 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 "OFDNSResourceRecord.h"

OF_ASSUME_NONNULL_BEGIN

/**
 * @class OFADNSResourceRecord OFDNSResourceRecord.h ObjFW/OFDNSResourceRecord.h
 *
 * @brief A class representing an A DNS resource record.
 */
OF_SUBCLASSING_RESTRICTED
@interface OFADNSResourceRecord: OFDNSResourceRecord
{
	OFSocketAddress _address;
}

/**
 * @brief The IPv4 address of the resource record.
 */
@property (readonly, nonatomic) const OFSocketAddress *address;

- (instancetype)initWithName: (OFString *)name
		    DNSClass: (OFDNSClass)DNSClass
		  recordType: (OFDNSRecordType)recordType
			 TTL: (uint32_t)TTL OF_UNAVAILABLE;

/**
 * @brief Initializes an already allocated OFADNSResourceRecord with the
 *	  specified name, class, address and time to live.
 *
 * @param name The name for the resource record
 * @param address The address for the resource record
 * @param TTL The time to live for the resource record
 * @return An initialized OFADNSResourceRecord
 */
- (instancetype)initWithName: (OFString *)name
		     address: (const OFSocketAddress *)address
			 TTL: (uint32_t)TTL OF_DESIGNATED_INITIALIZER;
@end

OF_ASSUME_NONNULL_END

Added src/OFADNSResourceRecord.m version [59d40bea74].















































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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-2024 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the 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 "OFADNSResourceRecord.h"

@implementation OFADNSResourceRecord
- (instancetype)initWithName: (OFString *)name
		    DNSClass: (OFDNSClass)DNSClass
		  recordType: (OFDNSRecordType)recordType
			 TTL: (uint32_t)TTL
{
	OF_INVALID_INIT_METHOD
}

- (instancetype)initWithName: (OFString *)name
		     address: (const OFSocketAddress *)address
			 TTL: (uint32_t)TTL
{
	self = [super initWithName: name
			  DNSClass: OFDNSClassIN
			recordType: OFDNSRecordTypeA
			       TTL: TTL];

	_address = *address;

	return self;
}

- (const OFSocketAddress *)address
{
	return &_address;
}

- (bool)isEqual: (id)object
{
	OFADNSResourceRecord *record;

	if (object == self)
		return true;

	if (![object isKindOfClass: [OFADNSResourceRecord class]])
		return false;

	record = object;

	if (record->_name != _name && ![record->_name isEqual: _name])
		return false;

	if (record->_DNSClass != _DNSClass)
		return false;

	if (record->_recordType != _recordType)
		return false;

	if (!OFSocketAddressEqual(&record->_address, &_address))
		return false;

	return true;
}

- (unsigned long)hash
{
	unsigned long hash;

	OFHashInit(&hash);

	OFHashAddHash(&hash, _name.hash);
	OFHashAddByte(&hash, _DNSClass >> 8);
	OFHashAddByte(&hash, _DNSClass);
	OFHashAddByte(&hash, _recordType >> 8);
	OFHashAddByte(&hash, _recordType);
	OFHashAddHash(&hash, OFSocketAddressHash(&_address));

	OFHashFinalize(&hash);

	return hash;
}

- (OFString *)description
{
	return [OFString stringWithFormat:
	    @"<%@:\n"
	    @"\tName = %@\n"
	    @"\tAddress = %@\n"
	    @"\tTTL = %" PRIu32 "\n"
	    @">",
	    self.className, _name, OFSocketAddressString(&_address), _TTL];
}
@end

Added src/OFCNAMEDNSResourceRecord.h version [4cffe1ae4c].





















































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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-2024 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the 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 "OFDNSResourceRecord.h"

OF_ASSUME_NONNULL_BEGIN

/**
 * @class OFCNAMEDNSResourceRecord \
 *	  OFDNSResourceRecord.h ObjFW/OFDNSResourceRecord.h
 *
 * @brief A class representing a CNAME DNS resource record.
 */
OF_SUBCLASSING_RESTRICTED
@interface OFCNAMEDNSResourceRecord: OFDNSResourceRecord
{
	OFString *_alias;
}

/**
 * @brief The alias of the resource record.
 */
@property (readonly, nonatomic) OFString *alias;

- (instancetype)initWithName: (OFString *)name
		    DNSClass: (OFDNSClass)DNSClass
		  recordType: (OFDNSRecordType)recordType
			 TTL: (uint32_t)TTL OF_UNAVAILABLE;

/**
 * @brief Initializes an already allocated OFCNAMEDNSResourceRecord with the
 *	  specified name, class, alias and time to live.
 *
 * @param name The name for the resource record
 * @param DNSClass The class code for the resource record
 * @param alias The alias for the resource record
 * @param TTL The time to live for the resource record
 * @return An initialized OFCNAMEDNSResourceRecord
 */
- (instancetype)initWithName: (OFString *)name
		    DNSClass: (OFDNSClass)DNSClass
		       alias: (OFString *)alias
			 TTL: (uint32_t)TTL OF_DESIGNATED_INITIALIZER;
@end

OF_ASSUME_NONNULL_END

Added src/OFCNAMEDNSResourceRecord.m version [68babb6a4c].





































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
/*
 * Copyright (c) 2008-2024 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the 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 "OFCNAMEDNSResourceRecord.h"

@implementation OFCNAMEDNSResourceRecord
@synthesize alias = _alias;

- (instancetype)initWithName: (OFString *)name
		    DNSClass: (OFDNSClass)DNSClass
		  recordType: (OFDNSRecordType)recordType
			 TTL: (uint32_t)TTL
{
	OF_INVALID_INIT_METHOD
}

- (instancetype)initWithName: (OFString *)name
		    DNSClass: (OFDNSClass)DNSClass
		       alias: (OFString *)alias
			 TTL: (uint32_t)TTL
{
	self = [super initWithName: name
			  DNSClass: DNSClass
			recordType: OFDNSRecordTypeCNAME
			       TTL: TTL];

	@try {
		_alias = [alias copy];
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (void)dealloc
{
	[_alias release];

	[super dealloc];
}

- (bool)isEqual: (id)object
{
	OFCNAMEDNSResourceRecord *record;

	if (object == self)
		return true;

	if (![object isKindOfClass: [OFCNAMEDNSResourceRecord class]])
		return false;

	record = object;

	if (record->_name != _name && ![record->_name isEqual: _name])
		return false;

	if (record->_DNSClass != _DNSClass)
		return false;

	if (record->_recordType != _recordType)
		return false;

	if (record->_alias != _alias && ![record->_alias isEqual: _alias])
		return false;

	return true;
}

- (unsigned long)hash
{
	unsigned long hash;

	OFHashInit(&hash);

	OFHashAddHash(&hash, _name.hash);
	OFHashAddByte(&hash, _DNSClass >> 8);
	OFHashAddByte(&hash, _DNSClass);
	OFHashAddByte(&hash, _recordType >> 8);
	OFHashAddByte(&hash, _recordType);
	OFHashAddHash(&hash, _alias.hash);

	OFHashFinalize(&hash);

	return hash;
}

- (OFString *)description
{
	return [OFString stringWithFormat:
	    @"<%@:\n"
	    @"\tName = %@\n"
	    @"\tClass = %@\n"
	    @"\tAlias = %@\n"
	    @"\tTTL = %" PRIu32 "\n"
	    @">",
	    self.className, _name, OFDNSClassName(_DNSClass), _alias, _TTL];
}
@end

Modified src/OFColor.h from [7160d2b484] to [26802d5b43].

22
23
24
25
26
27
28

29

30
31
32
33
34
35
36
 *
 * @brief A class for storing a color.
 */
@interface OFColor: OFObject
#ifdef OF_HAVE_CLASS_PROPERTIES
@property (class, readonly, nonatomic) OFColor *black;
@property (class, readonly, nonatomic) OFColor *silver;

@property (class, readonly, nonatomic) OFColor *grey;

@property (class, readonly, nonatomic) OFColor *white;
@property (class, readonly, nonatomic) OFColor *maroon;
@property (class, readonly, nonatomic) OFColor *red;
@property (class, readonly, nonatomic) OFColor *purple;
@property (class, readonly, nonatomic) OFColor *fuchsia;
@property (class, readonly, nonatomic) OFColor *green;
@property (class, readonly, nonatomic) OFColor *lime;







>
|
>







22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
 *
 * @brief A class for storing a color.
 */
@interface OFColor: OFObject
#ifdef OF_HAVE_CLASS_PROPERTIES
@property (class, readonly, nonatomic) OFColor *black;
@property (class, readonly, nonatomic) OFColor *silver;
@property (class, readonly, nonatomic) OFColor *gray;
@property (class, readonly, nonatomic) OFColor *grey
    OF_DEPRECATED(ObjFW, 1, 1, "Use gray instead");
@property (class, readonly, nonatomic) OFColor *white;
@property (class, readonly, nonatomic) OFColor *maroon;
@property (class, readonly, nonatomic) OFColor *red;
@property (class, readonly, nonatomic) OFColor *purple;
@property (class, readonly, nonatomic) OFColor *fuchsia;
@property (class, readonly, nonatomic) OFColor *green;
@property (class, readonly, nonatomic) OFColor *lime;
72
73
74
75
76
77
78
79











80
81
82
83
84
85
86
87
88
89
90
91
92
 * The RGBA value is (0.75, 0.75, 0.75, 1).
 *
 * @return The HTML color `silver`
 */
+ (OFColor *)silver;

/**
 * @brief Returns the HTML color `grey`.











 *
 * The RGBA value is (0.5, 0.5, 0.5, 1).
 *
 * @return The HTML color `grey`
 */
+ (OFColor *)grey;

/**
 * @brief Returns the HTML color `white`.
 *
 * The RGBA value is (1, 1, 1, 1).
 *
 * @return The HTML color `white`







|
>
>
>
>
>
>
>
>
>
>
>



|

|







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
 * The RGBA value is (0.75, 0.75, 0.75, 1).
 *
 * @return The HTML color `silver`
 */
+ (OFColor *)silver;

/**
 * @brief Returns the HTML color `gray`.
 *
 * The RGBA value is (0.5, 0.5, 0.5, 1).
 *
 * @return The HTML color `gray`
 */
+ (OFColor *)gray;

/**
 * @brief Returns the HTML color `gray`.
 *
 * @deprecated Use @ref gray instead.
 *
 * The RGBA value is (0.5, 0.5, 0.5, 1).
 *
 * @return The HTML color `gray`
 */
+ (OFColor *)grey OF_DEPRECATED(ObjFW, 1, 1, "Use gray instead");

/**
 * @brief Returns the HTML color `white`.
 *
 * The RGBA value is (1, 1, 1, 1).
 *
 * @return The HTML color `white`

Modified src/OFColor.m from [fa5fd20716] to [9779b523cd].

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
		OFOnce(&onceControl, initPredefinedColor_##name);	   \
									   \
		return name##Color;					   \
	}

PREDEFINED_COLOR(black,   0.00f, 0.00f, 0.00f)
PREDEFINED_COLOR(silver,  0.75f, 0.75f, 0.75f)
PREDEFINED_COLOR(grey,    0.50f, 0.50f, 0.50f)
PREDEFINED_COLOR(white,   1.00f, 1.00f, 1.00f)
PREDEFINED_COLOR(maroon,  0.50f, 0.00f, 0.00f)
PREDEFINED_COLOR(red,     1.00f, 0.00f, 0.00f)
PREDEFINED_COLOR(purple,  0.50f, 0.00f, 0.50f)
PREDEFINED_COLOR(fuchsia, 1.00f, 0.00f, 1.00f)
PREDEFINED_COLOR(green,   0.00f, 0.50f, 0.00f)
PREDEFINED_COLOR(lime,    0.00f, 1.00f, 0.00f)
PREDEFINED_COLOR(olive,   0.50f, 0.50f, 0.00f)
PREDEFINED_COLOR(yellow,  1.00f, 1.00f, 0.00f)
PREDEFINED_COLOR(navy,    0.00f, 0.00f, 0.50f)
PREDEFINED_COLOR(blue,    0.00f, 0.00f, 1.00f)
PREDEFINED_COLOR(teal,    0.00f, 0.50f, 0.50f)
PREDEFINED_COLOR(aqua,    0.00f, 1.00f, 1.00f)






+ (instancetype)colorWithRed: (float)red
		       green: (float)green
			blue: (float)blue
		       alpha: (float)alpha
{
	return [[[self alloc] initWithRed: red







|













>
>
>
>
>







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
		OFOnce(&onceControl, initPredefinedColor_##name);	   \
									   \
		return name##Color;					   \
	}

PREDEFINED_COLOR(black,   0.00f, 0.00f, 0.00f)
PREDEFINED_COLOR(silver,  0.75f, 0.75f, 0.75f)
PREDEFINED_COLOR(gray,    0.50f, 0.50f, 0.50f)
PREDEFINED_COLOR(white,   1.00f, 1.00f, 1.00f)
PREDEFINED_COLOR(maroon,  0.50f, 0.00f, 0.00f)
PREDEFINED_COLOR(red,     1.00f, 0.00f, 0.00f)
PREDEFINED_COLOR(purple,  0.50f, 0.00f, 0.50f)
PREDEFINED_COLOR(fuchsia, 1.00f, 0.00f, 1.00f)
PREDEFINED_COLOR(green,   0.00f, 0.50f, 0.00f)
PREDEFINED_COLOR(lime,    0.00f, 1.00f, 0.00f)
PREDEFINED_COLOR(olive,   0.50f, 0.50f, 0.00f)
PREDEFINED_COLOR(yellow,  1.00f, 1.00f, 0.00f)
PREDEFINED_COLOR(navy,    0.00f, 0.00f, 0.50f)
PREDEFINED_COLOR(blue,    0.00f, 0.00f, 1.00f)
PREDEFINED_COLOR(teal,    0.00f, 0.50f, 0.50f)
PREDEFINED_COLOR(aqua,    0.00f, 1.00f, 1.00f)

+ (OFColor *)grey
{
	return [self gray];
}

+ (instancetype)colorWithRed: (float)red
		       green: (float)green
			blue: (float)blue
		       alpha: (float)alpha
{
	return [[[self alloc] initWithRed: red

Modified src/OFDNSResolver.m from [b89d5a3a8f] to [294ed882f2].

375
376
377
378
379
380
381



























382
383
384
385
386
387
388
#endif
		memcpy(address.sockaddr.in6.sin6_addr.s6_addr, buffer + i, 16);

		return [[[OFAAAADNSResourceRecord alloc]
		    initWithName: name
			 address: &address
			     TTL: TTL] autorelease];



























	} else if (recordType == OFDNSRecordTypeSRV &&
	    DNSClass == OFDNSClassIN) {
		uint16_t priority, weight, port;
		size_t j;
		OFString *target;

		if (dataLength < 6)







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







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
#endif
		memcpy(address.sockaddr.in6.sin6_addr.s6_addr, buffer + i, 16);

		return [[[OFAAAADNSResourceRecord alloc]
		    initWithName: name
			 address: &address
			     TTL: TTL] autorelease];
	} else if (recordType == OFDNSRecordTypeLOC) {
		uint8_t size, horizontalPrecision, verticalPrecision;
		uint32_t latitude, longitude, altitude;

		if (dataLength < 16 || buffer[i] != 0)
			@throw [OFInvalidServerResponseException exception];

		size = buffer[i + 1];
		horizontalPrecision = buffer[i + 2];
		verticalPrecision = buffer[i + 3];
		latitude = (buffer[i + 4] << 24) | (buffer[i + 5] << 16) |
		    (buffer[i + 6] << 8) | buffer[i + 7];
		longitude = (buffer[i + 8] << 24) | (buffer[i + 9] << 16) |
		    (buffer[i + 10] << 8) | buffer[i + 11];
		altitude = (buffer[i + 12] << 24) | (buffer[i + 13] << 16) |
		    (buffer[i + 14] << 8) | buffer[i + 15];

		return [[[OFLOCDNSResourceRecord alloc]
			   initWithName: name
			       DNSClass: DNSClass
				   size: size
		    horizontalPrecision: horizontalPrecision
		      verticalPrecision: verticalPrecision
			       latitude: latitude
			      longitude: longitude
			       altitude: altitude
				    TTL: TTL] autorelease];
	} else if (recordType == OFDNSRecordTypeSRV &&
	    DNSClass == OFDNSClassIN) {
		uint16_t priority, weight, port;
		size_t j;
		OFString *target;

		if (dataLength < 6)
400
401
402
403
404
405
406




















407
408
409
410
411
412
413

		return [[[OFSRVDNSResourceRecord alloc]
		    initWithName: name
			priority: priority
			  weight: weight
			  target: target
			    port: port




















			     TTL: TTL] autorelease];
	} else
		return [[[OFDNSResourceRecord alloc]
		    initWithName: name
			DNSClass: DNSClass
		      recordType: recordType
			     TTL: TTL] autorelease];







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







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

		return [[[OFSRVDNSResourceRecord alloc]
		    initWithName: name
			priority: priority
			  weight: weight
			  target: target
			    port: port
			     TTL: TTL] autorelease];
	} else if (recordType == OFDNSRecordTypeURI) {
		uint16_t priority, weight;
		OFString *target;

		if (dataLength < 4)
			@throw [OFInvalidServerResponseException exception];

		priority = (buffer[i] << 8) | buffer[i + 1];
		weight = (buffer[i + 2] << 8) | buffer[i + 3];

		target = [OFString stringWithUTF8String: (char *)buffer + i + 4
						 length: dataLength - 4];

		return [[[OFURIDNSResourceRecord alloc]
		    initWithName: name
			DNSClass: DNSClass
			priority: priority
			  weight: weight
			  target: target
			     TTL: TTL] autorelease];
	} else
		return [[[OFDNSResourceRecord alloc]
		    initWithName: name
			DNSClass: DNSClass
		      recordType: recordType
			     TTL: TTL] autorelease];
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
		uint32_t TTL;
		uint16_t dataLength;
		OFDNSResourceRecord *record;

		if (*i + 10 > length)
			@throw [OFTruncatedDataException exception];

		recordType = (buffer[*i] << 16) | buffer[*i + 1];
		DNSClass = (buffer[*i + 2] << 16) | buffer[*i + 3];
		TTL = (buffer[*i + 4] << 24) | (buffer[*i + 5] << 16) |
		    (buffer[*i + 6] << 8) | buffer[*i + 7];
		dataLength = (buffer[*i + 8] << 16) | buffer[*i + 9];

		*i += 10;

		if (*i + dataLength > length)
			@throw [OFTruncatedDataException exception];

		record = parseResourceRecord(name, DNSClass, recordType, TTL,







|
|


|







476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
		uint32_t TTL;
		uint16_t dataLength;
		OFDNSResourceRecord *record;

		if (*i + 10 > length)
			@throw [OFTruncatedDataException exception];

		recordType = (buffer[*i] << 8) | buffer[*i + 1];
		DNSClass = (buffer[*i + 2] << 8) | buffer[*i + 3];
		TTL = (buffer[*i + 4] << 24) | (buffer[*i + 5] << 16) |
		    (buffer[*i + 6] << 8) | buffer[*i + 7];
		dataLength = (buffer[*i + 8] << 8) | buffer[*i + 9];

		*i += 10;

		if (*i + dataLength > length)
			@throw [OFTruncatedDataException exception];

		record = parseResourceRecord(name, DNSClass, recordType, TTL,

Modified src/OFDNSResourceRecord.h from [32d9ec1f01] to [97a2085498].

54
55
56
57
58
59
60


61
62
63
64


65
66
67
68
69
70
71
	OFDNSRecordTypeMX    =  15,
	/** TXT */
	OFDNSRecordTypeTXT   =  16,
	/** RP */
	OFDNSRecordTypeRP    =  17,
	/** AAAA */
	OFDNSRecordTypeAAAA  =  28,


	/** SRV */
	OFDNSRecordTypeSRV   =  33,
	/** All types. Only for queries. */
	OFDNSRecordTypeAll   = 255,


} OFDNSRecordType;

/**
 * @class OFDNSResourceRecord OFDNSResourceRecord.h ObjFW/OFDNSResourceRecord.h
 *
 * @brief A class representing a DNS resource record.
 */







>
>




>
>







54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
	OFDNSRecordTypeMX    =  15,
	/** TXT */
	OFDNSRecordTypeTXT   =  16,
	/** RP */
	OFDNSRecordTypeRP    =  17,
	/** AAAA */
	OFDNSRecordTypeAAAA  =  28,
	/** LOC */
	OFDNSRecordTypeLOC   =  29,
	/** SRV */
	OFDNSRecordTypeSRV   =  33,
	/** All types. Only for queries. */
	OFDNSRecordTypeAll   = 255,
	/** URI */
	OFDNSRecordTypeURI   = 256,
} OFDNSRecordType;

/**
 * @class OFDNSResourceRecord OFDNSResourceRecord.h ObjFW/OFDNSResourceRecord.h
 *
 * @brief A class representing a DNS resource record.
 */
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
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
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
 */
- (instancetype)initWithName: (OFString *)name
		    DNSClass: (OFDNSClass)DNSClass
		  recordType: (OFDNSRecordType)recordType
			 TTL: (uint32_t)TTL OF_DESIGNATED_INITIALIZER;
@end

/**
 * @class OFADNSResourceRecord OFDNSResourceRecord.h ObjFW/OFDNSResourceRecord.h
 *
 * @brief A class representing an A DNS resource record.
 */
OF_SUBCLASSING_RESTRICTED
@interface OFADNSResourceRecord: OFDNSResourceRecord
{
	OFSocketAddress _address;
}

/**
 * @brief The IPv4 address of the resource record.
 */
@property (readonly, nonatomic) const OFSocketAddress *address;

- (instancetype)initWithName: (OFString *)name
		    DNSClass: (OFDNSClass)DNSClass
		  recordType: (OFDNSRecordType)recordType
			 TTL: (uint32_t)TTL OF_UNAVAILABLE;

/**
 * @brief Initializes an already allocated OFADNSResourceRecord with the
 *	  specified name, class, address and time to live.
 *
 * @param name The name for the resource record
 * @param address The address for the resource record
 * @param TTL The time to live for the resource record
 * @return An initialized OFADNSResourceRecord
 */
- (instancetype)initWithName: (OFString *)name
		     address: (const OFSocketAddress *)address
			 TTL: (uint32_t)TTL OF_DESIGNATED_INITIALIZER;
@end

/**
 * @class OFAAAADNSResourceRecord \
 *	  OFDNSResourceRecord.h ObjFW/OFDNSResourceRecord.h
 *
 * @brief A class represenging a DNS resource record.
 */
OF_SUBCLASSING_RESTRICTED
@interface OFAAAADNSResourceRecord: OFDNSResourceRecord
{
	OFSocketAddress _address;
}

/**
 * @brief The IPv6 address of the resource record.
 */
@property (readonly, nonatomic) const OFSocketAddress *address;

- (instancetype)initWithName: (OFString *)name
		    DNSClass: (OFDNSClass)DNSClass
		  recordType: (OFDNSRecordType)recordType
			 TTL: (uint32_t)TTL OF_UNAVAILABLE;

/**
 * @brief Initializes an already allocated OFAAAADNSResourceRecord with the
 *	  specified name, class, address and time to live.
 *
 * @param name The name for the resource record
 * @param address The address for the resource record
 * @param TTL The time to live for the resource record
 * @return An initialized OFAAAADNSResourceRecord
 */
- (instancetype)initWithName: (OFString *)name
		     address: (const OFSocketAddress *)address
			 TTL: (uint32_t)TTL OF_DESIGNATED_INITIALIZER;
@end

/**
 * @class OFCNAMEDNSResourceRecord \
 *	  OFDNSResourceRecord.h ObjFW/OFDNSResourceRecord.h
 *
 * @brief A class representing a CNAME DNS resource record.
 */
OF_SUBCLASSING_RESTRICTED
@interface OFCNAMEDNSResourceRecord: OFDNSResourceRecord
{
	OFString *_alias;
}

/**
 * @brief The alias of the resource record.
 */
@property (readonly, nonatomic) OFString *alias;

- (instancetype)initWithName: (OFString *)name
		    DNSClass: (OFDNSClass)DNSClass
		  recordType: (OFDNSRecordType)recordType
			 TTL: (uint32_t)TTL OF_UNAVAILABLE;

/**
 * @brief Initializes an already allocated OFCNAMEDNSResourceRecord with the
 *	  specified name, class, alias and time to live.
 *
 * @param name The name for the resource record
 * @param DNSClass The class code for the resource record
 * @param alias The alias for the resource record
 * @param TTL The time to live for the resource record
 * @return An initialized OFCNAMEDNSResourceRecord
 */
- (instancetype)initWithName: (OFString *)name
		    DNSClass: (OFDNSClass)DNSClass
		       alias: (OFString *)alias
			 TTL: (uint32_t)TTL OF_DESIGNATED_INITIALIZER;
@end

/**
 * @class OFHINFODNSResourceRecord \
 *	  OFDNSResourceRecord.h ObjFW/OFDNSResourceRecord.h
 *
 * @brief A class representing an HINFO DNS resource record.
 */
OF_SUBCLASSING_RESTRICTED
@interface OFHINFODNSResourceRecord: OFDNSResourceRecord
{
	OFString *_CPU, *_OS;
}

/**
 * @brief The CPU of the host info of the resource record.
 */
@property (readonly, nonatomic) OFString *CPU;

/**
 * @brief The OS of the host info of the resource record.
 */
@property (readonly, nonatomic) OFString *OS;

- (instancetype)initWithName: (OFString *)name
		    DNSClass: (OFDNSClass)DNSClass
		  recordType: (OFDNSRecordType)recordType
			 TTL: (uint32_t)TTL OF_UNAVAILABLE;

/**
 * @brief Initializes an already allocated OFHINFODNSResourceRecord with the
 *	  specified name, class, domain name and time to live.
 *
 * @param name The name for the resource record
 * @param DNSClass The class code for the resource record
 * @param CPU The CPU of the host info for the resource record
 * @param OS The OS of the host info for the resource record
 * @param TTL The time to live for the resource record
 * @return An initialized OFHINFODNSResourceRecord
 */
- (instancetype)initWithName: (OFString *)name
		    DNSClass: (OFDNSClass)DNSClass
			 CPU: (OFString *)CPU
			  OS: (OFString *)OS
			 TTL: (uint32_t)TTL OF_DESIGNATED_INITIALIZER;
@end

/**
 * @class OFMXDNSResourceRecord \
 *	  OFDNSResourceRecord.h ObjFW/OFDNSResourceRecord.h
 *
 * @brief A class representing an MX DNS resource record.
 */
OF_SUBCLASSING_RESTRICTED
@interface OFMXDNSResourceRecord: OFDNSResourceRecord
{
	uint16_t _preference;
	OFString *_mailExchange;
}

/**
 * @brief The preference of the resource record.
 */
@property (readonly, nonatomic) uint16_t preference;

/**
 * @brief The mail exchange of the resource record.
 */
@property (readonly, nonatomic) OFString *mailExchange;

- (instancetype)initWithName: (OFString *)name
		    DNSClass: (OFDNSClass)DNSClass
		  recordType: (OFDNSRecordType)recordType
			 TTL: (uint32_t)TTL OF_UNAVAILABLE;

/**
 * @brief Initializes an already allocated OFMXDNSResourceRecord with the
 *	  specified name, class, preference, mail exchange and time to live.
 *
 * @param name The name for the resource record
 * @param DNSClass The class code for the resource record
 * @param preference The preference for the resource record
 * @param mailExchange The mail exchange for the resource record
 * @param TTL The time to live for the resource record
 * @return An initialized OFMXDNSResourceRecord
 */
- (instancetype)initWithName: (OFString *)name
		    DNSClass: (OFDNSClass)DNSClass
		  preference: (uint16_t)preference
		mailExchange: (OFString *)mailExchange
			 TTL: (uint32_t)TTL OF_DESIGNATED_INITIALIZER;
@end

/**
 * @class OFNSDNSResourceRecord \
 *	  OFDNSResourceRecord.h ObjFW/OFDNSResourceRecord.h
 *
 * @brief A class representing an NS DNS resource record.
 */
OF_SUBCLASSING_RESTRICTED
@interface OFNSDNSResourceRecord: OFDNSResourceRecord
{
	OFString *_authoritativeHost;
}

/**
 * @brief The authoritative host of the resource record.
 */
@property (readonly, nonatomic) OFString *authoritativeHost;

- (instancetype)initWithName: (OFString *)name
		    DNSClass: (OFDNSClass)DNSClass
		  recordType: (OFDNSRecordType)recordType
			 TTL: (uint32_t)TTL OF_UNAVAILABLE;

/**
 * @brief Initializes an already allocated OFNSDNSResourceRecord with the
 *	  specified name, class, authoritative host and time to live.
 *
 * @param name The name for the resource record
 * @param DNSClass The class code for the resource record
 * @param authoritativeHost The authoritative host for the resource record
 * @param TTL The time to live for the resource record
 * @return An initialized OFNSDNSResourceRecord
 */
- (instancetype)initWithName: (OFString *)name
		    DNSClass: (OFDNSClass)DNSClass
	   authoritativeHost: (OFString *)authoritativeHost
			 TTL: (uint32_t)TTL OF_DESIGNATED_INITIALIZER;
@end

/**
 * @class OFPTRDNSResourceRecord \
 *	  OFDNSResourceRecord.h ObjFW/OFDNSResourceRecord.h
 *
 * @brief A class representing a PTR DNS resource record.
 */
OF_SUBCLASSING_RESTRICTED
@interface OFPTRDNSResourceRecord: OFDNSResourceRecord
{
	OFString *_domainName;
}

/**
 * @brief The domain name of the resource record.
 */
@property (readonly, nonatomic) OFString *domainName;

- (instancetype)initWithName: (OFString *)name
		    DNSClass: (OFDNSClass)DNSClass
		  recordType: (OFDNSRecordType)recordType
			 TTL: (uint32_t)TTL OF_UNAVAILABLE;

/**
 * @brief Initializes an already allocated OFPTRDNSResourceRecord with the
 *	  specified name, class, domain name and time to live.
 *
 * @param name The name for the resource record
 * @param DNSClass The class code for the resource record
 * @param domainName The domain name for the resource record
 * @param TTL The time to live for the resource record
 * @return An initialized OFPTRDNSResourceRecord
 */
- (instancetype)initWithName: (OFString *)name
		    DNSClass: (OFDNSClass)DNSClass
		  domainName: (OFString *)domainName
			 TTL: (uint32_t)TTL OF_DESIGNATED_INITIALIZER;
@end

/**
 * @class OFRPNSResourceRecord \
 *	  OFDNSResourceRecord.h ObjFW/OFDNSResourceRecord.h
 *
 * @brief A class representing an RP DNS resource record.
 */
OF_SUBCLASSING_RESTRICTED
@interface OFRPDNSResourceRecord: OFDNSResourceRecord
{
	OFString *_mailbox, *_TXTDomainName;
}

/**
 * @brief The mailbox of the responsible person of the resource record.
 */
@property (readonly, nonatomic) OFString *mailbox;

/**
 * @brief A domain name that contains a TXT resource record for the responsible
 *	  person of the resource record.
 */
@property (readonly, nonatomic) OFString *TXTDomainName;

- (instancetype)initWithName: (OFString *)name
		    DNSClass: (OFDNSClass)DNSClass
		  recordType: (OFDNSRecordType)recordType
			 TTL: (uint32_t)TTL OF_UNAVAILABLE;

/**
 * @brief Initializes an already allocated OFRPDNSResourceRecord with the
 *	  specified name, class, alias and time to live.
 *
 * @param name The name for the resource record
 * @param DNSClass The class code for the resource record
 * @param mailbox The mailbox of the responsible person of the resource record
 * @param TXTDomainName A domain name that contains a TXT resource record for
 *			the responsible person of the resource record
 * @param TTL The time to live for the resource record
 * @return An initialized OFRPDNSResourceRecord
 */
- (instancetype)initWithName: (OFString *)name
		    DNSClass: (OFDNSClass)DNSClass
		     mailbox: (OFString *)mailbox
	       TXTDomainName: (OFString *)TXTDomainName
			 TTL: (uint32_t)TTL OF_DESIGNATED_INITIALIZER;
@end

/**
 * @class OFSOADNSResourceRecord \
 *	  OFDNSResourceRecord.h ObjFW/OFDNSResourceRecord.h
 *
 * @brief A class representing an SOA DNS resource record.
 */
OF_SUBCLASSING_RESTRICTED
@interface OFSOADNSResourceRecord: OFDNSResourceRecord
{
	OFString *_primaryNameServer, *_responsiblePerson;
	uint32_t _serialNumber, _refreshInterval, _retryInterval;
	uint32_t _expirationInterval, _minTTL;
}

/**
 * @brief The the primary name server for the zone.
 */
@property (readonly, nonatomic) OFString *primaryNameServer;

/**
 * @brief The mailbox of the person responsible for the zone.
 */
@property (readonly, nonatomic) OFString *responsiblePerson;

/**
 * @brief The serial number of the original copy of the zone.
 */
@property (readonly, nonatomic) uint32_t serialNumber;

/**
 * @brief The refresh interval of the zone.
 */
@property (readonly, nonatomic) uint32_t refreshInterval;

/**
 * @brief The retry interval of the zone.
 */
@property (readonly, nonatomic) uint32_t retryInterval;

/**
 * @brief The expiration interval of the zone.
 */
@property (readonly, nonatomic) uint32_t expirationInterval;

/**
 * @brief The minimum TTL of the zone.
 */
@property (readonly, nonatomic) uint32_t minTTL;

- (instancetype)initWithName: (OFString *)name
		    DNSClass: (OFDNSClass)DNSClass
		  recordType: (OFDNSRecordType)recordType
			 TTL: (uint32_t)TTL OF_UNAVAILABLE;

/**
 * @brief Initializes an already allocated OFSOADNSResourceRecord with the
 *	  specified name, class, text data and time to live.
 *
 * @param name The name for the resource record
 * @param DNSClass The class code for the resource record
 * @param primaryNameServer The the primary name server for the zone
 * @param responsiblePerson The mailbox of the person responsible for the zone
 * @param serialNumber The serial number of the original copy of the zone
 * @param refreshInterval The refresh interval of the zone
 * @param retryInterval The retry interval of the zone
 * @param expirationInterval The expiration interval of the zone
 * @param minTTL The minimum TTL of the zone
 * @param TTL The time to live for the resource record
 * @return An initialized OFSOADNSResourceRecord
 */
- (instancetype)initWithName: (OFString *)name
		    DNSClass: (OFDNSClass)DNSClass
	   primaryNameServer: (OFString *)primaryNameServer
	   responsiblePerson: (OFString *)responsiblePerson
		serialNumber: (uint32_t)serialNumber
	     refreshInterval: (uint32_t)refreshInterval
	       retryInterval: (uint32_t)retryInterval
	  expirationInterval: (uint32_t)expirationInterval
		      minTTL: (uint32_t)minTTL
			 TTL: (uint32_t)TTL OF_DESIGNATED_INITIALIZER;
@end

/**
 * @class OFSRVDNSResourceRecord \
 *	  OFDNSResourceRecord.h ObjFW/OFDNSResourceRecord.h
 *
 * @brief A class representing an SRV DNS resource record.
 */
OF_SUBCLASSING_RESTRICTED
@interface OFSRVDNSResourceRecord: OFDNSResourceRecord
{
	uint16_t _priority, _weight;
	OFString *_target;
	uint16_t _port;
}

/**
 * @brief The priority of the resource record.
 */
@property (readonly, nonatomic) uint16_t priority;

/**
 * @brief The weight of the resource record.
 */
@property (readonly, nonatomic) uint16_t weight;

/**
 * @brief The target of the resource record.
 */
@property (readonly, nonatomic) OFString *target;

/**
 * @brief The port on the target of the resource record.
 */
@property (readonly, nonatomic) uint16_t port;

- (instancetype)initWithName: (OFString *)name
		    DNSClass: (OFDNSClass)DNSClass
		  recordType: (OFDNSRecordType)recordType
			 TTL: (uint32_t)TTL OF_UNAVAILABLE;

/**
 * @brief Initializes an already allocated OFSRVDNSResourceRecord with the
 *	  specified name, class, preference, mail exchange and time to live.
 *
 * @param name The name for the resource record
 * @param priority The priority for the resource record
 * @param weight The weight for the resource record
 * @param target The target for the resource record
 * @param port The port on the target for the resource record
 * @param TTL The time to live for the resource record
 * @return An initialized OFSRVDNSResourceRecord
 */
- (instancetype)initWithName: (OFString *)name
		    priority: (uint16_t)priority
		      weight: (uint16_t)weight
		      target: (OFString *)target
			port: (uint16_t)port
			 TTL: (uint32_t)TTL OF_DESIGNATED_INITIALIZER;
@end

/**
 * @class OFTXTDNSResourceRecord \
 *	  OFDNSResourceRecord.h ObjFW/OFDNSResourceRecord.h
 *
 * @brief A class representing a TXT DNS resource record.
 */
OF_SUBCLASSING_RESTRICTED
@interface OFTXTDNSResourceRecord: OFDNSResourceRecord
{
	OFArray OF_GENERIC(OFData *) *_textStrings;
}

/**
 * @brief The text of the resource record.
 */
@property (readonly, nonatomic) OFArray OF_GENERIC(OFData *) *textStrings;

- (instancetype)initWithName: (OFString *)name
		    DNSClass: (OFDNSClass)DNSClass
		  recordType: (OFDNSRecordType)recordType
			 TTL: (uint32_t)TTL OF_UNAVAILABLE;

/**
 * @brief Initializes an already allocated OFTXTDNSResourceRecord with the
 *	  specified name, class, text data and time to live.
 *
 * @param name The name for the resource record
 * @param DNSClass The class code for the resource record
 * @param textStrings An array of text strings for the resource record
 * @param TTL The time to live for the resource record
 * @return An initialized OFTXTDNSResourceRecord
 */
- (instancetype)initWithName: (OFString *)name
		    DNSClass: (OFDNSClass)DNSClass
		 textStrings: (OFArray OF_GENERIC(OFData *) *)textStrings
			 TTL: (uint32_t)TTL OF_DESIGNATED_INITIALIZER;
@end

#ifdef __cplusplus
extern "C" {
#endif
/**
 * @brief Returns the name for the specified OFDNSClass.
 *
 * @param DNSClass The OFDNSClass to return the name for







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







115
116
117
118
119
120
121






















































































































































































































































































































































































































































































































122
123
124
125
126
127
128
 */
- (instancetype)initWithName: (OFString *)name
		    DNSClass: (OFDNSClass)DNSClass
		  recordType: (OFDNSRecordType)recordType
			 TTL: (uint32_t)TTL OF_DESIGNATED_INITIALIZER;
@end























































































































































































































































































































































































































































































































#ifdef __cplusplus
extern "C" {
#endif
/**
 * @brief Returns the name for the specified OFDNSClass.
 *
 * @param DNSClass The OFDNSClass to return the name for
654
655
656
657
658
659
660














 */
extern OFDNSRecordType OFDNSRecordTypeParseName(OFString *_Nonnull string);
#ifdef __cplusplus
}
#endif

OF_ASSUME_NONNULL_END





















>
>
>
>
>
>
>
>
>
>
>
>
>
>
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
 */
extern OFDNSRecordType OFDNSRecordTypeParseName(OFString *_Nonnull string);
#ifdef __cplusplus
}
#endif

OF_ASSUME_NONNULL_END

#import "OFAAAADNSResourceRecord.h"
#import "OFADNSResourceRecord.h"
#import "OFCNAMEDNSResourceRecord.h"
#import "OFHINFODNSResourceRecord.h"
#import "OFLOCDNSResourceRecord.h"
#import "OFMXDNSResourceRecord.h"
#import "OFNSDNSResourceRecord.h"
#import "OFPTRDNSResourceRecord.h"
#import "OFRPDNSResourceRecord.h"
#import "OFSOADNSResourceRecord.h"
#import "OFSRVDNSResourceRecord.h"
#import "OFTXTDNSResourceRecord.h"
#import "OFURIDNSResourceRecord.h"

Modified src/OFDNSResourceRecord.m from [be00327390] to [1387c4ff44].

54
55
56
57
58
59
60


61
62
63
64


65
66
67
68
69
70
71
		return @"MX";
	case OFDNSRecordTypeTXT:
		return @"TXT";
	case OFDNSRecordTypeRP:
		return @"RP";
	case OFDNSRecordTypeAAAA:
		return @"AAAA";


	case OFDNSRecordTypeSRV:
		return @"SRV";
	case OFDNSRecordTypeAll:
		return @"all";


	default:
		return [OFString stringWithFormat: @"%u", recordType];
	}
}

OFDNSClass
OFDNSClassParseName(OFString *string)







>
>




>
>







54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
		return @"MX";
	case OFDNSRecordTypeTXT:
		return @"TXT";
	case OFDNSRecordTypeRP:
		return @"RP";
	case OFDNSRecordTypeAAAA:
		return @"AAAA";
	case OFDNSRecordTypeLOC:
		return @"LOC";
	case OFDNSRecordTypeSRV:
		return @"SRV";
	case OFDNSRecordTypeAll:
		return @"all";
	case OFDNSRecordTypeURI:
		return @"URI";
	default:
		return [OFString stringWithFormat: @"%u", recordType];
	}
}

OFDNSClass
OFDNSClassParseName(OFString *string)
111
112
113
114
115
116
117


118
119
120
121


122
123
124
125
126
127
128
		recordType = OFDNSRecordTypeMX;
	else if ([string isEqual: @"TXT"])
		recordType = OFDNSRecordTypeTXT;
	else if ([string isEqual: @"RP"])
		recordType = OFDNSRecordTypeRP;
	else if ([string isEqual: @"AAAA"])
		recordType = OFDNSRecordTypeAAAA;


	else if ([string isEqual: @"SRV"])
		recordType = OFDNSRecordTypeSRV;
	else if ([string isEqual: @"ALL"])
		recordType = OFDNSRecordTypeAll;


	else {
		recordType =
		    (OFDNSRecordType)[string unsignedLongLongValueWithBase: 0];
	}

	objc_autoreleasePoolPop(pool);








>
>




>
>







115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
		recordType = OFDNSRecordTypeMX;
	else if ([string isEqual: @"TXT"])
		recordType = OFDNSRecordTypeTXT;
	else if ([string isEqual: @"RP"])
		recordType = OFDNSRecordTypeRP;
	else if ([string isEqual: @"AAAA"])
		recordType = OFDNSRecordTypeAAAA;
	else if ([string isEqual: @"LOC"])
		recordType = OFDNSRecordTypeLOC;
	else if ([string isEqual: @"SRV"])
		recordType = OFDNSRecordTypeSRV;
	else if ([string isEqual: @"ALL"])
		recordType = OFDNSRecordTypeAll;
	else if ([string isEqual: @"URI"])
		recordType = OFDNSRecordTypeURI;
	else {
		recordType =
		    (OFDNSRecordType)[string unsignedLongLongValueWithBase: 0];
	}

	objc_autoreleasePoolPop(pool);

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
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
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
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
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
1159
1160
1161
1162
1163
1164
1165
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
1198
1199
1200
1201
1202
1203
1204
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
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
	    @"\tClass = %@\n"
	    @"\tType = %@\n"
	    @"\tTTL = %" PRIu32 "\n"
	    @">",
	    self.className, _name, OFDNSClassName(_DNSClass),
	    OFDNSRecordTypeName(_recordType), _TTL];
}
@end

@implementation OFADNSResourceRecord
- (instancetype)initWithName: (OFString *)name
		    DNSClass: (OFDNSClass)DNSClass
		  recordType: (OFDNSRecordType)recordType
			 TTL: (uint32_t)TTL
{
	OF_INVALID_INIT_METHOD
}

- (instancetype)initWithName: (OFString *)name
		     address: (const OFSocketAddress *)address
			 TTL: (uint32_t)TTL
{
	self = [super initWithName: name
			  DNSClass: OFDNSClassIN
			recordType: OFDNSRecordTypeA
			       TTL: TTL];

	_address = *address;

	return self;
}

- (const OFSocketAddress *)address
{
	return &_address;
}

- (bool)isEqual: (id)object
{
	OFADNSResourceRecord *record;

	if (object == self)
		return true;

	if (![object isKindOfClass: [OFADNSResourceRecord class]])
		return false;

	record = object;

	if (record->_name != _name && ![record->_name isEqual: _name])
		return false;

	if (record->_DNSClass != _DNSClass)
		return false;

	if (record->_recordType != _recordType)
		return false;

	if (!OFSocketAddressEqual(&record->_address, &_address))
		return false;

	return true;
}

- (unsigned long)hash
{
	unsigned long hash;

	OFHashInit(&hash);

	OFHashAddHash(&hash, _name.hash);
	OFHashAddByte(&hash, _DNSClass >> 8);
	OFHashAddByte(&hash, _DNSClass);
	OFHashAddByte(&hash, _recordType >> 8);
	OFHashAddByte(&hash, _recordType);
	OFHashAddHash(&hash, OFSocketAddressHash(&_address));

	OFHashFinalize(&hash);

	return hash;
}

- (OFString *)description
{
	return [OFString stringWithFormat:
	    @"<%@:\n"
	    @"\tName = %@\n"
	    @"\tAddress = %@\n"
	    @"\tTTL = %" PRIu32 "\n"
	    @">",
	    self.className, _name, OFSocketAddressString(&_address), _TTL];
}
@end

@implementation OFAAAADNSResourceRecord
- (instancetype)initWithName: (OFString *)name
		    DNSClass: (OFDNSClass)DNSClass
		  recordType: (OFDNSRecordType)recordType
			 TTL: (uint32_t)TTL
{
	OF_INVALID_INIT_METHOD
}

- (instancetype)initWithName: (OFString *)name
		     address: (const OFSocketAddress *)address
			 TTL: (uint32_t)TTL
{
	self = [super initWithName: name
			  DNSClass: OFDNSClassIN
			recordType: OFDNSRecordTypeAAAA
			       TTL: TTL];

	_address = *address;

	return self;
}

- (const OFSocketAddress *)address
{
	return &_address;
}

- (bool)isEqual: (id)object
{
	OFAAAADNSResourceRecord *record;

	if (object == self)
		return true;

	if (![object isKindOfClass: [OFAAAADNSResourceRecord class]])
		return false;

	record = object;

	if (record->_name != _name && ![record->_name isEqual: _name])
		return false;

	if (record->_DNSClass != _DNSClass)
		return false;

	if (record->_recordType != _recordType)
		return false;

	if (!OFSocketAddressEqual(&record->_address, &_address))
		return false;

	return true;
}

- (unsigned long)hash
{
	unsigned long hash;

	OFHashInit(&hash);

	OFHashAddHash(&hash, _name.hash);
	OFHashAddByte(&hash, _DNSClass >> 8);
	OFHashAddByte(&hash, _DNSClass);
	OFHashAddByte(&hash, _recordType >> 8);
	OFHashAddByte(&hash, _recordType);
	OFHashAddHash(&hash, OFSocketAddressHash(&_address));

	OFHashFinalize(&hash);

	return hash;
}

- (OFString *)description
{
	return [OFString stringWithFormat:
	    @"<%@:\n"
	    @"\tName = %@\n"
	    @"\tAddress = %@\n"
	    @"\tTTL = %" PRIu32 "\n"
	    @">",
	    self.className, _name, OFSocketAddressString(&_address), _TTL];
}
@end

@implementation OFCNAMEDNSResourceRecord
@synthesize alias = _alias;

- (instancetype)initWithName: (OFString *)name
		    DNSClass: (OFDNSClass)DNSClass
		  recordType: (OFDNSRecordType)recordType
			 TTL: (uint32_t)TTL
{
	OF_INVALID_INIT_METHOD
}

- (instancetype)initWithName: (OFString *)name
		    DNSClass: (OFDNSClass)DNSClass
		       alias: (OFString *)alias
			 TTL: (uint32_t)TTL
{
	self = [super initWithName: name
			  DNSClass: DNSClass
			recordType: OFDNSRecordTypeCNAME
			       TTL: TTL];

	@try {
		_alias = [alias copy];
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (void)dealloc
{
	[_alias release];

	[super dealloc];
}

- (bool)isEqual: (id)object
{
	OFCNAMEDNSResourceRecord *record;

	if (object == self)
		return true;

	if (![object isKindOfClass: [OFCNAMEDNSResourceRecord class]])
		return false;

	record = object;

	if (record->_name != _name && ![record->_name isEqual: _name])
		return false;

	if (record->_DNSClass != _DNSClass)
		return false;

	if (record->_recordType != _recordType)
		return false;

	if (record->_alias != _alias && ![record->_alias isEqual: _alias])
		return false;

	return true;
}

- (unsigned long)hash
{
	unsigned long hash;

	OFHashInit(&hash);

	OFHashAddHash(&hash, _name.hash);
	OFHashAddByte(&hash, _DNSClass >> 8);
	OFHashAddByte(&hash, _DNSClass);
	OFHashAddByte(&hash, _recordType >> 8);
	OFHashAddByte(&hash, _recordType);
	OFHashAddHash(&hash, _alias.hash);

	OFHashFinalize(&hash);

	return hash;
}

- (OFString *)description
{
	return [OFString stringWithFormat:
	    @"<%@:\n"
	    @"\tName = %@\n"
	    @"\tClass = %@\n"
	    @"\tAlias = %@\n"
	    @"\tTTL = %" PRIu32 "\n"
	    @">",
	    self.className, _name, OFDNSClassName(_DNSClass), _alias, _TTL];
}
@end

@implementation OFHINFODNSResourceRecord
@synthesize CPU = _CPU, OS = _OS;

- (instancetype)initWithName: (OFString *)name
		    DNSClass: (OFDNSClass)DNSClass
		  recordType: (OFDNSRecordType)recordType
			 TTL: (uint32_t)TTL
{
	OF_INVALID_INIT_METHOD
}

- (instancetype)initWithName: (OFString *)name
		    DNSClass: (OFDNSClass)DNSClass
			 CPU: (OFString *)CPU
			  OS: (OFString *)OS
			 TTL: (uint32_t)TTL
{
	self = [super initWithName: name
			  DNSClass: DNSClass
			recordType: OFDNSRecordTypeHINFO
			       TTL: TTL];

	@try {
		_CPU = [CPU copy];
		_OS = [OS copy];
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (void)dealloc
{
	[_CPU release];
	[_OS release];

	[super dealloc];
}

- (bool)isEqual: (id)object
{
	OFHINFODNSResourceRecord *record;

	if (object == self)
		return true;

	if (![object isKindOfClass: [OFHINFODNSResourceRecord class]])
		return false;

	record = object;

	if (record->_name != _name && ![record->_name isEqual: _name])
		return false;

	if (record->_DNSClass != _DNSClass)
		return false;

	if (record->_recordType != _recordType)
		return false;

	if (record->_CPU != _CPU && ![record->_CPU isEqual: _CPU])
		return false;

	if (record->_OS != _OS && ![record->_OS isEqual: _OS])
		return false;

	return true;
}

- (unsigned long)hash
{
	unsigned long hash;

	OFHashInit(&hash);

	OFHashAddHash(&hash, _name.hash);
	OFHashAddByte(&hash, _DNSClass >> 8);
	OFHashAddByte(&hash, _DNSClass);
	OFHashAddByte(&hash, _recordType >> 8);
	OFHashAddByte(&hash, _recordType);
	OFHashAddHash(&hash, _CPU.hash);
	OFHashAddHash(&hash, _OS.hash);

	OFHashFinalize(&hash);

	return hash;
}

- (OFString *)description
{
	return [OFString stringWithFormat:
	    @"<%@:\n"
	    @"\tName = %@\n"
	    @"\tClass = %@\n"
	    @"\tCPU = %@\n"
	    @"\tOS = %@\n"
	    @"\tTTL = %" PRIu32 "\n"
	    @">",
	    self.className, _name, OFDNSClassName(_DNSClass), _CPU, _OS, _TTL];
}
@end

@implementation OFMXDNSResourceRecord
@synthesize preference = _preference, mailExchange = _mailExchange;

- (instancetype)initWithName: (OFString *)name
		    DNSClass: (OFDNSClass)DNSClass
		  recordType: (OFDNSRecordType)recordType
			 TTL: (uint32_t)TTL
{
	OF_INVALID_INIT_METHOD
}

- (instancetype)initWithName: (OFString *)name
		    DNSClass: (OFDNSClass)DNSClass
		  preference: (uint16_t)preference
		mailExchange: (OFString *)mailExchange
			 TTL: (uint32_t)TTL
{
	self = [super initWithName: name
			  DNSClass: DNSClass
			recordType: OFDNSRecordTypeMX
			       TTL: TTL];

	@try {
		_preference = preference;
		_mailExchange = [mailExchange copy];
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (void)dealloc
{
	[_mailExchange release];

	[super dealloc];
}

- (bool)isEqual: (id)object
{
	OFMXDNSResourceRecord *record;

	if (object == self)
		return true;

	if (![object isKindOfClass: [OFMXDNSResourceRecord class]])
		return false;

	record = object;

	if (record->_name != _name && ![record->_name isEqual: _name])
		return false;

	if (record->_DNSClass != _DNSClass)
		return false;

	if (record->_recordType != _recordType)
		return false;

	if (record->_preference != _preference)
		return false;

	if (record->_mailExchange != _mailExchange &&
	    ![record->_mailExchange isEqual: _mailExchange])
		return false;

	return true;
}

- (unsigned long)hash
{
	unsigned long hash;

	OFHashInit(&hash);

	OFHashAddHash(&hash, _name.hash);
	OFHashAddByte(&hash, _DNSClass >> 8);
	OFHashAddByte(&hash, _DNSClass);
	OFHashAddByte(&hash, _recordType >> 8);
	OFHashAddByte(&hash, _recordType);
	OFHashAddByte(&hash, _preference >> 8);
	OFHashAddByte(&hash, _preference);
	OFHashAddHash(&hash, _mailExchange.hash);

	OFHashFinalize(&hash);

	return hash;
}

- (OFString *)description
{
	return [OFString stringWithFormat:
	    @"<%@:\n"
	    @"\tName = %@\n"
	    @"\tClass = %@\n"
	    @"\tPreference = %" PRIu16 "\n"
	    @"\tMail Exchange = %@\n"
	    @"\tTTL = %" PRIu32 "\n"
	    @">",
	    self.className, _name, OFDNSClassName(_DNSClass), _preference,
	    _mailExchange, _TTL];
}
@end

@implementation OFNSDNSResourceRecord
@synthesize authoritativeHost = _authoritativeHost;

- (instancetype)initWithName: (OFString *)name
		    DNSClass: (OFDNSClass)DNSClass
		  recordType: (OFDNSRecordType)recordType
			 TTL: (uint32_t)TTL
{
	OF_INVALID_INIT_METHOD
}

- (instancetype)initWithName: (OFString *)name
		    DNSClass: (OFDNSClass)DNSClass
	   authoritativeHost: (OFString *)authoritativeHost
			 TTL: (uint32_t)TTL
{
	self = [super initWithName: name
			  DNSClass: DNSClass
			recordType: OFDNSRecordTypeNS
			       TTL: TTL];

	@try {
		_authoritativeHost = [authoritativeHost copy];
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (void)dealloc
{
	[_authoritativeHost release];

	[super dealloc];
}

- (bool)isEqual: (id)object
{
	OFNSDNSResourceRecord *record;

	if (object == self)
		return true;

	if (![object isKindOfClass: [OFNSDNSResourceRecord class]])
		return false;

	record = object;

	if (record->_name != _name && ![record->_name isEqual: _name])
		return false;

	if (record->_DNSClass != _DNSClass)
		return false;

	if (record->_recordType != _recordType)
		return false;

	if (record->_authoritativeHost != _authoritativeHost &&
	    ![record->_authoritativeHost isEqual: _authoritativeHost])
		return false;

	return true;
}

- (unsigned long)hash
{
	unsigned long hash;

	OFHashInit(&hash);

	OFHashAddHash(&hash, _name.hash);
	OFHashAddByte(&hash, _DNSClass >> 8);
	OFHashAddByte(&hash, _DNSClass);
	OFHashAddByte(&hash, _recordType >> 8);
	OFHashAddByte(&hash, _recordType);
	OFHashAddHash(&hash, _authoritativeHost.hash);

	OFHashFinalize(&hash);

	return hash;
}

- (OFString *)description
{
	return [OFString stringWithFormat:
	    @"<%@:\n"
	    @"\tName = %@\n"
	    @"\tClass = %@\n"
	    @"\tAuthoritative Host = %@\n"
	    @"\tTTL = %" PRIu32 "\n"
	    @">",
	    self.className, _name, OFDNSClassName(_DNSClass),
	    _authoritativeHost, _TTL];
}
@end

@implementation OFPTRDNSResourceRecord
@synthesize domainName = _domainName;

- (instancetype)initWithName: (OFString *)name
		    DNSClass: (OFDNSClass)DNSClass
		  recordType: (OFDNSRecordType)recordType
			 TTL: (uint32_t)TTL
{
	OF_INVALID_INIT_METHOD
}

- (instancetype)initWithName: (OFString *)name
		    DNSClass: (OFDNSClass)DNSClass
		  domainName: (OFString *)domainName
			 TTL: (uint32_t)TTL
{
	self = [super initWithName: name
			  DNSClass: DNSClass
			recordType: OFDNSRecordTypePTR
			       TTL: TTL];

	@try {
		_domainName = [domainName copy];
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (void)dealloc
{
	[_domainName release];

	[super dealloc];
}

- (bool)isEqual: (id)object
{
	OFPTRDNSResourceRecord *record;

	if (object == self)
		return true;

	if (![object isKindOfClass: [OFPTRDNSResourceRecord class]])
		return false;

	record = object;

	if (record->_name != _name && ![record->_name isEqual: _name])
		return false;

	if (record->_DNSClass != _DNSClass)
		return false;

	if (record->_recordType != _recordType)
		return false;

	if (record->_domainName != _domainName &&
	    ![record->_domainName isEqual: _domainName])
		return false;

	return true;
}

- (unsigned long)hash
{
	unsigned long hash;

	OFHashInit(&hash);

	OFHashAddHash(&hash, _name.hash);
	OFHashAddByte(&hash, _DNSClass >> 8);
	OFHashAddByte(&hash, _DNSClass);
	OFHashAddByte(&hash, _recordType >> 8);
	OFHashAddByte(&hash, _recordType);
	OFHashAddHash(&hash, _domainName.hash);

	OFHashFinalize(&hash);

	return hash;
}

- (OFString *)description
{
	return [OFString stringWithFormat:
	    @"<%@:\n"
	    @"\tName = %@\n"
	    @"\tClass = %@\n"
	    @"\tDomain Name = %@\n"
	    @"\tTTL = %" PRIu32 "\n"
	    @">",
	    self.className, _name, OFDNSClassName(_DNSClass), _domainName,
	    _TTL];
}
@end

@implementation OFRPDNSResourceRecord
@synthesize mailbox = _mailbox, TXTDomainName = _TXTDomainName;

- (instancetype)initWithName: (OFString *)name
		    DNSClass: (OFDNSClass)DNSClass
		  recordType: (OFDNSRecordType)recordType
			 TTL: (uint32_t)TTL
{
	OF_INVALID_INIT_METHOD
}

- (instancetype)initWithName: (OFString *)name
		    DNSClass: (OFDNSClass)DNSClass
		     mailbox: (OFString *)mailbox
	       TXTDomainName: (OFString *)TXTDomainName
			 TTL: (uint32_t)TTL
{
	self = [super initWithName: name
			  DNSClass: DNSClass
			recordType: OFDNSRecordTypeRP
			       TTL: TTL];

	@try {
		_mailbox = [mailbox copy];
		_TXTDomainName = [TXTDomainName copy];
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (void)dealloc
{
	[_mailbox release];
	[_TXTDomainName release];

	[super dealloc];
}

- (bool)isEqual: (id)object
{
	OFRPDNSResourceRecord *record;

	if (object == self)
		return true;

	if (![object isKindOfClass: [OFRPDNSResourceRecord class]])
		return false;

	record = object;

	if (record->_name != _name && ![record->_name isEqual: _name])
		return false;

	if (record->_DNSClass != _DNSClass)
		return false;

	if (record->_recordType != _recordType)
		return false;

	if (record->_mailbox != _mailbox &&
	    ![record->_mailbox isEqual: _mailbox])
		return false;

	if (record->_TXTDomainName != _TXTDomainName &&
	    ![record->_TXTDomainName isEqual: _TXTDomainName])
		return false;

	return true;
}

- (unsigned long)hash
{
	unsigned long hash;

	OFHashInit(&hash);

	OFHashAddHash(&hash, _name.hash);
	OFHashAddByte(&hash, _DNSClass >> 8);
	OFHashAddByte(&hash, _DNSClass);
	OFHashAddByte(&hash, _recordType >> 8);
	OFHashAddByte(&hash, _recordType);
	OFHashAddHash(&hash, _mailbox.hash);
	OFHashAddHash(&hash, _TXTDomainName.hash);

	OFHashFinalize(&hash);

	return hash;
}

- (OFString *)description
{
	return [OFString stringWithFormat:
	    @"<%@:\n"
	    @"\tName = %@\n"
	    @"\tClass = %@\n"
	    @"\tMailbox = %@\n"
	    @"\tTXT Domain Name = %@\n"
	    @"\tTTL = %" PRIu32 "\n"
	    @">",
	    self.className, _name, OFDNSClassName(_DNSClass), _mailbox,
	    _TXTDomainName, _TTL];
}
@end

@implementation OFSOADNSResourceRecord
@synthesize primaryNameServer = _primaryNameServer;
@synthesize responsiblePerson = _responsiblePerson;
@synthesize serialNumber = _serialNumber, refreshInterval = _refreshInterval;
@synthesize retryInterval = _retryInterval;
@synthesize expirationInterval = _expirationInterval, minTTL = _minTTL;

- (instancetype)initWithName: (OFString *)name
		    DNSClass: (OFDNSClass)DNSClass
		  recordType: (OFDNSRecordType)recordType
			 TTL: (uint32_t)TTL
{
	OF_INVALID_INIT_METHOD
}

- (instancetype)initWithName: (OFString *)name
		    DNSClass: (OFDNSClass)DNSClass
	   primaryNameServer: (OFString *)primaryNameServer
	   responsiblePerson: (OFString *)responsiblePerson
		serialNumber: (uint32_t)serialNumber
	     refreshInterval: (uint32_t)refreshInterval
	       retryInterval: (uint32_t)retryInterval
	  expirationInterval: (uint32_t)expirationInterval
		      minTTL: (uint32_t)minTTL
			 TTL: (uint32_t)TTL
{
	self = [super initWithName: name
			  DNSClass: DNSClass
			recordType: OFDNSRecordTypeSOA
			       TTL: TTL];

	@try {
		_primaryNameServer = [primaryNameServer copy];
		_responsiblePerson = [responsiblePerson copy];
		_serialNumber = serialNumber;
		_refreshInterval = refreshInterval;
		_retryInterval = retryInterval;
		_expirationInterval = expirationInterval;
		_minTTL = minTTL;
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (void)dealloc
{
	[_primaryNameServer release];
	[_responsiblePerson release];

	[super dealloc];
}

- (bool)isEqual: (id)object
{
	OFSOADNSResourceRecord *record;

	if (object == self)
		return true;

	if (![object isKindOfClass: [OFSOADNSResourceRecord class]])
		return false;

	record = object;

	if (record->_name != _name && ![record->_name isEqual: _name])
		return false;

	if (record->_DNSClass != _DNSClass)
		return false;

	if (record->_recordType != _recordType)
		return false;

	if (record->_primaryNameServer != _primaryNameServer &&
	    ![record->_primaryNameServer isEqual: _primaryNameServer])
		return false;

	if (record->_responsiblePerson != _responsiblePerson &&
	    ![record->_responsiblePerson isEqual: _responsiblePerson])
		return false;

	if (record->_serialNumber != _serialNumber)
		return false;

	if (record->_refreshInterval != _refreshInterval)
		return false;

	if (record->_retryInterval != _retryInterval)
		return false;

	if (record->_expirationInterval != _expirationInterval)
		return false;

	if (record->_minTTL != _minTTL)
		return false;

	return true;
}

- (unsigned long)hash
{
	unsigned long hash;

	OFHashInit(&hash);

	OFHashAddHash(&hash, _name.hash);
	OFHashAddByte(&hash, _DNSClass >> 8);
	OFHashAddByte(&hash, _DNSClass);
	OFHashAddByte(&hash, _recordType >> 8);
	OFHashAddByte(&hash, _recordType);
	OFHashAddHash(&hash, _primaryNameServer.hash);
	OFHashAddHash(&hash, _responsiblePerson.hash);
	OFHashAddByte(&hash, _serialNumber >> 24);
	OFHashAddByte(&hash, _serialNumber >> 16);
	OFHashAddByte(&hash, _serialNumber >> 8);
	OFHashAddByte(&hash, _serialNumber);
	OFHashAddByte(&hash, _refreshInterval >> 24);
	OFHashAddByte(&hash, _refreshInterval >> 16);
	OFHashAddByte(&hash, _refreshInterval >> 8);
	OFHashAddByte(&hash, _refreshInterval);
	OFHashAddByte(&hash, _retryInterval >> 24);
	OFHashAddByte(&hash, _retryInterval >> 16);
	OFHashAddByte(&hash, _retryInterval >> 8);
	OFHashAddByte(&hash, _retryInterval);
	OFHashAddByte(&hash, _expirationInterval >> 24);
	OFHashAddByte(&hash, _expirationInterval >> 16);
	OFHashAddByte(&hash, _expirationInterval >> 8);
	OFHashAddByte(&hash, _expirationInterval);
	OFHashAddByte(&hash, _minTTL >> 24);
	OFHashAddByte(&hash, _minTTL >> 16);
	OFHashAddByte(&hash, _minTTL >> 8);
	OFHashAddByte(&hash, _minTTL);

	OFHashFinalize(&hash);

	return hash;
}

- (OFString *)description
{
	return [OFString stringWithFormat:
	    @"<%@:\n"
	    @"\tName = %@\n"
	    @"\tClass = %@\n"
	    @"\tPrimary Name Server = %@\n"
	    @"\tResponsible Person = %@\n"
	    @"\tSerial Number = %" PRIu32 "\n"
	    @"\tRefresh Interval = %" PRIu32 "\n"
	    @"\tRetry Interval = %" PRIu32 "\n"
	    @"\tExpiration Interval = %" PRIu32 "\n"
	    @"\tMinimum TTL = %" PRIu32 "\n"
	    @"\tTTL = %" PRIu32 "\n"
	    @">",
	    self.className, _name, OFDNSClassName(_DNSClass),
	    _primaryNameServer, _responsiblePerson, _serialNumber,
	    _refreshInterval, _retryInterval, _expirationInterval, _minTTL,
	    _TTL];
}
@end

@implementation OFSRVDNSResourceRecord
@synthesize priority = _priority, weight = _weight, target = _target;
@synthesize port = _port;

- (instancetype)initWithName: (OFString *)name
		    DNSClass: (OFDNSClass)DNSClass
		  recordType: (OFDNSRecordType)recordType
			 TTL: (uint32_t)TTL
{
	OF_INVALID_INIT_METHOD
}

- (instancetype)initWithName: (OFString *)name
		    priority: (uint16_t)priority
		      weight: (uint16_t)weight
		      target: (OFString *)target
			port: (uint16_t)port
			 TTL: (uint32_t)TTL
{
	self = [super initWithName: name
			  DNSClass: OFDNSClassIN
			recordType: OFDNSRecordTypeSRV
			       TTL: TTL];

	@try {
		_priority = priority;
		_weight = weight;
		_target = [target copy];
		_port = port;
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (void)dealloc
{
	[_target release];

	[super dealloc];
}

- (bool)isEqual: (id)object
{
	OFSRVDNSResourceRecord *record;

	if (object == self)
		return true;

	if (![object isKindOfClass: [OFSRVDNSResourceRecord class]])
		return false;

	record = object;

	if (record->_name != _name && ![record->_name isEqual: _name])
		return false;

	if (record->_DNSClass != _DNSClass)
		return false;

	if (record->_recordType != _recordType)
		return false;

	if (record->_priority != _priority)
		return false;

	if (record->_weight != _weight)
		return false;

	if (record->_target != _target && ![record->_target isEqual: _target])
		return false;

	if (record->_port != _port)
		return false;

	return true;
}

- (unsigned long)hash
{
	unsigned long hash;

	OFHashInit(&hash);

	OFHashAddHash(&hash, _name.hash);
	OFHashAddByte(&hash, _DNSClass >> 8);
	OFHashAddByte(&hash, _DNSClass);
	OFHashAddByte(&hash, _recordType >> 8);
	OFHashAddByte(&hash, _recordType);
	OFHashAddByte(&hash, _priority >> 8);
	OFHashAddByte(&hash, _priority);
	OFHashAddByte(&hash, _weight >> 8);
	OFHashAddByte(&hash, _weight);
	OFHashAddHash(&hash, _target.hash);
	OFHashAddByte(&hash, _port >> 8);
	OFHashAddByte(&hash, _port);

	OFHashFinalize(&hash);

	return hash;
}

- (OFString *)description
{
	return [OFString stringWithFormat:
	    @"<%@:\n"
	    @"\tName = %@\n"
	    @"\tPriority = %" PRIu16 "\n"
	    @"\tWeight = %" PRIu16 "\n"
	    @"\tTarget = %@\n"
	    @"\tPort = %" PRIu16 "\n"
	    @"\tTTL = %" PRIu32 "\n"
	    @">",
	    self.className, _name, _priority, _weight, _target, _port, _TTL];
}
@end

@implementation OFTXTDNSResourceRecord
@synthesize textStrings = _textStrings;

- (instancetype)initWithName: (OFString *)name
		    DNSClass: (OFDNSClass)DNSClass
		  recordType: (OFDNSRecordType)recordType
			 TTL: (uint32_t)TTL
{
	OF_INVALID_INIT_METHOD
}

- (instancetype)initWithName: (OFString *)name
		    DNSClass: (OFDNSClass)DNSClass
		 textStrings: (OFArray OF_GENERIC(OFData *) *)textStrings
			 TTL: (uint32_t)TTL
{
	self = [super initWithName: name
			  DNSClass: DNSClass
			recordType: OFDNSRecordTypeTXT
			       TTL: TTL];

	@try {
		_textStrings = [textStrings copy];
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (void)dealloc
{
	[_textStrings release];

	[super dealloc];
}

- (bool)isEqual: (id)object
{
	OFTXTDNSResourceRecord *record;

	if (object == self)
		return true;

	if (![object isKindOfClass: [OFTXTDNSResourceRecord class]])
		return false;

	record = object;

	if (record->_name != _name && ![record->_name isEqual: _name])
		return false;

	if (record->_DNSClass != _DNSClass)
		return false;

	if (record->_recordType != _recordType)
		return false;

	if (record->_textStrings != _textStrings &&
	    ![record->_textStrings isEqual: _textStrings])
		return false;

	return true;
}

- (unsigned long)hash
{
	unsigned long hash;

	OFHashInit(&hash);

	OFHashAddHash(&hash, _name.hash);
	OFHashAddByte(&hash, _DNSClass >> 8);
	OFHashAddByte(&hash, _DNSClass);
	OFHashAddByte(&hash, _recordType >> 8);
	OFHashAddByte(&hash, _recordType);
	OFHashAddHash(&hash, _textStrings.hash);

	OFHashFinalize(&hash);

	return hash;
}

- (OFString *)description
{
	void *pool = objc_autoreleasePoolPush();
	OFMutableString *text = [OFMutableString string];
	bool first = true;
	OFString *ret;

	for (OFData *string in _textStrings) {
		const unsigned char *stringItems = string.items;
		size_t stringCount = string.count;

		if (first) {
			first = false;
			[text appendString: @"\""];
		} else
			[text appendString: @" \""];

		for (size_t i = 0; i < stringCount; i++) {
			if (stringItems[i] == '\\')
				[text appendString: @"\\\\"];
			else if (stringItems[i] == '"')
				[text appendString: @"\\\""];
			else if (stringItems[i] < 0x20)
				[text appendFormat: @"\\x%02X", stringItems[i]];
			else if (stringItems[i] < 0x7F)
				[text appendFormat: @"%c", stringItems[i]];
			else
				[text appendFormat: @"\\x%02X", stringItems[i]];
		}

		[text appendString: @"\""];
	}

	ret = [OFString stringWithFormat:
	    @"<%@:\n"
	    @"\tName = %@\n"
	    @"\tClass = %@\n"
	    @"\tText strings = %@\n"
	    @"\tTTL = %" PRIu32 "\n"
	    @">",
	    self.className, _name, OFDNSClassName(_DNSClass), text, _TTL];

	[ret retain];

	objc_autoreleasePoolPop(pool);

	return [ret autorelease];
}
@end








<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
181
182
183
184
185
186
187
188











































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































	    @"\tClass = %@\n"
	    @"\tType = %@\n"
	    @"\tTTL = %" PRIu32 "\n"
	    @">",
	    self.className, _name, OFDNSClassName(_DNSClass),
	    OFDNSRecordTypeName(_recordType), _TTL];
}
@end











































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































Modified src/OFData.h from [201a24ff3c] to [9788e734e3].

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
		     itemSize: (size_t)itemSize;

/**
 * @brief Creates a new OFData with the specified `count` items of size 1 by
 *	  taking over ownership of the specified items pointer.
 *
 * If initialization fails for whatever reason, the passed memory is *not*
 * free'd if `freeWhenDone` is true.
 *
 * @param items The items to store in the OFData
 * @param count The number of items
 * @param freeWhenDone Whether to free the pointer when it is no longer needed
 *		       by the OFData
 * @return A new autoreleased OFData
 */
+ (instancetype)dataWithItemsNoCopy: (void *)items
			      count: (size_t)count
		       freeWhenDone: (bool)freeWhenDone;

/**
 * @brief Creates a new OFData with the specified `count` items of the
 *	  specified size by taking ownership of the specified items pointer.
 *
 * If initialization fails for whatever reason, the passed memory is *not*
 * free'd if `freeWhenDone` is true.
 *
 * @param items The items to store in the OFData
 * @param count The number of items
 * @param itemSize The item size of a single item in bytes
 * @param freeWhenDone Whether to free the pointer when it is no longer needed
 *		       by the OFData
 * @return A new autoreleased OFData







|
















|







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
		     itemSize: (size_t)itemSize;

/**
 * @brief Creates a new OFData with the specified `count` items of size 1 by
 *	  taking over ownership of the specified items pointer.
 *
 * If initialization fails for whatever reason, the passed memory is *not*
 * freed if `freeWhenDone` is true.
 *
 * @param items The items to store in the OFData
 * @param count The number of items
 * @param freeWhenDone Whether to free the pointer when it is no longer needed
 *		       by the OFData
 * @return A new autoreleased OFData
 */
+ (instancetype)dataWithItemsNoCopy: (void *)items
			      count: (size_t)count
		       freeWhenDone: (bool)freeWhenDone;

/**
 * @brief Creates a new OFData with the specified `count` items of the
 *	  specified size by taking ownership of the specified items pointer.
 *
 * If initialization fails for whatever reason, the passed memory is *not*
 * freed if `freeWhenDone` is true.
 *
 * @param items The items to store in the OFData
 * @param count The number of items
 * @param itemSize The item size of a single item in bytes
 * @param freeWhenDone Whether to free the pointer when it is no longer needed
 *		       by the OFData
 * @return A new autoreleased OFData
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

/**
 * @brief Initializes an already allocated OFData with the specified `count`
 *	  items of size 1 by taking over ownership of the specified items
 *	  pointer.
 *
 * If initialization fails for whatever reason, the passed memory is *not*
 * free'd if `freeWhenDone` is true.
 *
 * @param items The items to store in the OFData
 * @param count The number of items
 * @param freeWhenDone Whether to free the pointer when it is no longer needed
 *		       by the OFData
 * @return An initialized OFData
 */
- (instancetype)initWithItemsNoCopy: (void *)items
			      count: (size_t)count
		       freeWhenDone: (bool)freeWhenDone;

/**
 * @brief Initializes an already allocated OFData with the specified `count`
 *	  items of the specified size by taking ownership of the specified
 *	  items pointer.
 *
 * If initialization fails for whatever reason, the passed memory is *not*
 * free'd if `freeWhenDone` is true.
 *
 * @param items The items to store in the OFData
 * @param count The number of items
 * @param itemSize The item size of a single item in bytes
 * @param freeWhenDone Whether to free the pointer when it is no longer needed
 *		       by the OFData
 * @return An initialized OFData







|

















|







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

/**
 * @brief Initializes an already allocated OFData with the specified `count`
 *	  items of size 1 by taking over ownership of the specified items
 *	  pointer.
 *
 * If initialization fails for whatever reason, the passed memory is *not*
 * freed if `freeWhenDone` is true.
 *
 * @param items The items to store in the OFData
 * @param count The number of items
 * @param freeWhenDone Whether to free the pointer when it is no longer needed
 *		       by the OFData
 * @return An initialized OFData
 */
- (instancetype)initWithItemsNoCopy: (void *)items
			      count: (size_t)count
		       freeWhenDone: (bool)freeWhenDone;

/**
 * @brief Initializes an already allocated OFData with the specified `count`
 *	  items of the specified size by taking ownership of the specified
 *	  items pointer.
 *
 * If initialization fails for whatever reason, the passed memory is *not*
 * freed if `freeWhenDone` is true.
 *
 * @param items The items to store in the OFData
 * @param count The number of items
 * @param itemSize The item size of a single item in bytes
 * @param freeWhenDone Whether to free the pointer when it is no longer needed
 *		       by the OFData
 * @return An initialized OFData

Modified src/OFDatagramSocket.h from [66a4384630] to [d713554b61].

183
184
185
186
187
188
189
190

191
192
193
194
195
196
197
 * @brief Asynchronously receives a datagram and stores it into the specified
 *	  buffer.
 *
 * If the buffer is too small, the datagram is truncated.
 *
 * @param buffer The buffer to write the datagram to
 * @param length The length of the buffer
 * @param runLoopMode The run loop mode in which to perform the async receive

 */
- (void)asyncReceiveIntoBuffer: (void *)buffer
			length: (size_t)length
		   runLoopMode: (OFRunLoopMode)runLoopMode;

#ifdef OF_HAVE_BLOCKS
/**







|
>







183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
 * @brief Asynchronously receives a datagram and stores it into the specified
 *	  buffer.
 *
 * If the buffer is too small, the datagram is truncated.
 *
 * @param buffer The buffer to write the datagram to
 * @param length The length of the buffer
 * @param runLoopMode The run loop mode in which to perform the asynchronous
 *		      receive
 */
- (void)asyncReceiveIntoBuffer: (void *)buffer
			length: (size_t)length
		   runLoopMode: (OFRunLoopMode)runLoopMode;

#ifdef OF_HAVE_BLOCKS
/**
217
218
219
220
221
222
223
224

225
226
227
228
229
230
231
 * @brief Asynchronously receives a datagram and stores it into the specified
 *	  buffer.
 *
 * If the buffer is too small, the datagram is truncated.
 *
 * @param buffer The buffer to write the datagram to
 * @param length The length of the buffer
 * @param runLoopMode The run loop mode in which to perform the async receive

 * @param block The block to call when the datagram has been received. If the
 *		block returns true, it will be called again with the same
 *		buffer and maximum length when more datagrams have been
 *		received. If you want the next method in the queue to handle
 *		the datagram received next, you need to return false from the
 *		method.
 */







|
>







218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
 * @brief Asynchronously receives a datagram and stores it into the specified
 *	  buffer.
 *
 * If the buffer is too small, the datagram is truncated.
 *
 * @param buffer The buffer to write the datagram to
 * @param length The length of the buffer
 * @param runLoopMode The run loop mode in which to perform the asynchronous
 *		      receive
 * @param block The block to call when the datagram has been received. If the
 *		block returns true, it will be called again with the same
 *		buffer and maximum length when more datagrams have been
 *		received. If you want the next method in the queue to handle
 *		the datagram received next, you need to return false from the
 *		method.
 */
259
260
261
262
263
264
265
266
267
268

269
270
271
272
273
274
275
- (void)asyncSendData: (OFData *)data
	     receiver: (const OFSocketAddress *)receiver;

/**
 * @brief Asynchronously sends the specified datagram to the specified address.
 *
 * @param data The data to send as a datagram
 * @param receiver A pointer to an @ref OFSocketAddress to which the datgram
 *		   should be sent. The receiver is copied.
 * @param runLoopMode The run loop mode in which to perform the async send

 */
- (void)asyncSendData: (OFData *)data
	     receiver: (const OFSocketAddress *)receiver
	  runLoopMode: (OFRunLoopMode)runLoopMode;

#ifdef OF_HAVE_BLOCKS
/**







|

|
>







261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
- (void)asyncSendData: (OFData *)data
	     receiver: (const OFSocketAddress *)receiver;

/**
 * @brief Asynchronously sends the specified datagram to the specified address.
 *
 * @param data The data to send as a datagram
 * @param receiver A pointer to an @ref OFSocketAddress to which the datagram
 *		   should be sent. The receiver is copied.
 * @param runLoopMode The run loop mode in which to perform the asynchronous
 *		      send
 */
- (void)asyncSendData: (OFData *)data
	     receiver: (const OFSocketAddress *)receiver
	  runLoopMode: (OFRunLoopMode)runLoopMode;

#ifdef OF_HAVE_BLOCKS
/**
288
289
290
291
292
293
294
295

296
297
298
299
300
301
302

/**
 * @brief Asynchronously sends the specified datagram to the specified address.
 *
 * @param data The data to send as a datagram
 * @param receiver A pointer to an @ref OFSocketAddress to which the datagram
 *		   should be sent. The receiver is copied.
 * @param runLoopMode The run loop mode in which to perform the async send

 * @param block The block to call when the packet has been sent. It should
 *		return the data for the next send with the same callback or nil
 *		if it should not repeat.
 */
- (void)asyncSendData: (OFData *)data
	     receiver: (const OFSocketAddress *)receiver
	  runLoopMode: (OFRunLoopMode)runLoopMode







|
>







291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306

/**
 * @brief Asynchronously sends the specified datagram to the specified address.
 *
 * @param data The data to send as a datagram
 * @param receiver A pointer to an @ref OFSocketAddress to which the datagram
 *		   should be sent. The receiver is copied.
 * @param runLoopMode The run loop mode in which to perform the asynchronous
 *		      send
 * @param block The block to call when the packet has been sent. It should
 *		return the data for the next send with the same callback or nil
 *		if it should not repeat.
 */
- (void)asyncSendData: (OFData *)data
	     receiver: (const OFSocketAddress *)receiver
	  runLoopMode: (OFRunLoopMode)runLoopMode

Modified src/OFDate.h from [4f1d875b2a] to [6b70e68930].

185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
 */
+ (instancetype)dateWithLocalDateString: (OFString *)string
				 format: (OFString *)format;

/**
 * @brief Returns a date in the distant future.
 *
 * The date is system-dependant.
 *
 * @return A date in the distant future
 */
+ (instancetype)distantFuture;

/**
 * @brief Returns a date in the distant past.
 *
 * The date is system-dependant.
 *
 * @return A date in the distant past
 */
+ (instancetype)distantPast;

/**
 * @brief Initializes an already allocated OFDate with the specified date and







|








|







185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
 */
+ (instancetype)dateWithLocalDateString: (OFString *)string
				 format: (OFString *)format;

/**
 * @brief Returns a date in the distant future.
 *
 * The date is system-dependent.
 *
 * @return A date in the distant future
 */
+ (instancetype)distantFuture;

/**
 * @brief Returns a date in the distant past.
 *
 * The date is system-dependent.
 *
 * @return A date in the distant past
 */
+ (instancetype)distantPast;

/**
 * @brief Initializes an already allocated OFDate with the specified date and

Modified src/OFFileManager.h from [e1a6d31241] to [e4f59a6817].

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
 */
- (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







|
















|







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
 */
- (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 of 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 of 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

Modified src/OFGZIPStream.m from [51e839e54b] to [446ae4ffb6].

246
247
248
249
250
251
252
253

254
255
256
257
258
259
260
261

			[_inflateStream release];
			_inflateStream = nil;

			_state++;
			break;
		case OFGZIPStreamStateCRC32:
			_bytesRead += [_stream readIntoBuffer: _buffer

						       length: 4 - _bytesRead];

			if (_bytesRead < 4)
				return 0;

			CRC32 = ((uint32_t)_buffer[3] << 24) |
			    (_buffer[2] << 16) | (_buffer[1] << 8) | _buffer[0];
			if (~_CRC32 != CRC32) {







|
>
|







246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262

			[_inflateStream release];
			_inflateStream = nil;

			_state++;
			break;
		case OFGZIPStreamStateCRC32:
			_bytesRead += [_stream
			    readIntoBuffer: _buffer + _bytesRead
				    length: 4 - _bytesRead];

			if (_bytesRead < 4)
				return 0;

			CRC32 = ((uint32_t)_buffer[3] << 24) |
			    (_buffer[2] << 16) | (_buffer[1] << 8) | _buffer[0];
			if (~_CRC32 != CRC32) {
270
271
272
273
274
275
276
277

278
279



280
281
282
283
284
285
286
287
			}

			_bytesRead = 0;
			_CRC32 = ~0;
			_state++;
			break;
		case OFGZIPStreamStateUncompressedSize:
			_bytesRead += [_stream readIntoBuffer: _buffer

						       length: 4 - _bytesRead];




			uncompressedSize = ((uint32_t)_buffer[3] << 24) |
			    (_buffer[2] << 16) | (_buffer[1] << 8) | _buffer[0];
			if (_uncompressedSize != uncompressedSize) {
				OFString *actual = [OFString stringWithFormat:
				    @"%" PRIu32, _uncompressedSize];
				OFString *expected = [OFString stringWithFormat:
				    @"%" PRIu32, uncompressedSize];








|
>
|

>
>
>
|







271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
			}

			_bytesRead = 0;
			_CRC32 = ~0;
			_state++;
			break;
		case OFGZIPStreamStateUncompressedSize:
			_bytesRead += [_stream
			    readIntoBuffer: _buffer + _bytesRead
				    length: 4 - _bytesRead];

			if (_bytesRead < 4)
				return 0;

			uncompressedSize = (_buffer[3] << 24) |
			    (_buffer[2] << 16) | (_buffer[1] << 8) | _buffer[0];
			if (_uncompressedSize != uncompressedSize) {
				OFString *actual = [OFString stringWithFormat:
				    @"%" PRIu32, _uncompressedSize];
				OFString *expected = [OFString stringWithFormat:
				    @"%" PRIu32, uncompressedSize];

Added src/OFHINFODNSResourceRecord.h version [14e295dba0].



































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
/*
 * Copyright (c) 2008-2024 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the 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 "OFDNSResourceRecord.h"

OF_ASSUME_NONNULL_BEGIN

/**
 * @class OFHINFODNSResourceRecord \
 *	  OFDNSResourceRecord.h ObjFW/OFDNSResourceRecord.h
 *
 * @brief A class representing an HINFO DNS resource record.
 */
OF_SUBCLASSING_RESTRICTED
@interface OFHINFODNSResourceRecord: OFDNSResourceRecord
{
	OFString *_CPU, *_OS;
}

/**
 * @brief The CPU of the host info of the resource record.
 */
@property (readonly, nonatomic) OFString *CPU;

/**
 * @brief The OS of the host info of the resource record.
 */
@property (readonly, nonatomic) OFString *OS;

- (instancetype)initWithName: (OFString *)name
		    DNSClass: (OFDNSClass)DNSClass
		  recordType: (OFDNSRecordType)recordType
			 TTL: (uint32_t)TTL OF_UNAVAILABLE;

/**
 * @brief Initializes an already allocated OFHINFODNSResourceRecord with the
 *	  specified name, class, domain name and time to live.
 *
 * @param name The name for the resource record
 * @param DNSClass The class code for the resource record
 * @param CPU The CPU of the host info for the resource record
 * @param OS The OS of the host info for the resource record
 * @param TTL The time to live for the resource record
 * @return An initialized OFHINFODNSResourceRecord
 */
- (instancetype)initWithName: (OFString *)name
		    DNSClass: (OFDNSClass)DNSClass
			 CPU: (OFString *)CPU
			  OS: (OFString *)OS
			 TTL: (uint32_t)TTL OF_DESIGNATED_INITIALIZER;
@end

OF_ASSUME_NONNULL_END

Added src/OFHINFODNSResourceRecord.m version [338b93a184].





















































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
/*
 * Copyright (c) 2008-2024 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the 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 "OFHINFODNSResourceRecord.h"

@implementation OFHINFODNSResourceRecord
@synthesize CPU = _CPU, OS = _OS;

- (instancetype)initWithName: (OFString *)name
		    DNSClass: (OFDNSClass)DNSClass
		  recordType: (OFDNSRecordType)recordType
			 TTL: (uint32_t)TTL
{
	OF_INVALID_INIT_METHOD
}

- (instancetype)initWithName: (OFString *)name
		    DNSClass: (OFDNSClass)DNSClass
			 CPU: (OFString *)CPU
			  OS: (OFString *)OS
			 TTL: (uint32_t)TTL
{
	self = [super initWithName: name
			  DNSClass: DNSClass
			recordType: OFDNSRecordTypeHINFO
			       TTL: TTL];

	@try {
		_CPU = [CPU copy];
		_OS = [OS copy];
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (void)dealloc
{
	[_CPU release];
	[_OS release];

	[super dealloc];
}

- (bool)isEqual: (id)object
{
	OFHINFODNSResourceRecord *record;

	if (object == self)
		return true;

	if (![object isKindOfClass: [OFHINFODNSResourceRecord class]])
		return false;

	record = object;

	if (record->_name != _name && ![record->_name isEqual: _name])
		return false;

	if (record->_DNSClass != _DNSClass)
		return false;

	if (record->_recordType != _recordType)
		return false;

	if (record->_CPU != _CPU && ![record->_CPU isEqual: _CPU])
		return false;

	if (record->_OS != _OS && ![record->_OS isEqual: _OS])
		return false;

	return true;
}

- (unsigned long)hash
{
	unsigned long hash;

	OFHashInit(&hash);

	OFHashAddHash(&hash, _name.hash);
	OFHashAddByte(&hash, _DNSClass >> 8);
	OFHashAddByte(&hash, _DNSClass);
	OFHashAddByte(&hash, _recordType >> 8);
	OFHashAddByte(&hash, _recordType);
	OFHashAddHash(&hash, _CPU.hash);
	OFHashAddHash(&hash, _OS.hash);

	OFHashFinalize(&hash);

	return hash;
}

- (OFString *)description
{
	return [OFString stringWithFormat:
	    @"<%@:\n"
	    @"\tName = %@\n"
	    @"\tClass = %@\n"
	    @"\tCPU = %@\n"
	    @"\tOS = %@\n"
	    @"\tTTL = %" PRIu32 "\n"
	    @">",
	    self.className, _name, OFDNSClassName(_DNSClass), _CPU, _OS, _TTL];
}
@end

Modified src/OFHTTPResponse.h from [d5e8497e61] to [0ce770d124].

70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
 *	  falling back to the specified encoding if not detectable.
 *
 * @return The response as a string
 */
- (OFString *)readString;

/**
 * @brief Rread the response as a string, trying to detect the encoding and
 *	  falling back to the specified encoding if not detectable.
 *
 * @return The response as a string
 */
- (OFString *)readStringWithEncoding: (OFStringEncoding)encoding;
@end








|







70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
 *	  falling back to the specified encoding if not detectable.
 *
 * @return The response as a string
 */
- (OFString *)readString;

/**
 * @brief Read the response as a string, trying to detect the encoding and
 *	  falling back to the specified encoding if not detectable.
 *
 * @return The response as a string
 */
- (OFString *)readStringWithEncoding: (OFStringEncoding)encoding;
@end

Modified src/OFHTTPServer.h from [4313a7362c] to [1ff7289cfa].

54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
 *	  encountered an exception.
 *
 * @param server The HTTP server which encountered an exception
 * @param exception The exception which occurred on the HTTP server's listening
 *		    socket
 * @return Whether to continue listening. If you return false, existing
 *	   connections will still be handled and you can start accepting new
 *	   connections again by calling @ref OFHTTPServer::start again.
 */
-			  (bool)server: (OFHTTPServer *)server
  didReceiveExceptionOnListeningSocket: (id)exception;

/**
 * @brief This method is called when a socket for a client encountered an
 * exception.







|







54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
 *	  encountered an exception.
 *
 * @param server The HTTP server which encountered an exception
 * @param exception The exception which occurred on the HTTP server's listening
 *		    socket
 * @return Whether to continue listening. If you return false, existing
 *	   connections will still be handled and you can start accepting new
 *	   connections again by calling @ref OFHTTPServer#start again.
 */
-			  (bool)server: (OFHTTPServer *)server
  didReceiveExceptionOnListeningSocket: (id)exception;

/**
 * @brief This method is called when a socket for a client encountered an
 * exception.

Modified src/OFIRI.h from [30cbd259c9] to [d647ebbbce].

214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
+ (instancetype)fileIRIWithPath: (OFString *)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 OFIRI
 */
+ (instancetype)fileIRIWithPath: (OFString *)path
		    isDirectory: (bool)isDirectory;
#endif

/**







|







214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
+ (instancetype)fileIRIWithPath: (OFString *)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
 *		      appended if there is no slash yet
 * @return An initialized OFIRI
 */
+ (instancetype)fileIRIWithPath: (OFString *)path
		    isDirectory: (bool)isDirectory;
#endif

/**
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277

/**
 * @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 OFIRI
 */
- (instancetype)initFileIRIWithPath: (OFString *)path
			isDirectory: (bool)isDirectory;
#endif

- (instancetype)init OF_UNAVAILABLE;







|







263
264
265
266
267
268
269
270
271
272
273
274
275
276
277

/**
 * @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
 *		      appended if there is no slash yet
 * @return An initialized OFIRI
 */
- (instancetype)initFileIRIWithPath: (OFString *)path
			isDirectory: (bool)isDirectory;
#endif

- (instancetype)init OF_UNAVAILABLE;

Modified src/OFIRIHandler.h from [91924a5c3a] to [c8eb6b46d2].

328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
 *				    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







|







328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
 *				    implemented for the specified item
 */
- (void)setExtendedAttributeData: (OFData *)data
			 forName: (OFString *)name
		     ofItemAtIRI: (OFIRI *)IRI;

/**
 * @brief Removes the extended attribute 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 to remove
 * @param IRI The IRI of the item to remove the extended attribute from
 * @throw OFSetItemAttributesFailedException Removing the extended attribute

Modified src/OFKernelEventObserver.h from [eb3d0cf38f] to [d85dfacfc9].

41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
 */
@protocol OFKernelEventObserverDelegate <OFObject>
@optional
/**
 * @brief This callback is called when an object did get ready for reading.
 *
 * @note If the object is a subclass of @ref OFStream and
 *	 @ref OFStream::tryReadLine or @ref OFStream::tryReadUntilDelimiter:
 *	 has been called on the stream, this callback will not be called again
 *	 until new data has been received, even though there is still data in
 *	 the cache. The reason for this is to prevent spinning in a loop when
 *	 there is an incomplete string in the cache. Once the string has been
 *	 completed, the callback will be called again as long there is data in
 *	 the cache.
 *







|







41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
 */
@protocol OFKernelEventObserverDelegate <OFObject>
@optional
/**
 * @brief This callback is called when an object did get ready for reading.
 *
 * @note If the object is a subclass of @ref OFStream and
 *	 @ref OFStream#tryReadLine or @ref OFStream#tryReadUntilDelimiter:
 *	 has been called on the stream, this callback will not be called again
 *	 until new data has been received, even though there is still data in
 *	 the cache. The reason for this is to prevent spinning in a loop when
 *	 there is an incomplete string in the cache. Once the string has been
 *	 completed, the callback will be called again as long there is data in
 *	 the cache.
 *

Added src/OFLOCDNSResourceRecord.h version [209ff98f84].









































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
/*
 * Copyright (c) 2008-2024 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the 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 "OFDNSResourceRecord.h"

OF_ASSUME_NONNULL_BEGIN

/**
 * @class OFLOCDNSResourceRecord \
 *	  OFDNSResourceRecord.h ObjFW/OFDNSResourceRecord.h
 *
 * @brief A class representing an LOC DNS resource record.
 */
OF_SUBCLASSING_RESTRICTED
@interface OFLOCDNSResourceRecord: OFDNSResourceRecord
{
	uint8_t _size, _horizontalPrecision, _verticalPrecision;
	uint32_t _latitude, _longitude, _altitude;
}

/**
 * @brief The diameter in centimeters of a sphere enclosing the position,
 *	  encoded as per RFC 1876.
 */
@property (readonly, nonatomic) uint8_t size;

/**
 * @brief The horizontal precision in centimeters, encoded as per RFC 1876.
 */
@property (readonly, nonatomic) uint8_t horizontalPrecision;

/**
 * @brief The vertical precision in centimeters, encoded as per RFC 1876.
 */
@property (readonly, nonatomic) uint8_t verticalPrecision;

/**
 * @brief The latitude in thousands of a second of an arc.
 */
@property (readonly, nonatomic) uint32_t latitude;

/**
 * @brief The longitude in thousands of a second of an arc.
 */
@property (readonly, nonatomic) uint32_t longitude;

/**
 * @brief The altitude in centimeters from a base of 100000 meters below the
 *	  GPS reference.
 */
@property (readonly, nonatomic) uint32_t altitude;

- (instancetype)initWithName: (OFString *)name
		    DNSClass: (OFDNSClass)DNSClass
		  recordType: (OFDNSRecordType)recordType
			 TTL: (uint32_t)TTL OF_UNAVAILABLE;

/**
 * @brief Initializes an already allocated OFLOCDNSResourceRecord with the
 *	  specified name, class, domain name and time to live.
 *
 * @param name The name for the resource record
 * @param DNSClass The class code for the resource record
 * @param size The diameter in centimeters of a sphere enclosing the position,
 *	       encoded as per RFC 1876
 * @param horizontalPrecision The horizontal precision in centimeters, encoded
 *			      as per RFC 1876
 * @param verticalPrecision The vertical precision in centimeters, encoded as
 *			    per RFC 1876
 * @param latitude The latitude in thousands of a second of an arc
 * @param longitude The longitude in thousands of a second of an arc
 * @param altitude The altitude in centimeters from a base of 100000 meters
 *		   below the GPS reference
 * @param TTL The time to live for the resource record
 * @return An initialized OFLOCDNSResourceRecord
 */
- (instancetype)initWithName: (OFString *)name
		    DNSClass: (OFDNSClass)DNSClass
			size: (uint8_t)size
	 horizontalPrecision: (uint8_t)horizontalPrecision
	   verticalPrecision: (uint8_t)verticalPrecision
		    latitude: (uint32_t)latitude
		   longitude: (uint32_t)longitude
		    altitude: (uint32_t)altitude
			 TTL: (uint32_t)TTL OF_DESIGNATED_INITIALIZER;
@end

OF_ASSUME_NONNULL_END

Added src/OFLOCDNSResourceRecord.m version [bd7a5c4c92].































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
/*
 * Copyright (c) 2008-2024 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the 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 "OFLOCDNSResourceRecord.h"

@implementation OFLOCDNSResourceRecord
@synthesize size = _size, horizontalPrecision = _horizontalPrecision;
@synthesize verticalPrecision = _verticalPrecision, latitude = _latitude;
@synthesize longitude = _longitude, altitude = _altitude;

- (instancetype)initWithName: (OFString *)name
		    DNSClass: (OFDNSClass)DNSClass
		  recordType: (OFDNSRecordType)recordType
			 TTL: (uint32_t)TTL
{
	OF_INVALID_INIT_METHOD
}

- (instancetype)initWithName: (OFString *)name
		    DNSClass: (OFDNSClass)DNSClass
			size: (uint8_t)size
	 horizontalPrecision: (uint8_t)horizontalPrecision
	   verticalPrecision: (uint8_t)verticalPrecision
		    latitude: (uint32_t)latitude
		   longitude: (uint32_t)longitude
		    altitude: (uint32_t)altitude
			 TTL: (uint32_t)TTL
{
	self = [super initWithName: name
			  DNSClass: DNSClass
			recordType: OFDNSRecordTypeLOC
			       TTL: TTL];

	@try {
		_size = size;
		_horizontalPrecision = horizontalPrecision;
		_verticalPrecision = verticalPrecision;
		_latitude = latitude;
		_longitude = longitude;
		_altitude = altitude;
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (bool)isEqual: (id)object
{
	OFLOCDNSResourceRecord *record;

	if (object == self)
		return true;

	if (![object isKindOfClass: [OFLOCDNSResourceRecord class]])
		return false;

	record = object;

	if (record->_name != _name && ![record->_name isEqual: _name])
		return false;

	if (record->_DNSClass != _DNSClass)
		return false;

	if (record->_recordType != _recordType)
		return false;

	if (record->_size != _size)
		return false;

	if (record->_horizontalPrecision != _horizontalPrecision)
		return false;

	if (record->_verticalPrecision != _verticalPrecision)
		return false;

	if (record->_latitude != _latitude)
		return false;

	if (record->_longitude != _longitude)
		return false;

	if (record->_altitude != _altitude)
		return false;

	return true;
}

- (unsigned long)hash
{
	unsigned long hash;

	OFHashInit(&hash);

	OFHashAddHash(&hash, _name.hash);
	OFHashAddByte(&hash, _DNSClass >> 8);
	OFHashAddByte(&hash, _DNSClass);
	OFHashAddByte(&hash, _recordType >> 8);
	OFHashAddByte(&hash, _recordType);
	OFHashAddByte(&hash, _size);
	OFHashAddByte(&hash, _horizontalPrecision);
	OFHashAddByte(&hash, _verticalPrecision);
	OFHashAddByte(&hash, _latitude >> 24);
	OFHashAddByte(&hash, _latitude >> 16);
	OFHashAddByte(&hash, _latitude >> 8);
	OFHashAddByte(&hash, _latitude);
	OFHashAddByte(&hash, _longitude >> 24);
	OFHashAddByte(&hash, _longitude >> 16);
	OFHashAddByte(&hash, _longitude >> 8);
	OFHashAddByte(&hash, _longitude);
	OFHashAddByte(&hash, _altitude >> 24);
	OFHashAddByte(&hash, _altitude >> 16);
	OFHashAddByte(&hash, _altitude >> 8);
	OFHashAddByte(&hash, _altitude);

	OFHashFinalize(&hash);

	return hash;
}

- (OFString *)description
{
	return [OFString stringWithFormat:
	    @"<%@:\n"
	    @"\tName = %@\n"
	    @"\tClass = %@\n"
	    @"\tSize = %ue%u\n"
	    @"\tHorizontal precision = %ue%u\n"
	    @"\tVertical precision = %ue%u\n"
	    @"\tLatitude = %f\n"
	    @"\tLongitude = %f\n"
	    @"\tAltitude = %f\n"
	    @"\tTTL = %" PRIu32 "\n"
	    @">",
	    self.className, _name, OFDNSClassName(_DNSClass),
	    _size >> 4, _size & 0xF,
	    _horizontalPrecision >> 4, _horizontalPrecision & 0xF,
	    _verticalPrecision >> 4, _verticalPrecision & 0xF,
	    ((double)_latitude - 2147483648) / 3600000,
	    ((double)_longitude - 2147483648) / 3600000,
	    ((double)_altitude - 10000000) / 100, _TTL];
}
@end

Modified src/OFList.h from [72f0b22ce8] to [cf0e346436].

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

OF_ASSUME_NONNULL_BEGIN

/** @file */

/*
 * Make clang's -Wdocumentation shut about about using @struct on someting it
 * thinks is not a struct. Doxygen requires it this way.
 */
#ifdef __clang__
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wdocumentation"
#endif
/**
 * @struct OFListItem OFList.h ObjFW/OFList.h







|
|







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

OF_ASSUME_NONNULL_BEGIN

/** @file */

/*
 * Make clang's -Wdocumentation shut up about about using @struct on something
 * it thinks is not a struct. Doxygen requires it this way.
 */
#ifdef __clang__
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wdocumentation"
#endif
/**
 * @struct OFListItem OFList.h ObjFW/OFList.h

Added src/OFMXDNSResourceRecord.h version [0fb7a9349d].





































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
/*
 * Copyright (c) 2008-2024 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the 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 "OFDNSResourceRecord.h"

OF_ASSUME_NONNULL_BEGIN

/**
 * @class OFMXDNSResourceRecord \
 *	  OFDNSResourceRecord.h ObjFW/OFDNSResourceRecord.h
 *
 * @brief A class representing an MX DNS resource record.
 */
OF_SUBCLASSING_RESTRICTED
@interface OFMXDNSResourceRecord: OFDNSResourceRecord
{
	uint16_t _preference;
	OFString *_mailExchange;
}

/**
 * @brief The preference of the resource record.
 */
@property (readonly, nonatomic) uint16_t preference;

/**
 * @brief The mail exchange of the resource record.
 */
@property (readonly, nonatomic) OFString *mailExchange;

- (instancetype)initWithName: (OFString *)name
		    DNSClass: (OFDNSClass)DNSClass
		  recordType: (OFDNSRecordType)recordType
			 TTL: (uint32_t)TTL OF_UNAVAILABLE;

/**
 * @brief Initializes an already allocated OFMXDNSResourceRecord with the
 *	  specified name, class, preference, mail exchange and time to live.
 *
 * @param name The name for the resource record
 * @param DNSClass The class code for the resource record
 * @param preference The preference for the resource record
 * @param mailExchange The mail exchange for the resource record
 * @param TTL The time to live for the resource record
 * @return An initialized OFMXDNSResourceRecord
 */
- (instancetype)initWithName: (OFString *)name
		    DNSClass: (OFDNSClass)DNSClass
		  preference: (uint16_t)preference
		mailExchange: (OFString *)mailExchange
			 TTL: (uint32_t)TTL OF_DESIGNATED_INITIALIZER;
@end

OF_ASSUME_NONNULL_END

Added src/OFMXDNSResourceRecord.m version [4f0b3f3d3d].

























































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
/*
 * Copyright (c) 2008-2024 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the 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 "OFMXDNSResourceRecord.h"

@implementation OFMXDNSResourceRecord
@synthesize preference = _preference, mailExchange = _mailExchange;

- (instancetype)initWithName: (OFString *)name
		    DNSClass: (OFDNSClass)DNSClass
		  recordType: (OFDNSRecordType)recordType
			 TTL: (uint32_t)TTL
{
	OF_INVALID_INIT_METHOD
}

- (instancetype)initWithName: (OFString *)name
		    DNSClass: (OFDNSClass)DNSClass
		  preference: (uint16_t)preference
		mailExchange: (OFString *)mailExchange
			 TTL: (uint32_t)TTL
{
	self = [super initWithName: name
			  DNSClass: DNSClass
			recordType: OFDNSRecordTypeMX
			       TTL: TTL];

	@try {
		_preference = preference;
		_mailExchange = [mailExchange copy];
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (void)dealloc
{
	[_mailExchange release];

	[super dealloc];
}

- (bool)isEqual: (id)object
{
	OFMXDNSResourceRecord *record;

	if (object == self)
		return true;

	if (![object isKindOfClass: [OFMXDNSResourceRecord class]])
		return false;

	record = object;

	if (record->_name != _name && ![record->_name isEqual: _name])
		return false;

	if (record->_DNSClass != _DNSClass)
		return false;

	if (record->_recordType != _recordType)
		return false;

	if (record->_preference != _preference)
		return false;

	if (record->_mailExchange != _mailExchange &&
	    ![record->_mailExchange isEqual: _mailExchange])
		return false;

	return true;
}

- (unsigned long)hash
{
	unsigned long hash;

	OFHashInit(&hash);

	OFHashAddHash(&hash, _name.hash);
	OFHashAddByte(&hash, _DNSClass >> 8);
	OFHashAddByte(&hash, _DNSClass);
	OFHashAddByte(&hash, _recordType >> 8);
	OFHashAddByte(&hash, _recordType);
	OFHashAddByte(&hash, _preference >> 8);
	OFHashAddByte(&hash, _preference);
	OFHashAddHash(&hash, _mailExchange.hash);

	OFHashFinalize(&hash);

	return hash;
}

- (OFString *)description
{
	return [OFString stringWithFormat:
	    @"<%@:\n"
	    @"\tName = %@\n"
	    @"\tClass = %@\n"
	    @"\tPreference = %" PRIu16 "\n"
	    @"\tMail Exchange = %@\n"
	    @"\tTTL = %" PRIu32 "\n"
	    @">",
	    self.className, _name, OFDNSClassName(_DNSClass), _preference,
	    _mailExchange, _TTL];
}
@end

Modified src/OFMatrix4x4.h from [c4c1c25c02] to [49eeebb49a].

58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
 * @param values A 2D array of 4x4 floats in row-major format
 * @return An initialized OFMatrix4x4
 */
- (instancetype)initWithValues: (const float [_Nonnull 4][4])values
    OF_DESIGNATED_INITIALIZER;

/**
 * @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;

/**







|







58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
 * @param values A 2D array of 4x4 floats in row-major format
 * @return An initialized OFMatrix4x4
 */
- (instancetype)initWithValues: (const float [_Nonnull 4][4])values
    OF_DESIGNATED_INITIALIZER;

/**
 * @brief Multiplies 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;

/**
91
92
93
94
95
96
97

98
99
100
101
102
 */
- (OFVector4D)transformedVector: (OFVector4D)vector;

/**
 * @brief Transforms the specified vectors in-place according to the matrix.
 *
 * @param vectors The vectors to transform

 */
- (void)transformVectors: (OFVector4D *)vectors count: (size_t)count;
@end

OF_ASSUME_NONNULL_END







>





91
92
93
94
95
96
97
98
99
100
101
102
103
 */
- (OFVector4D)transformedVector: (OFVector4D)vector;

/**
 * @brief Transforms the specified vectors in-place according to the matrix.
 *
 * @param vectors The vectors to transform
 * @param count The count of the specified vectors
 */
- (void)transformVectors: (OFVector4D *)vectors count: (size_t)count;
@end

OF_ASSUME_NONNULL_END

Modified src/OFMutableIRI.h from [e8a4ec8dda] to [d2091df092].

199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
- (void)appendPathComponent: (OFString *)component;

/**
 * @brief Appends the specified path component.
 *
 * @param component The component to append
 * @param isDirectory Whether the path is a directory, in which case a slash is
 *		      appened if there is no slash yet
 */
- (void)appendPathComponent: (OFString *)component
		isDirectory: (bool)isDirectory;

/**
 * @brief Resolves relative subpaths.
 */







|







199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
- (void)appendPathComponent: (OFString *)component;

/**
 * @brief Appends the specified path component.
 *
 * @param component The component to append
 * @param isDirectory Whether the path is a directory, in which case a slash is
 *		      appended if there is no slash yet
 */
- (void)appendPathComponent: (OFString *)component
		isDirectory: (bool)isDirectory;

/**
 * @brief Resolves relative subpaths.
 */

Modified src/OFMutableString.h from [b3cde87d6a] to [d2c2845047].

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

/**
 * @brief Replaces all occurrences of a string in the specified range with
 *	  another string.
 *
 * @param string The string to replace
 * @param replacement The string with which it should be replaced
 * @param options Options modifying search behaviour
 *		  Possible values: None yet
 * @param range The range in which the string should be replaced
 */
- (void)replaceOccurrencesOfString: (OFString *)string
			withString: (OFString *)replacement
			   options: (int)options
			     range: (OFRange)range;







|







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

/**
 * @brief Replaces all occurrences of a string in the specified range with
 *	  another string.
 *
 * @param string The string to replace
 * @param replacement The string with which it should be replaced
 * @param options Options modifying search behavior
 *		  Possible values: None yet
 * @param range The range in which the string should be replaced
 */
- (void)replaceOccurrencesOfString: (OFString *)string
			withString: (OFString *)replacement
			   options: (int)options
			     range: (OFRange)range;

Added src/OFNSDNSResourceRecord.h version [fa3df170b9].





















































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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-2024 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the 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 "OFDNSResourceRecord.h"

OF_ASSUME_NONNULL_BEGIN

/**
 * @class OFNSDNSResourceRecord \
 *	  OFDNSResourceRecord.h ObjFW/OFDNSResourceRecord.h
 *
 * @brief A class representing an NS DNS resource record.
 */
OF_SUBCLASSING_RESTRICTED
@interface OFNSDNSResourceRecord: OFDNSResourceRecord
{
	OFString *_authoritativeHost;
}

/**
 * @brief The authoritative host of the resource record.
 */
@property (readonly, nonatomic) OFString *authoritativeHost;

- (instancetype)initWithName: (OFString *)name
		    DNSClass: (OFDNSClass)DNSClass
		  recordType: (OFDNSRecordType)recordType
			 TTL: (uint32_t)TTL OF_UNAVAILABLE;

/**
 * @brief Initializes an already allocated OFNSDNSResourceRecord with the
 *	  specified name, class, authoritative host and time to live.
 *
 * @param name The name for the resource record
 * @param DNSClass The class code for the resource record
 * @param authoritativeHost The authoritative host for the resource record
 * @param TTL The time to live for the resource record
 * @return An initialized OFNSDNSResourceRecord
 */
- (instancetype)initWithName: (OFString *)name
		    DNSClass: (OFDNSClass)DNSClass
	   authoritativeHost: (OFString *)authoritativeHost
			 TTL: (uint32_t)TTL OF_DESIGNATED_INITIALIZER;
@end

OF_ASSUME_NONNULL_END

Added src/OFNSDNSResourceRecord.m version [7be2911f16].









































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
/*
 * Copyright (c) 2008-2024 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the 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 "OFMXDNSResourceRecord.h"

@implementation OFNSDNSResourceRecord
@synthesize authoritativeHost = _authoritativeHost;

- (instancetype)initWithName: (OFString *)name
		    DNSClass: (OFDNSClass)DNSClass
		  recordType: (OFDNSRecordType)recordType
			 TTL: (uint32_t)TTL
{
	OF_INVALID_INIT_METHOD
}

- (instancetype)initWithName: (OFString *)name
		    DNSClass: (OFDNSClass)DNSClass
	   authoritativeHost: (OFString *)authoritativeHost
			 TTL: (uint32_t)TTL
{
	self = [super initWithName: name
			  DNSClass: DNSClass
			recordType: OFDNSRecordTypeNS
			       TTL: TTL];

	@try {
		_authoritativeHost = [authoritativeHost copy];
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (void)dealloc
{
	[_authoritativeHost release];

	[super dealloc];
}

- (bool)isEqual: (id)object
{
	OFNSDNSResourceRecord *record;

	if (object == self)
		return true;

	if (![object isKindOfClass: [OFNSDNSResourceRecord class]])
		return false;

	record = object;

	if (record->_name != _name && ![record->_name isEqual: _name])
		return false;

	if (record->_DNSClass != _DNSClass)
		return false;

	if (record->_recordType != _recordType)
		return false;

	if (record->_authoritativeHost != _authoritativeHost &&
	    ![record->_authoritativeHost isEqual: _authoritativeHost])
		return false;

	return true;
}

- (unsigned long)hash
{
	unsigned long hash;

	OFHashInit(&hash);

	OFHashAddHash(&hash, _name.hash);
	OFHashAddByte(&hash, _DNSClass >> 8);
	OFHashAddByte(&hash, _DNSClass);
	OFHashAddByte(&hash, _recordType >> 8);
	OFHashAddByte(&hash, _recordType);
	OFHashAddHash(&hash, _authoritativeHost.hash);

	OFHashFinalize(&hash);

	return hash;
}

- (OFString *)description
{
	return [OFString stringWithFormat:
	    @"<%@:\n"
	    @"\tName = %@\n"
	    @"\tClass = %@\n"
	    @"\tAuthoritative Host = %@\n"
	    @"\tTTL = %" PRIu32 "\n"
	    @">",
	    self.className, _name, OFDNSClassName(_DNSClass),
	    _authoritativeHost, _TTL];
}
@end

Modified src/OFObject.h from [f6921949eb] to [cd5ab83dfc].

79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
 * @param right The right object
 * @return The order of the objects
 */
typedef OFComparisonResult (^OFComparator)(id _Nonnull left, id _Nonnull right);
#endif

/**
 * @brief An enum for representing endianess.
 */
typedef enum {
	/** Most significant byte first (big endian) */
	OFByteOrderBigEndian,
	/** Least significant byte first (little endian) */
	OFByteOrderLittleEndian,
	/** Native byte order of the system */







|







79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
 * @param right The right object
 * @return The order of the objects
 */
typedef OFComparisonResult (^OFComparator)(id _Nonnull left, id _Nonnull right);
#endif

/**
 * @brief An enum for representing endianness.
 */
typedef enum {
	/** Most significant byte first (big endian) */
	OFByteOrderBigEndian,
	/** Least significant byte first (little endian) */
	OFByteOrderLittleEndian,
	/** Native byte order of the system */
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
} OFRange;

/**
 * @brief Creates a new OFRange.
 *
 * @param start The starting index of the range
 * @param length The length of the range
 * @return An OFRangeith the specified start and length
 */
static OF_INLINE OFRange OF_CONST_FUNC
OFMakeRange(size_t start, size_t length)
{
	OFRange range = { start, length };

	return range;







|







111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
} OFRange;

/**
 * @brief Creates a new OFRange.
 *
 * @param start The starting index of the range
 * @param length The length of the range
 * @return An OFRange with the specified start and length
 */
static OF_INLINE OFRange OF_CONST_FUNC
OFMakeRange(size_t start, size_t length)
{
	OFRange range = { start, length };

	return range;
1373
1374
1375
1376
1377
1378
1379
1380

1381
1382
1383
1384
1385
1386
1387
@end

/**
 * @protocol OFComparing OFObject.h ObjFW/OFObject.h
 *
 * @brief A protocol for comparing objects.
 *
 * This protocol is implemented by objects that can be compared. Its only method, @ref compare:, should be overridden with a stronger type.

 */
@protocol OFComparing
/**
 * @brief Compares the object to another object.
 *
 * @param object An object to compare the object to
 * @return The result of the comparison







|
>







1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
@end

/**
 * @protocol OFComparing OFObject.h ObjFW/OFObject.h
 *
 * @brief A protocol for comparing objects.
 *
 * This protocol is implemented by objects that can be compared. Its only
 * method, @ref compare:, should be overridden with a stronger type.
 */
@protocol OFComparing
/**
 * @brief Compares the object to another object.
 *
 * @param object An object to compare the object to
 * @return The result of the comparison
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
extern void *_Nullable OFResizeMemory(void *_Nullable pointer, size_t count,
    size_t size) OF_WARN_UNUSED_RESULT;

/**
 * @brief Frees memory allocated by @ref OFAllocMemory, @ref OFAllocZeroedMemory
 *	  or @ref OFResizeMemory.
 *
 * @param pointer A pointer to the memory to free or nil (passing nil ooes
 *		  nothing)
 */
extern void OFFreeMemory(void *_Nullable pointer);

#ifdef OF_APPLE_RUNTIME
extern void *_Null_unspecified objc_autoreleasePoolPush(void);
extern void objc_autoreleasePoolPop(void *_Null_unspecified pool);







|







1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
extern void *_Nullable OFResizeMemory(void *_Nullable pointer, size_t count,
    size_t size) OF_WARN_UNUSED_RESULT;

/**
 * @brief Frees memory allocated by @ref OFAllocMemory, @ref OFAllocZeroedMemory
 *	  or @ref OFResizeMemory.
 *
 * @param pointer A pointer to the memory to free or nil (passing nil does
 *		  nothing)
 */
extern void OFFreeMemory(void *_Nullable pointer);

#ifdef OF_APPLE_RUNTIME
extern void *_Null_unspecified objc_autoreleasePoolPush(void);
extern void objc_autoreleasePoolPop(void *_Null_unspecified pool);

Modified src/OFPBKDF2.h from [6171bc59fb] to [79b5b7bbf4].

58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76

#ifdef __cplusplus
extern "C" {
#endif
/**
 * @brief Derives a key from a password and a salt using PBKDF2.
 *
 * @note This will call @ref OFHMAC::reset on the `HMAC` first, making it
 *	 possible to reuse the `HMAC`, but also meaning all previous results
 *	 from the `HMAC` get invalidated if they have not been copied.
 *
 * @param parameters The parameters to use
 */
extern void OFPBKDF2(OFPBKDF2Parameters parameters);
#ifdef __cplusplus
}
#endif

OF_ASSUME_NONNULL_END







|











58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76

#ifdef __cplusplus
extern "C" {
#endif
/**
 * @brief Derives a key from a password and a salt using PBKDF2.
 *
 * @note This will call @ref OFHMAC#reset on the `HMAC` first, making it
 *	 possible to reuse the `HMAC`, but also meaning all previous results
 *	 from the `HMAC` get invalidated if they have not been copied.
 *
 * @param parameters The parameters to use
 */
extern void OFPBKDF2(OFPBKDF2Parameters parameters);
#ifdef __cplusplus
}
#endif

OF_ASSUME_NONNULL_END

Added src/OFPTRDNSResourceRecord.h version [ecc16b91cc].





















































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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-2024 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the 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 "OFDNSResourceRecord.h"

OF_ASSUME_NONNULL_BEGIN

/**
 * @class OFPTRDNSResourceRecord \
 *	  OFDNSResourceRecord.h ObjFW/OFDNSResourceRecord.h
 *
 * @brief A class representing a PTR DNS resource record.
 */
OF_SUBCLASSING_RESTRICTED
@interface OFPTRDNSResourceRecord: OFDNSResourceRecord
{
	OFString *_domainName;
}

/**
 * @brief The domain name of the resource record.
 */
@property (readonly, nonatomic) OFString *domainName;

- (instancetype)initWithName: (OFString *)name
		    DNSClass: (OFDNSClass)DNSClass
		  recordType: (OFDNSRecordType)recordType
			 TTL: (uint32_t)TTL OF_UNAVAILABLE;

/**
 * @brief Initializes an already allocated OFPTRDNSResourceRecord with the
 *	  specified name, class, domain name and time to live.
 *
 * @param name The name for the resource record
 * @param DNSClass The class code for the resource record
 * @param domainName The domain name for the resource record
 * @param TTL The time to live for the resource record
 * @return An initialized OFPTRDNSResourceRecord
 */
- (instancetype)initWithName: (OFString *)name
		    DNSClass: (OFDNSClass)DNSClass
		  domainName: (OFString *)domainName
			 TTL: (uint32_t)TTL OF_DESIGNATED_INITIALIZER;
@end

OF_ASSUME_NONNULL_END

Added src/OFPTRDNSResourceRecord.m version [a0ec5a71b8].









































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
/*
 * Copyright (c) 2008-2024 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the 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 "OFPTRDNSResourceRecord.h"

@implementation OFPTRDNSResourceRecord
@synthesize domainName = _domainName;

- (instancetype)initWithName: (OFString *)name
		    DNSClass: (OFDNSClass)DNSClass
		  recordType: (OFDNSRecordType)recordType
			 TTL: (uint32_t)TTL
{
	OF_INVALID_INIT_METHOD
}

- (instancetype)initWithName: (OFString *)name
		    DNSClass: (OFDNSClass)DNSClass
		  domainName: (OFString *)domainName
			 TTL: (uint32_t)TTL
{
	self = [super initWithName: name
			  DNSClass: DNSClass
			recordType: OFDNSRecordTypePTR
			       TTL: TTL];

	@try {
		_domainName = [domainName copy];
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (void)dealloc
{
	[_domainName release];

	[super dealloc];
}

- (bool)isEqual: (id)object
{
	OFPTRDNSResourceRecord *record;

	if (object == self)
		return true;

	if (![object isKindOfClass: [OFPTRDNSResourceRecord class]])
		return false;

	record = object;

	if (record->_name != _name && ![record->_name isEqual: _name])
		return false;

	if (record->_DNSClass != _DNSClass)
		return false;

	if (record->_recordType != _recordType)
		return false;

	if (record->_domainName != _domainName &&
	    ![record->_domainName isEqual: _domainName])
		return false;

	return true;
}

- (unsigned long)hash
{
	unsigned long hash;

	OFHashInit(&hash);

	OFHashAddHash(&hash, _name.hash);
	OFHashAddByte(&hash, _DNSClass >> 8);
	OFHashAddByte(&hash, _DNSClass);
	OFHashAddByte(&hash, _recordType >> 8);
	OFHashAddByte(&hash, _recordType);
	OFHashAddHash(&hash, _domainName.hash);

	OFHashFinalize(&hash);

	return hash;
}

- (OFString *)description
{
	return [OFString stringWithFormat:
	    @"<%@:\n"
	    @"\tName = %@\n"
	    @"\tClass = %@\n"
	    @"\tDomain Name = %@\n"
	    @"\tTTL = %" PRIu32 "\n"
	    @">",
	    self.className, _name, OFDNSClassName(_DNSClass), _domainName,
	    _TTL];
}
@end

Modified src/OFPlugin.h from [273d4a698a] to [ee90650db0].

71
72
73
74
75
76
77
78
79
80
81
82
83
 */
- (instancetype)initWithPath: (OFString *)path;

/**
 * @brief Returns the address for the specified symbol, or `nil` if not found.
 *
 * @param symbol The symbol to return the address for
 * @return The address for the speccified symbol, or `nil` if not found
 */
- (nullable void *)addressForSymbol: (OFString *)symbol;
@end

OF_ASSUME_NONNULL_END







|





71
72
73
74
75
76
77
78
79
80
81
82
83
 */
- (instancetype)initWithPath: (OFString *)path;

/**
 * @brief Returns the address for the specified symbol, or `nil` if not found.
 *
 * @param symbol The symbol to return the address for
 * @return The address for the specified symbol, or `nil` if not found
 */
- (nullable void *)addressForSymbol: (OFString *)symbol;
@end

OF_ASSUME_NONNULL_END

Added src/OFRPDNSResourceRecord.h version [5c42444d41].







































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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-2024 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the 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 "OFDNSResourceRecord.h"

OF_ASSUME_NONNULL_BEGIN

/**
 * @class OFRPDNSResourceRecord \
 *	  OFDNSResourceRecord.h ObjFW/OFDNSResourceRecord.h
 *
 * @brief A class representing an RP DNS resource record.
 */
OF_SUBCLASSING_RESTRICTED
@interface OFRPDNSResourceRecord: OFDNSResourceRecord
{
	OFString *_mailbox, *_TXTDomainName;
}

/**
 * @brief The mailbox of the responsible person of the resource record.
 */
@property (readonly, nonatomic) OFString *mailbox;

/**
 * @brief A domain name that contains a TXT resource record for the responsible
 *	  person of the resource record.
 */
@property (readonly, nonatomic) OFString *TXTDomainName;

- (instancetype)initWithName: (OFString *)name
		    DNSClass: (OFDNSClass)DNSClass
		  recordType: (OFDNSRecordType)recordType
			 TTL: (uint32_t)TTL OF_UNAVAILABLE;

/**
 * @brief Initializes an already allocated OFRPDNSResourceRecord with the
 *	  specified name, class, alias and time to live.
 *
 * @param name The name for the resource record
 * @param DNSClass The class code for the resource record
 * @param mailbox The mailbox of the responsible person of the resource record
 * @param TXTDomainName A domain name that contains a TXT resource record for
 *			the responsible person of the resource record
 * @param TTL The time to live for the resource record
 * @return An initialized OFRPDNSResourceRecord
 */
- (instancetype)initWithName: (OFString *)name
		    DNSClass: (OFDNSClass)DNSClass
		     mailbox: (OFString *)mailbox
	       TXTDomainName: (OFString *)TXTDomainName
			 TTL: (uint32_t)TTL OF_DESIGNATED_INITIALIZER;
@end

OF_ASSUME_NONNULL_END

Added src/OFRPDNSResourceRecord.m version [683a6a3960].



























































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
/*
 * Copyright (c) 2008-2024 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the 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 "OFRPDNSResourceRecord.h"

@implementation OFRPDNSResourceRecord
@synthesize mailbox = _mailbox, TXTDomainName = _TXTDomainName;

- (instancetype)initWithName: (OFString *)name
		    DNSClass: (OFDNSClass)DNSClass
		  recordType: (OFDNSRecordType)recordType
			 TTL: (uint32_t)TTL
{
	OF_INVALID_INIT_METHOD
}

- (instancetype)initWithName: (OFString *)name
		    DNSClass: (OFDNSClass)DNSClass
		     mailbox: (OFString *)mailbox
	       TXTDomainName: (OFString *)TXTDomainName
			 TTL: (uint32_t)TTL
{
	self = [super initWithName: name
			  DNSClass: DNSClass
			recordType: OFDNSRecordTypeRP
			       TTL: TTL];

	@try {
		_mailbox = [mailbox copy];
		_TXTDomainName = [TXTDomainName copy];
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (void)dealloc
{
	[_mailbox release];
	[_TXTDomainName release];

	[super dealloc];
}

- (bool)isEqual: (id)object
{
	OFRPDNSResourceRecord *record;

	if (object == self)
		return true;

	if (![object isKindOfClass: [OFRPDNSResourceRecord class]])
		return false;

	record = object;

	if (record->_name != _name && ![record->_name isEqual: _name])
		return false;

	if (record->_DNSClass != _DNSClass)
		return false;

	if (record->_recordType != _recordType)
		return false;

	if (record->_mailbox != _mailbox &&
	    ![record->_mailbox isEqual: _mailbox])
		return false;

	if (record->_TXTDomainName != _TXTDomainName &&
	    ![record->_TXTDomainName isEqual: _TXTDomainName])
		return false;

	return true;
}

- (unsigned long)hash
{
	unsigned long hash;

	OFHashInit(&hash);

	OFHashAddHash(&hash, _name.hash);
	OFHashAddByte(&hash, _DNSClass >> 8);
	OFHashAddByte(&hash, _DNSClass);
	OFHashAddByte(&hash, _recordType >> 8);
	OFHashAddByte(&hash, _recordType);
	OFHashAddHash(&hash, _mailbox.hash);
	OFHashAddHash(&hash, _TXTDomainName.hash);

	OFHashFinalize(&hash);

	return hash;
}

- (OFString *)description
{
	return [OFString stringWithFormat:
	    @"<%@:\n"
	    @"\tName = %@\n"
	    @"\tClass = %@\n"
	    @"\tMailbox = %@\n"
	    @"\tTXT Domain Name = %@\n"
	    @"\tTTL = %" PRIu32 "\n"
	    @">",
	    self.className, _name, OFDNSClassName(_DNSClass), _mailbox,
	    _TXTDomainName, _TTL];
}
@end

Added src/OFSOADNSResourceRecord.h version [f6d39682e7].













































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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-2024 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the 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 "OFDNSResourceRecord.h"

OF_ASSUME_NONNULL_BEGIN

/**
 * @class OFSOADNSResourceRecord \
 *	  OFDNSResourceRecord.h ObjFW/OFDNSResourceRecord.h
 *
 * @brief A class representing an SOA DNS resource record.
 */
OF_SUBCLASSING_RESTRICTED
@interface OFSOADNSResourceRecord: OFDNSResourceRecord
{
	OFString *_primaryNameServer, *_responsiblePerson;
	uint32_t _serialNumber, _refreshInterval, _retryInterval;
	uint32_t _expirationInterval, _minTTL;
}

/**
 * @brief The the primary name server for the zone.
 */
@property (readonly, nonatomic) OFString *primaryNameServer;

/**
 * @brief The mailbox of the person responsible for the zone.
 */
@property (readonly, nonatomic) OFString *responsiblePerson;

/**
 * @brief The serial number of the original copy of the zone.
 */
@property (readonly, nonatomic) uint32_t serialNumber;

/**
 * @brief The refresh interval of the zone.
 */
@property (readonly, nonatomic) uint32_t refreshInterval;

/**
 * @brief The retry interval of the zone.
 */
@property (readonly, nonatomic) uint32_t retryInterval;

/**
 * @brief The expiration interval of the zone.
 */
@property (readonly, nonatomic) uint32_t expirationInterval;

/**
 * @brief The minimum TTL of the zone.
 */
@property (readonly, nonatomic) uint32_t minTTL;

- (instancetype)initWithName: (OFString *)name
		    DNSClass: (OFDNSClass)DNSClass
		  recordType: (OFDNSRecordType)recordType
			 TTL: (uint32_t)TTL OF_UNAVAILABLE;

/**
 * @brief Initializes an already allocated OFSOADNSResourceRecord with the
 *	  specified name, class, text data and time to live.
 *
 * @param name The name for the resource record
 * @param DNSClass The class code for the resource record
 * @param primaryNameServer The the primary name server for the zone
 * @param responsiblePerson The mailbox of the person responsible for the zone
 * @param serialNumber The serial number of the original copy of the zone
 * @param refreshInterval The refresh interval of the zone
 * @param retryInterval The retry interval of the zone
 * @param expirationInterval The expiration interval of the zone
 * @param minTTL The minimum TTL of the zone
 * @param TTL The time to live for the resource record
 * @return An initialized OFSOADNSResourceRecord
 */
- (instancetype)initWithName: (OFString *)name
		    DNSClass: (OFDNSClass)DNSClass
	   primaryNameServer: (OFString *)primaryNameServer
	   responsiblePerson: (OFString *)responsiblePerson
		serialNumber: (uint32_t)serialNumber
	     refreshInterval: (uint32_t)refreshInterval
	       retryInterval: (uint32_t)retryInterval
	  expirationInterval: (uint32_t)expirationInterval
		      minTTL: (uint32_t)minTTL
			 TTL: (uint32_t)TTL OF_DESIGNATED_INITIALIZER;
@end

OF_ASSUME_NONNULL_END

Added src/OFSOADNSResourceRecord.m version [a365590ab7].











































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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-2024 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the 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 "OFSOADNSResourceRecord.h"

@implementation OFSOADNSResourceRecord
@synthesize primaryNameServer = _primaryNameServer;
@synthesize responsiblePerson = _responsiblePerson;
@synthesize serialNumber = _serialNumber, refreshInterval = _refreshInterval;
@synthesize retryInterval = _retryInterval;
@synthesize expirationInterval = _expirationInterval, minTTL = _minTTL;

- (instancetype)initWithName: (OFString *)name
		    DNSClass: (OFDNSClass)DNSClass
		  recordType: (OFDNSRecordType)recordType
			 TTL: (uint32_t)TTL
{
	OF_INVALID_INIT_METHOD
}

- (instancetype)initWithName: (OFString *)name
		    DNSClass: (OFDNSClass)DNSClass
	   primaryNameServer: (OFString *)primaryNameServer
	   responsiblePerson: (OFString *)responsiblePerson
		serialNumber: (uint32_t)serialNumber
	     refreshInterval: (uint32_t)refreshInterval
	       retryInterval: (uint32_t)retryInterval
	  expirationInterval: (uint32_t)expirationInterval
		      minTTL: (uint32_t)minTTL
			 TTL: (uint32_t)TTL
{
	self = [super initWithName: name
			  DNSClass: DNSClass
			recordType: OFDNSRecordTypeSOA
			       TTL: TTL];

	@try {
		_primaryNameServer = [primaryNameServer copy];
		_responsiblePerson = [responsiblePerson copy];
		_serialNumber = serialNumber;
		_refreshInterval = refreshInterval;
		_retryInterval = retryInterval;
		_expirationInterval = expirationInterval;
		_minTTL = minTTL;
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (void)dealloc
{
	[_primaryNameServer release];
	[_responsiblePerson release];

	[super dealloc];
}

- (bool)isEqual: (id)object
{
	OFSOADNSResourceRecord *record;

	if (object == self)
		return true;

	if (![object isKindOfClass: [OFSOADNSResourceRecord class]])
		return false;

	record = object;

	if (record->_name != _name && ![record->_name isEqual: _name])
		return false;

	if (record->_DNSClass != _DNSClass)
		return false;

	if (record->_recordType != _recordType)
		return false;

	if (record->_primaryNameServer != _primaryNameServer &&
	    ![record->_primaryNameServer isEqual: _primaryNameServer])
		return false;

	if (record->_responsiblePerson != _responsiblePerson &&
	    ![record->_responsiblePerson isEqual: _responsiblePerson])
		return false;

	if (record->_serialNumber != _serialNumber)
		return false;

	if (record->_refreshInterval != _refreshInterval)
		return false;

	if (record->_retryInterval != _retryInterval)
		return false;

	if (record->_expirationInterval != _expirationInterval)
		return false;

	if (record->_minTTL != _minTTL)
		return false;

	return true;
}

- (unsigned long)hash
{
	unsigned long hash;

	OFHashInit(&hash);

	OFHashAddHash(&hash, _name.hash);
	OFHashAddByte(&hash, _DNSClass >> 8);
	OFHashAddByte(&hash, _DNSClass);
	OFHashAddByte(&hash, _recordType >> 8);
	OFHashAddByte(&hash, _recordType);
	OFHashAddHash(&hash, _primaryNameServer.hash);
	OFHashAddHash(&hash, _responsiblePerson.hash);
	OFHashAddByte(&hash, _serialNumber >> 24);
	OFHashAddByte(&hash, _serialNumber >> 16);
	OFHashAddByte(&hash, _serialNumber >> 8);
	OFHashAddByte(&hash, _serialNumber);
	OFHashAddByte(&hash, _refreshInterval >> 24);
	OFHashAddByte(&hash, _refreshInterval >> 16);
	OFHashAddByte(&hash, _refreshInterval >> 8);
	OFHashAddByte(&hash, _refreshInterval);
	OFHashAddByte(&hash, _retryInterval >> 24);
	OFHashAddByte(&hash, _retryInterval >> 16);
	OFHashAddByte(&hash, _retryInterval >> 8);
	OFHashAddByte(&hash, _retryInterval);
	OFHashAddByte(&hash, _expirationInterval >> 24);
	OFHashAddByte(&hash, _expirationInterval >> 16);
	OFHashAddByte(&hash, _expirationInterval >> 8);
	OFHashAddByte(&hash, _expirationInterval);
	OFHashAddByte(&hash, _minTTL >> 24);
	OFHashAddByte(&hash, _minTTL >> 16);
	OFHashAddByte(&hash, _minTTL >> 8);
	OFHashAddByte(&hash, _minTTL);

	OFHashFinalize(&hash);

	return hash;
}

- (OFString *)description
{
	return [OFString stringWithFormat:
	    @"<%@:\n"
	    @"\tName = %@\n"
	    @"\tClass = %@\n"
	    @"\tPrimary Name Server = %@\n"
	    @"\tResponsible Person = %@\n"
	    @"\tSerial Number = %" PRIu32 "\n"
	    @"\tRefresh Interval = %" PRIu32 "\n"
	    @"\tRetry Interval = %" PRIu32 "\n"
	    @"\tExpiration Interval = %" PRIu32 "\n"
	    @"\tMinimum TTL = %" PRIu32 "\n"
	    @"\tTTL = %" PRIu32 "\n"
	    @">",
	    self.className, _name, OFDNSClassName(_DNSClass),
	    _primaryNameServer, _responsiblePerson, _serialNumber,
	    _refreshInterval, _retryInterval, _expirationInterval, _minTTL,
	    _TTL];
}
@end

Modified src/OFSPXSocket.h from [8cb486db9e] to [64d9d0b6b0].

111
112
113
114
115
116
117
118

119
120
121
122
123
124
125
/**
 * @brief Asynchronously 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
 * @param runLoopMode The run loop mode in which to perform the async connect

 */
- (void)asyncConnectToNetwork: (uint32_t)network
			 node: (const unsigned char [_Nonnull IPX_NODE_LEN])node
			 port: (uint16_t)port
		  runLoopMode: (OFRunLoopMode)runLoopMode;

#ifdef OF_HAVE_BLOCKS







|
>







111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
/**
 * @brief Asynchronously 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
 * @param runLoopMode The run loop mode in which to perform the asynchronous
 *		      connect
 */
- (void)asyncConnectToNetwork: (uint32_t)network
			 node: (const unsigned char [_Nonnull IPX_NODE_LEN])node
			 port: (uint16_t)port
		  runLoopMode: (OFRunLoopMode)runLoopMode;

#ifdef OF_HAVE_BLOCKS
140
141
142
143
144
145
146
147

148
149
150
151
152
153
154
/**
 * @brief Asynchronously connect the OFSPXSocket to the specified destination.
 *
 * @param node The node to connect to
 * @param network The network on which the node to connect to is
 * @param port The port (sometimes also called socket number) on the node to
 *	       connect to
 * @param runLoopMode The run loop mode in which to perform the async connect

 * @param block The block to execute once the connection has been established
 */
- (void)asyncConnectToNetwork: (uint32_t)network
			 node: (const unsigned char [_Nonnull IPX_NODE_LEN])node
			 port: (uint16_t)port
		  runLoopMode: (OFRunLoopMode)runLoopMode
			block: (OFSPXSocketAsyncConnectBlock)block;







|
>







141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
/**
 * @brief Asynchronously connect the OFSPXSocket to the specified destination.
 *
 * @param node The node to connect to
 * @param network The network on which the node to connect to is
 * @param port The port (sometimes also called socket number) on the node to
 *	       connect to
 * @param runLoopMode The run loop mode in which to perform the asynchronous
 *		      connect
 * @param block The block to execute once the connection has been established
 */
- (void)asyncConnectToNetwork: (uint32_t)network
			 node: (const unsigned char [_Nonnull IPX_NODE_LEN])node
			 port: (uint16_t)port
		  runLoopMode: (OFRunLoopMode)runLoopMode
			block: (OFSPXSocketAsyncConnectBlock)block;

Modified src/OFSPXStreamSocket.h from [3937a43366] to [d292af026a].

114
115
116
117
118
119
120
121

122
123
124
125
126
127
128
 * @brief Asynchronously 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
 * @param runLoopMode The run loop mode in which to perform the async connect

 */
- (void)asyncConnectToNetwork: (uint32_t)network
			 node: (const unsigned char [_Nonnull IPX_NODE_LEN])node
			 port: (uint16_t)port
		  runLoopMode: (OFRunLoopMode)runLoopMode;

#ifdef OF_HAVE_BLOCKS







|
>







114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
 * @brief Asynchronously 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
 * @param runLoopMode The run loop mode in which to perform the asynchronous
 *		      connect
 */
- (void)asyncConnectToNetwork: (uint32_t)network
			 node: (const unsigned char [_Nonnull IPX_NODE_LEN])node
			 port: (uint16_t)port
		  runLoopMode: (OFRunLoopMode)runLoopMode;

#ifdef OF_HAVE_BLOCKS
145
146
147
148
149
150
151
152

153
154
155
156
157
158
159
 * @brief Asynchronously 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
 * @param runLoopMode The run loop mode in which to perform the async connect

 * @param block The block to execute once the connection has been established
 */
- (void)asyncConnectToNetwork: (uint32_t)network
			 node: (const unsigned char [_Nonnull IPX_NODE_LEN])node
			 port: (uint16_t)port
		  runLoopMode: (OFRunLoopMode)runLoopMode
			block: (OFSPXStreamSocketAsyncConnectBlock)block;







|
>







146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
 * @brief Asynchronously 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
 * @param runLoopMode The run loop mode in which to perform the asynchronous
 *		      connect
 * @param block The block to execute once the connection has been established
 */
- (void)asyncConnectToNetwork: (uint32_t)network
			 node: (const unsigned char [_Nonnull IPX_NODE_LEN])node
			 port: (uint16_t)port
		  runLoopMode: (OFRunLoopMode)runLoopMode
			block: (OFSPXStreamSocketAsyncConnectBlock)block;

Added src/OFSRVDNSResourceRecord.h version [d5575ff367].































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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-2024 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the 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 "OFDNSResourceRecord.h"

OF_ASSUME_NONNULL_BEGIN

/**
 * @class OFSRVDNSResourceRecord \
 *	  OFDNSResourceRecord.h ObjFW/OFDNSResourceRecord.h
 *
 * @brief A class representing an SRV DNS resource record.
 */
OF_SUBCLASSING_RESTRICTED
@interface OFSRVDNSResourceRecord: OFDNSResourceRecord
{
	uint16_t _priority, _weight;
	OFString *_target;
	uint16_t _port;
}

/**
 * @brief The priority of the resource record.
 */
@property (readonly, nonatomic) uint16_t priority;

/**
 * @brief The weight of the resource record.
 */
@property (readonly, nonatomic) uint16_t weight;

/**
 * @brief The target of the resource record.
 */
@property (readonly, nonatomic) OFString *target;

/**
 * @brief The port on the target of the resource record.
 */
@property (readonly, nonatomic) uint16_t port;

- (instancetype)initWithName: (OFString *)name
		    DNSClass: (OFDNSClass)DNSClass
		  recordType: (OFDNSRecordType)recordType
			 TTL: (uint32_t)TTL OF_UNAVAILABLE;

/**
 * @brief Initializes an already allocated OFSRVDNSResourceRecord with the
 *	  specified name, priority, weight, target, port and time to live.
 *
 * @param name The name for the resource record
 * @param priority The priority for the resource record
 * @param weight The weight for the resource record
 * @param target The target for the resource record
 * @param port The port on the target for the resource record
 * @param TTL The time to live for the resource record
 * @return An initialized OFSRVDNSResourceRecord
 */
- (instancetype)initWithName: (OFString *)name
		    priority: (uint16_t)priority
		      weight: (uint16_t)weight
		      target: (OFString *)target
			port: (uint16_t)port
			 TTL: (uint32_t)TTL OF_DESIGNATED_INITIALIZER;
@end

OF_ASSUME_NONNULL_END

Added src/OFSRVDNSResourceRecord.m version [5493cd3b6c].



















































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
/*
 * Copyright (c) 2008-2024 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the 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 "OFSRVDNSResourceRecord.h"

@implementation OFSRVDNSResourceRecord
@synthesize priority = _priority, weight = _weight, target = _target;
@synthesize port = _port;

- (instancetype)initWithName: (OFString *)name
		    DNSClass: (OFDNSClass)DNSClass
		  recordType: (OFDNSRecordType)recordType
			 TTL: (uint32_t)TTL
{
	OF_INVALID_INIT_METHOD
}

- (instancetype)initWithName: (OFString *)name
		    priority: (uint16_t)priority
		      weight: (uint16_t)weight
		      target: (OFString *)target
			port: (uint16_t)port
			 TTL: (uint32_t)TTL
{
	self = [super initWithName: name
			  DNSClass: OFDNSClassIN
			recordType: OFDNSRecordTypeSRV
			       TTL: TTL];

	@try {
		_priority = priority;
		_weight = weight;
		_target = [target copy];
		_port = port;
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (void)dealloc
{
	[_target release];

	[super dealloc];
}

- (bool)isEqual: (id)object
{
	OFSRVDNSResourceRecord *record;

	if (object == self)
		return true;

	if (![object isKindOfClass: [OFSRVDNSResourceRecord class]])
		return false;

	record = object;

	if (record->_name != _name && ![record->_name isEqual: _name])
		return false;

	if (record->_DNSClass != _DNSClass)
		return false;

	if (record->_recordType != _recordType)
		return false;

	if (record->_priority != _priority)
		return false;

	if (record->_weight != _weight)
		return false;

	if (record->_target != _target && ![record->_target isEqual: _target])
		return false;

	if (record->_port != _port)
		return false;

	return true;
}

- (unsigned long)hash
{
	unsigned long hash;

	OFHashInit(&hash);

	OFHashAddHash(&hash, _name.hash);
	OFHashAddByte(&hash, _DNSClass >> 8);
	OFHashAddByte(&hash, _DNSClass);
	OFHashAddByte(&hash, _recordType >> 8);
	OFHashAddByte(&hash, _recordType);
	OFHashAddByte(&hash, _priority >> 8);
	OFHashAddByte(&hash, _priority);
	OFHashAddByte(&hash, _weight >> 8);
	OFHashAddByte(&hash, _weight);
	OFHashAddHash(&hash, _target.hash);
	OFHashAddByte(&hash, _port >> 8);
	OFHashAddByte(&hash, _port);

	OFHashFinalize(&hash);

	return hash;
}

- (OFString *)description
{
	return [OFString stringWithFormat:
	    @"<%@:\n"
	    @"\tName = %@\n"
	    @"\tPriority = %" PRIu16 "\n"
	    @"\tWeight = %" PRIu16 "\n"
	    @"\tTarget = %@\n"
	    @"\tPort = %" PRIu16 "\n"
	    @"\tTTL = %" PRIu32 "\n"
	    @">",
	    self.className, _name, _priority, _weight, _target, _port, _TTL];
}
@end

Modified src/OFSequencedPacketSocket.h from [6a02d92297] to [aa11a4ef26].

205
206
207
208
209
210
211
212

213
214
215
216
217
218
219
 * @brief Asynchronously receives a packet and stores it into the specified
 *	  buffer.
 *
 * If the buffer is too small, the receive operation fails.
 *
 * @param buffer The buffer to write the packet to
 * @param length The length of the buffer
 * @param runLoopMode The run loop mode in which to perform the async receive

 */
- (void)asyncReceiveIntoBuffer: (void *)buffer
			length: (size_t)length
		   runLoopMode: (OFRunLoopMode)runLoopMode;

#ifdef OF_HAVE_BLOCKS
/**







|
>







205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
 * @brief Asynchronously receives a packet and stores it into the specified
 *	  buffer.
 *
 * If the buffer is too small, the receive operation fails.
 *
 * @param buffer The buffer to write the packet to
 * @param length The length of the buffer
 * @param runLoopMode The run loop mode in which to perform the asynchronous
 *		      receive
 */
- (void)asyncReceiveIntoBuffer: (void *)buffer
			length: (size_t)length
		   runLoopMode: (OFRunLoopMode)runLoopMode;

#ifdef OF_HAVE_BLOCKS
/**
238
239
240
241
242
243
244
245

246
247
248
249
250
251
252
 * @brief Asynchronously receives a packet and stores it into the specified
 *	  buffer.
 *
 * If the buffer is too small, the receive operation fails.
 *
 * @param buffer The buffer to write the packet to
 * @param length The length of the buffer
 * @param runLoopMode The run loop mode in which to perform the async receive

 * @param block The block to call when the packet has been received. If the
 *		block returns true, it will be called again with the same
 *		buffer and maximum length when more packets have been received.
 *		If you want the next method in the queue to handle the packet
 *		received next, you need to return false from the method.
 */
- (void)asyncReceiveIntoBuffer: (void *)buffer







|
>







239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
 * @brief Asynchronously receives a packet and stores it into the specified
 *	  buffer.
 *
 * If the buffer is too small, the receive operation fails.
 *
 * @param buffer The buffer to write the packet to
 * @param length The length of the buffer
 * @param runLoopMode The run loop mode in which to perform the asynchronous
 *		      receive
 * @param block The block to call when the packet has been received. If the
 *		block returns true, it will be called again with the same
 *		buffer and maximum length when more packets have been received.
 *		If you want the next method in the queue to handle the packet
 *		received next, you need to return false from the method.
 */
- (void)asyncReceiveIntoBuffer: (void *)buffer
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
 */
- (void)asyncSendData: (OFData *)data;

/**
 * @brief Asynchronously sends the specified packet.
 *
 * @param data The data to send as a packet
 * @param runLoopMode The run loop mode in which to perform the async send

 */
- (void)asyncSendData: (OFData *)data runLoopMode: (OFRunLoopMode)runLoopMode;

#ifdef OF_HAVE_BLOCKS
/**
 * @brief Asynchronously sends the specified packet.
 *
 * @param data The data to send as a packet
 * @param block The block to call when the packet has been sent. It should
 *		return the data for the next send with the same callback or nil
 *		if it should not repeat.
 */
- (void)asyncSendData: (OFData *)data
		block: (OFSequencedPacketSocketAsyncSendDataBlock)block;

/**
 * @brief Asynchronously sends the specified packet.
 *
 * @param data The data to send as a packet
 * @param runLoopMode The run loop mode in which to perform the async send

 * @param block The block to call when the packet has been sent. It should
 *		return the data for the next send with the same callback or nil
 *		if it should not repeat.
 */
- (void)asyncSendData: (OFData *)data
	  runLoopMode: (OFRunLoopMode)runLoopMode
		block: (OFSequencedPacketSocketAsyncSendDataBlock)block;







|
>



















|
>







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
 */
- (void)asyncSendData: (OFData *)data;

/**
 * @brief Asynchronously sends the specified packet.
 *
 * @param data The data to send as a packet
 * @param runLoopMode The run loop mode in which to perform the asynchronous
 *		      send
 */
- (void)asyncSendData: (OFData *)data runLoopMode: (OFRunLoopMode)runLoopMode;

#ifdef OF_HAVE_BLOCKS
/**
 * @brief Asynchronously sends the specified packet.
 *
 * @param data The data to send as a packet
 * @param block The block to call when the packet has been sent. It should
 *		return the data for the next send with the same callback or nil
 *		if it should not repeat.
 */
- (void)asyncSendData: (OFData *)data
		block: (OFSequencedPacketSocketAsyncSendDataBlock)block;

/**
 * @brief Asynchronously sends the specified packet.
 *
 * @param data The data to send as a packet
 * @param runLoopMode The run loop mode in which to perform the asynchronous
 *		      send
 * @param block The block to call when the packet has been sent. It should
 *		return the data for the next send with the same callback or nil
 *		if it should not repeat.
 */
- (void)asyncSendData: (OFData *)data
	  runLoopMode: (OFRunLoopMode)runLoopMode
		block: (OFSequencedPacketSocketAsyncSendDataBlock)block;
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
 * @brief Asynchronously accept an incoming connection.
 */
- (void)asyncAccept;

/**
 * @brief Asynchronously accept an incoming connection.
 *
 * @param runLoopMode The run loop mode in which to perform the async accept

 */
- (void)asyncAcceptWithRunLoopMode: (OFRunLoopMode)runLoopMode;

#ifdef OF_HAVE_BLOCKS
/**
 * @brief Asynchronously accept an incoming connection.
 *
 * @param block The block to execute when a new connection has been accepted.
 *		Returns whether the next incoming connection should be accepted
 *		by the specified block as well.
 */
- (void)asyncAcceptWithBlock: (OFSequencedPacketSocketAsyncAcceptBlock)block;

/**
 * @brief Asynchronously accept an incoming connection.
 *
 * @param runLoopMode The run loop mode in which to perform the async accept

 * @param block The block to execute when a new connection has been accepted.
 *		Returns whether the next incoming connection should be accepted
 *		by the specified block as well.
 */
- (void)
    asyncAcceptWithRunLoopMode: (OFRunLoopMode)runLoopMode
			 block: (OFSequencedPacketSocketAsyncAcceptBlock)block;







|
>
















|
>







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
 * @brief Asynchronously accept an incoming connection.
 */
- (void)asyncAccept;

/**
 * @brief Asynchronously accept an incoming connection.
 *
 * @param runLoopMode The run loop mode in which to perform the asynchronous
 *		      accept
 */
- (void)asyncAcceptWithRunLoopMode: (OFRunLoopMode)runLoopMode;

#ifdef OF_HAVE_BLOCKS
/**
 * @brief Asynchronously accept an incoming connection.
 *
 * @param block The block to execute when a new connection has been accepted.
 *		Returns whether the next incoming connection should be accepted
 *		by the specified block as well.
 */
- (void)asyncAcceptWithBlock: (OFSequencedPacketSocketAsyncAcceptBlock)block;

/**
 * @brief Asynchronously accept an incoming connection.
 *
 * @param runLoopMode The run loop mode in which to perform the asynchronous
 *		      accept
 * @param block The block to execute when a new connection has been accepted.
 *		Returns whether the next incoming connection should be accepted
 *		by the specified block as well.
 */
- (void)
    asyncAcceptWithRunLoopMode: (OFRunLoopMode)runLoopMode
			 block: (OFSequencedPacketSocketAsyncAcceptBlock)block;

Modified src/OFSettings.h from [cea23e990e] to [cc35f3b784].

21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
@class OFArray OF_GENERIC(ObjectType);

/**
 * @class OFSettings OFSettings.h ObjFW/OFSettings.h
 *
 * Paths are delimited by dots, for example `category.subcategory.key`.
 *
 * @note The behaviour when accessing a path with a different type than it has
 *	 been accessed with before is undefined! If you want to change the type
 *	 for a path, remove it and then set it with the new type.
 *
 * @brief A class for storing and retrieving settings
 */
@interface OFSettings: OFObject
{







|







21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
@class OFArray OF_GENERIC(ObjectType);

/**
 * @class OFSettings OFSettings.h ObjFW/OFSettings.h
 *
 * Paths are delimited by dots, for example `category.subcategory.key`.
 *
 * @note The behavior when accessing a path with a different type than it has
 *	 been accessed with before is undefined! If you want to change the type
 *	 for a path, remove it and then set it with the new type.
 *
 * @brief A class for storing and retrieving settings
 */
@interface OFSettings: OFObject
{

Modified src/OFStdIOStream.m from [b97df9550f] to [4bd5de9454].

135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
		return 34;
	if ([color isEqual: [OFColor purple]])
		return 35;
	if ([color isEqual: [OFColor teal]])
		return 36;
	if ([color isEqual: [OFColor silver]])
		return 37;
	if ([color isEqual: [OFColor grey]])
		return 90;
	if ([color isEqual: [OFColor red]])
		return 91;
	if ([color isEqual: [OFColor lime]])
		return 92;
	if ([color isEqual: [OFColor yellow]])
		return 93;







|







135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
		return 34;
	if ([color isEqual: [OFColor purple]])
		return 35;
	if ([color isEqual: [OFColor teal]])
		return 36;
	if ([color isEqual: [OFColor silver]])
		return 37;
	if ([color isEqual: [OFColor gray]])
		return 90;
	if ([color isEqual: [OFColor red]])
		return 91;
	if ([color isEqual: [OFColor lime]])
		return 92;
	if ([color isEqual: [OFColor yellow]])
		return 93;

Modified src/OFStream.h from [80480e6665] to [2e6542e905].

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

/**
 * @brief Reads a uint16_t from the stream which is encoded in big endian.
 *
 * @warning Only call this when you know that enough data is available!
 *	    Otherwise you will get an exception!
 *
 * @return A uint16_t from the stream in native endianess
 * @throw OFReadFailedException Reading failed
 * @throw OFTruncatedDataException The end of the stream was reached before
 *				   reading enough bytes
 * @throw OFNotOpenException The stream is not open
 */
- (uint16_t)readBigEndianInt16;

/**
 * @brief Reads a uint32_t from the stream which is encoded in big endian.
 *
 * @warning Only call this when you know that enough data is available!
 *	    Otherwise you will get an exception!
 *
 * @return A uint32_t from the stream in the native endianess
 * @throw OFReadFailedException Reading failed
 * @throw OFTruncatedDataException The end of the stream was reached before
 *				   reading enough bytes
 * @throw OFNotOpenException The stream is not open
 */
- (uint32_t)readBigEndianInt32;

/**
 * @brief Reads a uint64_t from the stream which is encoded in big endian.
 *
 * @warning Only call this when you know that enough data is available!
 *	    Otherwise you will get an exception!
 *
 * @return A uint64_t from the stream in the native endianess
 * @throw OFReadFailedException Reading failed
 * @throw OFTruncatedDataException The end of the stream was reached before
 *				   reading enough bytes
 * @throw OFNotOpenException The stream is not open
 */
- (uint64_t)readBigEndianInt64;

/**
 * @brief Reads a float from the stream which is encoded in big endian.
 *
 * @warning Only call this when you know that enough data is available!
 *	    Otherwise you will get an exception!
 *
 * @return A float from the stream in the native endianess
 * @throw OFReadFailedException Reading failed
 * @throw OFTruncatedDataException The end of the stream was reached before
 *				   reading enough bytes
 * @throw OFNotOpenException The stream is not open
 */
- (float)readBigEndianFloat;

/**
 * @brief Reads a double from the stream which is encoded in big endian.
 *
 * @warning Only call this when you know that enough data is available!
 *	    Otherwise you will get an exception!
 *
 * @return A double from the stream in the native endianess
 * @throw OFReadFailedException Reading failed
 * @throw OFTruncatedDataException The end of the stream was reached before
 *				   reading enough bytes
 * @throw OFNotOpenException The stream is not open
 */
- (double)readBigEndianDouble;

/**
 * @brief Reads a uint16_t from the stream which is encoded in little endian.
 *
 * @warning Only call this when you know that enough data is available!
 *	    Otherwise you will get an exception!
 *
 * @return A uint16_t from the stream in native endianess
 * @throw OFReadFailedException Reading failed
 * @throw OFTruncatedDataException The end of the stream was reached before
 *				   reading enough bytes
 * @throw OFNotOpenException The stream is not open
 */
- (uint16_t)readLittleEndianInt16;

/**
 * @brief Reads a uint32_t from the stream which is encoded in little endian.
 *
 * @warning Only call this when you know that enough data is available!
 *	    Otherwise you will get an exception!
 *
 * @return A uint32_t from the stream in the native endianess
 * @throw OFReadFailedException Reading failed
 * @throw OFTruncatedDataException The end of the stream was reached before
 *				   reading enough bytes
 * @throw OFNotOpenException The stream is not open
 */
- (uint32_t)readLittleEndianInt32;

/**
 * @brief Reads a uint64_t from the stream which is encoded in little endian.
 *
 * @warning Only call this when you know that enough data is available!
 *	    Otherwise you will get an exception!
 *
 * @return A uint64_t from the stream in the native endianess
 * @throw OFReadFailedException Reading failed
 * @throw OFTruncatedDataException The end of the stream was reached before
 *				   reading enough bytes
 * @throw OFNotOpenException The stream is not open
 */
- (uint64_t)readLittleEndianInt64;

/**
 * @brief Reads a float from the stream which is encoded in little endian.
 *
 * @warning Only call this when you know that enough data is available!
 *	    Otherwise you will get an exception!
 *
 * @return A float from the stream in the native endianess
 * @throw OFReadFailedException Reading failed
 * @throw OFTruncatedDataException The end of the stream was reached before
 *				   reading enough bytes
 * @throw OFNotOpenException The stream is not open
 */
- (float)readLittleEndianFloat;

/**
 * @brief Reads a double from the stream which is encoded in little endian.
 *
 * @warning Only call this when you know that enough data is available!
 *	    Otherwise you will get an exception!
 *
 * @return A double from the stream in the native endianess
 * @throw OFReadFailedException Reading failed
 * @throw OFTruncatedDataException The end of the stream was reached before
 *				   reading enough bytes
 * @throw OFNotOpenException The stream is not open
 */
- (double)readLittleEndianDouble;








|













|













|













|













|













|













|













|













|













|







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

/**
 * @brief Reads a uint16_t from the stream which is encoded in big endian.
 *
 * @warning Only call this when you know that enough data is available!
 *	    Otherwise you will get an exception!
 *
 * @return A uint16_t from the stream in big endian
 * @throw OFReadFailedException Reading failed
 * @throw OFTruncatedDataException The end of the stream was reached before
 *				   reading enough bytes
 * @throw OFNotOpenException The stream is not open
 */
- (uint16_t)readBigEndianInt16;

/**
 * @brief Reads a uint32_t from the stream which is encoded in big endian.
 *
 * @warning Only call this when you know that enough data is available!
 *	    Otherwise you will get an exception!
 *
 * @return A uint32_t from the stream in big endian
 * @throw OFReadFailedException Reading failed
 * @throw OFTruncatedDataException The end of the stream was reached before
 *				   reading enough bytes
 * @throw OFNotOpenException The stream is not open
 */
- (uint32_t)readBigEndianInt32;

/**
 * @brief Reads a uint64_t from the stream which is encoded in big endian.
 *
 * @warning Only call this when you know that enough data is available!
 *	    Otherwise you will get an exception!
 *
 * @return A uint64_t from the stream in big endian
 * @throw OFReadFailedException Reading failed
 * @throw OFTruncatedDataException The end of the stream was reached before
 *				   reading enough bytes
 * @throw OFNotOpenException The stream is not open
 */
- (uint64_t)readBigEndianInt64;

/**
 * @brief Reads a float from the stream which is encoded in big endian.
 *
 * @warning Only call this when you know that enough data is available!
 *	    Otherwise you will get an exception!
 *
 * @return A float from the stream in big endian
 * @throw OFReadFailedException Reading failed
 * @throw OFTruncatedDataException The end of the stream was reached before
 *				   reading enough bytes
 * @throw OFNotOpenException The stream is not open
 */
- (float)readBigEndianFloat;

/**
 * @brief Reads a double from the stream which is encoded in big endian.
 *
 * @warning Only call this when you know that enough data is available!
 *	    Otherwise you will get an exception!
 *
 * @return A double from the stream in big endian
 * @throw OFReadFailedException Reading failed
 * @throw OFTruncatedDataException The end of the stream was reached before
 *				   reading enough bytes
 * @throw OFNotOpenException The stream is not open
 */
- (double)readBigEndianDouble;

/**
 * @brief Reads a uint16_t from the stream which is encoded in little endian.
 *
 * @warning Only call this when you know that enough data is available!
 *	    Otherwise you will get an exception!
 *
 * @return A uint16_t from the stream in little endian
 * @throw OFReadFailedException Reading failed
 * @throw OFTruncatedDataException The end of the stream was reached before
 *				   reading enough bytes
 * @throw OFNotOpenException The stream is not open
 */
- (uint16_t)readLittleEndianInt16;

/**
 * @brief Reads a uint32_t from the stream which is encoded in little endian.
 *
 * @warning Only call this when you know that enough data is available!
 *	    Otherwise you will get an exception!
 *
 * @return A uint32_t from the stream in little endian
 * @throw OFReadFailedException Reading failed
 * @throw OFTruncatedDataException The end of the stream was reached before
 *				   reading enough bytes
 * @throw OFNotOpenException The stream is not open
 */
- (uint32_t)readLittleEndianInt32;

/**
 * @brief Reads a uint64_t from the stream which is encoded in little endian.
 *
 * @warning Only call this when you know that enough data is available!
 *	    Otherwise you will get an exception!
 *
 * @return A uint64_t from the stream in little endian
 * @throw OFReadFailedException Reading failed
 * @throw OFTruncatedDataException The end of the stream was reached before
 *				   reading enough bytes
 * @throw OFNotOpenException The stream is not open
 */
- (uint64_t)readLittleEndianInt64;

/**
 * @brief Reads a float from the stream which is encoded in little endian.
 *
 * @warning Only call this when you know that enough data is available!
 *	    Otherwise you will get an exception!
 *
 * @return A float from the stream in little endian
 * @throw OFReadFailedException Reading failed
 * @throw OFTruncatedDataException The end of the stream was reached before
 *				   reading enough bytes
 * @throw OFNotOpenException The stream is not open
 */
- (float)readLittleEndianFloat;

/**
 * @brief Reads a double from the stream which is encoded in little endian.
 *
 * @warning Only call this when you know that enough data is available!
 *	    Otherwise you will get an exception!
 *
 * @return A double from the stream in little endian
 * @throw OFReadFailedException Reading failed
 * @throw OFTruncatedDataException The end of the stream was reached before
 *				   reading enough bytes
 * @throw OFNotOpenException The stream is not open
 */
- (double)readLittleEndianDouble;

Modified src/OFString.h from [f7726f73ab] to [bf3f3e1afd].

75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
	OFStringEncodingISO8859_3,
	/** ISO 8859-15 */
	OFStringEncodingISO8859_15,
	/** Windows-1251 */
	OFStringEncodingWindows1251,
	/** Windows-1252 */
	OFStringEncodingWindows1252,
	/** Codepage 437 */
	OFStringEncodingCodepage437,
	/** Codepage 850 */
	OFStringEncodingCodepage850,
	/** Codepage 858 */
	OFStringEncodingCodepage858,
	/** Mac OS Roman */
	OFStringEncodingMacRoman,
	/** KOI8-R */
	OFStringEncodingKOI8R,
	/** KOI8-U */
	OFStringEncodingKOI8U,







|

|

|







75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
	OFStringEncodingISO8859_3,
	/** ISO 8859-15 */
	OFStringEncodingISO8859_15,
	/** Windows-1251 */
	OFStringEncodingWindows1251,
	/** Windows-1252 */
	OFStringEncodingWindows1252,
	/** Code page 437 */
	OFStringEncodingCodepage437,
	/** Code page 850 */
	OFStringEncodingCodepage850,
	/** Code page 858 */
	OFStringEncodingCodepage858,
	/** Mac OS Roman */
	OFStringEncodingMacRoman,
	/** KOI8-R */
	OFStringEncodingKOI8R,
	/** KOI8-U */
	OFStringEncodingKOI8U,
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
 * @class OFString OFString.h ObjFW/OFString.h
 *
 * @brief A class for handling strings.
 */
@interface OFString: OFObject <OFCopying, OFMutableCopying, OFComparing,
    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







|







130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
 * @class OFString OFString.h ObjFW/OFString.h
 *
 * @brief A class for handling strings.
 */
@interface OFString: OFObject <OFCopying, OFMutableCopying, OFComparing,
    OFJSONRepresentation, OFMessagePackRepresentation>
/**
 * @brief The length of the string in Unicode code points.
 */
@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
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
			      length: (size_t)UTF8StringLength;

/**
 * @brief Creates a new OFString from a UTF-8 encoded C string without copying
 *	  the string, if possible.
 *
 * If initialization fails for whatever reason, the passed C string is *not*
 * free'd if `freeWhenDone` is true.
 *
 * @note OFMutableString always creates a copy!
 *
 * @param UTF8String A UTF-8 encoded C string to initialize the OFString with
 * @param freeWhenDone Whether to free the C string when the OFString gets
 *		       deallocated
 * @return A new autoreleased OFString
 * @throw OFInvalidEncodingException The string is not properly UTF-8-encoded
 */
+ (instancetype)stringWithUTF8StringNoCopy: (char *)UTF8String
			      freeWhenDone: (bool)freeWhenDone;

/**
 * @brief Creates a new OFString from a UTF-8 encoded C string with the
 *	  specified length without copying the string, if possible.
 *
 * If initialization fails for whatever reason, the passed C string is *not*
 * free'd if `freeWhenDone` is true.
 *
 * @note OFMutableString always creates a copy!
 *
 * @param UTF8String A UTF-8 encoded C string to initialize the OFString with
 * @param UTF8StringLength The length of the UTF-8 encoded C string
 * @param freeWhenDone Whether to free the C string when the OFString gets
 *		       deallocated







|

















|







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
			      length: (size_t)UTF8StringLength;

/**
 * @brief Creates a new OFString from a UTF-8 encoded C string without copying
 *	  the string, if possible.
 *
 * If initialization fails for whatever reason, the passed C string is *not*
 * freed if `freeWhenDone` is true.
 *
 * @note OFMutableString always creates a copy!
 *
 * @param UTF8String A UTF-8 encoded C string to initialize the OFString with
 * @param freeWhenDone Whether to free the C string when the OFString gets
 *		       deallocated
 * @return A new autoreleased OFString
 * @throw OFInvalidEncodingException The string is not properly UTF-8-encoded
 */
+ (instancetype)stringWithUTF8StringNoCopy: (char *)UTF8String
			      freeWhenDone: (bool)freeWhenDone;

/**
 * @brief Creates a new OFString from a UTF-8 encoded C string with the
 *	  specified length without copying the string, if possible.
 *
 * If initialization fails for whatever reason, the passed C string is *not*
 * freed if `freeWhenDone` is true.
 *
 * @note OFMutableString always creates a copy!
 *
 * @param UTF8String A UTF-8 encoded C string to initialize the OFString with
 * @param UTF8StringLength The length of the UTF-8 encoded C string
 * @param freeWhenDone Whether to free the C string when the OFString gets
 *		       deallocated
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
#endif

/**
 * @brief Creates a new OFString with the contents of the specified IRI.
 *
 * If the IRI's scheme is file, it tries UTF-8 encoding.
 *
 * 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 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)stringWithContentsOfIRI: (OFIRI *)IRI;








|
|
|







527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
#endif

/**
 * @brief Creates a new OFString with the contents of the specified IRI.
 *
 * If the IRI's scheme is file, it tries UTF-8 encoding.
 *
 * If the IRI's scheme is `http` or `https`, 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 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)stringWithContentsOfIRI: (OFIRI *)IRI;

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
			    length: (size_t)UTF8StringLength;

/**
 * @brief Initializes an already allocated OFString from an UTF-8 encoded C
 *	  string without copying the string, if possible.
 *
 * If initialization fails for whatever reason, the passed C string is *not*
 * free'd if `freeWhenDone` is true.
 *
 * @note OFMutableString always creates a copy!
 *
 * @param UTF8String A UTF-8 encoded C string to initialize the OFString with
 * @param freeWhenDone Whether to free the C string when it is not needed
 *		       anymore
 * @return An initialized OFString
 * @throw OFInvalidEncodingException The string is not properly UTF-8-encoded
 */
- (instancetype)initWithUTF8StringNoCopy: (char *)UTF8String
			    freeWhenDone: (bool)freeWhenDone;

/**
 * @brief Initializes an already allocated OFString from an UTF-8 encoded C
 *	  string with the specified length without copying the string, if
 *	  possible.
 *
 * If initialization fails for whatever reason, the passed C string is *not*
 * free'd if `freeWhenDone` is true.
 *
 * @note OFMutableString always creates a copy!
 *
 * @param UTF8String A UTF-8 encoded C string to initialize the OFString with
 * @param UTF8StringLength The length of the UTF-8 encoded C string
 * @param freeWhenDone Whether to free the C string when it is not needed
 *		       anymore







|


















|







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
			    length: (size_t)UTF8StringLength;

/**
 * @brief Initializes an already allocated OFString from an UTF-8 encoded C
 *	  string without copying the string, if possible.
 *
 * If initialization fails for whatever reason, the passed C string is *not*
 * freed if `freeWhenDone` is true.
 *
 * @note OFMutableString always creates a copy!
 *
 * @param UTF8String A UTF-8 encoded C string to initialize the OFString with
 * @param freeWhenDone Whether to free the C string when it is not needed
 *		       anymore
 * @return An initialized OFString
 * @throw OFInvalidEncodingException The string is not properly UTF-8-encoded
 */
- (instancetype)initWithUTF8StringNoCopy: (char *)UTF8String
			    freeWhenDone: (bool)freeWhenDone;

/**
 * @brief Initializes an already allocated OFString from an UTF-8 encoded C
 *	  string with the specified length without copying the string, if
 *	  possible.
 *
 * If initialization fails for whatever reason, the passed C string is *not*
 * freed if `freeWhenDone` is true.
 *
 * @note OFMutableString always creates a copy!
 *
 * @param UTF8String A UTF-8 encoded C string to initialize the OFString with
 * @param UTF8StringLength The length of the UTF-8 encoded C string
 * @param freeWhenDone Whether to free the C string when it is not needed
 *		       anymore
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844

/**
 * @brief Initializes an already allocated OFString with the contents of the
 *	  specified IRI.
 *
 * If the IRI's scheme is file, it tries UTF-8 encoding.
 *
 * 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 IRI The IRI to the contents for the string
 * @return An initialized OFString
 * @throw OFInvalidEncodingException The string is not in the expected encoding
 */
- (instancetype)initWithContentsOfIRI: (OFIRI *)IRI;








|
|
|







828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844

/**
 * @brief Initializes an already allocated OFString with the contents of the
 *	  specified IRI.
 *
 * If the IRI's scheme is file, it tries UTF-8 encoding.
 *
 * If the IRI's scheme is `http` or `https`, 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 IRI The IRI to the contents for the string
 * @return An initialized OFString
 * @throw OFInvalidEncodingException The string is not in the expected encoding
 */
- (instancetype)initWithContentsOfIRI: (OFIRI *)IRI;

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
 */
- (size_t)indexOfCharacterFromSet: (OFCharacterSet *)characterSet;

/**
 * @brief Returns the index of the first character from the set.
 *
 * @param characterSet The set of characters to search for
 * @param options Options modifying search behaviour
 * @return The index of the first occurrence of a character from the set or
 *	   `OFNotFound` if it was not found
 */
- (size_t)indexOfCharacterFromSet: (OFCharacterSet *)characterSet
			  options: (OFStringSearchOptions)options;

/**
 * @brief Returns the index of the first character from the set.
 *
 * @param characterSet The set of characters to search for
 * @param options Options modifying search behaviour
 * @param range The range in which to search
 * @return The index of the first occurrence of a character from the set or
 *	   `OFNotFound` if it was not found
 */
- (size_t)indexOfCharacterFromSet: (OFCharacterSet *)characterSet
			  options: (OFStringSearchOptions)options
			    range: (OFRange)range;







|










|







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
 */
- (size_t)indexOfCharacterFromSet: (OFCharacterSet *)characterSet;

/**
 * @brief Returns the index of the first character from the set.
 *
 * @param characterSet The set of characters to search for
 * @param options Options modifying search behavior
 * @return The index of the first occurrence of a character from the set or
 *	   `OFNotFound` if it was not found
 */
- (size_t)indexOfCharacterFromSet: (OFCharacterSet *)characterSet
			  options: (OFStringSearchOptions)options;

/**
 * @brief Returns the index of the first character from the set.
 *
 * @param characterSet The set of characters to search for
 * @param options Options modifying search behavior
 * @param range The range in which to search
 * @return The index of the first occurrence of a character from the set or
 *	   `OFNotFound` if it was not found
 */
- (size_t)indexOfCharacterFromSet: (OFCharacterSet *)characterSet
			  options: (OFStringSearchOptions)options
			    range: (OFRange)range;
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
 */
- (OFString *)substringFromIndex: (size_t)idx;

/**
 * @brief Creates a substring from the beginning to the specified index.
 *
 * @param idx The index at which the substring should end, exclusive
 * @return The subtring from the beginning to the specified index
 */
- (OFString *)substringToIndex: (size_t)idx;

/**
 * @brief Creates a substring with the specified range.
 *
 * @param range The range of the substring







|







1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
 */
- (OFString *)substringFromIndex: (size_t)idx;

/**
 * @brief Creates a substring from the beginning to the specified index.
 *
 * @param idx The index at which the substring should end, exclusive
 * @return The substring from the beginning to the specified index
 */
- (OFString *)substringToIndex: (size_t)idx;

/**
 * @brief Creates a substring with the specified range.
 *
 * @param range The range of the substring
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161

/**
 * @brief Creates a new string by replacing the occurrences of the specified
 *	  string in the specified range with the specified replacement.
 *
 * @param string The string to replace
 * @param replacement The string with which it should be replaced
 * @param options Options modifying search behaviour.
 *		  Possible values are:
 *		    * None yet, pass 0
 * @param range The range in which to replace the string
 * @return A new string with the occurrences of the specified string replaced
 */
- (OFString *)stringByReplacingOccurrencesOfString: (OFString *)string
					withString: (OFString *)replacement







|







1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161

/**
 * @brief Creates a new string by replacing the occurrences of the specified
 *	  string in the specified range with the specified replacement.
 *
 * @param string The string to replace
 * @param replacement The string with which it should be replaced
 * @param options Options modifying search behavior.
 *		  Possible values are:
 *		    * None yet, pass 0
 * @param range The range in which to replace the string
 * @return A new string with the occurrences of the specified string replaced
 */
- (OFString *)stringByReplacingOccurrencesOfString: (OFString *)string
					withString: (OFString *)replacement

Modified src/OFTCPSocket.h from [f802834c92] to [2942ef5e7e].

76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
#ifdef OF_HAVE_CLASS_PROPERTIES
@property (class, nullable, copy, nonatomic) OFString *SOCKS5Host;
@property (class, nonatomic) uint16_t SOCKS5Port;
#endif

#if !defined(OF_WII) && !defined(OF_NINTENDO_3DS)
/**
 * @brief Whether the socket sends keep alives for the connection.
 *
 * @warning This is not available on the Wii or Nintendo 3DS!
 *
 * @throw OFGetOptionFailedException The option could not be retrieved
 * @throw OFSetOptionFailedException The option could not be set
 */
@property (nonatomic) bool sendsKeepAlives;







|







76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
#ifdef OF_HAVE_CLASS_PROPERTIES
@property (class, nullable, copy, nonatomic) OFString *SOCKS5Host;
@property (class, nonatomic) uint16_t SOCKS5Port;
#endif

#if !defined(OF_WII) && !defined(OF_NINTENDO_3DS)
/**
 * @brief Whether the socket sends keep-alives for the connection.
 *
 * @warning This is not available on the Wii or Nintendo 3DS!
 *
 * @throw OFGetOptionFailedException The option could not be retrieved
 * @throw OFSetOptionFailedException The option could not be set
 */
@property (nonatomic) bool sendsKeepAlives;
170
171
172
173
174
175
176
177

178
179
180
181
182
183
184
- (void)asyncConnectToHost: (OFString *)host port: (uint16_t)port;

/**
 * @brief Asynchronously connects the OFTCPSocket to the specified destination.
 *
 * @param host The host to connect to
 * @param port The port on the host to connect to
 * @param runLoopMode The run loop mode in which to perform the async connect

 */
- (void)asyncConnectToHost: (OFString *)host
		      port: (uint16_t)port
	       runLoopMode: (OFRunLoopMode)runLoopMode;

#ifdef OF_HAVE_BLOCKS
/**







|
>







170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
- (void)asyncConnectToHost: (OFString *)host port: (uint16_t)port;

/**
 * @brief Asynchronously connects the OFTCPSocket to the specified destination.
 *
 * @param host The host to connect to
 * @param port The port on the host to connect to
 * @param runLoopMode The run loop mode in which to perform the asynchronous
 *		      connect
 */
- (void)asyncConnectToHost: (OFString *)host
		      port: (uint16_t)port
	       runLoopMode: (OFRunLoopMode)runLoopMode;

#ifdef OF_HAVE_BLOCKS
/**
193
194
195
196
197
198
199
200

201
202
203
204
205
206
207
		     block: (OFTCPSocketAsyncConnectBlock)block;

/**
 * @brief Asynchronously connects the OFTCPSocket to the specified destination.
 *
 * @param host The host to connect to
 * @param port The port on the host to connect to
 * @param runLoopMode The run loop mode in which to perform the async connect

 * @param block The block to execute once the connection has been established
 */
- (void)asyncConnectToHost: (OFString *)host
		      port: (uint16_t)port
	       runLoopMode: (OFRunLoopMode)runLoopMode
		     block: (OFTCPSocketAsyncConnectBlock)block;
#endif







|
>







194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
		     block: (OFTCPSocketAsyncConnectBlock)block;

/**
 * @brief Asynchronously connects the OFTCPSocket to the specified destination.
 *
 * @param host The host to connect to
 * @param port The port on the host to connect to
 * @param runLoopMode The run loop mode in which to perform the asynchronous
 *		      connect
 * @param block The block to execute once the connection has been established
 */
- (void)asyncConnectToHost: (OFString *)host
		      port: (uint16_t)port
	       runLoopMode: (OFRunLoopMode)runLoopMode
		     block: (OFTCPSocketAsyncConnectBlock)block;
#endif

Added src/OFTXTDNSResourceRecord.h version [0e004b367e].





















































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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-2024 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the 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 "OFDNSResourceRecord.h"

OF_ASSUME_NONNULL_BEGIN

/**
 * @class OFTXTDNSResourceRecord \
 *	  OFDNSResourceRecord.h ObjFW/OFDNSResourceRecord.h
 *
 * @brief A class representing a TXT DNS resource record.
 */
OF_SUBCLASSING_RESTRICTED
@interface OFTXTDNSResourceRecord: OFDNSResourceRecord
{
	OFArray OF_GENERIC(OFData *) *_textStrings;
}

/**
 * @brief The text of the resource record.
 */
@property (readonly, nonatomic) OFArray OF_GENERIC(OFData *) *textStrings;

- (instancetype)initWithName: (OFString *)name
		    DNSClass: (OFDNSClass)DNSClass
		  recordType: (OFDNSRecordType)recordType
			 TTL: (uint32_t)TTL OF_UNAVAILABLE;

/**
 * @brief Initializes an already allocated OFTXTDNSResourceRecord with the
 *	  specified name, class, text data and time to live.
 *
 * @param name The name for the resource record
 * @param DNSClass The class code for the resource record
 * @param textStrings An array of text strings for the resource record
 * @param TTL The time to live for the resource record
 * @return An initialized OFTXTDNSResourceRecord
 */
- (instancetype)initWithName: (OFString *)name
		    DNSClass: (OFDNSClass)DNSClass
		 textStrings: (OFArray OF_GENERIC(OFData *) *)textStrings
			 TTL: (uint32_t)TTL OF_DESIGNATED_INITIALIZER;
@end

OF_ASSUME_NONNULL_END

Added src/OFTXTDNSResourceRecord.m version [63b8879aa3].





















































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
/*
 * Copyright (c) 2008-2024 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the 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 "OFTXTDNSResourceRecord.h"
#import "OFArray.h"
#import "OFData.h"

@implementation OFTXTDNSResourceRecord
@synthesize textStrings = _textStrings;

- (instancetype)initWithName: (OFString *)name
		    DNSClass: (OFDNSClass)DNSClass
		  recordType: (OFDNSRecordType)recordType
			 TTL: (uint32_t)TTL
{
	OF_INVALID_INIT_METHOD
}

- (instancetype)initWithName: (OFString *)name
		    DNSClass: (OFDNSClass)DNSClass
		 textStrings: (OFArray OF_GENERIC(OFData *) *)textStrings
			 TTL: (uint32_t)TTL
{
	self = [super initWithName: name
			  DNSClass: DNSClass
			recordType: OFDNSRecordTypeTXT
			       TTL: TTL];

	@try {
		_textStrings = [textStrings copy];
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (void)dealloc
{
	[_textStrings release];

	[super dealloc];
}

- (bool)isEqual: (id)object
{
	OFTXTDNSResourceRecord *record;

	if (object == self)
		return true;

	if (![object isKindOfClass: [OFTXTDNSResourceRecord class]])
		return false;

	record = object;

	if (record->_name != _name && ![record->_name isEqual: _name])
		return false;

	if (record->_DNSClass != _DNSClass)
		return false;

	if (record->_recordType != _recordType)
		return false;

	if (record->_textStrings != _textStrings &&
	    ![record->_textStrings isEqual: _textStrings])
		return false;

	return true;
}

- (unsigned long)hash
{
	unsigned long hash;

	OFHashInit(&hash);

	OFHashAddHash(&hash, _name.hash);
	OFHashAddByte(&hash, _DNSClass >> 8);
	OFHashAddByte(&hash, _DNSClass);
	OFHashAddByte(&hash, _recordType >> 8);
	OFHashAddByte(&hash, _recordType);
	OFHashAddHash(&hash, _textStrings.hash);

	OFHashFinalize(&hash);

	return hash;
}

- (OFString *)description
{
	void *pool = objc_autoreleasePoolPush();
	OFMutableString *text = [OFMutableString string];
	bool first = true;
	OFString *ret;

	for (OFData *string in _textStrings) {
		const unsigned char *stringItems = string.items;
		size_t stringCount = string.count;

		if (first) {
			first = false;
			[text appendString: @"\""];
		} else
			[text appendString: @" \""];

		for (size_t i = 0; i < stringCount; i++) {
			if (stringItems[i] == '\\')
				[text appendString: @"\\\\"];
			else if (stringItems[i] == '"')
				[text appendString: @"\\\""];
			else if (stringItems[i] < 0x20)
				[text appendFormat: @"\\x%02X", stringItems[i]];
			else if (stringItems[i] < 0x7F)
				[text appendFormat: @"%c", stringItems[i]];
			else
				[text appendFormat: @"\\x%02X", stringItems[i]];
		}

		[text appendString: @"\""];
	}

	ret = [OFString stringWithFormat:
	    @"<%@:\n"
	    @"\tName = %@\n"
	    @"\tClass = %@\n"
	    @"\tText strings = %@\n"
	    @"\tTTL = %" PRIu32 "\n"
	    @">",
	    self.className, _name, OFDNSClassName(_DNSClass), text, _TTL];

	[ret retain];

	objc_autoreleasePoolPop(pool);

	return [ret autorelease];
}
@end

Modified src/OFThread.h from [99dddf0f6e] to [5de5608550].

291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
 */
- (nullable id)main;

/**
 * @brief This routine is executed when the thread's main method has finished
 *	  executing or terminate has been called.
 *
 * @note Be sure to call [super handleTermination]!
 */
- (void)handleTermination OF_REQUIRES_SUPER;

/**
 * @brief Starts the thread.
 *
 * @throw OFStartThreadFailedException Starting the thread failed







|







291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
 */
- (nullable id)main;

/**
 * @brief This routine is executed when the thread's main method has finished
 *	  executing or terminate has been called.
 *
 * @note Be sure to call `[super handleTermination]`!
 */
- (void)handleTermination OF_REQUIRES_SUPER;

/**
 * @brief Starts the thread.
 *
 * @throw OFStartThreadFailedException Starting the thread failed

Added src/OFURIDNSResourceRecord.h version [5d24916d2f].



















































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
/*
 * Copyright (c) 2008-2024 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the 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 "OFDNSResourceRecord.h"

OF_ASSUME_NONNULL_BEGIN

/**
 * @class OFURIDNSResourceRecord \
 *	  OFDNSResourceRecord.h ObjFW/OFDNSResourceRecord.h
 *
 * @brief A class representing an URI DNS resource record.
 */
OF_SUBCLASSING_RESTRICTED
@interface OFURIDNSResourceRecord: OFDNSResourceRecord
{
	uint16_t _priority, _weight;
	OFString *_target;
}

/**
 * @brief The priority of the resource record.
 */
@property (readonly, nonatomic) uint16_t priority;

/**
 * @brief The weight of the resource record.
 */
@property (readonly, nonatomic) uint16_t weight;

/**
 * @brief The target of the resource record.
 */
@property (readonly, nonatomic) OFString *target;

- (instancetype)initWithName: (OFString *)name
		    DNSClass: (OFDNSClass)DNSClass
		  recordType: (OFDNSRecordType)recordType
			 TTL: (uint32_t)TTL OF_UNAVAILABLE;

/**
 * @brief Initializes an already allocated OFURIDNSResourceRecord with the
 *	  specified name, class, priority, weight, target and time to live.
 *
 * @param name The name for the resource record
 * @param DNSClass The class code for the resource record
 * @param priority The priority for the resource record
 * @param weight The weight for the resource record
 * @param target The target for the resource record
 * @param TTL The time to live for the resource record
 * @return An initialized OFURIDNSResourceRecord
 */
- (instancetype)initWithName: (OFString *)name
		    DNSClass: (OFDNSClass)DNSClass
		    priority: (uint16_t)priority
		      weight: (uint16_t)weight
		      target: (OFString *)target
			 TTL: (uint32_t)TTL OF_DESIGNATED_INITIALIZER;
@end

OF_ASSUME_NONNULL_END

Added src/OFURIDNSResourceRecord.m version [8d859480dd].







































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
/*
 * Copyright (c) 2008-2024 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the 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 "OFURIDNSResourceRecord.h"

@implementation OFURIDNSResourceRecord
@synthesize priority = _priority, weight = _weight, target = _target;

- (instancetype)initWithName: (OFString *)name
		    DNSClass: (OFDNSClass)DNSClass
		  recordType: (OFDNSRecordType)recordType
			 TTL: (uint32_t)TTL
{
	OF_INVALID_INIT_METHOD
}

- (instancetype)initWithName: (OFString *)name
		    DNSClass: (OFDNSClass)DNSClass
		    priority: (uint16_t)priority
		      weight: (uint16_t)weight
		      target: (OFString *)target
			 TTL: (uint32_t)TTL
{
	self = [super initWithName: name
			  DNSClass: DNSClass
			recordType: OFDNSRecordTypeURI
			       TTL: TTL];

	@try {
		_priority = priority;
		_weight = weight;
		_target = [target copy];
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (void)dealloc
{
	[_target release];

	[super dealloc];
}

- (bool)isEqual: (id)object
{
	OFURIDNSResourceRecord *record;

	if (object == self)
		return true;

	if (![object isKindOfClass: [OFURIDNSResourceRecord class]])
		return false;

	record = object;

	if (record->_name != _name && ![record->_name isEqual: _name])
		return false;

	if (record->_DNSClass != _DNSClass)
		return false;

	if (record->_recordType != _recordType)
		return false;

	if (record->_priority != _priority)
		return false;

	if (record->_weight != _weight)
		return false;

	if (record->_target != _target && ![record->_target isEqual: _target])
		return false;

	return true;
}

- (unsigned long)hash
{
	unsigned long hash;

	OFHashInit(&hash);

	OFHashAddHash(&hash, _name.hash);
	OFHashAddByte(&hash, _DNSClass >> 8);
	OFHashAddByte(&hash, _DNSClass);
	OFHashAddByte(&hash, _recordType >> 8);
	OFHashAddByte(&hash, _recordType);
	OFHashAddByte(&hash, _priority >> 8);
	OFHashAddByte(&hash, _priority);
	OFHashAddByte(&hash, _weight >> 8);
	OFHashAddByte(&hash, _weight);
	OFHashAddHash(&hash, _target.hash);

	OFHashFinalize(&hash);

	return hash;
}

- (OFString *)description
{
	return [OFString stringWithFormat:
	    @"<%@:\n"
	    @"\tName = %@\n"
	    @"\tClass = %@\n"
	    @"\tPriority = %" PRIu16 "\n"
	    @"\tWeight = %" PRIu16 "\n"
	    @"\tTarget = %@\n"
	    @"\tTTL = %" PRIu32 "\n"
	    @">",
	    self.className, _name, OFDNSClassName(_DNSClass), _priority,
	    _weight, _target, _TTL];
}
@end

Modified src/OFXMLElement.h from [ce204f44dc] to [b5e9230acd].

58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
/**
 * @brief An array with the attributes of the element.
 */
@property OF_NULLABLE_PROPERTY (readonly, nonatomic)
    OFArray OF_GENERIC(OFXMLAttribute *) *attributes;

/**
 * @brief An array of OFXMLNodes with all children of the element.
 */
@property OF_NULLABLE_PROPERTY (nonatomic, copy)
    OFArray OF_GENERIC(OFXMLNode *) *children;

/**
 * @brief All children that are elements.
 */







|







58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
/**
 * @brief An array with the attributes of the element.
 */
@property OF_NULLABLE_PROPERTY (readonly, nonatomic)
    OFArray OF_GENERIC(OFXMLAttribute *) *attributes;

/**
 * @brief An array of @ref OFXMLNode with all children of the element.
 */
@property OF_NULLABLE_PROPERTY (nonatomic, copy)
    OFArray OF_GENERIC(OFXMLNode *) *children;

/**
 * @brief All children that are elements.
 */
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
 * @param index The index where the child is added
 */
- (void)insertChild: (OFXMLNode *)child atIndex: (size_t)index;

/**
 * @brief Inserts the specified children at the specified index.
 *
 * @param children An array of OFXMLNodes which are added as children
 * @param index The index where the child is added
 */
- (void)insertChildren: (OFArray OF_GENERIC(OFXMLNode *) *)children
	       atIndex: (size_t)index;

/**
 * @brief Removes the first child that is equal to the specified OFXMLNode.







|







317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
 * @param index The index where the child is added
 */
- (void)insertChild: (OFXMLNode *)child atIndex: (size_t)index;

/**
 * @brief Inserts the specified children at the specified index.
 *
 * @param children An array of @ref OFXMLNode which are added as children
 * @param index The index where the child is added
 */
- (void)insertChildren: (OFArray OF_GENERIC(OFXMLNode *) *)children
	       atIndex: (size_t)index;

/**
 * @brief Removes the first child that is equal to the specified OFXMLNode.

Modified src/OFZIPArchiveEntry.h from [c8000ff1d0] to [b95a6943e9].

194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
 *
 * @param version The ZIP entry version to convert to a string
 * @return The ZIP entry version as a string
 */
extern OFString *OFZIPArchiveEntryVersionToString(uint16_t version);

/**
 * @brief Convers the ZIP entry compression method to a string.
 *
 * @param compressionMethod The ZIP entry compression method to convert to a
 *			    string
 * @return The ZIP entry compression method as a string
 */
extern OFString *OFZIPArchiveEntryCompressionMethodName(
    OFZIPArchiveEntryCompressionMethod compressionMethod);







|







194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
 *
 * @param version The ZIP entry version to convert to a string
 * @return The ZIP entry version as a string
 */
extern OFString *OFZIPArchiveEntryVersionToString(uint16_t version);

/**
 * @brief Converts the ZIP entry compression method to a string.
 *
 * @param compressionMethod The ZIP entry compression method to convert to a
 *			    string
 * @return The ZIP entry compression method as a string
 */
extern OFString *OFZIPArchiveEntryCompressionMethodName(
    OFZIPArchiveEntryCompressionMethod compressionMethod);

Modified src/bridge/Makefile from [311785c185] to [b387f09472].

37
38
39
40
41
42
43
44
45
46
47
	OFNSEnumerator.m	\
	OFNSSet.m

includesubdir = ObjFWBridge

include ../../buildsys.mk

CPPFLAGS += -I. -I.. -I../.. -I../exceptions -DOF_BRIDGE_LOCAL_INCLUDES
LD = ${OBJC}
FRAMEWORK_LIBS := -framework Foundation -F.. -framework ObjFW ${LIBS}
LIBS := -framework Foundation -L.. -lobjfw ${LIBS}







|



37
38
39
40
41
42
43
44
45
46
47
	OFNSEnumerator.m	\
	OFNSSet.m

includesubdir = ObjFWBridge

include ../../buildsys.mk

CPPFLAGS += -I. -I.. -I../.. -I../exceptions -DOBJFWBRIDGE_LOCAL_INCLUDES
LD = ${OBJC}
FRAMEWORK_LIBS := -framework Foundation -F.. -framework ObjFW ${LIBS}
LIBS := -framework Foundation -L.. -lobjfw ${LIBS}

Modified src/bridge/NSBridging.h from [bb8b560826] to [5d53579fe7].

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 *
 * 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.
 */

#ifdef OF_BRIDGE_LOCAL_INCLUDES
# import "macros.h"
#else
# if defined(__has_feature) && __has_feature(modules)
@import ObjFW;
# else
#  import <ObjFW/macros.h>
# endif







|







9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 *
 * 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.
 */

#ifdef OBJFWBRIDGE_LOCAL_INCLUDES
# import "macros.h"
#else
# if defined(__has_feature) && __has_feature(modules)
@import ObjFW;
# else
#  import <ObjFW/macros.h>
# endif

Modified src/bridge/OFArray+NSObject.h from [4b8ba8c9e9] to [7aafe3a853].

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 *
 * 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.
 */

#ifdef OF_BRIDGE_LOCAL_INCLUDES
# import "OFArray.h"
#else
# if defined(__has_feature) && __has_feature(modules)
@import ObjFW;
# else
#  import <ObjFW/OFArray.h>
# endif







|







9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 *
 * 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.
 */

#ifdef OBJFWBRIDGE_LOCAL_INCLUDES
# import "OFArray.h"
#else
# if defined(__has_feature) && __has_feature(modules)
@import ObjFW;
# else
#  import <ObjFW/OFArray.h>
# endif

Modified src/bridge/OFBridging.h from [71a8a0383b] to [778779f556].

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 *
 * 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.
 */

#ifdef OF_BRIDGE_LOCAL_INCLUDES
# import "macros.h"
#else
# if defined(__has_feature) && __has_feature(modules)
@import ObjFW;
# else
#  import <ObjFW/macros.h>
# endif







|







9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 *
 * 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.
 */

#ifdef OBJFWBRIDGE_LOCAL_INCLUDES
# import "macros.h"
#else
# if defined(__has_feature) && __has_feature(modules)
@import ObjFW;
# else
#  import <ObjFW/macros.h>
# endif

Modified src/bridge/OFDictionary+NSObject.h from [cc93713fad] to [14877bf984].

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 *
 * 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.
 */

#ifdef OF_BRIDGE_LOCAL_INCLUDES
# import "OFDictionary.h"
#else
# if defined(__has_feature) && __has_feature(modules)
@import ObjFW;
# else
#  import <ObjFW/OFDictionary.h>
# endif







|







9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 *
 * 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.
 */

#ifdef OBJFWBRIDGE_LOCAL_INCLUDES
# import "OFDictionary.h"
#else
# if defined(__has_feature) && __has_feature(modules)
@import ObjFW;
# else
#  import <ObjFW/OFDictionary.h>
# endif

Modified src/bridge/OFEnumerator+NSObject.h from [a35e608df0] to [4b0355c5ba].

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 *
 * 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.
 */

#ifdef OF_BRIDGE_LOCAL_INCLUDES
# import "OFEnumerator.h"
#else
# if defined(__has_feature) && __has_feature(modules)
@import ObjFW;
# else
#  import <ObjFW/OFEnumerator.h>
# endif







|







9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 *
 * 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.
 */

#ifdef OBJFWBRIDGE_LOCAL_INCLUDES
# import "OFEnumerator.h"
#else
# if defined(__has_feature) && __has_feature(modules)
@import ObjFW;
# else
#  import <ObjFW/OFEnumerator.h>
# endif

Modified src/bridge/OFException+Swift.h from [e1daea571c] to [2f4125cee1].

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 *
 * 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.
 */

#ifdef OF_BRIDGE_LOCAL_INCLUDES
# import "OFException.h"
#else
# if defined(__has_feature) && __has_feature(modules)
@import ObjFW;
# else
#  import <ObjFW/OFException.h>
# endif







|







9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 *
 * 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.
 */

#ifdef OBJFWBRIDGE_LOCAL_INCLUDES
# import "OFException.h"
#else
# if defined(__has_feature) && __has_feature(modules)
@import ObjFW;
# else
#  import <ObjFW/OFException.h>
# endif

Modified src/bridge/OFNSArray.h from [bc91fcf25e] to [60dbbeacf4].

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 *
 * 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.
 */

#ifdef OF_BRIDGE_LOCAL_INCLUDES
# import "OFArray.h"
#else
# if defined(__has_feature) && __has_feature(modules)
@import ObjFW;
# else
#  import <ObjFW/OFArray.h>
# endif







|







9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 *
 * 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.
 */

#ifdef OBJFWBRIDGE_LOCAL_INCLUDES
# import "OFArray.h"
#else
# if defined(__has_feature) && __has_feature(modules)
@import ObjFW;
# else
#  import <ObjFW/OFArray.h>
# endif

Modified src/bridge/OFNSDictionary.h from [b6fe03ba27] to [f77988fdac].

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 *
 * 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.
 */

#ifdef OF_BRIDGE_LOCAL_INCLUDES
# import "OFDictionary.h"
#else
# if defined(__has_feature) && __has_feature(modules)
@import ObjFW;
# else
#  import <ObjFW/OFDictionary.h>
# endif







|







9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 *
 * 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.
 */

#ifdef OBJFWBRIDGE_LOCAL_INCLUDES
# import "OFDictionary.h"
#else
# if defined(__has_feature) && __has_feature(modules)
@import ObjFW;
# else
#  import <ObjFW/OFDictionary.h>
# endif

Modified src/bridge/OFNSEnumerator.h from [146aaa60ea] to [1ff962951e].

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 *
 * 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.
 */

#ifdef OF_BRIDGE_LOCAL_INCLUDES
# import "OFEnumerator.h"
#else
# if defined(__has_feature) && __has_feature(modules)
@import ObjFW;
# else
#  import <ObjFW/OFEnumerator.h>
# endif







|







9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 *
 * 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.
 */

#ifdef OBJFWBRIDGE_LOCAL_INCLUDES
# import "OFEnumerator.h"
#else
# if defined(__has_feature) && __has_feature(modules)
@import ObjFW;
# else
#  import <ObjFW/OFEnumerator.h>
# endif

Modified src/bridge/OFNSSet.h from [8b3618717b] to [f477b41cf7].

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 *
 * 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.
 */

#ifdef OF_BRIDGE_LOCAL_INCLUDES
# import "OFSet.h"
#else
# if defined(__has_feature) && __has_feature(modules)
@import ObjFW;
# else
#  import <ObjFW/OFSet.h>
# endif







|







9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 *
 * 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.
 */

#ifdef OBJFWBRIDGE_LOCAL_INCLUDES
# import "OFSet.h"
#else
# if defined(__has_feature) && __has_feature(modules)
@import ObjFW;
# else
#  import <ObjFW/OFSet.h>
# endif

Modified src/bridge/OFNumber+NSObject.h from [fc32bb2b98] to [c8f67b170d].

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 *
 * 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.
 */

#ifdef OF_BRIDGE_LOCAL_INCLUDES
# import "OFNumber.h"
#else
# if defined(__has_feature) && __has_feature(modules)
@import ObjFW;
# else
#  import <ObjFW/OFNumber.h>
# endif







|







9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 *
 * 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.
 */

#ifdef OBJFWBRIDGE_LOCAL_INCLUDES
# import "OFNumber.h"
#else
# if defined(__has_feature) && __has_feature(modules)
@import ObjFW;
# else
#  import <ObjFW/OFNumber.h>
# endif

Modified src/bridge/OFSet+NSObject.h from [c4837c5b7d] to [367cc9a573].

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 *
 * 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.
 */

#ifdef OF_BRIDGE_LOCAL_INCLUDES
# import "OFSet.h"
#else
# if defined(__has_feature) && __has_feature(modules)
@import ObjFW;
# else
#  import <ObjFW/OFSet.h>
# endif







|







9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 *
 * 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.
 */

#ifdef OBJFWBRIDGE_LOCAL_INCLUDES
# import "OFSet.h"
#else
# if defined(__has_feature) && __has_feature(modules)
@import ObjFW;
# else
#  import <ObjFW/OFSet.h>
# endif

Modified src/bridge/OFString+NSObject.h from [9663e731bd] to [c50afdb5f8].

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 *
 * 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.
 */

#ifdef OF_BRIDGE_LOCAL_INCLUDES
# import "OFString.h"
#else
# if defined(__has_feature) && __has_feature(modules)
@import ObjFW;
# else
#  import <ObjFW/OFString.h>
# endif







|







9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 *
 * 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.
 */

#ifdef OBJFWBRIDGE_LOCAL_INCLUDES
# import "OFString.h"
#else
# if defined(__has_feature) && __has_feature(modules)
@import ObjFW;
# else
#  import <ObjFW/OFString.h>
# endif

Modified src/exceptions/OFCreateSymbolicLinkFailedException.h from [bd616cbde6] to [971338ad9a].

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
	OFIRI *_IRI;
	OFString *_target;
	int _errNo;
	OF_RESERVE_IVARS(OFCreateSymbolicLinkFailedException, 4)
}

/**
 * @brief The IRI at which the symlink should have been created.
 */
@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 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)exceptionWithIRI: (OFIRI *)IRI
			  target: (OFString *)target
			   errNo: (int)errNo;

+ (instancetype)exception OF_UNAVAILABLE;

/**
 * @brief Initializes an already allocated create symbolic link failed
 *	  exception.
 *
 * @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)initWithIRI: (OFIRI *)IRI
		     target: (OFString *)target
		      errNo: (int)errNo OF_DESIGNATED_INITIALIZER;

- (instancetype)init OF_UNAVAILABLE;
@end

OF_ASSUME_NONNULL_END







|




|











|














|












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
	OFIRI *_IRI;
	OFString *_target;
	int _errNo;
	OF_RESERVE_IVARS(OFCreateSymbolicLinkFailedException, 4)
}

/**
 * @brief The IRI at which the symbolic link should have been created.
 */
@property (readonly, nonatomic) OFIRI *IRI;

/**
 * @brief The target for the symbolic link.
 */
@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 IRI The IRI where the symbolic link 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)exceptionWithIRI: (OFIRI *)IRI
			  target: (OFString *)target
			   errNo: (int)errNo;

+ (instancetype)exception OF_UNAVAILABLE;

/**
 * @brief Initializes an already allocated create symbolic link failed
 *	  exception.
 *
 * @param IRI The IRI where the symbolic link 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)initWithIRI: (OFIRI *)IRI
		     target: (OFString *)target
		      errNo: (int)errNo OF_DESIGNATED_INITIALIZER;

- (instancetype)init OF_UNAVAILABLE;
@end

OF_ASSUME_NONNULL_END

Modified src/platform/POSIX/OFSubprocess.m from [6b69aef5c9] to [befc82a64d].

37
38
39
40
41
42
43
44
45



46
47
48
49
50
51
52

#import "OFInitializationFailedException.h"
#import "OFNotOpenException.h"
#import "OFOutOfRangeException.h"
#import "OFReadFailedException.h"
#import "OFWriteFailedException.h"

#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;
- (char **)of_environmentForDictionary: (OFDictionary *)dictionary;







|

>
>
>







37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55

#import "OFInitializationFailedException.h"
#import "OFNotOpenException.h"
#import "OFOutOfRangeException.h"
#import "OFReadFailedException.h"
#import "OFWriteFailedException.h"

#ifndef OF_MACOS
extern char **environ;
#else
# include <crt_externs.h>
# define environ (*_NSGetEnviron())
#endif

@interface OFSubprocess ()
- (void)of_getArgv: (char ***)argv
    forProgramName: (OFString *)programName
      andArguments: (OFArray *)arguments;
- (char **)of_environmentForDictionary: (OFDictionary *)dictionary;
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189

190
191
192
193
194
195
196
197
				if (posix_spawnattr_setflags(&attr,
				    POSIX_SPAWN_CLOEXEC_DEFAULT) != 0)
					@throw [OFInitializationFailedException
					    exceptionWithClass: self.class];
# endif

				if (posix_spawnp(&_pid, path, &actions, &attr,
				    argv, env) != 0)
					@throw [OFInitializationFailedException
					    exceptionWithClass: self.class];
			} @finally {
				posix_spawn_file_actions_destroy(&actions);
				posix_spawnattr_destroy(&attr);
			}
#else
			if ((_pid = vfork()) == 0) {

				environ = env;

				close(_readPipe[0]);
				close(_writePipe[1]);
				dup2(_writePipe[0], 0);
				dup2(_readPipe[1], 1);
				execvp(path, argv);








|








>
|







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
				if (posix_spawnattr_setflags(&attr,
				    POSIX_SPAWN_CLOEXEC_DEFAULT) != 0)
					@throw [OFInitializationFailedException
					    exceptionWithClass: self.class];
# endif

				if (posix_spawnp(&_pid, path, &actions, &attr,
				    argv, (env != NULL ? env : environ)) != 0)
					@throw [OFInitializationFailedException
					    exceptionWithClass: self.class];
			} @finally {
				posix_spawn_file_actions_destroy(&actions);
				posix_spawnattr_destroy(&attr);
			}
#else
			if ((_pid = vfork()) == 0) {
				if (env != NULL)
					environ = env;

				close(_readPipe[0]);
				close(_writePipe[1]);
				dup2(_writePipe[0], 0);
				dup2(_readPipe[1], 1);
				execvp(path, argv);

372
373
374
375
376
377
378

379

380
381
382
383
384
385
386
}

- (void)close
{
	if (_readPipe[0] == -1)
		@throw [OFNotOpenException exceptionWithObject: self];


	[self closeForWriting];

	close(_readPipe[0]);

	if (_pid != -1) {
		kill(_pid, SIGTERM);
		waitpid(_pid, &_status, WNOHANG);
	}








>
|
>







376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
}

- (void)close
{
	if (_readPipe[0] == -1)
		@throw [OFNotOpenException exceptionWithObject: self];

	if (_writePipe[1] != -1)
		[self closeForWriting];

	close(_readPipe[0]);

	if (_pid != -1) {
		kill(_pid, SIGTERM);
		waitpid(_pid, &_status, WNOHANG);
	}

Modified src/platform/Windows/OFSubprocess.m from [3257d0230c] to [4e382dab1b].

379
380
381
382
383
384
385

386

387
388
389
390
391
392
393
}

- (void)close
{
	if (_readPipe[0] == NULL)
		@throw [OFNotOpenException exceptionWithObject: self];


	[self closeForWriting];

	CloseHandle(_readPipe[0]);

	if (_handle != INVALID_HANDLE_VALUE) {
		TerminateProcess(_handle, 0);
		CloseHandle(_handle);
	}








>
|
>







379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
}

- (void)close
{
	if (_readPipe[0] == NULL)
		@throw [OFNotOpenException exceptionWithObject: self];

	if (_writePipe[1] != NULL)
		[self closeForWriting];

	CloseHandle(_readPipe[0]);

	if (_handle != INVALID_HANDLE_VALUE) {
		TerminateProcess(_handle, 0);
		CloseHandle(_handle);
	}

Modified src/platform/Windows/OFSystemInfo+NetworkInterfaces.m from [a714877a2e] to [f40e21866b].

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
{
	HMODULE module;

	if ((module = GetModuleHandle("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];
	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);








<













>







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
{
	HMODULE module;

	if ((module = GetModuleHandle("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];
	ULONG adapterAddressesSize = sizeof(IP_ADAPTER_ADDRESSES);
	PIP_ADAPTER_ADDRESSES adapterAddresses;

	if ((adapterAddresses = malloc(adapterAddressesSize)) == NULL)
		return nil;

	@try {
		OFStringEncoding encoding = [OFLocale encoding];
		ULONG error = GetAdaptersAddressesFuncPtr(AF_UNSPEC, 0, NULL,
		    adapterAddresses, &adapterAddressesSize);

		if (error == ERROR_BUFFER_OVERFLOW) {
			PIP_ADAPTER_ADDRESSES newAdapterAddresses =
			    realloc(adapterAddresses, adapterAddressesSize);

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

		for (PIP_ADAPTER_ADDRESSES iter = adapterAddresses;
		    iter != NULL; iter = iter->Next) {
			OFString *name;
			OFMutableDictionary *interface;
			OFNumber *index;

			name = [OFString stringWithFormat: @"%lu",
							   iter->IfIndex];

			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;








|
|



















|







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

		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 (__typeof__(iter->FirstUnicastAddress) addrIter =
			    iter->FirstUnicastAddress; addrIter != NULL;
			    addrIter = addrIter->Next) {
				OFSocketAddress address;
				int length;
				OFNetworkInterfaceKey key;
				OFMutableData *addresses;

Modified src/runtime/Makefile from [af674fab60] to [692471a52e].

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

14
15
16
17
18
19
20
include ../../extra.mk

SUBDIRS = lookup-asm
DISTCLEAN = Info.plist

SHARED_LIB = ${OBJFWRT_SHARED_LIB}
STATIC_LIB = ${OBJFWRT_STATIC_LIB}
FRAMEWORK = ${OBJFWRT_FRAMEWORK}
LIB_MAJOR = ${OBJFWRT_LIB_MAJOR}
LIB_MINOR = ${OBJFWRT_LIB_MINOR}
LIB_PATCH = ${OBJFWRT_LIB_PATCH}

SRCS = arc.m			\

       autorelease.m		\
       category.m		\
       class.m			\
       dtable.m			\
       exception.m		\
       hashtable.m		\
       init.m			\













>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
include ../../extra.mk

SUBDIRS = lookup-asm
DISTCLEAN = Info.plist

SHARED_LIB = ${OBJFWRT_SHARED_LIB}
STATIC_LIB = ${OBJFWRT_STATIC_LIB}
FRAMEWORK = ${OBJFWRT_FRAMEWORK}
LIB_MAJOR = ${OBJFWRT_LIB_MAJOR}
LIB_MINOR = ${OBJFWRT_LIB_MINOR}
LIB_PATCH = ${OBJFWRT_LIB_PATCH}

SRCS = arc.m			\
       association.m		\
       autorelease.m		\
       category.m		\
       class.m			\
       dtable.m			\
       exception.m		\
       hashtable.m		\
       init.m			\

Modified src/runtime/ObjFWRT.h from [a1ab03cb5a] to [8884ec4c85].

130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
 * @note This is a legacy from before C had a boolean type. Prefer the standard
 *	 C99 bool instead!
 */
typedef bool BOOL;
#endif

/**
 * @brief A method implemenation.
 *
 * @param object The messaged object
 * @param selector The selector sent
 */
typedef id _Nullable (*IMP)(id _Nonnull object, SEL _Nonnull selector, ...);

/**







|







130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
 * @note This is a legacy from before C had a boolean type. Prefer the standard
 *	 C99 bool instead!
 */
typedef bool BOOL;
#endif

/**
 * @brief A method implementation.
 *
 * @param object The messaged object
 * @param selector The selector sent
 */
typedef id _Nullable (*IMP)(id _Nonnull object, SEL _Nonnull selector, ...);

/**
169
170
171
172
173
174
175
















176
177
178
179
180
181
182
#ifdef __cplusplus
	Class _Nonnull class_;
#else
	Class _Nonnull class;
#endif
};

















#ifdef __cplusplus
extern "C" {
#endif

/**
 * @brief Registers a selector with the specified name with the runtime.
 *







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







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
#ifdef __cplusplus
	Class _Nonnull class_;
#else
	Class _Nonnull class;
#endif
};

/**
 * @brief A policy for object association, see @ref objc_setAssociatedObject.
 */
typedef enum objc_associationPolicy {
	/** @brief Associate the object like an assigned property. */
	OBJC_ASSOCIATION_ASSIGN	= 0,
	/** @brief Associate the object like a retained, nonatomic property. */
	OBJC_ASSOCIATION_RETAIN_NONATOMIC = 1,
	/** @brief Associate the object like a retained property. */
	OBJC_ASSOCIATION_RETAIN = OBJC_ASSOCIATION_RETAIN_NONATOMIC | 0x300,
	/** @brief Associate the object like a copied, nonatomic property. */
	OBJC_ASSOCIATION_COPY_NONATOMIC = 3,
	/** @brief Associate the object like a copied property. */
	OBJC_ASSOCIATION_COPY = OBJC_ASSOCIATION_COPY_NONATOMIC | 0x300
} objc_associationPolicy;

#ifdef __cplusplus
extern "C" {
#endif

/**
 * @brief Registers a selector with the specified name with the runtime.
 *
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
 * @warning If the method uses the struct return ABI, you need to use
 *	    @ref class_getMethodImplementation_stret instead! Depending on the
 *	    ABI, small structs might not use the struct return ABI.
 *
 * @param class_ The class whose method implementation should be returned
 * @param selector The selector for the method whose implementation should be
 *		   returned
 * @return The class's metod implementation for the specified selector
 */
extern IMP _Nullable class_getMethodImplementation(Class _Nullable class_,
    SEL _Nonnull selector);

/**
 * @brief Returns the class's method implementation for the specified selector.
 *
 * @warning If the method does not use use the struct return ABI, you need to
 *	    use @ref class_getMethodImplementation instead! Depending on the
 *	    ABI, small structs might not use the struct return ABI.
 *
 * @param class_ The class whose method implementation should be returned
 * @param selector The selector for the method whose implementation should be
 *		   returned
 * @return The class's metod implementation for the specified selector
 */
extern IMP _Nullable class_getMethodImplementation_stret(Class _Nullable class_,
    SEL _Nonnull selector);

/**
 * @brief Returns the class's instance method for the specified selector
 *







|














|







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
 * @warning If the method uses the struct return ABI, you need to use
 *	    @ref class_getMethodImplementation_stret instead! Depending on the
 *	    ABI, small structs might not use the struct return ABI.
 *
 * @param class_ The class whose method implementation should be returned
 * @param selector The selector for the method whose implementation should be
 *		   returned
 * @return The class's method implementation for the specified selector
 */
extern IMP _Nullable class_getMethodImplementation(Class _Nullable class_,
    SEL _Nonnull selector);

/**
 * @brief Returns the class's method implementation for the specified selector.
 *
 * @warning If the method does not use use the struct return ABI, you need to
 *	    use @ref class_getMethodImplementation instead! Depending on the
 *	    ABI, small structs might not use the struct return ABI.
 *
 * @param class_ The class whose method implementation should be returned
 * @param selector The selector for the method whose implementation should be
 *		   returned
 * @return The class's method implementation for the specified selector
 */
extern IMP _Nullable class_getMethodImplementation_stret(Class _Nullable class_,
    SEL _Nonnull selector);

/**
 * @brief Returns the class's instance method for the specified selector
 *
642
643
644
645
646
647
648































649
650
651
652
653
654
655
 *
 * @param class_ The tag ID for the tagged pointer class to use
 * @param value The value the tagged pointer should have
 * @return A tagged pointer, or `nil` if it could not be created
 */
extern id _Nullable objc_createTaggedPointer(int class_, uintptr_t value);
































/*
 * Used by the compiler, but can also be called manually.
 *
 * These declarations are also required to prevent Clang's implicit
 * declarations which include __declspec(dllimport) on Windows.
 */
struct objc_module;







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







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
 *
 * @param class_ The tag ID for the tagged pointer class to use
 * @param value The value the tagged pointer should have
 * @return A tagged pointer, or `nil` if it could not be created
 */
extern id _Nullable objc_createTaggedPointer(int class_, uintptr_t value);

/**
 * @brief Sets an associated object on the specified object for the specified
 *	  key.
 *
 * @param object The object on which to set an associated object
 * @param key A unique pointer to use as the key for the association
 * @param value The object to associate with the specified object
 * @param policy The association policy, see @ref objc_associationPolicy
 */
extern void objc_setAssociatedObject(id _Nonnull object,
    const void *_Nonnull key, id _Nullable value,
    objc_associationPolicy policy);

/**
 * @brief Returns the associated object on the specified object for the
 *	  specified key.
 *
 * @param object The object on which to get the associated object
 * @param key The key of the association
 * @return The associated object on the specified object for the specified key
 */
extern id _Nullable objc_getAssociatedObject(id _Nonnull object,
    const void *_Nonnull key);

/**
 * @brief Removes all associated objects for the specified object.
 *
 * @param object The object on which to remove all associated objects
 */
extern void objc_removeAssociatedObjects(id _Nonnull object);

/*
 * Used by the compiler, but can also be called manually.
 *
 * These declarations are also required to prevent Clang's implicit
 * declarations which include __declspec(dllimport) on Windows.
 */
struct objc_module;

Added src/runtime/association.m version [b558229b1e].























































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
/*
 * Copyright (c) 2008-2024 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the 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"

#ifdef OF_HAVE_THREADS
# import "OFPlainMutex.h"
# define numSpinlocks 8	/* needs to be a power of 2 */
static OFSpinlock spinlocks[numSpinlocks];

static OF_INLINE size_t
spinlockSlot(id object)
{
	return ((size_t)((uintptr_t)object >> 4) & (numSpinlocks - 1));
}
#endif

struct Association {
	id object;
	objc_associationPolicy policy;
};

static struct objc_hashtable *hashtable;

static uint32_t
hash(const void *object)
{
	return (uint32_t)(uintptr_t)object;
}

static bool
equal(const void *object1, const void *object2)
{
	return (object1 == object2);
}

OF_CONSTRUCTOR()
{
	hashtable = objc_hashtable_new(hash, equal, 2);

#ifdef OF_HAVE_THREADS
	for (size_t i = 0; i < numSpinlocks; i++)
		if (OFSpinlockNew(&spinlocks[i]) != 0)
			OBJC_ERROR("Failed to create spinlocks!");
#endif
}

void
objc_setAssociatedObject(id object, const void *key, id value,
    objc_associationPolicy policy)
{
#ifdef OF_HAVE_THREADS
	size_t slot;
#endif

	switch (policy) {
	case OBJC_ASSOCIATION_ASSIGN:
		break;
	case OBJC_ASSOCIATION_RETAIN:
	case OBJC_ASSOCIATION_RETAIN_NONATOMIC:
		value = [value retain];
		break;
	case OBJC_ASSOCIATION_COPY:
	case OBJC_ASSOCIATION_COPY_NONATOMIC:
		value = [value copy];
		break;
	default:
		/* Don't know what to do, so do nothing. */
		return;
	}

#ifdef OF_HAVE_THREADS
	slot = spinlockSlot(object);

	if (OFSpinlockLock(&spinlocks[slot]) != 0)
		OBJC_ERROR("Failed to lock spinlock!");

	@try {
#endif
		struct objc_hashtable *objectHashtable;
		struct Association *association;

		objectHashtable = objc_hashtable_get(hashtable, object);
		if (objectHashtable == NULL) {
			objectHashtable = objc_hashtable_new(hash, equal, 2);
			objc_hashtable_set(hashtable, object, objectHashtable);
		}

		association = objc_hashtable_get(objectHashtable, key);
		if (association != NULL) {
			switch (association->policy) {
			case OBJC_ASSOCIATION_RETAIN:
			case OBJC_ASSOCIATION_RETAIN_NONATOMIC:
			case OBJC_ASSOCIATION_COPY:
			case OBJC_ASSOCIATION_COPY_NONATOMIC:
				[association->object release];
				break;
			default:
				break;
			}
		} else {
			association = malloc(sizeof(*association));
			if (association == NULL)
				OBJC_ERROR("Failed to allocate association!");

			objc_hashtable_set(objectHashtable, key, association);
		}

		association->policy = policy;
		association->object = value;
#ifdef OF_HAVE_THREADS
	} @finally {
		if (OFSpinlockUnlock(&spinlocks[slot]) != 0)
			OBJC_ERROR("Failed to unlock spinlock!");
	}
#endif
}

id
objc_getAssociatedObject(id object, const void *key)
{
#ifdef OF_HAVE_THREADS
	size_t slot = spinlockSlot(object);

	if (OFSpinlockLock(&spinlocks[slot]) != 0)
		OBJC_ERROR("Failed to lock spinlock!");

	@try {
#endif
		struct objc_hashtable *objectHashtable;
		struct Association *association;

		objectHashtable = objc_hashtable_get(hashtable, object);
		if (objectHashtable == NULL)
			return nil;

		association = objc_hashtable_get(objectHashtable, key);
		if (association == NULL)
			return nil;

		switch (association->policy) {
		case OBJC_ASSOCIATION_RETAIN:
		case OBJC_ASSOCIATION_COPY:
			return [[association->object retain] autorelease];
		default:
			return association->object;
		}
#ifdef OF_HAVE_THREADS
	} @finally {
		if (OFSpinlockUnlock(&spinlocks[slot]) != 0)
			OBJC_ERROR("Failed to unlock spinlock!");
	}
#endif
}

void
objc_removeAssociatedObjects(id object)
{
#ifdef OF_HAVE_THREADS
	size_t slot = spinlockSlot(object);

	if (OFSpinlockLock(&spinlocks[slot]) != 0)
		OBJC_ERROR("Failed to lock spinlock!");

	@try {
#endif
		struct objc_hashtable *objectHashtable;

		objectHashtable = objc_hashtable_get(hashtable, object);
		if (objectHashtable == NULL)
			return;

		for (uint32_t i = 0; i < objectHashtable->size; i++) {
			struct Association *association;

			if (objectHashtable->data[i] == NULL ||
			    objectHashtable->data[i] == &objc_deletedBucket)
				continue;

			association = (struct Association *)
			    objectHashtable->data[i]->object;

			switch (association->policy) {
			case OBJC_ASSOCIATION_RETAIN:
			case OBJC_ASSOCIATION_RETAIN_NONATOMIC:
			case OBJC_ASSOCIATION_COPY:
			case OBJC_ASSOCIATION_COPY_NONATOMIC:
				[association->object release];
				break;
			default:
				break;
			}

			free(association);
		}

		objc_hashtable_delete(hashtable, object);
#ifdef OF_HAVE_THREADS
	} @finally {
		if (OFSpinlockUnlock(&spinlocks[slot]) != 0)
			OBJC_ERROR("Failed to unlock spinlock!");
	}
#endif
}

Modified src/runtime/class.m from [99bd522eda] to [628f2b08c1].

599
600
601
602
603
604
605
606

607
608
609
610
611
612
613
		void *class;

		if (j >= count) {
			objc_globalMutex_unlock();
			return j;
		}

		if (classes->data[i] == NULL)

			continue;

		if (strcmp(classes->data[i]->key, "Protocol") == 0)
			continue;

		class = (Class)classes->data[i]->object;








|
>







599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
		void *class;

		if (j >= count) {
			objc_globalMutex_unlock();
			return j;
		}

		if (classes->data[i] == NULL ||
		    classes->data[i] == &objc_deletedBucket)
			continue;

		if (strcmp(classes->data[i]->key, "Protocol") == 0)
			continue;

		class = (Class)classes->data[i]->object;

Modified src/runtime/instance.m from [356d4e5ea1] to [6c5de971d5].

97
98
99
100
101
102
103


104
105
106
			    destructSelector)) != last)
				destruct(object, destructSelector);

			last = destruct;
		} else
			break;
	}



	return object;
}







>
>



97
98
99
100
101
102
103
104
105
106
107
108
			    destructSelector)) != last)
				destruct(object, destructSelector);

			last = destruct;
		} else
			break;
	}

	objc_removeAssociatedObjects(object);

	return object;
}

Modified src/runtime/property.m from [eac1d5ea2f] to [20ebfada38].

26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
static OFSpinlock spinlocks[numSpinlocks];

static OF_INLINE size_t
spinlockSlot(const void *ptr)
{
	return ((size_t)((uintptr_t)ptr >> 4) & (numSpinlocks - 1));
}
#endif

#ifdef OF_HAVE_THREADS
OF_CONSTRUCTOR()
{
	for (size_t i = 0; i < numSpinlocks; i++)
		if (OFSpinlockNew(&spinlocks[i]) != 0)
			OBJC_ERROR("Failed to create spinlocks!");
}
#endif







<

<







26
27
28
29
30
31
32

33

34
35
36
37
38
39
40
static OFSpinlock spinlocks[numSpinlocks];

static OF_INLINE size_t
spinlockSlot(const void *ptr)
{
	return ((size_t)((uintptr_t)ptr >> 4) & (numSpinlocks - 1));
}



OF_CONSTRUCTOR()
{
	for (size_t i = 0; i < numSpinlocks; i++)
		if (OFSpinlockNew(&spinlocks[i]) != 0)
			OBJC_ERROR("Failed to create spinlocks!");
}
#endif

Added src/test/Makefile version [b269c69e19].





































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
include ../../extra.mk

DISTCLEAN = Info.plist

STATIC_LIB = libobjfwtest.a

SRCS = OTAssert.m	\
       OTTestCase.m
INCLUDES := ${SRCS:.m=.h}	\
	    ObjFWTest.h
SRCS += OTAppDelegate.m			\
	OTAssertionFailedException.m

includesubdir = ObjFWTest

include ../../buildsys.mk

CPPFLAGS += -I. 			\
	    -I..			\
	    -I../..			\
	    -I../exceptions		\
	    -I../runtime		\
	    -DOBJFWTEST_LOCAL_INCLUDES
LD = ${OBJC}
FRAMEWORK_LIBS := -F..				\
		  -framework ObjFW		\
		  -F../runtime			\
		  ${RUNTIME_FRAMEWORK_LIBS}	\
		  ${LIBS}
LIBS := -L.. -lobjfw -L../runtime ${RUNTIME_LIBS} ${LIBS}

install-extra:
	i=ObjFWTest.oc; \
	${INSTALL_STATUS}; \
	if ${MKDIR_P} ${libdir}/objfw-config && ${INSTALL} -m 644 $$i ${libdir}/objfw-config/$$i; then \
		${INSTALL_OK}; \
	else \
		${INSTALL_FAILED}; \
	fi

uninstall-extra:
	i=ObjFWTest.oc; \
	if test -f ${libdir}/objfw-config/$$i; then \
		if rm -f ${libdir}/objfw-config/$$i; then \
			${DELETE_OK}; \
		else \
			${DELETE_FAILED}; \
		fi \
	fi; \
	rmdir ${libdir}/objfw-config >/dev/null 2>&1 || true

Added src/test/OTAppDelegate.h version [64bf862003].















































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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-2024 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the 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 "OFApplication.h"

OF_ASSUME_NONNULL_BEGIN

@interface OTAppDelegate: OFObject <OFApplicationDelegate>
@end

OF_ASSUME_NONNULL_END

Added src/test/OTAppDelegate.m version [c000033e03].





















































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
/*
 * Copyright (c) 2008-2024 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the 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 "OTAppDelegate.h"

#import "OFColor.h"
#import "OFMethodSignature.h"
#import "OFSet.h"
#import "OFStdIOStream.h"
#import "OFValue.h"

#import "OTTestCase.h"

#import "OTAssertionFailedException.h"

OF_APPLICATION_DELEGATE(OTAppDelegate)

static bool
isSubclassOfClass(Class class, Class superclass)
{
	for (Class iter = class; iter != Nil; iter = class_getSuperclass(iter))
		if (iter == superclass)
			return true;

	return false;
}

@implementation OTAppDelegate
- (OFSet OF_GENERIC(Class) *)testClasses
{
	Class *classes = objc_copyClassList(NULL);
	OFMutableSet *testClasses;

	if (classes == NULL)
		return nil;

	@try {
		testClasses = [OFMutableSet set];

		for (Class *iter = classes; *iter != Nil; iter++) {
			/*
			 * Make sure the class is initialized.
			 * Required for the ObjFW runtime, as otherwise
			 * class_getSuperclass() crashes.
			 */
			[*iter class];

			/*
			 * Don't use +[isSubclassOfClass:], as the Apple runtime
			 * can return (presumably internal?) classes that don't
			 * implement it, resulting in a crash.
			 */
			if (isSubclassOfClass(*iter, [OTTestCase class]))
				[testClasses addObject: *iter];
		}
	} @finally {
		OFFreeMemory(classes);
	}

	[testClasses removeObject: [OTTestCase class]];

	[testClasses makeImmutable];
	return testClasses;
}

- (OFSet OF_GENERIC(OFValue *) *)testsInClass: (Class)class
{
	Method *methods = class_copyMethodList(class, NULL);
	OFMutableSet *tests;

	if (methods == NULL)
		return nil;

	@try {
		tests = [OFMutableSet set];

		for (Method *iter = methods; *iter != NULL; iter++) {
			SEL selector = method_getName(*iter);
			void *pool;
			OFMethodSignature *sig;

			if (selector == NULL)
				continue;

			if (strncmp(sel_getName(selector), "test", 4) != 0)
				continue;

			pool = objc_autoreleasePoolPush();
			sig = [OFMethodSignature signatureWithObjCTypes:
			    method_getTypeEncoding(*iter)];

			if (strcmp(sig.methodReturnType, "v") == 0 &&
			    sig.numberOfArguments == 2 &&
			    strcmp([sig argumentTypeAtIndex: 0], "@") == 0 &&
			    strcmp([sig argumentTypeAtIndex: 1], ":") == 0)
				[tests addObject:
				    [OFValue valueWithPointer: selector]];

			objc_autoreleasePoolPop(pool);
		}
	} @finally {
		OFFreeMemory(methods);
	}

	if (class_getSuperclass(class) != Nil)
		[tests unionSet:
		    [self testsInClass: class_getSuperclass(class)]];

	[tests makeImmutable];
	return tests;
}

- (void)printStatusForTest: (SEL)test
		   inClass: (Class)class
		    status: (int)status
	       description: (OFString *)description
{
	switch (status) {
	case 0:
		[OFStdOut setForegroundColor: [OFColor olive]];
		[OFStdOut writeFormat: @"-[%@ ", class];
		[OFStdOut setForegroundColor: [OFColor yellow]];
		[OFStdOut writeFormat: @"%s", sel_getName(test)];
		[OFStdOut setForegroundColor: [OFColor olive]];
		[OFStdOut writeString: @"]: "];
		break;
	case 1:
		[OFStdOut setForegroundColor: [OFColor green]];
		[OFStdOut writeFormat: @"\r-[%@ ", class];
		[OFStdOut setForegroundColor: [OFColor lime]];
		[OFStdOut writeFormat: @"%s", sel_getName(test)];
		[OFStdOut setForegroundColor: [OFColor green]];
		[OFStdOut writeLine: @"]: ok"];
		break;
	case 2:
		[OFStdOut setForegroundColor: [OFColor maroon]];
		[OFStdOut writeFormat: @"\r-[%@ ", class];
		[OFStdOut setForegroundColor: [OFColor red]];
		[OFStdOut writeFormat: @"%s", sel_getName(test)];
		[OFStdOut setForegroundColor: [OFColor maroon]];
		[OFStdOut writeLine: @"]: failed"];
		[OFStdOut writeLine: description];
		break;
	}

	[OFStdOut reset];
}

- (void)applicationDidFinishLaunching: (OFNotification *)notification
{
	OFSet OF_GENERIC(Class) *testClasses = [self testClasses];
	size_t numSucceeded = 0, numFailed = 0;

	[OFStdOut writeFormat: @"Running %zu test case(s)\n",
			       testClasses.count];

	for (Class class in testClasses) {
		[OFStdOut setForegroundColor: [OFColor teal]];
		[OFStdOut writeFormat: @"Running ", class];
		[OFStdOut setForegroundColor: [OFColor aqua]];
		[OFStdOut writeFormat: @"%@\n", class];
		[OFStdOut reset];

		for (OFValue *test in [self testsInClass: class]) {
			void *pool = objc_autoreleasePoolPush();
			bool failed = false;
			OTTestCase *instance;

			[self printStatusForTest: test.pointerValue
					 inClass: class
					  status: 0
				     description: nil];

			instance = [[[class alloc] init] autorelease];

			@try {
				[instance setUp];
				[instance performSelector: test.pointerValue];
			} @catch (OTAssertionFailedException *e) {
				/*
				 * If an assertion fails during -[setUp], don't
				 * run the test.
				 * If an assertion fails during a test, abort
				 * the test.
				 */
				[self printStatusForTest: test.pointerValue
						 inClass: class
						  status: 2
					     description: e.description];
				failed = true;
			}
			@try {
				[instance tearDown];
			} @catch (OTAssertionFailedException *e) {
				/*
				 * If an assertion fails during -[tearDown],
				 * abort the tear down.
				 */
				if (!failed) {
					SEL selector = test.pointerValue;
					OFString *description = e.description;

					[self printStatusForTest: selector
							 inClass: class
							  status: 2
						     description: description];
					failed = true;
				}
			}

			if (!failed) {
				[self printStatusForTest: test.pointerValue
						 inClass: class
						  status: 1
					     description: nil];
				numSucceeded++;
			} else
				numFailed++;

			objc_autoreleasePoolPop(pool);
		}
	}

	[OFStdOut setForegroundColor: [OFColor fuchsia]];
	[OFStdOut writeFormat: @"%zu", numSucceeded];
	[OFStdOut setForegroundColor: [OFColor purple]];
	[OFStdOut writeString: @" test(s) succeeded, "];
	[OFStdOut setForegroundColor: [OFColor fuchsia]];
	[OFStdOut writeFormat: @"%zu", numFailed];
	[OFStdOut setForegroundColor: [OFColor purple]];
	[OFStdOut writeLine: @" test(s) failed."];
	[OFStdOut reset];

	[OFApplication terminateWithStatus: (int)numFailed];
}
@end

Added src/test/OTAssert.h version [4079f8ef1f].





























































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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-2024 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the 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.
 */

/*
 * Unfortunately, that's the only way to make all compilers happy with the GNU
 * extensions for variadic macros that are being used here.
 */
#pragma GCC system_header

#define OTAssert(cond, ...) \
	OTAssertImpl(self, _cmd, cond, @#cond, @__FILE__, __LINE__,	\
	    ## __VA_ARGS__, nil)
#define OTAssertTrue(cond, ...) OTAssert(cond == true, ## __VA_ARGS__)
#define OTAssertFalse(cond, ...) OTAssert(cond == false, ## __VA_ARGS__)
#define OTAssertEqual(a, b, ...) OTAssert(a == b, ## __VA_ARGS__)
#define OTAssertNotEqual(a, b, ...) OTAssert(a != b, ## __VA_ARGS__)
#define OTAssertEqualObjects(a, b, ...) OTAssert([a isEqual: b], ## __VA_ARGS__)
#define OTAssertNotEqualObjects(a, b, ...) \
	OTAssert(![a isEqual: b], ## __VA_ARGS__)
#define OTAssertNil(object, ...) OTAssert(object == nil, ## __VA_ARGS__)
#define OTAssertNotNil(object, ...) OTAssert(object != nil, ## __VA_ARGS__)
#define OTAssertThrows(expression, ...)				\
	{							\
		bool OTThrown = false;				\
		@try {						\
			expression;				\
		} @catch (id e) {				\
			OTThrown = true;			\
		}						\
		OTAssert(OTThrown, ## __VA_ARGS__);		\
	}
#define OTAssertThrowsSpecific(expression, exception, ...)	\
	{							\
		bool OTThrown = false;				\
		@try {						\
			expression;				\
		} @catch (exception *e) {			\
			OTThrown = true;			\
		}						\
		OTAssert(OTThrown, ## __VA_ARGS__);		\
	}

#ifdef __cplusplus
extern "C" {
#endif
extern void OTAssertImpl(id testCase, SEL test, bool condition, OFString *check,
    OFString *file, size_t line, ...);
#ifdef __cplusplus
}
#endif

Added src/test/OTAssert.m version [dfc3f7ba82].



























































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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-2024 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the 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 "OTAssertionFailedException.h"

void
OTAssertImpl(id testCase, SEL test, bool condition, OFString *check,
    OFString *file, size_t line, ...)
{
	va_list arguments;
	OFConstantString *format;
	OFString *message = nil;

	if (condition)
		return;

	va_start(arguments, line);
	format = va_arg(arguments, OFConstantString *);

	if (format != nil)
		message = [[[OFString alloc]
		    initWithFormat: format
			 arguments: arguments] autorelease];

	va_end(arguments);

	@throw [OTAssertionFailedException exceptionWithCondition: check
							  message: message];
}

Added src/test/OTAssertionFailedException.h version [434d5612c9].













































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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-2024 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the 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 "OFString.h"

OF_ASSUME_NONNULL_BEGIN

@interface OTAssertionFailedException: OFException
{
	OFString *_condition;
	OFString *_Nullable _message;
}

@property (readonly, nonatomic) OFString *condition;
@property OF_NULLABLE_PROPERTY (readonly, nonatomic) OFString *message;

+ (instancetype)exceptionWithCondition: (OFString *)condition
			       message: (nullable OFString *)message;
+ (instancetype)exception OF_UNAVAILABLE;
- (instancetype)initWithCondition: (OFString *)condition
			  message: (nullable OFString *)message;
- (instancetype)init OF_UNAVAILABLE;
@end

OF_ASSUME_NONNULL_END

Added src/test/OTAssertionFailedException.m version [ca30ea25b3].



















































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
/*
 * Copyright (c) 2008-2024 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the 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 "OTAssertionFailedException.h"

@implementation OTAssertionFailedException
@synthesize condition = _condition, message = _message;

+ (instancetype)exceptionWithCondition: (OFString *)condition
			       message: (OFString *)message
{
	return [[[self alloc] initWithCondition: condition
					message: message] autorelease];
}

+ (instancetype)exception
{
	OF_UNRECOGNIZED_SELECTOR
}

- (instancetype)initWithCondition: (OFString *)condition
			  message: (OFString *)message
{
	self = [super init];

	@try {
		_condition = [condition copy];
		_message = [message copy];
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (instancetype)init
{
	OF_INVALID_INIT_METHOD
}

- (void)dealloc
{
	[_condition release];
	[_message release];

	[super dealloc];
}

- (OFString *)description
{
	if (_message != nil)
		return [OFString stringWithFormat: @"Assertion failed: %@: %@",
						   _condition, _message];
	else
		return [OFString stringWithFormat: @"Assertion failed: %@",
						   _condition];
}
@end

Added src/test/OTTestCase.h version [2add704de5].



























































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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-2024 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the 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.
 */

#ifdef OBJFWTEST_LOCAL_INCLUDES
# import "OFObject.h"
#else
# import <ObjFW/OFObject.h>
#endif

OF_ASSUME_NONNULL_BEGIN

@interface OTTestCase: OFObject
- (void)setUp;
- (void)tearDown;
@end

OF_ASSUME_NONNULL_END

Added src/test/OTTestCase.m version [3c3d45f200].

























































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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-2024 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the 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 "OTTestCase.h"

@implementation OTTestCase: OFObject
- (void)setUp
{
}

- (void)tearDown
{
}
@end

Added src/test/ObjFWTest.h version [c6fa64803a].



































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/*
 * Copyright (c) 2008-2024 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the 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 "OTTestCase.h"
#import "OTAssert.h"

Added src/test/ObjFWTest.oc version [d1ccd75e86].







>
>
>
1
2
3
package_format 1
LIBS="-lobjfwtest $LIBS"
FRAMEWORK_LIBS="-lobjfwtest $FRAMEWORK_LIBS"

Modified src/tls/OFGnuTLSTLSStream.m from [570186048d] to [25d18fe2f0].

192
193
194
195
196
197
198

199
200
201
202
203
204
205
}

- (void)asyncPerformClientHandshakeWithHost: (OFString *)host
				runLoopMode: (OFRunLoopMode)runLoopMode
{
	static const OFTLSStreamErrorCode initFailedErrorCode =
	    OFTLSStreamErrorCodeInitializationFailed;

	id exception = nil;
	int status;

	if (_initialized)
		@throw [OFAlreadyOpenException exceptionWithObject: self];

	if (gnutls_init(&_session, GNUTLS_CLIENT | GNUTLS_NONBLOCK |







>







192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
}

- (void)asyncPerformClientHandshakeWithHost: (OFString *)host
				runLoopMode: (OFRunLoopMode)runLoopMode
{
	static const OFTLSStreamErrorCode initFailedErrorCode =
	    OFTLSStreamErrorCodeInitializationFailed;
	void *pool = objc_autoreleasePoolPush();
	id exception = nil;
	int status;

	if (_initialized)
		@throw [OFAlreadyOpenException exceptionWithObject: self];

	if (gnutls_init(&_session, GNUTLS_CLIENT | GNUTLS_NONBLOCK |
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
					      runLoopMode: runLoopMode];
		else
			[_underlyingStream asyncReadIntoBuffer: (void *)""
							length: 0
						   runLoopMode: runLoopMode];

		[_delegate retain];

		return;
	}

	if (status == GNUTLS_E_SUCCESS)
		_handshakeDone = true;
	else
		/* FIXME: Map to better errors */
		exception = [OFTLSHandshakeFailedException
		    exceptionWithStream: self
				   host: host
			      errorCode: OFTLSStreamErrorCodeUnknown];

	if ([_delegate respondsToSelector:
	    @selector(stream:didPerformClientHandshakeWithHost:exception:)])
		[_delegate		       stream: self
		    didPerformClientHandshakeWithHost: host
					    exception: exception];


}

-      (bool)stream: (OFStream *)stream
  didReadIntoBuffer: (void *)buffer
	     length: (size_t)length
	  exception: (id)exception
{







>

















>
>







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
					      runLoopMode: runLoopMode];
		else
			[_underlyingStream asyncReadIntoBuffer: (void *)""
							length: 0
						   runLoopMode: runLoopMode];

		[_delegate retain];
		objc_autoreleasePoolPop(pool);
		return;
	}

	if (status == GNUTLS_E_SUCCESS)
		_handshakeDone = true;
	else
		/* FIXME: Map to better errors */
		exception = [OFTLSHandshakeFailedException
		    exceptionWithStream: self
				   host: host
			      errorCode: OFTLSStreamErrorCodeUnknown];

	if ([_delegate respondsToSelector:
	    @selector(stream:didPerformClientHandshakeWithHost:exception:)])
		[_delegate		       stream: self
		    didPerformClientHandshakeWithHost: host
					    exception: exception];

	objc_autoreleasePoolPop(pool);
}

-      (bool)stream: (OFStream *)stream
  didReadIntoBuffer: (void *)buffer
	     length: (size_t)length
	  exception: (id)exception
{

Modified src/tls/OFMbedTLSTLSStream.h from [b21f7f1267] to [9e5643f69d].

20
21
22
23
24
25
26

27
28
29
30
31
OF_ASSUME_NONNULL_BEGIN

@interface OFMbedTLSTLSStream: OFTLSStream <OFStreamDelegate>
{
	bool _initialized, _handshakeDone;
	mbedtls_ssl_config _config;
	mbedtls_ssl_context _SSL;

	OFString *_host;
}
@end

OF_ASSUME_NONNULL_END







>





20
21
22
23
24
25
26
27
28
29
30
31
32
OF_ASSUME_NONNULL_BEGIN

@interface OFMbedTLSTLSStream: OFTLSStream <OFStreamDelegate>
{
	bool _initialized, _handshakeDone;
	mbedtls_ssl_config _config;
	mbedtls_ssl_context _SSL;
	mbedtls_x509_crt _CAChain;
	OFString *_host;
}
@end

OF_ASSUME_NONNULL_END

Modified src/tls/OFMbedTLSTLSStream.m from [14845fbfc0] to [0265ea26a9].

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

#include "config.h"

#include <errno.h>

#import "OFMbedTLSTLSStream.h"

#import "OFData.h"



#import "OFAlreadyOpenException.h"
#import "OFInitializationFailedException.h"
#import "OFNotOpenException.h"
#import "OFOutOfRangeException.h"
#import "OFReadFailedException.h"
#import "OFTLSHandshakeFailedException.h"
#import "OFWriteFailedException.h"

#include <mbedtls/ctr_drbg.h>
#include <mbedtls/entropy.h>

int _ObjFWTLS_reference;
static mbedtls_entropy_context entropy;
static mbedtls_ctr_drbg_context CTRDRBG;
static mbedtls_x509_crt CAChain;

@implementation OFMbedTLSTLSStream
static int
readFunc(void *ctx, unsigned char *buffer, size_t length)
{
	OFMbedTLSTLSStream *stream = (OFMbedTLSTLSStream *)ctx;








>

>
>















<







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

#include "config.h"

#include <errno.h>

#import "OFMbedTLSTLSStream.h"
#import "OFApplication.h"
#import "OFData.h"
#import "OFDictionary.h"
#import "OFLocale.h"

#import "OFAlreadyOpenException.h"
#import "OFInitializationFailedException.h"
#import "OFNotOpenException.h"
#import "OFOutOfRangeException.h"
#import "OFReadFailedException.h"
#import "OFTLSHandshakeFailedException.h"
#import "OFWriteFailedException.h"

#include <mbedtls/ctr_drbg.h>
#include <mbedtls/entropy.h>

int _ObjFWTLS_reference;
static mbedtls_entropy_context entropy;
static mbedtls_ctr_drbg_context CTRDRBG;


@implementation OFMbedTLSTLSStream
static int
readFunc(void *ctx, unsigned char *buffer, size_t length)
{
	OFMbedTLSTLSStream *stream = (OFMbedTLSTLSStream *)ctx;

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

	mbedtls_entropy_init(&entropy);
	if (mbedtls_ctr_drbg_seed(&CTRDRBG, mbedtls_entropy_func, &entropy,
	    NULL, 0) != 0)
		@throw [OFInitializationFailedException
		    exceptionWithClass: self];

	mbedtls_x509_crt_init(&CAChain);
	if (mbedtls_x509_crt_parse_file(&CAChain, OF_MBEDTLS_CA_PATH) != 0)
		@throw [OFInitializationFailedException
		    exceptionWithClass: self];
}

- (instancetype)initWithStream: (OFStream <OFReadyForReadingObserving,
				     OFReadyForWritingObserving> *)stream
{
	self = [super initWithStream: stream];

	@try {
		_underlyingStream.delegate = self;


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

	return self;
}

- (void)dealloc
{
	if (_initialized)
		[self close];

	[_host release];



	[super dealloc];
}

- (void)close
{
	if (!_initialized)







<
<
<
<
<









>
>














>
>







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

	mbedtls_entropy_init(&entropy);
	if (mbedtls_ctr_drbg_seed(&CTRDRBG, mbedtls_entropy_func, &entropy,
	    NULL, 0) != 0)
		@throw [OFInitializationFailedException
		    exceptionWithClass: self];





}

- (instancetype)initWithStream: (OFStream <OFReadyForReadingObserving,
				     OFReadyForWritingObserving> *)stream
{
	self = [super initWithStream: stream];

	@try {
		_underlyingStream.delegate = self;

		mbedtls_x509_crt_init(&_CAChain);
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (void)dealloc
{
	if (_initialized)
		[self close];

	[_host release];

	mbedtls_x509_crt_free(&_CAChain);

	[super dealloc];
}

- (void)close
{
	if (!_initialized)
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
}

- (void)asyncPerformClientHandshakeWithHost: (OFString *)host
				runLoopMode: (OFRunLoopMode)runLoopMode
{
	static const OFTLSStreamErrorCode initFailedErrorCode =
	    OFTLSStreamErrorCodeInitializationFailed;


	id exception = nil;
	int status;

	if (_initialized)
		@throw [OFAlreadyOpenException exceptionWithObject: self];

	if (mbedtls_ssl_config_defaults(&_config, MBEDTLS_SSL_IS_CLIENT,
	    MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT) != 0)
		@throw [OFTLSHandshakeFailedException
		    exceptionWithStream: self
				   host: host
			      errorCode: initFailedErrorCode];

	mbedtls_ssl_conf_rng(&_config, mbedtls_ctr_drbg_random, &CTRDRBG);
	mbedtls_ssl_conf_authmode(&_config, (_verifiesCertificates
	    ? MBEDTLS_SSL_VERIFY_REQUIRED : MBEDTLS_SSL_VERIFY_NONE));













	mbedtls_ssl_conf_ca_chain(&_config, &CAChain, NULL);

	mbedtls_ssl_init(&_SSL);
	if (mbedtls_ssl_setup(&_SSL, &_config) != 0)
		@throw [OFTLSHandshakeFailedException
		    exceptionWithStream: self
				   host: host
			      errorCode: initFailedErrorCode];







>
>
















>
>
>
>
>
>
>
>
>
>
>
>
>
|







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
}

- (void)asyncPerformClientHandshakeWithHost: (OFString *)host
				runLoopMode: (OFRunLoopMode)runLoopMode
{
	static const OFTLSStreamErrorCode initFailedErrorCode =
	    OFTLSStreamErrorCodeInitializationFailed;
	void *pool = objc_autoreleasePoolPush();
	OFString *CAFilePath;
	id exception = nil;
	int status;

	if (_initialized)
		@throw [OFAlreadyOpenException exceptionWithObject: self];

	if (mbedtls_ssl_config_defaults(&_config, MBEDTLS_SSL_IS_CLIENT,
	    MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT) != 0)
		@throw [OFTLSHandshakeFailedException
		    exceptionWithStream: self
				   host: host
			      errorCode: initFailedErrorCode];

	mbedtls_ssl_conf_rng(&_config, mbedtls_ctr_drbg_random, &CTRDRBG);
	mbedtls_ssl_conf_authmode(&_config, (_verifiesCertificates
	    ? MBEDTLS_SSL_VERIFY_REQUIRED : MBEDTLS_SSL_VERIFY_NONE));

	/* TODO: Add other ways to add a CA chain */
	CAFilePath = [[OFApplication environment]
	    objectForKey: @"OBJFW_MBEDTLS_CA_PATH"];
	if (CAFilePath != nil) {
		if (mbedtls_x509_crt_parse_file(&_CAChain,
		    [CAFilePath cStringWithEncoding: [OFLocale encoding]]) != 0)
			@throw [OFTLSHandshakeFailedException
			    exceptionWithStream: self
					   host: host
				      errorCode: initFailedErrorCode];
	}

	mbedtls_ssl_conf_ca_chain(&_config, &_CAChain, NULL);

	mbedtls_ssl_init(&_SSL);
	if (mbedtls_ssl_setup(&_SSL, &_config) != 0)
		@throw [OFTLSHandshakeFailedException
		    exceptionWithStream: self
				   host: host
			      errorCode: initFailedErrorCode];
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
	status = mbedtls_ssl_handshake(&_SSL);

	if (status == MBEDTLS_ERR_SSL_WANT_READ) {
		[_underlyingStream asyncReadIntoBuffer: (void *)""
						length: 0
					   runLoopMode: runLoopMode];
		[_delegate retain];

		return;
	} else if (status == MBEDTLS_ERR_SSL_WANT_WRITE) {
		[_underlyingStream asyncWriteData: [OFData data]
				      runLoopMode: runLoopMode];
		[_delegate retain];

		return;
	}

	if (status == 0)
		_handshakeDone = true;
	else
		/* FIXME: Map to better errors */
		exception = [OFTLSHandshakeFailedException
		    exceptionWithStream: self
				   host: host
			      errorCode: OFTLSStreamErrorCodeUnknown];

	if ([_delegate respondsToSelector:
	    @selector(stream:didPerformClientHandshakeWithHost:exception:)])
		[_delegate		       stream: self
		    didPerformClientHandshakeWithHost: host
					    exception: exception];


}

-      (bool)stream: (OFStream *)stream
  didReadIntoBuffer: (void *)buffer
	     length: (size_t)length
	  exception: (id)exception
{







>





>

















>
>







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
	status = mbedtls_ssl_handshake(&_SSL);

	if (status == MBEDTLS_ERR_SSL_WANT_READ) {
		[_underlyingStream asyncReadIntoBuffer: (void *)""
						length: 0
					   runLoopMode: runLoopMode];
		[_delegate retain];
		objc_autoreleasePoolPop(pool);
		return;
	} else if (status == MBEDTLS_ERR_SSL_WANT_WRITE) {
		[_underlyingStream asyncWriteData: [OFData data]
				      runLoopMode: runLoopMode];
		[_delegate retain];
		objc_autoreleasePoolPop(pool);
		return;
	}

	if (status == 0)
		_handshakeDone = true;
	else
		/* FIXME: Map to better errors */
		exception = [OFTLSHandshakeFailedException
		    exceptionWithStream: self
				   host: host
			      errorCode: OFTLSStreamErrorCodeUnknown];

	if ([_delegate respondsToSelector:
	    @selector(stream:didPerformClientHandshakeWithHost:exception:)])
		[_delegate		       stream: self
		    didPerformClientHandshakeWithHost: host
					    exception: exception];

	objc_autoreleasePoolPop(pool);
}

-      (bool)stream: (OFStream *)stream
  didReadIntoBuffer: (void *)buffer
	     length: (size_t)length
	  exception: (id)exception
{

Modified src/tls/OFOpenSSLTLSStream.m from [acd160399f] to [2423ed840a].

210
211
212
213
214
215
216

217
218
219
220
221
222
223
}

- (void)asyncPerformClientHandshakeWithHost: (OFString *)host
				runLoopMode: (OFRunLoopMode)runLoopMode
{
	static const OFTLSStreamErrorCode initFailedErrorCode =
	    OFTLSStreamErrorCodeInitializationFailed;

	id exception = nil;
	int status;

	if (_SSL != NULL)
		@throw [OFAlreadyOpenException exceptionWithObject: self];

	if ((_readBIO = BIO_new(BIO_s_mem())) == NULL)







>







210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
}

- (void)asyncPerformClientHandshakeWithHost: (OFString *)host
				runLoopMode: (OFRunLoopMode)runLoopMode
{
	static const OFTLSStreamErrorCode initFailedErrorCode =
	    OFTLSStreamErrorCodeInitializationFailed;
	void *pool = objc_autoreleasePoolPush();
	id exception = nil;
	int status;

	if (_SSL != NULL)
		@throw [OFAlreadyOpenException exceptionWithObject: self];

	if ((_readBIO = BIO_new(BIO_s_mem())) == NULL)
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
	else {
		switch (SSL_get_error(_SSL, status)) {
		case SSL_ERROR_WANT_READ:
			[_underlyingStream asyncReadIntoBuffer: _buffer
							length: bufferSize
						   runLoopMode: runLoopMode];
			[_delegate retain];

			return;
		case SSL_ERROR_WANT_WRITE:
			[_underlyingStream asyncWriteData: [OFData data]
					      runLoopMode: runLoopMode];
			[_delegate retain];

			return;
		default:
			/* FIXME: Map to better errors */
			exception = [OFTLSHandshakeFailedException
			    exceptionWithStream: self
					   host: host
				      errorCode: OFTLSStreamErrorCodeUnknown];
			break;
		}
	}

	if ([_delegate respondsToSelector:
	    @selector(stream:didPerformClientHandshakeWithHost:exception:)])
		[_delegate		       stream: self
		    didPerformClientHandshakeWithHost: host
					    exception: exception];


}

-      (bool)stream: (OFStream *)stream
  didReadIntoBuffer: (void *)buffer
	     length: (size_t)length
	  exception: (nullable id)exception
{







>





>
















>
>







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
	else {
		switch (SSL_get_error(_SSL, status)) {
		case SSL_ERROR_WANT_READ:
			[_underlyingStream asyncReadIntoBuffer: _buffer
							length: bufferSize
						   runLoopMode: runLoopMode];
			[_delegate retain];
			objc_autoreleasePoolPop(pool);
			return;
		case SSL_ERROR_WANT_WRITE:
			[_underlyingStream asyncWriteData: [OFData data]
					      runLoopMode: runLoopMode];
			[_delegate retain];
			objc_autoreleasePoolPop(pool);
			return;
		default:
			/* FIXME: Map to better errors */
			exception = [OFTLSHandshakeFailedException
			    exceptionWithStream: self
					   host: host
				      errorCode: OFTLSStreamErrorCodeUnknown];
			break;
		}
	}

	if ([_delegate respondsToSelector:
	    @selector(stream:didPerformClientHandshakeWithHost:exception:)])
		[_delegate		       stream: self
		    didPerformClientHandshakeWithHost: host
					    exception: exception];

	objc_autoreleasePoolPop(pool);
}

-      (bool)stream: (OFStream *)stream
  didReadIntoBuffer: (void *)buffer
	     length: (size_t)length
	  exception: (nullable id)exception
{

Modified src/tls/OFSecureTransportTLSStream.m from [b218de48f5] to [57e790b2b8].

178
179
180
181
182
183
184

185
186
187
188
189
190
191
}

- (void)asyncPerformClientHandshakeWithHost: (OFString *)host
				runLoopMode: (OFRunLoopMode)runLoopMode
{
	static const OFTLSStreamErrorCode initFailedErrorCode =
	    OFTLSStreamErrorCodeInitializationFailed;

	id exception = nil;
	OSStatus status;

	if (_context != NULL)
		@throw [OFAlreadyOpenException exceptionWithObject: self];

#ifdef HAVE_SSLCREATECONTEXT







>







178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
}

- (void)asyncPerformClientHandshakeWithHost: (OFString *)host
				runLoopMode: (OFRunLoopMode)runLoopMode
{
	static const OFTLSStreamErrorCode initFailedErrorCode =
	    OFTLSStreamErrorCodeInitializationFailed;
	void *pool = objc_autoreleasePoolPush();
	id exception = nil;
	OSStatus status;

	if (_context != NULL)
		@throw [OFAlreadyOpenException exceptionWithObject: self];

#ifdef HAVE_SSLCREATECONTEXT
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
		 * readable or writable doesn't work either, as the stream is
		 * almost always at least ready for one of the two.
		 */
		[_underlyingStream asyncReadIntoBuffer: (void *)"" 
						length: 0
					   runLoopMode: runLoopMode];
		[_delegate retain];

		return;
	}

	if (status != noErr)
		/* FIXME: Map to better errors */
		exception = [OFTLSHandshakeFailedException
		    exceptionWithStream: self
				   host: _host
			      errorCode: OFTLSStreamErrorCodeUnknown];

	if ([_delegate respondsToSelector:
	    @selector(stream:didPerformClientHandshakeWithHost:exception:)])
		[_delegate		       stream: self
		    didPerformClientHandshakeWithHost: _host
					    exception: exception];


}

-      (bool)stream: (OFStream *)stream
  didReadIntoBuffer: (void *)buffer
	     length: (size_t)length
	  exception: (nullable id)exception
{







>















>
>







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
		 * readable or writable doesn't work either, as the stream is
		 * almost always at least ready for one of the two.
		 */
		[_underlyingStream asyncReadIntoBuffer: (void *)"" 
						length: 0
					   runLoopMode: runLoopMode];
		[_delegate retain];
		objc_autoreleasePoolPop(pool);
		return;
	}

	if (status != noErr)
		/* FIXME: Map to better errors */
		exception = [OFTLSHandshakeFailedException
		    exceptionWithStream: self
				   host: _host
			      errorCode: OFTLSStreamErrorCodeUnknown];

	if ([_delegate respondsToSelector:
	    @selector(stream:didPerformClientHandshakeWithHost:exception:)])
		[_delegate		       stream: self
		    didPerformClientHandshakeWithHost: _host
					    exception: exception];

	objc_autoreleasePoolPop(pool);
}

-      (bool)stream: (OFStream *)stream
  didReadIntoBuffer: (void *)buffer
	     length: (size_t)length
	  exception: (nullable id)exception
{

Modified tests/Makefile from [b7f0a6995a] to [a72949f202].

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
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	\
	testfile_bin.m		\
	testfile_ini.m
DISTCLEAN = Info.plist

PROG_NOINST = tests${PROG_SUFFIX}
STATIC_LIB_NOINST = ${TESTS_STATIC_LIB}
SRCS = ForwardingTests.m		\
       OFASN1DERParsingTests.m		\
       OFASN1DERRepresentationTests.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			\
       OFSetTests.m			\
       OFStreamTests.m			\
       OFStringTests.m			\
       OFSystemInfoTests.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}		\
       testfile_bin.m			\
       testfile_ini.m
SRCS_PLUGINS = OFPluginTests.m
SRCS_SOCKETS = OFDNSResolverTests.m		\
	       ${OF_HTTP_CLIENT_TESTS_M}	\
	       OFHTTPCookieTests.m		\
	       OFHTTPCookieManagerTests.m	\
	       OFKernelEventObserverTests.m	\
	       OFSocketTests.m			\
	       OFTCPSocketTests.m		\
	       OFUDPSocketTests.m		\
	       ${USE_SRCS_APPLETALK}		\
	       ${USE_SRCS_IPX}			\
	       ${USE_SRCS_UNIX_SOCKETS}
SRCS_APPLETALK = OFDDPSocketTests.m
SRCS_IPX = OFIPXSocketTests.m		\
	   OFSPXSocketTests.m		\
	   OFSPXStreamSocketTests.m
SRCS_UNIX_SOCKETS = OFUNIXDatagramSocketTests.m	\
		    OFUNIXStreamSocketTests.m
SRCS_THREADS = OFThreadTests.m
SRCS_WINDOWS = OFWindowsRegistryKeyTests.m

IOS_USER ?= mobile
IOS_TMP ?= /tmp/objfw-test

include ../buildsys.mk

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:
	rm -f libobjfw.so.${OBJFW_LIB_MAJOR}
	rm -f libobjfw.so.${OBJFW_LIB_MAJOR_MINOR}
	rm -f objfw${OBJFW_LIB_MAJOR}.dll libobjfw.${OBJFW_LIB_MAJOR}.dylib
	rm -f libobjfwrt.so.${OBJFWRT_LIB_MAJOR}
	rm -f libobjfwrt.so.${OBJFWRT_LIB_MAJOR_MINOR}


<
|







|
<
<







<

<
<

<

<
<
<
<
<


<
<

<

<

<
<
<
<
<
<
<
<
<












<

<
|
<
<
<





<











<







<
<
<
<
<







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
include ../extra.mk


SUBDIRS = ${OBJC_SYNC}	\
	  terminal

CLEAN = EBOOT.PBP		\
	boot.dol		\
	${PROG_NOINST}.arm9	\
	${PROG_NOINST}.nds	\
	${PROG_NOINST}.nro	\
	${PROG_NOINST}.rpx


DISTCLEAN = Info.plist

PROG_NOINST = tests${PROG_SUFFIX}
STATIC_LIB_NOINST = ${TESTS_STATIC_LIB}
SRCS = ForwardingTests.m		\
       OFASN1DERParsingTests.m		\
       OFASN1DERRepresentationTests.m	\

       ${OF_BLOCK_TESTS_M}		\


       OFDataTests.m			\

       OFDictionaryTests.m		\





       OFListTests.m			\
       OFLocaleTests.m			\


       OFMemoryStreamTests.m		\

       OFNotificationCenterTests.m	\

       OFObjectTests.m			\









       OFSetTests.m			\
       OFStreamTests.m			\
       OFStringTests.m			\
       OFSystemInfoTests.m		\
       OFValueTests.m			\
       OFXMLElementBuilderTests.m	\
       OFXMLNodeTests.m			\
       OFXMLParserTests.m		\
       RuntimeTests.m			\
       ${RUNTIME_ARC_TESTS_M}		\
       TestsAppDelegate.m		\
       ${USE_SRCS_FILES}		\

       ${USE_SRCS_SOCKETS}		\

       ${USE_SRCS_WINDOWS}



SRCS_SOCKETS = OFDNSResolverTests.m		\
	       ${OF_HTTP_CLIENT_TESTS_M}	\
	       OFHTTPCookieTests.m		\
	       OFHTTPCookieManagerTests.m	\
	       OFKernelEventObserverTests.m	\

	       OFTCPSocketTests.m		\
	       OFUDPSocketTests.m		\
	       ${USE_SRCS_APPLETALK}		\
	       ${USE_SRCS_IPX}			\
	       ${USE_SRCS_UNIX_SOCKETS}
SRCS_APPLETALK = OFDDPSocketTests.m
SRCS_IPX = OFIPXSocketTests.m		\
	   OFSPXSocketTests.m		\
	   OFSPXStreamSocketTests.m
SRCS_UNIX_SOCKETS = OFUNIXDatagramSocketTests.m	\
		    OFUNIXStreamSocketTests.m

SRCS_WINDOWS = OFWindowsRegistryKeyTests.m

IOS_USER ?= mobile
IOS_TMP ?= /tmp/objfw-test

include ../buildsys.mk






.PHONY: run run-on-ios run-on-android
run:
	rm -f libobjfw.so.${OBJFW_LIB_MAJOR}
	rm -f libobjfw.so.${OBJFW_LIB_MAJOR_MINOR}
	rm -f objfw${OBJFW_LIB_MAJOR}.dll libobjfw.${OBJFW_LIB_MAJOR}.dylib
	rm -f libobjfwrt.so.${OBJFWRT_LIB_MAJOR}
	rm -f libobjfwrt.so.${OBJFWRT_LIB_MAJOR_MINOR}
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
	rm -f libobjfw.${OBJFW_LIB_MAJOR}.dylib; \
	rm -f libobjfwrt.so.${OBJFWRT_LIB_MAJOR}; \
	rm -f libobjfwrt.so.${OBJFWRT_LIB_MAJOR_MINOR}; \
	rm -f objfwrt${OBJFWRT_LIB_MAJOR}.dll; \
	rm -f libobjfwrt.${OBJFWRT_LIB_MAJOR}.dylib; \
	exit $$EXIT

run-on-ios: all
	if [ -z "${IOS_HOST}" ]; then \
		echo "Please set IOS_HOST to the hostname of your iOS host!"; \
		exit 1; \
	fi
	echo "Uploading files to iOS device ${IOS_HOST} at ${IOS_TMP}..."
	ssh ${IOS_USER}@${IOS_HOST} \
	    'rm -fr ${IOS_TMP} && mkdir -p ${IOS_TMP}/plugin'
	destname=libobjfw.${OBJFW_LIB_MAJOR}.dylib; \
	scp -q ../src/libobjfw.dylib \
	    ${IOS_USER}@${IOS_HOST}:${IOS_TMP}/$$destname
	scp -q tests testfile.txt ${IOS_USER}@${IOS_HOST}:${IOS_TMP}/
	scp -q plugin/TestPlugin.bundle \
	    ${IOS_USER}@${IOS_HOST}:${IOS_TMP}/plugin/
	echo "Running tests binary on iOS device ${IOS_HOST}..."
	ssh ${IOS_USER}@${IOS_HOST} \
	    'cd ${IOS_TMP} && DYLD_LIBRARY_PATH=. ${WRAPPER} ./tests'

run-on-android: all
	echo "Uploading files to Android device..."
	if test -f ../src/libobjfw.so; then \
		adb push ../src/libobjfw.so \
		    /data/local/tmp/objfw/libobjfw.so.${OBJFW_LIB_MAJOR}; \
	fi
	if test -f ../src/runtime/libobjfwrt.so; then \
		adb push ../src/runtime/libobjfwrt.so \
		    /data/local/tmp/objfw/libobjfwrt.so.${OBJFWRT_LIB_MAJOR}; \
	fi
	adb push tests /data/local/tmp/objfw/tests
	adb push testfile.txt /data/local/tmp/objfw/testfile.txt
	if test -f plugin/TestPlugin.so; then \
		adb push plugin/TestPlugin.so \
		    /data/local/tmp/objfw/plugin/TestPlugin.so; \
	fi
	echo "Running tests binary on Android device..."
	adb shell 'cd /data/local/tmp/objfw && LD_LIBRARY_PATH=. exec ${WRAPPER} ./tests'

EBOOT.PBP: ${PROG_NOINST}
	psp-fixup-imports ${PROG_NOINST}
	mksfo "ObjFW Tests" PARAM.SFO
	psp-strip ${PROG_NOINST}







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












<
<
<
<







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
	rm -f libobjfw.${OBJFW_LIB_MAJOR}.dylib; \
	rm -f libobjfwrt.so.${OBJFWRT_LIB_MAJOR}; \
	rm -f libobjfwrt.so.${OBJFWRT_LIB_MAJOR_MINOR}; \
	rm -f objfwrt${OBJFWRT_LIB_MAJOR}.dll; \
	rm -f libobjfwrt.${OBJFWRT_LIB_MAJOR}.dylib; \
	exit $$EXIT



















run-on-android: all
	echo "Uploading files to Android device..."
	if test -f ../src/libobjfw.so; then \
		adb push ../src/libobjfw.so \
		    /data/local/tmp/objfw/libobjfw.so.${OBJFW_LIB_MAJOR}; \
	fi
	if test -f ../src/runtime/libobjfwrt.so; then \
		adb push ../src/runtime/libobjfwrt.so \
		    /data/local/tmp/objfw/libobjfwrt.so.${OBJFWRT_LIB_MAJOR}; \
	fi
	adb push tests /data/local/tmp/objfw/tests
	adb push testfile.txt /data/local/tmp/objfw/testfile.txt




	echo "Running tests binary on Android device..."
	adb shell 'cd /data/local/tmp/objfw && LD_LIBRARY_PATH=. exec ${WRAPPER} ./tests'

EBOOT.PBP: ${PROG_NOINST}
	psp-fixup-imports ${PROG_NOINST}
	mksfo "ObjFW Tests" PARAM.SFO
	psp-strip ${PROG_NOINST}
224
225
226
227
228
229
230
231




232
233
234
235
		"${PACKAGE_VERSION}" tests.nacp
	elf2nro ${PROG_NOINST} $@ --nacp=tests.nacp --romfsdir=romfs
	rm -fr romfs tests.nacp

${PROG_NOINST}.rpx: ${PROG_NOINST}
	elf2rpl $< $@

CPPFLAGS += -I../src -I../src/exceptions -I../src/runtime -I.. -DSTDOUT




OBJCFLAGS_RuntimeARCTests.m = -fobjc-arc -fobjc-arc-exceptions
LIBS := ${TESTS_LIBS} ${LIBS}
LDFLAGS += ${MAP_LDFLAGS}
LD = ${OBJC}







|
>
>
>
>




165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
		"${PACKAGE_VERSION}" tests.nacp
	elf2nro ${PROG_NOINST} $@ --nacp=tests.nacp --romfsdir=romfs
	rm -fr romfs tests.nacp

${PROG_NOINST}.rpx: ${PROG_NOINST}
	elf2rpl $< $@

CPPFLAGS += -I../src				\
	    -I../src/exceptions			\
	    -I../src/runtime			\
	    -I..				\
	    -DSTDOUT
OBJCFLAGS_RuntimeARCTests.m = -fobjc-arc -fobjc-arc-exceptions
LIBS := ${TESTS_LIBS} ${LIBS}
LDFLAGS += ${MAP_LDFLAGS}
LD = ${OBJC}

Deleted tests/OFMD5HashTests.m version [96fc59cb59].

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-2024 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the 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 "TestsAppDelegate.h"

static OFString *const module = @"OFMD5Hash";

const uint8_t testFileMD5[16] =
    "\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;
	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];
		[MD5 updateWithBuffer: buffer length: length];
	}
	[file close];

	TEST(@"-[copy]", (MD5Copy = [[MD5 copy] autorelease]))

	TEST(@"-[calculate]", R([MD5 calculate]) && R([MD5Copy calculate]))

	TEST(@"-[digest]",
	    memcmp(MD5.digest, testFileMD5, 16) == 0 &&
	    memcmp(MD5Copy.digest, testFileMD5, 16) == 0)

	EXPECT_EXCEPTION(@"Detect invalid call of "
	    @"-[updateWithBuffer:length]", OFHashAlreadyCalculatedException,
	    [MD5 updateWithBuffer: "" length: 1])

	objc_autoreleasePoolPop(pool);
}
@end
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<






















































































































Deleted tests/OFRIPEMD160HashTests.m version [4768731328].

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
/*
 * Copyright (c) 2008-2024 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the 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 "TestsAppDelegate.h"

static OFString *const module = @"OFRIPEMD160Hash";

const uint8_t testFileRIPEMD160[20] =
	"\x46\x02\x97\xF5\x85\xDF\xB9\x21\x00\xC8\xF9\x87\xC6\xEC\x84\x0D\xCE"
	"\xE6\x08\x8B";

@implementation TestsAppDelegate (OFRIPEMD160HashTests)
- (void)RIPEMD160HashTests
{
	void *pool = objc_autoreleasePoolPush();
	OFRIPEMD160Hash *RIPEMD160, *RIPEMD160Copy;
	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];
		[RIPEMD160 updateWithBuffer: buffer length: length];
	}
	[file close];

	TEST(@"-[copy]", (RIPEMD160Copy = [[RIPEMD160 copy] autorelease]))

	TEST(@"-[calculate]",
	    R([RIPEMD160 calculate]) && R([RIPEMD160Copy calculate]))

	TEST(@"-[digest]",
	    memcmp(RIPEMD160.digest, testFileRIPEMD160, 20) == 0 &&
	    memcmp(RIPEMD160Copy.digest, testFileRIPEMD160, 20) == 0)

	EXPECT_EXCEPTION(@"Detect invalid call of "
	    @"-[updateWithBuffer:length]", OFHashAlreadyCalculatedException,
	    [RIPEMD160 updateWithBuffer: "" length: 1])

	objc_autoreleasePoolPop(pool);
}
@end
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<


























































































































Deleted tests/OFSHA1HashTests.m version [7856801f0e].

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
/*
 * Copyright (c) 2008-2024 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the 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 "TestsAppDelegate.h"

static OFString *const module = @"OFSHA1Hash";

const uint8_t testFileSHA1[20] =
	"\xC9\x9A\xB8\x7E\x1E\xC8\xEC\x65\xD5\xEB\xE4\x2E\x0D\xA6\x80\x96\xF5"
	"\x94\xE7\x17";

@implementation TestsAppDelegate (SHA1HashTests)
- (void)SHA1HashTests
{
	void *pool = objc_autoreleasePoolPush();
	OFSHA1Hash *SHA1, *SHA1Copy;
	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];
		[SHA1 updateWithBuffer: buffer length: length];
	}
	[file close];

	TEST(@"-[copy]", (SHA1Copy = [[SHA1 copy] autorelease]))

	TEST(@"-[calculate]", R([SHA1 calculate]) && R([SHA1Copy calculate]))

	TEST(@"-[digest]",
	    memcmp(SHA1.digest, testFileSHA1, 20) == 0 &&
	    memcmp(SHA1Copy.digest, testFileSHA1, 20) == 0)

	EXPECT_EXCEPTION(@"Detect invalid call of "
	    @"-[updateWithBuffer:length:]", OFHashAlreadyCalculatedException,
	    [SHA1 updateWithBuffer: "" length: 1])

	objc_autoreleasePoolPop(pool);
}
@end
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
























































































































Deleted tests/OFSHA224HashTests.m version [74da8c08a3].

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
/*
 * Copyright (c) 2008-2024 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the 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 "TestsAppDelegate.h"

static OFString *const module = @"OFSHA224Hash";

const uint8_t testFileSHA224[28] =
	"\x27\x69\xD8\x04\x2D\x0F\xCA\x84\x6C\xF1\x62\x44\xBA\x0C\xBD\x46\x64"
	"\x5F\x4F\x20\x02\x4D\x15\xED\x1C\x61\x1F\xF7";

@implementation TestsAppDelegate (SHA224HashTests)
- (void)SHA224HashTests
{
	void *pool = objc_autoreleasePoolPush();
	OFSHA224Hash *SHA224, *SHA224Copy;
	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];
		[SHA224 updateWithBuffer: buffer length: length];
	}
	[file close];

	TEST(@"-[copy]", (SHA224Copy = [[SHA224 copy] autorelease]))

	TEST(@"-[calculate]",
	    R([SHA224 calculate]) && R([SHA224Copy calculate]))

	TEST(@"-[digest]",
	    memcmp(SHA224.digest, testFileSHA224, 28) == 0 &&
	    memcmp(SHA224Copy.digest, testFileSHA224, 28) == 0)

	EXPECT_EXCEPTION(@"Detect invalid call of "
	    @"-[updateWithBuffer:length:]", OFHashAlreadyCalculatedException,
	    [SHA224 updateWithBuffer: "" length: 1])

	objc_autoreleasePoolPop(pool);
}
@end
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<


























































































































Deleted tests/OFSHA256HashTests.m version [1004803a7d].

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
/*
 * Copyright (c) 2008-2024 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the 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 "TestsAppDelegate.h"

static OFString *const module = @"OFSHA256Hash";

const uint8_t testFileSHA256[32] =
	"\x1A\x02\xD6\x46\xF5\xA6\xBA\xAA\xFF\x7F\xD5\x87\xBA\xC3\xF6\xC6\xB5"
	"\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;
	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];
		[SHA256 updateWithBuffer: buffer length: length];
	}
	[file close];

	TEST(@"-[copy]", (SHA256Copy = [[SHA256 copy] autorelease]))

	TEST(@"-[calculate]",
	    R([SHA256 calculate]) && R([SHA256Copy calculate]))

	TEST(@"-[digest]",
	    memcmp(SHA256.digest, testFileSHA256, 32) == 0 &&
	    memcmp(SHA256Copy.digest, testFileSHA256, 32) == 0)

	EXPECT_EXCEPTION(@"Detect invalid call of "
	    @"-[updateWithBuffer:length:]", OFHashAlreadyCalculatedException,
	    [SHA256 updateWithBuffer: "" length: 1])

	objc_autoreleasePoolPop(pool);
}
@end
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<


























































































































Deleted tests/OFSHA384HashTests.m version [7039b1bf58].

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-2024 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the 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 "TestsAppDelegate.h"

static OFString *const module = @"OFSHA384Hash";

const uint8_t testFileSHA384[48] =
	"\x7E\xDE\x62\xE2\x10\xA5\x1E\x18\x8A\x11\x7F\x78\xD7\xC7\x55\xB6\x43"
	"\x94\x1B\xD2\x78\x5C\xCF\xF3\x8A\xB8\x98\x22\xC7\x0E\xFE\xF1\xEC\x53"
	"\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;
	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];
		[SHA384 updateWithBuffer: buffer length: length];
	}
	[file close];

	TEST(@"-[copy]", (SHA384Copy = [[SHA384 copy] autorelease]))

	TEST(@"-[calculate]",
	    R([SHA384 calculate]) && R([SHA384Copy calculate]))

	TEST(@"-[digest]",
	    memcmp(SHA384.digest, testFileSHA384, 48) == 0 &&
	    memcmp(SHA384Copy.digest, testFileSHA384, 48) == 0)

	EXPECT_EXCEPTION(@"Detect invalid call of "
	    @"-[updateWithBuffer:length:]", OFHashAlreadyCalculatedException,
	    [SHA384 updateWithBuffer: "" length: 1])

	objc_autoreleasePoolPop(pool);
}
@end
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<




























































































































Deleted tests/OFSHA512HashTests.m version [11c494533c].

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-2024 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the 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 "TestsAppDelegate.h"

static OFString *const module = @"OFSHA512Hash";

const uint8_t testFileSHA512[64] =
	"\x8F\x36\x6E\x3C\x19\x4B\xBB\xC7\x82\xAA\xCD\x7D\x55\xA2\xD3\x29\x29"
	"\x97\x6A\x3F\xEB\x9B\xB2\xCB\x75\xC9\xEC\xC8\x10\x07\xD6\x07\x31\x4A"
	"\xB1\x30\x97\x82\x58\xA5\x1F\x71\x42\xE6\x56\x07\x99\x57\xB2\xB8\x3B"
	"\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;
	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];
		[SHA512 updateWithBuffer: buffer length: length];
	}
	[file close];

	TEST(@"-[copy]", (SHA512Copy = [[SHA512 copy] autorelease]))

	TEST(@"-[calculate]",
	    R([SHA512 calculate]) && R([SHA512Copy calculate]))

	TEST(@"-[digest]",
	    memcmp(SHA512.digest, testFileSHA512, 64) == 0 &&
	    memcmp(SHA512Copy.digest, testFileSHA512, 64) == 0)

	EXPECT_EXCEPTION(@"Detect invalid call of "
	    @"-[updateWithBuffer:length:]", OFHashAlreadyCalculatedException,
	    [SHA512 updateWithBuffer: "" length: 1])

	objc_autoreleasePoolPop(pool);
}
@end
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<






























































































































Modified tests/RuntimeTests.m from [38c7914698] to [99fca0e28e].

14
15
16
17
18
19
20

21
22
23
24
25
26
27
 */

#include "config.h"

#import "TestsAppDelegate.h"

static OFString *const module = @"Runtime";


@interface OFObject (SuperTest)
- (id)superTest;
@end

@interface RuntimeTest: OFObject
{







>







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

#include "config.h"

#import "TestsAppDelegate.h"

static OFString *const module = @"Runtime";
static void *testKey = &testKey;

@interface OFObject (SuperTest)
- (id)superTest;
@end

@interface RuntimeTest: OFObject
{
84
85
86
87
88
89
90















91
92
93
94
95
96
97
	TEST(@"copy, nonatomic properties", [test.foo isEqual: foo] &&
	    test.foo != foo && test.foo.retainCount == 1)

	test.bar = string;
	TEST(@"retain, atomic properties",
	    test.bar == string && string.retainCount == 3)
















#ifdef OF_OBJFW_RUNTIME
	if (sizeof(uintptr_t) == 8)
		value = 0xDEADBEEFDEADBEF;
	else if (sizeof(uintptr_t) == 4)
		value = 0xDEADBEF;
	else
		abort();







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







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
	TEST(@"copy, nonatomic properties", [test.foo isEqual: foo] &&
	    test.foo != foo && test.foo.retainCount == 1)

	test.bar = string;
	TEST(@"retain, atomic properties",
	    test.bar == string && string.retainCount == 3)

	TEST(@"Associated objects",
	    R(objc_setAssociatedObject(self, testKey, test,
	    OBJC_ASSOCIATION_ASSIGN)) && test.retainCount == 2 &&
	    R(objc_setAssociatedObject(self, testKey, test,
	    OBJC_ASSOCIATION_RETAIN)) && test.retainCount == 3 &&
	    objc_getAssociatedObject(self, testKey) == test &&
	    test.retainCount == 4 &&
	    R(objc_setAssociatedObject(self, testKey, test,
	    OBJC_ASSOCIATION_ASSIGN)) && test.retainCount == 3 &&
	    R(objc_setAssociatedObject(self, testKey, test,
	    OBJC_ASSOCIATION_RETAIN_NONATOMIC)) && test.retainCount == 4 &&
	    objc_getAssociatedObject(self, testKey) == test &&
	    test.retainCount == 4 &&
	    R(objc_removeAssociatedObjects(self)) && test.retainCount == 3)

#ifdef OF_OBJFW_RUNTIME
	if (sizeof(uintptr_t) == 8)
		value = 0xDEADBEEFDEADBEF;
	else if (sizeof(uintptr_t) == 4)
		value = 0xDEADBEF;
	else
		abort();

Modified tests/TestsAppDelegate.h from [4ca959eac5] to [dc76d3b007].

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
- (void)ASN1DERParsingTests;
@end

@interface TestsAppDelegate (OFASN1DERRepresentationTests)
- (void)ASN1DERRepresentationTests;
@end

@interface TestsAppDelegate (OFArrayTests)
- (void)arrayTests;
@end

@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;
@end

@interface TestsAppDelegate (OFDataTests)
- (void)dataTests;
@end

@interface TestsAppDelegate (OFDateTests)
- (void)dateTests;
@end

@interface TestsAppDelegate (OFDictionaryTests)
- (void)dictionaryTests;
@end

@interface TestsAppDelegate (ForwardingTests)
- (void)forwardingTests;
@end

@interface TestsAppDelegate (OFHTTPClientTests)
- (void)HTTPClientTests;
@end

@interface TestsAppDelegate (OFHTTPCookieTests)
- (void)HTTPCookieTests;
@end

@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;
@end

@interface TestsAppDelegate (OFJSONTests)
- (void)JSONTests;
@end

@interface TestsAppDelegate (OFHMACTests)
- (void)HMACTests;
@end

@interface TestsAppDelegate (OFKernelEventObserverTests)
- (void)kernelEventObserverTests;
@end

@interface TestsAppDelegate (OFListTests)
- (void)listTests;
@end

@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;
@end

@interface TestsAppDelegate (OFNotificationCenterTests)
- (void)notificationCenterTests;
@end

@interface TestsAppDelegate (OFNumberTests)
- (void)numberTests;
@end

@interface TestsAppDelegate (OFObjectTests)
- (void)objectTests;
@end

@interface TestsAppDelegate (OFPBKDF2Tests)
- (void)PBKDF2Tests;
@end

@interface TestsAppDelegate (OFPropertyListTests)
- (void)propertyListTests;
@end

@interface TestsAppDelegate (OFPluginTests)
- (void)pluginTests;
@end

@interface TestsAppDelegate (RuntimeTests)
- (void)runtimeTests;
@end

@interface TestsAppDelegate (RuntimeARCTests)
- (void)runtimeARCTests;
@end

@interface TestsAppDelegate (OFRIPEMD160HashTests)
- (void)RIPEMD160HashTests;
@end

@interface TestsAppDelegate (OFScryptTests)
- (void)scryptTests;
@end

@interface TestsAppDelegate (OFSHA1HashTests)
- (void)SHA1HashTests;
@end

@interface TestsAppDelegate (OFSHA224HashTests)
- (void)SHA224HashTests;
@end

@interface TestsAppDelegate (OFSHA256HashTests)
- (void)SHA256HashTests;
@end

@interface TestsAppDelegate (OFSHA384HashTests)
- (void)SHA384HashTests;
@end

@interface TestsAppDelegate (OFSHA512HashTests)
- (void)SHA512HashTests;
@end

@interface TestsAppDelegate (OFSPXSocketTests)
- (void)SPXSocketTests;
@end

@interface TestsAppDelegate (OFSPXStreamSocketTests)
- (void)SPXStreamSocketTests;
@end

@interface TestsAppDelegate (OFSetTests)
- (void)setTests;
@end

@interface TestsAppDelegate (OFSystemInfoTests)
- (void)systemInfoTests;
@end

@interface TestsAppDelegate (OFSocketTests)
- (void)socketTests;
@end

@interface TestsAppDelegate (OFStreamTests)
- (void)streamTests;
@end

@interface TestsAppDelegate (OFStringTests)
- (void)stringTests;
@end

@interface TestsAppDelegate (OFTCPSocketTests)
- (void)TCPSocketTests;
@end

@interface TestsAppDelegate (OFThreadTests)
- (void)threadTests;
@end

@interface TestsAppDelegate (OFUDPSocketTests)
- (void)UDPSocketTests;
@end

@interface TestsAppDelegate (OFUNIXDatagramSocketTests)
- (void)UNIXDatagramSocketTests;
@end







<
<
<
<




<
<
<
<
<
<
<
<












<
<
<
<




















<
<
<
<
<
<
<
<




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












<
<
<
<
<
<
<
<




<
<
<
<




<
<
<
<




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








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
















<
<
<
<












<
<
<
<







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
- (void)ASN1DERParsingTests;
@end

@interface TestsAppDelegate (OFASN1DERRepresentationTests)
- (void)ASN1DERRepresentationTests;
@end





@interface TestsAppDelegate (OFBlockTests)
- (void)blockTests;
@end









@interface TestsAppDelegate (OFDDPSocketTests)
- (void)DDPSocketTests;
@end

@interface TestsAppDelegate (OFDNSResolverTests)
- (void)DNSResolverTests;
@end

@interface TestsAppDelegate (OFDataTests)
- (void)dataTests;
@end





@interface TestsAppDelegate (OFDictionaryTests)
- (void)dictionaryTests;
@end

@interface TestsAppDelegate (ForwardingTests)
- (void)forwardingTests;
@end

@interface TestsAppDelegate (OFHTTPClientTests)
- (void)HTTPClientTests;
@end

@interface TestsAppDelegate (OFHTTPCookieTests)
- (void)HTTPCookieTests;
@end

@interface TestsAppDelegate (OFHTTPCookieManagerTests)
- (void)HTTPCookieManagerTests;
@end









@interface TestsAppDelegate (OFIPXSocketTests)
- (void)IPXSocketTests;
@end













@interface TestsAppDelegate (OFKernelEventObserverTests)
- (void)kernelEventObserverTests;
@end

@interface TestsAppDelegate (OFListTests)
- (void)listTests;
@end

@interface TestsAppDelegate (OFLocaleTests)
- (void)localeTests;
@end









@interface TestsAppDelegate  (OFMemoryStreamTests)
- (void)memoryStreamTests;
@end





@interface TestsAppDelegate (OFNotificationCenterTests)
- (void)notificationCenterTests;
@end





@interface TestsAppDelegate (OFObjectTests)
- (void)objectTests;
@end













@interface TestsAppDelegate (RuntimeTests)
- (void)runtimeTests;
@end

@interface TestsAppDelegate (RuntimeARCTests)
- (void)runtimeARCTests;
@end





























@interface TestsAppDelegate (OFSPXSocketTests)
- (void)SPXSocketTests;
@end

@interface TestsAppDelegate (OFSPXStreamSocketTests)
- (void)SPXStreamSocketTests;
@end

@interface TestsAppDelegate (OFSetTests)
- (void)setTests;
@end

@interface TestsAppDelegate (OFSystemInfoTests)
- (void)systemInfoTests;
@end





@interface TestsAppDelegate (OFStreamTests)
- (void)streamTests;
@end

@interface TestsAppDelegate (OFStringTests)
- (void)stringTests;
@end

@interface TestsAppDelegate (OFTCPSocketTests)
- (void)TCPSocketTests;
@end





@interface TestsAppDelegate (OFUDPSocketTests)
- (void)UDPSocketTests;
@end

@interface TestsAppDelegate (OFUNIXDatagramSocketTests)
- (void)UNIXDatagramSocketTests;
@end

Modified tests/TestsAppDelegate.m from [3a8dda6580] to [49847be0d7].

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

	[self runtimeTests];
#ifdef COMPILER_SUPPORTS_ARC
	[self runtimeARCTests];
#endif
	[self objectTests];
	[self methodSignatureTests];
	[self invocationTests];
	[self forwardingTests];
#ifdef OF_HAVE_BLOCKS
	[self blockTests];
#endif
	[self stringTests];
	[self characterSetTests];
	[self dataTests];
	[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];
	[self SHA256HashTests];
	[self SHA384HashTests];
	[self SHA512HashTests];
	[self HMACTests];
	[self PBKDF2Tests];
	[self scryptTests];
#ifdef HAVE_CODEPAGE_437
	[self INIFileTests];
#endif
#ifdef OF_HAVE_SOCKETS
	[self socketTests];
	[self TCPSocketTests];
	[self UDPSocketTests];
# ifdef OF_HAVE_UNIX_SOCKETS
	[self UNIXDatagramSocketTests];
	[self UNIXStreamSocketTests];
# endif
# ifdef OF_HAVE_IPX
	[self IPXSocketTests];
	[self SPXSocketTests];
	[self SPXStreamSocketTests];
# endif
# ifdef OF_HAVE_APPLETALK
	[self DDPSocketTests];
# endif
	[self kernelEventObserverTests];
#endif
#ifdef OF_HAVE_THREADS
	[self threadTests];
#endif
	[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 JSONTests];
	[self propertyListTests];
	[self ASN1DERParsingTests];
	[self ASN1DERRepresentationTests];

	[self matrix4x4Tests];

#if defined(OF_HAVE_PLUGINS)
	[self pluginTests];
#endif

#ifdef OF_WINDOWS
	[self windowsRegistryKeyTests];
#endif

#ifdef OF_HAVE_SOCKETS
	[self DNSResolverTests];
#endif







<
<





<

<



<

<
<



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

<
















<
<
<
<










<
<



<
<
<
<
<
<







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

	[self runtimeTests];
#ifdef COMPILER_SUPPORTS_ARC
	[self runtimeARCTests];
#endif
	[self objectTests];


	[self forwardingTests];
#ifdef OF_HAVE_BLOCKS
	[self blockTests];
#endif
	[self stringTests];

	[self dataTests];

	[self dictionaryTests];
	[self listTests];
	[self setTests];

	[self valueTests];


	[self streamTests];
	[self memoryStreamTests];
	[self notificationCenterTests];













#ifdef OF_HAVE_SOCKETS

	[self TCPSocketTests];
	[self UDPSocketTests];
# ifdef OF_HAVE_UNIX_SOCKETS
	[self UNIXDatagramSocketTests];
	[self UNIXStreamSocketTests];
# endif
# ifdef OF_HAVE_IPX
	[self IPXSocketTests];
	[self SPXSocketTests];
	[self SPXStreamSocketTests];
# endif
# ifdef OF_HAVE_APPLETALK
	[self DDPSocketTests];
# endif
	[self kernelEventObserverTests];
#endif




#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 ASN1DERParsingTests];
	[self ASN1DERRepresentationTests];







#ifdef OF_WINDOWS
	[self windowsRegistryKeyTests];
#endif

#ifdef OF_HAVE_SOCKETS
	[self DNSResolverTests];
#endif

Modified tests/terminal/TerminalTests.m from [17ab7e7ff5] to [3e6dac3672].

26
27
28
29
30
31
32
33
34
35
36
37
38
39
40

OF_APPLICATION_DELEGATE(TerminalTests)

@implementation TerminalTests
- (void)applicationDidFinishLaunching: (OFNotification *)notification
{
	OFArray *colors = [OFArray arrayWithObjects:
	    [OFColor black], [OFColor silver], [OFColor grey], [OFColor white],
	    [OFColor maroon], [OFColor red], [OFColor purple],
	    [OFColor fuchsia], [OFColor green], [OFColor lime], [OFColor olive],
	    [OFColor yellow], [OFColor navy], [OFColor blue], [OFColor teal],
	    [OFColor aqua], nil];
	size_t i;
	OFEnumerator OF_GENERIC(OFColor *) *reverseEnumerator;








|







26
27
28
29
30
31
32
33
34
35
36
37
38
39
40

OF_APPLICATION_DELEGATE(TerminalTests)

@implementation TerminalTests
- (void)applicationDidFinishLaunching: (OFNotification *)notification
{
	OFArray *colors = [OFArray arrayWithObjects:
	    [OFColor black], [OFColor silver], [OFColor gray], [OFColor white],
	    [OFColor maroon], [OFColor red], [OFColor purple],
	    [OFColor fuchsia], [OFColor green], [OFColor lime], [OFColor olive],
	    [OFColor yellow], [OFColor navy], [OFColor blue], [OFColor teal],
	    [OFColor aqua], nil];
	size_t i;
	OFEnumerator OF_GENERIC(OFColor *) *reverseEnumerator;

Deleted tests/testfile.bin version [ac78121630].

cannot compute difference between binary files