ObjFW  Check-in [4320b1bf7d]

Overview
Comment:Merge trunk into branch "asn1"
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | asn1
Files: files | file ages | folders
SHA3-256: 4320b1bf7dfc515ef712636cfbbc7d00fbfa4dd4dacd606184d20d136f1a2590
User & Date: js on 2024-01-11 20:12:08
Other Links: branch diff | manifest | tags
Context
2024-01-14
13:00
Replace OFASN1Boolean with bool OFNumber check-in: 90ee6a8373 user: js tags: asn1
2024-01-11
20:12
Merge trunk into branch "asn1" check-in: 4320b1bf7d user: js tags: asn1
2024-01-06
15:36
OFDNSResolver: Use correct run loop mode for cache check-in: c13f9f78f1 user: js tags: trunk
2022-11-07
00:20
Merge trunk into branch "asn1" check-in: d8ef56254d user: js tags: asn1
Changes

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

35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
src/tls/Info.plist
tests/DerivedData
tests/EBOOT.PBP
tests/Info.plist
tests/PARAM.SFO
tests/objc_sync/objc_sync
tests/plugin/Info.plist
tests/serialization_xml.m
tests/terminal/terminal_tests
tests/testfile_bin.m
tests/testfile_ini.m
tests/tests
tests/tests.3dsx
tests/tests.arm9
tests/tests.nds







<







35
36
37
38
39
40
41

42
43
44
45
46
47
48
src/tls/Info.plist
tests/DerivedData
tests/EBOOT.PBP
tests/Info.plist
tests/PARAM.SFO
tests/objc_sync/objc_sync
tests/plugin/Info.plist

tests/terminal/terminal_tests
tests/testfile_bin.m
tests/testfile_ini.m
tests/tests
tests/tests.3dsx
tests/tests.arm9
tests/tests.nds

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

40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
tests/Info.plist
tests/PARAM.SFO
tests/iOS.xcodeproj/*.pbxuser
tests/iOS.xcodeproj/project.xcworkspace
tests/iOS.xcodeproj/xcuserdata
tests/objc_sync/objc_sync
tests/plugin/Info.plist
tests/serialization_xml.m
tests/terminal/terminal_tests
tests/testfile_bin.m
tests/testfile_ini.m
tests/tests
tests/tests.3dsx
tests/tests.arm9
tests/tests.nds







<







40
41
42
43
44
45
46

47
48
49
50
51
52
53
tests/Info.plist
tests/PARAM.SFO
tests/iOS.xcodeproj/*.pbxuser
tests/iOS.xcodeproj/project.xcworkspace
tests/iOS.xcodeproj/xcuserdata
tests/objc_sync/objc_sync
tests/plugin/Info.plist

tests/terminal/terminal_tests
tests/testfile_bin.m
tests/testfile_ini.m
tests/tests
tests/tests.3dsx
tests/tests.arm9
tests/tests.nds

Modified .github/workflows/amiga-gcc.yml from [d938c3ac40] to [334c337cae].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
name: amiga-gcc
on: [push, pull_request]
jobs:
  build:
    runs-on: ubuntu-latest
    container: amigadev/crosstools:m68k-amigaos
    strategy:
      matrix:
        configure_flags:
          -
          - --disable-amiga-lib
    steps:
    - uses: actions/checkout@v2
    - name: autogen.sh
      run: ./autogen.sh
    - name: configure
      run: ./configure --host=m68k-amigaos ${{ matrix.configure_flags }}
    - name: make
      run: make -j$(nproc)
    - name: make install
      run: make install






<
<
<
<
<

|



|




1
2
3
4
5
6





7
8
9
10
11
12
13
14
15
16
name: amiga-gcc
on: [push, pull_request]
jobs:
  build:
    runs-on: ubuntu-latest
    container: amigadev/crosstools:m68k-amigaos





    steps:
    - uses: actions/checkout@v4
    - name: autogen.sh
      run: ./autogen.sh
    - name: configure
      run: ./configure --host=m68k-amigaos
    - name: make
      run: make -j$(nproc)
    - name: make install
      run: make install

Modified .github/workflows/ios.yml from [dd34f22809] to [dbdab2a600].

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
          - x86_64
        configure_flags:
          - 
          - --disable-shared
    steps:
    - name: Install dependencies
      run: brew install autoconf automake
    - uses: actions/checkout@v2
    - name: autogen.sh
      run: ./autogen.sh
    - name: configure
      run: |
        export IPHONEOS_DEPLOYMENT_TARGET="9.0"
        if [ "${{ matrix.arch}}" = "x86_64" ]; then
          sdk="iphonesimulator"







|







10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
          - x86_64
        configure_flags:
          - 
          - --disable-shared
    steps:
    - name: Install dependencies
      run: brew install autoconf automake
    - uses: actions/checkout@v4
    - name: autogen.sh
      run: ./autogen.sh
    - name: configure
      run: |
        export IPHONEOS_DEPLOYMENT_TARGET="9.0"
        if [ "${{ matrix.arch}}" = "x86_64" ]; then
          sdk="iphonesimulator"

Modified .github/workflows/macos-11.yml from [d79ffc1fb9] to [ade6268255].

14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
          - --disable-sockets
          - --disable-sockets --disable-files
          - --disable-files
          - --disable-shared
    steps:
    - name: Install dependencies
      run: brew install autoconf automake
    - uses: actions/checkout@v2
    - name: autogen.sh
      run: ./autogen.sh
    - name: configure
      run: ./configure ${{ matrix.configure_flags }}
    - name: make
      run: make -j$(sysctl -n hw.logicalcpu)
    - name: make check
      run: make check
    - name: make install
      run: sudo make install







|










14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
          - --disable-sockets
          - --disable-sockets --disable-files
          - --disable-files
          - --disable-shared
    steps:
    - name: Install dependencies
      run: brew install autoconf automake
    - uses: actions/checkout@v4
    - name: autogen.sh
      run: ./autogen.sh
    - name: configure
      run: ./configure ${{ matrix.configure_flags }}
    - name: make
      run: make -j$(sysctl -n hw.logicalcpu)
    - name: make check
      run: make check
    - name: make install
      run: sudo make install

Modified .github/workflows/macos-12.yml from [a15421158f] to [ee9ffcacad].

14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
          - --disable-sockets
          - --disable-sockets --disable-files
          - --disable-files
          - --disable-shared
    steps:
    - name: Install dependencies
      run: brew install autoconf automake
    - uses: actions/checkout@v2
    - name: autogen.sh
      run: ./autogen.sh
    - name: configure
      run: ./configure ${{ matrix.configure_flags }}
    - name: make
      run: make -j$(sysctl -n hw.logicalcpu)
    - name: make check
      run: make check
    - name: make install
      run: sudo make install







|










14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
          - --disable-sockets
          - --disable-sockets --disable-files
          - --disable-files
          - --disable-shared
    steps:
    - name: Install dependencies
      run: brew install autoconf automake
    - uses: actions/checkout@v4
    - name: autogen.sh
      run: ./autogen.sh
    - name: configure
      run: ./configure ${{ matrix.configure_flags }}
    - name: make
      run: make -j$(sysctl -n hw.logicalcpu)
    - name: make check
      run: make check
    - name: make install
      run: sudo make install

Added .github/workflows/macos-13.yml version [e68bb1a491].































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
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
name: macos-13
on: [push, pull_request]
jobs:
  tests:
    runs-on: macos-13
    strategy:
      matrix:
        configure_flags:
          - 
          - --disable-threads
          - --disable-threads --disable-sockets
          - --disable-threads --disable-files
          - --disable-threads --disable-sockets --disable-files
          - --disable-sockets
          - --disable-sockets --disable-files
          - --disable-files
          - --disable-shared
    steps:
    - name: Install dependencies
      run: brew install autoconf automake
    - uses: actions/checkout@v4
    - name: autogen.sh
      run: ./autogen.sh
    - name: configure
      run: ./configure ${{ matrix.configure_flags }}
    - name: make
      run: make -j$(sysctl -n hw.logicalcpu)
    - name: make check
      run: make check
    - name: make install
      run: sudo make install

Modified .github/workflows/morphos.yml from [c3d30801ba] to [f96dbd2310].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
name: morphos
on: [push, pull_request]
jobs:
  build:
    runs-on: ubuntu-latest
    container: amigadev/crosstools:ppc-morphos
    strategy:
      matrix:
        configure_flags:
          -
          - --disable-amiga-lib
    steps:
    - uses: actions/checkout@v2
    - name: autogen.sh
      run: ./autogen.sh
    - name: configure
      run: ./configure --host=ppc-morphos ${{ matrix.configure_flags }}
    - name: make
      run: make -j$(nproc)
    - name: make install
      run: make install






<
<
<
<
<

|



|




1
2
3
4
5
6





7
8
9
10
11
12
13
14
15
16
name: morphos
on: [push, pull_request]
jobs:
  build:
    runs-on: ubuntu-latest
    container: amigadev/crosstools:ppc-morphos





    steps:
    - uses: actions/checkout@v4
    - name: autogen.sh
      run: ./autogen.sh
    - name: configure
      run: ./configure --host=ppc-morphos
    - name: make
      run: make -j$(nproc)
    - name: make install
      run: make install

Modified .github/workflows/nintendo-3ds.yml from [b6f005f187] to [d5f22cd8d0].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
name: nintendo-3ds
on: [push, pull_request]
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - name: Install dependencies
      run: docker pull devkitpro/devkitarm
    - uses: actions/checkout@v2
    - name: autogen.sh
      run: ./autogen.sh
    - name: configure
      run: |
        docker run \
          -e DEVKITPRO=/opt/devkitpro \
          -e PATH="/opt/devkitpro/devkitARM/bin:$PATH" \








|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
name: nintendo-3ds
on: [push, pull_request]
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - name: Install dependencies
      run: docker pull devkitpro/devkitarm
    - uses: actions/checkout@v4
    - name: autogen.sh
      run: ./autogen.sh
    - name: configure
      run: |
        docker run \
          -e DEVKITPRO=/opt/devkitpro \
          -e PATH="/opt/devkitpro/devkitARM/bin:$PATH" \

Modified .github/workflows/nintendo-ds.yml from [1d6308a4b1] to [6b553d5781].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
name: nintendo-ds
on: [push, pull_request]
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - name: Install dependencies
      run: docker pull devkitpro/devkitarm
    - uses: actions/checkout@v2
    - name: autogen.sh
      run: ./autogen.sh
    - name: configure
      run: |
        docker run \
          -e DEVKITPRO=/opt/devkitpro \
          -e PATH="/opt/devkitpro/devkitARM/bin:$PATH" \








|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
name: nintendo-ds
on: [push, pull_request]
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - name: Install dependencies
      run: docker pull devkitpro/devkitarm
    - uses: actions/checkout@v4
    - name: autogen.sh
      run: ./autogen.sh
    - name: configure
      run: |
        docker run \
          -e DEVKITPRO=/opt/devkitpro \
          -e PATH="/opt/devkitpro/devkitARM/bin:$PATH" \

Modified .github/workflows/nintendo-switch.yml from [9d8878050b] to [dd1432abab].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
name: nintendo-switch
on: [push, pull_request]
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - name: Install dependencies
      run: docker pull devkitpro/devkita64
    - uses: actions/checkout@v2
    - name: autogen.sh
      run: ./autogen.sh
    - name: configure
      run: |
        docker run \
          -e DEVKITPRO=/opt/devkitpro \
          -e PATH="/opt/devkitpro/devkitA64/bin:$PATH" \








|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
name: nintendo-switch
on: [push, pull_request]
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - name: Install dependencies
      run: docker pull devkitpro/devkita64
    - uses: actions/checkout@v4
    - name: autogen.sh
      run: ./autogen.sh
    - name: configure
      run: |
        docker run \
          -e DEVKITPRO=/opt/devkitpro \
          -e PATH="/opt/devkitpro/devkitA64/bin:$PATH" \

Modified .github/workflows/ubuntu-20.04-32bit.yml from [6af581a780] to [eafc923d25].

20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
          - --without-tls --disable-shared --enable-seluid24
          - --without-tls --disable-compiler-tls --disable-threads
    steps:
    - name: Install dependencies
      run: |
        sudo apt-get update
        sudo apt-get install gcc-multilib
    - uses: actions/checkout@v2
    - name: autogen.sh
      run: ./autogen.sh
    - name: configure
      run: ./configure OBJC="clang -m32" ${{ matrix.configure_flags }}
    - name: make
      run: make -j$(nproc)
    - name: make check
      run: make check
    - name: make install
      run: sudo make install







|










20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
          - --without-tls --disable-shared --enable-seluid24
          - --without-tls --disable-compiler-tls --disable-threads
    steps:
    - name: Install dependencies
      run: |
        sudo apt-get update
        sudo apt-get install gcc-multilib
    - uses: actions/checkout@v4
    - name: autogen.sh
      run: ./autogen.sh
    - name: configure
      run: ./configure OBJC="clang -m32" ${{ 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-20.04-gcc-32bit.yml from [16adbb51e7] to [b216b21e23].

20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
          - --without-tls --disable-shared --enable-seluid24
          - --without-tls --disable-compiler-tls --disable-threads
    steps:
    - name: Install dependencies
      run: |
        sudo apt-get update
        sudo apt-get install gcc-multilib gobjc
    - uses: actions/checkout@v2
    - name: autogen.sh
      run: ./autogen.sh
    - name: configure
      run: ./configure OBJC="gcc -m32" ${{ matrix.configure_flags }}
    - name: make
      run: make -j$(nproc)
    - name: make check
      run: make check
    - name: make install
      run: sudo make install







|










20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
          - --without-tls --disable-shared --enable-seluid24
          - --without-tls --disable-compiler-tls --disable-threads
    steps:
    - name: Install dependencies
      run: |
        sudo apt-get update
        sudo apt-get install gcc-multilib gobjc
    - uses: actions/checkout@v4
    - name: autogen.sh
      run: ./autogen.sh
    - name: configure
      run: ./configure OBJC="gcc -m32" ${{ 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-20.04-gcc.yml from [dd262654f6] to [db8cc56ce4].

22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
          - --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@v2
    - 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







|










22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
          - --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

Modified .github/workflows/ubuntu-20.04.yml from [051ed40d72] to [7132512cb3].

22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
          - --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@v2
    - 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







|










22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
          - --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

Modified .github/workflows/ubuntu-latest-32bit.yml from [3cbf56442c] to [c27d1cf836].

20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
          - --without-tls --disable-shared --enable-seluid24
          - --without-tls --disable-compiler-tls --disable-threads
    steps:
    - name: Install dependencies
      run: |
        sudo apt-get update
        sudo apt-get install gcc-multilib
    - uses: actions/checkout@v2
    - name: autogen.sh
      run: ./autogen.sh
    - name: configure
      run: ./configure OBJC="clang -m32" ${{ matrix.configure_flags }}
    - name: make
      run: make -j$(nproc)
    - name: make check
      run: make check
    - name: make install
      run: sudo make install







|










20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
          - --without-tls --disable-shared --enable-seluid24
          - --without-tls --disable-compiler-tls --disable-threads
    steps:
    - name: Install dependencies
      run: |
        sudo apt-get update
        sudo apt-get install gcc-multilib
    - uses: actions/checkout@v4
    - name: autogen.sh
      run: ./autogen.sh
    - name: configure
      run: ./configure OBJC="clang -m32" ${{ 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-gcc-32bit.yml from [b827a9a41f] to [e9d9b51c60].

20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
          - --without-tls --disable-shared --enable-seluid24
          - --without-tls --disable-compiler-tls --disable-threads
    steps:
    - name: Install dependencies
      run: |
        sudo apt-get update
        sudo apt-get install gcc-multilib gobjc
    - uses: actions/checkout@v2
    - name: autogen.sh
      run: ./autogen.sh
    - name: configure
      run: ./configure OBJC="gcc -m32" ${{ matrix.configure_flags }}
    - name: make
      run: make -j$(nproc)
    - name: make check
      run: make check
    - name: make install
      run: sudo make install







|










20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
          - --without-tls --disable-shared --enable-seluid24
          - --without-tls --disable-compiler-tls --disable-threads
    steps:
    - name: Install dependencies
      run: |
        sudo apt-get update
        sudo apt-get install gcc-multilib gobjc
    - uses: actions/checkout@v4
    - name: autogen.sh
      run: ./autogen.sh
    - name: configure
      run: ./configure OBJC="gcc -m32" ${{ 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-gcc.yml from [4509107d9f] to [b7ca4731c5].

22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
          - --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@v2
    - 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







|










22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
          - --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

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

22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
          - --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@v2
    - 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







|










22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
          - --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

Modified .github/workflows/wii-u.yml from [7d250df7d0] to [e120b2edbe].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
name: wii-u
on: [push, pull_request]
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - name: Install dependencies
      run: docker pull devkitpro/devkitppc
    - uses: actions/checkout@v2
    - name: autogen.sh
      run: ./autogen.sh
    - name: configure
      run: |
        docker run \
          -e DEVKITPRO=/opt/devkitpro \
          -e PATH="/opt/devkitpro/devkitPPC/bin:$PATH" \








|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
name: wii-u
on: [push, pull_request]
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - name: Install dependencies
      run: docker pull devkitpro/devkitppc
    - uses: actions/checkout@v4
    - name: autogen.sh
      run: ./autogen.sh
    - name: configure
      run: |
        docker run \
          -e DEVKITPRO=/opt/devkitpro \
          -e PATH="/opt/devkitpro/devkitPPC/bin:$PATH" \

Modified .github/workflows/wii.yml from [59cebc18ff] to [191971b95d].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
name: wii
on: [push, pull_request]
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - name: Install dependencies
      run: docker pull devkitpro/devkitppc
    - uses: actions/checkout@v2
    - name: autogen.sh
      run: ./autogen.sh
    - name: configure
      run: |
        docker run \
          -e DEVKITPRO=/opt/devkitpro \
          -e PATH="/opt/devkitpro/devkitPPC/bin:$PATH" \








|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
name: wii
on: [push, pull_request]
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - name: Install dependencies
      run: docker pull devkitpro/devkitppc
    - uses: actions/checkout@v4
    - name: autogen.sh
      run: ./autogen.sh
    - name: configure
      run: |
        docker run \
          -e DEVKITPRO=/opt/devkitpro \
          -e PATH="/opt/devkitpro/devkitPPC/bin:$PATH" \

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

40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
tests/Info.plist
tests/PARAM.SFO
tests/iOS.xcodeproj/*.pbxuser
tests/iOS.xcodeproj/project.xcworkspace
tests/iOS.xcodeproj/xcuserdata
tests/objc_sync/objc_sync
tests/plugin/Info.plist
tests/serialization_xml.m
tests/terminal/terminal_tests
tests/testfile_bin.m
tests/testfile_ini.m
tests/tests
tests/tests.3dsx
tests/tests.arm9
tests/tests.nds







<







40
41
42
43
44
45
46

47
48
49
50
51
52
53
tests/Info.plist
tests/PARAM.SFO
tests/iOS.xcodeproj/*.pbxuser
tests/iOS.xcodeproj/project.xcworkspace
tests/iOS.xcodeproj/xcuserdata
tests/objc_sync/objc_sync
tests/plugin/Info.plist

tests/terminal/terminal_tests
tests/testfile_bin.m
tests/testfile_ini.m
tests/tests
tests/tests.3dsx
tests/tests.arm9
tests/tests.nds

Modified ChangeLog from [9da9558760] to [0196990ba7].

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

This file only contains the most significant changes.









































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

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

ObjFW 0.8.1 -> ObjFW 0.90, 01.08.2017
 + New classes: OFFileManager, OFGZIPStream, OFTarArchive, OFTarArchiveEntry
		OFHMAC, OFSandbox, OFHTTPCookie, OFHTTPCookieManager,
		OFLocalization
 + New platforms: Nintendo 3DS, MorphOS
 + New lookup assembly for platforms: SPARC64/ELF, ARM64/ELF
 + New forwarding for: ARM64/ELF
 + New tools: objfw-new (to create boilerplate code)






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










|












|







1
2
3
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
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

ObjFW 1.0.3 -> ObjFW 1.0.4, 2023-10-08
 * Fixes OFFile closing fd 0 when initialization fails
 * Fixes -[stringByAppendingPathComponent:] on empty strings
 * Fixes +[OFSystemInfo operatingSystemName] and
   +[OFSystemInfo operatingSystemVersion] returning nil on some systems
 * Adds a license for localizations

ObjFW 1.0.2 -> ObjFW 1.0.3, 2023-09-14
 * Fixes -[OFConcreteData initWithItemSize:] not setting freeWhenDone to true,
   which resulted in a memory leak
 * Fixes -[OFData initWithContentsOfIRI:] freeing the buffer in @catch instead
   of @finally, which resulted in a memory leak

ObjFW 1.0.1 -> ObjFW 1.0.2, 2023-09-11
 * The build system has been updated to fix building .frameworks and to build
   them differently for macOS and iOS

ObjFW 1.0 -> ObjFW 1.0.1, 2023-09-10
 * Hanging connections with OFTLSStream have been fixed when using OpenSSL
 * The same fix as for OpenSSL has been applied to GnuTLS and SecureTransport
   out of caution, even though there have been no hangs in practice
 * The build system has been updated to fix building .frameworks among other
   minor changes
 * Some headers have been changed to fix compatibility with ObjC++
 * Warnings about empty .o files on x86_64 Darwin have been fixed
 * The OFDate documentation has been improved to list supported formats

ObjFW 0.90.2 -> ObjFW 1.0, 2023-08-29
 + First stable release with stable API and ABI
 * Too many changes to list, as it has been almost 6 years since the last
   release. See commits in the repository for details.

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

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

ObjFW 0.8.1 -> ObjFW 0.90, 2017-08-01
 + New classes: OFFileManager, OFGZIPStream, OFTarArchive, OFTarArchiveEntry
		OFHMAC, OFSandbox, OFHTTPCookie, OFHTTPCookieManager,
		OFLocalization
 + New platforms: Nintendo 3DS, MorphOS
 + New lookup assembly for platforms: SPARC64/ELF, ARM64/ELF
 + New forwarding for: ARM64/ELF
 + New tools: objfw-new (to create boilerplate code)
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
 * OFHash was renamed to OFCryptoHash
 + PBKDF2
 + scrypt
 + Xcode project to build for iOS
 + String decomposition to NFD
 * OFFile modes simplified ('b' removed)

ObjFW 0.8 -> ObjFW 0.8.1, 04.10.2015
 * Adjust to __nullable / __nonnull being changed to _Nullable / _Nonnull in
   Clang 3.7 (this fixes compilation with Clang 3.7)
 * Blocks: Proper handling when called from a byref handler
 * Fix compilation on Solaris
 * Fix compilation for Wii, PSP and Nintendo DS
 * OFProcess: Send SIGTERM on close instead of SIGKILL
 * OFZIPArchive: Throw invalid format exception on failed seeks
 * Make sure of_hash_seed is never initialized to 0
 * Special cases for the Wii's weird network stack (fixes the tests)
 * Better length checks for write / send calls
 * Don't use -pedantic on platforms where it's broken by the system headers
 * Documentation fixes

ObjFW 0.7.1 -> ObjFW 0.8, 14.08.2015

 + An insanely huge amount of new APIs
 + New classes: OFHTTPServer, OFINICategory, OFINIFile, OFInflate64Stream,
   OFInflateStream, OFMapTable, OFRIPEMD160Hash, OFSHA224Hash, OFSHA256Hash,
   OFSHA384Hash, OFSHA512Hash, OFSettings, OFStdIOStream, OFSystemInfo,
   OFUDPSocket, OFZIPArchive, OFZIPArchiveEntry
 + New utils: ofzip, ofhash, ofhttp







|













|







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
 * OFHash was renamed to OFCryptoHash
 + PBKDF2
 + scrypt
 + Xcode project to build for iOS
 + String decomposition to NFD
 * OFFile modes simplified ('b' removed)

ObjFW 0.8 -> ObjFW 0.8.1, 2015-10-04
 * Adjust to __nullable / __nonnull being changed to _Nullable / _Nonnull in
   Clang 3.7 (this fixes compilation with Clang 3.7)
 * Blocks: Proper handling when called from a byref handler
 * Fix compilation on Solaris
 * Fix compilation for Wii, PSP and Nintendo DS
 * OFProcess: Send SIGTERM on close instead of SIGKILL
 * OFZIPArchive: Throw invalid format exception on failed seeks
 * Make sure of_hash_seed is never initialized to 0
 * Special cases for the Wii's weird network stack (fixes the tests)
 * Better length checks for write / send calls
 * Don't use -pedantic on platforms where it's broken by the system headers
 * Documentation fixes

ObjFW 0.7.1 -> ObjFW 0.8, 2015-08-14

 + An insanely huge amount of new APIs
 + New classes: OFHTTPServer, OFINICategory, OFINIFile, OFInflate64Stream,
   OFInflateStream, OFMapTable, OFRIPEMD160Hash, OFSHA224Hash, OFSHA256Hash,
   OFSHA384Hash, OFSHA512Hash, OFSettings, OFStdIOStream, OFSystemInfo,
   OFUDPSocket, OFZIPArchive, OFZIPArchiveEntry
 + New utils: ofzip, ofhash, ofhttp
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
 * OFProcess improvements for Win32
 + epoll support for OFKernelEventObserver
 * Rewritten OFMD5Hash and OFSHA1Hash
 * Reworked OFTLSSocket API (easier verification)
 * Unicode support updated to Unicode 8.0
 * OFURL: Proper escaping and unescaping

ObjFW 0.7 -> ObjFW 0.7.1, 12.11.2012
 + Support for Haiku
 * Autorelease pools now work properly without __thread
 * Incorrect framework version in Xcode project fixed
 * Documentation fixes and improvements
 * Blocks now only use 16 bits for the reference count in order to avoid
   problems with newer Clang versions
 * More use of OF_SENTINEL

ObjFW 0.6 -> ObjFW 0.7, 27.10.2012
 Again, the differences are more than in any release before, thus listing them
 all would be too much. The major differences are:
 + ObjFW now comes with its own runtime, which greatly increases performance
   compared to the GNU runtime and is even faster than the Apple runtime
   (using Clang >= 3.2 is recommended, but not necessary)
 * Support for the GNU runtime has been dropped
 + New, much faster autorelease pool implementation (now inside the runtime)







|








|







159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
 * OFProcess improvements for Win32
 + epoll support for OFKernelEventObserver
 * Rewritten OFMD5Hash and OFSHA1Hash
 * Reworked OFTLSSocket API (easier verification)
 * Unicode support updated to Unicode 8.0
 * OFURL: Proper escaping and unescaping

ObjFW 0.7 -> ObjFW 0.7.1, 2012-11-12
 + Support for Haiku
 * Autorelease pools now work properly without __thread
 * Incorrect framework version in Xcode project fixed
 * Documentation fixes and improvements
 * Blocks now only use 16 bits for the reference count in order to avoid
   problems with newer Clang versions
 * More use of OF_SENTINEL

ObjFW 0.6 -> ObjFW 0.7, 2012-10-27
 Again, the differences are more than in any release before, thus listing them
 all would be too much. The major differences are:
 + ObjFW now comes with its own runtime, which greatly increases performance
   compared to the GNU runtime and is even faster than the Apple runtime
   (using Clang >= 3.2 is recommended, but not necessary)
 * Support for the GNU runtime has been dropped
 + New, much faster autorelease pool implementation (now inside the runtime)
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
 * Strings are allocated faster now
 + Support for JSON5
 * All private methods use the prefix OF_ now instead of _, making it possible
   to use the _ prefix in applications
 * Most ObjC compiler feature checks are not part of configure anymore, making
   it possible to use the same installation with different compilers

ObjFW 0.5.4 -> ObjFW 0.6, 27.02.2012
 The differences between 0.5.4 and 0.6 are too big to list them all. However,
 the major new features are:
 * OFString, OFArray, OFDictionary, OFSet and OFCountedSet are now class
   clusters
 + Serialization and deserialization of objects into/from XML and JSON
 + New class OFIntrospection for introspecting classes
 + New class OFProcess for working with and controlling child processes
 * Lots of OFXMLParser and OFXMLElement improvements
 + OFHTTPRequests can have a delegate now for status updates and processing
   data as soon as it arrives
 + There are several backends for OFStreamObserver now, including kqueue, poll
   and select
 + SOCKS5 support for OFTCPSockets (client only)
 * Several API changes

ObjFW 0.5.3 -> ObjFW 0.5.4, 30.08.2011
 * The blocks runtime is now working correctly
 * Documentation fixes
 * -framework works with objfw-compile now
 + Support for QNX
 * Various small fixes

ObjFW 0.5.2 -> ObjFW 0.5.3, 01.07.2011
 * Lots of bugfixes, see Git log for details

ObjFW 0.5.1 -> ObjFW 0.5.2, 25.04.2011
 * Fix double-retain in OFList
 * Don't ignore the timeout in OFStreamObserver when using select()
 * Do -[OFURL copy] in a try block to prevent a leak when an exception occurs
 * Fix too big buffer in -[OFMutableString _applyTable:withSize:]
 * Call madvise() on the correct length variable so it covers the whole string
 * Fix a warning when sizeof(size_t) < sizeof(long long)
 * Skip possible BOMs when appending strings

ObjFW 0.5 -> ObjFW 0.5.1, 21.04.2011
 * Work around a wrong warning produced by Apple GCC 4.0.1 which would cause
   the build to fail due to -Werror
 * Call objc_thread_{add,remove} when using the GNU runtime to make sure the
   runtime knows about our thread
 * Detach a thread before restarting if it was never joined
 * Release the old return value when restarting a thread

ObjFW 0.4-alpha1 -> 0.5, 09.04.2011
 + %@ is now allowed in format strings
 + Added of_log for easy logging
 * Exceptions have one header per exception now
 * Lots of exception improvements
 * Huge improvements in XML handling
 * Improvements in socket handling, including improved API
 * OFStreamObserver is now thread-safe and stops the current observe call when
   the set of streams to observe is modified
 + New class OFURL
 + New class OFHTTPRequest
 + New class OFCondition
 * Improvements in objfw-compile
 + Blocks can be used together with Cocoa now
 + When linking ObjFW and Cocoa, OFAutoreleasePools are used by both now
 + Support for Base64
 + Use a real Xcode project instead of just calling make
 + Add Haiku to the list of supported platforms
 * Lots of small bugfixes and countless small changes. Read the commits!

ObjFW 0.3.1 -> 0.4-alpha1, 03.01.2011
 * ObjFW is now available under the terms of the QPL, GPLv2 and GPLv3
 + Support for blocks was added, including a blocks runtime
 + Added support for the new GNU runtime, introduced in GCC 4.6
 * Objects returned from collections are no longer retained and autoreleased
 + Added new classes OFXMLParser, OFXMLElement, OFXMLAttribute and
   OFXMLElementBuilder
 + Added new class OFStreamObserver to observe streams
 + Added new class OFDate for storing dates
 + Many new methods in almost all classes
 * OFAutoreleasePool was optimized
 * Handling of ASCII strings was optimized
 * OFSocket was renamed to OFStreamSocket
 * OFConstString was renamed to OFConstantString
 * objfw-compile now has a new syntax
 + objfw-compile can now compile libraries and plugins
 * Many small changes and new features that would be too much to list here
   The diff between 0.3.1 and 0.4-alpha1 has almost 24000 lines!

ObjFW 0.3 -> 0.3.1, 19.06.2010
 * Fix a typo in OFMutableDictionary that prevented termination in case
   the last bucket is already used when the dictionary is resized
 * The mutations pointer is now correctly initialized in enumerators for
   immutable collections
 * The objc_sync test was still using the old threads API and was
   updated to use the new one now
 * PLATFORMS has been updated to be more specific

ObjFW 0.2.1 -> 0.3, 09.05.2010
 + Many new methods were added to different classes
 + A huge amount of methods was added to OFStream, allowing easy binary
   stream handling and even mixing string-based and binary operations
 + An optional write buffer was added to OFStream
 + OFSeekableStream was added for streams that allow seeking, for example
   OFFiles
 * OFNumber was completely reworked and got many new features now







|















|






|


|








|







|



















|


















|








|







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
 * Strings are allocated faster now
 + Support for JSON5
 * All private methods use the prefix OF_ now instead of _, making it possible
   to use the _ prefix in applications
 * Most ObjC compiler feature checks are not part of configure anymore, making
   it possible to use the same installation with different compilers

ObjFW 0.5.4 -> ObjFW 0.6, 2012-02-27
 The differences between 0.5.4 and 0.6 are too big to list them all. However,
 the major new features are:
 * OFString, OFArray, OFDictionary, OFSet and OFCountedSet are now class
   clusters
 + Serialization and deserialization of objects into/from XML and JSON
 + New class OFIntrospection for introspecting classes
 + New class OFProcess for working with and controlling child processes
 * Lots of OFXMLParser and OFXMLElement improvements
 + OFHTTPRequests can have a delegate now for status updates and processing
   data as soon as it arrives
 + There are several backends for OFStreamObserver now, including kqueue, poll
   and select
 + SOCKS5 support for OFTCPSockets (client only)
 * Several API changes

ObjFW 0.5.3 -> ObjFW 0.5.4, 2011-08-30
 * The blocks runtime is now working correctly
 * Documentation fixes
 * -framework works with objfw-compile now
 + Support for QNX
 * Various small fixes

ObjFW 0.5.2 -> ObjFW 0.5.3, 2011-07-01
 * Lots of bugfixes, see Git log for details

ObjFW 0.5.1 -> ObjFW 0.5.2, 2011-04-25
 * Fix double-retain in OFList
 * Don't ignore the timeout in OFStreamObserver when using select()
 * Do -[OFURL copy] in a try block to prevent a leak when an exception occurs
 * Fix too big buffer in -[OFMutableString _applyTable:withSize:]
 * Call madvise() on the correct length variable so it covers the whole string
 * Fix a warning when sizeof(size_t) < sizeof(long long)
 * Skip possible BOMs when appending strings

ObjFW 0.5 -> ObjFW 0.5.1, 2011-04-21
 * Work around a wrong warning produced by Apple GCC 4.0.1 which would cause
   the build to fail due to -Werror
 * Call objc_thread_{add,remove} when using the GNU runtime to make sure the
   runtime knows about our thread
 * Detach a thread before restarting if it was never joined
 * Release the old return value when restarting a thread

ObjFW 0.4-alpha1 -> 0.5, 2011-04-09
 + %@ is now allowed in format strings
 + Added of_log for easy logging
 * Exceptions have one header per exception now
 * Lots of exception improvements
 * Huge improvements in XML handling
 * Improvements in socket handling, including improved API
 * OFStreamObserver is now thread-safe and stops the current observe call when
   the set of streams to observe is modified
 + New class OFURL
 + New class OFHTTPRequest
 + New class OFCondition
 * Improvements in objfw-compile
 + Blocks can be used together with Cocoa now
 + When linking ObjFW and Cocoa, OFAutoreleasePools are used by both now
 + Support for Base64
 + Use a real Xcode project instead of just calling make
 + Add Haiku to the list of supported platforms
 * Lots of small bugfixes and countless small changes. Read the commits!

ObjFW 0.3.1 -> 0.4-alpha1, 2011-01-03
 * ObjFW is now available under the terms of the QPL, GPLv2 and GPLv3
 + Support for blocks was added, including a blocks runtime
 + Added support for the new GNU runtime, introduced in GCC 4.6
 * Objects returned from collections are no longer retained and autoreleased
 + Added new classes OFXMLParser, OFXMLElement, OFXMLAttribute and
   OFXMLElementBuilder
 + Added new class OFStreamObserver to observe streams
 + Added new class OFDate for storing dates
 + Many new methods in almost all classes
 * OFAutoreleasePool was optimized
 * Handling of ASCII strings was optimized
 * OFSocket was renamed to OFStreamSocket
 * OFConstString was renamed to OFConstantString
 * objfw-compile now has a new syntax
 + objfw-compile can now compile libraries and plugins
 * Many small changes and new features that would be too much to list here
   The diff between 0.3.1 and 0.4-alpha1 has almost 24000 lines!

ObjFW 0.3 -> 0.3.1, 2010-06-19
 * Fix a typo in OFMutableDictionary that prevented termination in case
   the last bucket is already used when the dictionary is resized
 * The mutations pointer is now correctly initialized in enumerators for
   immutable collections
 * The objc_sync test was still using the old threads API and was
   updated to use the new one now
 * PLATFORMS has been updated to be more specific

ObjFW 0.2.1 -> 0.3, 2010-05-09
 + Many new methods were added to different classes
 + A huge amount of methods was added to OFStream, allowing easy binary
   stream handling and even mixing string-based and binary operations
 + An optional write buffer was added to OFStream
 + OFSeekableStream was added for streams that allow seeking, for example
   OFFiles
 * OFNumber was completely reworked and got many new features now
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
 * The instance variable naming convention was changed so that properties work
 + Properties were added to the interfaces and are used if they are supported
   by the compiler
 + The library version is now included in the resulting dylib and libobjc is
   reexported now. Additionally, objfw-config offers --reexport now to produce
   libraries that link against ObjFW and reexport it

ObjFW 0.2 -> 0.2.1, 14.03.2010
 * Fix for OFNumbers not doing calculations
 * Improved -[hash] for OFNumbers with floats and doubles
 + Tests for OFNumber
 * Small optimization for OFArray's -[componentsJoinedByString:]
 * Documentation improvements
 * Updated copyright

ObjFW 0.1.2 -> 0.2, 01.02.2010
 + Support for ObjC 2 Fast Enumerations on every platform which has
   compiler support for fast enumerations
 + Support for ObjC 2 properties on every platform with compiler support
 + Fast Enumeration through arrays and dictionaries
 * OFIterator has been removed
 + OFEnumerator was added to replace OFIterator, which is more general
   and works with arrays and dictionaries







|







|







324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
 * The instance variable naming convention was changed so that properties work
 + Properties were added to the interfaces and are used if they are supported
   by the compiler
 + The library version is now included in the resulting dylib and libobjc is
   reexported now. Additionally, objfw-config offers --reexport now to produce
   libraries that link against ObjFW and reexport it

ObjFW 0.2 -> 0.2.1, 2010-03-14
 * Fix for OFNumbers not doing calculations
 * Improved -[hash] for OFNumbers with floats and doubles
 + Tests for OFNumber
 * Small optimization for OFArray's -[componentsJoinedByString:]
 * Documentation improvements
 * Updated copyright

ObjFW 0.1.2 -> 0.2, 2010-02-01
 + Support for ObjC 2 Fast Enumerations on every platform which has
   compiler support for fast enumerations
 + Support for ObjC 2 properties on every platform with compiler support
 + Fast Enumeration through arrays and dictionaries
 * OFIterator has been removed
 + OFEnumerator was added to replace OFIterator, which is more general
   and works with arrays and dictionaries
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
 * The interfaces of OFSocket and OFStream were cleaned up and some
   methods were moved to OFTCPSocket, as they make sense only there
 * File methods unavailable on Windows don't throw an exception at
   runtime anymore, but instead are not even in the interface on
   Windows. This way, it is a compile time error instead of a runtime
   error

ObjFW 0.1.1 -> 0.1.2, 15.01.2010
 * Fix a bug in OFMutableArray's -[removeObject:] and
   -[removeObjectIdenticalTo:] that could lead to not removing all
   occurrences of the object from the array and to out of bounds reads
 * Change the URL in the framework plist to the homepage

ObjFW 0.1 -> 0.1.1, 04.01.2010
 * Fix a missing out of range check for -[removeNItems:atIndex:] that
   allowed the programmer to specify too big ranges so it would crash
   instead of throwing an exception
 * Fix missing calls to -[retain] and -[autorelease] when getting
   objects from an OFArray or OFDictionary
 * Safer and more fault-tolerant way to remove objects from an
   OFMutableArray
 * Calling +[dealloc] throws an exception now. If someone really calls
   [SomeClass dealloc], this should be punished and not ignored, as
   this is a serious programmer error
 * -[readLineWithEncoding:] is more fault-tolerant now and does not
   lose data when it stumbles upon invalid encoding. Instead, it allows
   recalling with the correct encoding now

ObjFW 0.1, 24.12.2009
 + Initial release







|





|














|

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
 * The interfaces of OFSocket and OFStream were cleaned up and some
   methods were moved to OFTCPSocket, as they make sense only there
 * File methods unavailable on Windows don't throw an exception at
   runtime anymore, but instead are not even in the interface on
   Windows. This way, it is a compile time error instead of a runtime
   error

ObjFW 0.1.1 -> 0.1.2, 2010-01-15
 * Fix a bug in OFMutableArray's -[removeObject:] and
   -[removeObjectIdenticalTo:] that could lead to not removing all
   occurrences of the object from the array and to out of bounds reads
 * Change the URL in the framework plist to the homepage

ObjFW 0.1 -> 0.1.1, 2010-01-04
 * Fix a missing out of range check for -[removeNItems:atIndex:] that
   allowed the programmer to specify too big ranges so it would crash
   instead of throwing an exception
 * Fix missing calls to -[retain] and -[autorelease] when getting
   objects from an OFArray or OFDictionary
 * Safer and more fault-tolerant way to remove objects from an
   OFMutableArray
 * Calling +[dealloc] throws an exception now. If someone really calls
   [SomeClass dealloc], this should be punished and not ignored, as
   this is a serious programmer error
 * -[readLineWithEncoding:] is more fault-tolerant now and does not
   lose data when it stumbles upon invalid encoding. Instead, it allows
   recalling with the correct encoding now

ObjFW 0.1, 2009-12-24
 + Initial release

Modified Doxyfile from [6b8aa42255] to [68a4cb7d92].

1
2
3
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
PROJECT_NAME = "ObjFW"
OUTPUT_DIRECTORY = docs/
INPUT = src src/exceptions src/runtime
FILE_PATTERNS = *.h *.m
HTML_OUTPUT = .
HAVE_DOT = NO
GENERATE_LATEX = NO
HIDE_UNDOC_CLASSES = YES
HIDE_UNDOC_MEMBERS = YES
TYPEDEF_HIDES_STRUCT = YES
PREDEFINED = __OBJC__				\
	     _Nonnull=				\
	     _Nullable=				\
	     DOXYGEN				\
	     OF_BOXABLE=			\
	     OF_CONSUMED=			\
	     OF_DESIGNATED_INITIALIZER=		\





	     OF_GENERIC(...)=			\

	     OF_HAVE_BLOCKS			\
	     OF_HAVE_FILES			\



	     OF_HAVE_SANDBOX			\
	     OF_HAVE_SOCKETS			\
	     OF_HAVE_THREADS			\

	     OF_KINDOF(...)=			\
	     OF_NO_RETURN=			\
	     OF_NO_RETURN_FUNC=			\
	     OF_NULLABLE_PROPERTY(...)=		\
	     OF_NULL_RESETTABLE_PROPERTY(...)=	\
	     OF_REQUIRES_SUPER=			\
	     OF_RETURNS_INNER_POINTER=		\
	     OF_RETURNS_NOT_RETAINED=		\
	     OF_RETURNS_RETAINED=		\
	     OF_ROOT_CLASS=			\
	     OF_SENTINEL=			\
	     OF_WARN_UNUSED_RESULT=		\
	     OF_WEAK_UNAVAILABLE=		\
	     SIGHUP				\
	     SIGUSR1				\
	     SIGUSR2
MACRO_EXPANSION = YES
EXPAND_ONLY_PREDEF = YES
IGNORE_PREFIX = OF of_










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




1
2
3
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
PROJECT_NAME = "ObjFW"
OUTPUT_DIRECTORY = docs/
INPUT = src src/exceptions src/runtime
FILE_PATTERNS = *.h *.m
HTML_OUTPUT = .
HAVE_DOT = NO
GENERATE_LATEX = NO
HIDE_UNDOC_CLASSES = YES
HIDE_UNDOC_MEMBERS = YES
TYPEDEF_HIDES_STRUCT = YES
PREDEFINED = _Nonnull=						\

	     _Nullable=						\
	     DOXYGEN						\
	     OF_BOXABLE=					\
	     OF_CONSUMED=					\
	     OF_DESIGNATED_INITIALIZER=				\
	     OF_FILE_MANAGER_SUPPORTS_EXTENDED_ATTRIBUTES	\
	     OF_FILE_MANAGER_SUPPORTS_LINKS			\
	     OF_FILE_MANAGER_SUPPORTS_OWNER			\
	     OF_FILE_MANAGER_SUPPORTS_PERMISSIONS		\
	     OF_FILE_MANAGER_SUPPORTS_SYMLINKS			\
	     OF_GENERIC(...)=					\
	     OF_HAVE_APPLETALK					\
	     OF_HAVE_BLOCKS					\
	     OF_HAVE_FILES					\
	     OF_HAVE_IPV6					\
	     OF_HAVE_IPX					\
	     OF_HAVE_PLUGINS					\
	     OF_HAVE_SANDBOX					\
	     OF_HAVE_SOCKETS					\
	     OF_HAVE_THREADS					\
	     OF_HAVE_UNICODE_TABLES				\
	     OF_KINDOF(...)=					\
	     OF_NO_RETURN=					\
	     OF_NO_RETURN_FUNC=					\
	     OF_NULLABLE_PROPERTY(...)=				\
	     OF_NULL_RESETTABLE_PROPERTY(...)=			\
	     OF_REQUIRES_SUPER=					\
	     OF_RETURNS_INNER_POINTER=				\
	     OF_RETURNS_NOT_RETAINED=				\
	     OF_RETURNS_RETAINED=				\
	     OF_ROOT_CLASS=					\
	     OF_SENTINEL=					\
	     OF_WARN_UNUSED_RESULT=				\
	     OF_WEAK_UNAVAILABLE=				\
	     SIGHUP						\
	     SIGUSR1						\
	     SIGUSR2
MACRO_EXPANSION = YES
EXPAND_ONLY_PREDEF = YES
IGNORE_PREFIX = OF of_

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

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
	    config.h		\
	    config.log		\
	    config.status	\
	    extra.mk

include buildsys.mk

.PHONY: docs release

utils tests: src

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

docs:







|







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
	    config.h		\
	    config.log		\
	    config.status	\
	    extra.mk

include buildsys.mk

.PHONY: check docs release

utils tests: src

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

docs:
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
		--exclude '.fossil*,.git*' | ofarc -ttgz -xq -
	cp configure config.h.in objfw-${PACKAGE_VERSION}/
	ofarc -cq objfw-${PACKAGE_VERSION}.tar objfw-${PACKAGE_VERSION}
	rm -fr objfw-${PACKAGE_VERSION}
	gzip -9 objfw-${PACKAGE_VERSION}.tar
	rm -f objfw-${PACKAGE_VERSION}.tar
	gpg -b objfw-${PACKAGE_VERSION}.tar.gz || true
	echo "Generating documentation..."
	rm -fr docs
	doxygen >/dev/null
	rm -fr objfw-docs-${PACKAGE_VERSION} objfw-docs-${PACKAGE_VERSION}.tar \
		objfw-docs-${PACKAGE_VERSION}.tar.gz
	mv docs objfw-docs-${PACKAGE_VERSION}
	echo "Generating docs tarball for version ${PACKAGE_VERSION}..."
	ofarc -cq objfw-docs-${PACKAGE_VERSION}.tar \
		objfw-docs-${PACKAGE_VERSION}
	rm -fr objfw-docs-${PACKAGE_VERSION}
	gzip -9 objfw-docs-${PACKAGE_VERSION}.tar
	rm -f objfw-docs-${PACKAGE_VERSION}.tar
	gpg -b objfw-docs-${PACKAGE_VERSION}.tar.gz || true







<
<
<










31
32
33
34
35
36
37



38
39
40
41
42
43
44
45
46
47
		--exclude '.fossil*,.git*' | ofarc -ttgz -xq -
	cp configure config.h.in objfw-${PACKAGE_VERSION}/
	ofarc -cq objfw-${PACKAGE_VERSION}.tar objfw-${PACKAGE_VERSION}
	rm -fr objfw-${PACKAGE_VERSION}
	gzip -9 objfw-${PACKAGE_VERSION}.tar
	rm -f objfw-${PACKAGE_VERSION}.tar
	gpg -b objfw-${PACKAGE_VERSION}.tar.gz || true



	rm -fr objfw-docs-${PACKAGE_VERSION} objfw-docs-${PACKAGE_VERSION}.tar \
		objfw-docs-${PACKAGE_VERSION}.tar.gz
	mv docs objfw-docs-${PACKAGE_VERSION}
	echo "Generating docs tarball for version ${PACKAGE_VERSION}..."
	ofarc -cq objfw-docs-${PACKAGE_VERSION}.tar \
		objfw-docs-${PACKAGE_VERSION}
	rm -fr objfw-docs-${PACKAGE_VERSION}
	gzip -9 objfw-docs-${PACKAGE_VERSION}.tar
	rm -f objfw-docs-${PACKAGE_VERSION}.tar
	gpg -b objfw-docs-${PACKAGE_VERSION}.tar.gz || true

Modified PLATFORMS.md from [cb8b9b98c6] to [2210a2624d].

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
  * Runtimes: ObjFW


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

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


FreeBSD
-------

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











Haiku
-----

  * OS version: r1-alpha4
  * Architectures: x86
  * Compilers: Clang 3.2, GCC 4.6.3
  * Runtimes: ObjFW


HP-UX
-----

  * OS versions: 11i v1 (PA-RISC 2.0), 11i v3 (Itanium)
  * Architectures: Itanium, PA-RISC 2.0
  * Compilers: GCC 4.7.2, GCC 7.5.0
  * Runtimes: ObjFW
  * Notes: Exception handling on Itanium in 32 bit mode is broken, you need to
           use 64 bit mode by passing `OBJC="gcc -mlp64"` to `configure`.


iOS
---

  * Architectures: ARMv7, ARM64
  * Compilers: Clang
  * Runtimes: Apple


Linux
-----

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

  * Runtimes: ObjFW


macOS
-----

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


MiNT
----








|








|



>
>
>
>
>
>
>
>
>













|


















|
|
<

>







|







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
  * Runtimes: ObjFW


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

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


FreeBSD
-------

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


GNU/Hurd
--------

  * OS Versions: 0.9
  * Architectures: i686
  * Compilers: Clang 14.0.6
  * Runtimes: ObjFW


Haiku
-----

  * OS version: r1-alpha4
  * Architectures: x86
  * Compilers: Clang 3.2, GCC 4.6.3
  * Runtimes: ObjFW


HP-UX
-----

  * OS versions: 11i v1, 11i v3
  * Architectures: Itanium, PA-RISC 2.0
  * Compilers: GCC 4.7.2, GCC 7.5.0
  * Runtimes: ObjFW
  * Notes: Exception handling on Itanium in 32 bit mode is broken, you need to
           use 64 bit mode by passing `OBJC="gcc -mlp64"` to `configure`.


iOS
---

  * Architectures: ARMv7, ARM64
  * Compilers: Clang
  * Runtimes: Apple


Linux
-----

  * Architectures: Alpha, AMD64, ARMv6, ARMv7, ARM64, Itanium, m68k, MIPS (O32),
                   MIPS64 (N64), RISC-V 64, PowerPC, S390x, SuperH-4, x86

  * Compilers: Clang 3.0-10.0, GCC 4.6-10.0
  * C libraries: glibc, musl
  * Runtimes: ObjFW


macOS
-----

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


MiNT
----

125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
  * Runtimes: ObjFW


NetBSD
------

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


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








|
|







134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
  * Runtimes: ObjFW


NetBSD
------

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


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

165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
  * Limitations: No sockets, no shared libraries, not tested on real hardware


OpenBSD
-------

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


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








|







174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
  * Limitations: No sockets, no shared libraries, not tested on real hardware


OpenBSD
-------

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


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

192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
  * Compilers: GCC 4.6.1
  * Runtimes: ObjFW


Solaris
-------

  * OS Versions: OpenIndiana 2015.03
  * Architectures: x86, x86_64
  * Compilers: Clang 3.4.2, GCC 4.8.3
  * Runtimes: ObjFW


Wii
---

  * OS Versions: 4.3E / Homebrew Channel 1.1.0







|
|
|







201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
  * Compilers: GCC 4.6.1
  * Runtimes: ObjFW


Solaris
-------

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


Wii
---

  * OS Versions: 4.3E / Homebrew Channel 1.1.0
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
  * Limitations: No files, no threads, no sockets, no shared libraries, not
                 tested on real hardware


Windows
-------

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


Others
------








|
<
|
|

|







231
232
233
234
235
236
237
238

239
240
241
242
243
244
245
246
247
248
249
  * Limitations: No files, no threads, no sockets, no shared libraries, not
                 tested on real hardware


Windows
-------

  * OS Versions: 98 SE, NT 4.0, XP, 7, 8, 8.1, 10, 11, Wine

  * Architectures: AArch64, AMD64, x86
  * Compilers: GCC 5.3.0 & 6.2.0 from msys2 (AMD64 & x86),
               Clang 3.9.0 from msys2 (x86),
               Clang 10.0 from msys2 (AMD64 & x86),
               Clang 14.0.4 from msys2 (AArch64)
  * Runtimes: ObjFW


Others
------

252
253
254
255
256
257
258

259
260
261
262
263
264
265
266
267
268
269
==========

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


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

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







>







<



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

275
276
277
==========

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

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


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

Modified README.md from [711c05e9ce] to [6e10392554].

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

14
15
16
17
18
19
20
21
22
23
24
There are three ways you are probably reading this right now:

 * On [ObjFW](https://objfw.nil.im/)'s homepage, via Fossil's web interface
 * On [GitHub](https://github.com/ObjFW/ObjFW)
 * Via an editor or pager, by opening `README.md` from a clone or tarball

ObjFW is developed using Fossil, so if you are reading this on GitHub or any
other place, you are most likely using a mirror.


<h1 id="table-of-contents">Table of Contents</h1>

 * [What is ObjFW?](#what)

 * [License](#license)
 * [Releases](#releases)
 * [Cloning the repository](#cloning)
 * [Installation](#installation)
   * [macOS and iOS](#macos-and-ios)
     * [Building as a framework](#building-framework)
     * [Using the macOS or iOS framework in Xcode](#framework-in-xcode)
     * [Broken Xcode versions](#broken-xcode-versions)
   * [Windows](#windows)
     * [Getting MSYS2](#getting-msys2)
     * [Setting up MSYS2](#setting-up-msys2)













>



|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
There are three ways you are probably reading this right now:

 * On [ObjFW](https://objfw.nil.im/)'s homepage, via Fossil's web interface
 * On [GitHub](https://github.com/ObjFW/ObjFW)
 * Via an editor or pager, by opening `README.md` from a clone or tarball

ObjFW is developed using Fossil, so if you are reading this on GitHub or any
other place, you are most likely using a mirror.


<h1 id="table-of-contents">Table of Contents</h1>

 * [What is ObjFW?](#what)
 * [Installation](#installation)
 * [License](#license)
 * [Releases](#releases)
 * [Cloning the repository](#cloning)
 * [Building from source](#building-from-source)
   * [macOS and iOS](#macos-and-ios)
     * [Building as a framework](#building-framework)
     * [Using the macOS or iOS framework in Xcode](#framework-in-xcode)
     * [Broken Xcode versions](#broken-xcode-versions)
   * [Windows](#windows)
     * [Getting MSYS2](#getting-msys2)
     * [Setting up MSYS2](#setting-up-msys2)
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

  ObjFW is intentionally incompatible with Foundation. This has two reasons:

   * GNUstep already provides a reimplementation of Foundation, which is only
     compatible to a certain degree. This means that a developer still needs to
     care about differences between frameworks if they want to be portable. The
     idea behind ObjFW is that a developer does not need to concern themselves
     with portablility and making sure their code works with multiple
     frameworks: Instead, if it works it ObjFW on one platform, they can
     reasonably expect it to also work with ObjFW on another platform. ObjFW
     behaving differently on different operating systems (unless inevitable
     because it is a platform-specific part, like the Windows Registry) is
     considered a bug and will be fixed.
   * Foundation predates a lot of modern Objective-C concepts. The most
     prominent one is exceptions, which are only used in Foundation as a
     replacement for `abort()`. This results in cumbersome error handling,
     especially in initializers, which in Foundation only return `nil` on error
     with no indication of what went wrong. It also means that the return of
     every `init` call needs to be checked against `nil`. But in the wild,
     nobody actually checks *each and every* return from `init` against `nil`,
     leading to bugs. ObjFW fixes this by making exceptions a first class
     citizen.

  ObjFW also comes with its own lightweight and extremely fast Objective-C
  runtime, which in real world use cases was found to be significantly faster
  than both GNU's and Apple's runtime.




























<h1 id="license">License</h1>

  ObjFW is released under three licenses:

   * [QPL](LICENSE.QPL)
   * [GPLv2](LICENSE.GPLv2)
   * [GPLv3](LICENSE.GPLv3)

  The QPL allows you to use ObjFW in any open source project. Because the GPL
  does not allow using code under any other license, ObjFW is also available
  under the GPLv2 and GPLv3 to allow GPL-licensed projects to use ObjFW.

  You can pick under which of those three licenses you want to use ObjFW. If
  none of them work for you, contact me and we can find a solution.


<h1 id="releases">Releases</h1>

  Releases of ObjFW, as well as changelogs and the accompanying documentation
  can be found [here](https://objfw.nil.im/wiki?name=Releases).


<h1 id="cloning">Cloning the repository</h1>

  ObjFW is developed in a [Fossil](https://fossil-scm.org) repository, with
  automatic incremental exports to Git. This means you can either clone the







|



















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



















|







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

  ObjFW is intentionally incompatible with Foundation. This has two reasons:

   * GNUstep already provides a reimplementation of Foundation, which is only
     compatible to a certain degree. This means that a developer still needs to
     care about differences between frameworks if they want to be portable. The
     idea behind ObjFW is that a developer does not need to concern themselves
     with portability and making sure their code works with multiple
     frameworks: Instead, if it works it ObjFW on one platform, they can
     reasonably expect it to also work with ObjFW on another platform. ObjFW
     behaving differently on different operating systems (unless inevitable
     because it is a platform-specific part, like the Windows Registry) is
     considered a bug and will be fixed.
   * Foundation predates a lot of modern Objective-C concepts. The most
     prominent one is exceptions, which are only used in Foundation as a
     replacement for `abort()`. This results in cumbersome error handling,
     especially in initializers, which in Foundation only return `nil` on error
     with no indication of what went wrong. It also means that the return of
     every `init` call needs to be checked against `nil`. But in the wild,
     nobody actually checks *each and every* return from `init` against `nil`,
     leading to bugs. ObjFW fixes this by making exceptions a first class
     citizen.

  ObjFW also comes with its own lightweight and extremely fast Objective-C
  runtime, which in real world use cases was found to be significantly faster
  than both GNU's and Apple's runtime.


<h1 id="installation">Installation</h1>

  ObjFW packages are available for various operating systems and can be
  installed as following:

  Operating System           | Command
  ---------------------------|---------------------------------------------
  Alpine Linux               | `doas apk add objfw`
  CRUX                       | `sudo prt-get depinst objfw`
  Fedora                     | `sudo dnf install objfw`
  FreeBSD                    | `sudo pkg install objfw`
  Haiku                      | `pkgman install objfw`
  Haiku (gcc2h)              | `pkgman install objfw_x86`
  macOS (Homebrew)           | `brew install objfw`
  macOS (pkgsrc)             | `cd $PKGSRCDIR/devel/objfw && make install`
  NetBSD                     | `cd /usr/pkgsrc/devel/objfw && make install`
  OpenBSD                    | `doas pkg_add objfw`
  OpenIndiana                | `sudo pkg install developer/objfw`
  Windows (MSYS2/MINGW32)    | `pacman -S mingw-w64-i686-objfw`
  Windows (MSYS2/CLANG64)    | `pacman -S mingw-w64-clang-x86_64-objfw`
  Windows (MSYS2/CLANGARM64) | `pacman -S mingw-w64-clang-aarch64-objfw`

  If your operating system is not listed, you can
  <a href="#building-from-source">build ObjFW from source</a>.  


<h1 id="license">License</h1>

  ObjFW is released under three licenses:

   * [QPL](LICENSE.QPL)
   * [GPLv2](LICENSE.GPLv2)
   * [GPLv3](LICENSE.GPLv3)

  The QPL allows you to use ObjFW in any open source project. Because the GPL
  does not allow using code under any other license, ObjFW is also available
  under the GPLv2 and GPLv3 to allow GPL-licensed projects to use ObjFW.

  You can pick under which of those three licenses you want to use ObjFW. If
  none of them work for you, contact me and we can find a solution.


<h1 id="releases">Releases</h1>

  Releases of ObjFW, as well as change logs and the accompanying documentation,
  can be found [here](https://objfw.nil.im/wiki?name=Releases).


<h1 id="cloning">Cloning the repository</h1>

  ObjFW is developed in a [Fossil](https://fossil-scm.org) repository, with
  automatic incremental exports to Git. This means you can either clone the
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

  You can then use Fossil's web interface to browse the timeline, tickets,
  wiki pages, etc.:

    $ cd objfw
    $ fossil ui

  It's also possible to open the same local repository multiple times, so that
  you have multiple working directories all backed by the same local
  repository.

  In order to verify the signature of the currently checked out checkin, you
  can use:

    $ fossil artifact current | gpg --verify

  Please note that not all checkins are signed, as the signing key only resides
  on trusted systems. This means that checkins I perform on e.g. Windows are
  unsigned. However, usually it should not take long until there is another
  signed checkin. Alternatively, you can go back until the last signed checkin
  and review changes from there on.

<h2 id="cloning-git">Git</h2>

  To clone the Git repository, use the following:

    $ git clone https://github.com/ObjFW/ObjFW

  Git commits are not signed, so if you want to check the signature of an
  individual commit, branch head or tag, please use Fossil.

<h1 id="installation">Installation</h1>

  To install ObjFW, just run the following commands:

    $ ./configure
    $ make
    $ make check
    $ sudo make install

  In case you checked out ObjFW from the Fossil or Git repository, you need to
  run the following command first:

    $ ./autogen.sh

<h2 id="macos-and-ios">macOS and iOS</h2>

<h3 id="building-framework">Building as a framework</h3>

  When building for macOS or iOS, everything is built as a `.framework` by
  default if `--disable-shared` has not been specified to `./configure`. The
  frameworks will end up in `$PREFIX/Library/Frameworks`.

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

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

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

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

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

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

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

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







<
<
<
<




















|

|




















|




|
|
|
|





|
|
<
|
|







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

  You can then use Fossil's web interface to browse the timeline, tickets,
  wiki pages, etc.:

    $ cd objfw
    $ fossil ui





  In order to verify the signature of the currently checked out checkin, you
  can use:

    $ fossil artifact current | gpg --verify

  Please note that not all checkins are signed, as the signing key only resides
  on trusted systems. This means that checkins I perform on e.g. Windows are
  unsigned. However, usually it should not take long until there is another
  signed checkin. Alternatively, you can go back until the last signed checkin
  and review changes from there on.

<h2 id="cloning-git">Git</h2>

  To clone the Git repository, use the following:

    $ git clone https://github.com/ObjFW/ObjFW

  Git commits are not signed, so if you want to check the signature of an
  individual commit, branch head or tag, please use Fossil.

<h1 id="building-from-source">Building from source</h1>

  To build ObjFW from source and install it, just run the following commands:

    $ ./configure
    $ make
    $ make check
    $ sudo make install

  In case you checked out ObjFW from the Fossil or Git repository, you need to
  run the following command first:

    $ ./autogen.sh

<h2 id="macos-and-ios">macOS and iOS</h2>

<h3 id="building-framework">Building as a framework</h3>

  When building for macOS or iOS, everything is built as a `.framework` by
  default if `--disable-shared` has not been specified to `./configure`. The
  frameworks will end up in `$PREFIX/Library/Frameworks`.

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

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

    $ clang="xcrun --sdk iphoneos clang"
    $ export OBJC="$clang -arch arm64e -arch arm64"
    $ export OBJCPP="$clang -arch arm64e -E"
    $ export IPHONEOS_DEPLOYMENT_TARGET="10.0"
    $ ./configure --prefix=/usr/local/ios --host=arm64-apple-darwin

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

    $ clang="xcrun --sdk iphonesimulator clang"
    $ export OBJC="$clang -arch $(uname -m)"

    $ export IPHONEOS_DEPLOYMENT_TARGET="10.0"
    $ ./configure --prefix=/usr/local/iossim --host=$(uname -m)-apple-darwin

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

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

    -fconstant-string-class=OFConstantString -fno-constant-cfstrings
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333

<h1 id="first-app">Writing your first application with ObjFW</h1>

  To create your first, empty application, you can use `objfw-new`:

    $ objfw-new --app MyFirstApp

  This creates a file `MyFirstApp.m`. The `-[applicationDidFinishLaunching]`
  method is called as soon as ObjFW finished all initialization. Use this as
  the entry point to your own code. For example, you could add the following
  line there to create a "Hello World":

    [OFStdOut writeLine: @"Hello World!"];

  You can compile your new app using `objfw-compile`:







|







341
342
343
344
345
346
347
348
349
350
351
352
353
354
355

<h1 id="first-app">Writing your first application with ObjFW</h1>

  To create your first, empty application, you can use `objfw-new`:

    $ objfw-new --app MyFirstApp

  This creates a file `MyFirstApp.m`. The `-[applicationDidFinishLaunching:]`
  method is called as soon as ObjFW finished all initialization. Use this as
  the entry point to your own code. For example, you could add the following
  line there to create a "Hello World":

    [OFStdOut writeLine: @"Hello World!"];

  You can compile your new app using `objfw-compile`:
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
<h1 id="support">Support and community</h1>

  If you have any questions about ObjFW or would like to talk to other ObjFW
  users, the following venues are available:

   * The [forum](https://objfw.nil.im/forum)
   * A [Matrix room](https://matrix.to/#/%23objfw:nil.im)





   * An IRC channel named `#objfw` on `irc.oftc.net`
     ([Web chat](https://webchat.oftc.net/?channels=%23objfw)), bridged to the
     Matrix room above
   * A [Slack channel](https://objfw.nil.im/slack), bridged to the Matrix room
     above
   * A [Discord channel](https://objfw.nil.im/discord), bridged to the Matrix
     room above
   * A [Telegram room](https://t.me/objfw), bridged to the Matrix room above
   * A [Gitter room](https://gitter.im/ObjFW/ObjFW), bridged to the Matrix room
     above

  Please don't hesitate to join any or all of those!


<h1 id="donating">Donating</h1>

  If you want to donate to ObjFW, you can read about possible ways to do so
  [here](https://objfw.nil.im/wiki?name=Donating).


<h1 id="thanks">Thanks</h1>

  * Thank you to [Jonathan Neuschäfer](https://github.com/neuschaefer) for
    reviewing the *entirety* (all 84k LoC at the time) of ObjFW's codebase in
    2017!
  * Thank you to [Hill Ma](https://github.com/mahiuchun) for donating an M1 Mac
    Mini to the project!


<h1 id="commercial-use">Commercial use</h1>

  If for whatever reason neither the terms of the QPL nor those of the GPL work
  for you, a proprietary license for ObjFW including support is available upon
  request. Just write a mail to js@nil.im and we can find a reasonable solution
  for both parties.







>
>
>
>
>



<
<
<
<
<
<
<
















|








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
<h1 id="support">Support and community</h1>

  If you have any questions about ObjFW or would like to talk to other ObjFW
  users, the following venues are available:

   * The [forum](https://objfw.nil.im/forum)
   * A [Matrix room](https://matrix.to/#/%23objfw:nil.im)
   * A [Discord room](https://objfw.nil.im/discord), bridged to the Matrix
     room above
   * A [Telegram room](https://t.me/objfw), bridged to the Matrix room above
   * A [Slack room](https://objfw.nil.im/slack), bridged to the Matrix room
     above
   * An IRC channel named `#objfw` on `irc.oftc.net`
     ([Web chat](https://webchat.oftc.net/?channels=%23objfw)), bridged to the
     Matrix room above








  Please don't hesitate to join any or all of those!


<h1 id="donating">Donating</h1>

  If you want to donate to ObjFW, you can read about possible ways to do so
  [here](https://objfw.nil.im/wiki?name=Donating).


<h1 id="thanks">Thanks</h1>

  * Thank you to [Jonathan Neuschäfer](https://github.com/neuschaefer) for
    reviewing the *entirety* (all 84k LoC at the time) of ObjFW's codebase in
    2017!
  * Thank you to [Hill Ma](https://github.com/mahiuchun) for donating an M1 Mac
    Mini to the project in 2022!


<h1 id="commercial-use">Commercial use</h1>

  If for whatever reason neither the terms of the QPL nor those of the GPL work
  for you, a proprietary license for ObjFW including support is available upon
  request. Just write a mail to js@nil.im and we can find a reasonable solution
  for both parties.

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

1
2
3
4

5
6
7

8
9
10
11
#!/bin/sh
set -e

# Set a version for OpenBSD

: ${AUTOCONF_VERSION:=2.69}
: ${AUTOMAKE_VERSION:=1.16}
export AUTOCONF_VERSION AUTOMAKE_VERSION


aclocal -I build-aux/m4
autoconf
autoheader




>
|
|
|
>




1
2
3
4
5
6
7
8
9
10
11
12
13
#!/bin/sh
set -e

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

aclocal -I build-aux/m4
autoconf
autoheader

Modified build-aux/m4/buildsys.m4 from [0e90ccf38e] to [8bcbdfb241].

1
2
3
4
5
6
7
8
9
10
dnl
dnl Copyright (c) 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2016, 2017,
dnl               2018, 2020, 2021
dnl   Jonathan Schleifer <js@nil.im>
dnl
dnl https://fossil.nil.im/buildsys
dnl
dnl Permission to use, copy, modify, and/or distribute this software for any
dnl purpose with or without fee is hereby granted, provided that the above
dnl copyright notice and this permission notice is present in all copies.


|







1
2
3
4
5
6
7
8
9
10
dnl
dnl Copyright (c) 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2016, 2017,
dnl               2018, 2020, 2021, 2022, 2023
dnl   Jonathan Schleifer <js@nil.im>
dnl
dnl https://fossil.nil.im/buildsys
dnl
dnl Permission to use, copy, modify, and/or distribute this software for any
dnl purpose with or without fee is hereby granted, provided that the above
dnl copyright notice and this permission notice is present in all copies.
25
26
27
28
29
30
31




32
33
34
35
36
37
38
AC_DEFUN([BUILDSYS_INIT], [
	AC_REQUIRE([AC_CANONICAL_BUILD])
	AC_REQUIRE([AC_CANONICAL_HOST])

	AC_ARG_ENABLE(rpath,
		AS_HELP_STRING([--disable-rpath], [do not use rpath]))





	case "$build_os" in
	darwin*)
		case "$host_os" in
		darwin*)
			AC_SUBST(BUILD_AND_HOST_ARE_DARWIN, yes)
			;;
		esac







>
>
>
>







25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
AC_DEFUN([BUILDSYS_INIT], [
	AC_REQUIRE([AC_CANONICAL_BUILD])
	AC_REQUIRE([AC_CANONICAL_HOST])

	AC_ARG_ENABLE(rpath,
		AS_HELP_STRING([--disable-rpath], [do not use rpath]))

	AC_ARG_ENABLE(silent-rules,
		AS_HELP_STRING([--disable-silent-rules],
			[print executed commands during build]))

	case "$build_os" in
	darwin*)
		case "$host_os" in
		darwin*)
			AC_SUBST(BUILD_AND_HOST_ARE_DARWIN, yes)
			;;
		esac
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
					"$($TPUT AF 3 2>/dev/null)")
				AC_SUBST(TERM_SETAF4,
					"$($TPUT AF 4 2>/dev/null)")
				AC_SUBST(TERM_SETAF6,
					"$($TPUT AF 6 2>/dev/null)")
			fi
		])





	])
])

AC_DEFUN([BUILDSYS_CHECK_IOS], [
	case "$host_os" in
	darwin*)
		AC_MSG_CHECKING(whether host is iOS)
		AC_EGREP_CPP(yes, [
			#include <TargetConditionals.h>

			#if (defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE) || \
			    (defined(TARGET_OS_SIMULATOR) && \
			    TARGET_OS_SIMULATOR)
			yes
			#endif
		], [
			host_is_ios="yes"

		], [
			host_is_ios="no"
		])
		AC_MSG_RESULT($host_is_ios)

		;;
	esac
])

AC_DEFUN([BUILDSYS_PROG_IMPLIB], [
	AC_REQUIRE([AC_CANONICAL_HOST])
	AC_MSG_CHECKING(whether we need an implib)







>
>
>
>
>

















>




>







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
					"$($TPUT AF 3 2>/dev/null)")
				AC_SUBST(TERM_SETAF4,
					"$($TPUT AF 4 2>/dev/null)")
				AC_SUBST(TERM_SETAF6,
					"$($TPUT AF 6 2>/dev/null)")
			fi
		])

		AS_IF([test x"$enable_silent_rules" != x"no"], [
			AC_SUBST(SILENT, '.SILENT:')
			AC_SUBST(MAKEFLAGS_SILENT, '-s')
		])
	])
])

AC_DEFUN([BUILDSYS_CHECK_IOS], [
	case "$host_os" in
	darwin*)
		AC_MSG_CHECKING(whether host is iOS)
		AC_EGREP_CPP(yes, [
			#include <TargetConditionals.h>

			#if (defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE) || \
			    (defined(TARGET_OS_SIMULATOR) && \
			    TARGET_OS_SIMULATOR)
			yes
			#endif
		], [
			host_is_ios="yes"
			AC_SUBST(HOST_IS_IOS, yes)
		], [
			host_is_ios="no"
		])
		AC_MSG_RESULT($host_is_ios)
		AC_CHECK_TOOL(CODESIGN, codesign)
		;;
	esac
])

AC_DEFUN([BUILDSYS_PROG_IMPLIB], [
	AC_REQUIRE([AC_CANONICAL_HOST])
	AC_MSG_CHECKING(whether we need an implib)
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372

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
























































	AC_SUBST(PROG_IMPLIB_NEEDED)
	AC_SUBST(PROG_IMPLIB_LDFLAGS)
])

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

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

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

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

	AC_CHECK_TOOL(CODESIGN, codesign)

	case "$host_os" in
	darwin*)
		AS_IF([test x"$host_is_ios" = x"yes"], [
			FRAMEWORK_LDFLAGS='-dynamiclib -current_version ${LIB_MAJOR}.${LIB_MINOR} -compatibility_version ${LIB_MAJOR}'

			FRAMEWORK_LDFLAGS_INSTALL_NAME='-Wl,-install_name,@executable_path/Frameworks/$$out/$${out%.framework}'
		], [
			FRAMEWORK_LDFLAGS='-dynamiclib -current_version ${LIB_MAJOR}.${LIB_MINOR} -compatibility_version ${LIB_MAJOR}'
			FRAMEWORK_LDFLAGS_INSTALL_NAME='-Wl,-install_name,@executable_path/../Frameworks/$$out/$${out%.framework}'
		])

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

		$1
		;;
	esac
])































































|












<
<
<
<
<
<
<
<


<
<










<
<
<
<


<
<












<
<
<
<


<
<












<
<
<
<


<
<









<
<
<
<
|
|
<
<













<
<
<
<


<
<













<
<
<
<


<
<












<
<
<
<
|
|
<
<











<
<
<
<


<
<








<
<


<
|
>


<











>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
	AC_SUBST(PROG_IMPLIB_NEEDED)
	AC_SUBST(PROG_IMPLIB_LDFLAGS)
])

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

	case "$host" in
	*-*-darwin*)
		AC_MSG_RESULT(Darwin)
		LIB_CFLAGS='-fPIC -DPIC'
		LIB_LDFLAGS='-dynamiclib -current_version ${LIB_MAJOR}.${LIB_MINOR} -compatibility_version ${LIB_MAJOR}'
		LIB_LDFLAGS_INSTALL_NAME='-Wl,-install_name,${libdir}/$${out%.dylib}.${LIB_MAJOR}.dylib'
		LIB_PREFIX='lib'
		LIB_SUFFIX='.dylib'
		AS_IF([test x"$enable_rpath" != x"no"], [
			LDFLAGS_RPATH='-Wl,-rpath,${libdir}'
		])








		INSTALL_LIB='&& ${INSTALL} -m 755 $$i ${DESTDIR}${libdir}/$${i%.dylib}.${LIB_MAJOR}.${LIB_MINOR}.dylib && ${LN_S} -f $${i%.dylib}.${LIB_MAJOR}.${LIB_MINOR}.dylib ${DESTDIR}${libdir}/$${i%.dylib}.${LIB_MAJOR}.dylib && ${LN_S} -f $${i%.dylib}.${LIB_MAJOR}.${LIB_MINOR}.dylib ${DESTDIR}${libdir}/$$i'
		UNINSTALL_LIB='&& rm -f ${DESTDIR}${libdir}/$$i ${DESTDIR}${libdir}/$${i%.dylib}.${LIB_MAJOR}.dylib ${DESTDIR}${libdir}/$${i%.dylib}.${LIB_MAJOR}.${LIB_MINOR}.dylib'


		CLEAN_LIB=''
		;;
	*-*-mingw* | *-*-cygwin*)
		AC_MSG_RESULT(MinGW / Cygwin)
		LIB_CFLAGS=''
		LIB_LDFLAGS='-shared -Wl,--export-all-symbols'
		LIB_LDFLAGS_INSTALL_NAME=''
		LIB_PREFIX=''
		LIB_SUFFIX='${LIB_MAJOR}.dll'
		LINK_LIB='&& rm -f lib$${out%${LIB_SUFFIX}}.dll.a && ${LN_S} $$out lib$${out%${LIB_SUFFIX}}.dll.a'




		INSTALL_LIB='&& ${MKDIR_P} ${DESTDIR}${bindir} && ${INSTALL} -m 755 $$i ${DESTDIR}${bindir}/$$i && ${INSTALL} -m 755 lib$${i%${LIB_SUFFIX}}.dll.a ${DESTDIR}${libdir}/lib$${i%${LIB_SUFFIX}}.dll.a'
		UNINSTALL_LIB='&& rm -f ${DESTDIR}${bindir}/$$i ${DESTDIR}${libdir}/lib$${i%${LIB_SUFFIX}}.dll.a'


		CLEAN_LIB='${SHARED_LIB}.a ${SHARED_LIB_NOINST}.a'
		;;
	*-*-openbsd* | *-*-mirbsd*)
		AC_MSG_RESULT(OpenBSD)
		LIB_CFLAGS='-fPIC -DPIC'
		LIB_LDFLAGS='-shared'
		LIB_LDFLAGS_INSTALL_NAME=''
		LIB_PREFIX='lib'
		LIB_SUFFIX='.so.${LIB_MAJOR}.${LIB_MINOR}'
		AS_IF([test x"$enable_rpath" != x"no"], [
			LDFLAGS_RPATH='-Wl,-rpath,${libdir}'
		])




		INSTALL_LIB='&& ${INSTALL} -m 755 $$i ${DESTDIR}${libdir}/$$i'
		UNINSTALL_LIB='&& rm -f ${DESTDIR}${libdir}/$$i'


		CLEAN_LIB=''
		;;
	*-*-solaris*)
		AC_MSG_RESULT(Solaris)
		LIB_CFLAGS='-fPIC -DPIC'
		LIB_LDFLAGS='-shared -Wl,-soname=$$out.${LIB_MAJOR}.${LIB_MINOR}'
		LIB_LDFLAGS_INSTALL_NAME=''
		LIB_PREFIX='lib'
		LIB_SUFFIX='.so'
		AS_IF([test x"$enable_rpath" != x"no"], [
			LDFLAGS_RPATH='-Wl,-rpath,${libdir}'
		])




		INSTALL_LIB='&& ${INSTALL} -m 755 $$i ${DESTDIR}${libdir}/$$i.${LIB_MAJOR}.${LIB_MINOR} && rm -f ${DESTDIR}${libdir}/$$i && ${LN_S} $$i.${LIB_MAJOR}.${LIB_MINOR} ${DESTDIR}${libdir}/$$i'
		UNINSTALL_LIB='&& rm -f ${DESTDIR}${libdir}/$$i ${DESTDIR}${libdir}/$$i.${LIB_MAJOR}.${LIB_MINOR}'


		CLEAN_LIB=''
		;;
	*-*-android*)
		AC_MSG_RESULT(Android)
		LIB_CFLAGS='-fPIC -DPIC'
		LIB_LDFLAGS='-shared -Wl,-soname=$$out.${LIB_MAJOR}'
		LIB_LDFLAGS_INSTALL_NAME=''
		LIB_PREFIX='lib'
		LIB_SUFFIX='.so'




		INSTALL_LIB='&& ${INSTALL} -m 755 $$i ${DESTDIR}${libdir}/$$i.${LIB_MAJOR}.${LIB_MINOR}.${LIB_PATCH} && ${LN_S} -f $$i.${LIB_MAJOR}.${LIB_MINOR}.${LIB_PATCH} ${DESTDIR}${libdir}/$$i.${LIB_MAJOR} && ${LN_S} -f $$i.${LIB_MAJOR}.${LIB_MINOR}.${LIB_PATCH} ${DESTDIR}${libdir}/$$i'
		UNINSTALL_LIB='&& rm -f ${DESTDIR}${libdir}/$$i ${DESTDIR}${libdir}/$$i.${LIB_MAJOR} ${DESTDIR}${libdir}/$$i.${LIB_MAJOR}.${LIB_MINOR}.${LIB_PATCH}'


		CLEAN_LIB=''
		;;
	hppa*-*-hpux*)
		AC_MSG_RESULT([HP-UX (PA-RISC)])
		LIB_CFLAGS='-fPIC -DPIC'
		LIB_LDFLAGS='-shared -Wl,+h,$$out'
		LIB_LDFLAGS_INSTALL_NAME=''
		LIB_PREFIX='lib'
		LIB_SUFFIX='.${LIB_MAJOR}'
		LINK_LIB='&& rm -f $${out%%.*}.sl && ${LN_S} $$out $${out%%.*}.sl'
		AS_IF([test x"$enable_rpath" != x"no"], [
			LDFLAGS_RPATH='-Wl,+b,${libdir}'
		])




		INSTALL_LIB='&& ${INSTALL} -m 755 $$i ${DESTDIR}${libdir}/$$i && ${LN_S} -f $$i ${DESTDIR}${libdir}/$${i%%.*}.sl'
		UNINSTALL_LIB='&& rm -f ${DESTDIR}${libdir}/$$i ${DESTDIR}${libdir}/$${i%%.*}.sl'


		CLEAN_LIB=''
		;;
	ia64*-*-hpux*)
		AC_MSG_RESULT([HP-UX (Itanium)])
		LIB_CFLAGS='-fPIC -DPIC'
		LIB_LDFLAGS='-shared -Wl,+h,$$out'
		LIB_LDFLAGS_INSTALL_NAME=''
		LIB_PREFIX='lib'
		LIB_SUFFIX='.${LIB_MAJOR}'
		LINK_LIB='&& rm -f $${out%%.*}.so && ${LN_S} $$out $${out%%.*}.so'
		AS_IF([test x"$enable_rpath" != x"no"], [
			LDFLAGS_RPATH='-Wl,+b,${libdir}'
		])




		INSTALL_LIB='&& ${INSTALL} -m 755 $$i ${DESTDIR}${libdir}/$$i && ${LN_S} -f $$i ${DESTDIR}${libdir}/$${i%%.*}.so'
		UNINSTALL_LIB='&& rm -f ${DESTDIR}${libdir}/$$i ${DESTDIR}${libdir}/$${i%%.*}.so'


		CLEAN_LIB=''
		;;
	*)
		AC_MSG_RESULT(ELF)
		LIB_CFLAGS='-fPIC -DPIC'
		LIB_LDFLAGS='-shared -Wl,-soname=$$out.${LIB_MAJOR}'
		LIB_LDFLAGS_INSTALL_NAME=''
		LIB_PREFIX='lib'
		LIB_SUFFIX='.so'
		AS_IF([test x"$enable_rpath" != x"no"], [
			LDFLAGS_RPATH='-Wl,-rpath,${libdir}'
		])




		INSTALL_LIB='&& ${INSTALL} -m 755 $$i ${DESTDIR}${libdir}/$$i.${LIB_MAJOR}.${LIB_MINOR}.${LIB_PATCH} && ${LN_S} -f $$i.${LIB_MAJOR}.${LIB_MINOR}.${LIB_PATCH} ${DESTDIR}${libdir}/$$i.${LIB_MAJOR} && ${LN_S} -f $$i.${LIB_MAJOR}.${LIB_MINOR}.${LIB_PATCH} ${DESTDIR}${libdir}/$$i'
		UNINSTALL_LIB='&& rm -f ${DESTDIR}${libdir}/$$i ${DESTDIR}${libdir}/$$i.${LIB_MAJOR} ${DESTDIR}${libdir}/$$i.${LIB_MAJOR}.${LIB_MINOR}.${LIB_PATCH}'


		CLEAN_LIB=''
		;;
	esac

	AC_SUBST(LIB_CFLAGS)
	AC_SUBST(LIB_LDFLAGS)
	AC_SUBST(LIB_LDFLAGS_INSTALL_NAME)
	AC_SUBST(LIB_PREFIX)
	AC_SUBST(LIB_SUFFIX)
	AC_SUBST(LINK_LIB)
	AC_SUBST(LDFLAGS_RPATH)




	AC_SUBST(INSTALL_LIB)
	AC_SUBST(UNINSTALL_LIB)


	AC_SUBST(CLEAN_LIB)
])

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



	case "$host_os" in
	darwin*)

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

			FRAMEWORK_LDFLAGS_INSTALL_NAME='-Wl,-install_name,@executable_path/../Frameworks/$$out/$${out%.framework}'
		])

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

		$1
		;;
	esac
])

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

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

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

Modified buildsys.mk.in from [2dfee6e012] to [2c79875d24].

1
2
3
4
5
6
7
8
9
10
#
#  Copyright (c) 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016,
#                2017, 2018, 2020, 2021
#    Jonathan Schleifer <js@nil.im>
#
#  https://fossil.nil.im/buildsys
#
#  Permission to use, copy, modify, and/or distribute this software for any
#  purpose with or without fee is hereby granted, provided that the above
#  copyright notice and this permission notice is present in all copies.


|







1
2
3
4
5
6
7
8
9
10
#
#  Copyright (c) 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016,
#                2017, 2018, 2020, 2021, 2022, 2023
#    Jonathan Schleifer <js@nil.im>
#
#  https://fossil.nil.im/buildsys
#
#  Permission to use, copy, modify, and/or distribute this software for any
#  purpose with or without fee is hereby granted, provided that the above
#  copyright notice and this permission notice is present in all copies.
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
DEPS = ${OBJS:.o=.dep}			\
       ${LIB_OBJS:.o=.dep}		\
       ${AMIGA_LIB_OBJS:.o=.dep}	\
       ${PLUGIN_OBJS:.o=.dep}

MO_FILES = ${LOCALES:.po=.mo}

.SILENT:
.SUFFIXES:
.SUFFIXES: .amigalib.o .beam .c .cc .class .cxx .d .erl .lib.o .java .mo .m .mm .o .plugin.o .po .py .pyc .rc .S .xpm

.PHONY: all subdirs subdirs-after pre-depend depend install install-extra uninstall uninstall-extra clean distclean locales copy-headers-into-framework ${SUBDIRS} ${SUBDIRS_AFTER}



all:
	${MAKE} -s pre-all

	${MAKE} -s subdirs
	${MAKE} -s depend

	${MAKE} -s ${STATIC_LIB} ${STATIC_LIB_NOINST} ${STATIC_PIC_LIB} ${STATIC_PIC_LIB_NOINST} ${STATIC_AMIGA_LIB} ${STATIC_AMIGA_LIB_NOINST} ${SHARED_LIB} ${SHARED_LIB_NOINST} ${FRAMEWORK} ${FRAMEWORK_NOINST} ${AMIGA_LIB} ${AMIGA_LIB_NOINST} ${PLUGIN} ${PLUGIN_NOINST} ${PROG} ${PROG_NOINST} ${JARFILE} locales







	${MAKE} -s subdirs-after
	${MAKE} -s post-all

pre-all post-all:

subdirs: ${SUBDIRS}
subdirs-after: ${SUBDIRS_AFTER}

${SUBDIRS} ${SUBDIRS_AFTER}:
	for i in $@; do \
		${DIR_ENTER}; \
		${MAKE} -s || exit $$?; \
		${DIR_LEAVE}; \
	done

depend: pre-depend
	: >.deps
	for i in "" ${DEPS}; do \
		test x"$$i" = x"" && continue; \







|

|
>
|
>
>


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









|







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
DEPS = ${OBJS:.o=.dep}			\
       ${LIB_OBJS:.o=.dep}		\
       ${AMIGA_LIB_OBJS:.o=.dep}	\
       ${PLUGIN_OBJS:.o=.dep}

MO_FILES = ${LOCALES:.po=.mo}

@SILENT@
.SUFFIXES:
.SUFFIXES: .amigalib.o .beam .c .cc .class .cxx .d .erl .lib.o .java	\
	   .mo .m .mm .o .plugin.o .po .py .pyc .rc .S .xpm
.PHONY: all subdirs subdirs-after pre-depend depend install		\
	install-extra uninstall uninstall-extra clean distclean locales	\
	copy-headers-into-framework ${SUBDIRS} ${SUBDIRS_AFTER}

all:
	${MAKE} @MAKEFLAGS_SILENT@ pre-all
	${MAKE} @MAKEFLAGS_SILENT@ subdirs
	${MAKE} @MAKEFLAGS_SILENT@ depend
	${MAKE} @MAKEFLAGS_SILENT@				\
	    ${STATIC_LIB} ${STATIC_LIB_NOINST}			\
	    ${STATIC_PIC_LIB} ${STATIC_PIC_LIB_NOINST}		\
	    ${STATIC_AMIGA_LIB}${STATIC_AMIGA_LIB_NOINST}	\
	    ${SHARED_LIB} ${SHARED_LIB_NOINST}			\
	    ${FRAMEWORK} ${FRAMEWORK_NOINST}			\
	    ${AMIGA_LIB} ${AMIGA_LIB_NOINST}			\
	    ${PLUGIN} ${PLUGIN_NOINST}				\
	    ${PROG} ${PROG_NOINST}				\
	    ${JARFILE} locales
	${MAKE} @MAKEFLAGS_SILENT@ subdirs-after
	${MAKE} @MAKEFLAGS_SILENT@ post-all

pre-all post-all:

subdirs: ${SUBDIRS}
subdirs-after: ${SUBDIRS_AFTER}

${SUBDIRS} ${SUBDIRS_AFTER}:
	for i in $@; do \
		${DIR_ENTER}; \
		${MAKE} @MAKEFLAGS_SILENT@ || exit $$?; \
		${DIR_LEAVE}; \
	done

depend: pre-depend
	: >.deps
	for i in "" ${DEPS}; do \
		test x"$$i" = x"" && continue; \
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
	else \
		${LINK_FAILED}; \
	fi

${JARFILE}: ${EXT_DEPS} ${JAR_MANIFEST} ${OBJS} ${OBJS_EXTRA}
	${LINK_STATUS}
	if test x"${JAR_MANIFEST}" != x""; then \
		if ${JAR} cfm ${JARFILE} ${JAR_MANIFEST} ${OBJS} ${OBJS_EXTRA}; then \

			${LINK_OK}; \
		else \
			${LINK_FAILED}; \
		fi \
	else \
		if ${JAR} cf ${JARFILE} ${OBJS} ${OBJS_EXTRA}; then \
			${LINK_OK}; \
		else \
			${LINK_FAILED}; \
		fi \
	fi

${SHARED_LIB} ${SHARED_LIB_NOINST}: ${EXT_DEPS} ${LIB_OBJS} ${LIB_OBJS_EXTRA}
	${LINK_STATUS}
	out="$@"; \
	if ${LD} -o $@ ${LIB_OBJS} ${LIB_OBJS_EXTRA} ${LIB_LDFLAGS} ${LIB_LDFLAGS_INSTALL_NAME} ${LDFLAGS} ${LIBS} ${LINK_LIB}; then \

		${LINK_OK}; \
	else \
		${LINK_FAILED}; \
	fi

${FRAMEWORK} ${FRAMEWORK_NOINST}: ${EXT_DEPS} ${LIB_OBJS} ${LIB_OBJS_EXTRA}
	${LINK_STATUS}
	out="$@"; \




	if rm -fr $$out && ${MKDIR_P} $$out && ${MAKE} -s COPY_HEADERS_IF_SUBDIR=${includesubdir} COPY_HEADERS_DESTINATION=$$PWD/$@/Headers copy-headers-into-framework && if test -f Info.plist; then ${INSTALL} -m 644 Info.plist $$out/Info.plist; fi && if test -f module.modulemap; then ${MKDIR_P} $$out/Modules && ${INSTALL} -m 644 module.modulemap $$out/Modules/module.modulemap; fi && ${LD} -o $$out/$${out%.framework} ${LIB_OBJS} ${LIB_OBJS_EXTRA} ${FRAMEWORK_LDFLAGS} ${FRAMEWORK_LDFLAGS_INSTALL_NAME} ${LDFLAGS} ${FRAMEWORK_LIBS} && ${CODESIGN} -fs ${CODESIGN_IDENTITY} $$out; then \














		${LINK_OK}; \
	else \
		rm -fr $$out; false; \
		${LINK_FAILED}; \



































	fi

copy-headers-into-framework:
	for i in "" ${SUBDIRS} ${SUBDIRS_AFTER}; do \
		test x"$$i" = x"" && continue; \
		cd $$i || exit 1; \
		${MAKE} -s copy-headers-into-framework || exit $$?; \

		cd .. || exit 1; \
	done

	if test x"${includesubdir}" = x"${COPY_HEADERS_IF_SUBDIR}"; then \
		for i in "" ${INCLUDES}; do \
			test x"$$i" = x"" && continue; \

			${MKDIR_P} $$(dirname ${COPY_HEADERS_DESTINATION}/$$i) || exit $$?; \


			${INSTALL} -m 644 $$i ${COPY_HEADERS_DESTINATION}/$$i || exit $$?; \
		done \
	fi

${AMIGA_LIB} ${AMIGA_LIB_NOINST}: ${EXT_DEPS} ${AMIGA_LIB_OBJS_START} ${AMIGA_LIB_OBJS} ${AMIGA_LIB_OBJS_EXTRA}

	${LINK_STATUS}
	if ${LD} -o $@ ${AMIGA_LIB_OBJS_START} ${AMIGA_LIB_OBJS} ${AMIGA_LIB_OBJS_EXTRA} ${AMIGA_LIB_LDFLAGS} ${AMIGA_LIB_LIBS}; then \


		${LINK_OK}; \
	else \
		${LINK_FAILED}; \
	fi

${PLUGIN} ${PLUGIN_NOINST}: ${EXT_DEPS} ${PLUGIN_OBJS}
	${LINK_STATUS}







|
>















|
>








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






|
>






>
|
>
>
|



|
>

|
>
>







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
	else \
		${LINK_FAILED}; \
	fi

${JARFILE}: ${EXT_DEPS} ${JAR_MANIFEST} ${OBJS} ${OBJS_EXTRA}
	${LINK_STATUS}
	if test x"${JAR_MANIFEST}" != x""; then \
		if ${JAR} cfm ${JARFILE} ${JAR_MANIFEST} ${OBJS} \
		    ${OBJS_EXTRA}; then \
			${LINK_OK}; \
		else \
			${LINK_FAILED}; \
		fi \
	else \
		if ${JAR} cf ${JARFILE} ${OBJS} ${OBJS_EXTRA}; then \
			${LINK_OK}; \
		else \
			${LINK_FAILED}; \
		fi \
	fi

${SHARED_LIB} ${SHARED_LIB_NOINST}: ${EXT_DEPS} ${LIB_OBJS} ${LIB_OBJS_EXTRA}
	${LINK_STATUS}
	out="$@"; \
	if ${LD} -o $@ ${LIB_OBJS} ${LIB_OBJS_EXTRA} ${LIB_LDFLAGS} \
	    ${LIB_LDFLAGS_INSTALL_NAME} ${LDFLAGS} ${LIBS} ${LINK_LIB}; then \
		${LINK_OK}; \
	else \
		${LINK_FAILED}; \
	fi

${FRAMEWORK} ${FRAMEWORK_NOINST}: ${EXT_DEPS} ${LIB_OBJS} ${LIB_OBJS_EXTRA}
	${LINK_STATUS}
	out="$@"; \
	if test x"@HOST_IS_IOS@" = x"yes"; then \
		if rm -fr $@ && \
		    ${MAKE} @MAKEFLAGS_SILENT@ \
			COPY_HEADERS_IF_SUBDIR=${includesubdir} \
			COPY_HEADERS_DESTINATION=$$PWD/$@/Headers \
			copy-headers-into-framework && \
		    if test -f Info.plist; then \
			    ${INSTALL} -m 644 Info.plist $@/Info.plist; \
		    fi && \
		    if test -f module.modulemap; then \
			    ${MKDIR_P} $@/Modules && \
			    ${INSTALL} -m 644 module.modulemap \
				$@/Modules/module.modulemap; \
		    fi && \
		    ${LD} -o $@/$${out%.framework} \
			${LIB_OBJS} ${LIB_OBJS_EXTRA} ${FRAMEWORK_LDFLAGS} \
			${FRAMEWORK_LDFLAGS_INSTALL_NAME} ${LDFLAGS} \
			${FRAMEWORK_LIBS} && \
		    ${CODESIGN} -fs ${CODESIGN_IDENTITY} $@; then \
			${LINK_OK}; \
		else \
			rm -fr $$out; false; \
			${LINK_FAILED}; \
		fi; \
	else \
		versiondir="$@/Versions/${LIB_MAJOR}"; \
		if rm -fr $@ && \
		    ${MKDIR_P} $$versiondir && \
		    ${LN_S} ${LIB_MAJOR} $@/Versions/Current && \
		    ${MAKE} @MAKEFLAGS_SILENT@ \
			COPY_HEADERS_IF_SUBDIR=${includesubdir} \
			COPY_HEADERS_DESTINATION=$$PWD/$$versiondir/Headers \
			copy-headers-into-framework && \
		    ${LN_S} Versions/Current/Headers $@/Headers && \
		    if test -f Info.plist; then \
			    ${MKDIR_P} $$versiondir/Resources && \
			    ${INSTALL} -m 644 Info.plist \
				$$versiondir/Resources/Info.plist && \
			    ${LN_S} Versions/Current/Resources $@/Resources; \
		    fi && \
		    if test -f module.modulemap; then \
			    ${MKDIR_P} $$versiondir/Modules && \
			    ${INSTALL} -m 644 module.modulemap \
				$$versiondir/Modules/module.modulemap && \
			    ${LN_S} Versions/Current/Modules $@/Modules; \
		    fi && \
		    ${LD} -o $$versiondir/$${out%.framework} \
			${LIB_OBJS} ${LIB_OBJS_EXTRA} ${FRAMEWORK_LDFLAGS} \
			${FRAMEWORK_LDFLAGS_INSTALL_NAME} ${LDFLAGS} \
			${FRAMEWORK_LIBS} && \
		    ${LN_S} Versions/Current/$${out%.framework} \
			$@/$${out%.framework} && \
		    ${CODESIGN} -fs ${CODESIGN_IDENTITY} $@; then \
			${LINK_OK}; \
		else \
			rm -fr $$out; false; \
			${LINK_FAILED}; \
		fi; \
	fi

copy-headers-into-framework:
	for i in "" ${SUBDIRS} ${SUBDIRS_AFTER}; do \
		test x"$$i" = x"" && continue; \
		cd $$i || exit 1; \
		${MAKE} @MAKEFLAGS_SILENT@ copy-headers-into-framework || \
		    exit $$?; \
		cd .. || exit 1; \
	done

	if test x"${includesubdir}" = x"${COPY_HEADERS_IF_SUBDIR}"; then \
		for i in "" ${INCLUDES}; do \
			test x"$$i" = x"" && continue; \
			${MKDIR_P} \
			    $$(dirname ${COPY_HEADERS_DESTINATION}/$$i) || \
			    exit $$?; \
			${INSTALL} -m 644 $$i \
			    ${COPY_HEADERS_DESTINATION}/$$i || exit $$?; \
		done \
	fi

${AMIGA_LIB} ${AMIGA_LIB_NOINST}: ${EXT_DEPS} ${AMIGA_LIB_OBJS_START}	    \
				  ${AMIGA_LIB_OBJS} ${AMIGA_LIB_OBJS_EXTRA}
	${LINK_STATUS}
	if ${LD} -o $@ ${AMIGA_LIB_OBJS_START} ${AMIGA_LIB_OBJS} \
	    ${AMIGA_LIB_OBJS_EXTRA} ${AMIGA_LIB_LDFLAGS} \
	    ${AMIGA_LIB_LIBS}; then \
		${LINK_OK}; \
	else \
		${LINK_FAILED}; \
	fi

${PLUGIN} ${PLUGIN_NOINST}: ${EXT_DEPS} ${PLUGIN_OBJS}
	${LINK_STATUS}
278
279
280
281
282
283
284
285

286
287
288
289

290
291
292
293
294
295
296
		fi; \
		for i in $$ars; do \
			dir=".$$(echo $$i | sed 's/\//_/g').objs"; \
			rm -fr $$dir; \
		done; \
	fi

${STATIC_PIC_LIB} ${STATIC_PIC_LIB_NOINST}: ${EXT_DEPS} ${LIB_OBJS} ${LIB_OBJS_EXTRA}

	${LINK_STATUS}
	rm -f $@
	if test x"${BUILD_AND_HOST_ARE_DARWIN}" = x"yes"; then \
		if /usr/bin/libtool -static -o $@ ${LIB_OBJS} ${LIB_OBJS_EXTRA}; then \

			${LINK_OK}; \
		else \
			rm -f $@; false; \
			${LINK_FAILED}; \
		fi; \
	else \
		out="$@"; \







|
>



|
>







352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
		fi; \
		for i in $$ars; do \
			dir=".$$(echo $$i | sed 's/\//_/g').objs"; \
			rm -fr $$dir; \
		done; \
	fi

${STATIC_PIC_LIB} ${STATIC_PIC_LIB_NOINST}: ${EXT_DEPS} ${LIB_OBJS} \
					    ${LIB_OBJS_EXTRA}
	${LINK_STATUS}
	rm -f $@
	if test x"${BUILD_AND_HOST_ARE_DARWIN}" = x"yes"; then \
		if /usr/bin/libtool -static -o $@ ${LIB_OBJS} \
		    ${LIB_OBJS_EXTRA}; then \
			${LINK_OK}; \
		else \
			rm -f $@; false; \
			${LINK_FAILED}; \
		fi; \
	else \
		out="$@"; \
325
326
327
328
329
330
331
332

333
334
335
336
337
338
339
		fi; \
		for i in $$ars; do \
			dir=".$$(echo $$i | sed 's/\//_/g').objs"; \
			rm -fr $$dir; \
		done; \
	fi

${STATIC_AMIGA_LIB} ${STATIC_AMIGA_LIB_NOINST}: ${EXT_DEPS} ${AMIGA_LIB_OBJS} ${AMIGA_LIB_OBJS_EXTRA}

	${LINK_STATUS}
	rm -f $@
	out="$@"; \
	objs=""; \
	ars=""; \
	for i in ${AMIGA_LIB_OBJS} ${AMIGA_LIB_OBJS_EXTRA}; do \
		case $$i in \







|
>







401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
		fi; \
		for i in $$ars; do \
			dir=".$$(echo $$i | sed 's/\//_/g').objs"; \
			rm -fr $$dir; \
		done; \
	fi

${STATIC_AMIGA_LIB} ${STATIC_AMIGA_LIB_NOINST}: ${EXT_DEPS} ${AMIGA_LIB_OBJS} \
						${AMIGA_LIB_OBJS_EXTRA}
	${LINK_STATUS}
	rm -f $@
	out="$@"; \
	objs=""; \
	ars=""; \
	for i in ${AMIGA_LIB_OBJS} ${AMIGA_LIB_OBJS_EXTRA}; do \
		case $$i in \
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

locales: ${MO_FILES}

.c.o:
	${COMPILE_STATUS}
	in="$<"; \
	out="$@"; \
	if ${CC} ${CFLAGS} ${CPPFLAGS} ${CFLAGS_$<} ${CFLAGS_$@} ${DEP_CFLAGS} -c -o $@ $<; then \

		${COMPILE_OK}; \
	else \
		${COMPILE_FAILED}; \
	fi
.c.lib.o:
	${COMPILE_LIB_STATUS}
	in="$<"; \
	out="$@"; \
	if ${CC} ${LIB_CFLAGS} ${CFLAGS} ${CPPFLAGS} ${CFLAGS_$<} ${CFLAGS_$@} ${DEP_CFLAGS} -c -o $@ $<; then \

		${COMPILE_LIB_OK}; \
	else \
		${COMPILE_LIB_FAILED}; \
	fi
.c.amigalib.o:
	${COMPILE_AMIGA_LIB_STATUS}
	in="$<"; \
	out="$@"; \
	if ${CC} ${AMIGA_LIB_CFLAGS} ${CFLAGS} ${CPPFLAGS} ${CFLAGS_$<} ${CFLAGS_$@} ${DEP_CFLAGS} -c -o $@ $<; then \

		${COMPILE_AMIGA_LIB_OK}; \
	else \
		${COMPILE_AMIGA_LIB_FAILED}; \
	fi
.c.plugin.o:
	${COMPILE_PLUGIN_STATUS}
	in="$<"; \
	out="$@"; \
	if ${CC} ${PLUGIN_CFLAGS} ${CFLAGS} ${CPPFLAGS} ${CFLAGS_$<} ${CFLAGS_$@} ${DEP_CFLAGS} -c -o $@ $<; then \

		${COMPILE_PLUGIN_OK}; \
	else \
		${COMPILE_PLUGIN_FAILED}; \
	fi

.cc.o .cxx.o:
	${COMPILE_STATUS}
	in="$<"; \
	out="$@"; \
	if ${CXX} ${CXXFLAGS} ${CPPFLAGS} ${CXXFLAGS_$<} ${CXXFLAGS_$@} ${DEP_CXXFLAGS} -c -o $@ $<; then \

		${COMPILE_OK}; \
	else \
		${COMPILE_FAILED}; \
	fi
.cc.lib.o .cxx.lib.o:
	${COMPILE_LIB_STATUS}
	in="$<"; \
	out="$@"; \
	if ${CXX} ${LIB_CFLAGS} ${CXXFLAGS} ${CPPFLAGS} ${CXXFLAGS_$<} ${CXXFLAGS_$@} ${DEP_CXXFLAGS} -c -o $@ $<; then \

		${COMPILE_LIB_OK}; \
	else \
		${COMPILE_LIB_FAILED}; \
	fi
.cc.amigalib.o .cxx.amigalib.o:
	${COMPILE_AMIGA_LIB_STATUS}
	in="$<"; \
	out="$@"; \
	if ${CXX} ${AMIGA_LIB_CFLAGS} ${CXXFLAGS} ${CPPFLAGS} ${CXXFLAGS_$<} ${CXXFLAGS_$@} ${DEP_CXXFLAGS} -c -o $@ $<; then \

		${COMPILE_AMIGA_LIB_OK}; \
	else \
		${COMPILE_AMIGA_LIB_FAILED}; \
	fi
.cc.plugin.o .cxx.plugin.o:
	${COMPILE_PLUGIN_STATUS}
	in="$<"; \
	out="$@"; \
	if ${CXX} ${PLUGIN_CFLAGS} ${CXXFLAGS} ${CPPFLAGS} ${CXXFLAGS_$<} ${CXXFLAGS_$@} ${DEP_CXXFLAGS} -c -o $@ $<; then \

		${COMPILE_PLUGIN_OK}; \
	else \
		${COMPILE_PLUGIN_FAILED}; \
	fi

.d.o:
	${COMPILE_STATUS}







|
>








|
>








|
>








|
>









|
>








|
>








|
>








|
>







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

locales: ${MO_FILES}

.c.o:
	${COMPILE_STATUS}
	in="$<"; \
	out="$@"; \
	if ${CC} ${CFLAGS} ${CPPFLAGS} ${CFLAGS_$<} ${CFLAGS_$@} ${DEP_CFLAGS} \
	    -c -o $@ $<; then \
		${COMPILE_OK}; \
	else \
		${COMPILE_FAILED}; \
	fi
.c.lib.o:
	${COMPILE_LIB_STATUS}
	in="$<"; \
	out="$@"; \
	if ${CC} ${LIB_CFLAGS} ${CFLAGS} ${CPPFLAGS} ${CFLAGS_$<} ${CFLAGS_$@} \
	    ${DEP_CFLAGS} -c -o $@ $<; then \
		${COMPILE_LIB_OK}; \
	else \
		${COMPILE_LIB_FAILED}; \
	fi
.c.amigalib.o:
	${COMPILE_AMIGA_LIB_STATUS}
	in="$<"; \
	out="$@"; \
	if ${CC} ${AMIGA_LIB_CFLAGS} ${CFLAGS} ${CPPFLAGS} ${CFLAGS_$<} \
	    ${CFLAGS_$@} ${DEP_CFLAGS} -c -o $@ $<; then \
		${COMPILE_AMIGA_LIB_OK}; \
	else \
		${COMPILE_AMIGA_LIB_FAILED}; \
	fi
.c.plugin.o:
	${COMPILE_PLUGIN_STATUS}
	in="$<"; \
	out="$@"; \
	if ${CC} ${PLUGIN_CFLAGS} ${CFLAGS} ${CPPFLAGS} ${CFLAGS_$<} \
	    ${CFLAGS_$@} ${DEP_CFLAGS} -c -o $@ $<; then \
		${COMPILE_PLUGIN_OK}; \
	else \
		${COMPILE_PLUGIN_FAILED}; \
	fi

.cc.o .cxx.o:
	${COMPILE_STATUS}
	in="$<"; \
	out="$@"; \
	if ${CXX} ${CXXFLAGS} ${CPPFLAGS} ${CXXFLAGS_$<} ${CXXFLAGS_$@} \
	    ${DEP_CXXFLAGS} -c -o $@ $<; then \
		${COMPILE_OK}; \
	else \
		${COMPILE_FAILED}; \
	fi
.cc.lib.o .cxx.lib.o:
	${COMPILE_LIB_STATUS}
	in="$<"; \
	out="$@"; \
	if ${CXX} ${LIB_CFLAGS} ${CXXFLAGS} ${CPPFLAGS} ${CXXFLAGS_$<} \
	    ${CXXFLAGS_$@} ${DEP_CXXFLAGS} -c -o $@ $<; then \
		${COMPILE_LIB_OK}; \
	else \
		${COMPILE_LIB_FAILED}; \
	fi
.cc.amigalib.o .cxx.amigalib.o:
	${COMPILE_AMIGA_LIB_STATUS}
	in="$<"; \
	out="$@"; \
	if ${CXX} ${AMIGA_LIB_CFLAGS} ${CXXFLAGS} ${CPPFLAGS} ${CXXFLAGS_$<} \
	    ${CXXFLAGS_$@} ${DEP_CXXFLAGS} -c -o $@ $<; then \
		${COMPILE_AMIGA_LIB_OK}; \
	else \
		${COMPILE_AMIGA_LIB_FAILED}; \
	fi
.cc.plugin.o .cxx.plugin.o:
	${COMPILE_PLUGIN_STATUS}
	in="$<"; \
	out="$@"; \
	if ${CXX} ${PLUGIN_CFLAGS} ${CXXFLAGS} ${CPPFLAGS} ${CXXFLAGS_$<} \
	    ${CXXFLAGS_$@} ${DEP_CXXFLAGS} -c -o $@ $<; then \
		${COMPILE_PLUGIN_OK}; \
	else \
		${COMPILE_PLUGIN_FAILED}; \
	fi

.d.o:
	${COMPILE_STATUS}
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
		${COMPILE_FAILED}; \
	fi

.m.o:
	${COMPILE_STATUS}
	in="$<"; \
	out="$@"; \
	if ${OBJC} ${OBJCFLAGS} ${CPPFLAGS} ${OBJCFLAGS_$<} ${OBJCFLAGS_$@} ${DEP_OBJCFLAGS} -c -o $@ $<; then \

		${COMPILE_OK}; \
	else \
		${COMPILE_FAILED}; \
	fi
.m.lib.o:
	${COMPILE_LIB_STATUS}
	in="$<"; \
	out="$@"; \
	if ${OBJC} ${LIB_CFLAGS} ${OBJCFLAGS} ${CPPFLAGS} ${OBJCFLAGS_$<} ${OBJCFLAGS_$@} ${DEP_OBJCFLAGS} -c -o $@ $<; then \

		${COMPILE_LIB_OK}; \
	else \
		${COMPILE_LIB_FAILED}; \
	fi
.m.amigalib.o:
	${COMPILE_AMIGA_LIB_STATUS}
	in="$<"; \
	out="$@"; \
	if ${OBJC} ${AMIGA_LIB_CFLAGS} ${OBJCFLAGS} ${CPPFLAGS} ${OBJCFLAGS_$<} ${OBJCFLAGS_$@} ${DEP_OBJCFLAGS} -c -o $@ $<; then \

		${COMPILE_AMIGA_LIB_OK}; \
	else \
		${COMPILE_AMIGA_LIB_FAILED}; \
	fi
.m.plugin.o:
	${COMPILE_PLUGIN_STATUS}
	in="$<"; \
	out="$@"; \
	if ${OBJC} ${PLUGIN_CFLAGS} ${OBJCFLAGS} ${CPPFLAGS} ${OBJCFLAGS_$<} ${OBJCFLAGS_$@} ${DEP_OBJCFLAGS} -c -o $@ $<; then \

		${COMPILE_PLUGIN_OK}; \
	else \
		${COMPILE_PLUGIN_FAILED}; \
	fi

.mm.o:
	${COMPILE_STATUS}
	in="$<"; \
	out="$@"; \
	if ${OBJCXX} ${OBJCXXFLAGS} ${CPPFLAGS} ${OBJCXXFLAGS_$<} ${OBJCXXFLAGS_$@} ${DEP_OBJCXXFLAGS} -c -o $@ $<; then \

		${COMPILE_OK}; \
	else \
		${COMPILE_FAILED}; \
	fi
.mm.lib.o:
	${COMPILE_LIB_STATUS}
	in="$<"; \
	out="$@"; \
	if ${OBJCXX} ${LIB_CFLAGS} ${OBJCXXFLAGS} ${CPPFLAGS} ${OBJCXXFLAGS_$<} ${OBJCXXFLAGS_$@} ${DEP_OBJCXXFLAGS} -c -o $@ $<; then \


		${COMPILE_LIB_OK}; \
	else \
		${COMPILE_LIB_FAILED}; \
	fi
.mm.amigalib.o:
	${COMPILE_AMIGA_LIB_STATUS}
	in="$<"; \
	out="$@"; \
	if ${OBJCXX} ${AMIGA_LIB_CFLAGS} ${OBJCXXFLAGS} ${CPPFLAGS} ${OBJCXXFLAGS_$<} ${OBJCXXFLAGS_$@} ${DEP_OBJCXXFLAGS} -c -o $@ $<; then \


		${COMPILE_AMIGA_LIB_OK}; \
	else \
		${COMPILE_AMIGA_LIB_FAILED}; \
	fi
.mm.plugin.o:
	${COMPILE_PLUGIN_STATUS}
	in="$<"; \
	out="$@"; \
	if ${OBJCXX} ${PLUGIN_CFLAGS} ${OBJCXXFLAGS} ${CPPFLAGS} ${OBJCXXFLAGS_$<} ${OBJCXXFLAGS_$@} ${DEP_OBJCXXFLAGS} -c -o $@ $<; then \


		${COMPILE_PLUGIN_OK}; \
	else \
		${COMPILE_PLUGIN_FAILED}; \
	fi

.po.mo:
	${COMPILE_STATUS}
	in="$<"; \
	out="$@"; \
	if ${MSGFMT} -c -o $@ $<; then \
		${COMPILE_OK}; \
	else \
		${COMPILE_FAILED}; \
	fi

.py.pyc:
	${COMPILE_STATUS}
	in="$<"; \
	out="$@"; \
	if ${PYTHON} ${PYTHON_FLAGS} -c "import py_compile; py_compile.compile('$<')"; then \

		${COMPILE_OK}; \
	else \
		${COMPILE_FAILED}; \
	fi

.rc.o .rc.lib.o .rc.plugin.o:
	${COMPILE_STATUS}
	in="$<"; \
	out="$@"; \
	if ${RC} ${RCFLAGS} ${CPPFLAGS} -J rc -O coff -o $@ $<; then \
		${COMPILE_OK}; \
	else \
		${COMPILE_FAILED}; \
	fi

.S.o .S.amigalib.o:
	${COMPILE_STATUS}
	in="$<"; \
	out="$@"; \
	if ${AS} ${ASFLAGS} ${CPPFLAGS} ${ASFLAGS_$<} ${ASFLAGS_$@} ${DEP_ASFLAGS} -c -o $@ $<; then \

		${COMPILE_OK}; \
	else \
		${COMPILE_FAILED}; \
	fi
.S.lib.o:
	${COMPILE_LIB_STATUS}
	in="$<"; \
	out="$@"; \
	if ${AS} ${LIB_CFLAGS} ${ASFLAGS} ${CPPFLAGS} ${ASFLAGS_$<} ${ASFLAGS_$@} ${DEP_ASFLAGS} -c -o $@ $<; then \

		${COMPILE_LIB_OK}; \
	else \
		${COMPILE_LIB_FAILED}; \
	fi
.S.plugin.o:
	${COMPILE_PLUGIN_STATUS}
	in="$<"; \
	out="$@"; \
	if ${AS} ${PLUGIN_CFLAGS} ${ASFLAGS} ${CPPFLAGS} ${ASFLAGS_$<} ${ASFLAGS_$@} ${DEP_ASFLAGS} -c -o $@ $<; then \

		${COMPILE_PLUGIN_OK}; \
	else \
		${COMPILE_PLUGIN_FAILED}; \
	fi

.xpm.o:
	${COMPILE_STATUS}
	in="$<"; \
	out="$@"; \
	if ${CC} ${CFLAGS} ${CPPFLAGS} ${CFLAGS_$<} ${CFLAGS_$@} -x c -c -o $@ $<; then \

		${COMPILE_OK}; \
	else \
		${COMPILE_FAILED}; \
	fi
.xpm.lib.o:
	${COMPILE_LIB_STATUS}
	in="$<"; \
	out="$@"; \
	if ${CC} ${LIB_CFLAGS} ${CFLAGS} ${CPPFLAGS} ${CFLAGS_$<} ${CFLAGS_$@} -x c -c -o $@ $<; then \

		${COMPILE_LIB_OK}; \
	else \
		${COMPILE_LIB_FAILED}; \
	fi
.xpm.amigalib.o:
	${COMPILE_AMIGA_LIB_STATUS}
	in="$<"; \
	out="$@"; \
	if ${CC} ${AMIGA_LIB_CFLAGS} ${CFLAGS} ${CPPFLAGS} ${CFLAGS_$<} ${CFLAGS_$@} -x c -c -o $@ $<; then \

		${COMPILE_AMIGA_LIB_OK}; \
	else \
		${COMPILE_AMIGA_LIB_FAILED}; \
	fi
.xpm.plugin.o:
	${COMPILE_PLUGIN_STATUS}
	in="$<"; \
	out="$@"; \
	if ${CC} ${PLUGIN_CFLAGS} ${CFLAGS} ${CPPFLAGS} ${CFLAGS_$<} ${CFLAGS_$@} -x c -c -o $@ $<; then \

		${COMPILE_PLUGIN_OK}; \
	else \
		${COMPILE_PLUGIN_FAILED}; \
	fi

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

	for i in "" ${SHARED_LIB}; do \
		test x"$$i" = x"" && continue; \
		${INSTALL_STATUS}; \
		if ${MKDIR_P} ${DESTDIR}${libdir} @INSTALL_LIB@; then \
			${INSTALL_OK}; \
		else \
			${INSTALL_FAILED}; \
		fi \
	done

	for i in "" ${FRAMEWORK}; do \
		test x"$$i" = x"" && continue; \
		${INSTALL_STATUS}; \
		rm -fr ${DESTDIR}${prefix}/Library/Frameworks/$$i; \
		if ${MKDIR_P} ${DESTDIR}${prefix}/Library/Frameworks && cp -R $$i ${DESTDIR}${prefix}/Library/Frameworks/; then \

			${INSTALL_OK}; \
		else \
			${INSTALL_FAILED}; \
		fi \
	done

	for i in "" ${AMIGA_LIB}; do \
		test x"$$i" = x"" && continue; \
		${INSTALL_STATUS}; \
		if ${MKDIR_P} ${DESTDIR}${amigalibdir} && ${INSTALL} -m 755 $$i ${DESTDIR}${amigalibdir}/$$i; then \

			${INSTALL_OK}; \
		else \
			${INSTALL_FAILED}; \
		fi \
	done

	for i in "" ${STATIC_LIB} ${STATIC_PIC_LIB} ${STATIC_AMIGA_LIB}; do \
		test x"$$i" = x"" && continue; \
		${INSTALL_STATUS}; \
		if ${MKDIR_P} ${DESTDIR}${libdir} && ${INSTALL} -m 644 $$i ${DESTDIR}${libdir}/$$i; then \

			${INSTALL_OK}; \
		else \
			${INSTALL_FAILED}; \
		fi \
	done

	for i in "" ${PLUGIN}; do \
		test x"$$i" = x"" && continue; \
		${INSTALL_STATUS}; \
		if ${MKDIR_P} ${DESTDIR}${plugindir} @INSTALL_PLUGIN@; then \
			${INSTALL_OK}; \
		else \
			${INSTALL_FAILED}; \
		fi \
	done

	for i in "" ${DATA}; do \
		test x"$$i" = x"" && continue; \
		${INSTALL_STATUS}; \



		if ${MKDIR_P} $$(dirname ${DESTDIR}${datadir}/${PACKAGE_NAME}/$$i) && ${INSTALL} -m 644 $$i ${DESTDIR}${datadir}/${PACKAGE_NAME}/$$i; then \
			${INSTALL_OK}; \
		else \
			${INSTALL_FAILED}; \
		fi \
	done

	for i in "" ${PROG}; do \
		test x"$$i" = x"" && continue; \
		${INSTALL_STATUS}; \
		if ${MKDIR_P} ${DESTDIR}${bindir} && ${INSTALL} -m 755 $$i ${DESTDIR}${bindir}/$$i; then \

			${INSTALL_OK}; \
		else \
			${INSTALL_FAILED}; \
		fi \
	done

	if test x"${INSTALL_INCLUDES}" = x"yes"; then \
		for i in "" ${INCLUDES}; do \
			test x"$$i" = x"" && continue; \
			${INSTALL_STATUS}; \



			if ${MKDIR_P} $$(dirname ${DESTDIR}${includedir}/${includesubdir}/$$i) && ${INSTALL} -m 644 $$i ${DESTDIR}${includedir}/${includesubdir}/$$i; then \
				${INSTALL_OK}; \
			else \
				${INSTALL_FAILED}; \
			fi \
		done \
	fi

	for i in "" ${MO_FILES}; do \
		test x"$$i" = x"" && continue; \
		${INSTALL_STATUS}; \


		if ${MKDIR_P} ${DESTDIR}${localedir}/$${i%.mo}/LC_MESSAGES && ${INSTALL} -m 644 $$i ${DESTDIR}${localedir}/$${i%.mo}/LC_MESSAGES/${localename}.mo; then \

			${INSTALL_OK}; \
		else \
			${INSTALL_FAILED}; \
		fi \
	done

	for i in "" ${MAN}; do \
		test x"$$i" = x"" && continue; \
		${INSTALL_STATUS}; \

		if ${MKDIR_P} ${DESTDIR}${mandir}/${mansubdir} && ${INSTALL} -m 644 $$i ${DESTDIR}${mandir}/${mansubdir}/$$i; then \

			${INSTALL_OK}; \
		else \
			${INSTALL_FAILED}; \
		fi \
	done

install-extra:

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

	for i in "" ${SHARED_LIB}; do \
		test x"$$i" = x"" && continue; \
		if test -f ${DESTDIR}${libdir}/$$i -o -f ${DESTDIR}${bindir}/$$i; then \

			if : @UNINSTALL_LIB@; then \
				${DELETE_OK}; \
			else \
				${DELETE_FAILED}; \
			fi \
		fi; \
	done

	for i in "" ${FRAMEWORK}; do \
		test x"$$i" = x"" && continue; \
		if test -d ${DESTDIR}${prefix}/Library/Frameworks/$$i; then \
			if rm -fr ${DESTDIR}${prefix}/Library/Frameworks/$$i; then \

				${DELETE_OK}; \
			else \
				${DELETE_FAILED}; \
			fi \
		fi \
	done
	rmdir ${DESTDIR}${prefix}/Library/Frameworks >/dev/null 2>&1 || true







|
>








|
>








|
>








|
>









|
>








|
>
>








|
>
>








|
>
>



















|
>



















|
>








|
>








|
>









|
>








|
>








|
>








|
>









|

















|
>









|
>









|
>



















>
>
>
|









|
>










>
>
>
|










>
>
|
>









>
|
>








|



|





|
>











|
>







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
		${COMPILE_FAILED}; \
	fi

.m.o:
	${COMPILE_STATUS}
	in="$<"; \
	out="$@"; \
	if ${OBJC} ${OBJCFLAGS} ${CPPFLAGS} ${OBJCFLAGS_$<} ${OBJCFLAGS_$@} \
	    ${DEP_OBJCFLAGS} -c -o $@ $<; then \
		${COMPILE_OK}; \
	else \
		${COMPILE_FAILED}; \
	fi
.m.lib.o:
	${COMPILE_LIB_STATUS}
	in="$<"; \
	out="$@"; \
	if ${OBJC} ${LIB_CFLAGS} ${OBJCFLAGS} ${CPPFLAGS} ${OBJCFLAGS_$<} \
	    ${OBJCFLAGS_$@} ${DEP_OBJCFLAGS} -c -o $@ $<; then \
		${COMPILE_LIB_OK}; \
	else \
		${COMPILE_LIB_FAILED}; \
	fi
.m.amigalib.o:
	${COMPILE_AMIGA_LIB_STATUS}
	in="$<"; \
	out="$@"; \
	if ${OBJC} ${AMIGA_LIB_CFLAGS} ${OBJCFLAGS} ${CPPFLAGS} \
	    ${OBJCFLAGS_$<} ${OBJCFLAGS_$@} ${DEP_OBJCFLAGS} -c -o $@ $<; then \
		${COMPILE_AMIGA_LIB_OK}; \
	else \
		${COMPILE_AMIGA_LIB_FAILED}; \
	fi
.m.plugin.o:
	${COMPILE_PLUGIN_STATUS}
	in="$<"; \
	out="$@"; \
	if ${OBJC} ${PLUGIN_CFLAGS} ${OBJCFLAGS} ${CPPFLAGS} ${OBJCFLAGS_$<} \
	    ${OBJCFLAGS_$@} ${DEP_OBJCFLAGS} -c -o $@ $<; then \
		${COMPILE_PLUGIN_OK}; \
	else \
		${COMPILE_PLUGIN_FAILED}; \
	fi

.mm.o:
	${COMPILE_STATUS}
	in="$<"; \
	out="$@"; \
	if ${OBJCXX} ${OBJCXXFLAGS} ${CPPFLAGS} ${OBJCXXFLAGS_$<} \
	    ${OBJCXXFLAGS_$@} ${DEP_OBJCXXFLAGS} -c -o $@ $<; then \
		${COMPILE_OK}; \
	else \
		${COMPILE_FAILED}; \
	fi
.mm.lib.o:
	${COMPILE_LIB_STATUS}
	in="$<"; \
	out="$@"; \
	if ${OBJCXX} ${LIB_CFLAGS} ${OBJCXXFLAGS} ${CPPFLAGS} \
	    ${OBJCXXFLAGS_$<} ${OBJCXXFLAGS_$@} ${DEP_OBJCXXFLAGS} -c -o $@ \
	    $<; then \
		${COMPILE_LIB_OK}; \
	else \
		${COMPILE_LIB_FAILED}; \
	fi
.mm.amigalib.o:
	${COMPILE_AMIGA_LIB_STATUS}
	in="$<"; \
	out="$@"; \
	if ${OBJCXX} ${AMIGA_LIB_CFLAGS} ${OBJCXXFLAGS} ${CPPFLAGS} \
	    ${OBJCXXFLAGS_$<} ${OBJCXXFLAGS_$@} ${DEP_OBJCXXFLAGS} -c -o $@ \
	    $<; then \
		${COMPILE_AMIGA_LIB_OK}; \
	else \
		${COMPILE_AMIGA_LIB_FAILED}; \
	fi
.mm.plugin.o:
	${COMPILE_PLUGIN_STATUS}
	in="$<"; \
	out="$@"; \
	if ${OBJCXX} ${PLUGIN_CFLAGS} ${OBJCXXFLAGS} ${CPPFLAGS} \
	    ${OBJCXXFLAGS_$<} ${OBJCXXFLAGS_$@} ${DEP_OBJCXXFLAGS} -c -o $@ \
	    $<; then \
		${COMPILE_PLUGIN_OK}; \
	else \
		${COMPILE_PLUGIN_FAILED}; \
	fi

.po.mo:
	${COMPILE_STATUS}
	in="$<"; \
	out="$@"; \
	if ${MSGFMT} -c -o $@ $<; then \
		${COMPILE_OK}; \
	else \
		${COMPILE_FAILED}; \
	fi

.py.pyc:
	${COMPILE_STATUS}
	in="$<"; \
	out="$@"; \
	if ${PYTHON} ${PYTHON_FLAGS} -c \
	    "import py_compile; py_compile.compile('$<')"; then \
		${COMPILE_OK}; \
	else \
		${COMPILE_FAILED}; \
	fi

.rc.o .rc.lib.o .rc.plugin.o:
	${COMPILE_STATUS}
	in="$<"; \
	out="$@"; \
	if ${RC} ${RCFLAGS} ${CPPFLAGS} -J rc -O coff -o $@ $<; then \
		${COMPILE_OK}; \
	else \
		${COMPILE_FAILED}; \
	fi

.S.o .S.amigalib.o:
	${COMPILE_STATUS}
	in="$<"; \
	out="$@"; \
	if ${AS} ${ASFLAGS} ${CPPFLAGS} ${ASFLAGS_$<} ${ASFLAGS_$@} \
	    ${DEP_ASFLAGS} -c -o $@ $<; then \
		${COMPILE_OK}; \
	else \
		${COMPILE_FAILED}; \
	fi
.S.lib.o:
	${COMPILE_LIB_STATUS}
	in="$<"; \
	out="$@"; \
	if ${AS} ${LIB_CFLAGS} ${ASFLAGS} ${CPPFLAGS} ${ASFLAGS_$<} \
	    ${ASFLAGS_$@} ${DEP_ASFLAGS} -c -o $@ $<; then \
		${COMPILE_LIB_OK}; \
	else \
		${COMPILE_LIB_FAILED}; \
	fi
.S.plugin.o:
	${COMPILE_PLUGIN_STATUS}
	in="$<"; \
	out="$@"; \
	if ${AS} ${PLUGIN_CFLAGS} ${ASFLAGS} ${CPPFLAGS} ${ASFLAGS_$<} \
	    ${ASFLAGS_$@} ${DEP_ASFLAGS} -c -o $@ $<; then \
		${COMPILE_PLUGIN_OK}; \
	else \
		${COMPILE_PLUGIN_FAILED}; \
	fi

.xpm.o:
	${COMPILE_STATUS}
	in="$<"; \
	out="$@"; \
	if ${CC} ${CFLAGS} ${CPPFLAGS} ${CFLAGS_$<} ${CFLAGS_$@} -x c -c -o $@ \
	    $<; then \
		${COMPILE_OK}; \
	else \
		${COMPILE_FAILED}; \
	fi
.xpm.lib.o:
	${COMPILE_LIB_STATUS}
	in="$<"; \
	out="$@"; \
	if ${CC} ${LIB_CFLAGS} ${CFLAGS} ${CPPFLAGS} ${CFLAGS_$<} ${CFLAGS_$@} \
	    -x c -c -o $@ $<; then \
		${COMPILE_LIB_OK}; \
	else \
		${COMPILE_LIB_FAILED}; \
	fi
.xpm.amigalib.o:
	${COMPILE_AMIGA_LIB_STATUS}
	in="$<"; \
	out="$@"; \
	if ${CC} ${AMIGA_LIB_CFLAGS} ${CFLAGS} ${CPPFLAGS} ${CFLAGS_$<} \
	    ${CFLAGS_$@} -x c -c -o $@ $<; then \
		${COMPILE_AMIGA_LIB_OK}; \
	else \
		${COMPILE_AMIGA_LIB_FAILED}; \
	fi
.xpm.plugin.o:
	${COMPILE_PLUGIN_STATUS}
	in="$<"; \
	out="$@"; \
	if ${CC} ${PLUGIN_CFLAGS} ${CFLAGS} ${CPPFLAGS} ${CFLAGS_$<} \
	    ${CFLAGS_$@} -x c -c -o $@ $<; then \
		${COMPILE_PLUGIN_OK}; \
	else \
		${COMPILE_PLUGIN_FAILED}; \
	fi

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

	for i in "" ${SHARED_LIB}; do \
		test x"$$i" = x"" && continue; \
		${INSTALL_STATUS}; \
		if ${MKDIR_P} ${DESTDIR}${libdir} @INSTALL_LIB@; then \
			${INSTALL_OK}; \
		else \
			${INSTALL_FAILED}; \
		fi \
	done

	for i in "" ${FRAMEWORK}; do \
		test x"$$i" = x"" && continue; \
		${INSTALL_STATUS}; \
		rm -fr ${DESTDIR}${prefix}/Library/Frameworks/$$i; \
		if ${MKDIR_P} ${DESTDIR}${prefix}/Library/Frameworks && \
		    cp -R $$i ${DESTDIR}${prefix}/Library/Frameworks/; then \
			${INSTALL_OK}; \
		else \
			${INSTALL_FAILED}; \
		fi \
	done

	for i in "" ${AMIGA_LIB}; do \
		test x"$$i" = x"" && continue; \
		${INSTALL_STATUS}; \
		if ${MKDIR_P} ${DESTDIR}${amigalibdir} && \
		    ${INSTALL} -m 755 $$i ${DESTDIR}${amigalibdir}/$$i; then \
			${INSTALL_OK}; \
		else \
			${INSTALL_FAILED}; \
		fi \
	done

	for i in "" ${STATIC_LIB} ${STATIC_PIC_LIB} ${STATIC_AMIGA_LIB}; do \
		test x"$$i" = x"" && continue; \
		${INSTALL_STATUS}; \
		if ${MKDIR_P} ${DESTDIR}${libdir} && \
		    ${INSTALL} -m 644 $$i ${DESTDIR}${libdir}/$$i; then \
			${INSTALL_OK}; \
		else \
			${INSTALL_FAILED}; \
		fi \
	done

	for i in "" ${PLUGIN}; do \
		test x"$$i" = x"" && continue; \
		${INSTALL_STATUS}; \
		if ${MKDIR_P} ${DESTDIR}${plugindir} @INSTALL_PLUGIN@; then \
			${INSTALL_OK}; \
		else \
			${INSTALL_FAILED}; \
		fi \
	done

	for i in "" ${DATA}; do \
		test x"$$i" = x"" && continue; \
		${INSTALL_STATUS}; \
		if ${MKDIR_P} $$(dirname \
		    ${DESTDIR}${datadir}/${PACKAGE_NAME}/$$i) && \
		    ${INSTALL} -m 644 $$i \
		    ${DESTDIR}${datadir}/${PACKAGE_NAME}/$$i; then \
			${INSTALL_OK}; \
		else \
			${INSTALL_FAILED}; \
		fi \
	done

	for i in "" ${PROG}; do \
		test x"$$i" = x"" && continue; \
		${INSTALL_STATUS}; \
		if ${MKDIR_P} ${DESTDIR}${bindir} && \
		    ${INSTALL} -m 755 $$i ${DESTDIR}${bindir}/$$i; then \
			${INSTALL_OK}; \
		else \
			${INSTALL_FAILED}; \
		fi \
	done

	if test x"${INSTALL_INCLUDES}" = x"yes"; then \
		for i in "" ${INCLUDES}; do \
			test x"$$i" = x"" && continue; \
			${INSTALL_STATUS}; \
			if ${MKDIR_P} $$(dirname \
			    ${DESTDIR}${includedir}/${includesubdir}/$$i) && \
			    ${INSTALL} -m 644 $$i \
			    ${DESTDIR}${includedir}/${includesubdir}/$$i; then \
				${INSTALL_OK}; \
			else \
				${INSTALL_FAILED}; \
			fi \
		done \
	fi

	for i in "" ${MO_FILES}; do \
		test x"$$i" = x"" && continue; \
		${INSTALL_STATUS}; \
		dest="${localedir}/$${i%.mo}/LC_MESSAGES/${localename}.mo"; \
		dest="${DESTDIR}$$dest"; \
		if ${MKDIR_P} ${DESTDIR}${localedir}/$${i%.mo}/LC_MESSAGES && \
		    ${INSTALL} -m 644 $$i $$dest; then \
			${INSTALL_OK}; \
		else \
			${INSTALL_FAILED}; \
		fi \
	done

	for i in "" ${MAN}; do \
		test x"$$i" = x"" && continue; \
		${INSTALL_STATUS}; \
		dest="${DESTDIR}${mandir}/${mansubdir}/$$i"; \
		if ${MKDIR_P} ${DESTDIR}${mandir}/${mansubdir} && \
		    ${INSTALL} -m 644 $$i $$dest; then \
			${INSTALL_OK}; \
		else \
			${INSTALL_FAILED}; \
		fi \
	done

install-extra:

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

	for i in "" ${SHARED_LIB}; do \
		test x"$$i" = x"" && continue; \
		if test -f ${DESTDIR}${libdir}/$$i \
		    -o -f ${DESTDIR}${bindir}/$$i; then \
			if : @UNINSTALL_LIB@; then \
				${DELETE_OK}; \
			else \
				${DELETE_FAILED}; \
			fi \
		fi; \
	done

	for i in "" ${FRAMEWORK}; do \
		test x"$$i" = x"" && continue; \
		if test -d ${DESTDIR}${prefix}/Library/Frameworks/$$i; then \
			if rm -fr ${DESTDIR}${prefix}/Library/Frameworks/$$i; \
			then \
				${DELETE_OK}; \
			else \
				${DELETE_FAILED}; \
			fi \
		fi \
	done
	rmdir ${DESTDIR}${prefix}/Library/Frameworks >/dev/null 2>&1 || true
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
		fi \
	done
	rmdir ${DESTDIR}${plugindir} >/dev/null 2>&1 || true

	for i in "" ${DATA}; do \
		test x"$$i" = x"" && continue; \
		if test -f ${DESTDIR}${datadir}/${PACKAGE_NAME}/$$i; then \
			if rm -f ${DESTDIR}${datadir}/${PACKAGE_NAME}/$$i; then \

				${DELETE_OK}; \
			else \
				${DELETE_FAILED}; \
			fi \
		fi; \
		rmdir "$$(dirname ${DESTDIR}${datadir}/${PACKAGE_NAME}/$$i)" >/dev/null 2>&1 || true; \

	done
	rmdir ${DESTDIR}${datadir}/${PACKAGE_NAME} >/dev/null 2>&1 || true

	for i in "" ${PROG}; do \
		test x"$$i" = x"" && continue; \
		if test -f ${DESTDIR}${bindir}/$$i; then \
			if rm -f ${DESTDIR}${bindir}/$$i; then \
				${DELETE_OK}; \
			else \
				${DELETE_FAILED}; \
			fi \
		fi \
	done

	for i in "" ${INCLUDES}; do \
		test x"$$i" = x"" && continue; \
		if test -f ${DESTDIR}${includedir}/${includesubdir}/$$i; then \
			if rm -f ${DESTDIR}${includedir}/${includesubdir}/$$i; then \

				${DELETE_OK}; \
			else \
				${DELETE_FAILED}; \
			fi \
		fi \
	done
	rmdir ${DESTDIR}${includedir}/${includesubdir} >/dev/null 2>&1 || true

	for i in "" ${MO_FILES}; do \
		test x"$$i" = x"" && continue; \
		if test -f ${DESTDIR}${localedir}/$${i%.mo}/LC_MESSAGES/${localename}.mo; then \
			if rm -f ${DESTDIR}${localedir}/$${i%.mo}/LC_MESSAGES/${localename}.mo; then \


				${DELETE_OK}; \
			else \
				${DELETE_FAILED}; \
			fi \
		fi \
	done

	for i in "" ${MAN}; do \
		test x"$$i" = x"" && continue; \
		if test -f ${DESTDIR}${mandir}/${mansubdir}/$$i; then \
			if rm -f ${DESTDIR}${mandir}/${mansubdir}/$$i; then \
				${DELETE_OK}; \
			else \
				${DELETE_FAILED}; \
			fi \
		fi \
	done



uninstall-extra:

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

	: >.deps

	for i in "" ${DEPS} ${OBJS} ${OBJS_EXTRA} ${LIB_OBJS} ${LIB_OBJS_EXTRA} ${AMIGA_LIB_OBJS} ${AMIGA_LIB_OBJS_START} ${AMIGA_LIB_OBJS_EXTRA} ${PLUGIN_OBJS} ${PROG} ${PROG_NOINST} ${SHARED_LIB} ${SHARED_LIB_NOINST} ${AMIGA_LIB} ${AMIGA_LIB_NOINST} ${STATIC_LIB} ${STATIC_LIB_NOINST} ${STATIC_PIC_LIB} ${STATIC_PIC_LIB_NOINST} ${STATIC_AMIGA_LIB} ${STATIC_AMIGA_LIB_NOINST} ${FRAMEWORK} ${PLUGIN} ${PLUGIN_NOINST} ${CLEAN_LIB} ${MO_FILES} ${CLEAN}; do \







		test x"$$i" = x"" && continue; \
		if test -f $$i -o -d $$i; then \
			if rm -fr $$i; then \
				${DELETE_OK}; \
			else \
				${DELETE_FAILED}; \
			fi \
		fi \
	done

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

	for i in "" ${DISTCLEAN} .deps *~; do \
		test x"$$i" = x"" && continue; \
		if test -f $$i -o -d $$i; then \
			if rm -fr $$i; then \
				${DELETE_OK}; \
			else \
				${DELETE_FAILED}; \
			fi \
		fi \
	done

print-hierarchy:
	for i in "" ${SUBDIRS} ${SUBDIRS_AFTER}; do \
		test x"$$i" = x"" && continue; \
		echo ${PRINT_HIERARCHY_PREFIX}$$i; \
		cd $$i || exit $$?; \

		${MAKE} -s PRINT_HIERARCHY_PREFIX=$$i/ print-hierarchy || exit $$?; \
		cd .. || exit $$?; \
	done

print-var:
	printf '%s\n' '${${VAR}}'

DIR_ENTER = printf "@TERM_EL@@TERM_SETAF6@Entering directory @TERM_BOLD@%s@TERM_SGR0@@TERM_SETAF6@.@TERM_SGR0@\n" "$$i"; cd $$i || exit $$?







|
>





|
>

















|
>










|
|
>
>


















>
>






|





|
>
>
>
>
>
>
>














|



















>
|







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
		fi \
	done
	rmdir ${DESTDIR}${plugindir} >/dev/null 2>&1 || true

	for i in "" ${DATA}; do \
		test x"$$i" = x"" && continue; \
		if test -f ${DESTDIR}${datadir}/${PACKAGE_NAME}/$$i; then \
			if rm -f ${DESTDIR}${datadir}/${PACKAGE_NAME}/$$i; \
			then \
				${DELETE_OK}; \
			else \
				${DELETE_FAILED}; \
			fi \
		fi; \
		rmdir "$$(dirname ${DESTDIR}${datadir}/${PACKAGE_NAME}/$$i)" \
		    >/dev/null 2>&1 || true; \
	done
	rmdir ${DESTDIR}${datadir}/${PACKAGE_NAME} >/dev/null 2>&1 || true

	for i in "" ${PROG}; do \
		test x"$$i" = x"" && continue; \
		if test -f ${DESTDIR}${bindir}/$$i; then \
			if rm -f ${DESTDIR}${bindir}/$$i; then \
				${DELETE_OK}; \
			else \
				${DELETE_FAILED}; \
			fi \
		fi \
	done

	for i in "" ${INCLUDES}; do \
		test x"$$i" = x"" && continue; \
		if test -f ${DESTDIR}${includedir}/${includesubdir}/$$i; then \
			if rm -f ${DESTDIR}${includedir}/${includesubdir}/$$i; \
			then \
				${DELETE_OK}; \
			else \
				${DELETE_FAILED}; \
			fi \
		fi \
	done
	rmdir ${DESTDIR}${includedir}/${includesubdir} >/dev/null 2>&1 || true

	for i in "" ${MO_FILES}; do \
		test x"$$i" = x"" && continue; \
		mo="${localedir}/$${i%.mo}/LC_MESSAGES/${localename}.mo"; \
		mo="${DESTDIR}$$mo"; \
		if test -f $$mo; then \
			if rm -f $$mo; then \
				${DELETE_OK}; \
			else \
				${DELETE_FAILED}; \
			fi \
		fi \
	done

	for i in "" ${MAN}; do \
		test x"$$i" = x"" && continue; \
		if test -f ${DESTDIR}${mandir}/${mansubdir}/$$i; then \
			if rm -f ${DESTDIR}${mandir}/${mansubdir}/$$i; then \
				${DELETE_OK}; \
			else \
				${DELETE_FAILED}; \
			fi \
		fi \
	done

	${MAKE} @MAKEFLAGS_SILENT@ uninstall-extra

uninstall-extra:

clean:
	for i in "" ${SUBDIRS} ${SUBDIRS_AFTER}; do \
		test x"$$i" = x"" && continue; \
		${DIR_ENTER}; \
		${MAKE} @MAKEFLAGS_SILENT@ clean || exit $$?; \
		${DIR_LEAVE}; \
	done

	: >.deps

	for i in "" ${DEPS} ${OBJS} ${OBJS_EXTRA} ${LIB_OBJS} \
	    ${LIB_OBJS_EXTRA} ${AMIGA_LIB_OBJS} ${AMIGA_LIB_OBJS_START} \
	    ${AMIGA_LIB_OBJS_EXTRA} ${PLUGIN_OBJS} ${PROG} ${PROG_NOINST} \
	    ${SHARED_LIB} ${SHARED_LIB_NOINST} ${AMIGA_LIB} \
	    ${AMIGA_LIB_NOINST} ${STATIC_LIB} ${STATIC_LIB_NOINST} \
	    ${STATIC_PIC_LIB} ${STATIC_PIC_LIB_NOINST} ${STATIC_AMIGA_LIB} \
	    ${STATIC_AMIGA_LIB_NOINST} ${FRAMEWORK} ${PLUGIN} ${PLUGIN_NOINST} \
	    ${CLEAN_LIB} ${MO_FILES} ${CLEAN}; do \
		test x"$$i" = x"" && continue; \
		if test -f $$i -o -d $$i; then \
			if rm -fr $$i; then \
				${DELETE_OK}; \
			else \
				${DELETE_FAILED}; \
			fi \
		fi \
	done

distclean: clean
	for i in "" ${SUBDIRS} ${SUBDIRS_AFTER}; do \
		test x"$$i" = x"" && continue; \
		${DIR_ENTER}; \
		${MAKE} @MAKEFLAGS_SILENT@ distclean || exit $$?; \
		${DIR_LEAVE}; \
	done

	for i in "" ${DISTCLEAN} .deps *~; do \
		test x"$$i" = x"" && continue; \
		if test -f $$i -o -d $$i; then \
			if rm -fr $$i; then \
				${DELETE_OK}; \
			else \
				${DELETE_FAILED}; \
			fi \
		fi \
	done

print-hierarchy:
	for i in "" ${SUBDIRS} ${SUBDIRS_AFTER}; do \
		test x"$$i" = x"" && continue; \
		echo ${PRINT_HIERARCHY_PREFIX}$$i; \
		cd $$i || exit $$?; \
		${MAKE} @MAKEFLAGS_SILENT@ PRINT_HIERARCHY_PREFIX=$$i/ \
		    print-hierarchy || exit $$?; \
		cd .. || exit $$?; \
	done

print-var:
	printf '%s\n' '${${VAR}}'

DIR_ENTER = printf "@TERM_EL@@TERM_SETAF6@Entering directory @TERM_BOLD@%s@TERM_SGR0@@TERM_SETAF6@.@TERM_SGR0@\n" "$$i"; cd $$i || exit $$?

Modified configure.ac from [1cc78068e1] to [17ac08d8ed].

1
2
3
4
5
6
7
8
AC_INIT(ObjFW, 1.1dev, js@nil.im)
AC_CONFIG_SRCDIR(src)
AC_CONFIG_AUX_DIR(build-aux)
AC_CONFIG_MACRO_DIR(build-aux/m4)

AC_DEFINE(OBJFW_VERSION_MAJOR, 1, [The major version of ObjFW])
AC_DEFINE(OBJFW_VERSION_MINOR, 1, [The minor version of ObjFW])
dnl This may only be set to 1.1 once 1.1 is released
|







1
2
3
4
5
6
7
8
AC_INIT(ObjFW, 1.1dev, js@nil.im, objfw, https://objfw.nil.im/)
AC_CONFIG_SRCDIR(src)
AC_CONFIG_AUX_DIR(build-aux)
AC_CONFIG_MACRO_DIR(build-aux/m4)

AC_DEFINE(OBJFW_VERSION_MAJOR, 1, [The major version of ObjFW])
AC_DEFINE(OBJFW_VERSION_MINOR, 1, [The minor version of ObjFW])
dnl This may only be set to 1.1 once 1.1 is released
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

	enable_shared="no"
	enable_threads="no"
	enable_sockets="no"
	enable_files="no"
	;;
m68k-*-amigaos*)
	AS_IF([test x"$OBJCFLAGS" = x""], [OBJCFLAGS="-O0"])
	OBJCFLAGS="$OBJCFLAGS -noixemul"
	OBJFW_OBJCFLAGS="$OBJFW_OBJCFLAGS -noixemul"
	CPPFLAGS="$CPPFLAGS -D__NO_NET_API"
	LDFLAGS="$LDFLAGS -noixemul"
	LIBS="$LIBS -ldebug"

	enable_files="yes"	# Required for reading ENV:
	enable_shared="no"
	with_tls="no"
	supports_amiga_lib="yes"

	AS_IF([test x"$enable_amiga_lib" != x"no"], [
		AC_SUBST(OBJFWRT_AMIGA_LIB,
			['objfwrt${OBJFWRT_LIB_MAJOR}.library'])
		dnl For 68000, GCC emits calls to helper functions that
		dnl do not work properly in a library.
		t="-mcpu=68020 -fbaserel -noixemul -ffreestanding"
		AC_SUBST(AMIGA_LIB_CFLAGS, $t)
		t="$t -resident -nostartfiles -nodefaultlibs -ldebug -lc"
		AC_SUBST(AMIGA_LIB_LDFLAGS, $t)
	])

	AC_SUBST(LIBBASES_M, libbases.m)
	;;
powerpc-*-amigaos*)
	CPPFLAGS="$CPPFLAGS -D__USE_INLINE__"

	enable_files="yes"	# Required for reading ENV:







|









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







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












50
51
52
53
54
55
56

	enable_shared="no"
	enable_threads="no"
	enable_sockets="no"
	enable_files="no"
	;;
m68k-*-amigaos*)
	AS_IF([test x"$OBJCFLAGS" = x""], [OBJCFLAGS="-O0 -g"])
	OBJCFLAGS="$OBJCFLAGS -noixemul"
	OBJFW_OBJCFLAGS="$OBJFW_OBJCFLAGS -noixemul"
	CPPFLAGS="$CPPFLAGS -D__NO_NET_API"
	LDFLAGS="$LDFLAGS -noixemul"
	LIBS="$LIBS -ldebug"

	enable_files="yes"	# Required for reading ENV:
	enable_shared="no"
	with_tls="no"













	AC_SUBST(LIBBASES_M, libbases.m)
	;;
powerpc-*-amigaos*)
	CPPFLAGS="$CPPFLAGS -D__USE_INLINE__"

	enable_files="yes"	# Required for reading ENV:
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
	OBJCFLAGS="$OBJCFLAGS -noixemul"
	OBJFW_OBJCFLAGS="$OBJFW_OBJCFLAGS -noixemul"
	LDFLAGS="$LDFLAGS -noixemul"
	LIBS="$LIBS -ldebug"

	enable_files="yes"	# Required for reading ENV:
	enable_shared="no"
	supports_amiga_lib="yes"

	AS_IF([test x"$enable_amiga_lib" != x"no"], [
		AC_SUBST(OBJFWRT_AMIGA_LIB,
			['objfwrt${OBJFW_LIB_MAJOR}ppc.library'])
		t="-mresident32 -ffreestanding -noixemul"
		AC_SUBST(AMIGA_LIB_CFLAGS, $t)
		t="-mresident32 -nostartfiles -nodefaultlibs -noixemul -ldebug"
		AC_SUBST(AMIGA_LIB_LDFLAGS, "$t -lc")
	])

	AC_SUBST(LIBBASES_M, libbases.m)
	;;
*-msdosdjgpp*)
	enable_shared="no"
	enable_threads="no"
	enable_sockets="no"
	;;
*-*-mingw*)
	LDFLAGS="$LDFLAGS -Wl,--allow-multiple-definition -static-libgcc"
	LIBS="$LIBS -lversion"

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







<
<
<
<
<
<
<
<
<
<









|







64
65
66
67
68
69
70










71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
	OBJCFLAGS="$OBJCFLAGS -noixemul"
	OBJFW_OBJCFLAGS="$OBJFW_OBJCFLAGS -noixemul"
	LDFLAGS="$LDFLAGS -noixemul"
	LIBS="$LIBS -ldebug"

	enable_files="yes"	# Required for reading ENV:
	enable_shared="no"











	AC_SUBST(LIBBASES_M, libbases.m)
	;;
*-msdosdjgpp*)
	enable_shared="no"
	enable_threads="no"
	enable_sockets="no"
	;;
*-*-mingw*)
	LDFLAGS="$LDFLAGS -Wl,--allow-multiple-definition"
	LIBS="$LIBS -lversion"

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








147
148
149
150
151
152
153
	LIBS="$LIBS -latomic"
	;;
*-*-mint*)
	enable_shared="no"
	enable_threads="no"	# TODO
	with_tls="no"
	;;








esac

AS_IF([test x"$host_os" = x"msdosdjgpp" -a x"$build_os" = x"msdosdjgpp"], [
	dnl Hack to make configure find these on DOS.
	: ${AR:=ar.exe}
	: ${GREP:=grep.exe}
	: ${RANLIB:=ranlib.exe}







>
>
>
>
>
>
>
>







118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
	LIBS="$LIBS -latomic"
	;;
*-*-mint*)
	enable_shared="no"
	enable_threads="no"	# TODO
	with_tls="no"
	;;
*-apple-macos*)
	enable_shared="no"
	enable_threads="no"	# TODO
	enable_sockets="no"	# TODO

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

AS_IF([test x"$host_os" = x"msdosdjgpp" -a x"$build_os" = x"msdosdjgpp"], [
	dnl Hack to make configure find these on DOS.
	: ${AR:=ar.exe}
	: ${GREP:=grep.exe}
	: ${RANLIB:=ranlib.exe}
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
	;;
*)
	potential_compilers="clang egcc gcc"
	;;
esac
AC_PROG_OBJC($potential_compilers)
AC_PROG_OBJCPP
AC_PROG_LN_S
AC_PROG_EGREP

BUILDSYS_CHECK_IOS

AC_ARG_WITH(wii,
	AS_HELP_STRING([--with-wii], [build for Wii]))
AS_IF([test x"$with_wii" = x"yes"], [
	AS_IF([test x"$DEVKITPRO" = x""], [







|
|







148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
	;;
*)
	potential_compilers="clang egcc gcc"
	;;
esac
AC_PROG_OBJC($potential_compilers)
AC_PROG_OBJCPP
AC_PROG_EGREP
AC_PROG_LN_S

BUILDSYS_CHECK_IOS

AC_ARG_WITH(wii,
	AS_HELP_STRING([--with-wii], [build for Wii]))
AS_IF([test x"$with_wii" = x"yes"], [
	AS_IF([test x"$DEVKITPRO" = x""], [
344
345
346
347
348
349
350

351
352
353
354
355
356
357
AX_CHECK_COMPILER_FLAGS(-pipe, [OBJCFLAGS="$OBJCFLAGS -pipe"])
AX_CHECK_COMPILER_FLAGS(-fno-common, [OBJCFLAGS="$OBJCFLAGS -fno-common"])
AX_CHECK_COMPILER_FLAGS(-Xclang -fno-constant-cfstrings, [
	flag="-Xclang -fno-constant-cfstrings"
	OBJCFLAGS="$OBJCFLAGS $flag"
	OBJFW_OBJCFLAGS="$OBJFW_OBJCFLAGS $flag"
])

AX_CHECK_COMPILER_FLAGS([-Wsign-compare -Werror],
	[OBJCFLAGS="$OBJCFLAGS -Wsign-compare"])
AS_IF([test x"$with_nds" != x"yes"], [
	AX_CHECK_COMPILER_FLAGS([-Wshadow -Werror],
		[OBJCFLAGS="$OBJCFLAGS -Wshadow"])
])
AX_CHECK_COMPILER_FLAGS([-Wshorten-64-to-32 -Werror],







>







330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
AX_CHECK_COMPILER_FLAGS(-pipe, [OBJCFLAGS="$OBJCFLAGS -pipe"])
AX_CHECK_COMPILER_FLAGS(-fno-common, [OBJCFLAGS="$OBJCFLAGS -fno-common"])
AX_CHECK_COMPILER_FLAGS(-Xclang -fno-constant-cfstrings, [
	flag="-Xclang -fno-constant-cfstrings"
	OBJCFLAGS="$OBJCFLAGS $flag"
	OBJFW_OBJCFLAGS="$OBJFW_OBJCFLAGS $flag"
])

AX_CHECK_COMPILER_FLAGS([-Wsign-compare -Werror],
	[OBJCFLAGS="$OBJCFLAGS -Wsign-compare"])
AS_IF([test x"$with_nds" != x"yes"], [
	AX_CHECK_COMPILER_FLAGS([-Wshadow -Werror],
		[OBJCFLAGS="$OBJCFLAGS -Wshadow"])
])
AX_CHECK_COMPILER_FLAGS([-Wshorten-64-to-32 -Werror],
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
	;;
esac

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


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

	BUILDSYS_FRAMEWORK([
		AC_SUBST(OBJFW_FRAMEWORK, "ObjFW.framework")
		build_framework="yes"
	])
], [
	AC_DEFINE(OF_NO_SHARED, 1, [Whether no shared library was built])
	AC_SUBST(LIBOBJFW_DEP, "../src/libobjfw.a")
	AC_SUBST(LIBOBJFW_DEP_LVL2, "../../src/libobjfw.a")
])

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

AC_ARG_ENABLE(amiga-lib,
	AS_HELP_STRING([--disable-amiga-lib], [do not build Amiga library]))
AS_IF([test x"$supports_amiga_lib" != x"yes"], [enable_amiga_lib="no"])
AS_IF([test x"$enable_amiga_lib" != x"no"], [
	AC_SUBST(OBJFW_STATIC_LIB, "libobjfw.a")
	AC_SUBST(EXCEPTIONS_A, "exceptions.a")
	AC_SUBST(FORWARDING_A, "forwarding.a")
	AC_SUBST(LOOKUP_ASM_AMIGALIB_A, "lookup-asm.amigalib.a")
])

AC_ARG_ENABLE(static, AS_HELP_STRING([--enable-static], [build static library]))
AS_IF([test x"$enable_shared" = x"no" -a x"$enable_amiga_lib" = x"no"], [
	enable_static="yes"
])
AS_IF([test x"$enable_static" = x"yes"], [
	AC_SUBST(OBJFW_STATIC_LIB, "libobjfw.a")
	AC_SUBST(EXCEPTIONS_A, "exceptions.a")
	AC_SUBST(FORWARDING_A, "forwarding.a")
	AC_SUBST(LOOKUP_ASM_A, "lookup-asm.a")







>
>
|



















|



<
<
<
<
<
<
<
<
<
<

|







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

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

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

	BUILDSYS_FRAMEWORK([
		AC_SUBST(OBJFW_FRAMEWORK, "ObjFW.framework")
		build_framework="yes"
	])
], [
	AC_DEFINE(OF_NO_SHARED, 1, [Whether no shared library was built])
	AC_SUBST(LIBOBJFW_DEP, "../src/libobjfw.a")
	AC_SUBST(LIBOBJFW_DEP_LVL2, "../../src/libobjfw.a")
])

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











AC_ARG_ENABLE(static, AS_HELP_STRING([--enable-static], [build static library]))
AS_IF([test x"$enable_shared" = x"no"], [
	enable_static="yes"
])
AS_IF([test x"$enable_static" = x"yes"], [
	AC_SUBST(OBJFW_STATIC_LIB, "libobjfw.a")
	AC_SUBST(EXCEPTIONS_A, "exceptions.a")
	AC_SUBST(FORWARDING_A, "forwarding.a")
	AC_SUBST(LOOKUP_ASM_A, "lookup-asm.a")
523
524
525
526
527
528
529

530
531
532
533
534
535
536
	])
])
AC_MSG_RESULT($objc_runtime)

case "$objc_runtime" in
"ObjFW runtime")
	AC_DEFINE(OF_OBJFW_RUNTIME, 1, [Whether we use the ObjFW runtime])


	AC_MSG_CHECKING([whether -fobjc-runtime=objfw is supported])

	old_OBJCFLAGS="$OBJCFLAGS"
	OBJCFLAGS="$OBJCFLAGS -Xclang -fobjc-runtime=objfw"
	AC_LINK_IFELSE([
		AC_LANG_PROGRAM([







>







502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
	])
])
AC_MSG_RESULT($objc_runtime)

case "$objc_runtime" in
"ObjFW runtime")
	AC_DEFINE(OF_OBJFW_RUNTIME, 1, [Whether we use the ObjFW runtime])
	AC_SUBST(USE_SRCS_TAGGED_POINTERS, '${SRCS_TAGGED_POINTERS}')

	AC_MSG_CHECKING([whether -fobjc-runtime=objfw is supported])

	old_OBJCFLAGS="$OBJCFLAGS"
	OBJCFLAGS="$OBJCFLAGS -Xclang -fobjc-runtime=objfw"
	AC_LINK_IFELSE([
		AC_LANG_PROGRAM([
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
	])

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

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

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

	AS_IF([test x"$build_framework" = x"yes"], [
		AC_SUBST(OBJFWRT_FRAMEWORK, "ObjFWRT.framework")
		AC_SUBST(RUNTIME_FRAMEWORK_LIBS, "-framework ObjFWRT")
	])

	AS_IF([test x"$enable_amiga_lib" != x"no"], [
		AC_SUBST(RUNTIME_LIBS, "-lobjfwrt.library")
		AC_SUBST(LINKLIB, linklib)
		tmp="../src/runtime/linklib/libobjfwrt.library.a"
		AC_SUBST(LIBOBJFWRT_DEP, "$tmp")
		AC_SUBST(LIBOBJFWRT_DEP_LVL2, "../$tmp")
	], [
		AC_SUBST(RUNTIME_LIBS, "-lobjfwrt")
	])

	AS_IF([test x"$enable_shared" = x"no" \
	    -a x"$enable_amiga_lib" = x"no"], [
		AC_SUBST(LIBOBJFWRT_DEP, "../src/runtime/libobjfwrt.a")
		AC_SUBST(LIBOBJFWRT_DEP_LVL2, "../../src/runtime/libobjfwrt.a")
	])

	AS_IF([test x"$enable_seluid24" = x"yes"], [
		AC_DEFINE(OF_SELUID24, 1, [Whether to use 24 bit selector UIDs])
	])







|











<
<
<
<
<
<
<
|
<

|
<







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

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

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

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

	AS_IF([test x"$build_framework" = x"yes"], [
		AC_SUBST(OBJFWRT_FRAMEWORK, "ObjFWRT.framework")
		AC_SUBST(RUNTIME_FRAMEWORK_LIBS, "-framework ObjFWRT")
	])








	AC_SUBST(RUNTIME_LIBS, "-lobjfwrt")


	AS_IF([test x"$enable_shared" = x"no"], [

		AC_SUBST(LIBOBJFWRT_DEP, "../src/runtime/libobjfwrt.a")
		AC_SUBST(LIBOBJFWRT_DEP_LVL2, "../../src/runtime/libobjfwrt.a")
	])

	AS_IF([test x"$enable_seluid24" = x"yes"], [
		AC_DEFINE(OF_SELUID24, 1, [Whether to use 24 bit selector UIDs])
	])
1030
1031
1032
1033
1034
1035
1036








1037










1038
1039
1040
1041
1042
1043
1044

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

		AC_CHECK_FUNCS(pthread_attr_getschedpolicy)








		AC_CHECK_FUNCS(pthread_attr_setinheritsched)











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

	AC_DEFINE(OF_HAVE_THREADS, 1, [Whether we have threads])







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







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

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

		AC_CHECK_FUNCS(pthread_attr_getschedpolicy)

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

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

	AC_DEFINE(OF_HAVE_THREADS, 1, [Whether we have threads])
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
*)
	AC_CHECK_HEADERS(fcntl.h)
	AC_CHECK_FUNCS([fcntl nanosleep])
	;;
esac

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







|







1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
*)
	AC_CHECK_HEADERS(fcntl.h)
	AC_CHECK_FUNCS([fcntl nanosleep])
	;;
esac

AC_CHECK_HEADERS(xlocale.h)
AC_CHECK_FUNCS([strtod_l strtof_l asprintf_l uselocale])
AS_IF([test x"$gnu_source" != x"yes" -a \( \
    x"$ac_cv_func_strtod_l" = x"yes" -o x"$ac_cv_func_strtof_l" = x"yes" -o \
    x"$ac_cv_func_asprintf_l" = x"yes" \)], [
	AC_MSG_CHECKING(whether *_l functions need _GNU_SOURCE)
	AC_COMPILE_IFELSE([
		AC_LANG_PROGRAM([
			#include <stdlib.h>
1392
1393
1394
1395
1396
1397
1398

























1399
1400
1401
1402
1403
1404
1405
1406
1407
1408






1409


















1410
1411
1412
1413
1414
1415
1416
		;;
	esac

	AC_CHECK_HEADER(sys/socket.h, [
		AC_DEFINE(OF_HAVE_SYS_SOCKET_H, 1,
			[Whether we have sys/socket.h])
	])


























	AC_CHECK_HEADER(netinet/in.h, [
		AC_DEFINE(OF_HAVE_NETINET_IN_H, 1,
			[Whether we have netinet/in.h])
	])
	AC_CHECK_HEADER(netinet/tcp.h, [
		AC_DEFINE(OF_HAVE_NETINET_TCP_H, 1,
			[Whether we have netinet/tcp.h])
	])
	AC_CHECK_HEADERS([arpa/inet.h netdb.h net/if.h])






	AC_CHECK_FUNCS([if_indextoname if_nametoindex])


















	AC_CHECK_HEADER(sys/un.h, [
		AC_DEFINE(OF_HAVE_SYS_UN_H, 1, [Whether we have sys/un.h])
	])
	AC_CHECK_MEMBER([struct sockaddr_in6.sin6_addr], [
		AC_EGREP_CPP(egrep_cpp_yes, [
			#ifdef _WIN32
			typedef int BOOL;







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









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







1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
		;;
	esac

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

	AC_CHECK_HEADER(netinet/in.h, [
		AC_DEFINE(OF_HAVE_NETINET_IN_H, 1,
			[Whether we have netinet/in.h])
	])
	AC_CHECK_HEADER(netinet/tcp.h, [
		AC_DEFINE(OF_HAVE_NETINET_TCP_H, 1,
			[Whether we have netinet/tcp.h])
	])
	AC_CHECK_HEADERS([arpa/inet.h netdb.h sys/sockio.h])
	AC_CHECK_HEADERS([net/if.h], [], [], [
		#ifdef OF_HAVE_SYS_SOCKET_H
		# include <sys/socket.h>
		#endif
	])
	AC_CHECK_HEADERS([net/if_arp.h net/if_dl.h net/if_types.h])
	AC_CHECK_FUNCS([if_indextoname if_nametoindex if_nameindex])
	AC_CHECK_TYPES([struct sockaddr_dl], [], [], [
		#ifdef HAVE_SYS_TYPES_H
		# include <sys/types.h>
		#endif
		#ifdef HAVE_NET_IF_DL_H
		# include <net/if_dl.h>
		#endif
	])
	AC_CHECK_TYPES([struct lifconf], [], [], [
		#ifdef HAVE_NET_IF_H
		# include <net/if.h>
		#endif
	])
	AC_CHECK_MEMBERS([struct ifreq.ifr_hwaddr], [], [], [
		#ifdef HAVE_NET_IF_H
		# include <net/if.h>
		#endif
	])
	AC_CHECK_HEADER(sys/un.h, [
		AC_DEFINE(OF_HAVE_SYS_UN_H, 1, [Whether we have sys/un.h])
	])
	AC_CHECK_MEMBER([struct sockaddr_in6.sin6_addr], [
		AC_EGREP_CPP(egrep_cpp_yes, [
			#ifdef _WIN32
			typedef int BOOL;
1469
1470
1471
1472
1473
1474
1475















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















	], [], [
		#ifdef OF_HAVE_SYS_TYPES_H
		# include <sys/types.h>
		#endif
		#ifdef OF_HAVE_SYS_UN_H
		# include <sys/un.h>
		#endif







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







1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
		# include <winsock2.h>
		#endif
	])
	AC_CHECK_MEMBER(struct sockaddr_un.sun_path, [
		AC_DEFINE(OF_HAVE_UNIX_SOCKETS, 1,
			[Whether we have UNIX sockets])
		AC_SUBST(USE_SRCS_UNIX_SOCKETS, '${SRCS_UNIX_SOCKETS}')

		AC_CHECK_MEMBERS(struct sockaddr_un.sun_len, [], [], [
			#ifdef OF_HAVE_SYS_TYPES_H
			# include <sys/types.h>
			#endif
			#ifdef OF_HAVE_SYS_UN_H
			# include <sys/un.h>
			#endif
			#ifdef _WIN32
			# include <winsock2.h>
			#endif
			#ifdef HAVE_AFUNIX_H
			# include <afunix.h>
			#endif
		])
	], [], [
		#ifdef OF_HAVE_SYS_TYPES_H
		# include <sys/types.h>
		#endif
		#ifdef OF_HAVE_SYS_UN_H
		# include <sys/un.h>
		#endif
1497
1498
1499
1500
1501
1502
1503
1504











1505
1506
1507




1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527




1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545

1546
1547
1548
1549
1550
1551
1552
	])

	AC_CHECK_HEADER(netipx/ipx.h, [
		AC_DEFINE(OF_HAVE_NETIPX_IPX_H, 1,
			[Whether we have netipx/ipx.h])
	])
	AC_CHECK_MEMBER(struct sockaddr_ipx.sipx_network, [], [
		AC_CHECK_MEMBER(struct sockaddr_ipx.sa_netnum, [], [], [











			#ifdef _WIN32
			typedef int BOOL;
			#endif





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

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





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

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

		AC_EGREP_CPP(egrep_cpp_yes, [
			#ifdef _WIN32
			typedef int BOOL;
			#endif

			#ifdef OF_HAVE_SYS_SOCKET_H
			# include <sys/socket.h>







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



>
>
>
>




















>
>
>
>

















|
>







1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
	])

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

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

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

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

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

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

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

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

			#ifdef OF_HAVE_SYS_SOCKET_H
			# include <sys/socket.h>
1707
1708
1709
1710
1711
1712
1713
1714

1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781





1782
1783
1784





































1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
		])
		;;
	esac

	AC_ARG_WITH(tls,
		AS_HELP_STRING([--with-tls], [
			enable TLS support using the specified library
			(yes, openssl, gnutls, securetransport or no)]))

	AS_IF([test x"$with_tls" = x""], [with_tls="yes"])
	tls_support="no"

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

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

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

				AC_SUBST(OF_SECURE_TRANSPORT_TLS_STREAM_M,
					"OFSecureTransportTLSStream.m")

				AC_CHECK_FUNCS(SSLCreateContext)
			], [])

			LIBS="$old_LIBS"
		])
	])

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

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

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

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

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

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

				AC_SUBST(OF_OPENSSL_TLS_STREAM_M,
					"OFOpenSSLTLSStream.m")





			])
		], [], [-l$crypto])
	])






































	AS_IF([test x"$tls_support" != x"no"], [
		AC_SUBST(TLS, "tls")
		AC_SUBST(TLS_CPPFLAGS)
		AC_SUBST(TLS_LIBS)
		AC_DEFINE(HAVE_TLS_SUPPORT, 1,
			[Whether we have an implementation for TLS])
		AC_CONFIG_FILES(src/tls/Info.plist)

		OFHTTP_LIBS="-lobjfwtls $TLS_LIBS $OFHTTP_LIBS"

		AS_IF([test x"$enable_shared" != x"no"], [
			AC_SUBST(OBJFWTLS_SHARED_LIB,
				"${LIB_PREFIX}objfwtls${LIB_SUFFIX}")
		])
		AS_IF([test x"$enable_static" = x"yes" \
		    -o x"$enable_shared" = x"no"], [
			AC_SUBST(OBJFWTLS_STATIC_LIB, "libobjfwtls.a")
		])
		AS_IF([test x"$build_framework" = x"yes"], [
			AC_SUBST(OBJFWTLS_FRAMEWORK, "ObjFWTLS.framework")







|
>




|





<
<
<














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

|













<
<
<





>
>
>
>
>



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













|







1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798



1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812

















1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827



1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
		])
		;;
	esac

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

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

			AC_CHECK_FUNC(SSLHandshake, [



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

				AC_SUBST(OF_SECURE_TRANSPORT_TLS_STREAM_M,
					"OFSecureTransportTLSStream.m")

				AC_CHECK_FUNCS(SSLCreateContext)
			], [])

			LIBS="$old_LIBS"
		])
	])


















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

		AC_CHECK_LIB($ssl, SSL_set1_host, [
			AC_CHECK_HEADER(openssl/ssl.h, [



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

				AC_SUBST(OF_OPENSSL_TLS_STREAM_M,
					"OFOpenSSLTLSStream.m")

				old_LIBS="$LIBS"
				LIBS="$TLS_LIBS $LIBS"
				AC_CHECK_FUNCS(SSL_has_pending)
				LIBS="$old_LIBS"
			])
		], [], [-l$crypto])
	])

	AS_IF([test x"$with_tls" = x"gnutls" \
	    -o \( x"$with_tls" = x"yes" -a x"$tls_support" = x"no" \)], [
		PKG_CHECK_MODULES(gnutls, [gnutls >= 3.5.0], [
			tls_support="GnuTLS"
			TLS_CPPFLAGS="$gnutls_CFLAGS $TLS_CPPFLAGS"
			TLS_LIBS="$gnutls_LIBS $TLS_LIBS"

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

	AS_IF([test x"$with_tls" = x"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,
					"OFMbedTLSTLSStream.m")
			])
		], [], [-lmbedx509 -lmbedcrypto])
	])

	AS_IF([test x"$tls_support" != x"no"], [
		AC_SUBST(TLS, "tls")
		AC_SUBST(TLS_CPPFLAGS)
		AC_SUBST(TLS_LIBS)
		AC_DEFINE(HAVE_TLS_SUPPORT, 1,
			[Whether we have an implementation for TLS])
		AC_CONFIG_FILES(src/tls/Info.plist)

		OFHTTP_LIBS="-lobjfwtls $TLS_LIBS $OFHTTP_LIBS"

		AS_IF([test x"$enable_shared" != x"no"], [
			AC_SUBST(OBJFWTLS_SHARED_LIB,
				'${LIB_PREFIX}objfwtls${LIB_SUFFIX}')
		])
		AS_IF([test x"$enable_static" = x"yes" \
		    -o x"$enable_shared" = x"no"], [
			AC_SUBST(OBJFWTLS_STATIC_LIB, "libobjfwtls.a")
		])
		AS_IF([test x"$build_framework" = x"yes"], [
			AC_SUBST(OBJFWTLS_FRAMEWORK, "ObjFWTLS.framework")
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877


1878
1879
1880
1881
1882
1883
1884
1885
1886
1887

1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902

1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929

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

		AC_CHECK_FUNCS(posix_spawnp)
		AC_CHECK_HEADERS(spawn.h)
	], [
		AC_MSG_RESULT(no)
		have_subprocesses="no"
	])
	;;
mingw*)
	have_subprocesses="yes"
	;;
msdosdjgpp*)
	have_subprocesses="no"
	;;
*)


	AC_HEADER_SYS_WAIT
	AC_CHECK_FUNCS(kill)

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

			AC_CHECK_HEADERS(spawn.h)
		])
	], [

		AC_CHECK_FUNCS([vfork dup2 execvp _exit], [
			AS_IF([test x"$ac_cv_func_vfork" = x"yes" \
			    -a x"$ac_cv_func_pipe" = x"yes" \
			    -a x"$ac_cv_func_dup2" = x"yes" \
			    -a x"$ac_cv_func_execvp" = x"yes" \
			    -a x"$ac_cv_func_kill" = x"yes" \
			    -a x"$ac_cv_func__exit" = x"yes"], [
				have_subprocesses="yes"
			])
		], [
			break
		])
	])
	;;
esac

AS_IF([test x"$have_subprocesses" = x"yes"], [
	AC_SUBST(OF_SUBPROCESS_M, "OFSubprocess.m")
	AC_DEFINE(OF_HAVE_SUBPROCESSES, 1, [Whether we have subprocesses])
])

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

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

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

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







<
<
<
<











<
>
>





|
|
<
|
|
>













<
<
>






|












|







1948
1949
1950
1951
1952
1953
1954




1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965

1966
1967
1968
1969
1970
1971
1972
1973
1974

1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990


1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018

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




	], [
		AC_MSG_RESULT(no)
		have_subprocesses="no"
	])
	;;
mingw*)
	have_subprocesses="yes"
	;;
msdosdjgpp*)
	have_subprocesses="no"
	;;

esac
AS_IF([test x"$have_subprocesses" = x""], [
	AC_HEADER_SYS_WAIT
	AC_CHECK_FUNCS(kill)

	AC_CHECK_FUNCS(posix_spawnp, [
		AS_IF([test x"$ac_cv_func_kill" = x"yes"], [
			AC_CHECK_HEADERS(spawn.h, [have_subprocesses="yes"])
		])

	])

	AS_IF([test x"$have_subprocesses" = x""], [
		AC_CHECK_FUNCS([vfork dup2 execvp _exit], [
			AS_IF([test x"$ac_cv_func_vfork" = x"yes" \
			    -a x"$ac_cv_func_pipe" = x"yes" \
			    -a x"$ac_cv_func_dup2" = x"yes" \
			    -a x"$ac_cv_func_execvp" = x"yes" \
			    -a x"$ac_cv_func_kill" = x"yes" \
			    -a x"$ac_cv_func__exit" = x"yes"], [
				have_subprocesses="yes"
			])
		], [
			break
		])
	])


])
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, [
	AC_DEFINE(OF_HAVE_PLEDGE, 1, [Whether we have pledge()])
])

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

		AS_IF([test x"$enable_shared" != x"no"], [
			AC_SUBST(OBJFWBRIDGE_SHARED_LIB,
				'${LIB_PREFIX}objfwbridge${LIB_SUFFIX}')
		])
		AS_IF([test x"$enable_static" = x"yes" \
		    -o x"$enable_shared" = x"no"], [
			AC_SUBST(OBJFWBRIDGE_STATIC_LIB, "libobjfwbridge.a")
		])
		AS_IF([test x"$build_framework" = x"yes"], [
			AC_SUBST(OBJFWBRIDGE_FRAMEWORK,
1949
1950
1951
1952
1953
1954
1955
1956
1957








1958
1959
1960
1961
1962
1963
1964
	AC_MSG_RESULT(yes)
], [
	AC_MSG_RESULT(no)
	OBJCFLAGS="$old_OBJCFLAGS"
])

AS_IF([test x"$GOBJC" = x"yes"], [
	OBJCFLAGS="$OBJCFLAGS -Wwrite-strings -Wpointer-arith -Werror"









	AC_MSG_CHECKING(whether we need -Wno-strict-aliasing due to GCC bugs)
	AC_COMPILE_IFELSE([
		AC_LANG_PROGRAM([
			#ifdef __has_attribute
			# if __has_attribute(objc_root_class)
			__attribute__((__objc_root_class__))
			# endif







|

>
>
>
>
>
>
>
>







2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
	AC_MSG_RESULT(yes)
], [
	AC_MSG_RESULT(no)
	OBJCFLAGS="$old_OBJCFLAGS"
])

AS_IF([test x"$GOBJC" = x"yes"], [
	OBJCFLAGS="$OBJCFLAGS -Wwrite-strings -Wpointer-arith"

	AC_ARG_ENABLE(werror,
		AS_HELP_STRING([--disable-werror], [do not build with -Werror]))
	AS_IF([test x"$enable_werror" != x"no"], [
		OBJCFLAGS="$OBJCFLAGS -Werror"
	])

	old_OBJCFLAGS="$OBJCFLAGS"
	OBJCFLAGS="$OBJCFLAGS -Werror"
	AC_MSG_CHECKING(whether we need -Wno-strict-aliasing due to GCC bugs)
	AC_COMPILE_IFELSE([
		AC_LANG_PROGRAM([
			#ifdef __has_attribute
			# if __has_attribute(objc_root_class)
			__attribute__((__objc_root_class__))
			# endif
1974
1975
1976
1977
1978
1979
1980

1981
1982
1983
1984
1985


1986
1987
1988
1989
1990
1991
1992
			} object;
		], [
			Foo *test = (Foo *)&object;
			(void)test; /* Get rid of unused variable warning */
		])
	], [
		AC_MSG_RESULT(no)

	], [
		AC_MSG_RESULT(yes)
		OBJCFLAGS="$OBJCFLAGS -Wno-strict-aliasing"
	])



	AC_MSG_CHECKING(
	    whether we need -Wno-unused-property-ivar due to Clang bugs)
	AC_COMPILE_IFELSE([
		AC_LANG_SOURCE([
			#ifdef __has_attribute
			# if __has_attribute(objc_root_class)
			__attribute__((__objc_root_class__))







>


|


>
>







2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
			} object;
		], [
			Foo *test = (Foo *)&object;
			(void)test; /* Get rid of unused variable warning */
		])
	], [
		AC_MSG_RESULT(no)
		OBJCFLAGS="$old_OBJCFLAGS"
	], [
		AC_MSG_RESULT(yes)
		OBJCFLAGS="$old_OBJCFLAGS -Wno-strict-aliasing"
	])

	old_OBJCFLAGS="$OBJCFLAGS"
	OBJCFLAGS="$OBJCFLAGS -Werror"
	AC_MSG_CHECKING(
	    whether we need -Wno-unused-property-ivar due to Clang bugs)
	AC_COMPILE_IFELSE([
		AC_LANG_SOURCE([
			#ifdef __has_attribute
			# if __has_attribute(objc_root_class)
			__attribute__((__objc_root_class__))
2010
2011
2012
2013
2014
2015
2016

2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
			{
				return (Foo *)0;
			}
			@end
		])
	], [
		AC_MSG_RESULT(no)

	], [
		AC_MSG_RESULT(yes)
		OBJCFLAGS="$OBJCFLAGS -Wno-unused-property-ivar"
	])

	old_OBJCFLAGS="$OBJCFLAGS"
	OBJCFLAGS="$OBJCFLAGS -Wcast-align"
	AC_MSG_CHECKING(whether -Wcast-align is buggy)
	AC_COMPILE_IFELSE([
		AC_LANG_SOURCE([
			#ifdef __has_attribute
			# if __has_attribute(objc_root_class)
			__attribute__((__objc_root_class__))
			# endif







>


|



|







2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
			{
				return (Foo *)0;
			}
			@end
		])
	], [
		AC_MSG_RESULT(no)
		OBJCFLAGS="$old_OBJCFLAGS"
	], [
		AC_MSG_RESULT(yes)
		OBJCFLAGS="$old_OBJCFLAGS -Wno-unused-property-ivar"
	])

	old_OBJCFLAGS="$OBJCFLAGS"
	OBJCFLAGS="$OBJCFLAGS -Wcast-align -Werror"
	AC_MSG_CHECKING(whether -Wcast-align is buggy)
	AC_COMPILE_IFELSE([
		AC_LANG_SOURCE([
			#ifdef __has_attribute
			# if __has_attribute(objc_root_class)
			__attribute__((__objc_root_class__))
			# endif
2041
2042
2043
2044
2045
2046
2047

2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
				struct objc_class *c = _isa;
				(void)c;
			}
			@end
		])
	], [
		AC_MSG_RESULT(no)

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

	old_OBJCFLAGS="$OBJCFLAGS"
	OBJCFLAGS="$OBJCFLAGS -Wunreachable-code"
	AC_MSG_CHECKING(whether -Wunreachable-code can be used)
	AC_COMPILE_IFELSE([
		AC_LANG_SOURCE([[
			#include <stdlib.h>

			struct objc_selector;
			typedef const struct objc_selector *SEL;







>






|







2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
				struct objc_class *c = _isa;
				(void)c;
			}
			@end
		])
	], [
		AC_MSG_RESULT(no)
		OBJCFLAGS="$old_OBJCFLAGS -Wcast-align"
	], [
		AC_MSG_RESULT(yes)
		OBJCFLAGS="$old_OBJCFLAGS"
	])

	old_OBJCFLAGS="$OBJCFLAGS"
	OBJCFLAGS="$OBJCFLAGS -Wunreachable-code -Werror"
	AC_MSG_CHECKING(whether -Wunreachable-code can be used)
	AC_COMPILE_IFELSE([
		AC_LANG_SOURCE([[
			#include <stdlib.h>

			struct objc_selector;
			typedef const struct objc_selector *SEL;
2117
2118
2119
2120
2121
2122
2123

2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
			{
				OF_DEALLOC_UNSUPPORTED
			}
			@end
		]])
	], [
		AC_MSG_RESULT(yes)

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

	old_OBJCFLAGS="$OBJCFLAGS"
	OBJCFLAGS="$OBJCFLAGS -Wdocumentation"
	AC_MSG_CHECKING(whether -Wdocumentation works correctly)
	AC_COMPILE_IFELSE([
		AC_LANG_SOURCE([
			/**
			 * @class Test conftest.m conftest.m
			 */
			#ifdef __has_attribute







>






|







2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
			{
				OF_DEALLOC_UNSUPPORTED
			}
			@end
		]])
	], [
		AC_MSG_RESULT(yes)
		OBJCFLAGS="$old_OBJCFLAGS -Wunreachable-code"
	], [
		AC_MSG_RESULT(no)
		OBJCFLAGS="$old_OBJCFLAGS"
	])

	old_OBJCFLAGS="$OBJCFLAGS"
	OBJCFLAGS="$OBJCFLAGS -Wdocumentation -Werror"
	AC_MSG_CHECKING(whether -Wdocumentation works correctly)
	AC_COMPILE_IFELSE([
		AC_LANG_SOURCE([
			/**
			 * @class Test conftest.m conftest.m
			 */
			#ifdef __has_attribute
2145
2146
2147
2148
2149
2150
2151

2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
			/**
			 * @struct Foo conftest.m conftest.m
			 */
			typedef struct {} Foo;
		])
	], [
		AC_MSG_RESULT(yes)

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

	AS_IF([test x"$check_pedantic" = x"yes"], [
		old_OBJCFLAGS="$OBJCFLAGS"
		OBJCFLAGS="$OBJCFLAGS -pedantic"
		AC_MSG_CHECKING(whether -pedantic is buggy)
		AC_COMPILE_IFELSE([
			AC_LANG_SOURCE([
				#include <stdlib.h>

				#include <assert.h>








>







|







2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
			/**
			 * @struct Foo conftest.m conftest.m
			 */
			typedef struct {} Foo;
		])
	], [
		AC_MSG_RESULT(yes)
		OBJCFLAGS="$old_OBJCFLAGS -Wdocumentation"
	], [
		AC_MSG_RESULT(no)
		OBJCFLAGS="$old_OBJCFLAGS"
	])

	AS_IF([test x"$check_pedantic" = x"yes"], [
		old_OBJCFLAGS="$OBJCFLAGS"
		OBJCFLAGS="$OBJCFLAGS -pedantic -Werror"
		AC_MSG_CHECKING(whether -pedantic is buggy)
		AC_COMPILE_IFELSE([
			AC_LANG_SOURCE([
				#include <stdlib.h>

				#include <assert.h>

2188
2189
2190
2191
2192
2193
2194

2195
2196
2197
2198
2199
2200

















2201


2202
2203
2204
2205
2206
2207
2208
2209
2210
2211

2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
					 */
					assert(1);
				}
				@end
			])
		], [
			AC_MSG_RESULT(no)

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


















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


		AC_MSG_CHECKING(whether we need -Wno-gnu-imaginary-constant)
		AC_COMPILE_IFELSE([
			AC_LANG_PROGRAM([
				#include <complex.h>
			], [
				complex float f = 0.5 + 0.5 * I;
				(void)f;
			])
		], [
			AC_MSG_RESULT(no)

		], [
			AC_MSG_RESULT(yes)
			OBJCFLAGS="$OBJCFLAGS -Wno-gnu-imaginary-constant"
		])
	])
])

AS_IF([test x"$cross_compiling" = x"yes"], [
	AC_SUBST(BIN_PREFIX, "${host_alias}-")

	case "$host" in
	i?86-*-mingw*)
		AC_CHECK_PROG(WINE, wine, wine)
		;;
	x86_64-*-mingw*)
		AC_CHECK_PROG(WINE, wine64, wine64)
		;;
	esac

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

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

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

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

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







>






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

>
>










>


|















<
|
<
<













<
<
<
<
<
<
<
<
<
<
<







2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354

2355


2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368











2369
2370
2371
2372
2373
2374
2375
					 */
					assert(1);
				}
				@end
			])
		], [
			AC_MSG_RESULT(no)
			OBJCFLAGS="$old_OBJCFLAGS -pedantic"
		], [
			AC_MSG_RESULT(yes)
			OBJCFLAGS="$old_OBJCFLAGS"
		])
	])

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

	AS_IF([test x"$ac_cv_header_complex_h" = x"yes"], [
		old_OBJCFLAGS="$OBJCFLAGS"
		OBJCFLAGS="$OBJCFLAGS -Werror"
		AC_MSG_CHECKING(whether we need -Wno-gnu-imaginary-constant)
		AC_COMPILE_IFELSE([
			AC_LANG_PROGRAM([
				#include <complex.h>
			], [
				complex float f = 0.5 + 0.5 * I;
				(void)f;
			])
		], [
			AC_MSG_RESULT(no)
			OBJCFLAGS="$old_OBJCFLAGS"
		], [
			AC_MSG_RESULT(yes)
			OBJCFLAGS="$old_OBJCFLAGS -Wno-gnu-imaginary-constant"
		])
	])
])

AS_IF([test x"$cross_compiling" = x"yes"], [
	AC_SUBST(BIN_PREFIX, "${host_alias}-")

	case "$host" in
	i?86-*-mingw*)
		AC_CHECK_PROG(WINE, wine, wine)
		;;
	x86_64-*-mingw*)
		AC_CHECK_PROG(WINE, wine64, wine64)
		;;
	esac

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



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

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












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

Modified extra.mk.in from [8e59637d10] to [b53f574989].

1
2
3
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
OBJFW_SHARED_LIB = @OBJFW_SHARED_LIB@
OBJFW_STATIC_LIB = @OBJFW_STATIC_LIB@
OBJFW_FRAMEWORK = @OBJFW_FRAMEWORK@
OBJFW_LIB_MAJOR = 0
OBJFW_LIB_MINOR = 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_AMIGA_LIB = @OBJFWRT_AMIGA_LIB@
OBJFWRT_LIB_MAJOR = 0
OBJFWRT_LIB_MINOR = 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@




OBJFWTLS_SHARED_LIB = @OBJFWTLS_SHARED_LIB@
OBJFWTLS_STATIC_LIB = @OBJFWTLS_STATIC_LIB@
OBJFWTLS_FRAMEWORK = @OBJFWTLS_FRAMEWORK@




BIN_PREFIX = @BIN_PREFIX@
BRIDGE = @BRIDGE@
CVINCLUDE_INLINE_H = @CVINCLUDE_INLINE_H@
ENCODINGS_A = @ENCODINGS_A@
ENCODINGS_LIB_A = @ENCODINGS_LIB_A@
ENCODINGS_SRCS = @ENCODINGS_SRCS@
EXCEPTIONS_A = @EXCEPTIONS_A@
EXCEPTIONS_LIB_A = @EXCEPTIONS_LIB_A@
FISH_COMPLETIONS = @FISH_COMPLETIONS@
FORWARDING_A = @FORWARDING_A@
FORWARDING_LIB_A = @FORWARDING_LIB_A@
LIBBASES_M = @LIBBASES_M@
LIBOBJFWRT_DEP = @LIBOBJFWRT_DEP@
LIBOBJFWRT_DEP_LVL2 = @LIBOBJFWRT_DEP_LVL2@
LIBOBJFW_DEP = @LIBOBJFW_DEP@
LIBOBJFW_DEP_LVL2 = @LIBOBJFW_DEP_LVL2@
LINKLIB = @LINKLIB@
LOOKUP_ASM_A = @LOOKUP_ASM_A@
LOOKUP_ASM_AMIGALIB_A = @LOOKUP_ASM_AMIGALIB_A@
LOOKUP_ASM_LIB_A = @LOOKUP_ASM_LIB_A@
MAP_LDFLAGS = @MAP_LDFLAGS@
OBJC_SYNC = @OBJC_SYNC@
OBJFW_NEW = @OBJFW_NEW@
OFARC = @OFARC@
OFDNS = @OFDNS@
OFHASH = @OFHASH@
OFHTTP = @OFHTTP@
OFHTTP_LIBS = @OFHTTP_LIBS@
OF_BLOCK_TESTS_M = @OF_BLOCK_TESTS_M@
OF_EPOLL_KERNEL_EVENT_OBSERVER_M = @OF_EPOLL_KERNEL_EVENT_OBSERVER_M@
OF_GNUTLS_TLS_STREAM_M = @OF_GNUTLS_TLS_STREAM_M@
OF_HTTP_CLIENT_TESTS_M = @OF_HTTP_CLIENT_TESTS_M@
OF_KQUEUE_KERNEL_EVENT_OBSERVER_M = @OF_KQUEUE_KERNEL_EVENT_OBSERVER_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@



|
|
>





|
|
|





>
>
>




>
>
>









<







<

<














>







1
2
3
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
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
OBJFWBRIDGE_LIB_MINOR = 0
OBJFWBRIDGE_LIB_PATCH = 0

OBJFWTLS_SHARED_LIB = @OBJFWTLS_SHARED_LIB@
OBJFWTLS_STATIC_LIB = @OBJFWTLS_STATIC_LIB@
OBJFWTLS_FRAMEWORK = @OBJFWTLS_FRAMEWORK@
OBJFWTLS_LIB_MAJOR = 1
OBJFWTLS_LIB_MINOR = 0
OBJFWTLS_LIB_PATCH = 2

BIN_PREFIX = @BIN_PREFIX@
BRIDGE = @BRIDGE@
CVINCLUDE_INLINE_H = @CVINCLUDE_INLINE_H@
ENCODINGS_A = @ENCODINGS_A@
ENCODINGS_LIB_A = @ENCODINGS_LIB_A@
ENCODINGS_SRCS = @ENCODINGS_SRCS@
EXCEPTIONS_A = @EXCEPTIONS_A@
EXCEPTIONS_LIB_A = @EXCEPTIONS_LIB_A@

FORWARDING_A = @FORWARDING_A@
FORWARDING_LIB_A = @FORWARDING_LIB_A@
LIBBASES_M = @LIBBASES_M@
LIBOBJFWRT_DEP = @LIBOBJFWRT_DEP@
LIBOBJFWRT_DEP_LVL2 = @LIBOBJFWRT_DEP_LVL2@
LIBOBJFW_DEP = @LIBOBJFW_DEP@
LIBOBJFW_DEP_LVL2 = @LIBOBJFW_DEP_LVL2@

LOOKUP_ASM_A = @LOOKUP_ASM_A@

LOOKUP_ASM_LIB_A = @LOOKUP_ASM_LIB_A@
MAP_LDFLAGS = @MAP_LDFLAGS@
OBJC_SYNC = @OBJC_SYNC@
OBJFW_NEW = @OBJFW_NEW@
OFARC = @OFARC@
OFDNS = @OFDNS@
OFHASH = @OFHASH@
OFHTTP = @OFHTTP@
OFHTTP_LIBS = @OFHTTP_LIBS@
OF_BLOCK_TESTS_M = @OF_BLOCK_TESTS_M@
OF_EPOLL_KERNEL_EVENT_OBSERVER_M = @OF_EPOLL_KERNEL_EVENT_OBSERVER_M@
OF_GNUTLS_TLS_STREAM_M = @OF_GNUTLS_TLS_STREAM_M@
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@
80
81
82
83
84
85
86

87
88
89
90
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_THREADS = @USE_SRCS_THREADS@
USE_SRCS_UNIX_SOCKETS = @USE_SRCS_UNIX_SOCKETS@
USE_SRCS_WINDOWS = @USE_SRCS_WINDOWS@
WRAPPER = @WRAPPER@







>




85
86
87
88
89
90
91
92
93
94
95
96
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@

Deleted generators/library/FuncArrayGenerator.h version [2d0edf7996].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#import "OFObject.h"

#import "OFStream.h"
#import "OFXMLElement.h"

@interface FuncArrayGenerator: OFObject
{
	OFXMLElement *_library;
	OFStream *_include;
}

- (instancetype)initWithLibrary: (OFXMLElement *)library
			include: (OFStream *)include;
- (void)generate;
@end
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<




























































Deleted generators/library/FuncArrayGenerator.m version [4ed090453c].

1
2
3
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
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#import "OFArray.h"
#import "OFXMLAttribute.h"

#import "FuncArrayGenerator.h"

#import "OFInvalidFormatException.h"
#import "OFUnsupportedVersionException.h"

#import "copyright.h"

@implementation FuncArrayGenerator
- (instancetype)initWithLibrary: (OFXMLElement *)library
			include: (OFStream *)include
{
	self = [super init];

	@try {
		OFXMLAttribute *version;

		if (![library.name isEqual: @"amiga-library"] ||
		    library.namespace != nil)
			@throw [OFInvalidFormatException exception];

		if ((version = [library attributeForName: @"version"]) == nil)
			@throw [OFInvalidFormatException exception];

		if (![version.stringValue isEqual: @"1.0"])
			@throw [OFUnsupportedVersionException
			    exceptionWithVersion: version.stringValue];

		_library = [library retain];
		_include = [include retain];
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (void)dealloc
{
	[_library release];
	[_include release];

	[super dealloc];
}

- (void)generate
{
	[_include writeString: COPYRIGHT];
	[_include writeString:
	    @"/* This file is automatically generated from amiga-library.xml */"
	    @"\n\n"];

	for (OFXMLElement *function in [_library elementsForName: @"function"])
		[_include writeFormat:
		    @"(CONST_APTR)glue_%@,\n",
		    [function attributeForName: @"name"].stringValue];
}
@end
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<




























































































































































Deleted generators/library/GlueGenerator.h version [df3f9366c5].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#import "OFObject.h"

#import "OFStream.h"
#import "OFXMLElement.h"

@interface GlueGenerator: OFObject
{
	OFXMLElement *_library;
	OFStream *_header, *_impl;
}

- (instancetype)initWithLibrary: (OFXMLElement *)library
			 header: (OFStream *)header
		 implementation: (OFStream *)implementation;
- (void)generate;
@end
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<






























































Deleted generators/library/GlueGenerator.m version [a4f73aa06c].

1
2
3
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
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#import "OFArray.h"
#import "OFXMLAttribute.h"

#import "GlueGenerator.h"

#import "OFInvalidFormatException.h"
#import "OFUnsupportedVersionException.h"

#import "copyright.h"

@implementation GlueGenerator
- (instancetype)initWithLibrary: (OFXMLElement *)library
			 header: (OFStream *)header
		 implementation: (OFStream *)impl
{
	self = [super init];

	@try {
		OFXMLAttribute *version;

		if (![library.name isEqual: @"amiga-library"] ||
		    library.namespace != nil)
			@throw [OFInvalidFormatException exception];

		if ((version = [library attributeForName: @"version"]) == nil)
			@throw [OFInvalidFormatException exception];

		if (![version.stringValue isEqual: @"1.0"])
			@throw [OFUnsupportedVersionException
			    exceptionWithVersion: version.stringValue];

		_library = [library retain];
		_header = [header retain];
		_impl = [impl retain];
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (void)dealloc
{
	[_library release];
	[_header release];
	[_impl release];

	[super dealloc];
}

- (void)generate
{
	[_header writeString: COPYRIGHT];
	[_impl writeString: COPYRIGHT];

	[_header writeString:
	    @"/* This file is automatically generated from amiga-library.xml */"
	    @"\n\n"];

	[_impl writeString:
	    @"/* This file is automatically generated from amiga-library.xml */"
	    @"\n\n"
	    @"#include \"config.h\"\n"
	    @"\n"
	    @"#import \"amiga-glue.h\"\n"
	    @"\n"];

	for (OFXMLElement *include in [_library elementsForName: @"include"])
		[_header writeFormat: @"#import \"%@\"\n", include.stringValue];

	[_header writeString:
	    @"\n"
	    @"#ifdef OF_AMIGAOS_M68K\n"
	    @"# define PPC_PARAMS(...) (void)\n"
	    @"# define M68K_ARG(type, name, reg)\t\t\\\n"
	    @"\tregister type reg##name __asm__(#reg);\t\\\n"
	    @"\ttype name = reg##name;\n"
	    @"#else\n"
	    @"# define PPC_PARAMS(...) (__VA_ARGS__)\n"
	    @"# define M68K_ARG(...)\n"
	    @"#endif\n"
	    @"\n"];
	[_impl writeString:
	    @"#ifdef OF_MORPHOS\n"
	    @"/* All __saveds functions in this file need to use the SysV "
	    @"ABI */\n"
	    @"__asm__ (\n"
	    @"    \".section .text\\n\"\n"
	    @"    \".align 2\\n\"\n"
	    @"    \"__restore_r13:\\n\"\n"
	    @"    \"\tlwz\t%r13, 44(%r12)\\n\"\n"
	    @"    \"\tblr\\n\"\n"
	    @");\n"
	    @"#endif\n"];

	for (OFXMLElement *function in
	    [_library elementsForName: @"function"]) {
		OFString *name =
		    [function attributeForName: @"name"].stringValue;
		OFString *returnType =
		    [function attributeForName: @"return-type"].stringValue;
		OFArray OF_GENERIC(OFXMLElement *) *arguments =
		    [function elementsForName: @"argument"];
		size_t argumentIndex;

		if (returnType == nil)
			returnType = @"void";

		[_header writeFormat:
		    @"extern %@%@glue_%@",
		    returnType,
		    (![returnType hasSuffix: @"*"] ? @" " : @""),
		    name];

		[_impl writeFormat: @"\n"
				    @"%@ __saveds\n"
				    @"glue_%@",
				    returnType, name];

		if (arguments.count > 0) {
			[_header writeString: @" PPC_PARAMS("];
			[_impl writeString: @" PPC_PARAMS("];
		} else {
			[_header writeString: @"(void"];
			[_impl writeString: @"(void"];
		}

		argumentIndex = 0;
		for (OFXMLElement *argument in arguments) {
			OFString *argName =
			    [argument attributeForName: @"name"].stringValue;
			OFString *argType =
			    [argument attributeForName: @"type"].stringValue;

			if (argumentIndex++ > 0) {
				[_header writeString: @", "];
				[_impl writeString: @", "];
			}

			[_header writeString: argType];
			[_impl writeString: argType];
			if (![argType hasSuffix: @"*"]) {
				[_header writeString: @" "];
				[_impl writeString: @" "];
			}
			[_header writeString: argName];
			[_impl writeString: argName];
		}

		[_header writeString: @");\n"];

		[_impl writeString: @")\n{\n"];
		for (OFXMLElement *argument in arguments) {
			OFString *argName =
			    [argument attributeForName: @"name"].stringValue;
			OFString *argType =
			    [argument attributeForName: @"type"].stringValue;
			OFString *m68kReg = [argument
			    attributeForName: @"m68k-reg"].stringValue;

			[_impl writeFormat: @"\tM68K_ARG(%@, %@, %@)\n",
					    argType, argName, m68kReg];
		}

		if (arguments.count > 0)
			[_impl writeString: @"\n"];

		if (![returnType isEqual: @"void"])
			[_impl writeString: @"\treturn "];
		else
			[_impl writeString: @"\t"];

		[_impl writeFormat: @"%@(", name];

		argumentIndex = 0;
		for (OFXMLElement *argument in arguments) {
			OFString *argName =
			    [argument attributeForName: @"name"].stringValue;

			if (argumentIndex++ > 0)
				[_impl writeString: @", "];

			[_impl writeString: argName];
		}

		[_impl writeString: @");\n}\n"];
	}
}
@end
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<






























































































































































































































































































































































































































Deleted generators/library/LibraryGenerator.m version [69ede2939c].

1
2
3
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
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#import "OFApplication.h"
#import "OFFile.h"
#import "OFFileManager.h"
#import "OFURI.h"
#import "OFXMLElement.h"

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

@interface LibraryGenerator: OFObject <OFApplicationDelegate>
@end

OF_APPLICATION_DELEGATE(LibraryGenerator)

@implementation LibraryGenerator
- (void)applicationDidFinishLaunching
{
	OFURI *sourcesURI = [[OFFileManager defaultManager].currentDirectoryURI
	    URIByAppendingPathComponent: @"../../src"];
	OFURI *runtimeLibraryURI = [sourcesURI
	    URIByAppendingPathComponent: @"runtime/amiga-library.xml"];
	OFURI *runtimeLinkLibURI = [sourcesURI
	    URIByAppendingPathComponent: @"runtime/linklib/linklib.m"];
	OFURI *runtimeGlueHeaderURI = [sourcesURI
	    URIByAppendingPathComponent: @"runtime/amiga-glue.h"];
	OFURI *runtimeGlueURI = [sourcesURI
	    URIByAppendingPathComponent: @"runtime/amiga-glue.m"];
	OFURI *runtimeFuncArrayURI = [sourcesURI
	    URIByAppendingPathComponent: @"runtime/amiga-funcarray.inc"];
	OFXMLElement *runtimeLibrary = [OFXMLElement elementWithStream:
	    [OFFile fileWithPath: runtimeLibraryURI.fileSystemRepresentation
			    mode: @"r"]];
	OFFile *runtimeLinkLib =
	    [OFFile fileWithPath: runtimeLinkLibURI.fileSystemRepresentation
			    mode: @"w"];
	OFFile *runtimeGlueHeader =
	    [OFFile fileWithPath: runtimeGlueHeaderURI.fileSystemRepresentation
			    mode: @"w"];
	OFFile *runtimeGlue =
	    [OFFile fileWithPath: runtimeGlueURI.fileSystemRepresentation
			    mode: @"w"];
	OFFile *runtimeFuncArray =
	    [OFFile fileWithPath: runtimeFuncArrayURI.fileSystemRepresentation
			    mode: @"w"];
	LinkLibGenerator *runtimeLinkLibGenerator = [[[LinkLibGenerator alloc]
	    initWithLibrary: runtimeLibrary
	     implementation: runtimeLinkLib] autorelease];
	GlueGenerator *runtimeGlueGenerator = [[[GlueGenerator alloc]
	    initWithLibrary: runtimeLibrary
		     header: runtimeGlueHeader
	     implementation: runtimeGlue] autorelease];
	FuncArrayGenerator *runtimeFuncArrayGenerator;
	runtimeFuncArrayGenerator = [[[FuncArrayGenerator alloc]
	    initWithLibrary: runtimeLibrary
		    include: runtimeFuncArray] autorelease];

	[runtimeLinkLibGenerator generate];
	[runtimeGlueGenerator generate];
	[runtimeFuncArrayGenerator generate];

	[OFApplication terminate];
}
@end
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<


































































































































































Deleted generators/library/LinkLibGenerator.h version [58647bf17f].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#import "OFObject.h"
#import "OFStream.h"
#import "OFXMLElement.h"

@interface LinkLibGenerator: OFObject
{
	OFXMLElement *_library;
	OFStream *_impl;
}

- (instancetype)initWithLibrary: (OFXMLElement *)library
		 implementation: (OFStream *)impl;
- (void)generate;
@end
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<


























































Deleted generators/library/LinkLibGenerator.m version [e9161f0524].

1
2
3
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
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#import "OFArray.h"
#import "OFXMLAttribute.h"

#import "LinkLibGenerator.h"

#import "OFInvalidFormatException.h"
#import "OFUnsupportedVersionException.h"

#import "copyright.h"

@implementation LinkLibGenerator
- (instancetype)initWithLibrary: (OFXMLElement *)library
		 implementation: (OFStream *)impl
{
	self = [super init];

	@try {
		OFXMLAttribute *version;

		if (![library.name isEqual: @"amiga-library"] ||
		    library.namespace != nil)
			@throw [OFInvalidFormatException exception];

		if ((version = [library attributeForName: @"version"]) == nil)
			@throw [OFInvalidFormatException exception];

		if (![version.stringValue isEqual: @"1.0"])
			@throw [OFUnsupportedVersionException
			    exceptionWithVersion: version.stringValue];

		_library = [library retain];
		_impl = [impl retain];
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (void)dealloc
{
	[_library release];
	[_impl release];

	[super dealloc];
}

- (void)generate
{
	OFString *libBase = [_library attributeForName: @"base"].stringValue;
	OFArray OF_GENERIC(OFXMLElement *) *functions;
	size_t funcIndex = 0;

	[_impl writeString: COPYRIGHT];
	[_impl writeString:
	    @"/* This file is automatically generated from amiga-library.xml */"
	    @"\n\n"
	    @"#include \"config.h\"\n"
	    @"\n"];

	for (OFXMLElement *include in [_library elementsForName: @"include"])
		[_impl writeFormat: @"#import \"%@\"\n",
				    include.stringValue];

	[_impl writeFormat: @"\n"
			    @"extern struct Library *%@;\n"
			    @"\n",
			    libBase];

	functions = [_library elementsForName: @"function"];
	for (OFXMLElement *function in functions) {
		OFString *name =
		    [function attributeForName: @"name"].stringValue;
		OFString *returnType =
		    [function attributeForName: @"return-type"].stringValue;
		OFArray OF_GENERIC(OFXMLElement *) *arguments =
		    [function elementsForName: @"argument"];
		size_t argumentIndex;

		if (returnType == nil)
			returnType = @"void";

		[_impl writeFormat: @"%@\n%@(", returnType, name];

		argumentIndex = 0;
		for (OFXMLElement *argument in
		    [function elementsForName: @"argument"]) {
			OFString *argName =
			    [argument attributeForName: @"name"].stringValue;
			OFString *argType =
			    [argument attributeForName: @"type"].stringValue;

			if (argumentIndex++ > 0)
				[_impl writeString: @", "];

			[_impl writeString: argType];
			if (![argType hasSuffix: @"*"])
				[_impl writeString: @" "];
			[_impl writeString: argName];
		}

		[_impl writeFormat:
		    @")\n"
		    @"{\n"
		    @"#if defined(OF_AMIGAOS_M68K)\n"
		    @"\tregister struct Library *a6 __asm__(\"a6\") = %@;\n"
		    @"\t(void)a6;\n"
		    @"\t", libBase];

		if (![returnType isEqual: @"void"])
			[_impl writeString: @"return "];

		[_impl writeString: @"(("];
		[_impl writeString: returnType];
		if (![returnType hasSuffix: @"*"])
			[_impl writeString: @" "];
		[_impl writeString: @"(*)("];

		argumentIndex = 0;
		for (OFXMLElement *argument in arguments) {
			OFString *argType =
			    [argument attributeForName: @"type"].stringValue;
			OFString *m68kReg = [argument
			    attributeForName: @"m68k-reg"].stringValue;

			if (argumentIndex++ > 0)
				[_impl writeString: @", "];

			[_impl writeString: argType];
			if (![argType hasSuffix: @"*"])
				[_impl writeString: @" "];
			[_impl writeFormat: @"__asm__(\"%@\")",
						    m68kReg];
		}

		[_impl writeFormat: @"))(((uintptr_t)%@) - %zu))(",
				    libBase, 30 + funcIndex * 6];

		argumentIndex = 0;
		for (OFXMLElement *argument in
		    [function elementsForName: @"argument"]) {
			OFString *argName =
			    [argument attributeForName: @"name"].stringValue;

			if (argumentIndex++ > 0)
				[_impl writeString: @", "];

			[_impl writeString: argName];
		}

		[_impl writeFormat: @");\n"
				    @"#elif defined(OF_MORPHOS)\n"
				    @"\t__asm__ __volatile__ (\n"
				    @"\t    \"mr\t\t%%%%r12, %%0\"\n"
				    @"\t    :: \"r\"(%@) : \"r12\"\n"
				    @"\t);\n"
				    @"\n"
				    @"\t",
				    libBase, libBase];

		if (![returnType isEqual: @"void"])
			[_impl writeString: @"return "];

		[_impl writeString: @"__extension__ (("];
		[_impl writeString: returnType];
		if (![returnType hasSuffix: @"*"])
			[_impl writeString: @" "];
		[_impl writeString: @"(*)("];

		argumentIndex = 0;
		for (OFXMLElement *argument in arguments) {
			OFString *argType =
			    [argument attributeForName: @"type"].stringValue;

			if (argumentIndex++ > 0)
				[_impl writeString: @", "];

			[_impl writeString: argType];
		}

		[_impl writeFormat: @"))*(void **)(((uintptr_t)%@) - %zu))(",
				    libBase, 28 + funcIndex * 6];

		argumentIndex = 0;
		for (OFXMLElement *argument in
		    [function elementsForName: @"argument"]) {
			OFString *argName =
			    [argument attributeForName: @"name"].stringValue;

			if (argumentIndex++ > 0)
				[_impl writeString: @", "];

			[_impl writeString: argName];
		}

		[_impl writeString: @");\n"
				    @"#endif\n"];

		if ([function attributeForName: @"noreturn"] != nil)
			[_impl writeString: @"\n\tOF_UNREACHABLE\n"];

		[_impl writeString: @"}\n"];

		if (++funcIndex < functions.count)
			[_impl writeString: @"\n"];
	}
}
@end
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<




































































































































































































































































































































































































































































Deleted generators/library/Makefile version [b62d874949].

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

PROG_NOINST = gen_libraries${PROG_SUFFIX}
SRCS = FuncArrayGenerator.m	\
       GlueGenerator.m		\
       LibraryGenerator.m	\
       LinkLibGenerator.m

include ../../buildsys.mk

.PHONY: run
run: all
	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
	rm -f ${OBJFWRT_AMIGA_LIB}
	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
	if test -f ../../src/runtime/${OBJFWRT_AMIGA_LIB}; then \
		${LN_S} ../../src/runtime/${OBJFWRT_AMIGA_LIB} \
		    ${OBJFWRT_AMIGA_LIB}; \
	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

CPPFLAGS += -I../../src -I../../src/exceptions -I../../src/runtime -I../..
LIBS := -L../../src -lobjfw -L../../src/runtime ${RUNTIME_LIBS} ${LIBS}
LD = ${OBJC}
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<






















































































































































Deleted generators/library/copyright.h version [c0b22b50fd].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#import "OFString.h"

#define COPYRIGHT \
    @"/*\n"								       \
    @" * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>\n"	       \
    @" *\n"								       \
    @" * All rights reserved.\n"					       \
    @" *\n"								       \
    @" * This file is part of ObjFW. It may be distributed under the terms "   \
    @"of the\n"								       \
    @" * Q Public License 1.0, which can be found in the file LICENSE.QPL "    \
    @"included in\n"							       \
    @" * the packaging of this file.\n"					       \
    @" *\n"								       \
    @" * Alternatively, it may be distributed under the terms of the GNU "     \
    @"General\n"							       \
    @" * Public License, either version 2 or 3, which can be found in the "    \
    @"file\n"								       \
    @" * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the "	       \
    @"packaging of this\n"						       \
    @" * file.\n"							       \
    @" */\n"								       \
    @"\n"
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<












































































Modified generators/unicode/Makefile from [9009fb89e7] to [f73c114258].

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
	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
	rm -f ${OBJFWRT_AMIGA_LIB}
	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}; \







<







10
11
12
13
14
15
16

17
18
19
20
21
22
23
	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}; \
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
		${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
	if test -f ../../src/runtime/${OBJFWRT_AMIGA_LIB}; then \
		${LN_S} ../../src/runtime/${OBJFWRT_AMIGA_LIB} \
		    ${OBJFWRT_AMIGA_LIB}; \
	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}; \







<
<
<
<







42
43
44
45
46
47
48




49
50
51
52
53
54
55
		${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}; \

Modified generators/unicode/TableGenerator.h from [d5ba8e12b8] to [10674e4104].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
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
    OFHTTPClientDelegate>
{
	OFHTTPClient *_HTTPClient;
	OFUnichar _uppercaseTable[0x110000];
	OFUnichar _lowercaseTable[0x110000];
	OFUnichar _titlecaseTable[0x110000];
	OFUnichar _caseFoldingTable[0x110000];
	OFString *_decompositionTable[0x110000];
	OFString *_decompositionCompatTable[0x110000];
	char _uppercaseTableUsed[0x1100];
	char _lowercaseTableUsed[0x1100];
	char _titlecaseTableUsed[0x1100];
	char _caseFoldingTableUsed[0x1100];
	char _decompositionTableUsed[0x1100];
	char _decompositionCompatTableUsed[0x1100];
	size_t _uppercaseTableSize;
	size_t _lowercaseTableSize;
	size_t _titlecaseTableSize;
	size_t _caseFoldingTableSize;
	size_t _decompositionTableSize;
	size_t _decompositionCompatTableSize;
	enum {
		stateUnicodeData,
		stateCaseFolding
	} _state;
}

- (void)parseUnicodeData: (OFHTTPResponse *)response;
- (void)parseCaseFolding: (OFHTTPResponse *)response;
- (void)applyDecompositionRecursivelyForTable: (OFString *[0x110000])table;
- (void)writeFiles;
- (void)writeTablesToFile: (OFString *)path;
- (void)writeHeaderToFile: (OFString *)path;
@end







<
<




<
<




<
<








<




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
    OFHTTPClientDelegate>
{
	OFHTTPClient *_HTTPClient;
	OFUnichar _uppercaseTable[0x110000];
	OFUnichar _lowercaseTable[0x110000];
	OFUnichar _titlecaseTable[0x110000];
	OFUnichar _caseFoldingTable[0x110000];


	char _uppercaseTableUsed[0x1100];
	char _lowercaseTableUsed[0x1100];
	char _titlecaseTableUsed[0x1100];
	char _caseFoldingTableUsed[0x1100];


	size_t _uppercaseTableSize;
	size_t _lowercaseTableSize;
	size_t _titlecaseTableSize;
	size_t _caseFoldingTableSize;


	enum {
		stateUnicodeData,
		stateCaseFolding
	} _state;
}

- (void)parseUnicodeData: (OFHTTPResponse *)response;
- (void)parseCaseFolding: (OFHTTPResponse *)response;

- (void)writeFiles;
- (void)writeTablesToFile: (OFString *)path;
- (void)writeHeaderToFile: (OFString *)path;
@end

Modified generators/unicode/TableGenerator.m from [c1835e042f] to [723fa7abc3].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#include <string.h>

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

#import "OFOutOfRangeException.h"

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

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

OF_APPLICATION_DELEGATE(TableGenerator)

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

	@try {
		_HTTPClient = [[OFHTTPClient alloc] init];
		_HTTPClient.delegate = self;

		_uppercaseTableSize           = SIZE_MAX;
		_lowercaseTableSize           = SIZE_MAX;
		_titlecaseTableSize           = SIZE_MAX;
		_caseFoldingTableSize         = SIZE_MAX;
		_decompositionTableSize       = SIZE_MAX;
		_decompositionCompatTableSize = SIZE_MAX;
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (void)applicationDidFinishLaunching
{
	OFHTTPRequest *request;

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

-      (void)client: (OFHTTPClient *)client
  didPerformRequest: (OFHTTPRequest *)request
	   response: (OFHTTPResponse *)response
	  exception: (id)exception

|

















|

|
|


|
|
|






|

|

















<
<








|





|
|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54


55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
/*
 * Copyright (c) 2008-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 "OFApplication.h"
#import "OFArray.h"
#import "OFFile.h"
#import "OFHTTPClient.h"
#import "OFHTTPRequest.h"
#import "OFHTTPResponse.h"
#import "OFIRI.h"
#import "OFStdIOStream.h"
#import "OFString.h"

#import "OFOutOfRangeException.h"

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

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

OF_APPLICATION_DELEGATE(TableGenerator)

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

	@try {
		_HTTPClient = [[OFHTTPClient alloc] init];
		_HTTPClient.delegate = self;

		_uppercaseTableSize           = SIZE_MAX;
		_lowercaseTableSize           = SIZE_MAX;
		_titlecaseTableSize           = SIZE_MAX;
		_caseFoldingTableSize         = SIZE_MAX;


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

	return self;
}

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

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

-      (void)client: (OFHTTPClient *)client
  didPerformRequest: (OFHTTPRequest *)request
	   response: (OFHTTPResponse *)response
	  exception: (id)exception
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
		_uppercaseTable[codePoint] = (OFUnichar)[[components
		    objectAtIndex: 12] unsignedLongLongValueWithBase: 16];
		_lowercaseTable[codePoint] = (OFUnichar)[[components
		    objectAtIndex: 13] unsignedLongLongValueWithBase: 16];
		_titlecaseTable[codePoint] = (OFUnichar)[[components
		    objectAtIndex: 14] unsignedLongLongValueWithBase: 16];

		if ([[components objectAtIndex: 5] length] > 0) {
			OFArray *decomposed = [[components objectAtIndex: 5]
			    componentsSeparatedByString: @" "];
			bool compat = false;
			OFMutableString *string;

			if ([decomposed.firstObject hasPrefix: @"<"]) {
				decomposed = [decomposed objectsInRange:
				    OFMakeRange(1, decomposed.count - 1)];
				compat = true;
			}

			string = [OFMutableString string];

			for (OFString *character in decomposed) {
				OFUnichar unichar = (OFUnichar)[character
				    unsignedLongLongValueWithBase: 16];

				[string appendCharacters: &unichar
						  length: 1];
			}

			[string makeImmutable];

			if (!compat)
				_decompositionTable[codePoint] = [string copy];
			_decompositionCompatTable[codePoint] = [string copy];
		}

		objc_autoreleasePoolPop(pool2);
	}

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

	[OFStdOut writeLine: @" done"];

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

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








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



<
<
<




|
|







123
124
125
126
127
128
129





























130
131
132



133
134
135
136
137
138
139
140
141
142
143
144
145
		_uppercaseTable[codePoint] = (OFUnichar)[[components
		    objectAtIndex: 12] unsignedLongLongValueWithBase: 16];
		_lowercaseTable[codePoint] = (OFUnichar)[[components
		    objectAtIndex: 13] unsignedLongLongValueWithBase: 16];
		_titlecaseTable[codePoint] = (OFUnichar)[[components
		    objectAtIndex: 14] unsignedLongLongValueWithBase: 16];






























		objc_autoreleasePoolPop(pool2);
	}




	[OFStdOut writeLine: @" done"];

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

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

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
	}

	[OFStdOut writeLine: @" done"];

	[self writeFiles];
}

- (void)applyDecompositionRecursivelyForTable: (OFString *[0x110000])table
{
	bool done;

	do {
		done = true;

		for (OFUnichar i = 0; i < 0x110000; i++) {
			void *pool;
			const OFUnichar *characters;
			size_t length;
			OFMutableString *replacement;
			bool changed = false;

			if (table[i] == nil)
				continue;

			pool = objc_autoreleasePoolPush();
			characters = table[i].characters;
			length = table[i].length;
			replacement = [OFMutableString string];

			for (size_t j = 0; j < length; j++) {
				if (characters[j] > 0x10FFFF)
					@throw [OFOutOfRangeException
					    exception];

				if (table[characters[j]] == nil)
					[replacement
					    appendCharacters: &characters[j]
						      length: 1];
				else {
					[replacement
					    appendString: table[characters[j]]];
					changed = true;
				}
			}

			[replacement makeImmutable];

			if (changed) {
				[table[i] release];
				table[i] = [replacement copy];

				done = false;
			}

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

- (void)writeFiles
{
	OFURI *URI;

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

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

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

	[OFStdOut writeLine: @" done"];

	[OFApplication terminate];
}

- (void)writeTablesToFile: (OFString *)path
{
	void *pool = objc_autoreleasePoolPush();
	OFFile *file = [OFFile fileWithPath: path
				       mode: @"w"];

	[file writeString: COPYRIGHT
	    @"#include \"config.h\"\n"
	    @"\n"
	    @"#import \"OFString.h\"\n\n"
	    @"static const OFUnichar emptyPage[0x100] = { 0 };\n"
	    @"static const char *emptyDecompositionPage[0x100] = { NULL };\n"
	    @"\n"];

	/* Write uppercasePage%u */
	for (OFUnichar i = 0; i < 0x110000; i += 0x100) {
		bool isEmpty = true;

		for (OFUnichar j = i; j < i + 0x100; j++) {







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


|



|
|

|
|

















<







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
	}

	[OFStdOut writeLine: @" done"];

	[self writeFiles];
}





















































- (void)writeFiles
{
	OFIRI *IRI;

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

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

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

	[OFStdOut writeLine: @" done"];

	[OFApplication terminate];
}

- (void)writeTablesToFile: (OFString *)path
{
	void *pool = objc_autoreleasePoolPush();
	OFFile *file = [OFFile fileWithPath: path
				       mode: @"w"];

	[file writeString: COPYRIGHT
	    @"#include \"config.h\"\n"
	    @"\n"
	    @"#import \"OFString.h\"\n\n"
	    @"static const OFUnichar emptyPage[0x100] = { 0 };\n"

	    @"\n"];

	/* Write uppercasePage%u */
	for (OFUnichar i = 0; i < 0x110000; i += 0x100) {
		bool isEmpty = true;

		for (OFUnichar j = i; j < i + 0x100; j++) {
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

			[file writeString: @"};\n\n"];

			objc_autoreleasePoolPop(pool2);
		}
	}

	/* Write decompositionPage%u */
	for (OFUnichar i = 0; i < 0x110000; i += 0x100) {
		bool isEmpty = true;

		for (OFUnichar j = i; j < i + 0x100; j++) {
			if (_decompositionTable[j] != nil) {
				isEmpty = false;
				_decompositionTableSize = i >> 8;
				_decompositionTableUsed[
				    _decompositionTableSize] = 1;
				break;
			}
		}

		if (!isEmpty) {
			void *pool2 = objc_autoreleasePoolPush();

			[file writeFormat: @"static const char *const "
					   @"decompositionPage%u[0x100] = {\n",
					   i >> 8];

			for (OFUnichar j = i; j < i + 0x100; j++) {
				if ((j - i) % 2 == 0)
					[file writeString: @"\t"];
				else
					[file writeString: @" "];

				if (_decompositionTable[j] != nil) {
					const char *UTF8String =
					    _decompositionTable[j].UTF8String;
					size_t length = _decompositionTable[j]
					    .UTF8StringLength;

					[file writeString: @"\""];

					for (size_t k = 0; k < length; k++)
						[file writeFormat:
						    @"\\x%02X",
						    (uint8_t)UTF8String[k]];

					[file writeString: @"\","];
				} else
					[file writeString: @"NULL,"];

				if ((j - i) % 2 == 1)
					[file writeString: @"\n"];
			}

			[file writeString: @"};\n\n"];

			objc_autoreleasePoolPop(pool2);
		}
	}

	/* Write decompCompatPage%u if it does NOT match decompositionPage%u */
	for (OFUnichar i = 0; i < 0x110000; i += 0x100) {
		bool isEmpty = true;

		for (OFUnichar j = i; j < i + 0x100; j++) {
			if (_decompositionCompatTable[j] != 0) {
				/*
				 * We bulk-compare pointers via memcmp here.
				 * This is safe, as we always set the same
				 * pointer in both tables if both are the same.
				 */
				isEmpty = !memcmp(_decompositionTable + i,
				    _decompositionCompatTable + i,
				    256 * sizeof(const char *));
				_decompositionCompatTableSize = i >> 8;
				_decompositionCompatTableUsed[
				    _decompositionCompatTableSize] =
				    (isEmpty ? 2 : 1);

				break;
			}
		}

		if (!isEmpty) {
			void *pool2 = objc_autoreleasePoolPush();

			[file writeFormat: @"static const char *const "
					   @"decompCompatPage%u[0x100] = {\n",
					   i >> 8];

			for (OFUnichar j = i; j < i + 0x100; j++) {
				if ((j - i) % 2 == 0)
					[file writeString: @"\t"];
				else
					[file writeString: @" "];

				if (_decompositionCompatTable[j] != nil) {
					const char *UTF8String =
					    _decompositionCompatTable[j]
					    .UTF8String;
					size_t length =
					    _decompositionCompatTable[j]
					    .UTF8StringLength;

					[file writeString: @"\""];

					for (size_t k = 0; k < length; k++)
						[file writeFormat:
						    @"\\x%02X",
						    (uint8_t)UTF8String[k]];

					[file writeString: @"\","];
				} else
					[file writeString: @"NULL,"];

				if ((j - i) % 2 == 1)
					[file writeString: @"\n"];
			}

			[file writeString: @"};\n\n"];

			objc_autoreleasePoolPop(pool2);
		}
	}

	/*
	 * Those are currently set to the last index.
	 * But from now on, we need the size.
	 */
	_uppercaseTableSize++;
	_lowercaseTableSize++;
	_titlecaseTableSize++;
	_caseFoldingTableSize++;
	_decompositionTableSize++;
	_decompositionCompatTableSize++;

	/* Write OFUnicodeUppercaseTable */
	[file writeFormat: @"const OFUnichar *const "
			   @"OFUnicodeUppercaseTable[0x%X] = {\n\t",
			   _uppercaseTableSize];

	for (OFUnichar i = 0; i < _uppercaseTableSize; i++) {







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







<
<







366
367
368
369
370
371
372




























































373



























































374
375
376
377
378
379
380


381
382
383
384
385
386
387

			[file writeString: @"};\n\n"];

			objc_autoreleasePoolPop(pool2);
		}
	}





























































	/*



























































	 * Those are currently set to the last index.
	 * But from now on, we need the size.
	 */
	_uppercaseTableSize++;
	_lowercaseTableSize++;
	_titlecaseTableSize++;
	_caseFoldingTableSize++;



	/* Write OFUnicodeUppercaseTable */
	[file writeFormat: @"const OFUnichar *const "
			   @"OFUnicodeUppercaseTable[0x%X] = {\n\t",
			   _uppercaseTableSize];

	for (OFUnichar i = 0; i < _uppercaseTableSize; i++) {
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
			else
				[file writeString: @", "];
		}
	}

	[file writeString: @"\n};\n\n"];

	/* Write OFUnicodeDecompositionTable */
	[file writeFormat: @"const char *const "
			   @"*OFUnicodeDecompositionTable[0x%X] = {\n\t",
			   _decompositionTableSize];

	for (OFUnichar i = 0; i < _decompositionTableSize; i++) {
		if (_decompositionTableUsed[i])
			[file writeFormat: @"decompositionPage%u", i];
		else
			[file writeString: @"emptyDecompositionPage"];

		if (i + 1 < _decompositionTableSize) {
			if ((i + 1) % 3 == 0)
				[file writeString: @",\n\t"];
			else
				[file writeString: @", "];
		}
	}

	[file writeString: @"\n};\n\n"];

	/* Write OFUnicodeDecompositionCompatTable */
	[file writeFormat: @"const char *const "
			   @"*OFUnicodeDecompositionCompatTable[0x%X] = {"
			   @"\n\t",
			   _decompositionCompatTableSize];

	for (OFUnichar i = 0; i < _decompositionCompatTableSize; i++) {
		if (_decompositionCompatTableUsed[i] == 1)
			[file writeFormat: @"decompCompatPage%u", i];
		else if (_decompositionCompatTableUsed[i] == 2)
			[file writeFormat: @"decompositionPage%u", i];
		else
			[file writeString: @"emptyDecompositionPage"];

		if (i + 1 < _decompositionCompatTableSize) {
			if ((i + 1) % 3 == 0)
				[file writeString: @",\n\t"];
			else
				[file writeString: @", "];
		}
	}

	[file writeString: @"\n};\n"];

	objc_autoreleasePoolPop(pool);
}

- (void)writeHeaderToFile: (OFString *)path
{
	void *pool = objc_autoreleasePoolPush();
	OFFile *file = [OFFile fileWithPath: path
				       mode: @"w"];

	[file writeString: COPYRIGHT
	    @"#import \"OFString.h\"\n\n"];

	[file writeFormat:
	    @"#define OFUnicodeUppercaseTableSize 0x%X\n"
	    @"#define OFUnicodeLowercaseTableSize 0x%X\n"
	    @"#define OFUnicodeTitlecaseTableSize 0x%X\n"
	    @"#define OFUnicodeCaseFoldingTableSize 0x%X\n"
	    @"#define OFUnicodeDecompositionTableSize 0x%X\n"
	    @"#define OFUnicodeDecompositionCompatTableSize 0x%X\n\n",
	    _uppercaseTableSize, _lowercaseTableSize, _titlecaseTableSize,
	    _caseFoldingTableSize, _decompositionTableSize,
	    _decompositionCompatTableSize];

	[file writeString:
	    @"#ifdef __cplusplus\n"
	    @"extern \"C\" {\n"
	    @"#endif\n"
	    @"extern const OFUnichar *const _Nonnull\n"
	    @"    OFUnicodeUppercaseTable[OFUnicodeUppercaseTableSize];\n"
	    @"extern const OFUnichar *const _Nonnull\n"
	    @"    OFUnicodeLowercaseTable[OFUnicodeLowercaseTableSize];\n"
	    @"extern const OFUnichar *const _Nonnull\n"
	    @"    OFUnicodeTitlecaseTable[OFUnicodeTitlecaseTableSize];\n"
	    @"extern const OFUnichar *const _Nonnull\n"
	    @"    OFUnicodeCaseFoldingTable[OFUnicodeCaseFoldingTableSize];\n"
	    @"extern const char *const _Nullable *const _Nonnull\n"
	    @"    OFUnicodeDecompositionTable["
	    @"OFUnicodeDecompositionTableSize];\n"
	    @"extern const char *const _Nullable *const _Nonnull\n"
	    @"    OFUnicodeDecompositionCompatTable["
	    @"OFUnicodeDecompositionCompatTableSize];\n"
	    @"#ifdef __cplusplus\n"
	    @"}\n"
	    @"#endif\n"];

	objc_autoreleasePoolPop(pool);
}
@end







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
















|
<
<

|
<













<
<
<
<
<
<







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
			else
				[file writeString: @", "];
		}
	}

	[file writeString: @"\n};\n\n"];














































	objc_autoreleasePoolPop(pool);
}

- (void)writeHeaderToFile: (OFString *)path
{
	void *pool = objc_autoreleasePoolPush();
	OFFile *file = [OFFile fileWithPath: path
				       mode: @"w"];

	[file writeString: COPYRIGHT
	    @"#import \"OFString.h\"\n\n"];

	[file writeFormat:
	    @"#define OFUnicodeUppercaseTableSize 0x%X\n"
	    @"#define OFUnicodeLowercaseTableSize 0x%X\n"
	    @"#define OFUnicodeTitlecaseTableSize 0x%X\n"
	    @"#define OFUnicodeCaseFoldingTableSize 0x%X\n\n",


	    _uppercaseTableSize, _lowercaseTableSize, _titlecaseTableSize,
	    _caseFoldingTableSize];


	[file writeString:
	    @"#ifdef __cplusplus\n"
	    @"extern \"C\" {\n"
	    @"#endif\n"
	    @"extern const OFUnichar *const _Nonnull\n"
	    @"    OFUnicodeUppercaseTable[OFUnicodeUppercaseTableSize];\n"
	    @"extern const OFUnichar *const _Nonnull\n"
	    @"    OFUnicodeLowercaseTable[OFUnicodeLowercaseTableSize];\n"
	    @"extern const OFUnichar *const _Nonnull\n"
	    @"    OFUnicodeTitlecaseTable[OFUnicodeTitlecaseTableSize];\n"
	    @"extern const OFUnichar *const _Nonnull\n"
	    @"    OFUnicodeCaseFoldingTable[OFUnicodeCaseFoldingTableSize];\n"






	    @"#ifdef __cplusplus\n"
	    @"}\n"
	    @"#endif\n"];

	objc_autoreleasePoolPop(pool);
}
@end

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#import "OFString.h"

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

|

















|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/*
 * Copyright (c) 2008-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 "OFString.h"

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

Added misc/keys.asc version [1717b09117].









































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
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
-----BEGIN PGP PUBLIC KEY BLOCK-----

mDMEWtyz7hYJKwYBBAHaRw8BAQdAsw2r74WiB54Nr73sY2sxBLu0RUges2iPeBor
1Wc6Cre0O0pvbmF0aGFuIFNjaGxlaWZlciAoQ29tbWl0IFNpZ25pbmcgS2V5IDIw
MTgpIDxqc0BoZWFwLnpvbmU+iJkEExYKAEECGwMHCwoNDAgLBwYVCgkICwMFFgMC
AQACHgECF4AWIQTGxY7C74kJHg4TzVjYOna/43Y0XgUCXESzpAUJAWlRNgAKCRDY
Ona/43Y0XhA1AP4nIiBUL2nMtkDJSbSb0/kbyIoTNhRXtlI4crYIqfs07gD+NMdH
HzMnGtHkpaX7GAqVTeTiThZUnTGNMwnV9aerQQe0OkpvbmF0aGFuIFNjaGxlaWZl
ciAoT2JqRlcgU2lnbmluZyBLZXkgMjAxOCkgPGpzQGhlYXAuem9uZT6ImQQTFgoA
QQIbAwcLCg0MCAsHBhUKCQgLAwUWAwIBAAIeAQIXgBYhBMbFjsLviQkeDhPNWNg6
dr/jdjReBQJcRLOoBQkBaVE2AAoJENg6dr/jdjReDVoBANvkIYUTLemog3UhjZYh
Zdvq9Axd63L2lnpzm+For3tNAP9GmJwbq/oi8E0mAwesbvQYY/R4NOOKIdV7rkVj
JzoeCJgzBFxA+ccWCSsGAQQB2kcPAQEHQIe0NK4nnagyINx6Z2DJt4lUzv7a7e6x
PLifEvo1iQVptDpKb25hdGhhbiBTY2hsZWlmZXIgKE9iakZXIFNpZ25pbmcgS2V5
IDIwMTkpIDxqc0BoZWFwLnpvbmU+iJkEExYKAEEWIQQtKx7sQXauZ6pvl2B50hGJ
otRwjQUCXED55wIbAwUJAeEzgAcLCg0MCAsHBhUKCQgLAwUWAwIBAAIeAQIXgAAK
CRB50hGJotRwjeuIAP9wQ8r+13S0ZHPmOkeVQNqpVdvszisfszQKNRrkKrS7fgEA
AF4eI4IXb13x5hHvzYn2DMMe2ugx6LoCdzYcVlvFFQ60O0pvbmF0aGFuIFNjaGxl
aWZlciAoQ29tbWl0IFNpZ25pbmcgS2V5IDIwMTkpIDxqc0BoZWFwLnpvbmU+iJkE
ExYKAEEWIQQtKx7sQXauZ6pvl2B50hGJotRwjQUCXED5xwIbAwUJAeEzgAcLCg0M
CAsHBhUKCQgLAwUWAwIBAAIeAQIXgAAKCRB50hGJotRwjXTdAP4oYHIg5+LBhfO+
SNSQl008KH35KmyO4xtZPKfcbWjXcgD/dWVqZDjUYkCs/0oprdJDZPRBIB5QQhjc
1un38+eCiAeYMwReJFsBFgkrBgEEAdpHDwEBB0CjTf7buaAeNxgLpbv9/j4UgcjJ
Z97STkAaM7Xac+Dg1rQ3Sm9uYXRoYW4gU2NobGVpZmVyIChPYmpGVyBTaWduaW5n
IEtleSAyMDIwKSA8anNAbmlsLmltPoiZBBMWCgBBFiEEMOaUj6yAQrWMtKlu4rzO
azXhr4sFAl4kWykCGwMFCQHhM4AHCwoNDAgLBwYVCgkICwMFFgMCAQACHgECF4AA
CgkQ4rzOazXhr4tQAgD+P45Nx/YGk2Q/JzBz+cbsdtcha7IehgXulltd3xLjdwsB
AMoefVWwHOJa7q10ZRxDN48kDGD+kiqvSdIvKRGuLmMAiQIzBBMBCgAdFiEEbR7C
JpvAtUWci6kgz9q0H4KSzu4FAl6KMHcACgkQz9q0H4KSzu7HLBAAo2it0ci2HuJT
1+x1n74dBI5nwKak15OoABW37vxt10gMdm1wo9hq0cJorXdQmE07pMWpMmz883Yg
ayqTXyEJJydVqq3rgR1zcEKOGpiJT6azRfGxcvsNh8bMto9dC6cVVmknydyvNTg7
3TpofPmRlH8W8gt8w55EiO3Lk4RJODzGhCOrDxbR1o9rF39fUHj+g3NB7grK/TTt
dZvomOS+mcM+pANYivOTmMc5mn0mEVua3F6wRvUck8ij2JFTvJ5GV3xie6JIDa2h
l/hM2BLx2XRrwjnD+kig/CjpoFEP8bzc+epHb6ODAt2SQ5i4Zx30TFWiVeeljX1Q
zFq5pfJr3nbHQNhkzsu3uWXfqUu1M6mBadzYmLYLDgVFLFKdwhBgbvInr39UAtwE
Yl70NoqgVswPzWSkAyrLWs0+2XUXZlyhFxNaOqheWE7VQv/DPYDBPXrim3f5Alv2
PtQJ2BXDvl1PyDg6Ckg6Pe6XoVKPJwMYsiWZOrsnRRJzeQWa1zFsVWX+CYINPiEY
v4Ls2OFGZj67tzNU8Wf2EFbNmm/V82sXrPeu0iqcJ99aaxZw+tk+h5WS0BiXceZ9
J6dRKo2qHJJAq0FJnAt+6NRam1KYAknd9y6g5S2bRqiI1wJminmksbSLQ5wmeunl
EynylSIJx+UbXBYVbvmpLWZFFRUKBM60OEpvbmF0aGFuIFNjaGxlaWZlciAoQ29t
bWl0IFNpZ25pbmcgS2V5IDIwMjApIDxqc0BuaWwuaW0+iJkEExYKAEEWIQQw5pSP
rIBCtYy0qW7ivM5rNeGviwUCXiRbAQIbAwUJAeEzgAcLCg0MCAsHBhUKCQgLAwUW
AwIBAAIeAQIXgAAKCRDivM5rNeGvi4HuAPsEi38R7E8716m2ua2KvFB3CClSCsVT
tZjbIQBEHzQ/iAD/UEZtjaNUW/Mf8vFExbnqFes0dwF0p6PzQ0GLix12JQKJAjME
EwEKAB0WIQRtHsImm8C1RZyLqSDP2rQfgpLO7gUCXoowgQAKCRDP2rQfgpLO7jtA
D/403WskqoPnw+woWaeCPZcTU1LQ/o5baUUxbQDWTAUNav3hzDxBDQ1yPacZhwBu
ea6SNnrEZwc5wd5TPozh9sXday3vqDe6R9/AT+MokxJT3EWptTXmcawRSyDdFNZr
V8KJqfDjRNkv9Iqxsjjp9fD5Vw8zVC/KIr0JOq2oxzjU+Wukk94NhSOU2LDRaQLV
8vMpXZRpVJh30+7rq46sTzhZqB5AsTdBykFOsTl9LRmRJXnLjdK/4U7uhoj5ntfR
QzPUG3mmbHf5RlGoQIFq2Byop0MiGVWjHI93C5OU7fyjfnARnENOqCgUxs+yXauY
J+wngqdJroGEo/5kgbJxpTksuK9zQ3DDtE1p5y48qct0gvw3hYz1UGvpEQ2/Prcy
1q0Nc4hzQ2zrG9jO5971KW2alUT5lrILos17ZJlN5pI8NHhat7T9RX82ziB1fQKG
OzbSjxT8gXasy9gbMh8w9zm1prZ1+VRQT8JGLYPHM6mZID20F1q5cRLT41UyTjSe
zzStci/zo/dQKFKaTX9KesTSwVS9Zlo7yldUgH+lWyaSjF9VCrjyNI3YbEJ+/Fqt
rwxAp8kzFviOd7R5F4zAJBRwgfQNI46v9F3X9KpaTeuuJhm4KvyqPRE/0G0ond8G
yJYePoL3jMhfl50163cO69TGXyJmvKwATEa1xRU8n9lE9bg4BF4kWwESCisGAQQB
l1UBBQEBB0Cc6UB0PD0kppdYyeJV3uXSuXk7stS6si393JPKFX2wMgMBCAeIfgQY
FgoAJhYhBDDmlI+sgEK1jLSpbuK8zms14a+LBQJeJFsBAhsMBQkB4TOAAAoJEOK8
zms14a+L7UoBAJkNXZsY3zHeiSQ23YeaABQUTtpjWb0o6xljq3PXR/hEAP44Rvf3
hTkPPDuMCJelOxzkvr83upYCIyIpP5HpzqFWBpkCDQReih1/ARAAuXxV9zzoO2UY
YlXdNlNSxu9iJKH/RySUzIPtCWVxUfsI1NOo2ByhxxGWpATRye61Lm6cAU+tvEXj
saKpTi4i9WSy6m6xuLLqQrpDrbVOlazzM1MRQcqGK2wFPtNKV9qz+oOdPXK9a2Rl
gI2iwQh6AjCjq8oa3T1MtDF4D3uGBE+Fn9g+gryAf/TZ8gKWyYd8UZwtrlFLC7nq
8gSj2hFiRYTAPGy8GhcdyKvD0cP2xiFlpJmzCn5B+i9a5i3EJDcbfcc0BSyqxkz2
BY8bymw4kTt5e8Bmf4KdzK5OE4w3PFPiMq+Z3LVohQCI2CRh1wGw6lzntU5nqJ0c
eD2YV9C8dHwVEN1Vu2M5mXkoe9q4iLWETppxchrQWVAWZWCOeElNxdOrW/uhxpdX
RmzTMuCIHolB4VhszS+Wr3Uj98DWa9n/cPZpvRdVdXmy95G9ocp+uBozQEjdmLOm
rqPUUbE/WLUO/tRFqp6w6QVfh81G5omLo5VWlxCODK8OjOR4/rfCH28I75bjrm9H
pIYtSasVG1/XSV+ilv3PCwadftz8BR5iE0JJtk8NtI1jOvPrIe5d9hJ9109xk/r9
one51VLFFQDsNJexCswjD25xgpqnhZBd0yOtcE9+6hiENLZ0DFrKZSJjNC7xY/ts
K9usWwm3CBx2VFi+GpjL04Apo9ooPA0AEQEAAbQeSm9uYXRoYW4gU2NobGVpZmVy
IDxqc0BuaWwuaW0+iQJbBBMBCgBFAhsDAh4BAheACAsJCg0MCAsHBhUKCQgLAwUW
AwIBAAIZARYhBG0ewiabwLVFnIupIM/atB+Cks7uBQJj6WbtBQkJIbBuAAoJEM/a
tB+Cks7u1qUP+gLBceY67YURSNLLCO+L537Xukf2eYlzJzUvBI1nYv8C94dQcmSa
sBcAsg2ELfKE6GD1/7VwHQHwclpa3kSX55V6+Ep3VUSR7+2fqz4Ahr10FeOpjS5C
Ir51C44mAjeTkkmPIqhOWSoZyg2RxUZOAUZyFqpLDPFGrRTGmuEFnP1tXOAn3TR2
xllK9iAbB9ZcJ+MHEz+rVW5yj3XY8/QW1kcsWIA6qV7eHPP4Y8tEIoefvsU5g188
uHIhxWhB0Xd52VMxd32yiKRgPp9z+6e4PQ+XULv5oGiqR17XKMtMIfAe6kiDYXWT
HpqOHnOekVPuqTsjAFttgKeCEzbyit6HIFlqoXjoj23eTFQEi2qiSLCRDm2uGZJI
hAL5YeHPaNa82dg6YNCGD8FFSwP+hhXMaQ7zB2jB8smX9A9C+nHCKCFF4ba1RRNq
sFRziE2YuY+KX6bQKz6AZ7OxB16YAx75e4J/H/Si8bqm+1EKc6Xpg7uVjYYNH+dr
j4qvNsTf4tLr3FAm5tSRCdZkSlilS+565J4PInBVjcLnlRAxh1X1RJGVuFuueVdM
6joGmsPDnwdv8NOvy+4LvBHWkPLm3FVZE9fyDem+0SDooTpvFEuSRfna8agJB5kH
zA532hu1dEX/XJMCCJT4RBYy7KOVXqcjrLn/TqRiBZKPK4QbmC/JjdKJiQEiBBAB
CAAMBQJj6WgVBQMAEnUAAAoJEJcQuJvKV618c0IIAKLZVwWsgQWBjtjaIsXKUhoo
5HBwNpsNCnWAyUj0ayspkvM+hh5fa70s4Mj4oRdCd44X1iDHQw2bV6PVA+TvqkY2
NV7iL30Vqpyt50qreUz9qCdEittaFIkRNk2qkQB89cKTrrLDu2k80NZdV4sAAJKu
XFUOEecZVv5D3gYSKDQJ0lTUzSyS4cC5wdSpeEFRTVXpOQOI32mRM9BxmjtDSBct
fnHSWYoE+IoC+OPqDvbbP4TRz3UYjAz5lbLSL5BnlHxZDG2NryH9tUn+/wnJd41m
weKZidDO/AUQ9eKKaIsgzCXAjrLjKcgBBANn1yXl+YAr7J8GFdiGkVznYhGjmAW0
IkpvbmF0aGFuIFNjaGxlaWZlciA8anNATmV0QlNELm9yZz6JAlgEEwEKAEICGwMI
CwkKDQwICwcGFQoJCAsDBRYDAgEAAh4BAheAFiEEbR7CJpvAtUWci6kgz9q0H4KS
zu4FAmPpZvIFCQkhsG4ACgkQz9q0H4KSzu4/nRAAk5+6zavoleNtZ0/l9xs0lwwq
sENTfdWqp19YvkiQTWz0gDvRoxKbXHI4HK25th0rBu77ryQYjKrRjXhEZrNq2k6f
hTBwJ1sbsDceksaHRlUlVgn112gf6B/iKG3JpLxuFxuMS4ndN9z7H67t2RWDY/+M
qSgaNFWXQtfmtC3tfV8e5etZScVO8w+0Wed6MjGjA76crgVWXm2hGCokEk7+0uNd
VmFC+cPEBMixgAHqZvM+Gu3pZvHgV50Ybczalx/6KV2W37MsaX6iRUCCpnnoAAxN
pWo2Z2LIBVaoO9nuzO8pgF8dRdxwq3Px/RpseHtEUY4v1/aylB4z1joI7sWPqXOR
3QlRmCd2O36kCiLIvm9OQ5tmjmW9T+t/gcCzq5pHDNIx8D50urqnUH+WU/WaT5fp
uM6VifBpSZslTuRavc6kxa7kuGCrsBtVOzlMCxSVAqSgMMm4vVxJm20pYIItHHTZ
TXEehnLEst/EdEAmLmHO2Qch/qUh2i0w5+4pwjY1pIOVP8Si3xbxtoN6PIM/UBEP
fBQGB4NzljQwISdUUSGiWn7pcun350IsCjnC2c+tJQ/lHjhrJjZ+aMAi7OSV6g9P
pjFrz+z9UmTP0QUeBSNGBqAWgvC4okGgFr4cf9H01FbZPNkWIfZYPZ1Nv3apxNOx
lpzSHcURnFhXPJDlqNC0IkpvbmF0aGFuIFNjaGxlaWZlciA8anNAcGtnc3JjLm9y
Zz6JAlgEEwEKAEICGwMICwkKDQwICwcGFQoJCAsDBRYDAgEAAh4BAheAFiEEbR7C
JpvAtUWci6kgz9q0H4KSzu4FAmPpZvcFCQkhsG4ACgkQz9q0H4KSzu4TrxAAnWBr
gJnU96KbYRS7KkpUzeLeaLrHK5LIhaJ7rVxVrOo+x5Ey2NjGJKoTxC9UAfITCfO9
9vsycp3Gb9fJnowieuQ1y1MFCrYLPPLOfNxh4Jc9GZK64DlexrsXvDhx84wgN+el
rnjuatm9LUJWe5czWKiAnoki/u+SGFVxwOUtND205I4go/8FtY8rZ1P3VEGiXeZq
hjNOodDoGEGZJwQIycN5YCrweYPwM+p80ZbzkWGB+Ov3lOO+omMf7NQ3LFtueV0J
Nq7SjmNESYLm1Gg2NFHZp4D12sSUfHTvNVJBr1qCJggQs2mefRB/aKcS4i9Ajmfk
i7TkEwutDMX6rOCZRppYpS8N6aYoiAOZHQmffk8bdi0RBGVSxR+04IwpYObUbDIZ
US2exkiaDB0tFeguIlgHU/V+3GWEUDF4AhQLbSYkEwUc65FstULrDCRfegFoUBsY
9D+qPYnsNOlTRlalR8hZaQlwZLAuZx0kn+YGxs+9z2UhgMExRtCM/3FRpDuiFJGs
QML2DUArYZeh7JyJy0m9PIt59wg5wnHUyCLop8g1gn6Wh22/R/Le6CEusJsO2qiM
oE6PSB89g3nhsvUadRpYOP9eZS0aoRgNPLp+qigthgEV9fvSADHtAvsaLYpQ+wjr
O+Ih57Y2MrU8mPehwqGz17Ur58VcI65qXTkZpni5Ag0EXoodfwEQAPc4JUVqZGxS
KtipZKGewKuNyqASMq8gNwL7ToSni5cTuQLa9YU+5Zo/BX3OEJkXp+MNN3Y1wFxV
cPBZsYpBAx3apWhi0Fki+zdPjTmRE7QcFE+UE17OnnFReb93G2ErSiY+BzsfbW/3
dMjLfLhrVjJktLA9pGMoR483jI6rIVEBa6TikoMo8b790Ulo0xicl6ehFhQVUGN4
CfovBjCZ9CIX6dmRGaB/FMyOXgXWsx5+UilTgJhRHbJnggw6U1H8lk/WhJzCyLyY
Tg+YkHx3WwAF37pR6g1XACMQEdumCLxW21ELC5D4aX0QejM8oIDf/xw5mHcgB0xg
07FmRbyiZheg+CSPgwHWW/K6urw/G04SbYxnk1/kPA66x6Fss3BxTuJOYmEZqklV
Np2KfJdEiBECftRRWIbZu2zFOMGK1olPIOgsKdJvaATkgeYSxjCu9+o4vY1yGXtz
BEwBfIUkU2B33QzWLq+I61WeVbqRC6k0SYBKiQK/uQJSVYuEtNJ8pttYxdYkyY+r
s0yCZHlTlJcYKhAdMi1Gbh2L6WbzsHIHfmdraWqcv7EEuVacjrgerdk3ezOQspC5
Gfa6pLEmOoF/ctwg/uoGCyhnWBmHiuLdN7F4+z6BHBoqHU1i3z2oUJ3tHDoVnEmh
jYNOgIs7UgKxXiuczMJT4gpNM35ym32hABEBAAGJAjwEGAEKACYCGwwWIQRtHsIm
m8C1RZyLqSDP2rQfgpLO7gUCY+lnIwUJCSGwpAAKCRDP2rQfgpLO7oIlD/4oLDMH
qTzdDIXjM9x5U4ENBeGwUKHEkKeRduXuj0pZTnWTHmdXD3RPbG1EfGJU3PVBudZU
iEREibNaEYM5VFuDwMw51qw7Ox8j4r+RtP+8AI0zpRdababPP1/A4ap+xwReTWVM
/CFF3VekqeElgxSjM6luFPNDdwyBNavOLtbrWhmyclw3DLB03ZtS0sPvu0hXTnp4
nbuWdsPOxGIomb9UF0IplMPm5ChjkZaypKY75P1k5Il+AZFWEi5YB6y8yl1gmOxY
3pnKCJWcoGsaEoxREqHH/tZAeI299u8aE8Gjl+ZxGunuPDMUd8OSlE8MI3osnWU4
7rbVueWqJ4CG3OcYJP8Vj1Ygy68R5xBL5ku3ddv5oI2ZIDkqTBFKJQnhWMUX6Trz
e7US0jSdVFv4fYf3aHDJ0afc9RsKebPgbfN3FWak03zInVqdXRrraa410qz8fKBI
1CKalErJN7/dpXu3vfJJ2TgYcgAN9N0lY+YFQ834qpDk6KOTYzvIMJASVIJ1gjvl
iE94hE6FYuHU9DlwYL3/qbOOb6lLIFHxaeQ95ZZR+raPyi1FGVGXV8oZI5f2Uzxo
LYyioTRjgC0cr9aIK56ZQ5I/npwuEYSL/8oIWdRrYGQT0FFQQAnhhkd61DuPt3GA
fhsY1fGkPo/YC3yulOJt98FIMg/lRlYfOrxIbLkCDQReiiM/ARAAwIzaby43las5
ApAWVw4MxCIpdY9S0tKUBgF4koKKkgUQ20KzI395LctZ6TwRSaBp9df/Wi9JtXe3
bkt46ASjq8CCMggVptq80KyhnVMYDJD8mH+gFjUdlxTgILg1tnYwt01oBIMh8T1c
EUQ2kcWkDbIRnrrSkVxh+ntu8aqZaF9E9iScPbNO8V5qIGCTfeFti1IUfClQ10Cs
dANPxVngzttHs7eg+ddwZdiwxb7vxKy1/juqWTNFcHYd4XQ8MIuedXliHpvI5quf
MbFvOmX6xxxoXTL/efGoA/zCM6/BcM2ul1o/prJTauRuVKawE3mcMpTrubN+usf6
QEUohxsxCvxVqGcJVAU5286Hv0Kc2jzqcWqEfiyjCJI0vwCzFk3sRbuawlDuC535
paR23QC/ClSCghMzfRRnN4OpJQjzgc6yOZ3ydqmF5UeqGrgZhrW+O92jBb1XqGFV
zTOYHvLNJCQ0Cj53fiYpju4Pdf2BWvDo1oSoKbrvSd3DUyXlgN2Ar6t3X2uz7HhL
2496v3BoIOqzzcdvpCaDZjDdrw8SHpp45u9qrzMPKEIdqy4u5KjsKjuCZKczy4pc
u44+JjDzNJRik0Ppf2AUJLBCnik6prZIttbCfGsvid7SR5sZZgjbGk/fuQCF/tQt
aksvsIqb598/sTzNVBGkp6qWttTkPs8AEQEAAYkCPAQYAQoAJgIbIBYhBG0ewiab
wLVFnIupIM/atB+Cks7uBQJj6WcnBQkJIarkAAoJEM/atB+Cks7uei8QAIa+BrMi
fmLTSLe09CnGvacepKNao6UqSHwbmf6Tonv9rOU2EquKyCW/0YK53WGO6fnPE7FV
8JYDWxecBvtLjj+hloEHJ/wliYwd4W3FOuGnb/E9mzQgyKdWcSBIxreZLdD7xZ5B
iv3VLeKyx+xnJ99dC2+MBuL6CBk+gmzwri7/hkYG9GQW9TJEe7qi8D87iTN1YkXl
cJXdDcqapEZxv8+nAa5E4gTmLlXnKYNidC6+9gtnGpCRZtSpLwX0pMVY27w9sthU
Acnx5N3AwS7rCodqnU3ANa5a00wbWOmZ90qbofRX9RC3qkfoisr62bRELY7KFt7M
VTV0YBTCPHFeP+bubyOOyUe1OJsCvWJfIhJm87qjS37WXxYDUU+KHGN4MX9LDvTS
xy+h30Ba0XFfU1fgNtIvVR+MrrIGACq5VU2uSyBQLmIkgcusUComEx77mETE92Mw
ROJfy1O5VGsNDr61xIu72MjKAlukwgwX/qQ7i8Flyf8N++J7fETf/4DHXxNS9imV
JTVxHfvIWpclRfdUCZB6R1Ihv+n1T+yx/FroTxQ5wuilV7+0r2DhrW6Q0YISoWv5
L1sfohVZCXF7EQgteax0/86WSboerrWQmfGk0k4SjKhBJK1O8Jhh2tk8OmlUz6Fs
7MhFJ5NGASlFL7p0W5iB3qWYwn52sEBaI8VpmDMEYBW6BBYJKwYBBAHaRw8BAQdA
WWTgOvzlX/x5OiYhMLK72aKOMvr0g6KIaynmN2YMp5O0M0pvbmF0aGFuIFNjaGxl
aWZlciAoQ29tbWl0IFNpZ25pbmcgS2V5KSA8anNAbmlsLmltPoiaBBMWCgBCAhsD
CAsJCg0MCAsHBhUKCQgLAwUWAwIBAAIeAQIXgBYhBAzGrFQcetxzPGQWEGNnA1dz
lTEvBQJj6WYYBQkFtN+UAAoJEGNnA1dzlTEvXKQBAPQ4mbtEmbuMbfpeV3pMP8bO
1OhOB4/Thx4tUrrV7JcjAQCveLdvBrB+cSh+DA7edl6/XWfafCT0qrzRFhaoEZhx
Dbg4BGAVugQSCisGAQQBl1UBBQEBB0A2sxWorhv9BEE+urAmX5GBUfcCdta9Un6E
t5wEG5jLVAMBCAeIfgQYFgoAJgIbDBYhBAzGrFQcetxzPGQWEGNnA1dzlTEvBQJj
6WYtBQkFtN+pAAoJEGNnA1dzlTEvi+8BANiiPjamWJ3iSeMEaaYPoZXNZ7NAHlK0
UUgQvB/osfQWAP9NKXMO7P5R/K+D2nRE/Ndmk0lqBykzumouPVuR21pYB5gzBGWW
/sEWCSsGAQQB2kcPAQEHQAujl3ehBqKz3PFMW+rl8/d/1KS7Skx00xYU6xsLout+
tDhKb25hdGhhbiBTY2hsZWlmZXIgKENvbW1pdCBTaWduaW5nIEtleSAyMDI0KSA8
anNAbmlsLmltPoiaBBMWCgBCFiEEYy4qTb/j80NaLyG/lClu8uyb5oMFAmWW/sEC
GwMFCQHhM4AICwkKDQwICwcGFQoJCAsDBRYDAgEAAh4FAheAAAoJEJQpbvLsm+aD
g10BAP5MpkFbauicEGNTUJnmfbWZsGmmOTov7nG3ylVPp6UpAP4jIbm0Nz5L0+1B
vA35PeZfJ8z2dIcuKPKkCgxbv55NAIkCNwQTAQoAIRYhBG0ewiabwLVFnIupIM/a
tB+Cks7uBQJllwC0AwUBeAAKCRDP2rQfgpLO7sktEACdIKHR7vTHKgokw/6j2zwd
Na3sBt0jC7tsqA7xbfobwMR3yoVnD49T4zHlW5MwKaQBsTkwI9pS4qbaPsX7VoXV
5I8UpWPbXeDnofO9B+sO55ybVrGf1Fb2PmykZ85dgEe168hL0c5UX+9zCXjfFTHa
GAxRmTrYKP0h+jYZJns1QK3KZEWh0pkqJz5oOLELqeZS2GMGn1PQjmbzz72/korZ
sUswS5sDBbMVeusCWuNeY6FJZ6ziv97geu+uWe7ppwv25rebEKJgsuaIqDuAT2Gg
3NgrubfXFVLlDxjuYdaO+ieBQur5z8UPaSzEYlF2p7/cut24A8WV/d3D5dX3XO/g
AuEMkyAws9zOeY3NMMfkHEZsuX0AetH7cOQYyAUIlpye30OxeoZgO4Cl3G5q95sk
Q4i/LpzNERq+JydmniPMbM/TL8p87RYr/bidO+0KeHwRzsesVu2ae1xO/ZRSyqny
un5RZblS9QY1H3xUgKQWpMLxJGXr6n+9eRThRsrTK/JH6GFpkFnjmMpuxquAw32w
PdxGWDUUE35pC4f0X/6rL8IBf32spXG+mKbBLTJkSkteSM26Uff4zVFludQU+N06
c6XFX7eBpbhhHhsCabOskGFXXS0bdi6NcZgazm1I4rhqrT+pQFHDOZg/dgl5cND/
Q4zqQ9Xrv/iV6ljHHAPYGrg4BGWW/sESCisGAQQBl1UBBQEBB0CTeGWS64rbAwJz
Sioh6y0Urd5/pGIj5UEdyAFrjhiKDgMBCAeIfgQYFgoAJhYhBGMuKk2/4/NDWi8h
v5QpbvLsm+aDBQJllv7BAhsMBQkB4TOAAAoJEJQpbvLsm+aDv0sBAIFCR1MA+d7V
ll+AxWH/k2ghgfJ661e88iaoG7qUyve5APsFQbV5thutm99chCp8Sc+fulHNtrKJ
WBymwZqetu7HBg==
=mVJw
-----END PGP PUBLIC KEY BLOCK-----

Deleted objfw.spec version [218ec62f80].

1
2
3
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
%global libobjfw_major 0
%global libobjfw_minor 0
%global libobjfwrt_major 0
%global libobjfwrt_minor 0
%global libobjfwtls_major 0
%global libobjfwtls_minor 0
%if 0%{?suse_version}
%global libobjfw_pkgname libobjfw%{libobjfw_major}
%global libobjfwrt_pkgname libobjfwrt%{libobjfwrt_major}
%global libobjfwtls_pkgname libobjfwtls%{libobjfwtls_major}
%else
%global libobjfw_pkgname libobjfw
%global libobjfwrt_pkgname libobjfwrt
%global libobjfwtls_pkgname libobjfwtls
%endif

Name:          objfw
Version:       1.1dev
Release:       1%{?dist}
Summary:       Portable, lightweight framework for the Objective-C language

%if 0%{?suse_version}
License:       QPL-1.0 or GPL-3.0 or GPL-2.0
Group:         Development/Languages/C and C++
%else
License:       QPL or GPLv3 or GPLv2
%endif
URL:           https://objfw.nil.im
Source0:       objfw-%{version}.tar.gz

BuildRequires: autoconf
BuildRequires: automake
BuildRequires: clang
BuildRequires: make
BuildRequires: pkgconfig(gnutls)
Requires:      %{libobjfw_pkgname}%{_isa} = %{version}-%{release}
Requires:      %{libobjfw_pkgname}-devel = %{version}-%{release}
Requires:      %{libobjfwrt_pkgname}%{_isa} = %{version}-%{release}
Requires:      %{libobjfwrt_pkgname}-devel = %{version}-%{release}
Requires:      ofarc%{_isa} = %{version}-%{release}
Requires:      ofdns%{_isa} = %{version}-%{release}
Requires:      ofhash%{_isa} = %{version}-%{release}
Requires:      ofhttp%{_isa} = %{version}-%{release}

%description
ObjFW is a portable, lightweight framework for the Objective-C language. It
enables you to write an application in Objective-C that will run on any
platform supported by ObjFW without having to worry about differences between
operating systems or various frameworks you would otherwise need if you want to
be portable.

It supports all modern Objective-C features when using Clang, but is also
compatible with GCC ≥ 4.6 to allow maximum portability.

ObjFW also comes with its own lightweight and extremely fast Objective-C
runtime, which in real world use cases was found to be significantly faster
than both GNU's and Apple's runtime.

%package -n %{libobjfw_pkgname}
Summary:       ObjFW library
Requires:      %{libobjfwrt_pkgname}%{_isa} = %{version}-%{release}

%description -n %{libobjfw_pkgname}
The %{libobjfw_pkgname} package contains the library needed by programs using
ObjFW.

%package -n %{libobjfw_pkgname}-devel
Summary:       Header files, libraries and tools for %{libobjfw_pkgname}
Requires:      %{libobjfw_pkgname}%{_isa} = %{version}-%{release}
Requires:      %{libobjfwrt_pkgname}-devel = %{version}-%{release}

%description -n %{libobjfw_pkgname}-devel
The %{libobjfw_pkgname}-devel package contains the header files, libraries and
tools to develop programs using ObjFW.

%package -n %{libobjfwrt_pkgname}
Summary:       ObjFW Objective-C runtime library

%description -n %{libobjfwrt_pkgname}
The %{libobjfwrt_pkgname} package contains ObjFW's Objective-C runtime library.

%package -n %{libobjfwrt_pkgname}-devel
Summary:       Header files and libraries for %{libobjfwrt_pkgname}
Requires:      %{libobjfwrt_pkgname}%{_isa} = %{version}-%{release}

%description -n %{libobjfwrt_pkgname}-devel
The %{libobjfwrt_pkgname}-devel package contains header files and libraries for
ObjFW's Objective-C runtime library.

%package -n %{libobjfwtls_pkgname}
Summary:       TLS support for ObjFW
Requires:      gnutls%{_isa} >= 3.0.5

%description -n %{libobjfwtls_pkgname}
The %{libobjfwtls_pkgname} package contains TLS support for ObjFW

%package -n %{libobjfwtls_pkgname}-devel
Summary:       Header files and libraries for %{libobjfwtls_pkgname}
Requires:      %{libobjfwtls_pkgname}%{_isa} = %{version}-%{release}

%description -n %{libobjfwtls_pkgname}-devel
The %{libobjfwtls_pkgname}-devel package contains header files and libraries
for TLS support for ObjFW.

%package -n ofarc
Summary:       Utility for handling ZIP, Tar and LHA archives
Requires:      %{libobjfw_pkgname}%{_isa} = %{version}-%{release}
Requires:      %{libobjfwrt_pkgname}%{_isa} = %{version}-%{release}

%description -n ofarc
ofarc is a multi-format archive utility that allows creating, listing,
extracting and modifying ZIP, Tar and LHA archives using ObjFW's classes for
various archive types.

%package -n ofdns
Summary:       Utility for performing DNS requests on the command line
Requires:      %{libobjfw_pkgname}%{_isa} = %{version}-%{release}
Requires:      %{libobjfwrt_pkgname}%{_isa} = %{version}-%{release}

%description -n ofdns
ofdns is an utility for performing DNS requests on the command line using
ObjFW's DNS resolver.

%package -n ofhash
Summary:       Utility to hash files with various cryptographic hash functions
Requires:      %{libobjfw_pkgname}%{_isa} = %{version}-%{release}
Requires:      %{libobjfwrt_pkgname}%{_isa} = %{version}-%{release}

%description -n ofhash
ofhash is an utility to hash files with various cryptographic hash functions
(even using different algorithms at once) using ObjFW's classes for various
cryptographic hashes.

%package -n ofhttp
Summary:       Command line downloader for HTTP(S)
Requires:      %{libobjfw_pkgname}%{_isa} = %{version}-%{release}
Requires:      %{libobjfwrt_pkgname}%{_isa} = %{version}-%{release}
Requires:      %{libobjfwtls_pkgname}%{_isa} = %{version}-%{release}

%description -n ofhttp
ofhttp is a command line downloader for HTTP and HTTPS using ObjFW's
OFHTTPClient class. It supports all features one would expect from a modern
command line downloader such as resuming of downloads, using a SOCKS5 proxy, a
modern terminal-based UI, etc.

%prep
%autosetup
./autogen.sh

%build
%configure OBJC=clang --disable-rpath
%make_build

%install
%make_install

%check
make -C tests run

%if 0%{?suse_version}
%post -n %{libobjfw_pkgname} -p /sbin/ldconfig
%postun -n %{libobjfw_pkgname} -p /sbin/ldconfig
%post -n %{libobjfwrt_pkgname} -p /sbin/ldconfig
%postun -n %{libobjfwrt_pkgname} -p /sbin/ldconfig
%endif

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

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

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

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

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

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

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

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

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

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

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
















































































































































































































































































































































































































































































































Modified src/Makefile from [68d38296ac] to [58eab480cd].

1
2
3
4
5
6
7
8
9
10
11

12
13
14
15
16
17
18
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}


SRCS = OFASN1BitString.m		\
       OFASN1Boolean.m			\
       OFASN1Enumerated.m		\
       OFASN1IA5String.m		\
       OFASN1Integer.m			\
       OFASN1NumericString.m		\











>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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}
LIB_PATCH = ${OBJFW_LIB_PATCH}

SRCS = OFASN1BitString.m		\
       OFASN1Boolean.m			\
       OFASN1Enumerated.m		\
       OFASN1IA5String.m		\
       OFASN1Integer.m			\
       OFASN1NumericString.m		\
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
       OFDictionary.m			\
       OFEnumerator.m			\
       OFFileManager.m			\
       OFGZIPStream.m			\
       OFHMAC.m				\
       OFINICategory.m			\
       OFINIFile.m			\


       OFInflate64Stream.m		\
       OFInflateStream.m		\
       OFInvocation.m			\
       OFLHAArchive.m			\
       OFLHAArchiveEntry.m		\
       OFList.m				\
       OFLocale.m			\
       OFMD5Hash.m			\
       OFMapTable.m			\

       OFMemoryStream.m			\
       OFMessagePackExtension.m		\
       OFMethodSignature.m		\
       OFMutableArray.m			\
       OFMutableData.m			\
       OFMutableDictionary.m		\

       OFMutableLHAArchiveEntry.m	\
       OFMutablePair.m			\
       OFMutableSet.m			\
       OFMutableString.m		\
       OFMutableTarArchiveEntry.m	\
       OFMutableTriple.m		\
       OFMutableURI.m			\
       OFMutableZIPArchiveEntry.m	\
       OFNotification.m			\
       OFNotificationCenter.m		\
       OFNull.m				\
       OFNumber.m			\
       OFObject.m			\
       OFObject+KeyValueCoding.m	\
       OFObject+Serialization.m		\
       OFOnce.m				\
       OFOptionsParser.m		\
       OFPBKDF2.m			\
       OFPair.m				\
       OFRIPEMD160Hash.m		\
       OFRunLoop.m			\
       OFSHA1Hash.m			\
       OFSHA224Hash.m			\
       OFSHA224Or256Hash.m		\
       OFSHA256Hash.m			\
       OFSHA384Hash.m			\
       OFSHA384Or512Hash.m		\
       OFSHA512Hash.m			\
       OFScrypt.m			\
       OFSecureData.m			\
       OFSeekableStream.m		\
       OFSerialization.m		\
       OFSet.m				\

       OFSortedList.m			\
       OFStdIOStream.m			\
       OFStream.m			\
       OFString.m			\
       OFString+CryptographicHashing.m	\
       OFString+JSONParsing.m		\
       OFString+PercentEncoding.m	\
       OFString+PropertyListParsing.m	\
       OFString+Serialization.m		\
       OFString+XMLEscaping.m		\
       OFString+XMLUnescaping.m		\
       ${OF_SUBPROCESS_M}		\
       OFSettings.m			\
       OFSystemInfo.m			\
       OFTarArchive.m			\
       OFTarArchiveEntry.m		\
       OFThread.m			\
       OFTimer.m			\
       OFTriple.m			\
       OFURI.m				\
       OFURIHandler.m			\
       OFUUID.m				\
       OFValue.m			\
       OFXMLAttribute.m			\
       OFXMLCDATA.m			\
       OFXMLCharacters.m		\
       OFXMLComment.m			\
       OFXMLElement.m			\
       OFXMLElement+Serialization.m	\
       OFXMLElementBuilder.m		\
       OFXMLNode.m			\
       OFXMLParser.m			\
       OFXMLProcessingInstruction.m	\
       OFZIPArchive.m			\
       OFZIPArchiveEntry.m		\
       ${USE_SRCS_FILES}		\







>
>









>






>






<







<
















<

>








<



<






<
<







<







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
       OFDictionary.m			\
       OFEnumerator.m			\
       OFFileManager.m			\
       OFGZIPStream.m			\
       OFHMAC.m				\
       OFINICategory.m			\
       OFINIFile.m			\
       OFIRI.m				\
       OFIRIHandler.m			\
       OFInflate64Stream.m		\
       OFInflateStream.m		\
       OFInvocation.m			\
       OFLHAArchive.m			\
       OFLHAArchiveEntry.m		\
       OFList.m				\
       OFLocale.m			\
       OFMD5Hash.m			\
       OFMapTable.m			\
       OFMatrix4x4.m			\
       OFMemoryStream.m			\
       OFMessagePackExtension.m		\
       OFMethodSignature.m		\
       OFMutableArray.m			\
       OFMutableData.m			\
       OFMutableDictionary.m		\
       OFMutableIRI.m			\
       OFMutableLHAArchiveEntry.m	\
       OFMutablePair.m			\
       OFMutableSet.m			\
       OFMutableString.m		\
       OFMutableTarArchiveEntry.m	\
       OFMutableTriple.m		\

       OFMutableZIPArchiveEntry.m	\
       OFNotification.m			\
       OFNotificationCenter.m		\
       OFNull.m				\
       OFNumber.m			\
       OFObject.m			\
       OFObject+KeyValueCoding.m	\

       OFOnce.m				\
       OFOptionsParser.m		\
       OFPBKDF2.m			\
       OFPair.m				\
       OFRIPEMD160Hash.m		\
       OFRunLoop.m			\
       OFSHA1Hash.m			\
       OFSHA224Hash.m			\
       OFSHA224Or256Hash.m		\
       OFSHA256Hash.m			\
       OFSHA384Hash.m			\
       OFSHA384Or512Hash.m		\
       OFSHA512Hash.m			\
       OFScrypt.m			\
       OFSecureData.m			\
       OFSeekableStream.m		\

       OFSet.m				\
       OFSettings.m			\
       OFSortedList.m			\
       OFStdIOStream.m			\
       OFStream.m			\
       OFString.m			\
       OFString+CryptographicHashing.m	\
       OFString+JSONParsing.m		\
       OFString+PercentEncoding.m	\
       OFString+PropertyListParsing.m	\

       OFString+XMLEscaping.m		\
       OFString+XMLUnescaping.m		\
       ${OF_SUBPROCESS_M}		\

       OFSystemInfo.m			\
       OFTarArchive.m			\
       OFTarArchiveEntry.m		\
       OFThread.m			\
       OFTimer.m			\
       OFTriple.m			\


       OFUUID.m				\
       OFValue.m			\
       OFXMLAttribute.m			\
       OFXMLCDATA.m			\
       OFXMLCharacters.m		\
       OFXMLComment.m			\
       OFXMLElement.m			\

       OFXMLElementBuilder.m		\
       OFXMLNode.m			\
       OFXMLParser.m			\
       OFXMLProcessingInstruction.m	\
       OFZIPArchive.m			\
       OFZIPArchiveEntry.m		\
       ${USE_SRCS_FILES}		\
141
142
143
144
145
146
147

148
149
150
151
152
153
154
	       OFHTTPCookieManager.m		\
	       OFHTTPRequest.m			\
	       OFHTTPResponse.m			\
	       OFHTTPServer.m			\
	       OFSequencedPacketSocket.m	\
	       OFSocket.m			\
	       OFStreamSocket.m			\

	       OFTCPSocket.m			\
	       OFTLSStream.m			\
	       OFUDPSocket.m			\
	       ${USE_SRCS_APPLETALK}		\
	       ${USE_SRCS_IPX}			\
	       ${USE_SRCS_UNIX_SOCKETS}
SRCS_APPLETALK = OFDDPSocket.m







>







139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
	       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
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
	    ObjFW.h				\
	    macros.h				\
	    objfw-defs.h			\
	    platform.h				\
	    ${USE_INCLUDES_ATOMIC}

SRCS += OFASPrintF.m			\
	OFAdjacentArray.m		\
	OFAdjacentSubarray.m		\
	OFArchiveURIHandler.m		\
	OFBase64.m			\
	OFBitSetCharacterSet.m		\
	OFBytesValue.m			\
	OFCRC16.m			\
	OFCRC32.m			\









	OFCountedMapTableSet.m		\




	OFEmbeddedURIHandler.m		\
	OFHuffmanTree.m			\
	OFINIFileSettings.m		\
	OFInvertedCharacterSet.m	\
	OFLHADecompressingStream.m	\
	OFMapTableDictionary.m		\
	OFMapTableSet.m			\
	OFMutableAdjacentArray.m	\
	OFMutableMapTableDictionary.m	\
	OFMutableMapTableSet.m		\
	OFMutableUTF8String.m		\
	OFNonretainedObjectValue.m	\
	OFPointValue.m			\
	OFPointerValue.m		\
	OFRangeCharacterSet.m		\
	OFRangeValue.m			\
	OFRectValue.m			\
	OFSandbox.m			\
	OFSizeValue.m			\
	OFStrPTime.m			\
	OFSubarray.m			\

	OFUTF8String.m			\
	${LIBBASES_M}			\
	${RUNTIME_AUTORELEASE_M}	\
	${RUNTIME_INSTANCE_M}		\
	${UNICODE_M}

SRCS_FILES += OFFileURIHandler.m
SRCS_SOCKETS += OFAsyncIPSocketConnector.m		\
		OFDNSResolverSettings.m			\
		${OF_EPOLL_KERNEL_EVENT_OBSERVER_M}	\
		OFHTTPURIHandler.m			\
		OFHostAddressResolver.m			\
		OFKernelEventObserver.m			\
		${OF_KQUEUE_KERNEL_EVENT_OBSERVER_M}	\
		${OF_POLL_KERNEL_EVENT_OBSERVER_M}	\
		${OF_SELECT_KERNEL_EVENT_OBSERVER_M}	\
		OFTCPSocketSOCKS5Connector.m



SRCS_WINDOWS += platform/Windows/OFWin32ConsoleStdIOStream.m	\
		versioninfo.rc

OBJS_EXTRA = exceptions/exceptions.a	\
	     encodings/encodings.a	\
	     forwarding/forwarding.a
LIB_OBJS_EXTRA = exceptions/exceptions.lib.a	\







<
<
|


<


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




<
<
<
<
<

<
<
<

<
<

|


>




|
>
|



|






>
>
>







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
	    ObjFW.h				\
	    macros.h				\
	    objfw-defs.h			\
	    platform.h				\
	    ${USE_INCLUDES_ATOMIC}

SRCS += OFASPrintF.m			\


	OFArchiveIRIHandler.m		\
	OFBase64.m			\
	OFBitSetCharacterSet.m		\

	OFCRC16.m			\
	OFCRC32.m			\
	OFConcreteArray.m		\
	OFConcreteColor.m		\
	OFConcreteCountedSet.m		\
	OFConcreteData.m		\
	OFConcreteDate.m		\
	OFConcreteDictionary.m		\
	OFConcreteMutableArray.m	\
	OFConcreteMutableData.m		\
	OFConcreteMutableDictionary.m	\
	OFConcreteMutableSet.m		\
	OFConcreteNumber.m		\
	OFConcreteSet.m			\
	OFConcreteSubarray.m		\
	OFConcreteValue.m		\
	OFEmbeddedIRIHandler.m		\
	OFHuffmanTree.m			\
	OFINIFileSettings.m		\
	OFInvertedCharacterSet.m	\
	OFLHADecompressingStream.m	\





	OFMutableUTF8String.m		\



	OFRangeCharacterSet.m		\


	OFSandbox.m			\
	OFStrFTime.m			\
	OFStrPTime.m			\
	OFSubarray.m			\
	OFSubdata.m			\
	OFUTF8String.m			\
	${LIBBASES_M}			\
	${RUNTIME_AUTORELEASE_M}	\
	${RUNTIME_INSTANCE_M}		\
	${UNICODE_M}			\
	${USE_SRCS_TAGGED_POINTERS}
SRCS_FILES += OFFileIRIHandler.m
SRCS_SOCKETS += OFAsyncIPSocketConnector.m		\
		OFDNSResolverSettings.m			\
		${OF_EPOLL_KERNEL_EVENT_OBSERVER_M}	\
		OFHTTPIRIHandler.m			\
		OFHostAddressResolver.m			\
		OFKernelEventObserver.m			\
		${OF_KQUEUE_KERNEL_EVENT_OBSERVER_M}	\
		${OF_POLL_KERNEL_EVENT_OBSERVER_M}	\
		${OF_SELECT_KERNEL_EVENT_OBSERVER_M}	\
		OFTCPSocketSOCKS5Connector.m
SRCS_TAGGED_POINTERS = OFTaggedPointerColor.m		\
		       OFTaggedPointerDate.m		\
		       OFTaggedPointerNumber.m
SRCS_WINDOWS += platform/Windows/OFWin32ConsoleStdIOStream.m	\
		versioninfo.rc

OBJS_EXTRA = exceptions/exceptions.a	\
	     encodings/encodings.a	\
	     forwarding/forwarding.a
LIB_OBJS_EXTRA = exceptions/exceptions.lib.a	\
256
257
258
259
260
261
262








		  ${LIBS}
LIBS := -Lruntime ${RUNTIME_LIBS} ${REEXPORT_RUNTIME} ${LIBS}
RCFLAGS = --use-temp-file						\
	  -DOBJFW_LIB_MAJOR=${OBJFW_LIB_MAJOR}				\
	  -DOBJFW_LIB_MINOR=${OBJFW_LIB_MINOR}				\
	  -DOBJFW_LIB_VERSION=\"${OBJFW_LIB_MAJOR}.${OBJFW_LIB_MINOR}\" \
	  -DOBJFW_SHARED_LIB=\"${OBJFW_SHARED_LIB}\"















>
>
>
>
>
>
>
>
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
		  ${LIBS}
LIBS := -Lruntime ${RUNTIME_LIBS} ${REEXPORT_RUNTIME} ${LIBS}
RCFLAGS = --use-temp-file						\
	  -DOBJFW_LIB_MAJOR=${OBJFW_LIB_MAJOR}				\
	  -DOBJFW_LIB_MINOR=${OBJFW_LIB_MINOR}				\
	  -DOBJFW_LIB_VERSION=\"${OBJFW_LIB_MAJOR}.${OBJFW_LIB_MINOR}\" \
	  -DOBJFW_SHARED_LIB=\"${OBJFW_SHARED_LIB}\"

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

Modified src/OFASN1BitString.h from [847c32ae19] to [c4957e9037].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2021 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFASN1BitString.m from [bf8a8b6b76] to [1107525b69].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2021 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFASN1Boolean.h from [fc203ebb38] to [b9c65fd898].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2021 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFASN1Boolean.m from [61b56be007] to [574b738a35].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2021 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFASN1DERRepresentation.h from [fea4984136] to [52466d1131].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2021 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFASN1Enumerated.h from [fad8083b56] to [b126a2f323].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2021 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFASN1Enumerated.m from [228ca991fe] to [4528aa182f].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2021 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFASN1IA5String.h from [f196d55ae8] to [66930c1931].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2021 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFASN1IA5String.m from [fc018eb179] to [970b68594c].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2021 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFASN1Integer.h from [743531352e] to [0c0ab89a54].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2021 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFASN1Integer.m from [6a1770327a] to [8246828d88].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2021 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFASN1NumericString.h from [27d661590b] to [7abcb9227d].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2021 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFASN1NumericString.m from [2f7f6ebcad] to [9bb6ec3e55].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2021 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFASN1ObjectIdentifier.h from [734e16abfc] to [7ee39cae98].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2021 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFASN1ObjectIdentifier.m from [44cc1be626] to [3be9eea106].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2021 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFASN1OctetString.h from [ce97aa1af6] to [1707a79a57].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2021 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFASN1OctetString.m from [3105a2073e] to [d3dd764a8d].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2021 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFASN1PrintableString.h from [7d7f0de4a3] to [4206aa8983].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2021 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFASN1PrintableString.m from [c60631b8b5] to [a209e00a41].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2021 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFASN1UTF8String.h from [5c715a17a8] to [b4f578bb30].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2021 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFASN1UTF8String.m from [a9b43b4e94] to [d4060a4150].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2021 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFASN1Value.h from [2f49749142] to [9157bbe2be].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2021 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFASN1Value.m from [789f3d1ac5] to [0b3a3e16ec].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2021 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

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

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFASPrintF.m from [882db55cea] to [164c33d955].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
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
#include <stdarg.h>
#include <stdbool.h>

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

#ifdef HAVE_ASPRINTF_L
# include <locale.h>
#endif
#ifdef HAVE_XLOCALE_H
# include <xlocale.h>
#endif

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


#import "OFString.h"
#import "OFLocale.h"

#import "OFInitializationFailedException.h"

#define maxSubformatLen 64








|










>







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 <stdarg.h>
#include <stdbool.h>

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

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

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

#import "OFASPrintF.h"
#import "OFString.h"
#import "OFLocale.h"

#import "OFInitializationFailedException.h"

#define maxSubformatLen 64

79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
		lengthModifierZ,
		lengthModifierT,
		lengthModifierCapitalL
	} lengthModifier;
	bool useLocale;
};

#ifdef HAVE_ASPRINTF_L
static locale_t cLocale;

OF_CONSTRUCTOR()
{
	if ((cLocale = newlocale(LC_ALL_MASK, "C", NULL)) == NULL)
		@throw [OFInitializationFailedException exception];
}







|







80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
		lengthModifierZ,
		lengthModifierT,
		lengthModifierCapitalL
	} lengthModifier;
	bool useLocale;
};

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

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

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

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

	switch (ctx->format[ctx->i]) {







|







374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
}

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

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

	switch (ctx->format[ctx->i]) {
544
545
546
547
548
549
550
551
552
553
554
555
556







557
558
559
560
561
562
563
564
565
566
567







568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
	case 'g':
	case 'G':
	case 'a':
	case 'A':
		switch (ctx->lengthModifier) {
		case lengthModifierNone:
		case lengthModifierL:
#ifdef HAVE_ASPRINTF_L
			if (!ctx->useLocale)
				tmpLen = asprintf_l(&tmp, cLocale,
				    ctx->subformat,
				    va_arg(ctx->arguments, double));
			else







#endif
				tmpLen = asprintf(&tmp, ctx->subformat,
				    va_arg(ctx->arguments, double));
			break;
		case lengthModifierCapitalL:
#ifdef HAVE_ASPRINTF_L
			if (!ctx->useLocale)
				tmpLen = asprintf_l(&tmp, cLocale,
				    ctx->subformat,
				    va_arg(ctx->arguments, long double));
			else







#endif
				tmpLen = asprintf(&tmp, ctx->subformat,
				    va_arg(ctx->arguments, long double));
			break;
		default:
			return false;
		}

#ifndef HAVE_ASPRINTF_L
		if (tmpLen == -1)
			return false;

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

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








|





>
>
>
>
>
>
>





|





>
>
>
>
>
>
>








|




|
|
|







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

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

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

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

Modified src/OFApplication.h from [d7b817478b] to [b0247b31f0].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
25
26
27
28
29
30
31






32
33
34
35
36
37
38
@class OFArray OF_GENERIC(ObjectType);
@class OFDictionary OF_GENERIC(KeyType, ObjectType);
@class OFMutableArray OF_GENERIC(ObjectType);
@class OFMutableDictionary OF_GENERIC(KeyType, ObjectType);
@class OFSandbox;
@class OFString;







/**
 * @brief A notification that will be sent when the application will terminate.
 */
extern const OFNotificationName OFApplicationWillTerminateNotification;

/**
 * @brief Specify the class to be used as the application delegate.







>
>
>
>
>
>







25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
@class OFArray OF_GENERIC(ObjectType);
@class OFDictionary OF_GENERIC(KeyType, ObjectType);
@class OFMutableArray OF_GENERIC(ObjectType);
@class OFMutableDictionary OF_GENERIC(KeyType, ObjectType);
@class OFSandbox;
@class OFString;

/**
 * @brief A notification that will be sent when the application did finish
 *	  launching.
 */
extern const OFNotificationName OFApplicationDidFinishLaunchingNotification;

/**
 * @brief A notification that will be sent when the application will terminate.
 */
extern const OFNotificationName OFApplicationWillTerminateNotification;

/**
 * @brief Specify the class to be used as the application delegate.
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
 * @interface MyAppDelegate: OFObject <OFApplicationDelegate>
 * @end
 *
 * // In MyAppDelegate.m:
 * OF_APPLICATION_DELEGATE(MyAppDelegate)
 *
 * @implementation MyAppDelegate
 * - (void)applicationDidFinishLaunching
 * {
 *         [OFApplication terminate];
 * }
 * @end
 * @endcode
 */
#define OF_APPLICATION_DELEGATE(class_)			\







|







53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
 * @interface MyAppDelegate: OFObject <OFApplicationDelegate>
 * @end
 *
 * // In MyAppDelegate.m:
 * OF_APPLICATION_DELEGATE(MyAppDelegate)
 *
 * @implementation MyAppDelegate
 * - (void)applicationDidFinishLaunching: (OFNotification *)notification
 * {
 *         [OFApplication terminate];
 * }
 * @end
 * @endcode
 */
#define OF_APPLICATION_DELEGATE(class_)			\
77
78
79
80
81
82
83



84
85
86
87
88
89



90
91
92
93
94
95
96
97
98
 *
 * @note Signals are not available on AmigaOS!
 */
@protocol OFApplicationDelegate <OFObject>
/**
 * @brief A method which is called when the application was initialized and is
 *	  running now.



 */
- (void)applicationDidFinishLaunching;

@optional
/**
 * @brief A method which is called when the application will terminate.



 */
- (void)applicationWillTerminate;

/**
 * @brief A method which is called when the application received a SIGINT.
 *
 * @warning You are not allowed to send any messages inside this method, as
 *	    message dispatching is not signal-safe! You are only allowed to do
 *	    signal-safe operations like setting a variable or calling a







>
>
>

|




>
>
>

|







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
 *
 * @note Signals are not available on AmigaOS!
 */
@protocol OFApplicationDelegate <OFObject>
/**
 * @brief A method which is called when the application was initialized and is
 *	  running now.
 *
 * @param notification A notification with name
 *		       OFApplicationDidFinishLaunchingNotification
 */
- (void)applicationDidFinishLaunching: (OFNotification *)notification;

@optional
/**
 * @brief A method which is called when the application will terminate.
 *
 * @param notification A notification with name
 *		       OFApplicationWillTerminateNotification
 */
- (void)applicationWillTerminate: (OFNotification *)notification;

/**
 * @brief A method which is called when the application received a SIGINT.
 *
 * @warning You are not allowed to send any messages inside this method, as
 *	    message dispatching is not signal-safe! You are only allowed to do
 *	    signal-safe operations like setting a variable or calling a
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
 * @brief A class which represents the application as an object.
 *
 * In order to create a new OFApplication, you should create a class conforming
 * to the optional @ref OFApplicationDelegate protocol and put
 * `OF_APPLICATION_DELEGATE(NameOfYourClass)` in the .m file of that class.
 *
 * When the application is about to be terminated,
 * @ref OFApplicationDelegate#applicationWillTerminate will be called on the
 * delegate and an @ref OFApplicationWillTerminateNotification will be sent.
 */
OF_SUBCLASSING_RESTRICTED
@interface OFApplication: OFObject
{
	OFString *_programName;
	OFArray OF_GENERIC(OFString *) *_arguments;







|







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

Modified src/OFApplication.m from [1a4d3713d8] to [b344510e2d].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
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
#endif
#import "OFLocale.h"
#import "OFNotificationCenter.h"
#import "OFPair.h"
#import "OFRunLoop+Private.h"
#import "OFRunLoop.h"
#import "OFSandbox.h"

#import "OFString.h"
#import "OFSystemInfo.h"
#import "OFThread+Private.h"
#import "OFThread.h"

#import "OFActivateSandboxFailedException.h"
#import "OFInvalidArgumentException.h"
#import "OFOutOfMemoryException.h"
#import "OFOutOfRangeException.h"

#if defined(OF_MACOS)
# include <crt_externs.h>
#elif defined(OF_WINDOWS)
# include <windows.h>
extern int _CRT_glob;
extern void __wgetmainargs(int *, wchar_t ***, wchar_t ***, int, int *);
#elif defined(OF_AMIGAOS)

# include <proto/exec.h>
# include <proto/dos.h>

#elif !defined(OF_IOS)
extern char **environ;
#endif

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







>

















>


>







33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
#endif
#import "OFLocale.h"
#import "OFNotificationCenter.h"
#import "OFPair.h"
#import "OFRunLoop+Private.h"
#import "OFRunLoop.h"
#import "OFSandbox.h"
#import "OFStdIOStream.h"
#import "OFString.h"
#import "OFSystemInfo.h"
#import "OFThread+Private.h"
#import "OFThread.h"

#import "OFActivateSandboxFailedException.h"
#import "OFInvalidArgumentException.h"
#import "OFOutOfMemoryException.h"
#import "OFOutOfRangeException.h"

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

#ifdef OF_PSP
# include <pspkerneltypes.h>
# include <psploadexec.h>
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
	  andArgumentValues: (char **[])argv
       andWideArgumentCount: (int)wargc
      andWideArgumentValues: (wchar_t *[])wargv;
#endif
- (void)of_run;
@end



const OFNotificationName OFApplicationWillTerminateNotification =
    @"OFApplicationWillTerminateNotification";
static OFApplication *app = nil;

static void
atexitHandler(void)
{
	id <OFApplicationDelegate> delegate = app.delegate;

	[[OFNotificationCenter defaultCenter]
	    postNotificationName: OFApplicationWillTerminateNotification
			  object: app];

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

	[delegate release];



#if defined(OF_HAVE_THREADS) && defined(OF_HAVE_SOCKETS) && \
    defined(OF_AMIGAOS) && !defined(OF_MORPHOS)
	OFSocketDeinit();
#endif
}

int
OFApplicationMain(int *argc, char **argv[], id <OFApplicationDelegate> delegate)
{
#ifdef OF_WINDOWS
	wchar_t **wargv, **wenvp;
	int wargc, si = 0;
#endif

	[[OFLocale alloc] init];

	app = [[OFApplication alloc] of_init];

#ifdef OF_WINDOWS
	if ([OFSystemInfo isWindowsNT]) {



		__wgetmainargs(&wargc, &wargv, &wenvp, _CRT_glob, &si);

		[app of_setArgumentCount: argc
		       andArgumentValues: argv
		    andWideArgumentCount: wargc
		   andWideArgumentValues: wargv];
	} else
#endif
		[app of_setArgumentCount: argc andArgumentValues: argv];







>
>








<
|
|


|
|


>
>










<
<
<
<
<






>
>
>

>







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
	  andArgumentValues: (char **[])argv
       andWideArgumentCount: (int)wargc
      andWideArgumentValues: (wchar_t *[])wargv;
#endif
- (void)of_run;
@end

const OFNotificationName OFApplicationDidFinishLaunchingNotification =
    @"OFApplicationDidFinishLaunchingNotification";
const OFNotificationName OFApplicationWillTerminateNotification =
    @"OFApplicationWillTerminateNotification";
static OFApplication *app = nil;

static void
atexitHandler(void)
{
	id <OFApplicationDelegate> delegate = app.delegate;

	OFNotification *notification = [OFNotification
	    notificationWithName: OFApplicationWillTerminateNotification
			  object: app];

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

	[delegate release];

	[[OFNotificationCenter defaultCenter] postNotification: notification];

#if defined(OF_HAVE_THREADS) && defined(OF_HAVE_SOCKETS) && \
    defined(OF_AMIGAOS) && !defined(OF_MORPHOS)
	OFSocketDeinit();
#endif
}

int
OFApplicationMain(int *argc, char **argv[], id <OFApplicationDelegate> delegate)
{





	[[OFLocale alloc] init];

	app = [[OFApplication alloc] of_init];

#ifdef OF_WINDOWS
	if ([OFSystemInfo isWindowsNT]) {
		wchar_t **wargv, **wenvp;
		int wargc, si = 0;

		__wgetmainargs(&wargc, &wargv, &wenvp, _CRT_glob, &si);

		[app of_setArgumentCount: argc
		       andArgumentValues: argv
		    andWideArgumentCount: wargc
		   andWideArgumentValues: wargv];
	} else
#endif
		[app of_setArgumentCount: argc andArgumentValues: argv];
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
				if ([tmp hasPrefix: @"="]) {
					objc_autoreleasePoolPop(pool);
					continue;
				}

				pos = [tmp rangeOfString: @"="].location;
				if (pos == OFNotFound) {
					fprintf(stderr,
					    "Warning: Invalid environment "
					    "variable: %s\n", tmp.UTF8String);
					continue;
				}

				key = [tmp substringToIndex: pos];
				value = [tmp substringFromIndex: pos + 1];
				[_environment setObject: value forKey: key];








<
|
|







261
262
263
264
265
266
267

268
269
270
271
272
273
274
275
276
				if ([tmp hasPrefix: @"="]) {
					objc_autoreleasePoolPop(pool);
					continue;
				}

				pos = [tmp rangeOfString: @"="].location;
				if (pos == OFNotFound) {

					OFLog(@"Warning: Invalid environment "
					    "variable: %@", tmp);
					continue;
				}

				key = [tmp substringToIndex: pos];
				value = [tmp substringFromIndex: pos + 1];
				[_environment setObject: value forKey: key];

298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
				if ([tmp hasPrefix: @"="]) {
					objc_autoreleasePoolPop(pool);
					continue;
				}

				pos = [tmp rangeOfString: @"="].location;
				if (pos == OFNotFound) {
					fprintf(stderr,
					    "Warning: Invalid environment "
					    "variable: %s\n", tmp.UTF8String);
					continue;
				}

				key = [tmp substringToIndex: pos];
				value = [tmp substringFromIndex: pos + 1];
				[_environment setObject: value forKey: key];








<
|
|







302
303
304
305
306
307
308

309
310
311
312
313
314
315
316
317
				if ([tmp hasPrefix: @"="]) {
					objc_autoreleasePoolPop(pool);
					continue;
				}

				pos = [tmp rangeOfString: @"="].location;
				if (pos == OFNotFound) {

					OFLog(@"Warning: Invalid environment "
					    "variable: %@", tmp);
					continue;
				}

				key = [tmp substringToIndex: pos];
				value = [tmp substringFromIndex: pos + 1];
				[_environment setObject: value forKey: key];

392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407

			for (; *env != NULL; env++) {
				void *pool = objc_autoreleasePoolPush();
				OFString *key, *value;
				char *sep;

				if ((sep = strchr(*env, '=')) == NULL) {
					fprintf(stderr, "Warning: Invalid "
					    "environment variable: %s\n", *env);
					continue;
				}

				key = [OFString
				    stringWithCString: *env
					     encoding: encoding
					       length: sep - *env];







|
|







395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410

			for (; *env != NULL; env++) {
				void *pool = objc_autoreleasePoolPush();
				OFString *key, *value;
				char *sep;

				if ((sep = strchr(*env, '=')) == NULL) {
					OFLog(@"Warning: Invalid environment "
					    "variable: %s", *env);
					continue;
				}

				key = [OFString
				    stringWithCString: *env
					     encoding: encoding
					       length: sep - *env];
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
#undef REGISTER_SIGNAL
}

- (void)of_run
{
	void *pool = objc_autoreleasePoolPush();
	OFRunLoop *runLoop;


#ifdef OF_HAVE_THREADS
	[OFThread of_createMainThread];
	runLoop = [OFRunLoop currentRunLoop];
#else
	runLoop = [[[OFRunLoop alloc] init] autorelease];
#endif

	[OFRunLoop of_setMainRunLoop: runLoop];

	objc_autoreleasePoolPop(pool);

	/*
	 * Note: runLoop is still valid after the release of the pool, as
	 * of_setMainRunLoop: retained it. However, we only have a weak
	 * reference to it now, whereas we had a strong reference before.
	 */

	pool = objc_autoreleasePoolPush();







	[_delegate applicationDidFinishLaunching];

	objc_autoreleasePoolPop(pool);

	[runLoop run];
}

- (void)terminate
{







>



















>
>
>
>
>
>
>
|
>







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
#undef REGISTER_SIGNAL
}

- (void)of_run
{
	void *pool = objc_autoreleasePoolPush();
	OFRunLoop *runLoop;
	OFNotification *notification;

#ifdef OF_HAVE_THREADS
	[OFThread of_createMainThread];
	runLoop = [OFRunLoop currentRunLoop];
#else
	runLoop = [[[OFRunLoop alloc] init] autorelease];
#endif

	[OFRunLoop of_setMainRunLoop: runLoop];

	objc_autoreleasePoolPop(pool);

	/*
	 * Note: runLoop is still valid after the release of the pool, as
	 * of_setMainRunLoop: retained it. However, we only have a weak
	 * reference to it now, whereas we had a strong reference before.
	 */

	pool = objc_autoreleasePoolPush();

	notification = [OFNotification
	    notificationWithName: OFApplicationDidFinishLaunchingNotification
			  object: app];

	[[OFNotificationCenter defaultCenter] postNotification: notification];

	[_delegate applicationDidFinishLaunching: notification];

	objc_autoreleasePoolPop(pool);

	[runLoop run];
}

- (void)terminate
{

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

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Renamed and modified src/OFArchiveURIHandler.h [7c81cf8db2] to src/OFArchiveIRIHandler.h [8af45b43a0].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#import "OFURIHandler.h"

OF_ASSUME_NONNULL_BEGIN

@interface OFArchiveURIHandler: OFURIHandler
@end

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

OF_ASSUME_NONNULL_END

|













|



|





|
|





1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
/*
 * Copyright (c) 2008-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 "OFIRIHandler.h"

OF_ASSUME_NONNULL_BEGIN

@interface OFArchiveIRIHandler: OFIRIHandler
@end

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

OF_ASSUME_NONNULL_END

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#include <errno.h>

#import "OFArchiveURIHandler.h"
#import "OFCharacterSet.h"
#import "OFGZIPStream.h"

#import "OFLHAArchive.h"
#import "OFStream.h"
#import "OFTarArchive.h"
#import "OFURI.h"
#import "OFZIPArchive.h"

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

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

static OFCharacterSet *pathAllowedCharacters;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

end:
	stream = [stream retain];

	objc_autoreleasePoolPop(pool);

	return [stream autorelease];
}
@end

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

	@try {
		_characterSet =
		    [[OFCharacterSet URIPathAllowedCharacterSet] retain];
		_characterIsMember = (bool (*)(id, SEL, OFUnichar))
		    [_characterSet methodForSelector:
		    @selector(characterIsMember:)];
	} @catch (id e) {
		[self release];
		@throw e;
	}

|

















|


>



<





|












|


|
|


|


|


|
|















|
|





|





|







|










|



|










|



|















|






|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
/*
 * Copyright (c) 2008-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 <errno.h>

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

#import "OFZIPArchive.h"

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

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

static OFCharacterSet *pathAllowedCharacters;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

end:
	stream = [stream retain];

	objc_autoreleasePoolPop(pool);

	return [stream autorelease];
}
@end

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

	@try {
		_characterSet =
		    [[OFCharacterSet IRIPathAllowedCharacterSet] retain];
		_characterIsMember = (bool (*)(id, SEL, OFUnichar))
		    [_characterSet methodForSelector:
		    @selector(characterIsMember:)];
	} @catch (id e) {
		[self release];
		@throw e;
	}
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
- (bool)characterIsMember: (OFUnichar)character
{
	return (character != '!' && _characterIsMember(_characterSet,
	    @selector(characterIsMember:), character));
}
@end

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

	OFOnce(&onceControl, initPathAllowedCharacters);

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

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

	objc_autoreleasePoolPop(pool);

	return ret;
}







|
|
|


|

|






|




|






168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
- (bool)characterIsMember: (OFUnichar)character
{
	return (character != '!' && _characterIsMember(_characterSet,
	    @selector(characterIsMember:), character));
}
@end

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

	OFOnce(&onceControl, initPathAllowedCharacters);

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

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

	objc_autoreleasePoolPop(pool);

	return ret;
}

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

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFArray.h from [f90f803ff9] to [03770bb9c3].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#endif

#include <stdarg.h>

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

OF_ASSUME_NONNULL_BEGIN

/** @file */








<







21
22
23
24
25
26
27

28
29
30
31
32
33
34
#endif

#include <stdarg.h>

#import "OFObject.h"
#import "OFCollection.h"
#import "OFEnumerator.h"

#import "OFJSONRepresentation.h"
#import "OFMessagePackRepresentation.h"

OF_ASSUME_NONNULL_BEGIN

/** @file */

98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
 * @class OFArray OFArray.h ObjFW/OFArray.h
 *
 * @brief An abstract class for storing objects in an array.
 *
 * @note Subclasses must implement @ref count and @ref objectAtIndex:.
 */
@interface OFArray OF_GENERIC(ObjectType): OFObject <OFCopying,
    OFMutableCopying, OFCollection, OFSerialization, OFJSONRepresentation,
    OFMessagePackRepresentation>
#if !defined(OF_HAVE_GENERICS) && !defined(DOXYGEN)
# define ObjectType id
#endif
/**
 * @brief The objects of the array as a C array.
 *







|







97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
 * @class OFArray OFArray.h ObjFW/OFArray.h
 *
 * @brief An abstract class for storing objects in an array.
 *
 * @note Subclasses must implement @ref count and @ref objectAtIndex:.
 */
@interface OFArray OF_GENERIC(ObjectType): OFObject <OFCopying,
    OFMutableCopying, OFCollection, OFJSONRepresentation,
    OFMessagePackRepresentation>
#if !defined(OF_HAVE_GENERICS) && !defined(DOXYGEN)
# define ObjectType id
#endif
/**
 * @brief The objects of the array as a C array.
 *
181
182
183
184
185
186
187







188
189
190
191
192
193
194
 * @param objects A C array of objects
 * @param count The length of the C array
 * @return A new autoreleased OFArray
 */
+ (instancetype)arrayWithObjects: (ObjectType const _Nonnull *_Nonnull)objects
			   count: (size_t)count;








/**
 * @brief Initializes an OFArray with the specified object.
 *
 * @param object An object
 * @return An initialized OFArray
 */
- (instancetype)initWithObject: (ObjectType)object;







>
>
>
>
>
>
>







180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
 * @param objects A C array of objects
 * @param count The length of the C array
 * @return A new autoreleased OFArray
 */
+ (instancetype)arrayWithObjects: (ObjectType const _Nonnull *_Nonnull)objects
			   count: (size_t)count;

/**
 * @brief Initializes an OFArray with no objects.
 *
 * @return An initialized OFArray
 */
- (instancetype)init OF_DESIGNATED_INITIALIZER;

/**
 * @brief Initializes an OFArray with the specified object.
 *
 * @param object An object
 * @return An initialized OFArray
 */
- (instancetype)initWithObject: (ObjectType)object;
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
 *	  the specified length.
 *
 * @param objects A C array of objects
 * @param count The length of the C array
 * @return An initialized OFArray
 */
- (instancetype)initWithObjects: (ObjectType const _Nonnull *_Nonnull)objects
			  count: (size_t)count;

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







|







230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
 *	  the specified length.
 *
 * @param objects A C array of objects
 * @param count The length of the C array
 * @return An initialized OFArray
 */
- (instancetype)initWithObjects: (ObjectType const _Nonnull *_Nonnull)objects
			  count: (size_t)count OF_DESIGNATED_INITIALIZER;

/**
 * @brief Returns an OFEnumerator to enumerate through all objects of the array.
 *
 * @return An OFEnumerator to enumerate through all objects of the array
 */
- (OFEnumerator OF_GENERIC(ObjectType) *)objectEnumerator;
401
402
403
404
405
406
407














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















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







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







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

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

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

Modified src/OFArray.m from [c89de989b4] to [b037c2efc4].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49






50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the 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 <stdarg.h>
#include <stdlib.h>

#include <assert.h>

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

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

static struct {
	Class isa;
} placeholder;

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

@interface OFPlaceholderArray: OFArray
@end

@implementation OFPlaceholderArray






- (instancetype)init
{
	return (id)[[OFAdjacentArray alloc] init];
}

- (instancetype)initWithObject: (id)object
{
	return (id)[[OFAdjacentArray alloc] initWithObject: object];
}

- (instancetype)initWithObjects: (id)firstObject, ...
{
	id ret;
	va_list arguments;

	va_start(arguments, firstObject);
	ret = [[OFAdjacentArray alloc] initWithObject: firstObject
					    arguments: arguments];
	va_end(arguments);

	return ret;
}

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

- (instancetype)initWithArray: (OFArray *)array
{
	return (id)[[OFAdjacentArray alloc] initWithArray: array];
}

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

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

- (instancetype)retain
{
	return self;
}

- (instancetype)autorelease
{
	return self;
}

- (void)release
{
}

- (void)dealloc
{
	OF_DEALLOC_UNSUPPORTED
}
@end

@implementation OFArray
+ (void)initialize
{
	if (self == [OFArray class])
		placeholder.isa = [OFPlaceholderArray class];
}

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


|


















<
<


|




<



















>
>
>
>
>
>


|




|








|









|





|





|


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






|







1
2
3
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
/*
 * 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 <stdarg.h>
#include <stdlib.h>



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


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

static struct {
	Class isa;
} placeholder;

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

@interface OFPlaceholderArray: OFArray
@end

@implementation OFPlaceholderArray
#ifdef __clang__
/* We intentionally don't call into super, so silence the warning. */
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wunknown-pragmas"
# pragma clang diagnostic ignored "-Wobjc-designated-initializers"
#endif
- (instancetype)init
{
	return (id)[[OFConcreteArray alloc] init];
}

- (instancetype)initWithObject: (id)object
{
	return (id)[[OFConcreteArray alloc] initWithObject: object];
}

- (instancetype)initWithObjects: (id)firstObject, ...
{
	id ret;
	va_list arguments;

	va_start(arguments, firstObject);
	ret = [[OFConcreteArray alloc] initWithObject: firstObject
					    arguments: arguments];
	va_end(arguments);

	return ret;
}

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

- (instancetype)initWithArray: (OFArray *)array
{
	return (id)[[OFConcreteArray alloc] initWithArray: array];
}

- (instancetype)initWithObjects: (id const *)objects
			  count: (size_t)count
{
	return (id)[[OFConcreteArray alloc] initWithObjects: objects
						      count: count];
}
#ifdef __clang__




# pragma clang diagnostic pop




#endif




OF_SINGLETON_METHODS








@end

@implementation OFArray
+ (void)initialize
{
	if (self == [OFArray class])
		object_setClass((id)&placeholder, [OFPlaceholderArray class]);
}

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

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
{
	return [[[self alloc] initWithObjects: objects
					count: count] autorelease];
}

- (instancetype)init
{
	if ([self isMemberOfClass: [OFArray class]]) {

		@try {
			[self doesNotRecognizeSelector: _cmd];
		} @catch (id e) {
			[self release];
			@throw e;
		}

		abort();
	}

	return [super init];
}

- (instancetype)initWithObject: (id)object
{
	if (object == nil) {
		[self release];
		@throw [OFInvalidArgumentException exception];
	}

	return [self initWithObjects: object, nil];
}

- (instancetype)initWithObjects: (id)firstObject, ...
{
	id ret;
	va_list arguments;

	va_start(arguments, firstObject);
	ret = [self initWithObject: firstObject arguments: arguments];
	va_end(arguments);

	return ret;
}

- (instancetype)initWithObject: (id)firstObject


		     arguments: (va_list)arguments

{


	OF_INVALID_INIT_METHOD



}























- (instancetype)initWithArray: (OFArray *)array
{


	OF_INVALID_INIT_METHOD



}






















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

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


- (size_t)count
{
	OF_UNRECOGNIZED_SELECTOR
}

- (void)getObjects: (id *)buffer inRange: (OFRange)range







|
>















<
<
<
<
<
|














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


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





|
|
<
<
<
>







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
{
	return [[[self alloc] initWithObjects: objects
					count: count] autorelease];
}

- (instancetype)init
{
	if ([self isMemberOfClass: [OFArray class]] ||
	    [self isMemberOfClass: [OFMutableArray class]]) {
		@try {
			[self doesNotRecognizeSelector: _cmd];
		} @catch (id e) {
			[self release];
			@throw e;
		}

		abort();
	}

	return [super init];
}

- (instancetype)initWithObject: (id)object
{





	return [self initWithObjects: &object count: 1];
}

- (instancetype)initWithObjects: (id)firstObject, ...
{
	id ret;
	va_list arguments;

	va_start(arguments, firstObject);
	ret = [self initWithObject: firstObject arguments: arguments];
	va_end(arguments);

	return ret;
}

- (instancetype)initWithObject: (id)firstObject arguments: (va_list)arguments
{
	size_t count = 1;
	va_list argumentsCopy;
	id *objects;

	if (firstObject == nil)
		return [self init];

	va_copy(argumentsCopy, arguments);
	while (va_arg(argumentsCopy, id) != nil)
		count++;

	@try {
		objects = OFAllocMemory(count, sizeof(id));
	} @catch (id e) {
		[self release];
		@throw e;
	}

	@try {
		objects[0] = firstObject;

		for (size_t i = 1; i < count; i++) {
			objects[i] = va_arg(arguments, id);
			OFEnsure(objects[i] != nil);
		}

		self = [self initWithObjects: objects count: count];
	} @finally {
		OFFreeMemory(objects);
	}

	return self;
}

- (instancetype)initWithArray: (OFArray *)array
{
	id *objects;
	size_t count;

	@try {
		count = array.count;
		objects = OFAllocMemory(count, sizeof(id));

		[array getObjects: objects
			  inRange: OFMakeRange(0, count)];
	} @catch (id e) {
		[self release];
		@throw e;
	}

	@try {
		self = [self initWithObjects: objects count: count];
	} @finally {
		OFFreeMemory(objects);
	}

	return self;
}

#ifdef __clang__
/* We intentionally don't call into super, so silence the warning. */
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wunknown-pragmas"
# pragma clang diagnostic ignored "-Wobjc-designated-initializers"
#endif
- (instancetype)initWithObjects: (id const *)objects
			  count: (size_t)count
{
	OF_INVALID_INIT_METHOD
}
#ifdef __clang__
# pragma clang diagnostic pop



#endif

- (size_t)count
{
	OF_UNRECOGNIZED_SELECTOR
}

- (void)getObjects: (id *)buffer inRange: (OFRange)range
373
374
375
376
377
378
379

380
381
382
383
384
385
386
387
	id *buffer;

	if (range.length > SIZE_MAX - range.location ||
	    range.location + range.length < self.count)
		@throw [OFOutOfRangeException exception];

	if (![self isKindOfClass: [OFMutableArray class]])

		return [OFSubarray arrayWithArray: self range: range];

	buffer = OFAllocMemory(range.length, sizeof(*buffer));
	@try {
		[self getObjects: buffer inRange: range];

		ret = [OFArray arrayWithObjects: buffer count: range.length];
	} @finally {







>
|







407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
	id *buffer;

	if (range.length > SIZE_MAX - range.location ||
	    range.location + range.length < self.count)
		@throw [OFOutOfRangeException exception];

	if (![self isKindOfClass: [OFMutableArray class]])
		return [[[OFSubarray alloc] initWithArray: self
						    range: range] autorelease];

	buffer = OFAllocMemory(range.length, sizeof(*buffer));
	@try {
		[self getObjects: buffer inRange: range];

		ret = [OFArray arrayWithObjects: buffer count: range.length];
	} @finally {
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
	objc_autoreleasePoolPop(pool);

	[ret makeImmutable];

	return [ret autorelease];
}

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

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

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

		[element addChild: object.XMLElementBySerializing];

		objc_autoreleasePoolPop(pool2);
	}

	[element retain];

	objc_autoreleasePoolPop(pool);

	return [element autorelease];
}

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

- (OFString *)JSONRepresentationWithOptions:
    (OFJSONRepresentationOptions)options







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







581
582
583
584
585
586
587



























588
589
590
591
592
593
594
	objc_autoreleasePoolPop(pool);

	[ret makeImmutable];

	return [ret autorelease];
}




























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

- (OFString *)JSONRepresentationWithOptions:
    (OFJSONRepresentationOptions)options
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699

		child = [object messagePackRepresentation];
		[data addItems: child.items count: child.count];

		objc_autoreleasePoolPop(pool2);
	}

	assert(i == count);

	[data makeImmutable];

	objc_autoreleasePoolPop(pool);

	return data;
}







|







693
694
695
696
697
698
699
700
701
702
703
704
705
706
707

		child = [object messagePackRepresentation];
		[data addItems: child.items count: child.count];

		objc_autoreleasePoolPop(pool2);
	}

	OFAssert(i == count);

	[data makeImmutable];

	objc_autoreleasePoolPop(pool);

	return data;
}
723
724
725
726
727
728
729










730
731
732
733
734
735
736
			      options: (OFArraySortOptions)options
{
	OFMutableArray *new = [[self mutableCopy] autorelease];
	[new sortUsingSelector: selector options: options];
	[new makeImmutable];
	return new;
}











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







>
>
>
>
>
>
>
>
>
>







731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
			      options: (OFArraySortOptions)options
{
	OFMutableArray *new = [[self mutableCopy] autorelease];
	[new sortUsingSelector: selector options: options];
	[new makeImmutable];
	return new;
}

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

#ifdef OF_HAVE_BLOCKS
- (OFArray *)sortedArrayUsingComparator: (OFComparator)comparator
				options: (OFArraySortOptions)options
{
	OFMutableArray *new = [[self mutableCopy] autorelease];
	[new sortUsingComparator: comparator options: options];
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
	return new;
}

- (int)countByEnumeratingWithState: (OFFastEnumerationState *)state
			   objects: (id *)objects
			     count: (int)count
{

	OFRange range = OFMakeRange(state->state, count);

	if (range.length > SIZE_MAX - range.location)
		@throw [OFOutOfRangeException exception];

	if (range.location + range.length > self.count)
		range.length = self.count - range.location;

	[self getObjects: objects inRange: range];

	if (range.location + range.length > ULONG_MAX)
		@throw [OFOutOfRangeException exception];

	state->state = (unsigned long)(range.location + range.length);
	state->itemsPtr = objects;
	state->mutationsPtr = (unsigned long *)self;

	return (int)range.length;
}

- (OFEnumerator *)objectEnumerator
{
	return [[[OFArrayEnumerator alloc] initWithArray: self







>















|







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
	return new;
}

- (int)countByEnumeratingWithState: (OFFastEnumerationState *)state
			   objects: (id *)objects
			     count: (int)count
{
	static unsigned long dummyMutations;
	OFRange range = OFMakeRange(state->state, count);

	if (range.length > SIZE_MAX - range.location)
		@throw [OFOutOfRangeException exception];

	if (range.location + range.length > self.count)
		range.length = self.count - range.location;

	[self getObjects: objects inRange: range];

	if (range.location + range.length > ULONG_MAX)
		@throw [OFOutOfRangeException exception];

	state->state = (unsigned long)(range.location + range.length);
	state->itemsPtr = objects;
	state->mutationsPtr = &dummyMutations;

	return (int)range.length;
}

- (OFEnumerator *)objectEnumerator
{
	return [[[OFArrayEnumerator alloc] initWithArray: self

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

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFAsyncIPSocketConnector.m from [b9084cfb8c] to [d4ecee0079].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFAtomic.h from [25c89d25b5] to [44218ac496].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
}

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







|













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

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

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

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

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

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFBitSetCharacterSet.h from [6dd7022dff] to [57c1c01559].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFBitSetCharacterSet.m from [d65aed83c7] to [8559ff24b2].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

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

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFBlock.m from [0c18ed18b9] to [8f6ad5fb69].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
22
23
24
25
26
27
28

29
30
31
32
33
34
35
#import "OFBlock.h"
#ifdef OF_HAVE_ATOMIC_OPS
# import "OFAtomic.h"
#endif
#ifdef OF_HAVE_THREADS
# import "OFPlainMutex.h"
#endif


#import "OFAllocFailedException.h"
#import "OFInitializationFailedException.h"

#if defined(OF_OBJFW_RUNTIME)
# import "runtime/private.h"
#endif







>







22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#import "OFBlock.h"
#ifdef OF_HAVE_ATOMIC_OPS
# import "OFAtomic.h"
#endif
#ifdef OF_HAVE_THREADS
# import "OFPlainMutex.h"
#endif
#import "OFString.h"

#import "OFAllocFailedException.h"
#import "OFInitializationFailedException.h"

#if defined(OF_OBJFW_RUNTIME)
# import "runtime/private.h"
#endif
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
struct class _NSConcreteGlobalBlock_metaclass;
struct class _NSConcreteMallocBlock_metaclass;
# endif
#endif

static struct {
	Class isa;
} alloc_failed_exception;

#ifndef OF_HAVE_ATOMIC_OPS
# define numSpinlocks 8	/* needs to be a power of 2 */
# define SPINLOCK_HASH(p) ((uintptr_t)p >> 4) & (numSpinlocks - 1)
static OFSpinlock blockSpinlocks[numSpinlocks];
static OFSpinlock byrefSpinlocks[numSpinlocks];
#endif

void *
_Block_copy(const void *block_)
{
	struct Block *block = (struct Block *)block_;

	if ([(id)block isMemberOfClass: (Class)&_NSConcreteStackBlock]) {
		struct Block *copy;

		if ((copy = malloc(block->descriptor->size)) == NULL) {
			alloc_failed_exception.isa =
			    [OFAllocFailedException class];
			@throw (OFAllocFailedException *)
			    &alloc_failed_exception;
		}
		memcpy(copy, block, block->descriptor->size);

		object_setClass((id)copy, (Class)&_NSConcreteMallocBlock);
		copy->flags++;

		if (block->flags & OFBlockHasCopyDispose)







|

















|
|
|
<







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
struct class _NSConcreteGlobalBlock_metaclass;
struct class _NSConcreteMallocBlock_metaclass;
# endif
#endif

static struct {
	Class isa;
} allocFailedException;

#ifndef OF_HAVE_ATOMIC_OPS
# define numSpinlocks 8	/* needs to be a power of 2 */
# define SPINLOCK_HASH(p) ((uintptr_t)p >> 4) & (numSpinlocks - 1)
static OFSpinlock blockSpinlocks[numSpinlocks];
static OFSpinlock byrefSpinlocks[numSpinlocks];
#endif

void *
_Block_copy(const void *block_)
{
	struct Block *block = (struct Block *)block_;

	if ([(id)block isMemberOfClass: (Class)&_NSConcreteStackBlock]) {
		struct Block *copy;

		if ((copy = malloc(block->descriptor->size)) == NULL) {
			object_setClass((id)&allocFailedException,
			    [OFAllocFailedException class]);
			@throw (OFAllocFailedException *)&allocFailedException;

		}
		memcpy(copy, block, block->descriptor->size);

		object_setClass((id)copy, (Class)&_NSConcreteMallocBlock);
		copy->flags++;

		if (block->flags & OFBlockHasCopyDispose)
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
		struct Byref *src = (struct Byref *)src_;
		struct Byref **dst = (struct Byref **)dst_;

		src = src->forwarding;

		if ((src->flags & OFBlockRefCountMask) == 0) {
			if ((*dst = malloc(src->size)) == NULL) {
				alloc_failed_exception.isa =
				    [OFAllocFailedException class];
				@throw (OFAllocFailedException *)
				    &alloc_failed_exception;
			}

			memcpy(*dst, src, src->size);
			(*dst)->flags =
			    ((*dst)->flags & ~OFBlockRefCountMask) | 1;
			(*dst)->forwarding = *dst;








|
|

|







266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
		struct Byref *src = (struct Byref *)src_;
		struct Byref **dst = (struct Byref **)dst_;

		src = src->forwarding;

		if ((src->flags & OFBlockRefCountMask) == 0) {
			if ((*dst = malloc(src->size)) == NULL) {
				object_setClass((id)&allocFailedException,
				    [OFAllocFailedException class]);
				@throw (OFAllocFailedException *)
				    &allocFailedException;
			}

			memcpy(*dst, src, src->size);
			(*dst)->flags =
			    ((*dst)->flags & ~OFBlockRefCountMask) | 1;
			(*dst)->forwarding = *dst;

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

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFCRC16.m from [ba4e599142] to [e31c28850d].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFCRC32.h from [139d8dccac] to [7b94370b73].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFCRC32.m from [b50ad38210] to [0dec8de64b].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

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

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFCharacterSet.m from [76e8828364] to [4a8863c346].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
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
}

- (instancetype)initWithRange: (OFRange)range
{
	return (id)[[OFRangeCharacterSet alloc] initWithRange: range];
}

- (instancetype)retain
{
	return self;
}

- (instancetype)autorelease
{
	return self;
}

- (void)release
{
}

- (void)dealloc
{
	OF_DEALLOC_UNSUPPORTED
}
@end

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

	placeholder.isa = [OFPlaceholderCharacterSet class];
}

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








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





|
<
|
|







52
53
54
55
56
57
58




59













60
61
62
63
64
65

66
67
68
69
70
71
72
73
74
}

- (instancetype)initWithRange: (OFRange)range
{
	return (id)[[OFRangeCharacterSet alloc] initWithRange: range];
}





OF_SINGLETON_METHODS













@end

@implementation OFCharacterSet
+ (void)initialize
{
	if (self == [OFCharacterSet class])

		object_setClass((id)&placeholder,
		    [OFPlaceholderCharacterSet class]);
}

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

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
{
	return [[[OFInvertedCharacterSet alloc]
	    initWithCharacterSet: self] autorelease];
}
@end

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

- (instancetype)retain
{
	return self;
}

- (void)release
{
}

- (unsigned int)retainCount
{
	return OFMaxRetainCount;
}

- (bool)characterIsMember: (OFUnichar)character
{
	switch (character) {
	case 0x0009:
	case 0x0020:
	case 0x00A0:
	case 0x1680:







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







129
130
131
132
133
134
135



















136
137
138
139
140
141
142
{
	return [[[OFInvertedCharacterSet alloc]
	    initWithCharacterSet: self] autorelease];
}
@end

@implementation OFWhitespaceCharacterSet



















- (bool)characterIsMember: (OFUnichar)character
{
	switch (character) {
	case 0x0009:
	case 0x0020:
	case 0x00A0:
	case 0x1680:
192
193
194
195
196
197
198


199
	case 0x205F:
	case 0x3000:
		return true;
	default:
		return false;
	}
}


@end







>
>

155
156
157
158
159
160
161
162
163
164
	case 0x205F:
	case 0x3000:
		return true;
	default:
		return false;
	}
}

OF_SINGLETON_METHODS
@end

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

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFColor.h from [bce9432d45] to [7160d2b484].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

/**
 * @class OFColor OFColor.h ObjFW/OFColor.h
 *
 * @brief A class for storing a color.
 */
@interface OFColor: OFObject
{
	float _red, _green, _blue, _alpha;
	OF_RESERVE_IVARS(OFColor, 4)
}

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







<
<
<
<
<







19
20
21
22
23
24
25





26
27
28
29
30
31
32

/**
 * @class OFColor OFColor.h ObjFW/OFColor.h
 *
 * @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;

Modified src/OFColor.m from [ff82ab6aae] to [fa5fd20716].

1
2
3
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
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"



#import "OFColor.h"

#import "OFOnce.h"





#import "OFInvalidArgumentException.h"















































@implementation OFColor














#define PREDEFINED_COLOR(name, redValue, greenValue, blueValue)		   \
	static OFColor *name##Color = nil;				   \
									   \
	static void							   \
	initPredefinedColor_##name(void)				   \
	{								   \

		name##Color = [[OFColor alloc] initWithRed: redValue	   \
						     green: greenValue	   \
						      blue: blueValue	   \
						     alpha: 1];		   \
	}								   \
									   \
	+ (OFColor *)name						   \
	{								   \
		static OFOnceControl onceControl = OFOnceControlInitValue; \
		OFOnce(&onceControl, initPredefinedColor_##name);	   \
									   \

|















>
>

>

>
>

>
>
|
>
>

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

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






>
|
|
|
|







1
2
3
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
/*
 * 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 <math.h>

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

@interface OFPlaceholderColor: OFColor
@end

@interface OFConcreteColorSingleton: OFConcreteColor
@end

static struct {
	Class isa;
} placeholder;

#ifdef OF_OBJFW_RUNTIME
static const float allowedImprecision = 0.0000001;
#endif

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

	if (fabsf(red * 255 - redInt) < allowedImprecision &&
	    fabsf(green * 255 - greenInt) < allowedImprecision &&
	    fabsf(blue * 255 - blueInt) < allowedImprecision && alpha == 1) {
		id ret = [OFTaggedPointerColor colorWithRed: redInt
						      green: greenInt
						       blue: blueInt];

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

	return (id)[[OFConcreteColor alloc] initWithRed: red
						  green: green
						   blue: blue
						  alpha: alpha];
}

OF_SINGLETON_METHODS
@end

@implementation OFConcreteColorSingleton
OF_SINGLETON_METHODS
@end

@implementation OFColor
+ (void)initialize
{
	if (self == [OFColor class])
		object_setClass((id)&placeholder, [OFPlaceholderColor class]);
}

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

	return [super alloc];
}

#define PREDEFINED_COLOR(name, redValue, greenValue, blueValue)		   \
	static OFColor *name##Color = nil;				   \
									   \
	static void							   \
	initPredefinedColor_##name(void)				   \
	{								   \
		name##Color = [[OFConcreteColorSingleton alloc]		   \
		    initWithRed: redValue				   \
			  green: greenValue				   \
			   blue: blueValue				   \
			  alpha: 1];					   \
	}								   \
									   \
	+ (OFColor *)name						   \
	{								   \
		static OFOnceControl onceControl = OFOnceControlInitValue; \
		OFOnce(&onceControl, initPredefinedColor_##name);	   \
									   \
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
}

- (instancetype)initWithRed: (float)red
		      green: (float)green
		       blue: (float)blue
		      alpha: (float)alpha
{
	self = [super init];

	@try {
		if (red < 0.0 || red > 1.0 ||
		    green < 0.0 || green > 1.0 ||
		    blue < 0.0 || blue > 1.0 ||
		    alpha < 0.0 || alpha > 1.0)
			@throw [OFInvalidArgumentException exception];

		_red = red;
		_green = green;
		_blue = blue;
		_alpha = alpha;
	} @catch (id e) {
		[self release];
		@throw e;
	}




	return self;
}

- (bool)isEqual: (id)object
{
	OFColor *other;



	if (object == self)
		return true;

	if (![object isKindOfClass: [OFColor class]])
		return false;

	other = object;






	if (other->_red != _red)
		return false;
	if (other->_green != _green)
		return false;
	if (other->_blue != _blue)
		return false;
	if (other->_alpha != _alpha)
		return false;

	return true;
}

- (unsigned long)hash
{

	unsigned long hash;
	float tmp;



	OFHashInit(&hash);

	tmp = OFToLittleEndianFloat(_red);




	for (uint_fast8_t i = 0; i < sizeof(float); i++)
		OFHashAddByte(&hash, ((char *)&tmp)[i]);

	tmp = OFToLittleEndianFloat(_green);
	for (uint_fast8_t i = 0; i < sizeof(float); i++)
		OFHashAddByte(&hash, ((char *)&tmp)[i]);

	tmp = OFToLittleEndianFloat(_blue);
	for (uint_fast8_t i = 0; i < sizeof(float); i++)
		OFHashAddByte(&hash, ((char *)&tmp)[i]);

	tmp = OFToLittleEndianFloat(_alpha);
	for (uint_fast8_t i = 0; i < sizeof(float); i++)
		OFHashAddByte(&hash, ((char *)&tmp)[i]);

	OFHashFinalize(&hash);

	return hash;
}

- (void)getRed: (float *)red
	 green: (float *)green
	  blue: (float *)blue
	 alpha: (float *)alpha
{


	*red = _red;


	*green = _green;
	*blue = _blue;



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







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

>
>
>
|





>
>








>
>
>
>
>

|

|

|

|







>



>
>


|
>
>
>
>



|



|
<
<
<
<













>
>
|
>
>
|
|
>

>
|
|


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
}

- (instancetype)initWithRed: (float)red
		      green: (float)green
		       blue: (float)blue
		      alpha: (float)alpha
{

	if ([self isMemberOfClass: [OFColor class]]) {
		@try {





			[self doesNotRecognizeSelector: _cmd];




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

		abort();
	}

	return [super init];
}

- (bool)isEqual: (id)object
{
	OFColor *other;
	float red, green, blue, alpha;
	float otherRed, otherGreen, otherBlue, otherAlpha;

	if (object == self)
		return true;

	if (![object isKindOfClass: [OFColor class]])
		return false;

	other = object;
	[self getRed: &red green: &green blue: &blue alpha: &alpha];
	[other getRed: &otherRed
		green: &otherGreen
		 blue: &otherBlue
		alpha: &otherAlpha];

	if (otherRed != red)
		return false;
	if (otherGreen != green)
		return false;
	if (otherBlue != blue)
		return false;
	if (otherAlpha != alpha)
		return false;

	return true;
}

- (unsigned long)hash
{
	float red, green, blue, alpha;
	unsigned long hash;
	float tmp;

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

	OFHashInit(&hash);

	tmp = OFToLittleEndianFloat(red);
	for (uint_fast8_t i = 0; i < sizeof(float); i++)
		OFHashAddByte(&hash, ((char *)&tmp)[i]);

	tmp = OFToLittleEndianFloat(green);
	for (uint_fast8_t i = 0; i < sizeof(float); i++)
		OFHashAddByte(&hash, ((char *)&tmp)[i]);

	tmp = OFToLittleEndianFloat(blue);
	for (uint_fast8_t i = 0; i < sizeof(float); i++)
		OFHashAddByte(&hash, ((char *)&tmp)[i]);

	tmp = OFToLittleEndianFloat(alpha);




	for (uint_fast8_t i = 0; i < sizeof(float); i++)
		OFHashAddByte(&hash, ((char *)&tmp)[i]);

	OFHashFinalize(&hash);

	return hash;
}

- (void)getRed: (float *)red
	 green: (float *)green
	  blue: (float *)blue
	 alpha: (float *)alpha
{
	OF_UNRECOGNIZED_SELECTOR
}

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

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

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

Renamed and modified src/OFAdjacentArray.h [9facc27db0] to src/OFConcreteArray.h [db1bf1896b].

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

OF_ASSUME_NONNULL_BEGIN

@class OFMutableData;

@interface OFAdjacentArray: OFArray
{
	OFMutableData *_array;
}
@end

OF_ASSUME_NONNULL_END

|



















|






1
2
3
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.
 */

#import "OFArray.h"

OF_ASSUME_NONNULL_BEGIN

@class OFMutableData;

@interface OFConcreteArray: OFArray
{
	OFMutableData *_array;
}
@end

OF_ASSUME_NONNULL_END

Renamed and modified src/OFAdjacentArray.m [e305e33733] to src/OFConcreteArray.m [7603501025].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the 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 <stdarg.h>

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

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

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

	@try {
		_array = [[OFMutableData alloc] initWithItemSize: sizeof(id)];
	} @catch (id e) {

|

















|
|
|
|

<





|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

25
26
27
28
29
30
31
32
33
34
35
36
37
/*
 * Copyright (c) 2008-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 <stdarg.h>

#import "OFConcreteArray.h"
#import "OFConcreteMutableArray.h"
#import "OFConcreteSubarray.h"
#import "OFData.h"
#import "OFString.h"


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

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

	@try {
		_array = [[OFMutableData alloc] initWithItemSize: sizeof(id)];
	} @catch (id e) {
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
	}

	return self;
}

- (instancetype)initWithObjects: (id const *)objects count: (size_t)count
{
	self = [self init];

	@try {
		bool ok = true;

		for (size_t i = 0; i < count; i++) {
			if (objects[i] == nil)
				ok = false;

			[objects[i] retain];
		}

		if (!ok)
			@throw [OFInvalidArgumentException exception];



		[_array addItems: objects count: count];
	} @catch (id e) {
		for (size_t i = 0; i < count; i++)
			[objects[i] release];

		[self release];
		@throw e;
	}

	return self;
}

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

	@try {
		void *pool = objc_autoreleasePoolPush();

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

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

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

			objc_autoreleasePoolPop(pool2);
		}

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

	return self;
}

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







|














>
>









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







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
	}

	return self;
}

- (instancetype)initWithObjects: (id const *)objects count: (size_t)count
{
	self = [super init];

	@try {
		bool ok = true;

		for (size_t i = 0; i < count; i++) {
			if (objects[i] == nil)
				ok = false;

			[objects[i] retain];
		}

		if (!ok)
			@throw [OFInvalidArgumentException exception];

		_array = [[OFMutableData alloc] initWithItemSize: sizeof(id)
							capacity: count];
		[_array addItems: objects count: count];
	} @catch (id e) {
		for (size_t i = 0; i < count; i++)
			[objects[i] release];

		[self release];
		@throw e;
	}


































	return self;
}

- (size_t)count
{
	return _array.count;
}
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
		@throw [OFOutOfRangeException exception];

	if ([self isKindOfClass: [OFMutableArray class]])
		return [OFArray
		    arrayWithObjects: (id *)_array.items + range.location
			       count: range.length];


	return [OFAdjacentSubarray arrayWithArray: self range: range];
}

- (bool)isEqual: (id)object
{
	OFArray *otherArray;
	id const *objects, *otherObjects;
	size_t count;

	if (object == self)
		return true;

	if (![object isKindOfClass: [OFAdjacentArray class]] &&
	    ![object isKindOfClass: [OFMutableAdjacentArray class]])
		return [super isEqual: object];

	otherArray = object;

	count = _array.count;

	if (count != otherArray.count)







>
|











|
|







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
		@throw [OFOutOfRangeException exception];

	if ([self isKindOfClass: [OFMutableArray class]])
		return [OFArray
		    arrayWithObjects: (id *)_array.items + range.location
			       count: range.length];

	return [[[OFConcreteSubarray alloc] initWithArray: self
						    range: range] autorelease];
}

- (bool)isEqual: (id)object
{
	OFArray *otherArray;
	id const *objects, *otherObjects;
	size_t count;

	if (object == self)
		return true;

	if (![object isKindOfClass: [OFConcreteArray class]] &&
	    ![object isKindOfClass: [OFConcreteMutableArray class]])
		return [super isEqual: object];

	otherArray = object;

	count = _array.count;

	if (count != otherArray.count)
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
	return hash;
}

- (int)countByEnumeratingWithState: (OFFastEnumerationState *)state
			   objects: (id *)objects
			     count: (int)count_
{

	size_t count = _array.count;

	if (count > INT_MAX)
		/*
		 * Use the implementation from OFArray, which is slower, but can
		 * enumerate in chunks.
		 */
		return [super countByEnumeratingWithState: state
						  objects: objects
						    count: count_];

	if (state->state >= count)
		return 0;

	state->state = (unsigned long)count;
	state->itemsPtr = (id *)_array.items;
	state->mutationsPtr = (unsigned long *)self;

	return (int)count;
}

#ifdef OF_HAVE_BLOCKS
- (void)enumerateObjectsUsingBlock: (OFArrayEnumerationBlock)block
{







>
















|







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
	return hash;
}

- (int)countByEnumeratingWithState: (OFFastEnumerationState *)state
			   objects: (id *)objects
			     count: (int)count_
{
	static unsigned long dummyMutations;
	size_t count = _array.count;

	if (count > INT_MAX)
		/*
		 * Use the implementation from OFArray, which is slower, but can
		 * enumerate in chunks.
		 */
		return [super countByEnumeratingWithState: state
						  objects: objects
						    count: count_];

	if (state->state >= count)
		return 0;

	state->state = (unsigned long)count;
	state->itemsPtr = (id *)_array.items;
	state->mutationsPtr = &dummyMutations;

	return (int)count;
}

#ifdef OF_HAVE_BLOCKS
- (void)enumerateObjectsUsingBlock: (OFArrayEnumerationBlock)block
{

Added src/OFConcreteColor.h version [be50524c9c].





















































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/*
 * 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 "OFColor.h"

OF_ASSUME_NONNULL_BEGIN

@interface OFConcreteColor: OFColor
{
	float _red, _green, _blue, _alpha;
}
@end

OF_ASSUME_NONNULL_END

Added src/OFConcreteColor.m version [9cb3544c30].





























































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
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"

#import "OFConcreteColor.h"

#import "OFInvalidArgumentException.h"

@implementation OFConcreteColor
- (instancetype)initWithRed: (float)red
		      green: (float)green
		       blue: (float)blue
		      alpha: (float)alpha
{
	self = [super init];

	@try {
		if (red < 0.0 || red > 1.0 ||
		    green < 0.0 || green > 1.0 ||
		    blue < 0.0 || blue > 1.0 ||
		    alpha < 0.0 || alpha > 1.0)
			@throw [OFInvalidArgumentException exception];

		_red = red;
		_green = green;
		_blue = blue;
		_alpha = alpha;
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (void)getRed: (float *)red
	 green: (float *)green
	  blue: (float *)blue
	 alpha: (float *)alpha
{
	*red = _red;
	*green = _green;
	*blue = _blue;

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

Renamed and modified src/OFCountedMapTableSet.h [1da95cb48f] to src/OFConcreteCountedSet.h [8e71ffc035].

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

OF_ASSUME_NONNULL_BEGIN

@class OFMapTable;

@interface OFCountedMapTableSet: OFCountedSet
{
	OFMapTable *_mapTable;
}
@end

OF_ASSUME_NONNULL_END

|



















|






1
2
3
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.
 */

#import "OFCountedSet.h"

OF_ASSUME_NONNULL_BEGIN

@class OFMapTable;

@interface OFConcreteCountedSet: OFCountedSet
{
	OFMapTable *_mapTable;
}
@end

OF_ASSUME_NONNULL_END

Renamed and modified src/OFCountedMapTableSet.m [d7ae224517] to src/OFConcreteCountedSet.m [965f0d415a].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

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

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

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

- (instancetype)initWithSet: (OFSet *)set
{
	self = [self init];

	@try {

|















|

|
|


<






|


|
|







1
2
3
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
/*
 * 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 "OFConcreteCountedSet.h"
#import "OFArray.h"
#import "OFConcreteMutableSet.h"
#import "OFMapTable.h"
#import "OFString.h"
#import "OFXMLAttribute.h"


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

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

- (instancetype)initWithSet: (OFSet *)set
{
	self = [self init];

	@try {
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
		while ((object = va_arg(arguments, id)) != nil)
			[self addObject: object];
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

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

	@try {
		void *pool = objc_autoreleasePoolPush();

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

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

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

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

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

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

			objc_autoreleasePoolPop(pool2);
		}

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

	return self;
}

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







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







109
110
111
112
113
114
115














































116
117
118
119
120
121
122
		while ((object = va_arg(arguments, id)) != nil)
			[self addObject: object];
	} @catch (id e) {
		[self release];
		@throw e;
	}















































	return self;
}

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

Added src/OFConcreteData.h version [a698b0e43b].

























































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
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.
 */

#import "OFData.h"

OF_ASSUME_NONNULL_BEGIN

@interface OFConcreteData: OFData
{
	unsigned char *_Nullable _items;
	size_t _capacity, _count, _itemSize;
	bool _freeWhenDone;
}
@end

OF_ASSUME_NONNULL_END

Added src/OFConcreteData.m version [0286162fad].















































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
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
/*
 * 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 <limits.h>
#include <string.h>

#import "OFConcreteData.h"

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

@implementation OFConcreteData
- (instancetype)init
{
	return [self initWithItemSize: 1];
}

- (instancetype)initWithItemSize: (size_t)itemSize
{
	self = [super init];

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

		_itemSize = itemSize;
		_freeWhenDone = true;
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (instancetype)initWithItems: (const void *)items
			count: (size_t)count
		     itemSize: (size_t)itemSize
{
	self = [super init];

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

		_items = OFAllocMemory(count, itemSize);
		_capacity = _count = count;
		_itemSize = itemSize;
		_freeWhenDone = true;

		memcpy(_items, items, count * itemSize);
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (instancetype)initWithItemsNoCopy: (void *)items
			      count: (size_t)count
			   itemSize: (size_t)itemSize
		       freeWhenDone: (bool)freeWhenDone
{
	self = [super init];

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

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

	return self;
}

- (void)dealloc
{
	if (_freeWhenDone)
		OFFreeMemory(_items);

	[super dealloc];
}

- (size_t)count
{
	return _count;
}

- (size_t)itemSize
{
	return _itemSize;
}

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

Added src/OFConcreteDate.h version [a87a3d9f2b].





















































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/*
 * 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 "OFDate.h"

OF_ASSUME_NONNULL_BEGIN

@interface OFConcreteDate: OFDate
{
	OFTimeInterval _seconds;
}
@end

OF_ASSUME_NONNULL_END

Added src/OFConcreteDate.m version [88454b3318].

































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
/*
 * Copyright (c) 2008-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 "OFConcreteDate.h"

@implementation OFConcreteDate
- (instancetype)initWithTimeIntervalSince1970: (OFTimeInterval)seconds
{
	self = [super initWithTimeIntervalSince1970: seconds];

	_seconds = seconds;

	return self;
}

- (OFTimeInterval)timeIntervalSince1970
{
	return _seconds;
}
@end

Renamed and modified src/OFMapTableDictionary.h [23bbcf2cb0] to src/OFConcreteDictionary.h [9e7a8543fe].

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

OF_ASSUME_NONNULL_BEGIN

@class OFMapTable;
@class OFMapTableEnumerator;

@interface OFMapTableDictionary: OFDictionary
{
	OFMapTable *_mapTable;
}

- (instancetype)initWithCapacity: (size_t)capacity;
@end

OF_ASSUME_NONNULL_END

|




















|








1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/*
 * Copyright (c) 2008-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 "OFDictionary.h"

OF_ASSUME_NONNULL_BEGIN

@class OFMapTable;
@class OFMapTableEnumerator;

@interface OFConcreteDictionary: OFDictionary
{
	OFMapTable *_mapTable;
}

- (instancetype)initWithCapacity: (size_t)capacity;
@end

OF_ASSUME_NONNULL_END

Renamed and modified src/OFMapTableDictionary.m [3e7005d616] to src/OFConcreteDictionary.m [7b72b69230].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the 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 <assert.h>

#import "OFMapTableDictionary.h"
#import "OFArray.h"
#import "OFMapTable+Private.h"
#import "OFMapTable.h"
#import "OFMutableMapTableDictionary.h"
#import "OFString.h"
#import "OFXMLElement.h"

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

static void *
copy(void *object)

|















<
|
|
|


<

<







1
2
3
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 "OFConcreteDictionary.h"
#import "OFArray.h"
#import "OFConcreteMutableDictionary.h"
#import "OFMapTable+Private.h"
#import "OFMapTable.h"

#import "OFString.h"


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

static void *
copy(void *object)
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
static const OFMapTableFunctions objectFunctions = {
	.retain = retain,
	.release = release,
	.hash = hash,
	.equal = equal
};

@implementation OFMapTableDictionary
- (instancetype)init
{
	return [self initWithCapacity: 0];
}

- (instancetype)initWithCapacity: (size_t)capacity
{







|







65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
static const OFMapTableFunctions objectFunctions = {
	.retain = retain,
	.release = release,
	.hash = hash,
	.equal = equal
};

@implementation OFConcreteDictionary
- (instancetype)init
{
	return [self initWithCapacity: 0];
}

- (instancetype)initWithCapacity: (size_t)capacity
{
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
- (instancetype)initWithDictionary: (OFDictionary *)dictionary
{
	size_t count;

	if (dictionary == nil)
		return [self init];

	if ([dictionary isKindOfClass: [OFMapTableDictionary class]] ||
	    [dictionary isKindOfClass: [OFMutableMapTableDictionary class]]) {
		self = [super init];

		@try {
			OFMapTableDictionary *dictionary_ =
			    (OFMapTableDictionary *)dictionary;

			_mapTable = [dictionary_->_mapTable copy];
		} @catch (id e) {
			[self release];
			@throw e;
		}








|
|



|
|







95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
- (instancetype)initWithDictionary: (OFDictionary *)dictionary
{
	size_t count;

	if (dictionary == nil)
		return [self init];

	if ([dictionary isKindOfClass: [OFConcreteDictionary class]] ||
	    [dictionary isKindOfClass: [OFConcreteMutableDictionary class]]) {
		self = [super init];

		@try {
			OFConcreteDictionary *dictionary_ =
			    (OFConcreteDictionary *)dictionary;

			_mapTable = [dictionary_->_mapTable copy];
		} @catch (id e) {
			[self release];
			@throw e;
		}

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
		[self release];
		@throw e;
	}

	return self;
}

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

	@try {
		void *pool = objc_autoreleasePoolPush();
		OFArray *keys, *objects;
		OFEnumerator *keyEnumerator, *objectEnumerator;
		OFXMLElement *keyElement, *objectElement;

		keys = [element elementsForName: @"key"
				      namespace: OFSerializationNS];
		objects = [element elementsForName: @"object"
					 namespace: OFSerializationNS];

		if (keys.count != objects.count)
			@throw [OFInvalidFormatException exception];

		_mapTable = [[OFMapTable alloc]
		    initWithKeyFunctions: keyFunctions
			 objectFunctions: objectFunctions
				capacity: keys.count];

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

			key = [keyElement elementsForNamespace:
			    OFSerializationNS].firstObject;
			object = [objectElement elementsForNamespace:
			    OFSerializationNS].firstObject;

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

			[_mapTable setObject: object.objectByDeserializing
				      forKey: key.objectByDeserializing];

			objc_autoreleasePoolPop(pool2);
		}

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

	return self;
}

- (void)dealloc
{
	[_mapTable release];

	[super dealloc];
}

- (id)objectForKey: (id)key
{
	return [_mapTable objectForKey: key];
}

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

- (bool)isEqual: (id)object
{
	OFMapTableDictionary *dictionary;

	if (object == self)
		return true;

	if (![object isKindOfClass: [OFMapTableDictionary class]] &&
	    ![object isKindOfClass: [OFMutableMapTableDictionary class]])
		return [super isEqual: object];

	dictionary = (OFMapTableDictionary *)object;

	return [dictionary->_mapTable isEqual: _mapTable];
}

- (bool)containsObject: (id)object
{
	return [_mapTable containsObject: object];







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



















|




|
|


|







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
		[self release];
		@throw e;
	}

	return self;
}






















































- (void)dealloc
{
	[_mapTable release];

	[super dealloc];
}

- (id)objectForKey: (id)key
{
	return [_mapTable objectForKey: key];
}

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

- (bool)isEqual: (id)object
{
	OFConcreteDictionary *dictionary;

	if (object == self)
		return true;

	if (![object isKindOfClass: [OFConcreteDictionary class]] &&
	    ![object isKindOfClass: [OFConcreteMutableDictionary class]])
		return [super isEqual: object];

	dictionary = (OFConcreteDictionary *)object;

	return [dictionary->_mapTable isEqual: _mapTable];
}

- (bool)containsObject: (id)object
{
	return [_mapTable containsObject: object];
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
		OFMapTableEnumerator *enumerator;
		void **keyPtr;
		size_t i;

		i = 0;
		enumerator = [_mapTable keyEnumerator];
		while ((keyPtr = [enumerator nextObject]) != NULL) {
			assert(i < count);

			keys[i++] = (id)*keyPtr;
		}

		objc_autoreleasePoolPop(pool);

		ret = [OFArray arrayWithObjects: keys count: count];







|







286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
		OFMapTableEnumerator *enumerator;
		void **keyPtr;
		size_t i;

		i = 0;
		enumerator = [_mapTable keyEnumerator];
		while ((keyPtr = [enumerator nextObject]) != NULL) {
			OFAssert(i < count);

			keys[i++] = (id)*keyPtr;
		}

		objc_autoreleasePoolPop(pool);

		ret = [OFArray arrayWithObjects: keys count: count];
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
		OFMapTableEnumerator *enumerator;
		void **objectPtr;
		size_t i;

		i = 0;
		enumerator = [_mapTable objectEnumerator];
		while ((objectPtr = [enumerator nextObject]) != NULL) {
			assert(i < count);

			objects[i++] = (id)*objectPtr;
		}

		objc_autoreleasePoolPop(pool);

		ret = [OFArray arrayWithObjects: objects count: count];







|







319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
		OFMapTableEnumerator *enumerator;
		void **objectPtr;
		size_t i;

		i = 0;
		enumerator = [_mapTable objectEnumerator];
		while ((objectPtr = [enumerator nextObject]) != NULL) {
			OFAssert(i < count);

			objects[i++] = (id)*objectPtr;
		}

		objc_autoreleasePoolPop(pool);

		ret = [OFArray arrayWithObjects: objects count: count];

Renamed and modified src/OFMutableAdjacentArray.h [def2b8877c] to src/OFConcreteMutableArray.h [21f6b5d74d].

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

OF_ASSUME_NONNULL_BEGIN

@class OFMutableData;

@interface OFMutableAdjacentArray: OFMutableArray
{
	OFMutableData *_array;
	unsigned long _mutations;
}
@end

OF_ASSUME_NONNULL_END

|



















|







1
2
3
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.
 */

#import "OFArray.h"

OF_ASSUME_NONNULL_BEGIN

@class OFMutableData;

@interface OFConcreteMutableArray: OFMutableArray
{
	OFMutableData *_array;
	unsigned long _mutations;
}
@end

OF_ASSUME_NONNULL_END

Renamed and modified src/OFMutableAdjacentArray.m [7ff7f8969c] to src/OFConcreteMutableArray.m [0c182ca468].

1
2
3
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
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#include <string.h>

#import "OFMutableAdjacentArray.h"
#import "OFAdjacentArray.h"
#import "OFArray+Private.h"
#import "OFData.h"

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

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

- (instancetype)initWithCapacity: (size_t)capacity
{
	self = [super init];

	@try {

|

















|
|







|


|
|







1
2
3
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
/*
 * 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 "OFConcreteMutableArray.h"
#import "OFConcreteArray.h"
#import "OFArray+Private.h"
#import "OFData.h"

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

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

- (instancetype)initWithCapacity: (size_t)capacity
{
	self = [super init];

	@try {
374
375
376
377
378
379
380
381
382
383
		}
	}
}
#endif

- (void)makeImmutable
{
	object_setClass(self, [OFAdjacentArray class]);
}
@end







|


374
375
376
377
378
379
380
381
382
383
		}
	}
}
#endif

- (void)makeImmutable
{
	object_setClass(self, [OFConcreteArray class]);
}
@end

Added src/OFConcreteMutableData.h version [aa781c6069].

























































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
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.
 */

#import "OFMutableData.h"

OF_ASSUME_NONNULL_BEGIN

@interface OFConcreteMutableData: OFMutableData
{
	unsigned char *_Nullable _items;
	size_t _capacity, _count, _itemSize;
	bool _freeWhenDone;
}
@end

OF_ASSUME_NONNULL_END

Added src/OFConcreteMutableData.m version [8fb2e330e0].



























































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
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
/*
 * 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 <limits.h>
#include <string.h>

#import "OFConcreteMutableData.h"
#import "OFConcreteData.h"

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

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

- (instancetype)initWithItemSize: (size_t)itemSize capacity: (size_t)capacity
{
	self = [super init];

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

		_items = OFAllocMemory(capacity, itemSize);
		_itemSize = itemSize;
		_capacity = capacity;
		_freeWhenDone = true;
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (instancetype)initWithItemsNoCopy: (void *)items
			      count: (size_t)count
			   itemSize: (size_t)itemSize
		       freeWhenDone: (bool)freeWhenDone
{
	self = [self initWithItems: items count: count itemSize: itemSize];

	if (freeWhenDone)
		OFFreeMemory(items);

	return self;
}

- (void *)mutableItems
{
	return _items;
}

- (void)addItem: (const void *)item
{
	if (SIZE_MAX - _count < 1)
		@throw [OFOutOfRangeException exception];

	if (_count + 1 > _capacity) {
		_items = OFResizeMemory(_items, _count + 1, _itemSize);
		_capacity = _count + 1;
	}

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

	_count++;
}

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

	if (_count + count > _capacity) {
		_items = OFResizeMemory(_items, _count + count, _itemSize);
		_capacity = _count + count;
	}

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

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

	if (_count + count > _capacity) {
		_items = OFResizeMemory(_items, _count + count, _itemSize);
		_capacity = _count + count;
	}

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

	_count += count;
}

- (void)increaseCountBy: (size_t)count
{
	if (count > SIZE_MAX - _count)
		@throw [OFOutOfRangeException exception];

	if (_count + count > _capacity) {
		_items = OFResizeMemory(_items, _count + count, _itemSize);
		_capacity = _count + count;
	}

	memset(_items + _count * _itemSize, '\0', count * _itemSize);
	_count += count;
}

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

	memmove(_items + range.location * _itemSize,
	    _items + (range.location + range.length) * _itemSize,
	    (_count - range.location - range.length) * _itemSize);

	_count -= range.length;
	@try {
		_items = OFResizeMemory(_items, _count, _itemSize);
		_capacity = _count;
	} @catch (OFOutOfMemoryException *e) {
		/* We don't really care, as we only made it smaller */
	}
}

- (void)removeLastItem
{
	if (_count == 0)
		return;

	_count--;
	@try {
		_items = OFResizeMemory(_items, _count, _itemSize);
		_capacity = _count;
	} @catch (OFOutOfMemoryException *e) {
		/* We don't care, as we only made it smaller */
	}
}

- (void)removeAllItems
{
	OFFreeMemory(_items);
	_items = NULL;
	_count = 0;
	_capacity = 0;
}

- (void)makeImmutable
{
	if (_capacity != _count) {
		@try {
			_items = OFResizeMemory(_items, _count, _itemSize);
			_capacity = _count;
		} @catch (OFOutOfMemoryException *e) {
			/* We don't care, as we only made it smaller */
		}
	}

	object_setClass(self, [OFConcreteData class]);
}
@end

Renamed and modified src/OFMutableMapTableDictionary.h [e3ea116447] to src/OFConcreteMutableDictionary.h [8dcbf859ba].

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

OF_ASSUME_NONNULL_BEGIN

@class OFMapTable;

@interface OFMutableMapTableDictionary: OFMutableDictionary
{
	OFMapTable *_mapTable;
}
@end

OF_ASSUME_NONNULL_END

|



















|






1
2
3
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.
 */

#import "OFDictionary.h"

OF_ASSUME_NONNULL_BEGIN

@class OFMapTable;

@interface OFConcreteMutableDictionary: OFMutableDictionary
{
	OFMapTable *_mapTable;
}
@end

OF_ASSUME_NONNULL_END

Renamed and modified src/OFMutableMapTableDictionary.m [eda929d7fd] to src/OFConcreteMutableDictionary.m [26644559db].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the 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 "OFMutableMapTableDictionary.h"
#import "OFMapTable.h"
#import "OFMapTableDictionary.h"

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

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

- (void)setObject: (id)object forKey: (id)key
{
	[_mapTable setObject: object forKey: key];
}


|

















|
|
|




|


|
|







1
2
3
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.
 */

#include "config.h"

#include <string.h>

#import "OFConcreteMutableDictionary.h"
#import "OFConcreteDictionary.h"
#import "OFMapTable.h"

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

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

- (void)setObject: (id)object forKey: (id)key
{
	[_mapTable setObject: object forKey: key];
}

59
60
61
62
63
64
65
66
67
68
		    exceptionWithObject: self];
	}
}
#endif

- (void)makeImmutable
{
	object_setClass(self, [OFMapTableDictionary class]);
}
@end







|


59
60
61
62
63
64
65
66
67
68
		    exceptionWithObject: self];
	}
}
#endif

- (void)makeImmutable
{
	object_setClass(self, [OFConcreteDictionary class]);
}
@end

Renamed and modified src/OFMutableMapTableSet.h [ee94211a1c] to src/OFConcreteMutableSet.h [5acb7c2018].

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

OF_ASSUME_NONNULL_BEGIN

@class OFMapTable;

@interface OFMutableMapTableSet: OFMutableSet
{
	OFMapTable *_mapTable;
}
@end

OF_ASSUME_NONNULL_END

|



















|






1
2
3
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.
 */

#import "OFMutableSet.h"

OF_ASSUME_NONNULL_BEGIN

@class OFMapTable;

@interface OFConcreteMutableSet: OFMutableSet
{
	OFMapTable *_mapTable;
}
@end

OF_ASSUME_NONNULL_END

Renamed and modified src/OFMutableMapTableSet.m [134371a3b6] to src/OFConcreteMutableSet.m [9b530cede8].

1
2
3
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
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#import "OFMutableMapTableSet.h"
#import "OFMapTableSet.h"
#import "OFMapTable.h"

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

- (void)addObject: (id)object
{
	[_mapTable setObject: (void *)1 forKey: object];
}

- (void)removeObject: (id)object
{
	[_mapTable removeObjectForKey: object];
}

- (void)removeAllObjects
{
	[_mapTable removeAllObjects];
}

- (void)makeImmutable
{
	object_setClass(self, [OFMapTableSet class]);
}
@end

|















|
|


|


|
|



















|


1
2
3
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
/*
 * 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 "OFConcreteMutableSet.h"
#import "OFConcreteSet.h"
#import "OFMapTable.h"

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

- (void)addObject: (id)object
{
	[_mapTable setObject: (void *)1 forKey: object];
}

- (void)removeObject: (id)object
{
	[_mapTable removeObjectForKey: object];
}

- (void)removeAllObjects
{
	[_mapTable removeAllObjects];
}

- (void)makeImmutable
{
	object_setClass(self, [OFConcreteSet class]);
}
@end

Added src/OFConcreteNumber.h version [25e0843210].































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/*
 * Copyright (c) 2008-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 "OFNumber.h"

OF_ASSUME_NONNULL_BEGIN

@interface OFConcreteNumber: OFNumber
{
	union {
		double float_;
		long long signed_;
		unsigned long long unsigned_;
	} _value;
	char _typeEncoding;
}
@end

OF_ASSUME_NONNULL_END

Added src/OFConcreteNumber.m version [d9fb1574fa].























































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
/*
 * 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 "OFConcreteNumber.h"

#import "OFInvalidFormatException.h"

static bool
isUnsigned(OFNumber *number)
{
	switch (*number.objCType) {
	case 'B':
	case 'C':
	case 'S':
	case 'I':
	case 'L':
	case 'Q':
		return true;
	default:
		return false;
	}
}

static bool
isSigned(OFNumber *number)
{
	switch (*number.objCType) {
	case 'c':
	case 's':
	case 'i':
	case 'l':
	case 'q':
		return true;
	default:
		return false;
	}
}

static bool
isFloat(OFNumber *number)
{
	switch (*number.objCType) {
	case 'f':
	case 'd':
		return true;
	default:
		return false;
	}
}

@implementation OFConcreteNumber
- (instancetype)initWithBytes: (const void *)bytes
		     objCType: (const char *)objCType
{
#define CASE(type, method)				\
	if (strcmp(objCType, @encode(type)) == 0) {	\
		type value;				\
		memcpy(&value, bytes, sizeof(type));	\
		return [self method value];		\
	}

	CASE(bool, initWithBool:)
	CASE(signed char, initWithChar:)
	CASE(short, initWithShort:)
	CASE(int, initWithInt:)
	CASE(long, initWithLong:)
	CASE(long long, initWithLongLong:)
	CASE(unsigned char, initWithUnsignedChar:)
	CASE(unsigned short, initWithUnsignedShort:)
	CASE(unsigned int, initWithUnsignedInt:)
	CASE(unsigned long, initWithUnsignedLong:)
	CASE(unsigned long long, initWithUnsignedLongLong:)
	CASE(float, initWithFloat:)
	CASE(double, initWithDouble:)

	[self release];
	@throw [OFInvalidFormatException exception];
}

- (instancetype)initWithBool: (bool)value
{
	self = [super initWithBytes: &value objCType: @encode(bool)];

	_value.unsigned_ = value;
	_typeEncoding = *@encode(bool);

	return self;
}

- (instancetype)initWithChar: (signed char)value
{
	self = [super initWithBytes: &value objCType: @encode(signed char)];

	_value.signed_ = value;
	_typeEncoding = *@encode(signed char);

	return self;
}

- (instancetype)initWithShort: (short)value
{
	self = [super initWithBytes: &value objCType: @encode(short)];

	_value.signed_ = value;
	_typeEncoding = *@encode(short);

	return self;
}

- (instancetype)initWithInt: (int)value
{
	self = [super initWithBytes: &value objCType: @encode(int)];

	_value.signed_ = value;
	_typeEncoding = *@encode(int);

	return self;
}

- (instancetype)initWithLong: (long)value
{
	self = [super initWithBytes: &value objCType: @encode(long)];

	_value.signed_ = value;
	_typeEncoding = *@encode(long);

	return self;
}

- (instancetype)initWithLongLong: (long long)value
{
	self = [super initWithBytes: &value objCType: @encode(long long)];

	_value.signed_ = value;
	_typeEncoding = *@encode(long long);

	return self;
}

- (instancetype)initWithUnsignedChar: (unsigned char)value
{
	self = [super initWithBytes: &value objCType: @encode(unsigned char)];

	_value.unsigned_ = value;
	_typeEncoding = *@encode(unsigned long);

	return self;
}

- (instancetype)initWithUnsignedShort: (unsigned short)value
{
	self = [super initWithBytes: &value objCType: @encode(unsigned short)];

	_value.unsigned_ = value;
	_typeEncoding = *@encode(unsigned short);

	return self;
}

- (instancetype)initWithUnsignedInt: (unsigned int)value
{
	self = [super initWithBytes: &value objCType: @encode(unsigned int)];

	_value.unsigned_ = value;
	_typeEncoding = *@encode(unsigned int);

	return self;
}

- (instancetype)initWithUnsignedLong: (unsigned long)value
{
	self = [super initWithBytes: &value objCType: @encode(unsigned long)];

	_value.unsigned_ = value;
	_typeEncoding = *@encode(unsigned long);

	return self;
}

- (instancetype)initWithUnsignedLongLong: (unsigned long long)value
{
	self = [super initWithBytes: &value
			   objCType: @encode(unsigned long long)];

	_value.unsigned_ = value;
	_typeEncoding = *@encode(unsigned long long);

	return self;
}

- (instancetype)initWithFloat: (float)value
{
	self = [super initWithBytes: &value objCType: @encode(float)];

	_value.float_ = value;
	_typeEncoding = *@encode(float);

	return self;
}

- (instancetype)initWithDouble: (double)value
{
	self = [super initWithBytes: &value objCType: @encode(double)];

	_value.float_ = value;
	_typeEncoding = *@encode(double);

	return self;
}

- (const char *)objCType
{
	return &_typeEncoding;
}

- (long long)longLongValue
{
	if (isFloat(self))
		return _value.float_;
	else if (isSigned(self))
		return _value.signed_;
	else if (isUnsigned(self))
		return _value.unsigned_;
	else
		@throw [OFInvalidFormatException exception];
}

- (unsigned long long)unsignedLongLongValue
{
	if (isFloat(self))
		return _value.float_;
	else if (isSigned(self))
		return _value.signed_;
	else if (isUnsigned(self))
		return _value.unsigned_;
	else
		@throw [OFInvalidFormatException exception];
}

- (double)doubleValue
{
	if (isFloat(self))
		return _value.float_;
	else if (isSigned(self))
		return _value.signed_;
	else if (isUnsigned(self))
		return _value.unsigned_;
	else
		@throw [OFInvalidFormatException exception];
}
@end

Renamed and modified src/OFMapTableSet.h [1664d9d036] to src/OFConcreteSet.h [f15a7439bb].

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

OF_ASSUME_NONNULL_BEGIN

@class OFMapTable;

@interface OFMapTableSet: OFSet
{
	OFMapTable *_mapTable;
}

- (instancetype)initWithCapacity: (size_t)capacity;
@end

OF_ASSUME_NONNULL_END

|



















|








1
2
3
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.
 */

#import "OFSet.h"

OF_ASSUME_NONNULL_BEGIN

@class OFMapTable;

@interface OFConcreteSet: OFSet
{
	OFMapTable *_mapTable;
}

- (instancetype)initWithCapacity: (size_t)capacity;
@end

OF_ASSUME_NONNULL_END

Renamed and modified src/OFMapTableSet.m [87bc750df2] to src/OFConcreteSet.m [10d5322a55].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the 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 "OFMapTableSet.h"
#import "OFArray.h"
#import "OFCountedMapTableSet.h"
#import "OFMapTable.h"
#import "OFMapTable+Private.h"
#import "OFMutableMapTableSet.h"
#import "OFString.h"
#import "OFXMLElement.h"

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

static void *
retain(void *object)
{

|















|

|
|

|

<







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

25
26
27
28
29
30
31
/*
 * Copyright (c) 2008-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 "OFConcreteSet.h"
#import "OFArray.h"
#import "OFConcreteCountedSet.h"
#import "OFConcreteMutableSet.h"
#import "OFMapTable+Private.h"
#import "OFMapTable.h"
#import "OFString.h"


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

static void *
retain(void *object)
{
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
	.retain = retain,
	.release = release,
	.hash = hash,
	.equal = equal
};
static const OFMapTableFunctions objectFunctions = { NULL };

@implementation OFMapTableSet
- (instancetype)init
{
	return [self initWithCapacity: 0];
}

- (instancetype)initWithCapacity: (size_t)capacity
{







|







54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
	.retain = retain,
	.release = release,
	.hash = hash,
	.equal = equal
};
static const OFMapTableFunctions objectFunctions = { NULL };

@implementation OFConcreteSet
- (instancetype)init
{
	return [self initWithCapacity: 0];
}

- (instancetype)initWithCapacity: (size_t)capacity
{
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
		[self release];
		@throw e;
	}

	return self;
}

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

	@try {
		void *pool = objc_autoreleasePoolPush();

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

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

			[_mapTable setObject: (void *)1
				      forKey: [child objectByDeserializing]];

			objc_autoreleasePoolPop(pool2);
		}

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

	return self;
}

- (void)dealloc
{
	[_mapTable release];

	[super dealloc];
}








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







176
177
178
179
180
181
182































183
184
185
186
187
188
189
		[self release];
		@throw e;
	}

	return self;
}
































- (void)dealloc
{
	[_mapTable release];

	[super dealloc];
}

230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
		return false;

	return ([_mapTable objectForKey: object] != nil);
}

- (bool)isEqual: (id)object
{
	OFMapTableSet *set;

	if (object == self)
		return true;

	if (![object isKindOfClass: [OFMapTableSet class]] &&
	    ![object isKindOfClass: [OFMutableMapTableSet class]] &&
	    ![object isKindOfClass: [OFCountedMapTableSet class]])
		return [super isEqual: object];

	set = object;

	return [set->_mapTable isEqual: _mapTable];
}








|




|
|
|







198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
		return false;

	return ([_mapTable objectForKey: object] != nil);
}

- (bool)isEqual: (id)object
{
	OFConcreteSet *set;

	if (object == self)
		return true;

	if (![object isKindOfClass: [OFConcreteSet class]] &&
	    ![object isKindOfClass: [OFConcreteMutableSet class]] &&
	    ![object isKindOfClass: [OFConcreteCountedSet class]])
		return [super isEqual: object];

	set = object;

	return [set->_mapTable isEqual: _mapTable];
}

Renamed and modified src/OFAdjacentSubarray.h [08f4f942e1] to src/OFConcreteSubarray.h [1bb50129fd].

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

OF_ASSUME_NONNULL_BEGIN

@interface OFAdjacentSubarray: OFSubarray
@end

OF_ASSUME_NONNULL_END

|

















|



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 "OFSubarray.h"

OF_ASSUME_NONNULL_BEGIN

@interface OFConcreteSubarray: OFSubarray
@end

OF_ASSUME_NONNULL_END

Renamed and modified src/OFAdjacentSubarray.m [76d5c349a9] to src/OFConcreteSubarray.m [b6d3c2386d].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the 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 "OFAdjacentSubarray.h"
#import "OFAdjacentArray.h"
#import "OFMutableAdjacentArray.h"

@implementation OFAdjacentSubarray
- (const id *)objects
{
	return _array.objects + _range.location;
}

- (bool)isEqual: (id)object
{
	OFArray *otherArray;
	id const *objects, *otherObjects;

	if (object == self)
		return true;

	if (![object isKindOfClass: [OFAdjacentArray class]] &&
	    ![object isKindOfClass: [OFMutableAdjacentArray class]])
		return [super isEqual: object];

	otherArray = object;

	if (_range.length != otherArray.count)
		return false;


|















|
|
|

|













|
|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
/*
 * Copyright (c) 2008-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 "OFConcreteSubarray.h"
#import "OFConcreteArray.h"
#import "OFConcreteMutableArray.h"

@implementation OFConcreteSubarray
- (const id *)objects
{
	return _array.objects + _range.location;
}

- (bool)isEqual: (id)object
{
	OFArray *otherArray;
	id const *objects, *otherObjects;

	if (object == self)
		return true;

	if (![object isKindOfClass: [OFConcreteArray class]] &&
	    ![object isKindOfClass: [OFConcreteMutableArray class]])
		return [super isEqual: object];

	otherArray = object;

	if (_range.length != otherArray.count)
		return false;

Renamed and modified src/OFBytesValue.h [ca1dbf0669] to src/OFConcreteValue.h [5cdb4976fe].

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

OF_ASSUME_NONNULL_BEGIN

@interface OFBytesValue: OFValue
{
	size_t _size;
	void *_bytes;
	const char *_objCType;
}
@end

OF_ASSUME_NONNULL_END

|

















|



|




1
2
3
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.
 */

#import "OFValue.h"

OF_ASSUME_NONNULL_BEGIN

@interface OFConcreteValue: OFValue
{
	size_t _size;
	void *_bytes;
	char *_objCType;
}
@end

OF_ASSUME_NONNULL_END

Renamed and modified src/OFBytesValue.m [b331442837] to src/OFConcreteValue.m [c41994aa1b].

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

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

46
47
48





49
50
51
52
53
54
55
56
57
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the 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 "OFBytesValue.h"
#import "OFMethodSignature.h"


#import "OFOutOfRangeException.h"

@implementation OFBytesValue
@synthesize objCType = _objCType;

- (instancetype)initWithBytes: (const void *)bytes
		     objCType: (const char *)objCType
{
	self = [super init];

	@try {
		_size = OFSizeOfTypeEncoding(objCType);
		_objCType = objCType;
		_bytes = OFAllocMemory(1, _size);

		memcpy(_bytes, bytes, _size);
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (void)dealloc
{
	OFFreeMemory(_bytes);


	[super dealloc];
}






- (void)getValue: (void *)value size: (size_t)size
{
	if (size != _size)
		@throw [OFOutOfRangeException exception];

	memcpy(value, _bytes, _size);
}
@end

|













|

>



|
<
<



|



|

<












>



>
>
>
>
>









1
2
3
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.
 */

#import "OFConcreteValue.h"
#import "OFMethodSignature.h"
#import "OFString.h"

#import "OFOutOfRangeException.h"

@implementation OFConcreteValue


- (instancetype)initWithBytes: (const void *)bytes
		     objCType: (const char *)objCType
{
	self = [super initWithBytes: bytes objCType: objCType];

	@try {
		_size = OFSizeOfTypeEncoding(objCType);
		_objCType = OFStrDup(objCType);
		_bytes = OFAllocMemory(1, _size);

		memcpy(_bytes, bytes, _size);
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (void)dealloc
{
	OFFreeMemory(_bytes);
	OFFreeMemory(_objCType);

	[super dealloc];
}

- (const char *)objCType
{
	return _objCType;
}

- (void)getValue: (void *)value size: (size_t)size
{
	if (size != _size)
		@throw [OFOutOfRangeException exception];

	memcpy(value, _bytes, _size);
}
@end

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

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
 * @note Waiting might have been interrupted by a signal. It is thus recommended
 *	 to check the condition again after @ref wait returned!
 *
 * @throw OFWaitForConditionFailedException Waiting for the condition failed
 */
- (void)wait;

#ifdef OF_AMIGAOS
/**
 * @brief Blocks the current thread until another thread calls @ref signal,
 *	  @ref broadcast or an Exec Signal is received.
 *
 * @note This is only available on AmigaOS!
 *
 * @param signalMask A pointer to a signal mask of Exec Signals to receive.







|







46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
 * @note Waiting might have been interrupted by a signal. It is thus recommended
 *	 to check the condition again after @ref wait returned!
 *
 * @throw OFWaitForConditionFailedException Waiting for the condition failed
 */
- (void)wait;

#if defined(OF_AMIGAOS) || defined(DOXYGEN)
/**
 * @brief Blocks the current thread until another thread calls @ref signal,
 *	  @ref broadcast or an Exec Signal is received.
 *
 * @note This is only available on AmigaOS!
 *
 * @param signalMask A pointer to a signal mask of Exec Signals to receive.
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
 *
 * @param timeInterval The time interval until the timeout is reached
 * @return Whether the condition has been signaled
 * @throw OFWaitForConditionFailedException Waiting for the condition failed
 */
- (bool)waitForTimeInterval: (OFTimeInterval)timeInterval;

#ifdef OF_AMIGAOS
/**
 * @brief Blocks the current thread until another thread calls @ref signal,
 *	  @ref broadcast, the timeout is reached or an Exec Signal is received.
 *
 * @note This is only available on AmigaOS!
 *
 * @param timeInterval The time interval until the timeout is reached







|







73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
 *
 * @param timeInterval The time interval until the timeout is reached
 * @return Whether the condition has been signaled
 * @throw OFWaitForConditionFailedException Waiting for the condition failed
 */
- (bool)waitForTimeInterval: (OFTimeInterval)timeInterval;

#if defined(OF_AMIGAOS) || defined(DOXYGEN)
/**
 * @brief Blocks the current thread until another thread calls @ref signal,
 *	  @ref broadcast, the timeout is reached or an Exec Signal is received.
 *
 * @note This is only available on AmigaOS!
 *
 * @param timeInterval The time interval until the timeout is reached
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
 *
 * @param date The date at which the timeout is reached
 * @return Whether the condition has been signaled
 * @throw OFWaitForConditionFailedException Waiting for the condition failed
 */
- (bool)waitUntilDate: (OFDate *)date;

#ifdef OF_AMIGAOS
/**
 * @brief Blocks the current thread until another thread calls @ref signal,
 *	  @ref broadcast, the timeout is reached or an Exec Signal is received.
 *
 * @note This is only available on AmigaOS!
 *
 * @param date The date at which the timeout is reached







|







103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
 *
 * @param date The date at which the timeout is reached
 * @return Whether the condition has been signaled
 * @throw OFWaitForConditionFailedException Waiting for the condition failed
 */
- (bool)waitUntilDate: (OFDate *)date;

#if defined(OF_AMIGAOS) || defined(DOXYGEN)
/**
 * @brief Blocks the current thread until another thread calls @ref signal,
 *	  @ref broadcast, the timeout is reached or an Exec Signal is received.
 *
 * @note This is only available on AmigaOS!
 *
 * @param date The date at which the timeout is reached

Modified src/OFCondition.m from [6291bb097b] to [be26e530b5].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

22
23
24
25
26
27
28
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#include <errno.h>

#import "OFCondition.h"
#import "OFDate.h"


#import "OFBroadcastConditionFailedException.h"
#import "OFConditionStillWaitingException.h"
#import "OFInitializationFailedException.h"
#import "OFSignalConditionFailedException.h"
#import "OFWaitForConditionFailedException.h"


|



















>







1
2
3
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.
 */

#include "config.h"

#include <errno.h>

#import "OFCondition.h"
#import "OFDate.h"
#import "OFString.h"

#import "OFBroadcastConditionFailedException.h"
#import "OFConditionStillWaitingException.h"
#import "OFInitializationFailedException.h"
#import "OFSignalConditionFailedException.h"
#import "OFWaitForConditionFailedException.h"

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

1
2
3
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
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#ifndef OBJFW_OF_CONSTANT_STRING_H
#define OBJFW_OF_CONSTANT_STRING_H

#include "OFString.h"

OF_ASSUME_NONNULL_BEGIN

#if !defined(OF_CONSTANT_STRING_M) && \
    defined(OF_APPLE_RUNTIME) && !defined(__OBJC2__)
# ifdef __cplusplus
extern "C" {
# endif
extern void *_OFConstantStringClassReference;
# ifdef __cplusplus
}
# endif
#endif

#ifdef __OBJC__
/**
 * @class OFConstantString OFConstantString.h ObjFW/OFConstantString.h
 *
 * @brief A class for storing constant strings using the `@""` literal.
 */
OF_SUBCLASSING_RESTRICTED
@interface OFConstantString: OFString
{
	char *_cString;
	unsigned int _cStringLength;
}
@end
#endif

OF_ASSUME_NONNULL_END

#endif

|













<
<
<
|














<












<


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



16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

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

43
44


/*
 * Copyright (c) 2008-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 "OFString.h"

OF_ASSUME_NONNULL_BEGIN

#if !defined(OF_CONSTANT_STRING_M) && \
    defined(OF_APPLE_RUNTIME) && !defined(__OBJC2__)
# ifdef __cplusplus
extern "C" {
# endif
extern void *_OFConstantStringClassReference;
# ifdef __cplusplus
}
# endif
#endif


/**
 * @class OFConstantString OFConstantString.h ObjFW/OFConstantString.h
 *
 * @brief A class for storing constant strings using the `@""` literal.
 */
OF_SUBCLASSING_RESTRICTED
@interface OFConstantString: OFString
{
	char *_cString;
	unsigned int _cStringLength;
}
@end


OF_ASSUME_NONNULL_END


Modified src/OFConstantString.m from [3adc07df05] to [745f0950c3].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
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

@implementation OFConstantUTF8String
+ (instancetype)alloc
{
	OF_UNRECOGNIZED_SELECTOR
}

- (instancetype)retain
{
	return self;
}

- (instancetype)autorelease
{
	return self;
}

- (unsigned int)retainCount
{
	return OFMaxRetainCount;
}

- (void)release
{
}

- (void)dealloc
{
	OF_DEALLOC_UNSUPPORTED
}
@end

@implementation OFConstantString
+ (void)load
{
#if defined(OF_APPLE_RUNTIME) && !defined(__OBJC2__)
	/*







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







48
49
50
51
52
53
54




55


















56
57
58
59
60
61
62

@implementation OFConstantUTF8String
+ (instancetype)alloc
{
	OF_UNRECOGNIZED_SELECTOR
}





OF_SINGLETON_METHODS


















@end

@implementation OFConstantString
+ (void)load
{
#if defined(OF_APPLE_RUNTIME) && !defined(__OBJC2__)
	/*
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
}

+ (instancetype)alloc
{
	OF_UNRECOGNIZED_SELECTOR
}

- (instancetype)retain
{
	return self;
}

- (instancetype)autorelease
{
	return self;
}

- (unsigned int)retainCount
{
	return OFMaxRetainCount;
}

- (void)release
{
}

- (void)dealloc
{
	OF_DEALLOC_UNSUPPORTED
}

/*
 * In all following methods, the constant string is converted to an
 * OFConstantUTF8String and the message sent again.
 */

/* From protocol OFCopying */







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







109
110
111
112
113
114
115




116


















117
118
119
120
121
122
123
}

+ (instancetype)alloc
{
	OF_UNRECOGNIZED_SELECTOR
}





OF_SINGLETON_METHODS



















/*
 * In all following methods, the constant string is converted to an
 * OFConstantUTF8String and the message sent again.
 */

/* From protocol OFCopying */
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

- (OFData *)dataWithEncoding: (OFStringEncoding)encoding
{
	[self finishInitialization];
	return [self dataWithEncoding: encoding];
}

#ifdef OF_HAVE_UNICODE_TABLES
- (OFString *)decomposedStringWithCanonicalMapping
{
	[self finishInitialization];
	return self.decomposedStringWithCanonicalMapping;
}

- (OFString *)decomposedStringWithCompatibilityMapping
{
	[self finishInitialization];
	return self.decomposedStringWithCompatibilityMapping;
}
#endif

#ifdef OF_WINDOWS
- (OFString *)stringByExpandingWindowsEnvironmentStrings
{
	[self finishInitialization];
	return self.stringByExpandingWindowsEnvironmentStrings;
}
#endif







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







501
502
503
504
505
506
507














508
509
510
511
512
513
514

- (OFData *)dataWithEncoding: (OFStringEncoding)encoding
{
	[self finishInitialization];
	return [self dataWithEncoding: encoding];
}















#ifdef OF_WINDOWS
- (OFString *)stringByExpandingWindowsEnvironmentStrings
{
	[self finishInitialization];
	return self.stringByExpandingWindowsEnvironmentStrings;
}
#endif
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
- (void)writeToFile: (OFString *)path encoding: (OFStringEncoding)encoding
{
	[self finishInitialization];
	[self writeToFile: path encoding: encoding];
}
#endif

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

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

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







|


|


|


|










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
- (void)writeToFile: (OFString *)path encoding: (OFStringEncoding)encoding
{
	[self finishInitialization];
	[self writeToFile: path encoding: encoding];
}
#endif

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

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

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

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

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

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

1
2
3
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-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#include <stdlib.h>

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

static struct {
	Class isa;
} placeholder;

@interface OFCountedSetPlaceholder: OFCountedSet
@end

@implementation OFCountedSetPlaceholder






- (instancetype)init
{
	return (id)[[OFCountedMapTableSet alloc] init];
}

- (instancetype)initWithSet: (OFSet *)set
{
	return (id)[[OFCountedMapTableSet alloc] initWithSet: set];
}

- (instancetype)initWithArray: (OFArray *)array
{
	return (id)[[OFCountedMapTableSet alloc] initWithArray: array];
}

- (instancetype)initWithObjects: (id)firstObject, ...
{
	id ret;
	va_list arguments;

	va_start(arguments, firstObject);
	ret = [[OFCountedMapTableSet alloc] initWithObject: firstObject
						 arguments: arguments];
	va_end(arguments);

	return ret;
}

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

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

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

- (instancetype)retain
{
	return self;
}

- (instancetype)autorelease
{
	return self;
}

- (void)release
{
}

- (void)dealloc
{
	OF_DEALLOC_UNSUPPORTED
}
@end

@implementation OFCountedSet
+ (void)initialize
{
	if (self == [OFCountedSet class])
		placeholder.isa = [OFCountedSetPlaceholder class];

}

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

	return [super alloc];
}

- (instancetype)init
{
	if ([self isMemberOfClass: [OFCountedSet class]]) {
		@try {
			[self doesNotRecognizeSelector: _cmd];
		} @catch (id e) {
			[self release];
			@throw e;
		}

		abort();
	}

	return [super init];
}

- (size_t)countForObject: (id)object
{
	OF_UNRECOGNIZED_SELECTOR
}

- (OFString *)description
{

|


















|


<





|


|
>
>
>
>
>
>


|




|




|








|








|





|


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






|
>










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







1
2
3
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
/*
 * 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 <stdlib.h>

#import "OFCountedSet.h"
#import "OFConcreteCountedSet.h"
#import "OFNumber.h"
#import "OFString.h"


static struct {
	Class isa;
} placeholder;

@interface OFPlaceholderCountedSet: OFCountedSet
@end

@implementation OFPlaceholderCountedSet
#ifdef __clang__
/* We intentionally don't call into super, so silence the warning. */
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wunknown-pragmas"
# pragma clang diagnostic ignored "-Wobjc-designated-initializers"
#endif
- (instancetype)init
{
	return (id)[[OFConcreteCountedSet alloc] init];
}

- (instancetype)initWithSet: (OFSet *)set
{
	return (id)[[OFConcreteCountedSet alloc] initWithSet: set];
}

- (instancetype)initWithArray: (OFArray *)array
{
	return (id)[[OFConcreteCountedSet alloc] initWithArray: array];
}

- (instancetype)initWithObjects: (id)firstObject, ...
{
	id ret;
	va_list arguments;

	va_start(arguments, firstObject);
	ret = [[OFConcreteCountedSet alloc] initWithObject: firstObject
						 arguments: arguments];
	va_end(arguments);

	return ret;
}

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

- (instancetype)initWithObject: (id)firstObject arguments: (va_list)arguments
{
	return (id)[[OFConcreteCountedSet alloc] initWithObject: firstObject
						      arguments: arguments];
}
#ifdef __clang__





# pragma clang diagnostic pop




#endif




OF_SINGLETON_METHODS








@end

@implementation OFCountedSet
+ (void)initialize
{
	if (self == [OFCountedSet class])
		object_setClass((id)&placeholder,
		    [OFPlaceholderCountedSet class]);
}

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

	return [super alloc];
}

















- (size_t)countForObject: (id)object
{
	OF_UNRECOGNIZED_SELECTOR
}

- (OFString *)description
{
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
}

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

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

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

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

		OFXMLElement *objectElement;
		OFString *count;

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

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

		objc_autoreleasePoolPop(pool2);
	}

	[element retain];

	objc_autoreleasePoolPop(pool);

	return [element autorelease];
}

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







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







143
144
145
146
147
148
149




































150
151
152
153
154
155
156
}

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





































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

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

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

21
22
23
24
25
26
27
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#import "OFDatagramSocket.h"

OF_ASSUME_NONNULL_BEGIN

@class OFString;


/**
 * @protocol OFDDPSocketDelegate OFDDPSocket.h ObjFW/OFDDPSocket.h
 *
 * @brief A delegate for OFDDPSocket.
 */
@protocol OFDDPSocketDelegate <OFDatagramSocketDelegate>

|


















>







1
2
3
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.
 */

#import "OFDatagramSocket.h"

OF_ASSUME_NONNULL_BEGIN

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

/**
 * @protocol OFDDPSocketDelegate OFDDPSocket.h ObjFW/OFDDPSocket.h
 *
 * @brief A delegate for OFDDPSocket.
 */
@protocol OFDDPSocketDelegate <OFDatagramSocketDelegate>
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
 * @ref OFSocketAddressAppleTalkNode to get the AppleTalk node and
 * @ref OFSocketAddressAppleTalkPort to get the port (sometimes also called
 * socket number).
 *
 * @note On some systems, packets received with the wrong protocol type just
 *	 get filtered by the kernel, however, on other systems, the packet is
 *	 queued up and will raise an @ref OFReadFailedException with the
 *	 @ref errNo set to `ENOMSG` when being received.
 *
 * @warning Even though the OFCopying protocol is implemented, it does *not*
 *	    return an independent copy of the socket, but instead retains it.
 *	    This is so that the socket can be used as a key for a dictionary,
 *	    so context can be associated with a socket. Using a socket in more
 *	    than one thread at the same time is not thread-safe, even if copy
 *	    was called to create one "instance" for every thread!







|







40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
 * @ref OFSocketAddressAppleTalkNode to get the AppleTalk node and
 * @ref OFSocketAddressAppleTalkPort to get the port (sometimes also called
 * socket number).
 *
 * @note On some systems, packets received with the wrong protocol type just
 *	 get filtered by the kernel, however, on other systems, the packet is
 *	 queued up and will raise an @ref OFReadFailedException with the
 *	 @ref OFReadFailedException#errNo set to `ENOMSG` when being received.
 *
 * @warning Even though the OFCopying protocol is implemented, it does *not*
 *	    return an independent copy of the socket, but instead retains it.
 *	    This is so that the socket can be used as a key for a dictionary,
 *	    so context can be associated with a socket. Using a socket in more
 *	    than one thread at the same time is not thread-safe, even if copy
 *	    was called to create one "instance" for every thread!
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
 * @param port The port to bind to. 0 means to pick one and return it via the
 *	       returned socket address.
 * @param protocolType The DDP protocol type to use. Must not be 0. If you want
 *		       to use DDP directly and not a protocol built on top of
 *		       it, use 11 for compatibility with Open Transport.
 * @return The address on which this socket can be reached
 * @throw OFBindDDPSockeFailedException Binding failed
 * @throw OFAlreadyConnectedException The socket is already bound
 */
- (OFSocketAddress)bindToNetwork: (uint16_t)network
			    node: (uint8_t)node
			    port: (uint8_t)port
		    protocolType: (uint8_t)protocolType;
@end

OF_ASSUME_NONNULL_END







|








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

OF_ASSUME_NONNULL_END

Modified src/OFDDPSocket.m from [d532fdd70f] to [eb08afcb9b].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
18
19
20
21
22
23
24



25
26
27
28
29

30
31

32

33







34
35
36
37
38
39
40
#include <errno.h>

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

#import "OFDDPSocket.h"



#import "OFSocket.h"
#import "OFSocket+Private.h"

#import "OFAlreadyConnectedException.h"
#import "OFBindDDPSocketFailedException.h"

#import "OFInvalidArgumentException.h"
#import "OFNotOpenException.h"

#import "OFReadFailedException.h"

#import "OFWriteFailedException.h"








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

/* Unfortulately, there is no struct for the following in userland headers */
struct ATInterfaceConfig {







>
>
>



|

>


>

>

>
>
>
>
>
>
>







18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#include <errno.h>

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

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

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

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

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

/* Unfortulately, there is no struct for the following in userland headers */
struct ATInterfaceConfig {
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
	int flags;
#endif

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

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

	address = OFSocketAddressMakeAppleTalk(network, node, port);

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







|







76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
	int flags;
#endif

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

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

	address = OFSocketAddressMakeAppleTalk(network, node, port);

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

Modified src/OFDNSQuery.h from [b49f52a5a4] to [6f603e03bb].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFDNSQuery.m from [eb5858939c] to [68023ab95d].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

	@try {
		void *pool = objc_autoreleasePoolPush();

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

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

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







|







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

	@try {
		void *pool = objc_autoreleasePoolPush();

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

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

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

Modified src/OFDNSResolver.h from [a91104c174] to [ba43b85159].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
26
27
28
29
30
31
32

33
34

35
36
37
38
39
40
41

@class OFArray OF_GENERIC(ObjectType);
@class OFDNSResolver;
@class OFDNSResolverContext;
@class OFDNSResolverSettings;
@class OFDate;
@class OFDictionary OF_GENERIC(KeyType, ObjectType);

@class OFMutableDictionary OF_GENERIC(KeyType, ObjectType);
@class OFNumber;

@class OFTCPSocket;
@class OFUDPSocket;

/**
 * @enum OFDNSResolverErrorCode OFDNSResolver.h ObjFW/OFDNSResolver.h
 *
 * @brief An enum describing why resolving a host failed.







>


>







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

@class OFArray OF_GENERIC(ObjectType);
@class OFDNSResolver;
@class OFDNSResolverContext;
@class OFDNSResolverSettings;
@class OFDate;
@class OFDictionary OF_GENERIC(KeyType, ObjectType);
@class OFMutableArray OF_GENERIC(ObjectType);
@class OFMutableDictionary OF_GENERIC(KeyType, ObjectType);
@class OFNumber;
@class OFPair OF_GENERIC(FirstType, SecondType);
@class OFTCPSocket;
@class OFUDPSocket;

/**
 * @enum OFDNSResolverErrorCode OFDNSResolver.h ObjFW/OFDNSResolver.h
 *
 * @brief An enum describing why resolving a host failed.
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
	OFUDPSocket *_IPv6Socket;
#endif
	char _buffer[OFDNSResolverBufferLength];
	OFMutableDictionary OF_GENERIC(OFNumber *, OFDNSResolverContext *)
	    *_queries;
	OFMutableDictionary OF_GENERIC(OFTCPSocket *, OFDNSResolverContext *)
	    *_TCPQueries;




}

/**
 * @brief A dictionary of static hosts.
 *
 * This dictionary is checked before actually looking up a host.




 */
@property (copy, nonatomic) OFDictionary OF_GENERIC(OFString *,
    OFArray OF_GENERIC(OFString *) *) *staticHosts;

/**
 * @brief An array of name servers to use.
 *
 * The name servers are tried in order.




 */
@property (copy, nonatomic) OFArray OF_GENERIC(OFString *) *nameServers;

/**
 * @brief The local domain.
 */
@property OF_NULLABLE_PROPERTY (readonly, nonatomic) OFString *localDomain;

/**
 * @brief The domains to search for queries for short names.




 */
@property (copy, nonatomic) OFArray OF_GENERIC(OFString *) *searchDomains;

/**
 * @brief The timeout, in seconds, after which the next name server should be
 *	  tried.




 */
@property (nonatomic) OFTimeInterval timeout;

/**
 * @brief The number of attempts before giving up to resolve a host.
 *
 * Trying all name servers once is considered a single attempt.




 */
@property (nonatomic) unsigned int maxAttempts;

/**
 * @brief The minimum number of dots for a name to be considered absolute.




 */
@property (nonatomic) unsigned int minNumberOfDotsInAbsoluteName;

/**
 * @brief Whether the resolver uses TCP to talk to a name server.




 */
@property (nonatomic) bool usesTCP;

/**
 * @brief The interval in seconds in which the config should be reloaded.
 *
 * Setting this to 0 disables config reloading.




 */
@property (nonatomic) OFTimeInterval configReloadInterval;

/**
 * @brief Creates a new, autoreleased OFDNSResolver.
 */
+ (instancetype)resolver;







>
>
>
>






>
>
>
>








>
>
>
>










>
>
>
>






>
>
>
>







>
>
>
>





>
>
>
>




|
>
>
>
>

|





>
>
>
>







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
	OFUDPSocket *_IPv6Socket;
#endif
	char _buffer[OFDNSResolverBufferLength];
	OFMutableDictionary OF_GENERIC(OFNumber *, OFDNSResolverContext *)
	    *_queries;
	OFMutableDictionary OF_GENERIC(OFTCPSocket *, OFDNSResolverContext *)
	    *_TCPQueries;
	OFMutableDictionary OF_GENERIC(OFDNSQuery *,
	    OFPair OF_GENERIC(OFDate *, OFDNSResponse *) *) *_cache;
	OFMutableArray OF_GENERIC(OFString *) *_lastNameServers;
	OFTimeInterval _lastCacheCleanup;
}

/**
 * @brief A dictionary of static hosts.
 *
 * This dictionary is checked before actually looking up a host.
 *
 * @warning If you change this, you need to set @ref configReloadInterval to 0
 *	    to disable reloading the config after some time. If you don't, the
 *	    config will be reloaded and your change overridden.
 */
@property (copy, nonatomic) OFDictionary OF_GENERIC(OFString *,
    OFArray OF_GENERIC(OFString *) *) *staticHosts;

/**
 * @brief An array of name servers to use.
 *
 * The name servers are tried in order.
 *
 * @warning If you change this, you need to set @ref configReloadInterval to 0
 *	    to disable reloading the config after some time. If you don't, the
 *	    config will be reloaded and your change overridden.
 */
@property (copy, nonatomic) OFArray OF_GENERIC(OFString *) *nameServers;

/**
 * @brief The local domain.
 */
@property OF_NULLABLE_PROPERTY (readonly, nonatomic) OFString *localDomain;

/**
 * @brief The domains to search for queries for short names.
 *
 * @warning If you change this, you need to set @ref configReloadInterval to 0
 *	    to disable reloading the config after some time. If you don't, the
 *	    config will be reloaded and your change overridden.
 */
@property (copy, nonatomic) OFArray OF_GENERIC(OFString *) *searchDomains;

/**
 * @brief The timeout, in seconds, after which the next name server should be
 *	  tried.
 *
 * @warning If you change this, you need to set @ref configReloadInterval to 0
 *	    to disable reloading the config after some time. If you don't, the
 *	    config will be reloaded and your change overridden.
 */
@property (nonatomic) OFTimeInterval timeout;

/**
 * @brief The number of attempts before giving up to resolve a host.
 *
 * Trying all name servers once is considered a single attempt.
 *
 * @warning If you change this, you need to set @ref configReloadInterval to 0
 *	    to disable reloading the config after some time. If you don't, the
 *	    config will be reloaded and your change overridden.
 */
@property (nonatomic) unsigned int maxAttempts;

/**
 * @brief The minimum number of dots for a name to be considered absolute.
 *
 * @warning If you change this, you need to set @ref configReloadInterval to 0
 *	    to disable reloading the config after some time. If you don't, the
 *	    config will be reloaded and your change overridden.
 */
@property (nonatomic) unsigned int minNumberOfDotsInAbsoluteName;

/**
 * @brief Whether the resolver forces TCP to talk to a name server.
 *
 * @warning If you change this, you need to set @ref configReloadInterval to 0
 *	    to disable reloading the config after some time. If you don't, the
 *	    config will be reloaded and your change overridden.
 */
@property (nonatomic) bool forcesTCP;

/**
 * @brief The interval in seconds in which the config should be reloaded.
 *
 * Setting this to 0 disables config reloading.
 *
 * @warning If you change this to anything other than 0, the config will be
 *	    reloaded eventually, which in turn can override the config
 *	    reloading interval itself again.
 */
@property (nonatomic) OFTimeInterval configReloadInterval;

/**
 * @brief Creates a new, autoreleased OFDNSResolver.
 */
+ (instancetype)resolver;

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

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
{
	OFMutableDictionary *ret = [OFMutableDictionary dictionary];
	OFEnumerator OF_GENERIC(OFMutableArray *) *objectEnumerator;
	OFMutableArray *array;

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

		if (*i + 10 > length)







|







419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
{
	OFMutableDictionary *ret = [OFMutableDictionary dictionary];
	OFEnumerator OF_GENERIC(OFMutableArray *) *objectEnumerator;
	OFMutableArray *array;

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

		if (*i + 10 > length)
462
463
464
465
466
467
468














469
470
471
472
473
474
475
	while ((array = [objectEnumerator nextObject]) != nil)
		[array makeImmutable];

	[ret makeImmutable];

	return ret;
}















@implementation OFDNSResolverContext
- (instancetype)initWithQuery: (OFDNSQuery *)query
			   ID: (OFNumber *)ID
		     settings: (OFDNSResolverSettings *)settings
		     delegate: (id <OFDNSResolverQueryDelegate>)delegate
{







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







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
	while ((array = [objectEnumerator nextObject]) != nil)
		[array makeImmutable];

	[ret makeImmutable];

	return ret;
}

static bool
containsExpiredRecord(OFDNSResponseRecords responseRecords, uint32_t age)
{
	OFEnumerator *enumerator = [responseRecords objectEnumerator];
	OFArray OF_GENERIC(OFDNSResourceRecord *) *records;

	while ((records = [enumerator nextObject]) != nil)
		for (OFDNSResourceRecord *record in records)
			if (record.TTL < age)
				return true;

	return false;
}

@implementation OFDNSResolverContext
- (instancetype)initWithQuery: (OFDNSQuery *)query
			   ID: (OFNumber *)ID
		     settings: (OFDNSResolverSettings *)settings
		     delegate: (id <OFDNSResolverQueryDelegate>)delegate
{
574
575
576
577
578
579
580

581
582
583
584
585
586
587
{
	self = [super init];

	@try {
		_settings = [[OFDNSResolverSettings alloc] init];
		_queries = [[OFMutableDictionary alloc] init];
		_TCPQueries = [[OFMutableDictionary alloc] init];


		[_settings reload];
	} @catch (id e) {
		[self release];
		@throw e;
	}








>







588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
{
	self = [super init];

	@try {
		_settings = [[OFDNSResolverSettings alloc] init];
		_queries = [[OFMutableDictionary alloc] init];
		_TCPQueries = [[OFMutableDictionary alloc] init];
		_cache = [[OFMutableDictionary alloc] init];

		[_settings reload];
	} @catch (id e) {
		[self release];
		@throw e;
	}

597
598
599
600
601
602
603


604
605
606
607
608
609
610
	[_IPv4Socket release];
#ifdef OF_HAVE_IPV6
	[_IPv6Socket cancelAsyncRequests];
	[_IPv6Socket release];
#endif
	[_queries release];
	[_TCPQueries release];



	[super dealloc];
}

- (OFDictionary *)staticHosts
{
	return _settings->_staticHosts;







>
>







612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
	[_IPv4Socket release];
#ifdef OF_HAVE_IPV6
	[_IPv6Socket cancelAsyncRequests];
	[_IPv6Socket release];
#endif
	[_queries release];
	[_TCPQueries release];
	[_cache release];
	[_lastNameServers release];

	[super dealloc];
}

- (OFDictionary *)staticHosts
{
	return _settings->_staticHosts;
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
- (void)setMinNumberOfDotsInAbsoluteName:
    (unsigned int)minNumberOfDotsInAbsoluteName
{
	_settings->_minNumberOfDotsInAbsoluteName =
	    minNumberOfDotsInAbsoluteName;
}

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

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

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








|

|


|

|







691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
- (void)setMinNumberOfDotsInAbsoluteName:
    (unsigned int)minNumberOfDotsInAbsoluteName
{
	_settings->_minNumberOfDotsInAbsoluteName =
	    minNumberOfDotsInAbsoluteName;
}

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

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

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

719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
		     repeats: false];
	[[OFRunLoop currentRunLoop] addTimer: context->_cancelTimer
				     forMode: runLoopMode];

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

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

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

		context->_TCPSocket.delegate = self;
		[context->_TCPSocket asyncConnectToHost: nameServer







|







736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
		     repeats: false];
	[[OFRunLoop currentRunLoop] addTimer: context->_cancelTimer
				     forMode: runLoopMode];

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

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

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

		context->_TCPSocket.delegate = self;
		[context->_TCPSocket asyncConnectToHost: nameServer
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
	[sock asyncSendData: context->_queryData
		   receiver: &context->_usedNameServer
		runLoopMode: runLoopMode];
	[sock asyncReceiveIntoBuffer: _buffer
			      length: bufferLength
			 runLoopMode: runLoopMode];
}








































- (void)asyncPerformQuery: (OFDNSQuery *)query
		 delegate: (id <OFDNSResolverQueryDelegate>)delegate
{
	[self asyncPerformQuery: query
		    runLoopMode: OFDefaultRunLoopMode
		       delegate: delegate];
}

- (void)asyncPerformQuery: (OFDNSQuery *)query
	      runLoopMode: (OFRunLoopMode)runLoopMode
		 delegate: (id <OFDNSResolverQueryDelegate>)delegate
{
	void *pool = objc_autoreleasePoolPush();
	OFNumber *ID;
	OFDNSResolverContext *context;































	/* Random, unused ID */
	do {
		ID = [OFNumber numberWithUnsignedShort: OFRandom16()];
	} while ([_queries objectForKey: ID] != nil);

	if (query.domainName.UTF8StringLength > 253)







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
















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







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
	[sock asyncSendData: context->_queryData
		   receiver: &context->_usedNameServer
		runLoopMode: runLoopMode];
	[sock asyncReceiveIntoBuffer: _buffer
			      length: bufferLength
			 runLoopMode: runLoopMode];
}

- (void)of_cleanUpCache
{
	OFTimeInterval now = [[OFDate date] timeIntervalSince1970];
	OFMutableArray *removeList;

	if (_lastNameServers != _settings->_nameServers &&
	    ![_lastNameServers isEqual: _settings->_nameServers]) {
		OFArray *old = _lastNameServers;
		_lastNameServers = [_settings->_nameServers copy];
		[old release];

		[_cache removeAllObjects];

		return;
	}

	if (now - _lastCacheCleanup < 1)
		return;

	_lastCacheCleanup = now;
	removeList = [OFMutableArray arrayWithCapacity: _cache.count];

	for (OFDNSQuery *query in _cache) {
		OFPair OF_GENERIC(OFDate *, OFDNSResponse *) *entry =
		    [_cache objectForKey: query];
		uint32_t age =
		    (uint32_t)now - [entry.firstObject timeIntervalSince1970];
		OFDNSResponse *response = entry.secondObject;

		if (containsExpiredRecord(response.answerRecords, age) ||
		    containsExpiredRecord(response.authorityRecords, age) ||
		    containsExpiredRecord(response.additionalRecords, age))
			[removeList addObject: query];
	}

	for (OFDNSQuery *query in removeList)
		[_cache removeObjectForKey: query];
}

- (void)asyncPerformQuery: (OFDNSQuery *)query
		 delegate: (id <OFDNSResolverQueryDelegate>)delegate
{
	[self asyncPerformQuery: query
		    runLoopMode: OFDefaultRunLoopMode
		       delegate: delegate];
}

- (void)asyncPerformQuery: (OFDNSQuery *)query
	      runLoopMode: (OFRunLoopMode)runLoopMode
		 delegate: (id <OFDNSResolverQueryDelegate>)delegate
{
	void *pool = objc_autoreleasePoolPush();
	OFNumber *ID;
	OFDNSResolverContext *context;
	OFPair OF_GENERIC(OFDate *, OFDNSResponse *) *cacheEntry;

	[self of_cleanUpCache];

	if ((cacheEntry = [_cache objectForKey: query]) != nil) {
		uint32_t age =
		    (uint32_t)-[cacheEntry.firstObject timeIntervalSinceNow];
		OFDNSResponse *response = cacheEntry.secondObject;

		if (!containsExpiredRecord(response.answerRecords, age) &&
		    !containsExpiredRecord(response.authorityRecords, age) &&
		    !containsExpiredRecord(response.additionalRecords, age)) {
			OFTimer *timer = [OFTimer
			    timerWithTimeInterval: 0
					   target: delegate
					 selector: @selector(resolver:
						       didPerformQuery:response:
						       exception:)
					   object: self
					   object: query
					   object: response
					   object: nil
					  repeats: false];
			[[OFRunLoop currentRunLoop] addTimer: timer
						     forMode: runLoopMode];

			objc_autoreleasePoolPop(pool);
			return;
		}
	}

	/* Random, unused ID */
	do {
		ID = [OFNumber numberWithUnsignedShort: OFRandom16()];
	} while ([_queries objectForKey: ID] != nil);

	if (query.domainName.UTF8StringLength > 253)
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
		if ((buffer[2] & 0x78) != (queryDataBuffer[2] & 0x78))
			@throw [OFInvalidServerResponseException exception];

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

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

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

		/* RCODE */







|


|







1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
		if ((buffer[2] & 0x78) != (queryDataBuffer[2] & 0x78))
			@throw [OFInvalidServerResponseException exception];

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

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

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

		/* RCODE */
1036
1037
1038
1039
1040
1041
1042









1043
1044
1045
1046
1047
1048
1049
	} @catch (id e) {
		exception = e;
	}

	if (exception != nil)
		response = nil;










	[context->_delegate resolver: self
		     didPerformQuery: context->_query
			    response: response
			   exception: exception];

	return false;
}







>
>
>
>
>
>
>
>
>







1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
	} @catch (id e) {
		exception = e;
	}

	if (exception != nil)
		response = nil;

	[self of_cleanUpCache];

	if (response != nil)
		[_cache setObject: [OFPair pairWithFirstObject: [OFDate date]
						  secondObject: response]
			   forKey: context->_query];
	else
		[_cache removeObjectForKey: context->_query];

	[context->_delegate resolver: self
		     didPerformQuery: context->_query
			    response: response
			   exception: exception];

	return false;
}

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

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
	OFDictionary OF_GENERIC(OFString *, OFArray OF_GENERIC(OFString *) *)
	    *_staticHosts;
	OFArray OF_GENERIC(OFString *) *_nameServers;
	OFString *_Nullable _localDomain;
	OFArray OF_GENERIC(OFString *) *_searchDomains;
	OFTimeInterval _timeout;
	unsigned int _maxAttempts, _minNumberOfDotsInAbsoluteName;
	bool _usesTCP;
	OFTimeInterval _configReloadInterval;
@protected
	OFDate *_lastConfigReload;
}

- (void)reload;
@end

OF_ASSUME_NONNULL_END







|









27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
	OFDictionary OF_GENERIC(OFString *, OFArray OF_GENERIC(OFString *) *)
	    *_staticHosts;
	OFArray OF_GENERIC(OFString *) *_nameServers;
	OFString *_Nullable _localDomain;
	OFArray OF_GENERIC(OFString *) *_searchDomains;
	OFTimeInterval _timeout;
	unsigned int _maxAttempts, _minNumberOfDotsInAbsoluteName;
	bool _forcesTCP;
	OFTimeInterval _configReloadInterval;
@protected
	OFDate *_lastConfigReload;
}

- (void)reload;
@end

OF_ASSUME_NONNULL_END

Modified src/OFDNSResolverSettings.m from [1a84838633] to [8540cd3817].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
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
#include "unistd_wrapper.h"

#import "OFDNSResolverSettings.h"
#import "OFArray.h"
#import "OFCharacterSet.h"
#import "OFDate.h"
#import "OFDictionary.h"

#import "OFFile.h"


#import "OFLocale.h"
#import "OFSocket+Private.h"
#import "OFString.h"
#ifdef OF_WINDOWS
# import "OFWindowsRegistryKey.h"
#endif

#import "OFInvalidFormatException.h"
#import "OFOpenItemFailedException.h"



#import "OFOutOfMemoryException.h"
#import "OFOutOfRangeException.h"


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

#ifdef OF_NINTENDO_3DS
/* Newer versions of libctru started using id as a parameter name. */
# define id id_3ds
# include <3ds.h>
# undef id
#endif






#ifdef OF_MORPHOS
# include <proto/rexxsyslib.h>
# include <rexx/errors.h>
# include <rexx/storage.h>
#endif

#if defined(OF_HAIKU)
# define HOSTS_PATH @"/system/settings/network/hosts"
# define RESOLV_CONF_PATH @"/system/settings/network/resolv.conf"
#elif defined(OF_AMIGAOS4)
# define HOSTS_PATH @"DEVS:Internet/hosts"
#elif defined(OF_AMIGAOS)
# define HOSTS_PATH @"AmiTCP:db/hosts"
# define RESOLV_CONF_PATH @"AmiTCP:db/resolv.conf"
#else
# define HOSTS_PATH @"/etc/hosts"
# define RESOLV_CONF_PATH @"/etc/resolv.conf"
#endif

#ifndef HOST_NAME_MAX
# define HOST_NAME_MAX 255







>
|
>
>









>
>
>


>














>
>
>
>
>









<
<
<
<
<







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
#include "unistd_wrapper.h"

#import "OFDNSResolverSettings.h"
#import "OFArray.h"
#import "OFCharacterSet.h"
#import "OFDate.h"
#import "OFDictionary.h"
#ifdef OF_HAVE_FILES
# import "OFFile.h"
# import "OFFileManager.h"
#endif
#import "OFLocale.h"
#import "OFSocket+Private.h"
#import "OFString.h"
#ifdef OF_WINDOWS
# import "OFWindowsRegistryKey.h"
#endif

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

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

#ifdef OF_NINTENDO_3DS
/* Newer versions of libctru started using id as a parameter name. */
# define id id_3ds
# include <3ds.h>
# undef id
#endif

#if defined(OF_AMIGAOS_M68K) || defined(OF_AMIGAOS4)
# define Class IntuitionClass
# include <proto/dos.h>
# undef Class
#endif
#ifdef OF_MORPHOS
# include <proto/rexxsyslib.h>
# include <rexx/errors.h>
# include <rexx/storage.h>
#endif

#if defined(OF_HAIKU)
# define HOSTS_PATH @"/system/settings/network/hosts"
# define RESOLV_CONF_PATH @"/system/settings/network/resolv.conf"





#else
# define HOSTS_PATH @"/etc/hosts"
# define RESOLV_CONF_PATH @"/etc/resolv.conf"
#endif

#ifndef HOST_NAME_MAX
# define HOST_NAME_MAX 255
111
112
113
114
115
116
117











118
119
120
121
122
123
124
	if (gethostname(hostname, HOST_NAME_MAX + 1) != 0)
		return nil;

	return [OFString stringWithCString: hostname
				  encoding: [OFLocale encoding]];
}
#endif












#ifdef OF_MORPHOS
static OFString *
arexxCommand(const char *port, const char *command)
{
	struct Library *RexxSysBase;
	struct MsgPort *replyPort = NULL;







>
>
>
>
>
>
>
>
>
>
>







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
	if (gethostname(hostname, HOST_NAME_MAX + 1) != 0)
		return nil;

	return [OFString stringWithCString: hostname
				  encoding: [OFLocale encoding]];
}
#endif

#ifdef OF_AMIGAOS_M68K
static bool
assignExists(const char *assign)
{
	struct DosList *list = LockDosList(LDF_ASSIGNS | LDF_READ);
	bool found = (FindDosEntry(list, assign, LDF_ASSIGNS) != NULL);
	UnLockDosList(LDF_ASSIGNS | LDF_READ);
	return found;
}
#endif

#ifdef OF_MORPHOS
static OFString *
arexxCommand(const char *port, const char *command)
{
	struct Library *RexxSysBase;
	struct MsgPort *replyPort = NULL;
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
		copy->_nameServers = [_nameServers copy];
		copy->_localDomain = [_localDomain copy];
		copy->_searchDomains = [_searchDomains copy];
		copy->_timeout = _timeout;
		copy->_maxAttempts = _maxAttempts;
		copy->_minNumberOfDotsInAbsoluteName =
		    _minNumberOfDotsInAbsoluteName;
		copy->_usesTCP = _usesTCP;
		copy->_configReloadInterval = _configReloadInterval;
		copy->_lastConfigReload = [_lastConfigReload copy];
	} @catch (id e) {
		[copy release];
		@throw e;
	}








|







227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
		copy->_nameServers = [_nameServers copy];
		copy->_localDomain = [_localDomain copy];
		copy->_searchDomains = [_searchDomains copy];
		copy->_timeout = _timeout;
		copy->_maxAttempts = _maxAttempts;
		copy->_minNumberOfDotsInAbsoluteName =
		    _minNumberOfDotsInAbsoluteName;
		copy->_forcesTCP = _forcesTCP;
		copy->_configReloadInterval = _configReloadInterval;
		copy->_lastConfigReload = [_lastConfigReload copy];
	} @catch (id e) {
		[copy release];
		@throw e;
	}

237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
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

	[_searchDomains release];
	_searchDomains = nil;

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

#if defined(OF_HAVE_FILES) && !defined(OF_MORPHOS) && !defined(OF_NINTENDO_3DS)
- (void)parseHosts: (OFString *)path
{
	void *pool = objc_autoreleasePoolPush();
	OFCharacterSet *whitespaceCharacterSet =
	    [OFCharacterSet whitespaceCharacterSet];


	OFMutableDictionary *staticHosts;
	OFFile *file;
	OFString *line;

	@try {
		file = [OFFile fileWithPath: path mode: @"r"];
	} @catch (OFOpenItemFailedException *e) {
		objc_autoreleasePoolPop(pool);
		return;
	}

	staticHosts = [OFMutableDictionary dictionary];

	while ((line =
	    [file readLineWithEncoding: [OFLocale encoding]]) != nil) {
		OFArray *components, *hosts;
		size_t pos;
		OFString *address;

		pos = [line rangeOfString: @"#"].location;
		if (pos != OFNotFound)
			line = [line substringToIndex: pos];

		components = [line
		    componentsSeparatedByCharactersInSet: whitespaceCharacterSet
		    options: OFStringSkipEmptyComponents];

		if (components.count < 2)
			continue;

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

		for (OFString *host in hosts) {
			OFMutableArray *addresses =


			    [staticHosts objectForKey: host];

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

			[addresses addObject: address];
		}
	}
	for (OFMutableArray *addresses in [staticHosts objectEnumerator])
		[addresses makeImmutable];

	[staticHosts makeImmutable];
	_staticHosts = [staticHosts copy];

	objc_autoreleasePoolPop(pool);
}

# if !defined(OF_WINDOWS) && !defined(OF_AMIGAOS4)
- (void)parseResolvConfOption: (OFString *)option
{
	@try {
		if ([option hasPrefix: @"ndots:"]) {
			unsigned long long number;

			option = [option substringFromIndex: 6];







|













>
>



















|















|
>
>
|


















|







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

	[_searchDomains release];
	_searchDomains = nil;

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

#if defined(OF_HAVE_FILES) && !defined(OF_MORPHOS) && !defined(OF_NINTENDO_3DS)
- (void)parseHosts: (OFString *)path
{
	void *pool = objc_autoreleasePoolPush();
	OFCharacterSet *whitespaceCharacterSet =
	    [OFCharacterSet whitespaceCharacterSet];
	OFCharacterSet *commentCharacters =
	    [OFCharacterSet characterSetWithCharactersInString: @"#;"];
	OFMutableDictionary *staticHosts;
	OFFile *file;
	OFString *line;

	@try {
		file = [OFFile fileWithPath: path mode: @"r"];
	} @catch (OFOpenItemFailedException *e) {
		objc_autoreleasePoolPop(pool);
		return;
	}

	staticHosts = [OFMutableDictionary dictionary];

	while ((line =
	    [file readLineWithEncoding: [OFLocale encoding]]) != nil) {
		OFArray *components, *hosts;
		size_t pos;
		OFString *address;

		pos = [line indexOfCharacterFromSet: commentCharacters];
		if (pos != OFNotFound)
			line = [line substringToIndex: pos];

		components = [line
		    componentsSeparatedByCharactersInSet: whitespaceCharacterSet
		    options: OFStringSkipEmptyComponents];

		if (components.count < 2)
			continue;

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

		for (OFString *host in hosts) {
			OFMutableArray *addresses;

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

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

			[addresses addObject: address];
		}
	}
	for (OFMutableArray *addresses in [staticHosts objectEnumerator])
		[addresses makeImmutable];

	[staticHosts makeImmutable];
	_staticHosts = [staticHosts copy];

	objc_autoreleasePoolPop(pool);
}

# ifndef OF_WINDOWS
- (void)parseResolvConfOption: (OFString *)option
{
	@try {
		if ([option hasPrefix: @"ndots:"]) {
			unsigned long long number;

			option = [option substringFromIndex: 6];
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353

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

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

- (void)parseResolvConf: (OFString *)path
{
	void *pool = objc_autoreleasePoolPush();







|







361
362
363
364
365
366
367
368
369
370
371
372
373
374
375

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

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

- (void)parseResolvConf: (OFString *)path
{
	void *pool = objc_autoreleasePoolPush();
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
		    options: OFStringSkipEmptyComponents];

		if (components.count < 2) {
			objc_autoreleasePoolPop(pool2);
			continue;
		}

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

		if ([option isEqual: @"nameserver"]) {
			if (arguments.count != 1) {
				objc_autoreleasePoolPop(pool2);
				continue;







|







407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
		    options: OFStringSkipEmptyComponents];

		if (components.count < 2) {
			objc_autoreleasePoolPop(pool2);
			continue;
		}

		option = [components.firstObject lowercaseString];
		arguments = [components objectsInRange:
		    OFMakeRange(1, components.count - 1)];

		if ([option isEqual: @"nameserver"]) {
			if (arguments.count != 1) {
				objc_autoreleasePoolPop(pool2);
				continue;
443
444
445
446
447
448
449
450

451
452
453




454
455
456
457
458
459
460
	PIP_ADDR_STRING iter;

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

	nameServers = [OFMutableArray array];

	for (iter = &fixedInfo->DnsServerList; iter != NULL; iter = iter->Next)

		[nameServers addObject:
		    [OFString stringWithCString: iter->IpAddress.String
				       encoding: encoding]];





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

	if (fixedInfo->DomainName[0] != '\0')







|
>
|

|
>
>
>
>







465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
	PIP_ADDR_STRING iter;

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

	nameServers = [OFMutableArray array];

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

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

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

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


497
498
499
500
501
502
503
504
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
			continue;

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

		for (OFString *host in hosts) {
			OFMutableArray *addresses =


			    [staticHosts objectForKey: host];

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

			[addresses addObject: address];
		}
	}
	for (OFMutableArray *addresses in [staticHosts objectEnumerator])
		[addresses makeImmutable];

	[staticHosts makeImmutable];
	_staticHosts = [staticHosts copy];

	objc_autoreleasePoolPop(pool);
}
#endif

#ifdef OF_AMIGAOS4
- (void)obtainAmigaOS4SystemConfig
{
	OFMutableArray *nameServers = [OFMutableArray array];
	OFStringEncoding encoding = [OFLocale encoding];
	struct List *nameServerList = ObtainDomainNameServerList();
	char buffer[MAXHOSTNAMELEN];










	if (nameServerList == NULL)
		@throw [OFOutOfMemoryException exception];

	@try {
		struct DomainNameServerNode *iter =
		    (struct DomainNameServerNode *)&nameServerList->lh_Head;







|
>
>
|



















|
|

|
|
|

>
>
>
>
>
>
>
>
>







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

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

		for (OFString *host in hosts) {
			OFMutableArray *addresses;

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

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

			[addresses addObject: address];
		}
	}
	for (OFMutableArray *addresses in [staticHosts objectEnumerator])
		[addresses makeImmutable];

	[staticHosts makeImmutable];
	_staticHosts = [staticHosts copy];

	objc_autoreleasePoolPop(pool);
}
#endif

#if defined(OF_AMIGAOS_M68K) || defined(OF_AMIGAOS4)
- (bool)obtainRoadshowSystemConfig
{
	OFMutableArray *nameServers;
	OFStringEncoding encoding;
	struct List *nameServerList;
	char buffer[MAXHOSTNAMELEN];
	LONG hasDNSAPI;

	if (SocketBaseTags(SBTM_GETREF(SBTC_HAVE_DNS_API), (ULONG)&hasDNSAPI,
	    TAG_END) != 0 || !hasDNSAPI)
		return false;

	nameServers = [OFMutableArray array];
	encoding = [OFLocale encoding];
	nameServerList = ObtainDomainNameServerList();

	if (nameServerList == NULL)
		@throw [OFOutOfMemoryException exception];

	@try {
		struct DomainNameServerNode *iter =
		    (struct DomainNameServerNode *)&nameServerList->lh_Head;
550
551
552
553
554
555
556


557
558
559
560
561
562
563
		[nameServers makeImmutable];
		_nameServers = [nameServers copy];
	}

	if (GetDefaultDomainName(buffer, sizeof(buffer)))
		_localDomain = [[OFString alloc] initWithCString: buffer
							encoding: encoding];


}
#endif

#ifdef OF_NINTENDO_3DS
- (void)obtainNintendo3DSSytemConfig
{
	OFMutableArray *nameServers = [OFMutableArray array];







>
>







588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
		[nameServers makeImmutable];
		_nameServers = [nameServers copy];
	}

	if (GetDefaultDomainName(buffer, sizeof(buffer)))
		_localDomain = [[OFString alloc] initWithCString: buffer
							encoding: encoding];

	return true;
}
#endif

#ifdef OF_NINTENDO_3DS
- (void)obtainNintendo3DSSytemConfig
{
	OFMutableArray *nameServers = [OFMutableArray array];
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
		_nameServers = [nameServers copy];
	}
}
#endif

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





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

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

	pool = objc_autoreleasePoolPush();

	[self setDefaults];

#if defined(OF_WINDOWS)
# ifdef OF_HAVE_FILES

	OFWindowsRegistryKey *key = [[OFWindowsRegistryKey localMachineKey]


		   openSubkeyAtPath: @"SYSTEM\\CurrentControlSet\\Services\\"
				     @"Tcpip\\Parameters"
		       accessRights: KEY_QUERY_VALUE
			    options: 0];
	path = [[[key stringForValueNamed: @"DataBasePath"]
	    stringByAppendingPathComponent: @"hosts"]
	    stringByExpandingWindowsEnvironmentStrings];






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

	[self obtainWindowsSystemConfig];
#elif defined(OF_MORPHOS)
	[self obtainMorphOSSystemConfig];
#elif defined(OF_AMIGAOS4)














	[self parseHosts: HOSTS_PATH];

	[self obtainAmigaOS4SystemConfig];

#elif defined(OF_NINTENDO_3DS)
	[self obtainNintendo3DSSytemConfig];
#elif defined(OF_HAVE_FILES)
	[self parseHosts: HOSTS_PATH];
	[self parseResolvConf: RESOLV_CONF_PATH];
#endif








<

|

>
>
>
>
















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








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







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
		_nameServers = [nameServers copy];
	}
}
#endif

- (void)reload
{

#ifdef OF_WINDOWS
	OFString *path = nil;
#endif
#if (defined(OF_AMIGAOS_M68K) || defined(OF_AMIGAOS4)) && defined(OF_HAVE_FILES)
	OFFileManager *fileManager = [OFFileManager defaultManager];
#endif
	void *pool;

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

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

	pool = objc_autoreleasePoolPush();

	[self setDefaults];

#if defined(OF_WINDOWS)
# ifdef OF_HAVE_FILES
	@try {
		OFWindowsRegistryKey *key;

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

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

	[self obtainWindowsSystemConfig];
#elif defined(OF_MORPHOS)
	[self obtainMorphOSSystemConfig];
#elif defined(OF_AMIGAOS_M68K) || defined(OF_AMIGAOS4)
# ifdef OF_HAVE_FILES
	if (![self obtainRoadshowSystemConfig]) {
		if (assignExists("AmiTCP"))
			/*
			 * FIXME: The installer puts it there, but theoretically
			 *	  it could also be in AmiTCP:db/netdb or any of
			 *	  the files included there.
			 */
			[self parseResolvConf: @"AmiTCP:db/netdb-myhost"];
	}

	if ([fileManager fileExistsAtPath: @"DEVS:Internet/hosts"])
		[self parseHosts: @"DEVS:Internet/hosts"];
	else if (assignExists("AmiTCP"))
		[self parseHosts: @"AmiTCP:db/hosts"];
# else
	[self obtainRoadshowSystemConfig];
# endif
#elif defined(OF_NINTENDO_3DS)
	[self obtainNintendo3DSSytemConfig];
#elif defined(OF_HAVE_FILES)
	[self parseHosts: HOSTS_PATH];
	[self parseResolvConf: RESOLV_CONF_PATH];
#endif

Modified src/OFDNSResourceRecord.h from [30273f1f1b] to [32d9ec1f01].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

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

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

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

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

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

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFData+ASN1DERParsing.h from [98f51ac0d9] to [ccb2c495e5].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2021 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFData+ASN1DERParsing.m from [515019e2e6] to [b0aa916c3e].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2021 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

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

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

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

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
	void *pool = objc_autoreleasePoolPush();
	id <OFCryptographicHash> hash =
	    [class hashWithAllowsSwappableMemory: true];
	size_t digestSize = [class digestSize];
	const unsigned char *digest;
	char cString[digestSize * 2];

	[hash updateWithBuffer: self->_items
			length: self->_count * self->_itemSize];
	[hash calculate];
	digest = hash.digest;

	for (size_t i = 0; i < digestSize; i++) {
		uint8_t high, low;

		high = digest[i] >> 4;







|
|







35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
	void *pool = objc_autoreleasePoolPush();
	id <OFCryptographicHash> hash =
	    [class hashWithAllowsSwappableMemory: true];
	size_t digestSize = [class digestSize];
	const unsigned char *digest;
	char cString[digestSize * 2];

	[hash updateWithBuffer: self.items
			length: self.count * self.itemSize];
	[hash calculate];
	digest = hash.digest;

	for (size_t i = 0; i < digestSize; i++) {
		uint8_t high, low;

		high = digest[i] >> 4;

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

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFData+MessagePackParsing.m from [8bd7ef8227] to [5553f1238c].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFData.h from [b5feba23f0] to [201a24ff3c].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

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

/*! @file */

OF_ASSUME_NONNULL_BEGIN

@class OFString;
@class OFURI;

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

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

/**
 * @brief The size of a single item in the OFData in bytes.
 */
@property (readonly, nonatomic) size_t itemSize;

/**
 * @brief The number of items in the OFData.

|














<






|
|















<
<
<


|
<
<
<
<
<
<
<
<
<







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

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



40
41
42









43
44
45
46
47
48
49
/*
 * Copyright (c) 2008-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 "OFObject.h"

#import "OFMessagePackRepresentation.h"

/*! @file */

OF_ASSUME_NONNULL_BEGIN

@class OFIRI;
@class OFString;

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

/**
 * @class OFData OFData.h ObjFW/OFData.h
 *
 * @brief A class for storing arbitrary data in an array.



 */
@interface OFData: OFObject <OFCopying, OFMutableCopying, OFComparing,
    OFMessagePackRepresentation>









/**
 * @brief The size of a single item in the OFData in bytes.
 */
@property (readonly, nonatomic) size_t itemSize;

/**
 * @brief The number of items in the OFData.
92
93
94
95
96
97
98















99
100
101
102
103
104
105
@property (readonly, nonatomic) OFString *stringRepresentation;

/**
 * @brief A string containing the data in Base64 encoding.
 */
@property (readonly, nonatomic) OFString *stringByBase64Encoding;
















/**
 * @brief Creates a new OFData with the specified `count` items of size 1.
 *
 * @param items The items to store in the OFData
 * @param count The number of items
 * @return A new autoreleased OFData
 */







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







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
@property (readonly, nonatomic) OFString *stringRepresentation;

/**
 * @brief A string containing the data in Base64 encoding.
 */
@property (readonly, nonatomic) OFString *stringByBase64Encoding;

/**
 * @brief Creates a new OFData that is empty with an item size of 1.
 *
 * @return A new autoreleased OFData
 */
+ (instancetype)data;

/**
 * @brief Creates a new OFData that is empty with the specified item size.
 *
 * @param itemSize The size of a single element in the OFData
 * @return A new autoreleased OFData
 */
+ (instancetype)dataWithItemSize: (size_t)itemSize;

/**
 * @brief Creates a new OFData with the specified `count` items of size 1.
 *
 * @param items The items to store in the OFData
 * @param count The number of items
 * @return A new autoreleased OFData
 */
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
 * @return A new autoreleased OFData
 */
+ (instancetype)dataWithContentsOfFile: (OFString *)path;
#endif

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

/**
 * @brief Creates a new OFData with an item size of 1, containing the data of
 *	  the hex string representation.
 *
 * @param string The hex string representation of the data
 * @return A new autoreleased OFData







|

|


|







165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
 * @return A new autoreleased OFData
 */
+ (instancetype)dataWithContentsOfFile: (OFString *)path;
#endif

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

/**
 * @brief Creates a new OFData with an item size of 1, containing the data of
 *	  the hex string representation.
 *
 * @param string The hex string representation of the data
 * @return A new autoreleased OFData
192
193
194
195
196
197
198

















199
200
201
202
203
204
205
 * @param string The string with the Base64-encoded data
 * @return A new autoreleased OFData
 * @throw OFInvalidFormatException The specified string is not correctly
 *				   formatted
 */
+ (instancetype)dataWithBase64EncodedString: (OFString *)string;


















/**
 * @brief Initializes an already allocated OFData with the specified `count`
 *	  items of size 1.
 *
 * @param items The items to store in the OFData
 * @param count The number of items
 * @return An initialized OFData







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







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
 * @param string The string with the Base64-encoded data
 * @return A new autoreleased OFData
 * @throw OFInvalidFormatException The specified string is not correctly
 *				   formatted
 */
+ (instancetype)dataWithBase64EncodedString: (OFString *)string;

/**
 * @brief Initializes an already allocated OFData to be empty with an item size
 *	  of 1.
 *
 * @return An initialized OFData
 */
- (instancetype)init;

/**
 * @brief Initializes an already allocated OFData to be empty with the
 *	  specified item size.
 *
 * @param itemSize The size of a single element in the OFData
 * @return An initialized OFData
 */
- (instancetype)initWithItemSize: (size_t)itemSize;

/**
 * @brief Initializes an already allocated OFData with the specified `count`
 *	  items of size 1.
 *
 * @param items The items to store in the OFData
 * @param count The number of items
 * @return An initialized OFData
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
 * @return An initialized OFData
 */
- (instancetype)initWithContentsOfFile: (OFString *)path;
#endif

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

/**
 * @brief Initializes an already allocated OFData with an item size of 1,
 *	  containing the data of the hex string representation.
 *
 * @param string The hex string representation of the data
 * @return A new autoreleased OFData







|

|


|







285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
 * @return An initialized OFData
 */
- (instancetype)initWithContentsOfFile: (OFString *)path;
#endif

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

/**
 * @brief Initializes an already allocated OFData with an item size of 1,
 *	  containing the data of the hex string representation.
 *
 * @param string The hex string representation of the data
 * @return A new autoreleased OFData
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
 *
 * @param path The path of the file to write to
 */
- (void)writeToFile: (OFString *)path;
#endif

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

OF_ASSUME_NONNULL_END

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







|

|

|








361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
 *
 * @param path The path of the file to write to
 */
- (void)writeToFile: (OFString *)path;
#endif

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

OF_ASSUME_NONNULL_END

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

Modified src/OFData.m from [7f49d598ed] to [dc16e1e87f].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
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

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

#import "OFData.h"
#import "OFBase64.h"

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

#import "OFInvalidArgumentException.h"
#import "OFInvalidFormatException.h"
#import "OFNotImplementedException.h"
#import "OFOutOfMemoryException.h"
#import "OFOutOfRangeException.h"
#import "OFTruncatedDataException.h"
#import "OFUnsupportedProtocolException.h"








/* References for static linking */
void
_references_to_categories_of_OFData(void)
{
	_OFData_ASN1DERParsing_reference = 1;
	_OFData_CryptographicHashing_reference = 1;
	_OFData_MessagePackParsing_reference = 1;
}








































































@implementation OFData





@synthesize itemSize = _itemSize;


















+ (instancetype)dataWithItems: (const void *)items count: (size_t)count
{
	return [[[self alloc] initWithItems: items count: count] autorelease];
}

+ (instancetype)dataWithItems: (const void *)items







>





|
|
|
|
|
|









>
>
>
>
>
>
>








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


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







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

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

#import "OFData.h"
#import "OFBase64.h"
#import "OFConcreteData.h"
#import "OFDictionary.h"
#ifdef OF_HAVE_FILES
# import "OFFile.h"
# import "OFFileManager.h"
#endif
#import "OFIRI.h"
#import "OFIRIHandler.h"
#import "OFStream.h"
#import "OFString.h"
#import "OFSubdata.h"
#import "OFSystemInfo.h"

#import "OFInvalidArgumentException.h"
#import "OFInvalidFormatException.h"
#import "OFNotImplementedException.h"
#import "OFOutOfMemoryException.h"
#import "OFOutOfRangeException.h"
#import "OFTruncatedDataException.h"
#import "OFUnsupportedProtocolException.h"

static struct {
	Class isa;
} placeholder;

@interface OFPlaceholderData: OFString
@end

/* References for static linking */
void
_references_to_categories_of_OFData(void)
{
	_OFData_ASN1DERParsing_reference = 1;
	_OFData_CryptographicHashing_reference = 1;
	_OFData_MessagePackParsing_reference = 1;
}

@implementation OFPlaceholderData
- (instancetype)init
{
	return (id)[[OFConcreteData alloc] init];
}

- (instancetype)initWithItemSize: (size_t)itemSize
{
	return (id)[[OFConcreteData alloc] initWithItemSize: itemSize];
}

- (instancetype)initWithItems: (const void *)items count: (size_t)count
{
	return (id)[[OFConcreteData alloc] initWithItems: items count: count];
}

- (instancetype)initWithItems: (const void *)items
			count: (size_t)count
		     itemSize: (size_t)itemSize
{
	return (id)[[OFConcreteData alloc] initWithItems: items
						   count: count
						itemSize: itemSize];
}

- (instancetype)initWithItemsNoCopy: (void *)items
			      count: (size_t)count
		       freeWhenDone: (bool)freeWhenDone
{
	return (id)[[OFConcreteData alloc] initWithItemsNoCopy: items
							 count: count
						  freeWhenDone: freeWhenDone];
}

- (instancetype)initWithItemsNoCopy: (void *)items
			      count: (size_t)count
			   itemSize: (size_t)itemSize
		       freeWhenDone: (bool)freeWhenDone
{
	return (id)[[OFConcreteData alloc] initWithItemsNoCopy: items
							 count: count
						      itemSize: itemSize
						  freeWhenDone: freeWhenDone];
}

#ifdef OF_HAVE_FILES
- (instancetype)initWithContentsOfFile: (OFString *)path
{
	return (id)[[OFConcreteData alloc] initWithContentsOfFile: path];
}
#endif

- (instancetype)initWithContentsOfIRI: (OFIRI *)IRI
{
	return (id)[[OFConcreteData alloc] initWithContentsOfIRI: IRI];
}

- (instancetype)initWithStringRepresentation: (OFString *)string
{
	return (id)[[OFConcreteData alloc]
	    initWithStringRepresentation: string];
}

- (instancetype)initWithBase64EncodedString: (OFString *)string
{
	return (id)[[OFConcreteData alloc] initWithBase64EncodedString: string];
}

OF_SINGLETON_METHODS
@end

@implementation OFData
+ (void)initialize
{
	if (self == [OFData class])
		object_setClass((id)&placeholder, [OFPlaceholderData class]);
}

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

	return [super alloc];
}

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

+ (instancetype)dataWithItemSize: (size_t)itemSize
{
	return [[[self alloc] initWithItemSize: itemSize] autorelease];
}

+ (instancetype)dataWithItems: (const void *)items count: (size_t)count
{
	return [[[self alloc] initWithItems: items count: count] autorelease];
}

+ (instancetype)dataWithItems: (const void *)items
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
#ifdef OF_HAVE_FILES
+ (instancetype)dataWithContentsOfFile: (OFString *)path
{
	return [[[self alloc] initWithContentsOfFile: path] autorelease];
}
#endif

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

+ (instancetype)dataWithStringRepresentation: (OFString *)string
{
	return [[[self alloc]
	    initWithStringRepresentation: string] autorelease];
}

+ (instancetype)dataWithBase64EncodedString: (OFString *)string
{
	return [[[self alloc] initWithBase64EncodedString: string] autorelease];
}























- (instancetype)initWithItems: (const void *)items count: (size_t)count
{
	return [self initWithItems: items count: count itemSize: 1];
}

- (instancetype)initWithItems: (const void *)items
			count: (size_t)count
		     itemSize: (size_t)itemSize
{
	self = [super init];

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

		_items = OFAllocMemory(count, itemSize);
		_count = count;
		_itemSize = itemSize;
		_freeWhenDone = true;

		memcpy(_items, items, count * itemSize);
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (instancetype)initWithItemsNoCopy: (void *)items
			      count: (size_t)count
		       freeWhenDone: (bool)freeWhenDone
{
	return [self initWithItemsNoCopy: items
				   count: count
				itemSize: 1
			    freeWhenDone: freeWhenDone];
}

- (instancetype)initWithItemsNoCopy: (void *)items
			      count: (size_t)count
			   itemSize: (size_t)itemSize
		       freeWhenDone: (bool)freeWhenDone
{
	self = [super init];

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

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

	return self;
}

#ifdef OF_HAVE_FILES
- (instancetype)initWithContentsOfFile: (OFString *)path
{
	char *buffer = NULL;
	OFStreamOffset fileSize;

	@try {
		void *pool = objc_autoreleasePoolPush();
		OFFile *file = [OFFile fileWithPath: path mode: @"r"];
		fileSize = [file seekToOffset: 0 whence: OFSeekEnd];

		if (fileSize < 0 || (unsigned long long)fileSize > SIZE_MAX)
			@throw [OFOutOfRangeException exception];

		[file seekToOffset: 0 whence: OFSeekSet];

		buffer = OFAllocMemory((size_t)fileSize, 1);
		[file readIntoBuffer: buffer exactLength: (size_t)fileSize];

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

		@throw e;
	}

	@try {
		self = [self initWithItemsNoCopy: buffer
					   count: (size_t)fileSize
				    freeWhenDone: true];
	} @catch (id e) {
		OFFreeMemory(buffer);
		@throw e;
	}


	return self;
}
#endif

- (instancetype)initWithContentsOfURI: (OFURI *)URI
{

	self = [super init];

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

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

		pageSize = [OFSystemInfo pageSize];
		buffer = OFAllocMemory(1, pageSize);

		@try {
			while (!stream.atEndOfStream) {
				size_t length = [stream
				    readIntoBuffer: buffer
					    length: pageSize];

				if (SIZE_MAX - _count < length)
					@throw [OFOutOfRangeException
					    exception];

				_items = OFResizeMemory(_items,
				    _count + length, 1);
				memcpy(_items + _count, buffer, length);
				_count += length;
			}
		} @finally {
			OFFreeMemory(buffer);
		}

		objc_autoreleasePoolPop(pool);
	} @catch (id e) {

		[self release];












		@throw e;
	}

	return self;
}

- (instancetype)initWithStringRepresentation: (OFString *)string
{

	self = [super init];

	@try {


		size_t count = [string
		    cStringLengthWithEncoding: OFStringEncodingASCII];
		const char *cString;

		if (count % 2 != 0)
			@throw [OFInvalidFormatException exception];

		count /= 2;

		_items = OFAllocMemory(count, 1);
		_count = count;
		_itemSize = 1;
		_freeWhenDone = true;

		cString = [string cStringWithEncoding: OFStringEncodingASCII];

		for (size_t i = 0; i < count; i++) {
			uint8_t c1 = cString[2 * i];
			uint8_t c2 = cString[2 * i + 1];
			uint8_t byte;







|

|












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










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

















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



<
<
<
<
|
<
<
|
<
<

<
|
<
<
|
<

<

<



<
|
<
<
<
<
<
|
>





|

>
|



|

<

<
<
<
<



<
|
|
<
|

|
|
<

|
<
|
|
<
<
<




>

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








>
|


>
>
|

<





<
|
<
<
<







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
#ifdef OF_HAVE_FILES
+ (instancetype)dataWithContentsOfFile: (OFString *)path
{
	return [[[self alloc] initWithContentsOfFile: path] autorelease];
}
#endif

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

+ (instancetype)dataWithStringRepresentation: (OFString *)string
{
	return [[[self alloc]
	    initWithStringRepresentation: string] autorelease];
}

+ (instancetype)dataWithBase64EncodedString: (OFString *)string
{
	return [[[self alloc] initWithBase64EncodedString: string] autorelease];
}

- (instancetype)init
{
	if ([self isMemberOfClass: [OFData class]] ||
	    [self isMemberOfClass: [OFMutableData class]]) {
		@try {
			[self doesNotRecognizeSelector: _cmd];
		} @catch (id e) {
			[self release];
			@throw e;
		}

		abort();
	}

	return [super init];
}

- (instancetype)initWithItemSize: (size_t)itemSize
{
	OF_INVALID_INIT_METHOD
}

- (instancetype)initWithItems: (const void *)items count: (size_t)count
{
	return [self initWithItems: items count: count itemSize: 1];
}

- (instancetype)initWithItems: (const void *)items
			count: (size_t)count
		     itemSize: (size_t)itemSize
{

	OF_INVALID_INIT_METHOD
















}

- (instancetype)initWithItemsNoCopy: (void *)items
			      count: (size_t)count
		       freeWhenDone: (bool)freeWhenDone
{
	return [self initWithItemsNoCopy: items
				   count: count
				itemSize: 1
			    freeWhenDone: freeWhenDone];
}

- (instancetype)initWithItemsNoCopy: (void *)items
			      count: (size_t)count
			   itemSize: (size_t)itemSize
		       freeWhenDone: (bool)freeWhenDone
{

	OF_INVALID_INIT_METHOD



}












#ifdef OF_HAVE_FILES
- (instancetype)initWithContentsOfFile: (OFString *)path
{




	void *pool = objc_autoreleasePoolPush();


	OFIRI *IRI;




	@try {


		IRI = [OFIRI fileIRIWithPath: path];

	} @catch (id e) {

		[self release];

		@throw e;
	}


	self = [self initWithContentsOfIRI: IRI];






	objc_autoreleasePoolPop(pool);

	return self;
}
#endif

- (instancetype)initWithContentsOfIRI: (OFIRI *)IRI
{
	char *items = NULL, *buffer = NULL;
	size_t count = 0;

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






		pageSize = [OFSystemInfo pageSize];
		buffer = OFAllocMemory(1, pageSize);


		while (!stream.atEndOfStream) {
			size_t length = [stream readIntoBuffer: buffer

							length: pageSize];

			if (SIZE_MAX - count < length)
				@throw [OFOutOfRangeException exception];


			items = OFResizeMemory(items, count + length, 1);

			memcpy(items + count, buffer, length);
			count += length;



		}

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

		@throw e;
	} @finally {
		OFFreeMemory(buffer);
	}

	@try {
		self = [self initWithItemsNoCopy: items
					   count: count
				    freeWhenDone: true];
	} @catch (id e) {
		OFFreeMemory(items);
		@throw e;
	}

	return self;
}

- (instancetype)initWithStringRepresentation: (OFString *)string
{
	char *items = NULL;
	size_t count = 0;

	@try {
		const char *cString;

		count = [string
		    cStringLengthWithEncoding: OFStringEncodingASCII];


		if (count % 2 != 0)
			@throw [OFInvalidFormatException exception];

		count /= 2;

		items = OFAllocMemory(count, 1);




		cString = [string cStringWithEncoding: OFStringEncodingASCII];

		for (size_t i = 0; i < count; i++) {
			uint8_t c1 = cString[2 * i];
			uint8_t c2 = cString[2 * i + 1];
			uint8_t byte;
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
			else if (c2 >= 'a' && c2 <= 'f')
				byte |= c2 - 'a' + 10;
			else if (c2 >= 'A' && c2 <= 'F')
				byte |= c2 - 'A' + 10;
			else
				@throw [OFInvalidFormatException exception];

			_items[i] = byte;
		}
	} @catch (id e) {

		[self release];










		@throw e;
	}

	return self;
}

- (instancetype)initWithBase64EncodedString: (OFString *)string
{
	bool mutable = [self isKindOfClass: [OFMutableData class]];

	if (!mutable) {
		[self release];
		self = [OFMutableData alloc];
	}

	self = [(OFMutableData *)self initWithCapacity: string.length / 3];

	@try {
		if (!OFBase64Decode((OFMutableData *)self,
		    [string cStringWithEncoding: OFStringEncodingASCII],
		    [string cStringLengthWithEncoding: OFStringEncodingASCII]))
			@throw [OFInvalidFormatException exception];
	} @catch (id e) {
		[self release];
		@throw e;
	}


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


	return self;
}

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

	OFString *stringValue;


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

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








	self = [self initWithBase64EncodedString: stringValue];

	objc_autoreleasePoolPop(pool);

	return self;
}

- (void)dealloc
{
	if (_freeWhenDone)
		OFFreeMemory(_items);

	[_parentData release];

	[super dealloc];
}

- (size_t)count
{
	return _count;

}

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

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

	return _items + idx * _itemSize;
}

- (const void *)firstItem
{


	if (_items == NULL || _count == 0)
		return NULL;

	return _items;
}

- (const void *)lastItem
{



	if (_items == NULL || _count == 0)
		return NULL;

	return _items + (_count - 1) * _itemSize;
}

- (id)copy
{
	return [self retain];
}

- (id)mutableCopy
{
	return [[OFMutableData alloc] initWithItems: _items
					      count: _count
					   itemSize: _itemSize];
}

- (bool)isEqual: (id)object
{

	OFData *data;

	if (object == self)
		return true;

	if (![object isKindOfClass: [OFData class]])
		return false;



	data = object;

	if (data.count != _count || data.itemSize != _itemSize)
		return false;
	if (memcmp(data.items, _items, _count * _itemSize) != 0)
		return false;

	return true;
}

- (OFComparisonResult)compare: (OFData *)data
{
	int comparison;
	size_t count, minCount;

	if (![data isKindOfClass: [OFData class]])
		@throw [OFInvalidArgumentException exception];

	if (data.itemSize != _itemSize)
		@throw [OFInvalidArgumentException exception];


	count = data.count;
	minCount = (_count > count ? count : _count);

	if ((comparison = memcmp(_items, data.items,
	    minCount * _itemSize)) == 0) {
		if (_count > count)
			return OFOrderedDescending;
		if (_count < count)
			return OFOrderedAscending;

		return OFOrderedSame;
	}

	if (comparison > 0)
		return OFOrderedDescending;
	else
		return OFOrderedAscending;
}

- (unsigned long)hash
{


	unsigned long hash;

	OFHashInit(&hash);

	for (size_t i = 0; i < _count * _itemSize; i++)
		OFHashAddByte(&hash, ((uint8_t *)_items)[i]);

	OFHashFinalize(&hash);

	return hash;
}

- (OFData *)subdataWithRange: (OFRange)range
{
	OFData *ret;

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

	ret = [OFData dataWithItemsNoCopy: _items + (range.location * _itemSize)


				    count: range.length
				 itemSize: _itemSize
			     freeWhenDone: false];
	ret->_parentData = [(_parentData != nil ? _parentData : self) copy];

	return ret;



}

- (OFString *)description
{
	OFMutableString *ret = [OFMutableString stringWithString: @"<"];



	for (size_t i = 0; i < _count; i++) {
		if (i > 0)
			[ret appendString: @" "];

		for (size_t j = 0; j < _itemSize; j++)
			[ret appendFormat: @"%02x", _items[i * _itemSize + j]];
	}

	[ret appendString: @">"];

	[ret makeImmutable];
	return ret;
}

- (OFString *)stringRepresentation
{
	OFMutableString *ret = [OFMutableString string];



	for (size_t i = 0; i < _count; i++)
		for (size_t j = 0; j < _itemSize; j++)
			[ret appendFormat: @"%02x", _items[i * _itemSize + j]];

	[ret makeImmutable];
	return ret;
}

- (OFString *)stringByBase64Encoding
{
	return OFBase64Encode(_items, _count * _itemSize);
}

- (OFRange)rangeOfData: (OFData *)data
	       options: (OFDataSearchOptions)options
		 range: (OFRange)range
{


	const char *search;
	size_t searchLength;

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

	if (data == nil || data.itemSize != _itemSize)
		@throw [OFInvalidArgumentException exception];

	if ((searchLength = data.count) == 0)
		return OFMakeRange(0, 0);

	if (searchLength > range.length)
		return OFMakeRange(OFNotFound, 0);

	search = data.items;

	if (options & OFDataSearchBackwards) {
		for (size_t i = range.length - searchLength;; i--) {
			if (memcmp(_items + i * _itemSize, search,
			    searchLength * _itemSize) == 0)
				return OFMakeRange(i, searchLength);

			/* No match and we're at the last item */
			if (i == 0)
				break;
		}
	} else {
		for (size_t i = range.location;
		    i <= range.length - searchLength; i++)
			if (memcmp(_items + i * _itemSize, search,
			    searchLength * _itemSize) == 0)
				return OFMakeRange(i, searchLength);
	}

	return OFMakeRange(OFNotFound, 0);
}

#ifdef OF_HAVE_FILES
- (void)writeToFile: (OFString *)path
{
	OFFile *file = [[OFFile alloc] initWithPath: path mode: @"w"];
	@try {
		[file writeBuffer: _items length: _count * _itemSize];

	} @finally {
		[file release];
	}
}
#endif

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

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

	objc_autoreleasePoolPop(pool);
}

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

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

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

	[element retain];

	objc_autoreleasePoolPop(pool);

	return [element autorelease];
}

- (OFData *)messagePackRepresentation
{
	OFMutableData *data;


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



	if (_count <= UINT8_MAX) {
		uint8_t type = 0xC4;
		uint8_t tmp = (uint8_t)_count;

		data = [OFMutableData dataWithCapacity: _count + 2];
		[data addItem: &type];
		[data addItem: &tmp];
	} else if (_count <= UINT16_MAX) {
		uint8_t type = 0xC5;
		uint16_t tmp = OFToBigEndian16((uint16_t)_count);

		data = [OFMutableData dataWithCapacity: _count + 3];
		[data addItem: &type];
		[data addItems: &tmp count: sizeof(tmp)];
	} else if (_count <= UINT32_MAX) {
		uint8_t type = 0xC6;
		uint32_t tmp = OFToBigEndian32((uint32_t)_count);

		data = [OFMutableData dataWithCapacity: _count + 5];
		[data addItem: &type];
		[data addItems: &tmp count: sizeof(tmp)];
	} else
		@throw [OFOutOfRangeException exception];

	[data addItems: _items count: _count];
	[data makeImmutable];

	return data;
}
@end







|


>

>
>
>
>
>
>
>
>
>
>








<
|
<
<
|
|
|
|

<
|








>
|
|
|
>
|
|

<
<
<
>
|
|
>

<
<
<
|
<





>
>
>
>
>
>
>
|






|

<
<
|
<
|
<
|
<
|

<
>




|




|


|




>
>
|


|




>
>
>
|


|









|
|
|




>








>
>


|

|








|




|


>
|
|

|
|
|

|













>
>




|
|








<
<

|


<
>
>
|
<
<
<

|
>
>
>





>
>

|



|
|











>
>

|
|
|







|






>
>




|


|












|
|









|
|











|
>






|



|


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





>

|



>
>
|

|

|


|

|

|


|

|

|





|





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
			else if (c2 >= 'a' && c2 <= 'f')
				byte |= c2 - 'a' + 10;
			else if (c2 >= 'A' && c2 <= 'F')
				byte |= c2 - 'A' + 10;
			else
				@throw [OFInvalidFormatException exception];

			items[i] = byte;
		}
	} @catch (id e) {
		OFFreeMemory(items);
		[self release];

		@throw e;
	}

	@try {
		self = [self initWithItemsNoCopy: items
					   count: count
				    freeWhenDone: true];
	} @catch (id e) {
		OFFreeMemory(items);
		@throw e;
	}

	return self;
}

- (instancetype)initWithBase64EncodedString: (OFString *)string
{

	void *pool = objc_autoreleasePoolPush();


	OFMutableData *data;

	@try {
		data = [OFMutableData data];


		if (!OFBase64Decode(data,
		    [string cStringWithEncoding: OFStringEncodingASCII],
		    [string cStringLengthWithEncoding: OFStringEncodingASCII]))
			@throw [OFInvalidFormatException exception];
	} @catch (id e) {
		[self release];
		@throw e;
	}

	/* Avoid copying if the class already matches. */
	if (data.class == self.class) {
		[self release];
		self = [data retain];
		objc_autoreleasePoolPop(pool);
		return self;
	}




	/*
	 * Make it immutable and avoid copying if the class already matches
	 * after that.
	 */
	@try {



		[data makeImmutable];

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

	if (data.class == self.class) {
		[self release];
		self = [data retain];
		objc_autoreleasePoolPop(pool);
		return self;
	}

	self = [self initWithItems: data.items count: data.count];

	objc_autoreleasePoolPop(pool);

	return self;
}

- (size_t)count
{


	OF_UNRECOGNIZED_SELECTOR

}



- (size_t)itemSize
{

	OF_UNRECOGNIZED_SELECTOR
}

- (const void *)items
{
	OF_UNRECOGNIZED_SELECTOR
}

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

	return (const unsigned char *)self.items + idx * self.itemSize;
}

- (const void *)firstItem
{
	const void *items = self.items;

	if (items == NULL || self.count == 0)
		return NULL;

	return items;
}

- (const void *)lastItem
{
	const unsigned char *items = self.items;
	size_t count = self.count;

	if (items == NULL || count == 0)
		return NULL;

	return items + (count - 1) * self.itemSize;
}

- (id)copy
{
	return [self retain];
}

- (id)mutableCopy
{
	return [[OFMutableData alloc] initWithItems: self.items
					      count: self.count
					   itemSize: self.itemSize];
}

- (bool)isEqual: (id)object
{
	size_t count, itemSize;
	OFData *data;

	if (object == self)
		return true;

	if (![object isKindOfClass: [OFData class]])
		return false;

	count = self.count;
	itemSize = self.itemSize;
	data = object;

	if (data.count != count || data.itemSize != itemSize)
		return false;
	if (memcmp(data.items, self.items, count * itemSize) != 0)
		return false;

	return true;
}

- (OFComparisonResult)compare: (OFData *)data
{
	int comparison;
	size_t count, dataCount, minCount;

	if (![data isKindOfClass: [OFData class]])
		@throw [OFInvalidArgumentException exception];

	if (data.itemSize != self.itemSize)
		@throw [OFInvalidArgumentException exception];

	count = self.count;
	dataCount = data.count;
	minCount = (count > dataCount ? dataCount : count);

	if ((comparison = memcmp(self.items, data.items,
	    minCount * self.itemSize)) == 0) {
		if (count > dataCount)
			return OFOrderedDescending;
		if (count < dataCount)
			return OFOrderedAscending;

		return OFOrderedSame;
	}

	if (comparison > 0)
		return OFOrderedDescending;
	else
		return OFOrderedAscending;
}

- (unsigned long)hash
{
	const unsigned char *items = self.items;
	size_t count = self.count, itemSize = self.itemSize;
	unsigned long hash;

	OFHashInit(&hash);

	for (size_t i = 0; i < count * itemSize; i++)
		OFHashAddByte(&hash, items[i]);

	OFHashFinalize(&hash);

	return hash;
}

- (OFData *)subdataWithRange: (OFRange)range
{


	if (range.length > SIZE_MAX - range.location ||
	    range.location + range.length > self.count)
		@throw [OFOutOfRangeException exception];


	if (![self isKindOfClass: [OFMutableData class]])
		return [[[OFSubdata alloc] initWithData: self
						  range: range] autorelease];




	return [OFData dataWithItems: (const unsigned char *)self.items +
				      (range.location * self.itemSize)
			       count: self.count
			    itemSize: self.itemSize];
}

- (OFString *)description
{
	OFMutableString *ret = [OFMutableString stringWithString: @"<"];
	const unsigned char *items = self.items;
	size_t count = self.count, itemSize = self.itemSize;

	for (size_t i = 0; i < count; i++) {
		if (i > 0)
			[ret appendString: @" "];

		for (size_t j = 0; j < itemSize; j++)
			[ret appendFormat: @"%02x", items[i * itemSize + j]];
	}

	[ret appendString: @">"];

	[ret makeImmutable];
	return ret;
}

- (OFString *)stringRepresentation
{
	OFMutableString *ret = [OFMutableString string];
	const unsigned char *items = self.items;
	size_t count = self.count, itemSize = self.itemSize;

	for (size_t i = 0; i < count; i++)
		for (size_t j = 0; j < itemSize; j++)
			[ret appendFormat: @"%02x", items[i * itemSize + j]];

	[ret makeImmutable];
	return ret;
}

- (OFString *)stringByBase64Encoding
{
	return OFBase64Encode(self.items, self.count * self.itemSize);
}

- (OFRange)rangeOfData: (OFData *)data
	       options: (OFDataSearchOptions)options
		 range: (OFRange)range
{
	const unsigned char *items = self.items;
	size_t count = self.count, itemSize = self.itemSize;
	const char *search;
	size_t searchLength;

	if (range.length > SIZE_MAX - range.location ||
	    range.location + range.length > count)
		@throw [OFOutOfRangeException exception];

	if (data == nil || data.itemSize != itemSize)
		@throw [OFInvalidArgumentException exception];

	if ((searchLength = data.count) == 0)
		return OFMakeRange(0, 0);

	if (searchLength > range.length)
		return OFMakeRange(OFNotFound, 0);

	search = data.items;

	if (options & OFDataSearchBackwards) {
		for (size_t i = range.length - searchLength;; i--) {
			if (memcmp(items + i * itemSize, search,
			    searchLength * itemSize) == 0)
				return OFMakeRange(i, searchLength);

			/* No match and we're at the last item */
			if (i == 0)
				break;
		}
	} else {
		for (size_t i = range.location;
		    i <= range.length - searchLength; i++)
			if (memcmp(items + i * itemSize, search,
			    searchLength * itemSize) == 0)
				return OFMakeRange(i, searchLength);
	}

	return OFMakeRange(OFNotFound, 0);
}

#ifdef OF_HAVE_FILES
- (void)writeToFile: (OFString *)path
{
	OFFile *file = [[OFFile alloc] initWithPath: path mode: @"w"];
	@try {
		[file writeBuffer: self.items
			   length: self.count * self.itemSize];
	} @finally {
		[file release];
	}
}
#endif

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

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

	objc_autoreleasePoolPop(pool);






















}

- (OFData *)messagePackRepresentation
{
	OFMutableData *data;
	size_t count;

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

	count = self.count;

	if (count <= UINT8_MAX) {
		uint8_t type = 0xC4;
		uint8_t tmp = (uint8_t)count;

		data = [OFMutableData dataWithCapacity: count + 2];
		[data addItem: &type];
		[data addItem: &tmp];
	} else if (count <= UINT16_MAX) {
		uint8_t type = 0xC5;
		uint16_t tmp = OFToBigEndian16((uint16_t)count);

		data = [OFMutableData dataWithCapacity: count + 3];
		[data addItem: &type];
		[data addItems: &tmp count: sizeof(tmp)];
	} else if (count <= UINT32_MAX) {
		uint8_t type = 0xC6;
		uint32_t tmp = OFToBigEndian32((uint32_t)count);

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

	[data addItems: self.items count: count];
	[data makeImmutable];

	return data;
}
@end

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

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
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
 *	    than one thread at the same time is not thread-safe, even if copy
 *	    was called to create one "instance" for every thread!
 */
@interface OFDatagramSocket: OFObject <OFCopying, OFReadyForReadingObserving,
    OFReadyForWritingObserving>
{
	OFSocketHandle _socket;




	bool _canBlock;
#ifdef OF_WII
	bool _canSendToBroadcastAddresses;
#endif
	id <OFDatagramSocketDelegate> _Nullable _delegate;
	OF_RESERVE_IVARS(OFDatagramSocket, 4)
}

/**
 * @brief Whether the socket can block.
 *
 * By default, a socket can block.
 *

 * @throw OFSetOptionFailedException The option could not be set
 */
@property (nonatomic) bool canBlock;

/**
 * @brief Whether the socket can send to broadcast addresses.
 *

 * @throw OFSetOptionFailedException The option could not be set
 */
@property (nonatomic) bool canSendToBroadcastAddresses;

/**
 * @brief The delegate for asynchronous operations on the socket.
 *







>
>
>
>













>







>







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
 *	    than one thread at the same time is not thread-safe, even if copy
 *	    was called to create one "instance" for every thread!
 */
@interface OFDatagramSocket: OFObject <OFCopying, OFReadyForReadingObserving,
    OFReadyForWritingObserving>
{
	OFSocketHandle _socket;
#ifdef OF_AMIGAOS
	LONG _socketID;
	int _family;	/* unused, reserved for ABI stability */
#endif
	bool _canBlock;
#ifdef OF_WII
	bool _canSendToBroadcastAddresses;
#endif
	id <OFDatagramSocketDelegate> _Nullable _delegate;
	OF_RESERVE_IVARS(OFDatagramSocket, 4)
}

/**
 * @brief Whether the socket can block.
 *
 * By default, a socket can block.
 *
 * @throw OFGetOptionFailedException The option could not be retrieved
 * @throw OFSetOptionFailedException The option could not be set
 */
@property (nonatomic) bool canBlock;

/**
 * @brief Whether the socket can send to broadcast addresses.
 *
 * @throw OFGetOptionFailedException The option could not be retrieved
 * @throw OFSetOptionFailedException The option could not be set
 */
@property (nonatomic) bool canSendToBroadcastAddresses;

/**
 * @brief The delegate for asynchronous operations on the socket.
 *
293
294
295
296
297
298
299
























300
301
302
303
304
305
306
 */
- (void)asyncSendData: (OFData *)data
	     receiver: (const OFSocketAddress *)receiver
	  runLoopMode: (OFRunLoopMode)runLoopMode
		block: (OFDatagramSocketAsyncSendDataBlock)block;
#endif

























/**
 * @brief Cancels all pending asynchronous requests on the socket.
 */
- (void)cancelAsyncRequests;

/**
 * @brief Closes the socket so that it can neither receive nor send any more







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







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
 */
- (void)asyncSendData: (OFData *)data
	     receiver: (const OFSocketAddress *)receiver
	  runLoopMode: (OFRunLoopMode)runLoopMode
		block: (OFDatagramSocketAsyncSendDataBlock)block;
#endif

/**
 * @brief Releases the socket from the current thread.
 *
 * This is necessary on some platforms in order to allow a different thread to
 * use the socket, e.g. on AmigaOS, but you should call it on all operating
 * systems before using the socket from a different thread.
 *
 * After calling this method, you must no longer use the socket until
 * @ref obtainSocketForCurrentThread has been called.
 */
- (void)releaseSocketFromCurrentThread;

/**
 * @brief Obtains the socket for the current thread.
 *
 * This is necessary on some platforms in order to allow a different thread to
 * use the socket, e.g. on AmigaOS, but you should call it on all operating
 * systems before using the socket from a different thread.
 *
 * You must only call this method after @ref releaseSocketFromCurrentThread has
 * been called from a different thread.
 */
- (void)obtainSocketForCurrentThread;

/**
 * @brief Cancels all pending asynchronous requests on the socket.
 */
- (void)cancelAsyncRequests;

/**
 * @brief Closes the socket so that it can neither receive nor send any more

Modified src/OFDatagramSocket.m from [ea19c6b109] to [2a2f93fda5].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
29
30
31
32
33
34
35

36
37
38

39
40
41
42
43




44
45
46
47
48
49
50
#import "OFDatagramSocket.h"
#import "OFData.h"
#import "OFRunLoop.h"
#import "OFRunLoop+Private.h"
#import "OFSocket.h"
#import "OFSocket+Private.h"


#import "OFGetOptionFailedException.h"
#import "OFInitializationFailedException.h"
#import "OFNotOpenException.h"

#import "OFOutOfRangeException.h"
#import "OFReadFailedException.h"
#import "OFSetOptionFailedException.h"
#import "OFSetOptionFailedException.h"
#import "OFWriteFailedException.h"





@implementation OFDatagramSocket
@synthesize delegate = _delegate;

+ (void)initialize
{
	if (self != [OFDatagramSocket class])







>



>





>
>
>
>







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
#import "OFDatagramSocket.h"
#import "OFData.h"
#import "OFRunLoop.h"
#import "OFRunLoop+Private.h"
#import "OFSocket.h"
#import "OFSocket+Private.h"

#import "OFAlreadyOpenException.h"
#import "OFGetOptionFailedException.h"
#import "OFInitializationFailedException.h"
#import "OFNotOpenException.h"
#import "OFOutOfMemoryException.h"
#import "OFOutOfRangeException.h"
#import "OFReadFailedException.h"
#import "OFSetOptionFailedException.h"
#import "OFSetOptionFailedException.h"
#import "OFWriteFailedException.h"

#if defined(OF_AMIGAOS) && !defined(UNIQUE_ID)
# define UNIQUE_ID -1
#endif

@implementation OFDatagramSocket
@synthesize delegate = _delegate;

+ (void)initialize
{
	if (self != [OFDatagramSocket class])
67
68
69
70
71
72
73



74
75
76
77
78
79
80
	@try {
		if (self.class == [OFDatagramSocket class]) {
			[self doesNotRecognizeSelector: _cmd];
			abort();
		}

		_socket = OFInvalidSocketHandle;



		_canBlock = true;
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;







>
>
>







73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
	@try {
		if (self.class == [OFDatagramSocket class]) {
			[self doesNotRecognizeSelector: _cmd];
			abort();
		}

		_socket = OFInvalidSocketHandle;
#ifdef OF_HAVE_AMIGAOS
		_socketID = -1;
#endif
		_canBlock = true;
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
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
		@throw [OFReadFailedException
		    exceptionWithObject: self
			requestedLength: length
				  errNo: OFSocketErrNo()];
#endif

	if (sender != NULL) {
		switch (((struct sockaddr *)&sender->sockaddr)->sa_family) {



		case AF_INET:
			sender->family = OFSocketAddressFamilyIPv4;
			break;
#ifdef OF_HAVE_IPV6
		case AF_INET6:
			sender->family = OFSocketAddressFamilyIPv6;
			break;
#endif
#ifdef OF_HAVE_UNIX_SOCKETS
		case AF_UNIX:
			sender->family = OFSocketAddressFamilyUNIX;
			break;
#endif
#ifdef OF_HAVE_IPX
		case AF_IPX:
			sender->family = OFSocketAddressFamilyIPX;
			break;
#endif
#ifdef OF_HAVE_APPLETALK
		case AF_APPLETALK:
			sender->family = OFSocketAddressFamilyAppleTalk;
			break;
#endif
		default:
			sender->family = OFSocketAddressFamilyUnknown;
			break;
		}


	}

	return ret;
}

- (void)asyncReceiveIntoBuffer: (void *)buffer length: (size_t)length
{







|
>
>
>
|
|
|

|
|
|


|
|
|


|
|
|


|
|
|

|
|
|
|
>
>







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
		@throw [OFReadFailedException
		    exceptionWithObject: self
			requestedLength: length
				  errNo: OFSocketErrNo()];
#endif

	if (sender != NULL) {
		struct sockaddr *sa = (struct sockaddr *)&sender->sockaddr;

		if (sender->length >= (socklen_t)sizeof(sa->sa_family)) {
			switch (sa->sa_family) {
			case AF_INET:
				sender->family = OFSocketAddressFamilyIPv4;
				break;
#ifdef OF_HAVE_IPV6
			case AF_INET6:
				sender->family = OFSocketAddressFamilyIPv6;
				break;
#endif
#ifdef OF_HAVE_UNIX_SOCKETS
			case AF_UNIX:
				sender->family = OFSocketAddressFamilyUNIX;
				break;
#endif
#ifdef OF_HAVE_IPX
			case AF_IPX:
				sender->family = OFSocketAddressFamilyIPX;
				break;
#endif
#ifdef OF_HAVE_APPLETALK
			case AF_APPLETALK:
				sender->family = OFSocketAddressFamilyAppleTalk;
				break;
#endif
			default:
				sender->family = OFSocketAddressFamilyUnknown;
				break;
			}
		} else
			sender->family = OFSocketAddressFamilyUnknown;
	}

	return ret;
}

- (void)asyncReceiveIntoBuffer: (void *)buffer length: (size_t)length
{
397
398
399
400
401
402
403













































404
405
406
407
408
409
410
411
412
413

	if (_socket > INT_MAX)
		@throw [OFOutOfRangeException exception];

	return (int)_socket;
#endif
}














































- (void)close
{
	if (_socket == OFInvalidSocketHandle)
		@throw [OFNotOpenException exceptionWithObject: self];

	closesocket(_socket);
	_socket = OFInvalidSocketHandle;
}
@end







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










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

	if (_socket > INT_MAX)
		@throw [OFOutOfRangeException exception];

	return (int)_socket;
#endif
}

- (void)releaseSocketFromCurrentThread
{
#ifdef OF_AMIGAOS
	if (_socket == OFInvalidSocketHandle)
		@throw [OFNotOpenException exceptionWithObject: self];

	if ((_socketID = ReleaseSocket(_socket, UNIQUE_ID)) == -1) {
		switch (Errno()) {
		case ENOMEM:
			@throw [OFOutOfMemoryException
			    exceptionWithRequestedSize: 0];
		case EBADF:
			@throw [OFNotOpenException exceptionWithObject: self];
		default:
			OFEnsure(0);
		}
	}

	_socket = OFInvalidSocketHandle;
#endif
}

- (void)obtainSocketForCurrentThread
{
#ifdef OF_AMIGAOS
	if (_socket != OFInvalidSocketHandle)
		@throw [OFAlreadyOpenException exceptionWithObject: self];

	if (_socketID == -1)
		@throw [OFNotOpenException exceptionWithObject: self];

	/*
	 * FIXME: We should store these, but that requires changing all
	 *	  subclasses. This only becomes a problem if IPv6 support ever
	 *	  gets added.
	 */
	_socket = ObtainSocket(_socketID, AF_INET, SOCK_DGRAM, 0);
	if (_socket == OFInvalidSocketHandle)
		@throw [OFInitializationFailedException
		    exceptionWithClass: self.class];

	_socketID = -1;
#endif
}

- (void)close
{
	if (_socket == OFInvalidSocketHandle)
		@throw [OFNotOpenException exceptionWithObject: self];

	closesocket(_socket);
	_socket = OFInvalidSocketHandle;
}
@end

Modified src/OFDate.h from [ba59d767f1] to [4f1d875b2a].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

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

OF_ASSUME_NONNULL_BEGIN

@class OFString;
@class OFConstantString;

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

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

/**
 * @brief The microsecond of the date.

|















<











<
<
<
|

<
<
<
<







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

18
19
20
21
22
23
24
25
26
27
28



29
30




31
32
33
34
35
36
37
/*
 * Copyright (c) 2008-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 "OFObject.h"
#import "OFMessagePackRepresentation.h"


OF_ASSUME_NONNULL_BEGIN

@class OFString;
@class OFConstantString;

/**
 * @class OFDate OFDate.h ObjFW/OFDate.h
 *
 * @brief A class for storing, accessing and comparing dates.
 */



@interface OFDate: OFObject <OFCopying, OFComparing,
    OFMessagePackRepresentation>




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

/**
 * @brief The microsecond of the date.
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
 */
- (OFComparisonResult)compare: (OFDate *)date;

/**
 * @brief Creates a string of the date with the specified format.
 *
 * See the man page for `strftime` for information on the format.




 *
 * @param format The format for the date string
 * @return A new, autoreleased OFString
 * @throw OFInvalidFormatException The specified format is invalid
 */
- (OFString *)dateStringWithFormat: (OFConstantString *)format;

/**
 * @brief Creates a string of the local date with the specified format.
 *
 * See the man page for `strftime` for information on the format.




 *
 * @param format The format for the date string
 * @return A new, autoreleased OFString
 * @throw OFInvalidFormatException The specified format is invalid
 */
- (OFString *)localDateStringWithFormat: (OFConstantString *)format;








>
>
>
>











>
>
>
>







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
 */
- (OFComparisonResult)compare: (OFDate *)date;

/**
 * @brief Creates a string of the date with the specified format.
 *
 * See the man page for `strftime` for information on the format.
 *
 * @warning The format is currently limited to the following format specifiers:
 *	    %%a, %%b, %%d, %%e, %%H, %%m, %%M, %%S, %%y, %%Y, %%z, %%, %%n and
 *	    %%t.
 *
 * @param format The format for the date string
 * @return A new, autoreleased OFString
 * @throw OFInvalidFormatException The specified format is invalid
 */
- (OFString *)dateStringWithFormat: (OFConstantString *)format;

/**
 * @brief Creates a string of the local date with the specified format.
 *
 * See the man page for `strftime` for information on the format.
 *
 * @warning The format is currently limited to the following format specifiers:
 *	    %%a, %%b, %%d, %%e, %%H, %%m, %%M, %%S, %%y, %%Y, %%z, %%, %%n and
 *	    %%t.
 *
 * @param format The format for the date string
 * @return A new, autoreleased OFString
 * @throw OFInvalidFormatException The specified format is invalid
 */
- (OFString *)localDateStringWithFormat: (OFConstantString *)format;

Modified src/OFDate.m from [692871b1cf] to [3692a5861b].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
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
#include <limits.h>
#include <time.h>
#include <math.h>

#include <sys/time.h>

#import "OFDate.h"

#import "OFData.h"
#import "OFDictionary.h"
#import "OFMessagePackExtension.h"
#ifdef OF_HAVE_THREADS
# import "OFMutex.h"
#endif

#import "OFStrPTime.h"
#import "OFString.h"
#import "OFSystemInfo.h"
#import "OFXMLAttribute.h"
#import "OFXMLElement.h"

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

#if defined(OF_AMIGAOS_M68K) || defined(OF_MINT)
/* amiga-gcc and freemint-gcc do not have trunc() */
# define trunc(x) ((int64_t)(x))
#endif

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

@interface OFDateSingleton: OFDate
@end

@interface OFDatePlaceholder: OFDateSingleton
@end

#if defined(OF_OBJFW_RUNTIME) && UINTPTR_MAX == UINT64_MAX
@interface OFTaggedPointerDate: OFDateSingleton
@end
#endif

static struct {
	Class isa;
} placeholder;

static OFDateSingleton *zeroDate, *distantFuture, *distantPast;
#if defined(OF_OBJFW_RUNTIME) && UINTPTR_MAX == UINT64_MAX
static int dateTag;
#endif

static void
initZeroDate(void)
{

	zeroDate = [[OFDateSingleton alloc] initWithTimeIntervalSince1970: 0];
}

static void
initDistantFuture(void)
{
	distantFuture = [[OFDateSingleton alloc]
	    initWithTimeIntervalSince1970: 64060588800.0];
}

static void
initDistantPast(void)
{
	distantPast = [[OFDateSingleton alloc]
	    initWithTimeIntervalSince1970: -62167219200.0];
}

static OFTimeInterval
now(void)
{
	struct timeval tv;







>






>



|
|












|
<


|

<
<
<
<
<
<
<
<





|
<
<
<




>
|





|






|







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
#include <limits.h>
#include <time.h>
#include <math.h>

#include <sys/time.h>

#import "OFDate.h"
#import "OFConcreteDate.h"
#import "OFData.h"
#import "OFDictionary.h"
#import "OFMessagePackExtension.h"
#ifdef OF_HAVE_THREADS
# import "OFMutex.h"
#endif
#import "OFStrFTime.h"
#import "OFStrPTime.h"
#import "OFString.h"
#import "OFSystemInfo.h"
#import "OFTaggedPointerDate.h"
#import "OFXMLAttribute.h"

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

#if defined(OF_AMIGAOS_M68K) || defined(OF_MINT)
/* amiga-gcc and freemint-gcc do not have trunc() */
# define trunc(x) ((int64_t)(x))
#endif

@interface OFPlaceholderDate: OFDate

@end

@interface OFConcreteDateSingleton: OFConcreteDate
@end









static struct {
	Class isa;
} placeholder;

static OFConcreteDateSingleton *zeroDate, *distantFuture, *distantPast;




static void
initZeroDate(void)
{
	zeroDate = [[OFConcreteDateSingleton alloc]
	    initWithTimeIntervalSince1970: 0];
}

static void
initDistantFuture(void)
{
	distantFuture = [[OFConcreteDateSingleton alloc]
	    initWithTimeIntervalSince1970: 64060588800.0];
}

static void
initDistantPast(void)
{
	distantPast = [[OFConcreteDateSingleton alloc]
	    initWithTimeIntervalSince1970: -62167219200.0];
}

static OFTimeInterval
now(void)
{
	struct timeval tv;
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
	seconds += tm->tm_sec;
	/* Time zone */
	seconds += -(double)tz * 60;

	return seconds;
}

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

- (instancetype)retain
{
	return self;
}

- (void)release
{
}

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

@implementation OFDatePlaceholder
#ifdef __clang__
/* We intentionally don't call into super, so silence the warning. */
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wunknown-pragmas"
# pragma clang diagnostic ignored "-Wobjc-designated-initializers"
#endif
- (instancetype)initWithTimeIntervalSince1970: (OFTimeInterval)seconds







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


|







247
248
249
250
251
252
253
254




255













256
257
258
259
260
261
262
263
264
265
	seconds += tm->tm_sec;
	/* Time zone */
	seconds += -(double)tz * 60;

	return seconds;
}

@implementation OFConcreteDateSingleton




OF_SINGLETON_METHODS













@end

@implementation OFPlaceholderDate
#ifdef __clang__
/* We intentionally don't call into super, so silence the warning. */
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wunknown-pragmas"
# pragma clang diagnostic ignored "-Wobjc-designated-initializers"
#endif
- (instancetype)initWithTimeIntervalSince1970: (OFTimeInterval)seconds
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

#if defined(OF_OBJFW_RUNTIME) && UINTPTR_MAX == UINT64_MAX
	value = OFFromBigEndian64(OFDoubleToRawUInt64(OFToBigEndianDouble(
	    seconds)));

	/* Almost all dates fall into this range. */
	if (value & (UINT64_C(4) << 60)) {
		id ret = objc_createTaggedPointer(dateTag,
		    value & ~(UINT64_C(4) << 60));

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


	return (id)[[OFDate of_alloc] initWithTimeIntervalSince1970: seconds];
}
#ifdef __clang__
# pragma clang diagnostic pop
#endif
@end

#if defined(OF_OBJFW_RUNTIME) && UINTPTR_MAX == UINT64_MAX
@implementation OFTaggedPointerDate
- (OFTimeInterval)timeIntervalSince1970
{
	uint64_t value = (uint64_t)object_getTaggedPointerValue(self);

	value |= UINT64_C(4) << 60;

	return OFFromBigEndianDouble(OFRawUInt64ToDouble(OFToBigEndian64(
	    value)));
}
@end
#endif

@implementation OFDate
+ (void)initialize
{
#ifdef OF_WINDOWS
	HMODULE module;
#endif

	if (self != [OFDate class])
		return;

	placeholder.isa = [OFDatePlaceholder class];

#if (!defined(HAVE_GMTIME_R) || !defined(HAVE_LOCALTIME_R)) && \
    defined(OF_HAVE_THREADS)
	mutex = [[OFMutex alloc] init];
	atexit(releaseMutex);
#endif

#ifdef OF_WINDOWS
	if ((module = LoadLibrary("msvcrt.dll")) != NULL)
		_mktime64FuncPtr = (__time64_t (*)(struct tm *))
		    GetProcAddress(module, "_mktime64");
#endif

#if defined(OF_OBJFW_RUNTIME) && UINTPTR_MAX == UINT64_MAX
	dateTag = objc_registerTaggedPointerClass([OFTaggedPointerDate class]);
#endif
}

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

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








|
|






>
|




<

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











|








|



<
<
<
<
<
<
<
<
<







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

#if defined(OF_OBJFW_RUNTIME) && UINTPTR_MAX == UINT64_MAX
	value = OFFromBigEndian64(OFDoubleToRawUInt64(OFToBigEndianDouble(
	    seconds)));

	/* Almost all dates fall into this range. */
	if (value & (UINT64_C(4) << 60)) {
		id ret = [OFTaggedPointerDate
		    dateWithUInt64TimeIntervalSince1970: value];

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

	return (id)[[OFConcreteDate alloc]
	    initWithTimeIntervalSince1970: seconds];
}
#ifdef __clang__
# pragma clang diagnostic pop
#endif







OF_SINGLETON_METHODS

@end






@implementation OFDate
+ (void)initialize
{
#ifdef OF_WINDOWS
	HMODULE module;
#endif

	if (self != [OFDate class])
		return;

	object_setClass((id)&placeholder, [OFPlaceholderDate class]);

#if (!defined(HAVE_GMTIME_R) || !defined(HAVE_LOCALTIME_R)) && \
    defined(OF_HAVE_THREADS)
	mutex = [[OFMutex alloc] init];
	atexit(releaseMutex);
#endif

#ifdef OF_WINDOWS
	if ((module = GetModuleHandle("msvcrt.dll")) != NULL)
		_mktime64FuncPtr = (__time64_t (*)(struct tm *))
		    GetProcAddress(module, "_mktime64");
#endif









}

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

425
426
427
428
429
430
431




432

433
434

435

436
437
438
439
440
441
442
443
- (instancetype)init
{
	return [self initWithTimeIntervalSince1970: now()];
}

- (instancetype)initWithTimeIntervalSince1970: (OFTimeInterval)seconds
{




	self = [super init];


	_seconds = seconds;



	return self;
}

- (instancetype)initWithTimeIntervalSinceNow: (OFTimeInterval)seconds
{
	return [self initWithTimeIntervalSince1970: now() + seconds];
}








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







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
- (instancetype)init
{
	return [self initWithTimeIntervalSince1970: now()];
}

- (instancetype)initWithTimeIntervalSince1970: (OFTimeInterval)seconds
{
	if ([self isMemberOfClass: [OFDate class]]) {
		@try {
			[self doesNotRecognizeSelector: _cmd];
		} @catch (id e) {
			[self release];
			@throw e;
		}

		abort();
	}

	return [super init];
}

- (instancetype)initWithTimeIntervalSinceNow: (OFTimeInterval)seconds
{
	return [self initWithTimeIntervalSince1970: now() + seconds];
}

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
		seconds = tmAndTzToTime(&tm, tz);

	objc_autoreleasePoolPop(pool);

	return [self initWithTimeIntervalSince1970: seconds];
}

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

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

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

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

		value = [element unsignedLongLongValueWithBase: 16];

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

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

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

	return [self initWithTimeIntervalSince1970: seconds];
}

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

	if (object == self)
		return true;








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







454
455
456
457
458
459
460

































461
462
463
464
465
466
467
		seconds = tmAndTzToTime(&tm, tz);

	objc_autoreleasePoolPop(pool);

	return [self initWithTimeIntervalSince1970: seconds];
}


































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

	if (object == self)
		return true;

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
		return OFOrderedDescending;

	return OFOrderedSame;
}

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

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

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

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

	[element retain];

	objc_autoreleasePoolPop(pool);

	return [element autorelease];
}

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







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







509
510
511
512
513
514
515
516




















517
518
519
520
521
522
523
		return OFOrderedDescending;

	return OFOrderedSame;
}

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




















}

- (OFData *)messagePackRepresentation
{
	void *pool = objc_autoreleasePoolPush();
	OFTimeInterval timeInterval = self.timeIntervalSince1970;
	int64_t seconds = (int64_t)timeInterval;
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
- (OFString *)dateStringWithFormat: (OFConstantString *)format
{
	OFString *ret;
	OFTimeInterval timeInterval = self.timeIntervalSince1970;
	time_t seconds = (time_t)timeInterval;
	struct tm tm;
	size_t pageSize;
#ifndef OF_WINDOWS
	char *buffer;
#else
	wchar_t *buffer;
#endif

	if (seconds != trunc(timeInterval))
		@throw [OFOutOfRangeException exception];

#ifdef HAVE_GMTIME_R
	if (gmtime_r(&seconds, &tm) == NULL)
		@throw [OFOutOfRangeException exception];







<

<
<
<







655
656
657
658
659
660
661

662



663
664
665
666
667
668
669
- (OFString *)dateStringWithFormat: (OFConstantString *)format
{
	OFString *ret;
	OFTimeInterval timeInterval = self.timeIntervalSince1970;
	time_t seconds = (time_t)timeInterval;
	struct tm tm;
	size_t pageSize;

	char *buffer;




	if (seconds != trunc(timeInterval))
		@throw [OFOutOfRangeException exception];

#ifdef HAVE_GMTIME_R
	if (gmtime_r(&seconds, &tm) == NULL)
		@throw [OFOutOfRangeException exception];
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
	}
# endif
#endif

	pageSize = [OFSystemInfo pageSize];
	buffer = OFAllocMemory(1, pageSize);
	@try {
#ifndef OF_WINDOWS
		if (strftime(buffer, pageSize, format.UTF8String, &tm) == 0)

			@throw [OFOutOfRangeException exception];

		ret = [OFString stringWithUTF8String: buffer];
#else
		if (wcsftime(buffer, pageSize / sizeof(wchar_t),
		    format.UTF16String, &tm) == 0)
			@throw [OFOutOfRangeException exception];

		ret = [OFString stringWithUTF16String: buffer];
#endif
	} @finally {
		OFFreeMemory(buffer);
	}

	return ret;
}

- (OFString *)localDateStringWithFormat: (OFConstantString *)format
{
	OFString *ret;
	OFTimeInterval timeInterval = self.timeIntervalSince1970;
	time_t seconds = (time_t)timeInterval;
	struct tm tm;
	size_t pageSize;
#ifndef OF_WINDOWS
	char *buffer;
#else
	wchar_t *buffer;
#endif

	if (seconds != trunc(timeInterval))
		@throw [OFOutOfRangeException exception];

#ifdef HAVE_LOCALTIME_R
	if (localtime_r(&seconds, &tm) == NULL)
		@throw [OFOutOfRangeException exception];







<
|
>



<
<
<
<
<
<
<














<

<
<
<







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
	}
# endif
#endif

	pageSize = [OFSystemInfo pageSize];
	buffer = OFAllocMemory(1, pageSize);
	@try {

		if (OFStrFTime(buffer, pageSize, format.UTF8String, &tm,
		    0) == 0)
			@throw [OFOutOfRangeException exception];

		ret = [OFString stringWithUTF8String: buffer];







	} @finally {
		OFFreeMemory(buffer);
	}

	return ret;
}

- (OFString *)localDateStringWithFormat: (OFConstantString *)format
{
	OFString *ret;
	OFTimeInterval timeInterval = self.timeIntervalSince1970;
	time_t seconds = (time_t)timeInterval;
	struct tm tm;
	size_t pageSize;

	char *buffer;




	if (seconds != trunc(timeInterval))
		@throw [OFOutOfRangeException exception];

#ifdef HAVE_LOCALTIME_R
	if (localtime_r(&seconds, &tm) == NULL)
		@throw [OFOutOfRangeException exception];
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
	}
# endif
#endif

	pageSize = [OFSystemInfo pageSize];
	buffer = OFAllocMemory(1, pageSize);
	@try {
#ifndef OF_WINDOWS
		if (strftime(buffer, pageSize, format.UTF8String, &tm) == 0)

			@throw [OFOutOfRangeException exception];

		ret = [OFString stringWithUTF8String: buffer];
#else
		if (wcsftime(buffer, pageSize / sizeof(wchar_t),
		    format.UTF16String, &tm) == 0)
			@throw [OFOutOfRangeException exception];

		ret = [OFString stringWithUTF16String: buffer];
#endif
	} @finally {
		OFFreeMemory(buffer);
	}

	return ret;
}








<
|
>



<
<
<
<
<
<
<







734
735
736
737
738
739
740

741
742
743
744
745







746
747
748
749
750
751
752
	}
# endif
#endif

	pageSize = [OFSystemInfo pageSize];
	buffer = OFAllocMemory(1, pageSize);
	@try {

		if (OFStrFTime(buffer, pageSize, format.UTF8String, &tm,
		    0) == 0)
			@throw [OFOutOfRangeException exception];

		ret = [OFString stringWithUTF8String: buffer];







	} @finally {
		OFFreeMemory(buffer);
	}

	return ret;
}

883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
		return otherDate;

	return self;
}

- (OFTimeInterval)timeIntervalSince1970
{
	return _seconds;
}

- (OFTimeInterval)timeIntervalSinceDate: (OFDate *)otherDate
{
	return self.timeIntervalSince1970 - otherDate.timeIntervalSince1970;
}








|







770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
		return otherDate;

	return self;
}

- (OFTimeInterval)timeIntervalSince1970
{
	OF_UNRECOGNIZED_SELECTOR
}

- (OFTimeInterval)timeIntervalSinceDate: (OFDate *)otherDate
{
	return self.timeIntervalSince1970 - otherDate.timeIntervalSince1970;
}

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

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#endif

#include <stdarg.h>

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

OF_ASSUME_NONNULL_BEGIN

@class OFArray OF_GENERIC(ObjectType);








<







21
22
23
24
25
26
27

28
29
30
31
32
33
34
#endif

#include <stdarg.h>

#import "OFObject.h"
#import "OFCollection.h"
#import "OFEnumerator.h"

#import "OFJSONRepresentation.h"
#import "OFMessagePackRepresentation.h"

OF_ASSUME_NONNULL_BEGIN

@class OFArray OF_GENERIC(ObjectType);

73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
 * @note Fast enumeration on a dictionary enumerates through the keys of the
 *	 dictionary.
 *
 * @note Subclasses must implement @ref objectForKey:, @ref count and
 *	 @ref keyEnumerator.
 */
@interface OFDictionary OF_GENERIC(KeyType, ObjectType): OFObject <OFCopying,
    OFMutableCopying, OFCollection, OFSerialization, OFJSONRepresentation,
    OFMessagePackRepresentation>
#if !defined(OF_HAVE_GENERICS) && !defined(DOXYGEN)
# define KeyType id
# define ObjectType id
#endif
/**
 * @brief An array of all keys.







|







72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
 * @note Fast enumeration on a dictionary enumerates through the keys of the
 *	 dictionary.
 *
 * @note Subclasses must implement @ref objectForKey:, @ref count and
 *	 @ref keyEnumerator.
 */
@interface OFDictionary OF_GENERIC(KeyType, ObjectType): OFObject <OFCopying,
    OFMutableCopying, OFCollection, OFJSONRepresentation,
    OFMessagePackRepresentation>
#if !defined(OF_HAVE_GENERICS) && !defined(DOXYGEN)
# define KeyType id
# define ObjectType id
#endif
/**
 * @brief An array of all keys.
146
147
148
149
150
151
152







153
154
155
156
157
158
159
 *
 * @param firstKey The first key
 * @return A new autoreleased OFDictionary
 */
+ (instancetype)dictionaryWithKeysAndObjects: (KeyType)firstKey, ...
    OF_SENTINEL;








/**
 * @brief Initializes an already allocated OFDictionary with the specified
 *	  OFDictionary.
 *
 * @param dictionary An OFDictionary
 * @return An initialized OFDictionary
 */







>
>
>
>
>
>
>







145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
 *
 * @param firstKey The first key
 * @return A new autoreleased OFDictionary
 */
+ (instancetype)dictionaryWithKeysAndObjects: (KeyType)firstKey, ...
    OF_SENTINEL;

/**
 * @brief Initializes an already allocated OFDictionary to be empty.
 *
 * @return An initialized OFDictionary
 */
- (instancetype)init OF_DESIGNATED_INITIALIZER;

/**
 * @brief Initializes an already allocated OFDictionary with the specified
 *	  OFDictionary.
 *
 * @param dictionary An OFDictionary
 * @return An initialized OFDictionary
 */
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
 * @param keys An array of keys
 * @param objects An array of objects
 * @param count The number of objects in the arrays
 * @return An initialized OFDictionary
 */
- (instancetype)initWithObjects: (ObjectType const _Nonnull *_Nonnull)objects
			forKeys: (KeyType const _Nonnull *_Nonnull)keys
			  count: (size_t)count;

/**
 * @brief Initializes an already allocated OFDictionary with the specified keys
 *	  and objects.
 *
 * @param firstKey The first key
 * @return An initialized OFDictionary







|







194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
 * @param keys An array of keys
 * @param objects An array of objects
 * @param count The number of objects in the arrays
 * @return An initialized OFDictionary
 */
- (instancetype)initWithObjects: (ObjectType const _Nonnull *_Nonnull)objects
			forKeys: (KeyType const _Nonnull *_Nonnull)keys
			  count: (size_t)count OF_DESIGNATED_INITIALIZER;

/**
 * @brief Initializes an already allocated OFDictionary with the specified keys
 *	  and objects.
 *
 * @param firstKey The first key
 * @return An initialized OFDictionary

Modified src/OFDictionary.m from [9689ae0f89] to [b6db2734d8].

1
2
3
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
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#include <stdlib.h>

#include <assert.h>

#import "OFDictionary.h"
#import "OFArray.h"
#import "OFCharacterSet.h"

#import "OFData.h"
#import "OFEnumerator.h"
#import "OFMapTableDictionary.h"
#import "OFString.h"
#import "OFXMLElement.h"

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

static struct {
	Class isa;
} placeholder;

static OFCharacterSet *URIQueryPartAllowedCharacterSet = nil;

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

@interface OFDictionaryPlaceholder: OFDictionary
@end

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

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

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



@end

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

- (instancetype)initWithDictionary: (OFDictionary *)dictionary
{
	return (id)[[OFMapTableDictionary alloc]
	    initWithDictionary: dictionary];
}

- (instancetype)initWithObject: (id)object forKey: (id)key
{
	return (id)[[OFMapTableDictionary alloc] initWithObject: object
							 forKey: key];
}

- (instancetype)initWithObjects: (OFArray *)objects forKeys: (OFArray *)keys
{
	return (id)[[OFMapTableDictionary alloc] initWithObjects: objects
							 forKeys: keys];
}

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

- (instancetype)initWithKeysAndObjects: (id <OFCopying>)firstKey, ...
{
	id ret;
	va_list arguments;

	va_start(arguments, firstKey);
	ret = [[OFMapTableDictionary alloc] initWithKey: firstKey
					      arguments: arguments];
	va_end(arguments);

	return ret;
}

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

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

- (instancetype)retain
{
	return self;
}

- (instancetype)autorelease
{
	return self;
}

- (void)release
{
}

- (void)dealloc
{
	OF_DEALLOC_UNSUPPORTED
}
@end

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

	URIQueryPartAllowedCharacterSet =
	    [[OFURIQueryPartAllowedCharacterSet alloc] init];
}

+ (OFCharacterSet *)URIQueryPartAllowedCharacterSet
{
	return URIQueryPartAllowedCharacterSet;
}

- (instancetype)autorelease
{
	return self;
}

- (instancetype)retain
{
	return self;
}

- (void)release
{
}

- (unsigned int)retainCount
{
	return OFMaxRetainCount;
}

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

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

@implementation OFDictionary
+ (void)initialize
{
	if (self == [OFDictionary class])
		placeholder.isa = [OFDictionaryPlaceholder class];

}

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


|

















<
<



>


<

<









<
<






|












|
|
|
>
>
>
|
<
<


|




|





|





|







|










|









|


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

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






|
>







1
2
3
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
/*
 * 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 <stdlib.h>



#import "OFDictionary.h"
#import "OFArray.h"
#import "OFCharacterSet.h"
#import "OFConcreteDictionary.h"
#import "OFData.h"
#import "OFEnumerator.h"

#import "OFString.h"


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

static struct {
	Class isa;
} placeholder;



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

@interface OFPlaceholderDictionary: OFDictionary
@end

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

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

@implementation OFPlaceholderDictionary
#ifdef __clang__
/* We intentionally don't call into super, so silence the warning. */
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wunknown-pragmas"
# pragma clang diagnostic ignored "-Wobjc-designated-initializers"
#endif


- (instancetype)init
{
	return (id)[[OFConcreteDictionary alloc] init];
}

- (instancetype)initWithDictionary: (OFDictionary *)dictionary
{
	return (id)[[OFConcreteDictionary alloc]
	    initWithDictionary: dictionary];
}

- (instancetype)initWithObject: (id)object forKey: (id)key
{
	return (id)[[OFConcreteDictionary alloc] initWithObject: object
							 forKey: key];
}

- (instancetype)initWithObjects: (OFArray *)objects forKeys: (OFArray *)keys
{
	return (id)[[OFConcreteDictionary alloc] initWithObjects: objects
							 forKeys: keys];
}

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

- (instancetype)initWithKeysAndObjects: (id <OFCopying>)firstKey, ...
{
	id ret;
	va_list arguments;

	va_start(arguments, firstKey);
	ret = [[OFConcreteDictionary alloc] initWithKey: firstKey
					      arguments: arguments];
	va_end(arguments);

	return ret;
}

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





# pragma clang diagnostic pop


















#endif






OF_SINGLETON_METHODS




















































@end

@implementation OFDictionary
+ (void)initialize
{
	if (self == [OFDictionary class])
		object_setClass((id)&placeholder,
		    [OFPlaceholderDictionary class]);
}

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

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
	va_end(arguments);

	return ret;
}

- (instancetype)init
{
	if ([self isMemberOfClass: [OFDictionary class]]) {

		@try {
			[self doesNotRecognizeSelector: _cmd];
		} @catch (id e) {
			[self release];
			@throw e;
		}

		abort();
	}

	return [super init];
}

- (instancetype)initWithDictionary: (OFDictionary *)dictionary
{



	OF_INVALID_INIT_METHOD



}























- (instancetype)initWithObject: (id)object forKey: (id)key
{

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





	return [self initWithKeysAndObjects: key, object, nil];
}

- (instancetype)initWithObjects: (OFArray *)objects_ forKeys: (OFArray *)keys_
{

	id const *objects, *keys;
	size_t count;

	@try {
		count = objects_.count;

		if (count != keys_.count)
			@throw [OFInvalidArgumentException exception];

		objects = objects_.objects;
		keys = keys_.objects;
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return [self initWithObjects: objects forKeys: keys count: count];
}











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




- (instancetype)initWithKeysAndObjects: (id)firstKey, ...
{
	id ret;
	va_list arguments;

	va_start(arguments, firstKey);
	ret = [self initWithKey: firstKey arguments: arguments];
	va_end(arguments);

	return ret;
}

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



	OF_INVALID_INIT_METHOD


}







- (instancetype)initWithSerialization: (OFXMLElement *)element


{

	OF_INVALID_INIT_METHOD






























}

- (id)objectForKey: (id)key
{
	OF_UNRECOGNIZED_SELECTOR
}








|
>















>
>
>
|
>
>
>
|
>

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


>
|
|
>
>
>
|
>
|




>
















|
|
>

>
>
>
>
>
>
>
>
>






>
>
>















>
>
>
|
>
>
|
>
>
>

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







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
	va_end(arguments);

	return ret;
}

- (instancetype)init
{
	if ([self isMemberOfClass: [OFDictionary class]] ||
	    [self isMemberOfClass: [OFMutableDictionary class]]) {
		@try {
			[self doesNotRecognizeSelector: _cmd];
		} @catch (id e) {
			[self release];
			@throw e;
		}

		abort();
	}

	return [super init];
}

- (instancetype)initWithDictionary: (OFDictionary *)dictionary
{
	void *pool = objc_autoreleasePoolPush();
	id const *objects, *keys;
	size_t count;

	@try {
		OFArray *objects_ = [dictionary.objectEnumerator allObjects];
		OFArray *keys_ = [dictionary.keyEnumerator allObjects];

		count = dictionary.count;

		if (count != keys_.count || count != objects_.count)
			@throw [OFInvalidArgumentException exception];

		objects = objects_.objects;
		keys = keys_.objects;
	} @catch (id e) {
		[self release];
		@throw e;
	}

	@try {
		self = [self initWithObjects: objects
				     forKeys: keys
				       count: count];
	} @finally {
		objc_autoreleasePoolPop(pool);
	}

	return self;
}

- (instancetype)initWithObject: (id)object forKey: (id)key
{
	@try {
		if (key == nil || object == nil)
			@throw [OFInvalidArgumentException exception];
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return [self initWithObjects: &object forKeys: &key count: 1];
}

- (instancetype)initWithObjects: (OFArray *)objects_ forKeys: (OFArray *)keys_
{
	void *pool = objc_autoreleasePoolPush();
	id const *objects, *keys;
	size_t count;

	@try {
		count = objects_.count;

		if (count != keys_.count)
			@throw [OFInvalidArgumentException exception];

		objects = objects_.objects;
		keys = keys_.objects;
	} @catch (id e) {
		[self release];
		@throw e;
	}

	self = [self initWithObjects: objects forKeys: keys count: count];

	objc_autoreleasePoolPop(pool);

	return self;
}

#ifdef __clang__
/* We intentionally don't call into super, so silence the warning. */
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wunknown-pragmas"
# pragma clang diagnostic ignored "-Wobjc-designated-initializers"
#endif
- (instancetype)initWithObjects: (id const *)objects
			forKeys: (id const *)keys
			  count: (size_t)count
{
	OF_INVALID_INIT_METHOD
}
#ifdef __clang__
# pragma clang diagnostic pop
#endif

- (instancetype)initWithKeysAndObjects: (id)firstKey, ...
{
	id ret;
	va_list arguments;

	va_start(arguments, firstKey);
	ret = [self initWithKey: firstKey arguments: arguments];
	va_end(arguments);

	return ret;
}

- (instancetype)initWithKey: (id)firstKey arguments: (va_list)arguments
{
	size_t count = 1;
	id *objects = NULL, *keys = NULL;
	va_list argumentsCopy;

	if (firstKey == nil)
		return [self init];

	va_copy(argumentsCopy, arguments);
	while (va_arg(argumentsCopy, id) != nil)
		count++;

	@try {
		size_t i = 0;
		id key, object;

		if (count % 2 != 0)
			@throw [OFInvalidArgumentException exception];

		count /= 2;

		objects = OFAllocMemory(count, sizeof(id));
		keys = OFAllocMemory(count, sizeof(id));

		while ((key = va_arg(arguments, id)) != nil &&
		    (object = va_arg(arguments, id)) != nil) {
			OFEnsure(i < count);

			objects[i] = object;
			keys[i] = key;

			i++;
		}
	} @catch (id e) {
		OFFreeMemory(objects);
		OFFreeMemory(keys);

		[self release];
		@throw e;
	}

	@try {
		self = [self initWithObjects: objects
				     forKeys: keys
				       count: count];
	} @finally {
		OFFreeMemory(objects);
		OFFreeMemory(keys);
	}

	return self;
}

- (id)objectForKey: (id)key
{
	OF_UNRECOGNIZED_SELECTOR
}

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
	    initWithDictionary: self] autorelease];
}

- (int)countByEnumeratingWithState: (OFFastEnumerationState *)state
			   objects: (id *)objects
			     count: (int)count
{

	OFEnumerator *enumerator;
	int i;

	memcpy(&enumerator, state->extra, sizeof(enumerator));

	if (enumerator == nil) {
		enumerator = [self keyEnumerator];
		memcpy(state->extra, &enumerator, sizeof(enumerator));
	}

	state->itemsPtr = objects;
	state->mutationsPtr = (unsigned long *)self;

	for (i = 0; i < count; i++) {
		id object = [enumerator nextObject];

		if (object == nil)
			return i;








>











|







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
	    initWithDictionary: self] autorelease];
}

- (int)countByEnumeratingWithState: (OFFastEnumerationState *)state
			   objects: (id *)objects
			     count: (int)count
{
	static unsigned long dummyMutations;
	OFEnumerator *enumerator;
	int i;

	memcpy(&enumerator, state->extra, sizeof(enumerator));

	if (enumerator == nil) {
		enumerator = [self keyEnumerator];
		memcpy(state->extra, &enumerator, sizeof(enumerator));
	}

	state->itemsPtr = objects;
	state->mutationsPtr = &dummyMutations;

	for (i = 0; i < count; i++) {
		id object = [enumerator nextObject];

		if (object == nil)
			return i;

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
	[ret makeImmutable];

	objc_autoreleasePoolPop(pool);

	return ret;
}

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

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

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

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

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

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

		objc_autoreleasePoolPop(pool2);
	}

	[element retain];

	objc_autoreleasePoolPop(pool);

	return [element autorelease];
}

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

- (OFString *)JSONRepresentationWithOptions:
    (OFJSONRepresentationOptions)options







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







645
646
647
648
649
650
651












































652
653
654
655
656
657
658
	[ret makeImmutable];

	objc_autoreleasePoolPop(pool);

	return ret;
}













































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

- (OFString *)JSONRepresentationWithOptions:
    (OFJSONRepresentationOptions)options
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836

		child = object.messagePackRepresentation;
		[data addItems: child.items count: child.count];

		objc_autoreleasePoolPop(pool2);
	}

	assert(i == count);

	[data makeImmutable];

	objc_autoreleasePoolPop(pool);

	return data;
}







|







788
789
790
791
792
793
794
795
796
797
798
799
800
801
802

		child = object.messagePackRepresentation;
		[data addItems: child.items count: child.count];

		objc_autoreleasePoolPop(pool2);
	}

	OFAssert(i == count);

	[data makeImmutable];

	objc_autoreleasePoolPop(pool);

	return data;
}

Renamed and modified src/OFEmbeddedURIHandler.h [5163464dd8] to src/OFEmbeddedIRIHandler.h [31a8c8ae59].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22





















23
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#import "OFURIHandler.h"

OF_ASSUME_NONNULL_BEGIN

@interface OFEmbeddedURIHandler: OFURIHandler
@end






















OF_ASSUME_NONNULL_END

|













|



|


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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
/*
 * Copyright (c) 2008-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 "OFIRIHandler.h"

OF_ASSUME_NONNULL_BEGIN

@interface OFEmbeddedIRIHandler: OFIRIHandler
@end

#ifdef __cplusplus
extern "C" {
#endif
/**
 * @brief Register a file for the `embedded:` IRI scheme.
 *
 * Usually, you should not use the directly, but rather generate a source file
 * for a file to be embedded using the `objfw-embed` tool.
 *
 * @param path The path to the file under the `embedded:` scheme. This is not
 *	       retained, so you must either pass a constant string or pass a
 *	       string that is already retained!
 * @param bytes The raw bytes for the file
 * @param size The size of the file
 */
extern void OFRegisterEmbeddedFile(OFString *path, const uint8_t *bytes,
    size_t size);
#ifdef __cplusplus
}
#endif

OF_ASSUME_NONNULL_END

Renamed and modified src/OFEmbeddedURIHandler.m [bac2da914b] to src/OFEmbeddedIRIHandler.m [9af2b60174].

1
2
3
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
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

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

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

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

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

struct EmbeddedFile {
	const char *name;
	const uint8_t *bytes;
	size_t size;
} *embeddedFiles = NULL;
size_t numEmbeddedFiles = 0;
#ifdef OF_HAVE_THREADS
static OFPlainMutex mutex;


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

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

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

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

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

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

@implementation OFEmbeddedURIHandler








- (OFStream *)openItemAtURI: (OFURI *)URI mode: (OFString *)mode
{
	const char *path;

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

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

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

#ifdef OF_HAVE_THREADS
	OFEnsure(OFPlainMutexLock(&mutex) == 0);
	@try {
#endif
		for (size_t i = 0; i < numEmbeddedFiles; i++) {
			if (strcmp(embeddedFiles[i].name, path) != 0)
				continue;

			return [OFMemoryStream
			    streamWithMemoryAddress: (void *)
							 embeddedFiles[i].bytes
					       size: embeddedFiles[i].size
					   writable: false];
		}
#ifdef OF_HAVE_THREADS
	} @finally {
		OFEnsure(OFPlainMutexUnlock(&mutex) == 0);
	}
#endif

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

|



















|
|
|










|






>


|






|


<
|








|









|
>
>
>
>
>
>
>
>
|

|

|
|
|



|



|








|














|




1
2
3
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"

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

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

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

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

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

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

void
OFRegisterEmbeddedFile(OFString *path, const uint8_t *bytes, size_t size)
{
#ifdef OF_HAVE_THREADS

	OFOnce(&mutexOnceControl, initMutex);

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

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

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

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

@implementation OFEmbeddedIRIHandler
#ifdef OF_HAVE_THREADS
+ (void)initialize
{
	if (self == [OFEmbeddedIRIHandler class])
		OFOnce(&mutexOnceControl, initMutex);
}
#endif

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

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

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

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

#ifdef OF_HAVE_THREADS
	OFEnsure(OFPlainMutexLock(&mutex) == 0);
	@try {
#endif
		for (size_t i = 0; i < numEmbeddedFiles; i++) {
			if (![embeddedFiles[i].path isEqual: path])
				continue;

			return [OFMemoryStream
			    streamWithMemoryAddress: (void *)
							 embeddedFiles[i].bytes
					       size: embeddedFiles[i].size
					   writable: false];
		}
#ifdef OF_HAVE_THREADS
	} @finally {
		OFEnsure(OFPlainMutexUnlock(&mutex) == 0);
	}
#endif

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

Modified src/OFEnumerator.h from [bebf66139d] to [2f3a8fcd9b].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFEnumerator.m from [bb10b4629e] to [395adc2765].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
57
58
59
60
61
62
63

64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
	return ret;
}

- (int)countByEnumeratingWithState: (OFFastEnumerationState *)state
			   objects: (id *)objects
			     count: (int)count
{

	int i;

	state->itemsPtr = objects;
	state->mutationsPtr = (unsigned long *)self;

	for (i = 0; i < count; i++) {
		id object = [self nextObject];

		if (object == nil)
			return i;

		objects[i] = object;
	}

	return i;
}
@end







>



|













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
	return ret;
}

- (int)countByEnumeratingWithState: (OFFastEnumerationState *)state
			   objects: (id *)objects
			     count: (int)count
{
	static unsigned long dummyMutations;
	int i;

	state->itemsPtr = objects;
	state->mutationsPtr = &dummyMutations;

	for (i = 0; i < count; i++) {
		id object = [self nextObject];

		if (object == nil)
			return i;

		objects[i] = object;
	}

	return i;
}
@end

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

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFEpollKernelEventObserver.m from [a510ac5746] to [e36e5adeff].

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

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


|















<







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

18
19
20
21
22
23
24
/*
 * Copyright (c) 2008-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 <errno.h>

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

Modified src/OFFile.h from [b56cdf66da] to [6a89472d4e].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
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
#else
typedef struct _OFFileHandle *OFFileHandle;
static const OFFileHandle OFInvalidFileHandle = NULL;
#endif

OF_ASSUME_NONNULL_BEGIN

@class OFURI;

/**
 * @class OFFile OFFile.h ObjFW/OFFile.h
 *
 * @brief A class which provides methods to read and write files.
 */
OF_SUBCLASSING_RESTRICTED
@interface OFFile: OFSeekableStream
#ifdef OF_FILE_HANDLE_IS_FD
    <OFReadyForReadingObserving, OFReadyForWritingObserving>
#endif
{
	OFFileHandle _handle;
	bool _atEndOfStream;
}

/**
 * @brief Creates a new OFFile with the specified path and mode.
 *
 * @param path The path to the file to open as a string
 * @param mode The mode in which the file should be opened.







<
<












|







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
#else
typedef struct _OFFileHandle *OFFileHandle;
static const OFFileHandle OFInvalidFileHandle = NULL;
#endif

OF_ASSUME_NONNULL_BEGIN



/**
 * @class OFFile OFFile.h ObjFW/OFFile.h
 *
 * @brief A class which provides methods to read and write files.
 */
OF_SUBCLASSING_RESTRICTED
@interface OFFile: OFSeekableStream
#ifdef OF_FILE_HANDLE_IS_FD
    <OFReadyForReadingObserving, OFReadyForWritingObserving>
#endif
{
	OFFileHandle _handle;
	bool _initialized, _atEndOfStream;
}

/**
 * @brief Creates a new OFFile with the specified path and mode.
 *
 * @param path The path to the file to open as a string
 * @param mode The mode in which the file should be opened.

Modified src/OFFile.m from [57c941bba1] to [a835c0f98a].

1
2
3
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-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"


#define _LARGEFILE64_SOURCE


#include <assert.h>
#include <errno.h>

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

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

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

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

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

#ifdef OF_AMIGAOS

# include <proto/exec.h>
# include <proto/dos.h>

#endif

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

#ifdef OF_NINTENDO_DS

|















>
|
>

<















<
















>


>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

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

37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
/*
 * 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"

#ifndef _LARGEFILE64_SOURCE
# define _LARGEFILE64_SOURCE
#endif


#include <errno.h>

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

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

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


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

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

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

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

#ifdef OF_NINTENDO_DS
335
336
337
338
339
340
341

342
343
344
345
346
347
348
}

- (instancetype)initWithHandle: (OFFileHandle)handle
{
	self = [super init];

	_handle = handle;


	return self;
}

- (instancetype)init
{
	OF_INVALID_INIT_METHOD







>







337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
}

- (instancetype)initWithHandle: (OFFileHandle)handle
{
	self = [super init];

	_handle = handle;
	_initialized = true;

	return self;
}

- (instancetype)init
{
	OF_INVALID_INIT_METHOD
550
551
552
553
554
555
556
557
558
559
560
561
562
	_handle = OFInvalidFileHandle;

	[super close];
}

- (void)dealloc
{
	if (_handle != OFInvalidFileHandle)
		[self close];

	[super dealloc];
}
@end







|





553
554
555
556
557
558
559
560
561
562
563
564
565
	_handle = OFInvalidFileHandle;

	[super close];
}

- (void)dealloc
{
	if (_initialized && _handle != OFInvalidFileHandle)
		[self close];

	[super dealloc];
}
@end

Renamed and modified src/OFFileURIHandler.h [24ec18a27d] to src/OFFileIRIHandler.h [9587a93485].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#import "OFURIHandler.h"

OF_ASSUME_NONNULL_BEGIN

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

OF_ASSUME_NONNULL_END

|













|



|




1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/*
 * Copyright (c) 2008-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 "OFIRIHandler.h"

OF_ASSUME_NONNULL_BEGIN

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

OF_ASSUME_NONNULL_END

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

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

18

19
20
21
22
23
24
25
26
27
28
29
30
31
32



33
34
35



36



37
38
39
40
41
42
43
44
45

46
47
48

49
50
51
52
53
54
55
56
57
58
59
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"


#define _LARGEFILE64_SOURCE


#include <errno.h>
#include <math.h>

#ifdef HAVE_DIRENT_H
# include <dirent.h>
#endif
#include "unistd_wrapper.h"

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



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







#ifdef HAVE_PWD_H
# include <pwd.h>
#endif
#ifdef HAVE_GRP_H
# include <grp.h>
#endif

#import "OFFileURIHandler.h"
#import "OFArray.h"

#import "OFDate.h"
#import "OFFile.h"
#import "OFFileManager.h"

#import "OFLocale.h"
#import "OFNumber.h"
#import "OFSystemInfo.h"
#import "OFURI.h"

#ifdef OF_HAVE_THREADS
# import "OFMutex.h"
#endif

#import "OFCreateDirectoryFailedException.h"
#import "OFCreateSymbolicLinkFailedException.h"

|















>
|
>














>
>
>



>
>
>

>
>
>







|

>



>



<







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

65
66
67
68
69
70
71
/*
 * Copyright (c) 2008-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"

#ifndef _LARGEFILE64_SOURCE
# define _LARGEFILE64_SOURCE
#endif

#include <errno.h>
#include <math.h>

#ifdef HAVE_DIRENT_H
# include <dirent.h>
#endif
#include "unistd_wrapper.h"

#include "platform.h"
#ifdef HAVE_SYS_STAT_H
# include <sys/stat.h>
#endif
#include <sys/time.h>
#if defined(OF_LINUX) || defined(OF_MACOS)
# include <sys/xattr.h>
#endif
#ifdef OF_WINDOWS
# include <utime.h>
#endif
#ifdef OF_DJGPP
# include <syslimits.h>
#endif

#ifdef HAVE_FCNTL_H
# include <fcntl.h>
#endif
#ifdef HAVE_PWD_H
# include <pwd.h>
#endif
#ifdef HAVE_GRP_H
# include <grp.h>
#endif

#import "OFFileIRIHandler.h"
#import "OFArray.h"
#import "OFData.h"
#import "OFDate.h"
#import "OFFile.h"
#import "OFFileManager.h"
#import "OFIRI.h"
#import "OFLocale.h"
#import "OFNumber.h"
#import "OFSystemInfo.h"


#ifdef OF_HAVE_THREADS
# import "OFMutex.h"
#endif

#import "OFCreateDirectoryFailedException.h"
#import "OFCreateSymbolicLinkFailedException.h"
73
74
75
76
77
78
79

80
81
82

83
84
85
86
87
88
89
# include <windows.h>
# include <direct.h>
# include <ntdef.h>
# include <wchar.h>
#endif

#ifdef OF_AMIGAOS

# include <proto/exec.h>
# include <proto/dos.h>
# include <proto/locale.h>

# ifdef OF_AMIGAOS4
#  define DeleteFile(path) Delete(path)
# endif
#endif

#if defined(OF_WINDOWS) || defined(OF_AMIGAOS)
typedef struct {







>



>







85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# include <windows.h>
# include <direct.h>
# include <ntdef.h>
# include <wchar.h>
#endif

#ifdef OF_AMIGAOS
# define Class IntuitionClass
# include <proto/exec.h>
# include <proto/dos.h>
# include <proto/locale.h>
# undef Class
# ifdef OF_AMIGAOS4
#  define DeleteFile(path) Delete(path)
# endif
#endif

#if defined(OF_WINDOWS) || defined(OF_AMIGAOS)
typedef struct {
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533

















































534














































535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
# endif
#endif
}

#ifdef OF_FILE_MANAGER_SUPPORTS_SYMLINKS
static void
setSymbolicLinkDestinationAttribute(OFMutableFileAttributes attributes,
    OFURI *URI)
{
	OFString *path = URI.fileSystemRepresentation;
# ifndef OF_WINDOWS
	OFStringEncoding encoding = [OFLocale encoding];
	char destinationC[PATH_MAX];
	ssize_t length;
	OFString *destination;

	length = readlink([path cStringWithEncoding: encoding], destinationC,
	    PATH_MAX);

	if (length < 0)
		@throw [OFGetItemAttributesFailedException
		    exceptionWithURI: URI
			       errNo: errno];

	destination = [OFString stringWithCString: destinationC
					 encoding: encoding
					   length: length];

	[attributes setObject: destination
		       forKey: OFFileSymbolicLinkDestination];
# else
	HANDLE handle;
	OFString *destination;

	if (createSymbolicLinkWFuncPtr == NULL)
		return;

	if ((handle = CreateFileW(path.UTF16String, 0, (FILE_SHARE_READ |
	    FILE_SHARE_WRITE), NULL, OPEN_EXISTING,
	    FILE_FLAG_OPEN_REPARSE_POINT, NULL)) == INVALID_HANDLE_VALUE)
		@throw [OFGetItemAttributesFailedException
		    exceptionWithURI: URI
			       errNo: lastError()];

	@try {
		union {
			char bytes[MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
			REPARSE_DATA_BUFFER data;
		} buffer;
		DWORD size;
		wchar_t *tmp;

		if (!DeviceIoControl(handle, FSCTL_GET_REPARSE_POINT, NULL, 0,
		    buffer.bytes, MAXIMUM_REPARSE_DATA_BUFFER_SIZE, &size,
		    NULL))
			@throw [OFGetItemAttributesFailedException
			    exceptionWithURI: URI
				       errNo: lastError()];

		if (buffer.data.ReparseTag != IO_REPARSE_TAG_SYMLINK)
			@throw [OFGetItemAttributesFailedException
			    exceptionWithURI: URI
				       errNo: lastError()];

#  define slrb buffer.data.SymbolicLinkReparseBuffer
		tmp = slrb.PathBuffer +
		    (slrb.SubstituteNameOffset / sizeof(wchar_t));

		destination = [OFString
		    stringWithUTF16String: tmp
				   length: slrb.SubstituteNameLength /
					   sizeof(wchar_t)];

		[attributes setObject: OFFileTypeSymbolicLink
			       forKey: OFFileType];
		[attributes setObject: destination
			       forKey: OFFileSymbolicLinkDestination];
#  undef slrb
	} @finally {
		CloseHandle(handle);
	}

















































# endif














































}
#endif

@implementation OFFileURIHandler
+ (void)initialize
{
#ifdef OF_WINDOWS
	HMODULE module;
#endif

	if (self != [OFFileURIHandler class])
		return;

#if defined(OF_FILE_MANAGER_SUPPORTS_OWNER) && defined(OF_HAVE_THREADS)
	passwdMutex = [[OFMutex alloc] init];
	atexit(releasePasswdMutex);
#endif
#if !defined(HAVE_READDIR_R) && !defined(OF_WINDOWS) && defined(OF_HAVE_THREADS)
	readdirMutex = [[OFMutex alloc] init];
	atexit(releaseReaddirMutex);
#endif

#ifdef OF_WINDOWS
	if ((module = LoadLibrary("msvcrt.dll")) != NULL)
		_wutime64FuncPtr = (int (*)(const wchar_t *,
		    struct __utimbuf64 *))GetProcAddress(module, "_wutime64");

	if ((module = LoadLibrary("kernel32.dll")) != NULL) {
		createSymbolicLinkWFuncPtr =
		    (WINAPI BOOLEAN (*)(LPCWSTR, LPCWSTR, DWORD))
		    GetProcAddress(module, "CreateSymbolicLinkW");
		createHardLinkWFuncPtr =
		    (WINAPI BOOLEAN (*)(LPCWSTR, LPCWSTR,
		    LPSECURITY_ATTRIBUTES))
		    GetProcAddress(module, "CreateHardLinkW");







|

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










|














|




|



















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

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



|






|












|



|







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
# endif
#endif
}

#ifdef OF_FILE_MANAGER_SUPPORTS_SYMLINKS
static void
setSymbolicLinkDestinationAttribute(OFMutableFileAttributes attributes,
    OFIRI *IRI)
{
	OFString *path = IRI.fileSystemRepresentation;
# ifdef OF_WINDOWS




















	HANDLE handle;
	OFString *destination;

	if (createSymbolicLinkWFuncPtr == NULL)
		return;

	if ((handle = CreateFileW(path.UTF16String, 0, (FILE_SHARE_READ |
	    FILE_SHARE_WRITE), NULL, OPEN_EXISTING,
	    FILE_FLAG_OPEN_REPARSE_POINT, NULL)) == INVALID_HANDLE_VALUE)
		@throw [OFGetItemAttributesFailedException
		    exceptionWithIRI: IRI
			       errNo: lastError()];

	@try {
		union {
			char bytes[MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
			REPARSE_DATA_BUFFER data;
		} buffer;
		DWORD size;
		wchar_t *tmp;

		if (!DeviceIoControl(handle, FSCTL_GET_REPARSE_POINT, NULL, 0,
		    buffer.bytes, MAXIMUM_REPARSE_DATA_BUFFER_SIZE, &size,
		    NULL))
			@throw [OFGetItemAttributesFailedException
			    exceptionWithIRI: IRI
				       errNo: lastError()];

		if (buffer.data.ReparseTag != IO_REPARSE_TAG_SYMLINK)
			@throw [OFGetItemAttributesFailedException
			    exceptionWithIRI: IRI
				       errNo: lastError()];

#  define slrb buffer.data.SymbolicLinkReparseBuffer
		tmp = slrb.PathBuffer +
		    (slrb.SubstituteNameOffset / sizeof(wchar_t));

		destination = [OFString
		    stringWithUTF16String: tmp
				   length: slrb.SubstituteNameLength /
					   sizeof(wchar_t)];

		[attributes setObject: OFFileTypeSymbolicLink
			       forKey: OFFileType];
		[attributes setObject: destination
			       forKey: OFFileSymbolicLinkDestination];
#  undef slrb
	} @finally {
		CloseHandle(handle);
	}
# elif defined(OF_HURD)
	OFStringEncoding encoding = [OFLocale encoding];
	int fd;
	OFMutableData *destinationData;
	OFString *destination;

	fd = open([path cStringWithEncoding: encoding], O_RDONLY | O_NOLINK);
	if (fd == -1)
		@throw [OFGetItemAttributesFailedException
		    exceptionWithIRI: IRI
			       errNo: errno];

	@try {
		char buffer[512];
		ssize_t length;

		destinationData = [OFMutableData data];
		while ((length = read(fd, buffer, 512)) > 0)
			[destinationData addItems: buffer count: length];
	} @finally {
		close(fd);
	}

	destination = [OFString stringWithCString: destinationData.items
					 encoding: encoding
					   length: destinationData.count];

	[attributes setObject: destination
		       forKey: OFFileSymbolicLinkDestination];
# else
	OFStringEncoding encoding = [OFLocale encoding];
	char destinationC[PATH_MAX];
	ssize_t length;
	OFString *destination;

	length = readlink([path cStringWithEncoding: encoding], destinationC,
	    PATH_MAX);

	if (length < 0)
		@throw [OFGetItemAttributesFailedException
		    exceptionWithIRI: IRI
			       errNo: errno];

	destination = [OFString stringWithCString: destinationC
					 encoding: encoding
					   length: length];

	[attributes setObject: destination
		       forKey: OFFileSymbolicLinkDestination];
# endif
}
#endif

#ifdef OF_FILE_MANAGER_SUPPORTS_EXTENDED_ATTRIBUTES
static void
setExtendedAttributes(OFMutableFileAttributes attributes, OFIRI *IRI)
{
	OFString *path = IRI.fileSystemRepresentation;
	OFStringEncoding encoding = [OFLocale encoding];
	const char *cPath = [path cStringWithEncoding: encoding];
# if defined(OF_LINUX)
	ssize_t size = llistxattr(cPath, NULL, 0);
# elif defined(OF_MACOS)
	ssize_t size = listxattr(cPath, NULL, 0, XATTR_NOFOLLOW);
# endif
	char *list = OFAllocMemory(1, size);
	OFMutableArray *names = nil;

	@try {
		char *name;

# if defined(OF_LINUX)
		if ((size = llistxattr(cPath, list, size)) < 0)
# elif defined(OF_MACOS)
		if ((size = listxattr(cPath, list, size, XATTR_NOFOLLOW)) < 0)
# endif
			return;

		names = [OFMutableArray array];
		name = list;

		while (size > 0) {
			size_t length = strlen(name);

			[names addObject: [OFString stringWithCString: name
							     encoding: encoding
							       length: length]];

			name += length + 1;
			size -= length + 1;
		}
	} @finally {
		OFFreeMemory(list);
	}

	[attributes setObject: names forKey: OFFileExtendedAttributesNames];
}
#endif

@implementation OFFileIRIHandler
+ (void)initialize
{
#ifdef OF_WINDOWS
	HMODULE module;
#endif

	if (self != [OFFileIRIHandler class])
		return;

#if defined(OF_FILE_MANAGER_SUPPORTS_OWNER) && defined(OF_HAVE_THREADS)
	passwdMutex = [[OFMutex alloc] init];
	atexit(releasePasswdMutex);
#endif
#if !defined(HAVE_READDIR_R) && !defined(OF_WINDOWS) && defined(OF_HAVE_THREADS)
	readdirMutex = [[OFMutex alloc] init];
	atexit(releaseReaddirMutex);
#endif

#ifdef OF_WINDOWS
	if ((module = GetModuleHandle("msvcrt.dll")) != NULL)
		_wutime64FuncPtr = (int (*)(const wchar_t *,
		    struct __utimbuf64 *))GetProcAddress(module, "_wutime64");

	if ((module = GetModuleHandleA("kernel32.dll")) != NULL) {
		createSymbolicLinkWFuncPtr =
		    (WINAPI BOOLEAN (*)(LPCWSTR, LPCWSTR, DWORD))
		    GetProcAddress(module, "CreateSymbolicLinkW");
		createHardLinkWFuncPtr =
		    (WINAPI BOOLEAN (*)(LPCWSTR, LPCWSTR,
		    LPSECURITY_ATTRIBUTES))
		    GetProcAddress(module, "CreateHardLinkW");
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

	if (statWrapper(path, &s) != 0)
		return false;

	return S_ISDIR(s.st_mode);
}

- (OFStream *)openItemAtURI: (OFURI *)URI mode: (OFString *)mode
{
	void *pool = objc_autoreleasePoolPush();
	OFFile *file = [[OFFile alloc]
	    initWithPath: URI.fileSystemRepresentation
		    mode: mode];

	objc_autoreleasePoolPop(pool);

	return [file autorelease];
}

- (OFFileAttributes)attributesOfItemAtURI: (OFURI *)URI
{
	OFMutableFileAttributes ret = [OFMutableDictionary dictionary];
	void *pool = objc_autoreleasePoolPush();
	OFString *path;
	int error;
	Stat s;

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

	if (![[URI scheme] isEqual: _scheme])
		@throw [OFInvalidArgumentException exception];

	path = URI.fileSystemRepresentation;

	if ((error = lstatWrapper(path, &s)) != 0)
		@throw [OFGetItemAttributesFailedException
		    exceptionWithURI: URI
			       errNo: error];

	if (s.st_size < 0)
		@throw [OFOutOfRangeException exception];

	[ret setObject: [NSNumber numberWithUnsignedLongLong: s.st_size]
		forKey: OFFileSize];

	setTypeAttribute(ret, &s);

	[ret setObject: [NSNumber numberWithUnsignedLong: s.st_mode]
		forKey: OFFilePOSIXPermissions];

	setOwnerAndGroupAttributes(ret, &s);
	setDateAttributes(ret, &s);

#ifdef OF_FILE_MANAGER_SUPPORTS_SYMLINKS
	if (S_ISLNK(s.st_mode))
		setSymbolicLinkDestinationAttribute(ret, URI);




#endif

	objc_autoreleasePoolPop(pool);

	return ret;
}

- (void)of_setLastAccessDate: (OFDate *)lastAccessDate
	 andModificationDate: (OFDate *)modificationDate
		 ofItemAtURI: (OFURI *)URI
		  attributes: (OFFileAttributes)attributes OF_DIRECT
{
	OFString *path = URI.fileSystemRepresentation;
	OFFileAttributeKey attributeKey = (modificationDate != nil
	    ? OFFileModificationDate : OFFileLastAccessDate);

	if (lastAccessDate == nil)
		lastAccessDate = modificationDate;
	if (modificationDate == nil)
		modificationDate = lastAccessDate;

#if defined(OF_WINDOWS)
	if (_wutime64FuncPtr != NULL) {
		struct __utimbuf64 times = {
			.actime =
			    (__time64_t)lastAccessDate.timeIntervalSince1970,
			.modtime =
			    (__time64_t)modificationDate.timeIntervalSince1970
		};

		if (_wutime64FuncPtr([path UTF16String], &times) != 0)





			@throw [OFSetItemAttributesFailedException
			    exceptionWithURI: URI
				  attributes: attributes
			     failedAttribute: attributeKey
				       errNo: errno];

	} else {
		struct _utimbuf times = {
			.actime = (time_t)lastAccessDate.timeIntervalSince1970,
			.modtime =
			    (time_t)modificationDate.timeIntervalSince1970
		};
		int status;

		if ([OFSystemInfo isWindowsNT])
			status = _wutime([path UTF16String], &times);
		else
			status = _utime(
			    [path cStringWithEncoding: [OFLocale encoding]],
			    &times);

		if (status != 0)





			@throw [OFSetItemAttributesFailedException
			    exceptionWithURI: URI
				  attributes: attributes
			     failedAttribute: attributeKey
				       errNo: errno];

	}
#elif defined(OF_AMIGAOS)
	/* AmigaOS does not support access time. */
	OFTimeInterval modificationTime =
	    modificationDate.timeIntervalSince1970;
	struct Locale *locale;
	struct DateStamp date;







|



|







|







|


|


|



|


















|
>
>
>
>









|


|

















|
>
>
>
>
>

|


|
>















|
>
>
>
>
>

|


|
>







672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808

	if (statWrapper(path, &s) != 0)
		return false;

	return S_ISDIR(s.st_mode);
}

- (OFStream *)openItemAtIRI: (OFIRI *)IRI mode: (OFString *)mode
{
	void *pool = objc_autoreleasePoolPush();
	OFFile *file = [[OFFile alloc]
	    initWithPath: IRI.fileSystemRepresentation
		    mode: mode];

	objc_autoreleasePoolPop(pool);

	return [file autorelease];
}

- (OFFileAttributes)attributesOfItemAtIRI: (OFIRI *)IRI
{
	OFMutableFileAttributes ret = [OFMutableDictionary dictionary];
	void *pool = objc_autoreleasePoolPush();
	OFString *path;
	int error;
	Stat s;

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

	if (![[IRI scheme] isEqual: _scheme])
		@throw [OFInvalidArgumentException exception];

	path = IRI.fileSystemRepresentation;

	if ((error = lstatWrapper(path, &s)) != 0)
		@throw [OFGetItemAttributesFailedException
		    exceptionWithIRI: IRI
			       errNo: error];

	if (s.st_size < 0)
		@throw [OFOutOfRangeException exception];

	[ret setObject: [NSNumber numberWithUnsignedLongLong: s.st_size]
		forKey: OFFileSize];

	setTypeAttribute(ret, &s);

	[ret setObject: [NSNumber numberWithUnsignedLong: s.st_mode]
		forKey: OFFilePOSIXPermissions];

	setOwnerAndGroupAttributes(ret, &s);
	setDateAttributes(ret, &s);

#ifdef OF_FILE_MANAGER_SUPPORTS_SYMLINKS
	if (S_ISLNK(s.st_mode))
		setSymbolicLinkDestinationAttribute(ret, IRI);
#endif

#ifdef OF_FILE_MANAGER_SUPPORTS_EXTENDED_ATTRIBUTES
	setExtendedAttributes(ret, IRI);
#endif

	objc_autoreleasePoolPop(pool);

	return ret;
}

- (void)of_setLastAccessDate: (OFDate *)lastAccessDate
	 andModificationDate: (OFDate *)modificationDate
		 ofItemAtIRI: (OFIRI *)IRI
		  attributes: (OFFileAttributes)attributes OF_DIRECT
{
	OFString *path = IRI.fileSystemRepresentation;
	OFFileAttributeKey attributeKey = (modificationDate != nil
	    ? OFFileModificationDate : OFFileLastAccessDate);

	if (lastAccessDate == nil)
		lastAccessDate = modificationDate;
	if (modificationDate == nil)
		modificationDate = lastAccessDate;

#if defined(OF_WINDOWS)
	if (_wutime64FuncPtr != NULL) {
		struct __utimbuf64 times = {
			.actime =
			    (__time64_t)lastAccessDate.timeIntervalSince1970,
			.modtime =
			    (__time64_t)modificationDate.timeIntervalSince1970
		};

		if (_wutime64FuncPtr([path UTF16String], &times) != 0) {
			int errNo = errno;

			if (errNo == EACCES && [self directoryExistsAtIRI: IRI])
				errNo = EISDIR;

			@throw [OFSetItemAttributesFailedException
			    exceptionWithIRI: IRI
				  attributes: attributes
			     failedAttribute: attributeKey
				       errNo: errNo];
		}
	} else {
		struct _utimbuf times = {
			.actime = (time_t)lastAccessDate.timeIntervalSince1970,
			.modtime =
			    (time_t)modificationDate.timeIntervalSince1970
		};
		int status;

		if ([OFSystemInfo isWindowsNT])
			status = _wutime([path UTF16String], &times);
		else
			status = _utime(
			    [path cStringWithEncoding: [OFLocale encoding]],
			    &times);

		if (status != 0) {
			int errNo = errno;

			if (errNo == EACCES && [self directoryExistsAtIRI: IRI])
				errNo = EISDIR;

			@throw [OFSetItemAttributesFailedException
			    exceptionWithIRI: IRI
				  attributes: attributes
			     failedAttribute: attributeKey
				       errNo: errNo];
		}
	}
#elif defined(OF_AMIGAOS)
	/* AmigaOS does not support access time. */
	OFTimeInterval modificationTime =
	    modificationDate.timeIntervalSince1970;
	struct Locale *locale;
	struct DateStamp date;
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
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
	if (!SetDate([path cStringWithEncoding: [OFLocale encoding]],
	    &date) != 0)
# else
	if (!SetFileDate([path cStringWithEncoding: [OFLocale encoding]],
	    &date) != 0)
# endif
		@throw [OFSetItemAttributesFailedException
		    exceptionWithURI: URI
			  attributes: attributes
		     failedAttribute: attributeKey
			       errNo: lastError()];
#else
	OFTimeInterval lastAccessTime = lastAccessDate.timeIntervalSince1970;
	OFTimeInterval modificationTime =
	    modificationDate.timeIntervalSince1970;
	struct timeval times[2] = {
		{
			.tv_sec = (time_t)lastAccessTime,
			.tv_usec =
			    (int)((lastAccessTime - times[0].tv_sec) * 1000000)
		},
		{
			.tv_sec = (time_t)modificationTime,
			.tv_usec = (int)((modificationTime - times[1].tv_sec) *
			    1000000)
		},
	};

	if (utimes([path cStringWithEncoding: [OFLocale encoding]], times) != 0)
		@throw [OFSetItemAttributesFailedException
		    exceptionWithURI: URI
			  attributes: attributes
		     failedAttribute: attributeKey
			       errNo: errno];
#endif
}

- (void)of_setPOSIXPermissions: (OFNumber *)permissions
		   ofItemAtURI: (OFURI *)URI
		    attributes: (OFFileAttributes)attributes OF_DIRECT
{
#ifdef OF_FILE_MANAGER_SUPPORTS_PERMISSIONS
	mode_t mode = (mode_t)permissions.unsignedLongValue;
	OFString *path = URI.fileSystemRepresentation;
	int status;

# ifdef OF_WINDOWS
	if ([OFSystemInfo isWindowsNT])
		status = _wchmod(path.UTF16String, mode);
	else
# endif
		status = chmod(
		    [path cStringWithEncoding: [OFLocale encoding]], mode);

	if (status != 0)
		@throw [OFSetItemAttributesFailedException
		    exceptionWithURI: URI
			  attributes: attributes
		     failedAttribute: OFFilePOSIXPermissions
			       errNo: errno];
#else
	OF_UNRECOGNIZED_SELECTOR
#endif
}

- (void)of_setOwnerAccountName: (OFString *)owner
      andGroupOwnerAccountName: (OFString *)group
		   ofItemAtURI: (OFURI *)URI
		  attributeKey: (OFFileAttributeKey)attributeKey
		    attributes: (OFFileAttributes)attributes OF_DIRECT
{
#ifdef OF_FILE_MANAGER_SUPPORTS_OWNER
	OFString *path = URI.fileSystemRepresentation;
	uid_t uid = -1;
	gid_t gid = -1;
	OFStringEncoding encoding;

	if (owner == nil && group == nil)
		@throw [OFInvalidArgumentException exception];

	encoding = [OFLocale encoding];

# ifdef OF_HAVE_THREADS
	[passwdMutex lock];
	@try {
# endif
		if (owner != nil) {
			struct passwd *passwd;

			if ((passwd = getpwnam([owner
			    cStringWithEncoding: encoding])) == NULL)
				@throw [OFSetItemAttributesFailedException
				    exceptionWithURI: URI
					  attributes: attributes
				     failedAttribute: attributeKey
					       errNo: errno];

			uid = passwd->pw_uid;
		}

		if (group != nil) {
			struct group *group_;

			if ((group_ = getgrnam([group
			    cStringWithEncoding: encoding])) == NULL)
				@throw [OFSetItemAttributesFailedException
				    exceptionWithURI: URI
					  attributes: attributes
				     failedAttribute: attributeKey
					       errNo: errno];

			gid = group_->gr_gid;
		}
# ifdef OF_HAVE_THREADS
	} @finally {
		[passwdMutex unlock];
	}
# endif

	if (chown([path cStringWithEncoding: encoding], uid, gid) != 0)
		@throw [OFSetItemAttributesFailedException
		    exceptionWithURI: URI
			  attributes: attributes
		     failedAttribute: attributeKey
			       errNo: errno];
#else
	OF_UNRECOGNIZED_SELECTOR
#endif
}

- (void)setAttributes: (OFFileAttributes)attributes ofItemAtURI: (OFURI *)URI
{
	void *pool = objc_autoreleasePoolPush();
	OFEnumerator OF_GENERIC(OFFileAttributeKey) *keyEnumerator;
	OFEnumerator *objectEnumerator;
	OFFileAttributeKey key;
	id object;
	OFDate *lastAccessDate, *modificationDate;

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

	if (![URI.scheme isEqual: _scheme])
		@throw [OFInvalidArgumentException exception];

	keyEnumerator = [attributes keyEnumerator];
	objectEnumerator = [attributes objectEnumerator];

	while ((key = [keyEnumerator nextObject]) != nil &&
	    (object = [objectEnumerator nextObject]) != nil) {
		if ([key isEqual: OFFileModificationDate] ||
		    [key isEqual: OFFileLastAccessDate])
			continue;
		else if ([key isEqual: OFFilePOSIXPermissions])
			[self of_setPOSIXPermissions: object
					 ofItemAtURI: URI
					  attributes: attributes];
		else if ([key isEqual: OFFileOwnerAccountName])
			[self of_setOwnerAccountName: object
			    andGroupOwnerAccountName: nil
					 ofItemAtURI: URI
					attributeKey: key
					  attributes: attributes];
		else if ([key isEqual: OFFileGroupOwnerAccountName])
			[self of_setOwnerAccountName: nil
			    andGroupOwnerAccountName: object
					 ofItemAtURI: URI
					attributeKey: key
					  attributes: attributes];
		else
			@throw [OFNotImplementedException
			    exceptionWithSelector: _cmd
					   object: self];
	}

	lastAccessDate = [attributes objectForKey: OFFileLastAccessDate];
	modificationDate = [attributes objectForKey: OFFileModificationDate];

	if (lastAccessDate != nil || modificationDate != nil)
		[self of_setLastAccessDate: lastAccessDate
		       andModificationDate: modificationDate
			       ofItemAtURI: URI
				attributes: attributes];

	objc_autoreleasePoolPop(pool);
}

- (bool)fileExistsAtURI: (OFURI *)URI
{
	void *pool = objc_autoreleasePoolPush();
	Stat s;
	bool ret;

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

	if (![URI.scheme isEqual: _scheme])
		@throw [OFInvalidArgumentException exception];

	if (statWrapper(URI.fileSystemRepresentation, &s) != 0) {
		objc_autoreleasePoolPop(pool);
		return false;
	}

	ret = S_ISREG(s.st_mode);

	objc_autoreleasePoolPop(pool);

	return ret;
}

- (bool)directoryExistsAtURI: (OFURI *)URI
{
	void *pool = objc_autoreleasePoolPush();
	Stat s;
	bool ret;

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

	if (![URI.scheme isEqual: _scheme])
		@throw [OFInvalidArgumentException exception];

	if (statWrapper(URI.fileSystemRepresentation, &s) != 0) {
		objc_autoreleasePoolPop(pool);
		return false;
	}

	ret = S_ISDIR(s.st_mode);

	objc_autoreleasePoolPop(pool);

	return ret;
}

- (void)createDirectoryAtURI: (OFURI *)URI
{
	void *pool = objc_autoreleasePoolPush();
	OFString *path;

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

	if (![URI.scheme isEqual: _scheme])
		@throw [OFInvalidArgumentException exception];

	path = URI.fileSystemRepresentation;

#if defined(OF_WINDOWS)
	int status;

	if ([OFSystemInfo isWindowsNT])
		status = _wmkdir(path.UTF16String);
	else
		status = _mkdir(
		    [path cStringWithEncoding: [OFLocale encoding]]);

	if (status != 0)
		@throw [OFCreateDirectoryFailedException
		    exceptionWithURI: URI
			       errNo: errno];
#elif defined(OF_AMIGAOS)
	BPTR lock;

	if ((lock = CreateDir(
	    [path cStringWithEncoding: [OFLocale encoding]])) == 0)
		@throw [OFCreateDirectoryFailedException
		    exceptionWithURI: URI
			       errNo: lastError()];

	UnLock(lock);
#else
	if (mkdir([path cStringWithEncoding: [OFLocale encoding]], 0777) != 0)
		@throw [OFCreateDirectoryFailedException
		    exceptionWithURI: URI
			       errNo: errno];
#endif

	objc_autoreleasePoolPop(pool);
}

- (OFArray OF_GENERIC(OFURI *) *)contentsOfDirectoryAtURI: (OFURI *)URI
{
	OFMutableArray *URIs = [OFMutableArray array];
	void *pool = objc_autoreleasePoolPush();
	OFString *path;

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

	if (![URI.scheme isEqual: _scheme])
		@throw [OFInvalidArgumentException exception];

	path = URI.fileSystemRepresentation;

#if defined(OF_WINDOWS)
	HANDLE handle;

	path = [path stringByAppendingString: @"\\*"];

	if ([OFSystemInfo isWindowsNT]) {
		WIN32_FIND_DATAW fd;

		if ((handle = FindFirstFileW(path.UTF16String,
		    &fd)) == INVALID_HANDLE_VALUE)
			@throw [OFOpenItemFailedException
			    exceptionWithURI: URI
					mode: nil
				       errNo: lastError()];

		@try {
			do {
				OFString *file;

				if (wcscmp(fd.cFileName, L".") == 0 ||
				    wcscmp(fd.cFileName, L"..") == 0)
					continue;

				file = [[OFString alloc]
				    initWithUTF16String: fd.cFileName];
				@try {
					[URIs addObject: [URI
					    URIByAppendingPathComponent: file]];
				} @finally {
					[file release];
				}
			} while (FindNextFileW(handle, &fd));

			if (GetLastError() != ERROR_NO_MORE_FILES)
				@throw [OFReadFailedException







|










|
|



|
|





|







|




|












|










|




|



















|













|














|








|








|


|












|




|





|














|





|





|


|


|
<
<
<
<
<






|





|


|


|











|




|


|


|












|







|






|






|

|



|


|


|












|














|
|







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
	if (!SetDate([path cStringWithEncoding: [OFLocale encoding]],
	    &date) != 0)
# else
	if (!SetFileDate([path cStringWithEncoding: [OFLocale encoding]],
	    &date) != 0)
# endif
		@throw [OFSetItemAttributesFailedException
		    exceptionWithIRI: IRI
			  attributes: attributes
		     failedAttribute: attributeKey
			       errNo: lastError()];
#else
	OFTimeInterval lastAccessTime = lastAccessDate.timeIntervalSince1970;
	OFTimeInterval modificationTime =
	    modificationDate.timeIntervalSince1970;
	struct timeval times[2] = {
		{
			.tv_sec = (time_t)lastAccessTime,
			.tv_usec = (int)((lastAccessTime -
			    (time_t)lastAccessTime) * 1000000)
		},
		{
			.tv_sec = (time_t)modificationTime,
			.tv_usec = (int)((modificationTime -
			    (time_t)modificationTime) * 1000000)
		},
	};

	if (utimes([path cStringWithEncoding: [OFLocale encoding]], times) != 0)
		@throw [OFSetItemAttributesFailedException
		    exceptionWithIRI: IRI
			  attributes: attributes
		     failedAttribute: attributeKey
			       errNo: errno];
#endif
}

- (void)of_setPOSIXPermissions: (OFNumber *)permissions
		   ofItemAtIRI: (OFIRI *)IRI
		    attributes: (OFFileAttributes)attributes OF_DIRECT
{
#ifdef OF_FILE_MANAGER_SUPPORTS_PERMISSIONS
	mode_t mode = (mode_t)permissions.unsignedLongValue;
	OFString *path = IRI.fileSystemRepresentation;
	int status;

# ifdef OF_WINDOWS
	if ([OFSystemInfo isWindowsNT])
		status = _wchmod(path.UTF16String, mode);
	else
# endif
		status = chmod(
		    [path cStringWithEncoding: [OFLocale encoding]], mode);

	if (status != 0)
		@throw [OFSetItemAttributesFailedException
		    exceptionWithIRI: IRI
			  attributes: attributes
		     failedAttribute: OFFilePOSIXPermissions
			       errNo: errno];
#else
	OF_UNRECOGNIZED_SELECTOR
#endif
}

- (void)of_setOwnerAccountName: (OFString *)owner
      andGroupOwnerAccountName: (OFString *)group
		   ofItemAtIRI: (OFIRI *)IRI
		  attributeKey: (OFFileAttributeKey)attributeKey
		    attributes: (OFFileAttributes)attributes OF_DIRECT
{
#ifdef OF_FILE_MANAGER_SUPPORTS_OWNER
	OFString *path = IRI.fileSystemRepresentation;
	uid_t uid = -1;
	gid_t gid = -1;
	OFStringEncoding encoding;

	if (owner == nil && group == nil)
		@throw [OFInvalidArgumentException exception];

	encoding = [OFLocale encoding];

# ifdef OF_HAVE_THREADS
	[passwdMutex lock];
	@try {
# endif
		if (owner != nil) {
			struct passwd *passwd;

			if ((passwd = getpwnam([owner
			    cStringWithEncoding: encoding])) == NULL)
				@throw [OFSetItemAttributesFailedException
				    exceptionWithIRI: IRI
					  attributes: attributes
				     failedAttribute: attributeKey
					       errNo: errno];

			uid = passwd->pw_uid;
		}

		if (group != nil) {
			struct group *group_;

			if ((group_ = getgrnam([group
			    cStringWithEncoding: encoding])) == NULL)
				@throw [OFSetItemAttributesFailedException
				    exceptionWithIRI: IRI
					  attributes: attributes
				     failedAttribute: attributeKey
					       errNo: errno];

			gid = group_->gr_gid;
		}
# ifdef OF_HAVE_THREADS
	} @finally {
		[passwdMutex unlock];
	}
# endif

	if (chown([path cStringWithEncoding: encoding], uid, gid) != 0)
		@throw [OFSetItemAttributesFailedException
		    exceptionWithIRI: IRI
			  attributes: attributes
		     failedAttribute: attributeKey
			       errNo: errno];
#else
	OF_UNRECOGNIZED_SELECTOR
#endif
}

- (void)setAttributes: (OFFileAttributes)attributes ofItemAtIRI: (OFIRI *)IRI
{
	void *pool = objc_autoreleasePoolPush();
	OFEnumerator OF_GENERIC(OFFileAttributeKey) *keyEnumerator;
	OFEnumerator *objectEnumerator;
	OFFileAttributeKey key;
	id object;
	OFDate *lastAccessDate, *modificationDate;

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

	if (![IRI.scheme isEqual: _scheme])
		@throw [OFInvalidArgumentException exception];

	keyEnumerator = [attributes keyEnumerator];
	objectEnumerator = [attributes objectEnumerator];

	while ((key = [keyEnumerator nextObject]) != nil &&
	    (object = [objectEnumerator nextObject]) != nil) {
		if ([key isEqual: OFFileModificationDate] ||
		    [key isEqual: OFFileLastAccessDate])
			continue;
		else if ([key isEqual: OFFilePOSIXPermissions])
			[self of_setPOSIXPermissions: object
					 ofItemAtIRI: IRI
					  attributes: attributes];
		else if ([key isEqual: OFFileOwnerAccountName])
			[self of_setOwnerAccountName: object
			    andGroupOwnerAccountName: nil
					 ofItemAtIRI: IRI
					attributeKey: key
					  attributes: attributes];
		else if ([key isEqual: OFFileGroupOwnerAccountName])
			[self of_setOwnerAccountName: nil
			    andGroupOwnerAccountName: object
					 ofItemAtIRI: IRI
					attributeKey: key
					  attributes: attributes];
		else
			@throw [OFNotImplementedException
			    exceptionWithSelector: _cmd
					   object: self];
	}

	lastAccessDate = [attributes objectForKey: OFFileLastAccessDate];
	modificationDate = [attributes objectForKey: OFFileModificationDate];

	if (lastAccessDate != nil || modificationDate != nil)
		[self of_setLastAccessDate: lastAccessDate
		       andModificationDate: modificationDate
			       ofItemAtIRI: IRI
				attributes: attributes];

	objc_autoreleasePoolPop(pool);
}

- (bool)fileExistsAtIRI: (OFIRI *)IRI
{
	void *pool = objc_autoreleasePoolPush();
	Stat s;
	bool ret;

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

	if (![IRI.scheme isEqual: _scheme])
		@throw [OFInvalidArgumentException exception];

	ret = (statWrapper(IRI.fileSystemRepresentation, &s) == 0);






	objc_autoreleasePoolPop(pool);

	return ret;
}

- (bool)directoryExistsAtIRI: (OFIRI *)IRI
{
	void *pool = objc_autoreleasePoolPush();
	Stat s;
	bool ret;

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

	if (![IRI.scheme isEqual: _scheme])
		@throw [OFInvalidArgumentException exception];

	if (statWrapper(IRI.fileSystemRepresentation, &s) != 0) {
		objc_autoreleasePoolPop(pool);
		return false;
	}

	ret = S_ISDIR(s.st_mode);

	objc_autoreleasePoolPop(pool);

	return ret;
}

- (void)createDirectoryAtIRI: (OFIRI *)IRI
{
	void *pool = objc_autoreleasePoolPush();
	OFString *path;

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

	if (![IRI.scheme isEqual: _scheme])
		@throw [OFInvalidArgumentException exception];

	path = IRI.fileSystemRepresentation;

#if defined(OF_WINDOWS)
	int status;

	if ([OFSystemInfo isWindowsNT])
		status = _wmkdir(path.UTF16String);
	else
		status = _mkdir(
		    [path cStringWithEncoding: [OFLocale encoding]]);

	if (status != 0)
		@throw [OFCreateDirectoryFailedException
		    exceptionWithIRI: IRI
			       errNo: errno];
#elif defined(OF_AMIGAOS)
	BPTR lock;

	if ((lock = CreateDir(
	    [path cStringWithEncoding: [OFLocale encoding]])) == 0)
		@throw [OFCreateDirectoryFailedException
		    exceptionWithIRI: IRI
			       errNo: lastError()];

	UnLock(lock);
#else
	if (mkdir([path cStringWithEncoding: [OFLocale encoding]], 0777) != 0)
		@throw [OFCreateDirectoryFailedException
		    exceptionWithIRI: IRI
			       errNo: errno];
#endif

	objc_autoreleasePoolPop(pool);
}

- (OFArray OF_GENERIC(OFIRI *) *)contentsOfDirectoryAtIRI: (OFIRI *)IRI
{
	OFMutableArray *IRIs = [OFMutableArray array];
	void *pool = objc_autoreleasePoolPush();
	OFString *path;

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

	if (![IRI.scheme isEqual: _scheme])
		@throw [OFInvalidArgumentException exception];

	path = IRI.fileSystemRepresentation;

#if defined(OF_WINDOWS)
	HANDLE handle;

	path = [path stringByAppendingString: @"\\*"];

	if ([OFSystemInfo isWindowsNT]) {
		WIN32_FIND_DATAW fd;

		if ((handle = FindFirstFileW(path.UTF16String,
		    &fd)) == INVALID_HANDLE_VALUE)
			@throw [OFOpenItemFailedException
			    exceptionWithIRI: IRI
					mode: nil
				       errNo: lastError()];

		@try {
			do {
				OFString *file;

				if (wcscmp(fd.cFileName, L".") == 0 ||
				    wcscmp(fd.cFileName, L"..") == 0)
					continue;

				file = [[OFString alloc]
				    initWithUTF16String: fd.cFileName];
				@try {
					[IRIs addObject: [IRI
					    IRIByAppendingPathComponent: file]];
				} @finally {
					[file release];
				}
			} while (FindNextFileW(handle, &fd));

			if (GetLastError() != ERROR_NO_MORE_FILES)
				@throw [OFReadFailedException
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
		OFStringEncoding encoding = [OFLocale encoding];
		WIN32_FIND_DATA fd;

		if ((handle = FindFirstFileA(
		    [path cStringWithEncoding: encoding], &fd)) ==
		    INVALID_HANDLE_VALUE)
			@throw [OFOpenItemFailedException
			    exceptionWithURI: URI
					mode: nil
				       errNo: lastError()];

		@try {
			do {
				OFString *file;

				if (strcmp(fd.cFileName, ".") == 0 ||
				    strcmp(fd.cFileName, "..") == 0)
					continue;

				file = [[OFString alloc]
				    initWithCString: fd.cFileName
					   encoding: encoding];
				@try {
					[URIs addObject: [URI
					    URIByAppendingPathComponent: file]];
				} @finally {
					[file release];
				}
			} while (FindNextFileA(handle, &fd));

			if (GetLastError() != ERROR_NO_MORE_FILES)
				@throw [OFReadFailedException







|















|
|







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
		OFStringEncoding encoding = [OFLocale encoding];
		WIN32_FIND_DATA fd;

		if ((handle = FindFirstFileA(
		    [path cStringWithEncoding: encoding], &fd)) ==
		    INVALID_HANDLE_VALUE)
			@throw [OFOpenItemFailedException
			    exceptionWithIRI: IRI
					mode: nil
				       errNo: lastError()];

		@try {
			do {
				OFString *file;

				if (strcmp(fd.cFileName, ".") == 0 ||
				    strcmp(fd.cFileName, "..") == 0)
					continue;

				file = [[OFString alloc]
				    initWithCString: fd.cFileName
					   encoding: encoding];
				@try {
					[IRIs addObject: [IRI
					    IRIByAppendingPathComponent: file]];
				} @finally {
					[file release];
				}
			} while (FindNextFileA(handle, &fd));

			if (GetLastError() != ERROR_NO_MORE_FILES)
				@throw [OFReadFailedException
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
#elif defined(OF_AMIGAOS)
	OFStringEncoding encoding = [OFLocale encoding];
	BPTR lock;

	if ((lock = Lock([path cStringWithEncoding: encoding],
	    SHARED_LOCK)) == 0)
		@throw [OFOpenItemFailedException
		    exceptionWithURI: URI
				mode: nil
			       errNo: lastError()];

	@try {
# ifdef OF_AMIGAOS4
		struct ExamineData *ed;
		APTR context;

		if ((context = ObtainDirContextTags(EX_FileLockInput, lock,
		    EX_DoCurrentDir, TRUE, EX_DataFields, EXF_NAME,
		    TAG_END)) == NULL)
			@throw [OFOpenItemFailedException
			    exceptionWithURI: URI
					mode: nil
				       errNo: lastError()];

		@try {
			while ((ed = ExamineDir(context)) != NULL) {
				OFString *file = [[OFString alloc]
				    initWithCString: ed->Name
					   encoding: encoding];

				@try {
					[URIs addObject: [URI
					    URIByAppendingPathComponent: file]];
				} @finally {
					[file release];
				}
			}
		} @finally {
			ReleaseDirContext(context);
		}
# else
		struct FileInfoBlock fib;

		if (!Examine(lock, &fib))
			@throw [OFOpenItemFailedException
			    exceptionWithURI: URI
					mode: nil
				       errNo: lastError()];

		while (ExNext(lock, &fib)) {
			OFString *file = [[OFString alloc]
			    initWithCString: fib.fib_FileName
				   encoding: encoding];
			@try {
				[URIs addObject:
				    [URI URIByAppendingPathComponent: file]];
			} @finally {
				[file release];
			}
		}
# endif

		if (IoErr() != ERROR_NO_MORE_ENTRIES)
			@throw [OFReadFailedException
			    exceptionWithObject: self
				requestedLength: 0
					  errNo: lastError()];
	} @finally {
		UnLock(lock);
	}
#else
	OFStringEncoding encoding = [OFLocale encoding];
	DIR *dir;
	if ((dir = opendir([path cStringWithEncoding: encoding])) == NULL)
		@throw [OFOpenItemFailedException exceptionWithURI: URI
							      mode: nil
							     errNo: errno];

# if !defined(HAVE_READDIR_R) && defined(OF_HAVE_THREADS)
	@try {
		[readdirMutex lock];
	} @catch (id e) {







|












|










|
|












|








|
|


















|







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
#elif defined(OF_AMIGAOS)
	OFStringEncoding encoding = [OFLocale encoding];
	BPTR lock;

	if ((lock = Lock([path cStringWithEncoding: encoding],
	    SHARED_LOCK)) == 0)
		@throw [OFOpenItemFailedException
		    exceptionWithIRI: IRI
				mode: nil
			       errNo: lastError()];

	@try {
# ifdef OF_AMIGAOS4
		struct ExamineData *ed;
		APTR context;

		if ((context = ObtainDirContextTags(EX_FileLockInput, lock,
		    EX_DoCurrentDir, TRUE, EX_DataFields, EXF_NAME,
		    TAG_END)) == NULL)
			@throw [OFOpenItemFailedException
			    exceptionWithIRI: IRI
					mode: nil
				       errNo: lastError()];

		@try {
			while ((ed = ExamineDir(context)) != NULL) {
				OFString *file = [[OFString alloc]
				    initWithCString: ed->Name
					   encoding: encoding];

				@try {
					[IRIs addObject: [IRI
					    IRIByAppendingPathComponent: file]];
				} @finally {
					[file release];
				}
			}
		} @finally {
			ReleaseDirContext(context);
		}
# else
		struct FileInfoBlock fib;

		if (!Examine(lock, &fib))
			@throw [OFOpenItemFailedException
			    exceptionWithIRI: IRI
					mode: nil
				       errNo: lastError()];

		while (ExNext(lock, &fib)) {
			OFString *file = [[OFString alloc]
			    initWithCString: fib.fib_FileName
				   encoding: encoding];
			@try {
				[IRIs addObject:
				    [IRI IRIByAppendingPathComponent: file]];
			} @finally {
				[file release];
			}
		}
# endif

		if (IoErr() != ERROR_NO_MORE_ENTRIES)
			@throw [OFReadFailedException
			    exceptionWithObject: self
				requestedLength: 0
					  errNo: lastError()];
	} @finally {
		UnLock(lock);
	}
#else
	OFStringEncoding encoding = [OFLocale encoding];
	DIR *dir;
	if ((dir = opendir([path cStringWithEncoding: encoding])) == NULL)
		@throw [OFOpenItemFailedException exceptionWithIRI: IRI
							      mode: nil
							     errNo: errno];

# if !defined(HAVE_READDIR_R) && defined(OF_HAVE_THREADS)
	@try {
		[readdirMutex lock];
	} @catch (id e) {
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
			if (strcmp(dirent->d_name, ".") == 0 ||
			    strcmp(dirent->d_name, "..") == 0)
				continue;

			file = [[OFString alloc] initWithCString: dirent->d_name
							encoding: encoding];
			@try {
				[URIs addObject:
				    [URI URIByAppendingPathComponent: file]];
			} @finally {
				[file release];
			}
		}
	} @finally {
		closedir(dir);
# if !defined(HAVE_READDIR_R) && defined(OF_HAVE_THREADS)
		[readdirMutex unlock];
# endif
	}
#endif

	[URIs makeImmutable];

	objc_autoreleasePoolPop(pool);

	return URIs;
}

- (void)removeItemAtURI: (OFURI *)URI
{
	void *pool = objc_autoreleasePoolPush();
	OFString *path;
	int error;
	Stat s;

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

	if (![URI.scheme isEqual: _scheme])
		@throw [OFInvalidArgumentException exception];

	path = URI.fileSystemRepresentation;

	if ((error = lstatWrapper(path, &s)) != 0)
		@throw [OFRemoveItemFailedException exceptionWithURI: URI
							       errNo: error];

	if (S_ISDIR(s.st_mode)) {
		OFArray OF_GENERIC(OFURI *) *contents;

		@try {
			contents = [self contentsOfDirectoryAtURI: URI];
		} @catch (id e) {
			/*
			 * Only convert exceptions to
			 * OFRemoveItemFailedException that have an errNo
			 * property. This covers all I/O related exceptions
			 * from the operations used to remove an item, all
			 * others should be left as is.
			 */
			if ([e respondsToSelector: @selector(errNo)])
				@throw [OFRemoveItemFailedException
				    exceptionWithURI: URI
					       errNo: [e errNo]];

			@throw e;
		}

		for (OFURI *item in contents) {
			void *pool2 = objc_autoreleasePoolPush();

			[self removeItemAtURI: item];

			objc_autoreleasePoolPop(pool2);
		}

#ifndef OF_AMIGAOS
		int status;

# ifdef OF_WINDOWS
		if ([OFSystemInfo isWindowsNT])
			status = _wrmdir(path.UTF16String);
		else
# endif
			status = rmdir(
			    [path cStringWithEncoding: [OFLocale encoding]]);

		if (status != 0)
			@throw [OFRemoveItemFailedException
				exceptionWithURI: URI
					   errNo: errno];
	} else {
		int status;

# ifdef OF_WINDOWS
		if ([OFSystemInfo isWindowsNT])
			status = _wunlink(path.UTF16String);
		else
# endif
			status = unlink(
			    [path cStringWithEncoding: [OFLocale encoding]]);

		if (status != 0)
			@throw [OFRemoveItemFailedException
			    exceptionWithURI: URI
				       errNo: errno];
#endif
	}

#ifdef OF_AMIGAOS
	if (!DeleteFile([path cStringWithEncoding: [OFLocale encoding]]))
		@throw [OFRemoveItemFailedException
		    exceptionWithURI: URI
			       errNo: lastError()];
#endif

	objc_autoreleasePoolPop(pool);
}

#ifdef OF_FILE_MANAGER_SUPPORTS_LINKS
- (void)linkItemAtURI: (OFURI *)source toURI: (OFURI *)destination
{
	void *pool = objc_autoreleasePoolPush();
	OFString *sourcePath, *destinationPath;

	if (source == nil || destination == nil)
		@throw [OFInvalidArgumentException exception];

	if (![source.scheme isEqual: _scheme] ||
	    ![destination.scheme isEqual: _scheme])
		@throw [OFInvalidArgumentException exception];

	sourcePath = source.fileSystemRepresentation;
	destinationPath = destination.fileSystemRepresentation;

# ifndef OF_WINDOWS
	OFStringEncoding encoding = [OFLocale encoding];

	if (link([sourcePath cStringWithEncoding: encoding],
	    [destinationPath cStringWithEncoding: encoding]) != 0)
		@throw [OFLinkItemFailedException
		    exceptionWithSourceURI: source
			    destinationURI: destination
				     errNo: errno];
# else
	if (createHardLinkWFuncPtr == NULL)
		@throw [OFNotImplementedException exceptionWithSelector: _cmd
								 object: self];

	if (!createHardLinkWFuncPtr(destinationPath.UTF16String,
	    sourcePath.UTF16String, NULL))
		@throw [OFLinkItemFailedException
		    exceptionWithSourceURI: source
			    destinationURI: destination
				     errNo: lastError()];
# endif

	objc_autoreleasePoolPop(pool);
}
#endif

#ifdef OF_FILE_MANAGER_SUPPORTS_SYMLINKS
- (void)createSymbolicLinkAtURI: (OFURI *)URI
	    withDestinationPath: (OFString *)target
{
	void *pool = objc_autoreleasePoolPush();
	OFString *path;

	if (URI == nil || target == nil)
		@throw [OFInvalidArgumentException exception];

	if (![URI.scheme isEqual: _scheme])
		@throw [OFInvalidArgumentException exception];

	path = URI.fileSystemRepresentation;

# ifndef OF_WINDOWS
	OFStringEncoding encoding = [OFLocale encoding];

	if (symlink([target cStringWithEncoding: encoding],
	    [path cStringWithEncoding: encoding]) != 0)
		@throw [OFCreateSymbolicLinkFailedException
		    exceptionWithURI: URI
			      target: target
			       errNo: errno];
# else
	if (createSymbolicLinkWFuncPtr == NULL)
		@throw [OFNotImplementedException exceptionWithSelector: _cmd
								 object: self];

	if (!createSymbolicLinkWFuncPtr(path.UTF16String, target.UTF16String,
	    0))
		@throw [OFCreateSymbolicLinkFailedException
		    exceptionWithURI: URI
			      target: target
			       errNo: lastError()];
# endif

	objc_autoreleasePoolPop(pool);
}
#endif

- (bool)moveItemAtURI: (OFURI *)source toURI: (OFURI *)destination
{
	void *pool;

	if (![source.scheme isEqual: _scheme] ||
	    ![destination.scheme isEqual: _scheme])
		return false;

	if ([self fileExistsAtURI: destination])
		@throw [OFMoveItemFailedException
		    exceptionWithSourceURI: source
			    destinationURI: destination
				     errNo: EEXIST];

	pool = objc_autoreleasePoolPush();

#ifdef OF_AMIGAOS
	OFStringEncoding encoding = [OFLocale encoding];

	if (!Rename([source.fileSystemRepresentation
	    cStringWithEncoding: encoding],
	    [destination.fileSystemRepresentation
	    cStringWithEncoding: encoding]))
		@throw [OFMoveItemFailedException
		    exceptionWithSourceURI: source
			    destinationURI: destination
				     errNo: lastError()];
#else
	int status;

# ifdef OF_WINDOWS
	if ([OFSystemInfo isWindowsNT])
		status = _wrename(source.fileSystemRepresentation.UTF16String,







|
|












|



|


|






|


|


|


|



|


|










|





|


|

















|














|







|







|




















|
|









|
|








|





|


|


|







|










|








|







|

|
|












|
|







1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
			if (strcmp(dirent->d_name, ".") == 0 ||
			    strcmp(dirent->d_name, "..") == 0)
				continue;

			file = [[OFString alloc] initWithCString: dirent->d_name
							encoding: encoding];
			@try {
				[IRIs addObject:
				    [IRI IRIByAppendingPathComponent: file]];
			} @finally {
				[file release];
			}
		}
	} @finally {
		closedir(dir);
# if !defined(HAVE_READDIR_R) && defined(OF_HAVE_THREADS)
		[readdirMutex unlock];
# endif
	}
#endif

	[IRIs makeImmutable];

	objc_autoreleasePoolPop(pool);

	return IRIs;
}

- (void)removeItemAtIRI: (OFIRI *)IRI
{
	void *pool = objc_autoreleasePoolPush();
	OFString *path;
	int error;
	Stat s;

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

	if (![IRI.scheme isEqual: _scheme])
		@throw [OFInvalidArgumentException exception];

	path = IRI.fileSystemRepresentation;

	if ((error = lstatWrapper(path, &s)) != 0)
		@throw [OFRemoveItemFailedException exceptionWithIRI: IRI
							       errNo: error];

	if (S_ISDIR(s.st_mode)) {
		OFArray OF_GENERIC(OFIRI *) *contents;

		@try {
			contents = [self contentsOfDirectoryAtIRI: IRI];
		} @catch (id e) {
			/*
			 * Only convert exceptions to
			 * OFRemoveItemFailedException that have an errNo
			 * property. This covers all I/O related exceptions
			 * from the operations used to remove an item, all
			 * others should be left as is.
			 */
			if ([e respondsToSelector: @selector(errNo)])
				@throw [OFRemoveItemFailedException
				    exceptionWithIRI: IRI
					       errNo: [e errNo]];

			@throw e;
		}

		for (OFIRI *item in contents) {
			void *pool2 = objc_autoreleasePoolPush();

			[self removeItemAtIRI: item];

			objc_autoreleasePoolPop(pool2);
		}

#ifndef OF_AMIGAOS
		int status;

# ifdef OF_WINDOWS
		if ([OFSystemInfo isWindowsNT])
			status = _wrmdir(path.UTF16String);
		else
# endif
			status = rmdir(
			    [path cStringWithEncoding: [OFLocale encoding]]);

		if (status != 0)
			@throw [OFRemoveItemFailedException
				exceptionWithIRI: IRI
					   errNo: errno];
	} else {
		int status;

# ifdef OF_WINDOWS
		if ([OFSystemInfo isWindowsNT])
			status = _wunlink(path.UTF16String);
		else
# endif
			status = unlink(
			    [path cStringWithEncoding: [OFLocale encoding]]);

		if (status != 0)
			@throw [OFRemoveItemFailedException
			    exceptionWithIRI: IRI
				       errNo: errno];
#endif
	}

#ifdef OF_AMIGAOS
	if (!DeleteFile([path cStringWithEncoding: [OFLocale encoding]]))
		@throw [OFRemoveItemFailedException
		    exceptionWithIRI: IRI
			       errNo: lastError()];
#endif

	objc_autoreleasePoolPop(pool);
}

#ifdef OF_FILE_MANAGER_SUPPORTS_LINKS
- (void)linkItemAtIRI: (OFIRI *)source toIRI: (OFIRI *)destination
{
	void *pool = objc_autoreleasePoolPush();
	OFString *sourcePath, *destinationPath;

	if (source == nil || destination == nil)
		@throw [OFInvalidArgumentException exception];

	if (![source.scheme isEqual: _scheme] ||
	    ![destination.scheme isEqual: _scheme])
		@throw [OFInvalidArgumentException exception];

	sourcePath = source.fileSystemRepresentation;
	destinationPath = destination.fileSystemRepresentation;

# ifndef OF_WINDOWS
	OFStringEncoding encoding = [OFLocale encoding];

	if (link([sourcePath cStringWithEncoding: encoding],
	    [destinationPath cStringWithEncoding: encoding]) != 0)
		@throw [OFLinkItemFailedException
		    exceptionWithSourceIRI: source
			    destinationIRI: destination
				     errNo: errno];
# else
	if (createHardLinkWFuncPtr == NULL)
		@throw [OFNotImplementedException exceptionWithSelector: _cmd
								 object: self];

	if (!createHardLinkWFuncPtr(destinationPath.UTF16String,
	    sourcePath.UTF16String, NULL))
		@throw [OFLinkItemFailedException
		    exceptionWithSourceIRI: source
			    destinationIRI: destination
				     errNo: lastError()];
# endif

	objc_autoreleasePoolPop(pool);
}
#endif

#ifdef OF_FILE_MANAGER_SUPPORTS_SYMLINKS
- (void)createSymbolicLinkAtIRI: (OFIRI *)IRI
	    withDestinationPath: (OFString *)target
{
	void *pool = objc_autoreleasePoolPush();
	OFString *path;

	if (IRI == nil || target == nil)
		@throw [OFInvalidArgumentException exception];

	if (![IRI.scheme isEqual: _scheme])
		@throw [OFInvalidArgumentException exception];

	path = IRI.fileSystemRepresentation;

# ifndef OF_WINDOWS
	OFStringEncoding encoding = [OFLocale encoding];

	if (symlink([target cStringWithEncoding: encoding],
	    [path cStringWithEncoding: encoding]) != 0)
		@throw [OFCreateSymbolicLinkFailedException
		    exceptionWithIRI: IRI
			      target: target
			       errNo: errno];
# else
	if (createSymbolicLinkWFuncPtr == NULL)
		@throw [OFNotImplementedException exceptionWithSelector: _cmd
								 object: self];

	if (!createSymbolicLinkWFuncPtr(path.UTF16String, target.UTF16String,
	    0))
		@throw [OFCreateSymbolicLinkFailedException
		    exceptionWithIRI: IRI
			      target: target
			       errNo: lastError()];
# endif

	objc_autoreleasePoolPop(pool);
}
#endif

- (bool)moveItemAtIRI: (OFIRI *)source toIRI: (OFIRI *)destination
{
	void *pool;

	if (![source.scheme isEqual: _scheme] ||
	    ![destination.scheme isEqual: _scheme])
		return false;

	if ([self fileExistsAtIRI: destination])
		@throw [OFMoveItemFailedException
		    exceptionWithSourceIRI: source
			    destinationIRI: destination
				     errNo: EEXIST];

	pool = objc_autoreleasePoolPush();

#ifdef OF_AMIGAOS
	OFStringEncoding encoding = [OFLocale encoding];

	if (!Rename([source.fileSystemRepresentation
	    cStringWithEncoding: encoding],
	    [destination.fileSystemRepresentation
	    cStringWithEncoding: encoding]))
		@throw [OFMoveItemFailedException
		    exceptionWithSourceIRI: source
			    destinationIRI: destination
				     errNo: lastError()];
#else
	int status;

# ifdef OF_WINDOWS
	if ([OFSystemInfo isWindowsNT])
		status = _wrename(source.fileSystemRepresentation.UTF16String,
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475


































































































1476
		    cStringWithEncoding: encoding]);
# ifdef OF_WINDOWS
	}
# endif

	if (status != 0)
		@throw [OFMoveItemFailedException
		    exceptionWithSourceURI: source
			    destinationURI: destination
				     errNo: errno];
#endif

	objc_autoreleasePoolPop(pool);

	return true;
}


































































































@end







|
|







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

1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
		    cStringWithEncoding: encoding]);
# ifdef OF_WINDOWS
	}
# endif

	if (status != 0)
		@throw [OFMoveItemFailedException
		    exceptionWithSourceIRI: source
			    destinationIRI: destination
				     errNo: errno];
#endif

	objc_autoreleasePoolPop(pool);

	return true;
}

#ifdef OF_FILE_MANAGER_SUPPORTS_EXTENDED_ATTRIBUTES
- (OFData *)extendedAttributeDataForName: (OFString *)name
			     ofItemAtIRI: (OFIRI *)IRI
{
	void *pool = objc_autoreleasePoolPush();
	OFString *path = IRI.fileSystemRepresentation;
	OFStringEncoding encoding = [OFLocale encoding];
	const char *cPath = [path cStringWithEncoding: encoding];
	const char *cName = [name cStringWithEncoding: encoding];
# if defined(OF_LINUX)
	ssize_t size = lgetxattr(cPath, cName, NULL, 0);
# elif defined(OF_MACOS)
	ssize_t size = getxattr(cPath, cName, NULL, 0, 0, XATTR_NOFOLLOW);
# endif
	void *value = OFAllocMemory(1, size);
	OFData *data;

	@try {
# if defined(OF_LINUX)
		if ((size = lgetxattr(cPath, cName, value, size)) < 0)
# elif defined(OF_MACOS)
		if ((size = getxattr(cPath, cName, value, size, 0,
		    XATTR_NOFOLLOW)) < 0)
# endif
			@throw [OFGetItemAttributesFailedException
			    exceptionWithIRI: IRI
				       errNo: errno];

		data = [OFData dataWithItems: value count: size];
	} @finally {
		OFFreeMemory(value);
	}

	[data retain];

	objc_autoreleasePoolPop(pool);

	return [data autorelease];
}

- (void)setExtendedAttributeData: (OFData *)data
			 forName: (OFString *)name
		     ofItemAtIRI: (OFIRI *)IRI
{
	void *pool = objc_autoreleasePoolPush();
	OFString *path = IRI.fileSystemRepresentation;
	OFStringEncoding encoding = [OFLocale encoding];

# if defined(OF_LINUX)
	if (lsetxattr([path cStringWithEncoding: encoding],
	    [name cStringWithEncoding: encoding], data.items,
	    data.count * data.itemSize, 0) != 0) {
# elif defined(OF_MACOS)
	if (setxattr([path cStringWithEncoding: encoding],
	    [name cStringWithEncoding: encoding], data.items,
	    data.count * data.itemSize, 0, XATTR_NOFOLLOW) != 0) {
# endif
		int errNo = errno;

		/* TODO: Add an attribute (prefix?) for extended attributes? */
		@throw [OFSetItemAttributesFailedException
		    exceptionWithIRI: IRI
			  attributes: [OFDictionary dictionary]
		     failedAttribute: @""
			       errNo: errNo];
	}

	objc_autoreleasePoolPop(pool);
}

- (void)removeExtendedAttributeForName: (OFString *)name
			   ofItemAtIRI: (OFIRI *)IRI
{
	void *pool = objc_autoreleasePoolPush();
	OFString *path = IRI.fileSystemRepresentation;
	OFStringEncoding encoding = [OFLocale encoding];

# if defined(OF_LINUX)
	if (lremovexattr([path cStringWithEncoding: encoding],
	    [name cStringWithEncoding: encoding]) != 0) {
# elif defined(OF_MACOS)
	if (removexattr([path cStringWithEncoding: encoding],
	    [name cStringWithEncoding: encoding], XATTR_NOFOLLOW) != 0) {
# endif
		int errNo = errno;

		/* TODO: Add an attribute (prefix?) for extended attributes? */
		@throw [OFSetItemAttributesFailedException
		    exceptionWithIRI: IRI
			  attributes: [OFDictionary dictionary]
		     failedAttribute: @""
			       errNo: errNo];
	}

	objc_autoreleasePoolPop(pool);
}
#endif
@end

Modified src/OFFileManager.h from [1cfc8cfdf6] to [e1a6d31241].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
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
#import "OFDictionary.h"

OF_ASSUME_NONNULL_BEGIN

/** @file */

#ifdef OF_HAVE_FILES
# if defined(OF_HAVE_CHMOD) && !defined(OF_AMIGAOS)
#  define OF_FILE_MANAGER_SUPPORTS_PERMISSIONS
# endif
# if defined(OF_HAVE_CHOWN) && !defined(OF_AMIGAOS)
#  define OF_FILE_MANAGER_SUPPORTS_OWNER
# endif
# if (defined(OF_HAVE_LINK) && !defined(OF_AMIGAOS)) || defined(OF_WINDOWS)

#  define OF_FILE_MANAGER_SUPPORTS_LINKS
# endif
# if (defined(OF_HAVE_SYMLINK) && !defined(OF_AMIGAOS)) || defined(OF_WINDOWS)

#  define OF_FILE_MANAGER_SUPPORTS_SYMLINKS



# endif
#endif

@class OFArray OF_GENERIC(ObjectType);
@class OFConstantString;
@class OFDate;
@class OFString;
@class OFURI;

/**
 * @brief A key for a file attribute in the file attributes dictionary.
 *
 * Possible keys for file URIs are:
 *
 *  * @ref OFFileSize
 *  * @ref OFFileType
 *  * @ref OFFilePOSIXPermissions
 *  * @ref OFFileOwnerAccountID
 *  * @ref OFFileGroupOwnerAccountID
 *  * @ref OFFileOwnerAccountName
 *  * @ref OFFileGroupOwnerAccountName
 *  * @ref OFFileLastAccessDate
 *  * @ref OFFileModificationDate
 *  * @ref OFFileStatusChangeDate
 *  * @ref OFFileCreationDate
 *  * @ref OFFileSymbolicLinkDestination

 *
 * Other URI schemes might not have all keys and might have keys not listed.
 */
typedef OFConstantString *OFFileAttributeKey;

/**
 * @brief The type of a file.
 *
 * Possibles values for file URIs are:
 *
 *  * @ref OFFileTypeRegular
 *  * @ref OFFileTypeDirectory
 *  * @ref OFFileTypeSymbolicLink
 *  * @ref OFFileTypeFIFO
 *  * @ref OFFileTypeCharacterSpecial
 *  * @ref OFFileTypeBlockSpecial
 *  * @ref OFFileTypeSocket
 *  * @ref OFFileTypeUnknown
 *
 * Other URI schemes might not have all types and might have types not listed.
 */
typedef OFConstantString *OFFileAttributeType;

/**
 * @brief A dictionary mapping keys of type @ref OFFileAttributeKey to their
 *	  attribute values.
 */







|


|


|
>


|
>

>
>
>






|
|




|













>

|






|










|







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
#import "OFDictionary.h"

OF_ASSUME_NONNULL_BEGIN

/** @file */

#ifdef OF_HAVE_FILES
# if (defined(OF_HAVE_CHMOD) && !defined(OF_AMIGAOS)) || defined(DOXYGEN)
#  define OF_FILE_MANAGER_SUPPORTS_PERMISSIONS
# endif
# if (defined(OF_HAVE_CHOWN) && !defined(OF_AMIGAOS)) || defined(DOXYGEN)
#  define OF_FILE_MANAGER_SUPPORTS_OWNER
# endif
# if (defined(OF_HAVE_LINK) && !defined(OF_AMIGAOS)) || defined(OF_WINDOWS) || \
    defined(DOXYGEN)
#  define OF_FILE_MANAGER_SUPPORTS_LINKS
# endif
# if (defined(OF_HAVE_SYMLINK) && !defined(OF_AMIGAOS)) || \
    defined(OF_WINDOWS) || defined(DOXYGEN)
#  define OF_FILE_MANAGER_SUPPORTS_SYMLINKS
# endif
# if defined(OF_LINUX) || defined(OF_MACOS) || defined(DOXYGEN)
#  define OF_FILE_MANAGER_SUPPORTS_EXTENDED_ATTRIBUTES
# endif
#endif

@class OFArray OF_GENERIC(ObjectType);
@class OFConstantString;
@class OFDate;
@class OFIRI;
@class OFString;

/**
 * @brief A key for a file attribute in the file attributes dictionary.
 *
 * Possible keys for file IRIs are:
 *
 *  * @ref OFFileSize
 *  * @ref OFFileType
 *  * @ref OFFilePOSIXPermissions
 *  * @ref OFFileOwnerAccountID
 *  * @ref OFFileGroupOwnerAccountID
 *  * @ref OFFileOwnerAccountName
 *  * @ref OFFileGroupOwnerAccountName
 *  * @ref OFFileLastAccessDate
 *  * @ref OFFileModificationDate
 *  * @ref OFFileStatusChangeDate
 *  * @ref OFFileCreationDate
 *  * @ref OFFileSymbolicLinkDestination
 *  * @ref OFFileExtendedAttributesNames
 *
 * Other IRI schemes might not have all keys and might have keys not listed.
 */
typedef OFConstantString *OFFileAttributeKey;

/**
 * @brief The type of a file.
 *
 * Possibles values for file IRIs are:
 *
 *  * @ref OFFileTypeRegular
 *  * @ref OFFileTypeDirectory
 *  * @ref OFFileTypeSymbolicLink
 *  * @ref OFFileTypeFIFO
 *  * @ref OFFileTypeCharacterSpecial
 *  * @ref OFFileTypeBlockSpecial
 *  * @ref OFFileTypeSocket
 *  * @ref OFFileTypeUnknown
 *
 * Other IRI schemes might not have all types and might have types not listed.
 */
typedef OFConstantString *OFFileAttributeType;

/**
 * @brief A dictionary mapping keys of type @ref OFFileAttributeKey to their
 *	  attribute values.
 */
184
185
186
187
188
189
190
191
192
193
194
195
196
197









198
199
200
201
202
203
204
 *
 * For convenience, a category on @ref OFDictionary is provided to access this
 * via @ref OFDictionary#fileCreationDate.
 */
extern const OFFileAttributeKey OFFileCreationDate;

/**
 * @brief The destination of a symbolic link as an OFString.
 *
 * For convenience, a category on @ref OFDictionary is provided to access this
 * via @ref OFDictionary#fileSymbolicLinkDestination.
 */
extern const OFFileAttributeKey OFFileSymbolicLinkDestination;










/**
 * @brief A regular file.
 */
extern const OFFileAttributeType OFFileTypeRegular;

/**
 * @brief A directory.







|






>
>
>
>
>
>
>
>
>







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
 *
 * For convenience, a category on @ref OFDictionary is provided to access this
 * via @ref OFDictionary#fileCreationDate.
 */
extern const OFFileAttributeKey OFFileCreationDate;

/**
 * @brief The destination of a symbolic link as an @ref OFString.
 *
 * For convenience, a category on @ref OFDictionary is provided to access this
 * via @ref OFDictionary#fileSymbolicLinkDestination.
 */
extern const OFFileAttributeKey OFFileSymbolicLinkDestination;

/**
 * @brief The names of the extended attributes as an @ref OFArray of
 *	  @ref OFString.
 *
 * For convenience, a category on @ref OFDictionary is provided to access this
 * via @ref OFDictionary#fileExtendedAttributesNames.
 */
extern const OFFileAttributeKey OFFileExtendedAttributesNames;

/**
 * @brief A regular file.
 */
extern const OFFileAttributeType OFFileTypeRegular;

/**
 * @brief A directory.
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
 * @brief The path of the current working directory.
 *
 * @throw OFGetCurrentDirectoryFailedException Couldn't get current directory
 */
@property (readonly, nonatomic) OFString *currentDirectoryPath;

/**
 * @brief The URI of the current working directory.
 *
 * @throw OFGetCurrentDirectoryFailedException Couldn't get current directory
 */
@property (readonly, nonatomic) OFURI *currentDirectoryURI;
#endif

/**
 * @brief Returns the default file manager.
 */
+ (OFFileManager *)defaultManager;








|



|







276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
 * @brief The path of the current working directory.
 *
 * @throw OFGetCurrentDirectoryFailedException Couldn't get current directory
 */
@property (readonly, nonatomic) OFString *currentDirectoryPath;

/**
 * @brief The IRI of the current working directory.
 *
 * @throw OFGetCurrentDirectoryFailedException Couldn't get current directory
 */
@property (readonly, nonatomic) OFIRI *currentDirectoryIRI;
#endif

/**
 * @brief Returns the default file manager.
 */
+ (OFFileManager *)defaultManager;

287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
 * @throw OFGetItemAttributesFailedException Failed to get the attributes of
 *					     the item
 */
- (OFFileAttributes)attributesOfItemAtPath: (OFString *)path;
#endif

/**
 * @brief Returns the attributes for the item at the specified URI.
 *
 * @param URI The URI to return the attributes for
 * @return A dictionary of attributes for the specified URI, with the keys of
 *	   type @ref OFFileAttributeKey
 * @throw OFGetItemAttributesFailedException Failed to get the attributes of
 *					     the item
 * @throw OFUnsupportedProtocolException No handler is registered for the URI's
 *					 scheme
 */
- (OFFileAttributes)attributesOfItemAtURI: (OFURI *)URI;

#ifdef OF_HAVE_FILES
/**
 * @brief Sets the attributes for the item at the specified path.
 *
 * All attributes not part of the dictionary are left unchanged.
 *
 * @param attributes The attributes to set for the specified path
 * @param path The path of the item to set the attributes for
 * @throw OFSetItemAttributesFailedException Failed to set the attributes of
 *					     the item
 * @throw OFNotImplementedException Setting one or more of the specified
 *				    attributes is not implemented for the
 *				    specified item
 */
- (void)setAttributes: (OFFileAttributes)attributes
	 ofItemAtPath: (OFString *)path;
#endif

/**
 * @brief Sets the attributes for the item at the specified URI.
 *
 * All attributes not part of the dictionary are left unchanged.
 *
 * @param attributes The attributes to set for the specified URI
 * @param URI The URI of the item to set the attributes for
 * @throw OFSetItemAttributesFailedException Failed to set the attributes of
 *					     the item
 * @throw OFUnsupportedProtocolException No handler is registered for the URI's
 *					 scheme
 * @throw OFNotImplementedException Setting one or more of the specified
 *				    attributes is not implemented for the
 *				    specified item
 */
- (void)setAttributes: (OFFileAttributes)attributes ofItemAtURI: (OFURI *)URI;

#ifdef OF_HAVE_FILES
/**
 * @brief Checks whether a file exists at the specified path.
 *
 * @param path The path to check
 * @return A boolean whether there is a file at the specified path
 */
- (bool)fileExistsAtPath: (OFString *)path;
#endif

/**
 * @brief Checks whether a file exists at the specified URI.
 *
 * @param URI The URI to check
 * @return A boolean whether there is a file at the specified URI
 * @throw OFUnsupportedProtocolException No handler is registered for the URI's
 *					 scheme
 */
- (bool)fileExistsAtURI: (OFURI *)URI;

#ifdef OF_HAVE_FILES
/**
 * @brief Checks whether a directory exists at the specified path.
 *
 * @param path The path to check
 * @return A boolean whether there is a directory at the specified path
 */
- (bool)directoryExistsAtPath: (OFString *)path;
#endif

/**
 * @brief Checks whether a directory exists at the specified URI.
 *
 * @param URI The URI to check
 * @return A boolean whether there is a directory at the specified URI
 * @throw OFUnsupportedProtocolException No handler is registered for the URI's
 *					 scheme
 */
- (bool)directoryExistsAtURI: (OFURI *)URI;

#ifdef OF_HAVE_FILES
/**
 * @brief Creates a directory at the specified path.
 *
 * @param path The path of the directory to create
 * @throw OFCreateDirectoryFailedException Creating the directory failed







|

|
|



|


|




















|



|
|


|





|












|

|
|
|


|












|

|
|
|


|







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
 * @throw OFGetItemAttributesFailedException Failed to get the attributes of
 *					     the item
 */
- (OFFileAttributes)attributesOfItemAtPath: (OFString *)path;
#endif

/**
 * @brief Returns the attributes for the item at the specified IRI.
 *
 * @param IRI The IRI to return the attributes for
 * @return A dictionary of attributes for the specified IRI, with the keys of
 *	   type @ref OFFileAttributeKey
 * @throw OFGetItemAttributesFailedException Failed to get the attributes of
 *					     the item
 * @throw OFUnsupportedProtocolException No handler is registered for the IRI's
 *					 scheme
 */
- (OFFileAttributes)attributesOfItemAtIRI: (OFIRI *)IRI;

#ifdef OF_HAVE_FILES
/**
 * @brief Sets the attributes for the item at the specified path.
 *
 * All attributes not part of the dictionary are left unchanged.
 *
 * @param attributes The attributes to set for the specified path
 * @param path The path of the item to set the attributes for
 * @throw OFSetItemAttributesFailedException Failed to set the attributes of
 *					     the item
 * @throw OFNotImplementedException Setting one or more of the specified
 *				    attributes is not implemented for the
 *				    specified item
 */
- (void)setAttributes: (OFFileAttributes)attributes
	 ofItemAtPath: (OFString *)path;
#endif

/**
 * @brief Sets the attributes for the item at the specified IRI.
 *
 * All attributes not part of the dictionary are left unchanged.
 *
 * @param attributes The attributes to set for the specified IRI
 * @param IRI The IRI of the item to set the attributes for
 * @throw OFSetItemAttributesFailedException Failed to set the attributes of
 *					     the item
 * @throw OFUnsupportedProtocolException No handler is registered for the IRI's
 *					 scheme
 * @throw OFNotImplementedException Setting one or more of the specified
 *				    attributes is not implemented for the
 *				    specified item
 */
- (void)setAttributes: (OFFileAttributes)attributes ofItemAtIRI: (OFIRI *)IRI;

#ifdef OF_HAVE_FILES
/**
 * @brief Checks whether a file exists at the specified path.
 *
 * @param path The path to check
 * @return A boolean whether there is a file at the specified path
 */
- (bool)fileExistsAtPath: (OFString *)path;
#endif

/**
 * @brief Checks whether a file exists at the specified IRI.
 *
 * @param IRI The IRI to check
 * @return A boolean whether there is a file at the specified IRI
 * @throw OFUnsupportedProtocolException No handler is registered for the IRI's
 *					 scheme
 */
- (bool)fileExistsAtIRI: (OFIRI *)IRI;

#ifdef OF_HAVE_FILES
/**
 * @brief Checks whether a directory exists at the specified path.
 *
 * @param path The path to check
 * @return A boolean whether there is a directory at the specified path
 */
- (bool)directoryExistsAtPath: (OFString *)path;
#endif

/**
 * @brief Checks whether a directory exists at the specified IRI.
 *
 * @param IRI The IRI to check
 * @return A boolean whether there is a directory at the specified IRI
 * @throw OFUnsupportedProtocolException No handler is registered for the IRI's
 *					 scheme
 */
- (bool)directoryExistsAtIRI: (OFIRI *)IRI;

#ifdef OF_HAVE_FILES
/**
 * @brief Creates a directory at the specified path.
 *
 * @param path The path of the directory to create
 * @throw OFCreateDirectoryFailedException Creating the directory failed
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
 *					   parents failed
 */
- (void)createDirectoryAtPath: (OFString *)path
		createParents: (bool)createParents;
#endif

/**
 * @brief Creates a directory at the specified URI.
 *
 * @param URI The URI of the directory to create
 * @throw OFCreateDirectoryFailedException Creating the directory failed
 * @throw OFUnsupportedProtocolException No handler is registered for the URI's
 *					 scheme
 */
- (void)createDirectoryAtURI: (OFURI *)URI;

/**
 * @brief Creates a directory at the specified URI.
 *
 * @param URI The URI of the directory to create
 * @param createParents Whether to create the parents of the directory
 * @throw OFCreateDirectoryFailedException Creating the directory or one of its
 *					   parents failed
 * @throw OFUnsupportedProtocolException No handler is registered for the URI's
 *					 scheme
 */
- (void)createDirectoryAtURI: (OFURI *)URI createParents: (bool)createParents;

#ifdef OF_HAVE_FILES
/**
 * @brief Returns an array with the items in the specified directory.
 *
 * @note `.` and `..` are not part of the returned array.
 *
 * @param path The path to the directory whose items should be returned
 * @return An array of OFString with the items in the specified directory
 * @throw OFOpenItemFailedException Opening the directory failed
 * @throw OFReadFailedException Reading from the directory failed
 */
- (OFArray OF_GENERIC(OFString *) *)contentsOfDirectoryAtPath: (OFString *)path;
#endif

/**
 * @brief Returns an array with the URIs of the items in the specified
 *	  directory.
 *
 * @note `.` and `..` are not part of the returned array.
 *
 * @param URI The URI to the directory whose items should be returned
 * @return An array with the URIs of the items in the specified directory
 * @throw OFOpenItemFailedException Opening the directory failed
 * @throw OFReadFailedException Reading from the directory failed
 * @throw OFUnsupportedProtocolException No handler is registered for the URI's
 *					 scheme
 */
- (OFArray OF_GENERIC(OFURI *) *)contentsOfDirectoryAtURI: (OFURI *)URI;

#ifdef OF_HAVE_FILES
/**
 * @brief Returns an array with all subpaths of the specified directory.
 *
 * @note `.` and `..` (of the directory itself or any subdirectory) are not
 * part of the returned array.







|

|

|


|


|

|



|


|
















|




|
|


|


|







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
 *					   parents failed
 */
- (void)createDirectoryAtPath: (OFString *)path
		createParents: (bool)createParents;
#endif

/**
 * @brief Creates a directory at the specified IRI.
 *
 * @param IRI The IRI of the directory to create
 * @throw OFCreateDirectoryFailedException Creating the directory failed
 * @throw OFUnsupportedProtocolException No handler is registered for the IRI's
 *					 scheme
 */
- (void)createDirectoryAtIRI: (OFIRI *)IRI;

/**
 * @brief Creates a directory at the specified IRI.
 *
 * @param IRI The IRI of the directory to create
 * @param createParents Whether to create the parents of the directory
 * @throw OFCreateDirectoryFailedException Creating the directory or one of its
 *					   parents failed
 * @throw OFUnsupportedProtocolException No handler is registered for the IRI's
 *					 scheme
 */
- (void)createDirectoryAtIRI: (OFIRI *)IRI createParents: (bool)createParents;

#ifdef OF_HAVE_FILES
/**
 * @brief Returns an array with the items in the specified directory.
 *
 * @note `.` and `..` are not part of the returned array.
 *
 * @param path The path to the directory whose items should be returned
 * @return An array of OFString with the items in the specified directory
 * @throw OFOpenItemFailedException Opening the directory failed
 * @throw OFReadFailedException Reading from the directory failed
 */
- (OFArray OF_GENERIC(OFString *) *)contentsOfDirectoryAtPath: (OFString *)path;
#endif

/**
 * @brief Returns an array with the IRIs of the items in the specified
 *	  directory.
 *
 * @note `.` and `..` are not part of the returned array.
 *
 * @param IRI The IRI to the directory whose items should be returned
 * @return An array with the IRIs of the items in the specified directory
 * @throw OFOpenItemFailedException Opening the directory failed
 * @throw OFReadFailedException Reading from the directory failed
 * @throw OFUnsupportedProtocolException No handler is registered for the IRI's
 *					 scheme
 */
- (OFArray OF_GENERIC(OFIRI *) *)contentsOfDirectoryAtIRI: (OFIRI *)IRI;

#ifdef OF_HAVE_FILES
/**
 * @brief Returns an array with all subpaths of the specified directory.
 *
 * @note `.` and `..` (of the directory itself or any subdirectory) are not
 * part of the returned array.
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
 *						  directory failed
 */
- (void)changeCurrentDirectoryPath: (OFString *)path;

/**
 * @brief Changes the current working directory.
 *
 * @param URI The new directory to change to
 * @throw OFChangeCurrentDirectoryFailedException Changing the current working
 *						  directory failed
 */
- (void)changeCurrentDirectoryURI: (OFURI *)URI;

/**
 * @brief Copies a file, directory or symbolic link (if supported by the OS).
 *
 * The destination path must be a full path, which means it must include the
 * name of the item.
 *







|



|







485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
 *						  directory failed
 */
- (void)changeCurrentDirectoryPath: (OFString *)path;

/**
 * @brief Changes the current working directory.
 *
 * @param IRI The new directory to change to
 * @throw OFChangeCurrentDirectoryFailedException Changing the current working
 *						  directory failed
 */
- (void)changeCurrentDirectoryIRI: (OFIRI *)IRI;

/**
 * @brief Copies a file, directory or symbolic link (if supported by the OS).
 *
 * The destination path must be a full path, which means it must include the
 * name of the item.
 *
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
 */
- (void)copyItemAtPath: (OFString *)source toPath: (OFString *)destination;
#endif

/**
 * @brief Copies a file, directory or symbolic link (if supported by the OS).
 *
 * The destination URI must have a full path, which means it must include the
 * name of the item.
 *
 * If an item already exists, the copy operation fails. This is also the case
 * if a directory is copied and an item already exists in the destination
 * directory.
 *
 * @param source The file, directory or symbolic link to copy
 * @param destination The destination URI
 * @throw OFCopyItemFailedException Copying failed
 * @throw OFCreateDirectoryFailedException Creating a destination directory
 *					   failed
 * @throw OFUnsupportedProtocolException No handler is registered for either of
 *					 the URI's scheme
 */
- (void)copyItemAtURI: (OFURI *)source toURI: (OFURI *)destination;

#ifdef OF_HAVE_FILES
/**
 * @brief Moves an item.
 *
 * The destination path must be a full path, which means it must include the
 * name of the item.







|







|




|

|







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
 */
- (void)copyItemAtPath: (OFString *)source toPath: (OFString *)destination;
#endif

/**
 * @brief Copies a file, directory or symbolic link (if supported by the OS).
 *
 * The destination IRI must have a full path, which means it must include the
 * name of the item.
 *
 * If an item already exists, the copy operation fails. This is also the case
 * if a directory is copied and an item already exists in the destination
 * directory.
 *
 * @param source The file, directory or symbolic link to copy
 * @param destination The destination IRI
 * @throw OFCopyItemFailedException Copying failed
 * @throw OFCreateDirectoryFailedException Creating a destination directory
 *					   failed
 * @throw OFUnsupportedProtocolException No handler is registered for either of
 *					 the IRI's scheme
 */
- (void)copyItemAtIRI: (OFIRI *)source toIRI: (OFIRI *)destination;

#ifdef OF_HAVE_FILES
/**
 * @brief Moves an item.
 *
 * The destination path must be a full path, which means it must include the
 * name of the item.
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666

667
668
669
670
671
















































































































672
673
674
675
676
677
678
 */
- (void)moveItemAtPath: (OFString *)source toPath: (OFString *)destination;
#endif

/**
 * @brief Moves an item.
 *
 * The destination URI must have a full path, which means it must include the
 * name of the item.
 *
 * If the destination is on a different logical device or uses a different
 * scheme, the source will be copied to the destination using
 * @ref copyItemAtURI:toURI: and the source removed using @ref removeItemAtURI:.
 *
 * @param source The item to rename
 * @param destination The new name for the item
 * @throw OFMoveItemFailedException Moving failed
 * @throw OFCopyItemFailedException Copying (to move between different devices)
 *				    failed
 * @throw OFRemoveItemFailedException Removing the source after copying to the
 *				      destination (to move between different
 *				      devices) failed
 * @throw OFCreateDirectoryFailedException Creating a destination directory
 *					   failed
 * @throw OFUnsupportedProtocolException No handler is registered for either of
 *					 the URI's scheme
 */
- (void)moveItemAtURI: (OFURI *)source toURI: (OFURI *)destination;

#ifdef OF_HAVE_FILES
/**
 * @brief Removes the item at the specified path.
 *
 * If the item at the specified path is a directory, it is removed recursively.
 *
 * @param path The path to the item which should be removed
 * @throw OFRemoveItemFailedException Removing the item failed
 */
- (void)removeItemAtPath: (OFString *)path;
#endif

/**
 * @brief Removes the item at the specified URI.
 *
 * If the item at the specified URI is a directory, it is removed recursively.
 *
 * @param URI The URI to the item which should be removed
 * @throw OFRemoveItemFailedException Removing the item failed
 * @throw OFUnsupportedProtocolException No handler is registered for the URI's
 *					 scheme
 */
- (void)removeItemAtURI: (OFURI *)URI;

#ifdef OF_FILE_MANAGER_SUPPORTS_LINKS
/**
 * @brief Creates a hard link for the specified item.
 *
 * The destination path must be a full path, which means it must include the
 * name of the item.
 *
 * This method is not available on some systems.
 *
 * @param source The path to the item for which a link should be created
 * @param destination The path to the item which should link to the source
 * @throw OFLinkItemFailedException Linking the item failed
 * @throw OFNotImplementedException Hardlinks are not implemented for the
 *				    specified URI
 */
- (void)linkItemAtPath: (OFString *)source toPath: (OFString *)destination;
#endif

/**
 * @brief Creates a hard link for the specified item.
 *
 * The destination URI must have a full path, which means it must include the
 * name of the item.
 *
 * This method is not available for all URIs.
 *
 * @param source The URI to the item for which a link should be created
 * @param destination The URI to the item which should link to the source
 * @throw OFLinkItemFailedException Linking the item failed
 * @throw OFUnsupportedProtocolException No handler is registered for the URI's
 *					 scheme
 * @throw OFNotImplementedException Hardlinks are not implemented for the
 *				    specified URI
 */
- (void)linkItemAtURI: (OFURI *)source toURI: (OFURI *)destination;

#ifdef OF_FILE_MANAGER_SUPPORTS_SYMLINKS
/**
 * @brief Creates a symbolic link for an item.
 *
 * The destination path must be a full path, which means it must include the
 * name of the item.
 *
 * This method is not available on some systems.
 *
 * @note On Windows, this requires at least Windows Vista and administrator
 *	 privileges!
 *
 * @param path The path to the item which should symbolically link to the target
 * @param target The target of the symbolic link
 * @throw OFCreateSymbolicLinkFailedException Creating the symbolic link failed
 * @throw OFNotImplementedException Symbolic links are not implemented for the
 *				    specified URI
 */
- (void)createSymbolicLinkAtPath: (OFString *)path
	     withDestinationPath: (OFString *)target;
#endif

/**
 * @brief Creates a symbolic link for an item.
 *
 * The destination URI must have a full path, which means it must include the
 * name of the item.
 *
 * This method is not available for all URIs.
 *
 * @note On Windows, this requires at least Windows Vista and administrator
 *	 privileges!
 *
 * @param URI The URI to the item which should symbolically link to the target
 * @param target The target of the symbolic link

 * @throw OFUnsupportedProtocolException No handler is registered for the URI's
 *					 scheme
 */
- (void)createSymbolicLinkAtURI: (OFURI *)URI
	    withDestinationPath: (OFString *)target;
















































































































@end

@interface OFDictionary (FileAttributes)
/**
 * @brief The @ref OFFileSize key from the dictionary.
 *
 * @throw OFUndefinedKeyException The key is missing







|




|












|

|














|

|

|

|


|














|







|


|

|
|

|


|

|

















|








|


|

|
|

|

>
|


|

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







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
 */
- (void)moveItemAtPath: (OFString *)source toPath: (OFString *)destination;
#endif

/**
 * @brief Moves an item.
 *
 * The destination IRI must have a full path, which means it must include the
 * name of the item.
 *
 * If the destination is on a different logical device or uses a different
 * scheme, the source will be copied to the destination using
 * @ref copyItemAtIRI:toIRI: and the source removed using @ref removeItemAtIRI:.
 *
 * @param source The item to rename
 * @param destination The new name for the item
 * @throw OFMoveItemFailedException Moving failed
 * @throw OFCopyItemFailedException Copying (to move between different devices)
 *				    failed
 * @throw OFRemoveItemFailedException Removing the source after copying to the
 *				      destination (to move between different
 *				      devices) failed
 * @throw OFCreateDirectoryFailedException Creating a destination directory
 *					   failed
 * @throw OFUnsupportedProtocolException No handler is registered for either of
 *					 the IRI's scheme
 */
- (void)moveItemAtIRI: (OFIRI *)source toIRI: (OFIRI *)destination;

#ifdef OF_HAVE_FILES
/**
 * @brief Removes the item at the specified path.
 *
 * If the item at the specified path is a directory, it is removed recursively.
 *
 * @param path The path to the item which should be removed
 * @throw OFRemoveItemFailedException Removing the item failed
 */
- (void)removeItemAtPath: (OFString *)path;
#endif

/**
 * @brief Removes the item at the specified IRI.
 *
 * If the item at the specified IRI is a directory, it is removed recursively.
 *
 * @param IRI The IRI to the item which should be removed
 * @throw OFRemoveItemFailedException Removing the item failed
 * @throw OFUnsupportedProtocolException No handler is registered for the IRI's
 *					 scheme
 */
- (void)removeItemAtIRI: (OFIRI *)IRI;

#ifdef OF_FILE_MANAGER_SUPPORTS_LINKS
/**
 * @brief Creates a hard link for the specified item.
 *
 * The destination path must be a full path, which means it must include the
 * name of the item.
 *
 * This method is not available on some systems.
 *
 * @param source The path to the item for which a link should be created
 * @param destination The path to the item which should link to the source
 * @throw OFLinkItemFailedException Linking the item failed
 * @throw OFNotImplementedException Hardlinks are not implemented for the
 *				    specified IRI
 */
- (void)linkItemAtPath: (OFString *)source toPath: (OFString *)destination;
#endif

/**
 * @brief Creates a hard link for the specified item.
 *
 * The destination IRI must have a full path, which means it must include the
 * name of the item.
 *
 * This method is not available for all IRIs.
 *
 * @param source The IRI to the item for which a link should be created
 * @param destination The IRI to the item which should link to the source
 * @throw OFLinkItemFailedException Linking the item failed
 * @throw OFUnsupportedProtocolException No handler is registered for the IRI's
 *					 scheme
 * @throw OFNotImplementedException Hardlinks are not implemented for the
 *				    specified IRI
 */
- (void)linkItemAtIRI: (OFIRI *)source toIRI: (OFIRI *)destination;

#ifdef OF_FILE_MANAGER_SUPPORTS_SYMLINKS
/**
 * @brief Creates a symbolic link for an item.
 *
 * The destination path must be a full path, which means it must include the
 * name of the item.
 *
 * This method is not available on some systems.
 *
 * @note On Windows, this requires at least Windows Vista and administrator
 *	 privileges!
 *
 * @param path The path to the item which should symbolically link to the target
 * @param target The target of the symbolic link
 * @throw OFCreateSymbolicLinkFailedException Creating the symbolic link failed
 * @throw OFNotImplementedException Symbolic links are not implemented for the
 *				    specified IRI
 */
- (void)createSymbolicLinkAtPath: (OFString *)path
	     withDestinationPath: (OFString *)target;
#endif

/**
 * @brief Creates a symbolic link for an item.
 *
 * The destination IRI must have a full path, which means it must include the
 * name of the item.
 *
 * This method is not available for all IRIs.
 *
 * @note For file IRIs on Windows, this requires at least Windows Vista and
 *	 administrator privileges!
 *
 * @param IRI The IRI to the item which should symbolically link to the target
 * @param target The target of the symbolic link
 * @throw OFOFCreateSymbolicLinkFailedException Creating a symbolic link failed
 * @throw OFUnsupportedProtocolException No handler is registered for the IRI's
 *					 scheme
 */
- (void)createSymbolicLinkAtIRI: (OFIRI *)IRI
	    withDestinationPath: (OFString *)target;

#ifdef OF_FILE_MANAGER_SUPPORTS_EXTENDED_ATTRIBUTES
/**
 * @brief Returns the extended attribute data for the specified name of the
 *	  item at the specified path.
 *
 * This method is not available on some systems.
 *
 * @param name The name of the extended attribute
 * @param path The path of the item to return the extended attribute from
 * @throw OFGetItemAttributesFailedException Getting the extended attribute
 *					     failed
 * @throw OFNotImplementedException Getting extended attributes is not
 *				    implemented for the specified item
 */
- (OFData *)extendedAttributeDataForName: (OFString *)name
			    ofItemAtPath: (OFString *)path;
#endif

/**
 * @brief Returns the extended attribute data for the specified name of the
 *	  item at the specified IRI.
 *
 * This method is not available for all IRIs.
 *
 * @param name The name of the extended attribute
 * @param IRI The IRI of the item to return the extended attribute from
 * @throw OFGetItemAttributesFailedException Getting the extended attribute
 *					     failed
 * @throw OFUnsupportedProtocolException No handler is registered for the IRI's
 *					 scheme
 * @throw OFNotImplementedException Getting extended attributes is not
 *				    implemented for the specified item
 */
- (OFData *)extendedAttributeDataForName: (OFString *)name
			     ofItemAtIRI: (OFIRI *)IRI;

#ifdef OF_FILE_MANAGER_SUPPORTS_EXTENDED_ATTRIBUTES
/**
 * @brief Sets the extended attribute data for the specified name of the item
 *	  at the specified path.
 *
 * This method is not available on some systems.
 *
 * @param data The data for the extended attribute
 * @param name The name of the extended attribute
 * @param path The path of the item to set the extended attribute on
 * @throw OFSetItemAttributesFailedException Setting the extended attribute
 *					     failed
 * @throw OFNotImplementedException Setting extended attributes is not
 *				    implemented for the specified item
 */
- (void)setExtendedAttributeData: (OFData *)data
			 forName: (OFString *)name
		    ofItemAtPath: (OFString *)path;
#endif

/**
 * @brief Sets the extended attribute data for the specified name of the item
 *	  at the specified IRI.
 *
 * This method is not available for all IRIs.
 *
 * @param data The data for the extended attribute
 * @param name The name of the extended attribute
 * @param IRI The IRI of the item to set the extended attribute on
 * @throw OFSetItemAttributesFailedException Setting the extended attribute
 *					     failed
 * @throw OFUnsupportedProtocolException No handler is registered for the IRI's
 *					 scheme
 * @throw OFNotImplementedException Setting extended attributes is not
 *				    implemented for the specified item
 */
- (void)setExtendedAttributeData: (OFData *)data
			 forName: (OFString *)name
		     ofItemAtIRI: (OFIRI *)IRI;

#ifdef OF_FILE_MANAGER_SUPPORTS_EXTENDED_ATTRIBUTES
/**
 * @brief Removes the extended attribute for the specified name wof the item at
 *	  the specified path.
 *
 * This method is not available on some systems.
 *
 * @param name The name of the extended attribute to remove
 * @param path The path of the item to remove the extended attribute from
 * @throw OFSetItemAttributesFailedException Removing the extended attribute
 *					     failed
 * @throw OFNotImplementedException Removing extended attributes is not
 *				    implemented for the specified item
 */
- (void)removeExtendedAttributeForName: (OFString *)name
			  ofItemAtPath: (OFString *)path;
#endif

/**
 * @brief Removes the extended attribute for the specified name wof the item at
 *	  the specified IRI.
 *
 * This method is not available for all IRIs.
 *
 * @param name The name of the extended attribute to remove
 * @param IRI The IRI of the item to remove the extended attribute from
 * @throw OFSetItemAttributesFailedException Removing the extended attribute
 *					     failed
 * @throw OFUnsupportedProtocolException No handler is registered for the IRI's
 *					 scheme
 * @throw OFNotImplementedException Removing extended attributes is not
 *				    implemented for the specified item
 */
- (void)removeExtendedAttributeForName: (OFString *)name
			   ofItemAtIRI: (OFIRI *)IRI;
@end

@interface OFDictionary (FileAttributes)
/**
 * @brief The @ref OFFileSize key from the dictionary.
 *
 * @throw OFUndefinedKeyException The key is missing
751
752
753
754
755
756
757








758
759
760

/**
 * @brief The @ref OFFileSymbolicLinkDestination key from the dictionary.
 *
 * @throw OFUndefinedKeyException The key is missing
 */
@property (readonly, nonatomic) OFString *fileSymbolicLinkDestination;








@end

OF_ASSUME_NONNULL_END







>
>
>
>
>
>
>
>



879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896

/**
 * @brief The @ref OFFileSymbolicLinkDestination key from the dictionary.
 *
 * @throw OFUndefinedKeyException The key is missing
 */
@property (readonly, nonatomic) OFString *fileSymbolicLinkDestination;

/**
 * @brief The @ref OFFileExtendedAttributesNames key from the dictionary.
 *
 * @throw OFUndefinedKeyException The key is missing
 */
@property (readonly, nonatomic)
    OFArray OF_GENERIC(OFString *) *fileExtendedAttributesNames;
@end

OF_ASSUME_NONNULL_END

Modified src/OFFileManager.m from [5dfeac045a] to [0ef3517469].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
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 <errno.h>
#include <limits.h>
#include "unistd_wrapper.h"

#include "platform.h"




#ifdef OF_PSP
# include <sys/syslimits.h>
#endif

#import "OFArray.h"

#import "OFDate.h"
#import "OFDictionary.h"
#ifdef OF_HAVE_FILES
# import "OFFile.h"
#endif
#import "OFFileManager.h"


#import "OFLocale.h"
#import "OFNumber.h"
#import "OFStream.h"
#import "OFString.h"
#import "OFSystemInfo.h"
#import "OFURI.h"
#import "OFURIHandler.h"

#import "OFChangeCurrentDirectoryFailedException.h"
#import "OFCopyItemFailedException.h"
#import "OFCreateDirectoryFailedException.h"
#import "OFGetCurrentDirectoryFailedException.h"
#import "OFInitializationFailedException.h"
#import "OFInvalidArgumentException.h"







>
>
>





>






>
>





<
<







19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47


48
49
50
51
52
53
54

#include <errno.h>
#include <limits.h>
#include "unistd_wrapper.h"

#include "platform.h"

#ifdef OF_DJGPP
# include <syslimits.h>
#endif
#ifdef OF_PSP
# include <sys/syslimits.h>
#endif

#import "OFArray.h"
#import "OFData.h"
#import "OFDate.h"
#import "OFDictionary.h"
#ifdef OF_HAVE_FILES
# import "OFFile.h"
#endif
#import "OFFileManager.h"
#import "OFIRI.h"
#import "OFIRIHandler.h"
#import "OFLocale.h"
#import "OFNumber.h"
#import "OFStream.h"
#import "OFString.h"
#import "OFSystemInfo.h"



#import "OFChangeCurrentDirectoryFailedException.h"
#import "OFCopyItemFailedException.h"
#import "OFCreateDirectoryFailedException.h"
#import "OFGetCurrentDirectoryFailedException.h"
#import "OFInitializationFailedException.h"
#import "OFInvalidArgumentException.h"
60
61
62
63
64
65
66

67
68

69
70
71
72
73
74
75
#ifdef OF_WINDOWS
# include <windows.h>
# include <direct.h>
# include <ntdef.h>
#endif

#ifdef OF_AMIGAOS

# include <proto/exec.h>
# include <proto/dos.h>

#endif

#ifdef OF_MINT
# include <bits/local_lim.h>
#endif

@interface OFDefaultFileManager: OFFileManager







>


>







64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
#ifdef OF_WINDOWS
# include <windows.h>
# include <direct.h>
# include <ntdef.h>
#endif

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

#ifdef OF_MINT
# include <bits/local_lim.h>
#endif

@interface OFDefaultFileManager: OFFileManager
163
164
165
166
167
168
169
















170
171
172
173
174
175
176
			@throw [OFOutOfRangeException exception];

		return nil;
	}

	return [OFString stringWithCString: buffer
				  encoding: [OFLocale encoding]];
















# else
	char buffer[PATH_MAX];

	if ((getcwd(buffer, PATH_MAX)) == NULL)
		@throw [OFGetCurrentDirectoryFailedException
		    exceptionWithErrNo: errno];








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







169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
			@throw [OFOutOfRangeException exception];

		return nil;
	}

	return [OFString stringWithCString: buffer
				  encoding: [OFLocale encoding]];
# elif defined(OF_GLIBC)
	char *buffer;
	OFString *path;

	if ((buffer = getcwd(NULL, 0)) == NULL)
		@throw [OFGetCurrentDirectoryFailedException
		    exceptionWithErrNo: errno];

	@try {
		path = [OFString stringWithCString: buffer
					  encoding: [OFLocale encoding]];
	} @finally {
		free(buffer);
	}

	return path;
# else
	char buffer[PATH_MAX];

	if ((getcwd(buffer, PATH_MAX)) == NULL)
		@throw [OFGetCurrentDirectoryFailedException
		    exceptionWithErrNo: errno];

185
186
187
188
189
190
191
192
193
194
195
196
197

198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313

314
315
316
317
318
319
320
321
322
323

324

325
326
327
328
329
330
331
332
333
334
335
336
337
338


339
340
341
342
343
344
345
346
347
348

349

350
351

352
353


354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
#  endif

	return [OFString stringWithCString: buffer
				  encoding: [OFLocale encoding]];
# endif
}

- (OFURI *)currentDirectoryURI
{
	void *pool = objc_autoreleasePoolPush();
	OFURI *ret;

	ret = [OFURI fileURIWithPath: self.currentDirectoryPath];


	[ret retain];
	objc_autoreleasePoolPop(pool);
	return [ret autorelease];
}
#endif

- (OFFileAttributes)attributesOfItemAtURI: (OFURI *)URI
{
	OFURIHandler *URIHandler;

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

	if ((URIHandler = [OFURIHandler handlerForURI: URI]) == nil)
		@throw [OFUnsupportedProtocolException exceptionWithURI: URI];

	return [URIHandler attributesOfItemAtURI: URI];
}

#ifdef OF_HAVE_FILES
- (OFFileAttributes)attributesOfItemAtPath: (OFString *)path
{
	void *pool = objc_autoreleasePoolPush();
	OFFileAttributes ret;

	ret = [self attributesOfItemAtURI: [OFURI fileURIWithPath: path]];

	[ret retain];

	objc_autoreleasePoolPop(pool);

	return [ret autorelease];
}
#endif

- (void)setAttributes: (OFFileAttributes)attributes ofItemAtURI: (OFURI *)URI
{
	OFURIHandler *URIHandler;

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

	if ((URIHandler = [OFURIHandler handlerForURI: URI]) == nil)
		@throw [OFUnsupportedProtocolException exceptionWithURI: URI];

	[URIHandler setAttributes: attributes ofItemAtURI: URI];
}

#ifdef OF_HAVE_FILES
- (void)setAttributes: (OFFileAttributes)attributes
	 ofItemAtPath: (OFString *)path
{
	void *pool = objc_autoreleasePoolPush();
	[self setAttributes: attributes
		ofItemAtURI: [OFURI fileURIWithPath: path]];
	objc_autoreleasePoolPop(pool);
}
#endif

- (bool)fileExistsAtURI: (OFURI *)URI
{
	OFURIHandler *URIHandler;

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

	if ((URIHandler = [OFURIHandler handlerForURI: URI]) == nil)
		@throw [OFUnsupportedProtocolException exceptionWithURI: URI];

	return [URIHandler fileExistsAtURI: URI];
}

#ifdef OF_HAVE_FILES
- (bool)fileExistsAtPath: (OFString *)path
{
	void *pool = objc_autoreleasePoolPush();
	bool ret;

	ret = [self fileExistsAtURI: [OFURI fileURIWithPath: path]];

	objc_autoreleasePoolPop(pool);

	return ret;
}
#endif

- (bool)directoryExistsAtURI: (OFURI *)URI
{
	OFURIHandler *URIHandler;

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

	if ((URIHandler = [OFURIHandler handlerForURI: URI]) == nil)
		@throw [OFUnsupportedProtocolException exceptionWithURI: URI];

	return [URIHandler directoryExistsAtURI: URI];
}

#ifdef OF_HAVE_FILES
- (bool)directoryExistsAtPath: (OFString *)path
{
	void *pool = objc_autoreleasePoolPush();
	bool ret;

	ret = [self directoryExistsAtURI: [OFURI fileURIWithPath: path]];

	objc_autoreleasePoolPop(pool);

	return ret;
}
#endif

- (void)createDirectoryAtURI: (OFURI *)URI
{

	OFURIHandler *URIHandler;

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

	if ((URIHandler = [OFURIHandler handlerForURI: URI]) == nil)
		@throw [OFUnsupportedProtocolException exceptionWithURI: URI];

	[URIHandler createDirectoryAtURI: URI];
}



- (void)createDirectoryAtURI: (OFURI *)URI createParents: (bool)createParents
{
	void *pool = objc_autoreleasePoolPush();
	OFMutableURI *mutableURI;
	OFArray OF_GENERIC(OFString *) *components;
	OFMutableArray OF_GENERIC(OFURI *) *componentURIs;
	size_t componentURIsCount;
	ssize_t i;

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

	if (!createParents) {
		[self createDirectoryAtURI: URI];


		return;
	}

	/*
	 * Try blindly creating the directory first.
	 *
	 * The reason for this is that we might be sandboxed, so attempting to
	 * create any of the parent directories will fail, while creating the
	 * directory itself will work.
	 */

	if ([self directoryExistsAtURI: URI])

		return;


	@try {
		[self createDirectoryAtURI: URI];


		return;
	} @catch (OFCreateDirectoryFailedException *e) {
		/*
		 * If we didn't fail because any of the parents is missing,
		 * there is no point in trying to create the parents.
		 */
		if (e.errNo != ENOENT)
			@throw e;
	}

	/*
	 * Because we might be sandboxed (and for remote URIs don't even know
	 * anything at all), we generate the URI for every component. We then
	 * iterate them in reverse order until we find the first existing
	 * directory, and then create subdirectories from there.
	 */
	mutableURI = [[URI mutableCopy] autorelease];
	mutableURI.percentEncodedPath = @"/";
	components = URI.pathComponents;
	componentURIs = [OFMutableArray arrayWithCapacity: components.count];

	for (OFString *component in components) {
		[mutableURI appendPathComponent: component];

		if (![mutableURI.percentEncodedPath isEqual: @"/"])
			[componentURIs addObject:
			    [[mutableURI copy] autorelease]];
	}

	componentURIsCount = componentURIs.count;
	for (i = componentURIsCount - 1; i > 0; i--) {
		if ([self directoryExistsAtURI:
		    [componentURIs objectAtIndex: i]])
			break;
	}

	if (++i == (ssize_t)componentURIsCount) {
		/*
		 * The URI exists, even though before we made sure it did not.
		 * That means it was created in the meantime by something else,
		 * so we're done here.
		 */
		objc_autoreleasePoolPop(pool);
		return;
	}

	for (; i < (ssize_t)componentURIsCount; i++)
		[self createDirectoryAtURI: [componentURIs objectAtIndex: i]];

	objc_autoreleasePoolPop(pool);
}

#ifdef OF_HAVE_FILES
- (void)createDirectoryAtPath: (OFString *)path
{
	void *pool = objc_autoreleasePoolPush();

	[self createDirectoryAtURI: [OFURI fileURIWithPath: path]];

	objc_autoreleasePoolPop(pool);
}

- (void)createDirectoryAtPath: (OFString *)path
		createParents: (bool)createParents
{
	void *pool = objc_autoreleasePoolPush();

	[self createDirectoryAtURI: [OFURI fileURIWithPath: path]
		     createParents: createParents];

	objc_autoreleasePoolPop(pool);
}
#endif

- (OFArray OF_GENERIC(OFURI *) *)contentsOfDirectoryAtURI: (OFURI *)URI
{
	OFURIHandler *URIHandler;

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

	if ((URIHandler = [OFURIHandler handlerForURI: URI]) == nil)
		@throw [OFUnsupportedProtocolException exceptionWithURI: URI];

	return [URIHandler contentsOfDirectoryAtURI: URI];
}

#ifdef OF_HAVE_FILES
- (OFArray OF_GENERIC(OFString *) *)contentsOfDirectoryAtPath: (OFString *)path
{
	void *pool = objc_autoreleasePoolPush();
	OFArray OF_GENERIC(OFURI *) *URIs;
	OFMutableArray OF_GENERIC(OFString *) *ret;

	URIs = [self contentsOfDirectoryAtURI: [OFURI fileURIWithPath: path]];
	ret = [OFMutableArray arrayWithCapacity: URIs.count];

	for (OFURI *URI in URIs)
		[ret addObject: URI.lastPathComponent];

	[ret makeImmutable];
	[ret retain];

	objc_autoreleasePoolPop(pool);

	return [ret autorelease];
}

- (OFArray OF_GENERIC(OFString *) *)subpathsOfDirectoryAtPath: (OFString *)path







|


|

|
>

<





|

|

|


|
|

|








|
<
|







|

|

|


|
|

|








|




|

|

|


|
|

|








|







|

|

|


|
|

|








|







|

>
|

|


|
|

|
|
>
|
>
|


|

|
|


|



|
>
>










>
|
>

|
>

|
>
>











|
|



|
|
|
|


|

|
|
|


|
|
|
|



|

|







|
|









|









|






|

|

|


|
|

|






|


|
|

|
|


|







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

	return [OFString stringWithCString: buffer
				  encoding: [OFLocale encoding]];
# endif
}

- (OFIRI *)currentDirectoryIRI
{
	void *pool = objc_autoreleasePoolPush();
	OFIRI *ret;

	ret = [OFIRI fileIRIWithPath: self.currentDirectoryPath];
	ret = [ret retain];


	objc_autoreleasePoolPop(pool);
	return [ret autorelease];
}
#endif

- (OFFileAttributes)attributesOfItemAtIRI: (OFIRI *)IRI
{
	OFIRIHandler *IRIHandler;

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

	if ((IRIHandler = [OFIRIHandler handlerForIRI: IRI]) == nil)
		@throw [OFUnsupportedProtocolException exceptionWithIRI: IRI];

	return [IRIHandler attributesOfItemAtIRI: IRI];
}

#ifdef OF_HAVE_FILES
- (OFFileAttributes)attributesOfItemAtPath: (OFString *)path
{
	void *pool = objc_autoreleasePoolPush();
	OFFileAttributes ret;

	ret = [self attributesOfItemAtIRI: [OFIRI fileIRIWithPath: path]];

	ret = [ret retain];

	objc_autoreleasePoolPop(pool);

	return [ret autorelease];
}
#endif

- (void)setAttributes: (OFFileAttributes)attributes ofItemAtIRI: (OFIRI *)IRI
{
	OFIRIHandler *IRIHandler;

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

	if ((IRIHandler = [OFIRIHandler handlerForIRI: IRI]) == nil)
		@throw [OFUnsupportedProtocolException exceptionWithIRI: IRI];

	[IRIHandler setAttributes: attributes ofItemAtIRI: IRI];
}

#ifdef OF_HAVE_FILES
- (void)setAttributes: (OFFileAttributes)attributes
	 ofItemAtPath: (OFString *)path
{
	void *pool = objc_autoreleasePoolPush();
	[self setAttributes: attributes
		ofItemAtIRI: [OFIRI fileIRIWithPath: path]];
	objc_autoreleasePoolPop(pool);
}
#endif

- (bool)fileExistsAtIRI: (OFIRI *)IRI
{
	OFIRIHandler *IRIHandler;

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

	if ((IRIHandler = [OFIRIHandler handlerForIRI: IRI]) == nil)
		@throw [OFUnsupportedProtocolException exceptionWithIRI: IRI];

	return [IRIHandler fileExistsAtIRI: IRI];
}

#ifdef OF_HAVE_FILES
- (bool)fileExistsAtPath: (OFString *)path
{
	void *pool = objc_autoreleasePoolPush();
	bool ret;

	ret = [self fileExistsAtIRI: [OFIRI fileIRIWithPath: path]];

	objc_autoreleasePoolPop(pool);

	return ret;
}
#endif

- (bool)directoryExistsAtIRI: (OFIRI *)IRI
{
	OFIRIHandler *IRIHandler;

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

	if ((IRIHandler = [OFIRIHandler handlerForIRI: IRI]) == nil)
		@throw [OFUnsupportedProtocolException exceptionWithIRI: IRI];

	return [IRIHandler directoryExistsAtIRI: IRI];
}

#ifdef OF_HAVE_FILES
- (bool)directoryExistsAtPath: (OFString *)path
{
	void *pool = objc_autoreleasePoolPush();
	bool ret;

	ret = [self directoryExistsAtIRI: [OFIRI fileIRIWithPath: path]];

	objc_autoreleasePoolPop(pool);

	return ret;
}
#endif

- (void)createDirectoryAtIRI: (OFIRI *)IRI
{
	void *pool = objc_autoreleasePoolPush();
	OFIRIHandler *IRIHandler;

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

	if ((IRIHandler = [OFIRIHandler handlerForIRI: IRI]) == nil)
		@throw [OFUnsupportedProtocolException exceptionWithIRI: IRI];

	[IRIHandler createDirectoryAtIRI: IRI];

	objc_autoreleasePoolPop(pool);
}

- (void)createDirectoryAtIRI: (OFIRI *)IRI createParents: (bool)createParents
{
	void *pool = objc_autoreleasePoolPush();
	OFMutableIRI *mutableIRI;
	OFArray OF_GENERIC(OFString *) *components;
	OFMutableArray OF_GENERIC(OFIRI *) *componentIRIs;
	size_t componentIRIsCount;
	ssize_t i;

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

	if (!createParents) {
		[self createDirectoryAtIRI: IRI];

		objc_autoreleasePoolPop(pool);
		return;
	}

	/*
	 * Try blindly creating the directory first.
	 *
	 * The reason for this is that we might be sandboxed, so attempting to
	 * create any of the parent directories will fail, while creating the
	 * directory itself will work.
	 */

	if ([self directoryExistsAtIRI: IRI]) {
		objc_autoreleasePoolPop(pool);
		return;
	}

	@try {
		[self createDirectoryAtIRI: IRI];

		objc_autoreleasePoolPop(pool);
		return;
	} @catch (OFCreateDirectoryFailedException *e) {
		/*
		 * If we didn't fail because any of the parents is missing,
		 * there is no point in trying to create the parents.
		 */
		if (e.errNo != ENOENT)
			@throw e;
	}

	/*
	 * Because we might be sandboxed (and for remote IRIs don't even know
	 * anything at all), we generate the IRI for every component. We then
	 * iterate them in reverse order until we find the first existing
	 * directory, and then create subdirectories from there.
	 */
	mutableIRI = [[IRI mutableCopy] autorelease];
	mutableIRI.percentEncodedPath = @"/";
	components = IRI.pathComponents;
	componentIRIs = [OFMutableArray arrayWithCapacity: components.count];

	for (OFString *component in components) {
		[mutableIRI appendPathComponent: component];

		if (![mutableIRI.percentEncodedPath isEqual: @"/"])
			[componentIRIs addObject:
			    [[mutableIRI copy] autorelease]];
	}

	componentIRIsCount = componentIRIs.count;
	for (i = componentIRIsCount - 1; i > 0; i--) {
		if ([self directoryExistsAtIRI:
		    [componentIRIs objectAtIndex: i]])
			break;
	}

	if (++i == (ssize_t)componentIRIsCount) {
		/*
		 * The IRI exists, even though before we made sure it did not.
		 * That means it was created in the meantime by something else,
		 * so we're done here.
		 */
		objc_autoreleasePoolPop(pool);
		return;
	}

	for (; i < (ssize_t)componentIRIsCount; i++)
		[self createDirectoryAtIRI: [componentIRIs objectAtIndex: i]];

	objc_autoreleasePoolPop(pool);
}

#ifdef OF_HAVE_FILES
- (void)createDirectoryAtPath: (OFString *)path
{
	void *pool = objc_autoreleasePoolPush();

	[self createDirectoryAtIRI: [OFIRI fileIRIWithPath: path]];

	objc_autoreleasePoolPop(pool);
}

- (void)createDirectoryAtPath: (OFString *)path
		createParents: (bool)createParents
{
	void *pool = objc_autoreleasePoolPush();

	[self createDirectoryAtIRI: [OFIRI fileIRIWithPath: path]
		     createParents: createParents];

	objc_autoreleasePoolPop(pool);
}
#endif

- (OFArray OF_GENERIC(OFIRI *) *)contentsOfDirectoryAtIRI: (OFIRI *)IRI
{
	OFIRIHandler *IRIHandler;

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

	if ((IRIHandler = [OFIRIHandler handlerForIRI: IRI]) == nil)
		@throw [OFUnsupportedProtocolException exceptionWithIRI: IRI];

	return [IRIHandler contentsOfDirectoryAtIRI: IRI];
}

#ifdef OF_HAVE_FILES
- (OFArray OF_GENERIC(OFString *) *)contentsOfDirectoryAtPath: (OFString *)path
{
	void *pool = objc_autoreleasePoolPush();
	OFArray OF_GENERIC(OFIRI *) *IRIs;
	OFMutableArray OF_GENERIC(OFString *) *ret;

	IRIs = [self contentsOfDirectoryAtIRI: [OFIRI fileIRIWithPath: path]];
	ret = [OFMutableArray arrayWithCapacity: IRIs.count];

	for (OFIRI *IRI in IRIs)
		[ret addObject: IRI.lastPathComponent];

	[ret makeImmutable];
	ret = [ret retain];

	objc_autoreleasePoolPop(pool);

	return [ret autorelease];
}

- (OFArray OF_GENERIC(OFString *) *)subpathsOfDirectoryAtPath: (OFString *)path
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
		else
			[ret addObject: fullSubpath];

		objc_autoreleasePoolPop(pool2);
	}

	[ret makeImmutable];
	[ret retain];

	objc_autoreleasePoolPop(pool);

	return [ret autorelease];
}

- (void)changeCurrentDirectoryPath: (OFString *)path







|







509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
		else
			[ret addObject: fullSubpath];

		objc_autoreleasePoolPop(pool2);
	}

	[ret makeImmutable];
	ret = [ret retain];

	objc_autoreleasePoolPop(pool);

	return [ret autorelease];
}

- (void)changeCurrentDirectoryPath: (OFString *)path
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
	if (status != 0)
		@throw [OFChangeCurrentDirectoryFailedException
		    exceptionWithPath: path
				errNo: errno];
# endif
}

- (void)changeCurrentDirectoryURI: (OFURI *)URI
{
	void *pool = objc_autoreleasePoolPush();

	[self changeCurrentDirectoryPath: URI.fileSystemRepresentation];

	objc_autoreleasePoolPop(pool);
}

- (void)copyItemAtPath: (OFString *)source toPath: (OFString *)destination
{
	void *pool = objc_autoreleasePoolPush();

	[self copyItemAtURI: [OFURI fileURIWithPath: source]
		      toURI: [OFURI fileURIWithPath: destination]];

	objc_autoreleasePoolPop(pool);
}
#endif

- (void)copyItemAtURI: (OFURI *)source toURI: (OFURI *)destination
{
	void *pool;
	OFURIHandler *URIHandler;
	OFFileAttributes attributes;
	OFFileAttributeType type;

	if (source == nil || destination == nil)
		@throw [OFInvalidArgumentException exception];

	pool = objc_autoreleasePoolPush();

	if ((URIHandler = [OFURIHandler handlerForURI: source]) == nil)
		@throw [OFUnsupportedProtocolException
		    exceptionWithURI: source];

	if ([URIHandler copyItemAtURI: source toURI: destination])
		return;

	if ([self fileExistsAtURI: destination])
		@throw [OFCopyItemFailedException
		    exceptionWithSourceURI: source
			    destinationURI: destination
				     errNo: EEXIST];

	@try {
		attributes = [self attributesOfItemAtURI: source];
	} @catch (OFGetItemAttributesFailedException *e) {
		@throw [OFCopyItemFailedException
		    exceptionWithSourceURI: source
			    destinationURI: destination
				     errNo: e.errNo];
	}

	type = attributes.fileType;

	if ([type isEqual: OFFileTypeDirectory]) {
		OFArray OF_GENERIC(OFURI *) *contents;

		@try {
			[self createDirectoryAtURI: destination];

			@try {
				OFFileAttributeKey key = OFFilePOSIXPermissions;
				OFNumber *permissions =
				    [attributes objectForKey: key];
				OFFileAttributes destinationAttributes;

				if (permissions != nil) {
					destinationAttributes = [OFDictionary
					    dictionaryWithObject: permissions
							  forKey: key];
					[self
					    setAttributes: destinationAttributes
					      ofItemAtURI: destination];
				}
			} @catch (OFNotImplementedException *e) {
			}

			contents = [self contentsOfDirectoryAtURI: source];
		} @catch (id e) {
			/*
			 * Only convert exceptions to OFCopyItemFailedException
			 * that have an errNo property. This covers all I/O
			 * related exceptions from the operations used to copy
			 * an item, all others should be left as is.
			 */
			if ([e respondsToSelector: @selector(errNo)])
				@throw [OFCopyItemFailedException
				    exceptionWithSourceURI: source
					    destinationURI: destination
						     errNo: [e errNo]];

			@throw e;
		}

		for (OFURI *item in contents) {
			void *pool2 = objc_autoreleasePoolPush();
			OFURI *destinationURI = [destination
			    URIByAppendingPathComponent:
			    item.lastPathComponent];

			[self copyItemAtURI: item toURI: destinationURI];

			objc_autoreleasePoolPop(pool2);
		}
	} else if ([type isEqual: OFFileTypeRegular]) {
		size_t pageSize = [OFSystemInfo pageSize];
		OFStream *sourceStream = nil;
		OFStream *destinationStream = nil;
		char *buffer;

		buffer = OFAllocMemory(1, pageSize);
		@try {
			sourceStream = [OFURIHandler openItemAtURI: source
							      mode: @"r"];
			destinationStream = [OFURIHandler
			    openItemAtURI: destination
				     mode: @"w"];

			while (!sourceStream.atEndOfStream) {
				size_t length;

				length = [sourceStream
				    readIntoBuffer: buffer







|



|








|
|





|


|








|

|

|


|

|
|



|


|
|






|


|













|




|









|
|





|

|
|


|











|

|
|







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
	if (status != 0)
		@throw [OFChangeCurrentDirectoryFailedException
		    exceptionWithPath: path
				errNo: errno];
# endif
}

- (void)changeCurrentDirectoryIRI: (OFIRI *)IRI
{
	void *pool = objc_autoreleasePoolPush();

	[self changeCurrentDirectoryPath: IRI.fileSystemRepresentation];

	objc_autoreleasePoolPop(pool);
}

- (void)copyItemAtPath: (OFString *)source toPath: (OFString *)destination
{
	void *pool = objc_autoreleasePoolPush();

	[self copyItemAtIRI: [OFIRI fileIRIWithPath: source]
		      toIRI: [OFIRI fileIRIWithPath: destination]];

	objc_autoreleasePoolPop(pool);
}
#endif

- (void)copyItemAtIRI: (OFIRI *)source toIRI: (OFIRI *)destination
{
	void *pool;
	OFIRIHandler *IRIHandler;
	OFFileAttributes attributes;
	OFFileAttributeType type;

	if (source == nil || destination == nil)
		@throw [OFInvalidArgumentException exception];

	pool = objc_autoreleasePoolPush();

	if ((IRIHandler = [OFIRIHandler handlerForIRI: source]) == nil)
		@throw [OFUnsupportedProtocolException
		    exceptionWithIRI: source];

	if ([IRIHandler copyItemAtIRI: source toIRI: destination])
		return;

	if ([self fileExistsAtIRI: destination])
		@throw [OFCopyItemFailedException
		    exceptionWithSourceIRI: source
			    destinationIRI: destination
				     errNo: EEXIST];

	@try {
		attributes = [self attributesOfItemAtIRI: source];
	} @catch (OFGetItemAttributesFailedException *e) {
		@throw [OFCopyItemFailedException
		    exceptionWithSourceIRI: source
			    destinationIRI: destination
				     errNo: e.errNo];
	}

	type = attributes.fileType;

	if ([type isEqual: OFFileTypeDirectory]) {
		OFArray OF_GENERIC(OFIRI *) *contents;

		@try {
			[self createDirectoryAtIRI: destination];

			@try {
				OFFileAttributeKey key = OFFilePOSIXPermissions;
				OFNumber *permissions =
				    [attributes objectForKey: key];
				OFFileAttributes destinationAttributes;

				if (permissions != nil) {
					destinationAttributes = [OFDictionary
					    dictionaryWithObject: permissions
							  forKey: key];
					[self
					    setAttributes: destinationAttributes
					      ofItemAtIRI: destination];
				}
			} @catch (OFNotImplementedException *e) {
			}

			contents = [self contentsOfDirectoryAtIRI: source];
		} @catch (id e) {
			/*
			 * Only convert exceptions to OFCopyItemFailedException
			 * that have an errNo property. This covers all I/O
			 * related exceptions from the operations used to copy
			 * an item, all others should be left as is.
			 */
			if ([e respondsToSelector: @selector(errNo)])
				@throw [OFCopyItemFailedException
				    exceptionWithSourceIRI: source
					    destinationIRI: destination
						     errNo: [e errNo]];

			@throw e;
		}

		for (OFIRI *item in contents) {
			void *pool2 = objc_autoreleasePoolPush();
			OFIRI *destinationIRI = [destination
			    IRIByAppendingPathComponent:
			    item.lastPathComponent];

			[self copyItemAtIRI: item toIRI: destinationIRI];

			objc_autoreleasePoolPop(pool2);
		}
	} else if ([type isEqual: OFFileTypeRegular]) {
		size_t pageSize = [OFSystemInfo pageSize];
		OFStream *sourceStream = nil;
		OFStream *destinationStream = nil;
		char *buffer;

		buffer = OFAllocMemory(1, pageSize);
		@try {
			sourceStream = [OFIRIHandler openItemAtIRI: source
							      mode: @"r"];
			destinationStream = [OFIRIHandler
			    openItemAtIRI: destination
				     mode: @"w"];

			while (!sourceStream.atEndOfStream) {
				size_t length;

				length = [sourceStream
				    readIntoBuffer: buffer
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887























































































888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915

				if (permissions != nil) {
					destinationAttributes = [OFDictionary
					    dictionaryWithObject: permissions
							  forKey: key];
					[self
					    setAttributes: destinationAttributes
					      ofItemAtURI: destination];
				}
			} @catch (OFNotImplementedException *e) {
			}
		} @catch (id e) {
			/*
			 * Only convert exceptions to OFCopyItemFailedException
			 * that have an errNo property. This covers all I/O
			 * related exceptions from the operations used to copy
			 * an item, all others should be left as is.
			 */
			if ([e respondsToSelector: @selector(errNo)])
				@throw [OFCopyItemFailedException
				    exceptionWithSourceURI: source
					    destinationURI: destination
						     errNo: [e errNo]];

			@throw e;
		} @finally {
			[sourceStream close];
			[destinationStream close];
			OFFreeMemory(buffer);
		}
	} else if ([type isEqual: OFFileTypeSymbolicLink]) {
		@try {
			OFString *linkDestination =
			    attributes.fileSymbolicLinkDestination;

			[self createSymbolicLinkAtURI: destination
				  withDestinationPath: linkDestination];
		} @catch (id e) {
			/*
			 * Only convert exceptions to OFCopyItemFailedException
			 * that have an errNo property. This covers all I/O
			 * related exceptions from the operations used to copy
			 * an item, all others should be left as is.
			 */
			if ([e respondsToSelector: @selector(errNo)])
				@throw [OFCopyItemFailedException
				    exceptionWithSourceURI: source
					    destinationURI: destination
						     errNo: [e errNo]];

			@throw e;
		}
	} else
		@throw [OFCopyItemFailedException
		    exceptionWithSourceURI: source
			    destinationURI: destination
				     errNo: EINVAL];

	objc_autoreleasePoolPop(pool);
}

#ifdef OF_HAVE_FILES
- (void)moveItemAtPath: (OFString *)source toPath: (OFString *)destination
{
	void *pool = objc_autoreleasePoolPush();
	[self moveItemAtURI: [OFURI fileURIWithPath: source]
		      toURI: [OFURI fileURIWithPath: destination]];
	objc_autoreleasePoolPop(pool);
}
#endif

- (void)moveItemAtURI: (OFURI *)source toURI: (OFURI *)destination
{
	void *pool;
	OFURIHandler *URIHandler;

	if (source == nil || destination == nil)
		@throw [OFInvalidArgumentException exception];

	pool = objc_autoreleasePoolPush();

	if ((URIHandler = [OFURIHandler handlerForURI: source]) == nil)
		@throw [OFUnsupportedProtocolException
		    exceptionWithURI: source];

	@try {
		if ([URIHandler moveItemAtURI: source toURI: destination])
			return;
	} @catch (OFMoveItemFailedException *e) {
		if (e.errNo != EXDEV)
			@throw e;
	}

	if ([self fileExistsAtURI: destination])
		@throw [OFMoveItemFailedException
		    exceptionWithSourceURI: source
			    destinationURI: destination
				     errNo: EEXIST];

	@try {
		[self copyItemAtURI: source toURI: destination];
	} @catch (OFCopyItemFailedException *e) {
		[self removeItemAtURI: destination];

		@throw [OFMoveItemFailedException
		    exceptionWithSourceURI: source
			    destinationURI: destination
				     errNo: e.errNo];
	}

	@try {
		[self removeItemAtURI: source];
	} @catch (OFRemoveItemFailedException *e) {
		@throw [OFMoveItemFailedException
		    exceptionWithSourceURI: source
			    destinationURI: destination
				     errNo: e.errNo];
	}

	objc_autoreleasePoolPop(pool);
}

- (void)removeItemAtURI: (OFURI *)URI
{
	OFURIHandler *URIHandler;

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

	if ((URIHandler = [OFURIHandler handlerForURI: URI]) == nil)
		@throw [OFUnsupportedProtocolException exceptionWithURI: URI];

	[URIHandler removeItemAtURI: URI];
}

#ifdef OF_HAVE_FILES
- (void)removeItemAtPath: (OFString *)path
{
	void *pool = objc_autoreleasePoolPush();
	[self removeItemAtURI: [OFURI fileURIWithPath: path]];
	objc_autoreleasePoolPop(pool);
}
#endif

- (void)linkItemAtURI: (OFURI *)source toURI: (OFURI *)destination
{
	void *pool = objc_autoreleasePoolPush();
	OFURIHandler *URIHandler;

	if (source == nil || destination == nil)
		@throw [OFInvalidArgumentException exception];

	if (![destination.scheme isEqual: source.scheme])
		@throw [OFInvalidArgumentException exception];

	URIHandler = [OFURIHandler handlerForURI: source];

	if (URIHandler == nil)
		@throw [OFUnsupportedProtocolException
		    exceptionWithURI: source];

	[URIHandler linkItemAtURI: source toURI: destination];

	objc_autoreleasePoolPop(pool);
}

#ifdef OF_FILE_MANAGER_SUPPORTS_LINKS
- (void)linkItemAtPath: (OFString *)source toPath: (OFString *)destination
{
	void *pool = objc_autoreleasePoolPush();
	[self linkItemAtURI: [OFURI fileURIWithPath: source]
		      toURI: [OFURI fileURIWithPath: destination]];
	objc_autoreleasePoolPop(pool);
}
#endif

- (void)createSymbolicLinkAtURI: (OFURI *)URI
	    withDestinationPath: (OFString *)target
{
	void *pool = objc_autoreleasePoolPush();
	OFURIHandler *URIHandler;

	if (URI == nil || target == nil)
		@throw [OFInvalidArgumentException exception];

	URIHandler = [OFURIHandler handlerForURI: URI];

	if (URIHandler == nil)
		@throw [OFUnsupportedProtocolException exceptionWithURI: URI];

	[URIHandler createSymbolicLinkAtURI: URI withDestinationPath: target];

	objc_autoreleasePoolPop(pool);
}

#ifdef OF_FILE_MANAGER_SUPPORTS_SYMLINKS
- (void)createSymbolicLinkAtPath: (OFString *)path
	     withDestinationPath: (OFString *)target
{
	void *pool = objc_autoreleasePoolPush();
	[self createSymbolicLinkAtURI: [OFURI fileURIWithPath: path]
		  withDestinationPath: target];
	objc_autoreleasePoolPop(pool);
}
#endif























































































@end

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

- (instancetype)retain
{
	return self;
}

- (void)release
{
}

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

@implementation OFDictionary (FileAttributes)
- (unsigned long long)fileSize
{
	return [attributeForKeyOrException(self, OFFileSize)
	    unsignedLongLongValue];







|












|
|













|










|
|






|
|









|
|




|


|






|

|


|






|

|
|



|

|


|
|




|


|
|






|

|

|


|
|

|






|




|


|







|

|

|

|








|
|




|



|

|


|

|
|

|









|




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



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







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

				if (permissions != nil) {
					destinationAttributes = [OFDictionary
					    dictionaryWithObject: permissions
							  forKey: key];
					[self
					    setAttributes: destinationAttributes
					      ofItemAtIRI: destination];
				}
			} @catch (OFNotImplementedException *e) {
			}
		} @catch (id e) {
			/*
			 * Only convert exceptions to OFCopyItemFailedException
			 * that have an errNo property. This covers all I/O
			 * related exceptions from the operations used to copy
			 * an item, all others should be left as is.
			 */
			if ([e respondsToSelector: @selector(errNo)])
				@throw [OFCopyItemFailedException
				    exceptionWithSourceIRI: source
					    destinationIRI: destination
						     errNo: [e errNo]];

			@throw e;
		} @finally {
			[sourceStream close];
			[destinationStream close];
			OFFreeMemory(buffer);
		}
	} else if ([type isEqual: OFFileTypeSymbolicLink]) {
		@try {
			OFString *linkDestination =
			    attributes.fileSymbolicLinkDestination;

			[self createSymbolicLinkAtIRI: destination
				  withDestinationPath: linkDestination];
		} @catch (id e) {
			/*
			 * Only convert exceptions to OFCopyItemFailedException
			 * that have an errNo property. This covers all I/O
			 * related exceptions from the operations used to copy
			 * an item, all others should be left as is.
			 */
			if ([e respondsToSelector: @selector(errNo)])
				@throw [OFCopyItemFailedException
				    exceptionWithSourceIRI: source
					    destinationIRI: destination
						     errNo: [e errNo]];

			@throw e;
		}
	} else
		@throw [OFCopyItemFailedException
		    exceptionWithSourceIRI: source
			    destinationIRI: destination
				     errNo: EINVAL];

	objc_autoreleasePoolPop(pool);
}

#ifdef OF_HAVE_FILES
- (void)moveItemAtPath: (OFString *)source toPath: (OFString *)destination
{
	void *pool = objc_autoreleasePoolPush();
	[self moveItemAtIRI: [OFIRI fileIRIWithPath: source]
		      toIRI: [OFIRI fileIRIWithPath: destination]];
	objc_autoreleasePoolPop(pool);
}
#endif

- (void)moveItemAtIRI: (OFIRI *)source toIRI: (OFIRI *)destination
{
	void *pool;
	OFIRIHandler *IRIHandler;

	if (source == nil || destination == nil)
		@throw [OFInvalidArgumentException exception];

	pool = objc_autoreleasePoolPush();

	if ((IRIHandler = [OFIRIHandler handlerForIRI: source]) == nil)
		@throw [OFUnsupportedProtocolException
		    exceptionWithIRI: source];

	@try {
		if ([IRIHandler moveItemAtIRI: source toIRI: destination])
			return;
	} @catch (OFMoveItemFailedException *e) {
		if (e.errNo != EXDEV)
			@throw e;
	}

	if ([self fileExistsAtIRI: destination])
		@throw [OFMoveItemFailedException
		    exceptionWithSourceIRI: source
			    destinationIRI: destination
				     errNo: EEXIST];

	@try {
		[self copyItemAtIRI: source toIRI: destination];
	} @catch (OFCopyItemFailedException *e) {
		[self removeItemAtIRI: destination];

		@throw [OFMoveItemFailedException
		    exceptionWithSourceIRI: source
			    destinationIRI: destination
				     errNo: e.errNo];
	}

	@try {
		[self removeItemAtIRI: source];
	} @catch (OFRemoveItemFailedException *e) {
		@throw [OFMoveItemFailedException
		    exceptionWithSourceIRI: source
			    destinationIRI: destination
				     errNo: e.errNo];
	}

	objc_autoreleasePoolPop(pool);
}

- (void)removeItemAtIRI: (OFIRI *)IRI
{
	OFIRIHandler *IRIHandler;

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

	if ((IRIHandler = [OFIRIHandler handlerForIRI: IRI]) == nil)
		@throw [OFUnsupportedProtocolException exceptionWithIRI: IRI];

	[IRIHandler removeItemAtIRI: IRI];
}

#ifdef OF_HAVE_FILES
- (void)removeItemAtPath: (OFString *)path
{
	void *pool = objc_autoreleasePoolPush();
	[self removeItemAtIRI: [OFIRI fileIRIWithPath: path]];
	objc_autoreleasePoolPop(pool);
}
#endif

- (void)linkItemAtIRI: (OFIRI *)source toIRI: (OFIRI *)destination
{
	void *pool = objc_autoreleasePoolPush();
	OFIRIHandler *IRIHandler;

	if (source == nil || destination == nil)
		@throw [OFInvalidArgumentException exception];

	if (![destination.scheme isEqual: source.scheme])
		@throw [OFInvalidArgumentException exception];

	IRIHandler = [OFIRIHandler handlerForIRI: source];

	if (IRIHandler == nil)
		@throw [OFUnsupportedProtocolException
		    exceptionWithIRI: source];

	[IRIHandler linkItemAtIRI: source toIRI: destination];

	objc_autoreleasePoolPop(pool);
}

#ifdef OF_FILE_MANAGER_SUPPORTS_LINKS
- (void)linkItemAtPath: (OFString *)source toPath: (OFString *)destination
{
	void *pool = objc_autoreleasePoolPush();
	[self linkItemAtIRI: [OFIRI fileIRIWithPath: source]
		      toIRI: [OFIRI fileIRIWithPath: destination]];
	objc_autoreleasePoolPop(pool);
}
#endif

- (void)createSymbolicLinkAtIRI: (OFIRI *)IRI
	    withDestinationPath: (OFString *)target
{
	void *pool = objc_autoreleasePoolPush();
	OFIRIHandler *IRIHandler;

	if (IRI == nil || target == nil)
		@throw [OFInvalidArgumentException exception];

	IRIHandler = [OFIRIHandler handlerForIRI: IRI];

	if (IRIHandler == nil)
		@throw [OFUnsupportedProtocolException exceptionWithIRI: IRI];

	[IRIHandler createSymbolicLinkAtIRI: IRI withDestinationPath: target];

	objc_autoreleasePoolPop(pool);
}

#ifdef OF_FILE_MANAGER_SUPPORTS_SYMLINKS
- (void)createSymbolicLinkAtPath: (OFString *)path
	     withDestinationPath: (OFString *)target
{
	void *pool = objc_autoreleasePoolPush();
	[self createSymbolicLinkAtIRI: [OFIRI fileIRIWithPath: path]
		  withDestinationPath: target];
	objc_autoreleasePoolPop(pool);
}
#endif

- (OFData *)extendedAttributeDataForName: (OFString *)name
			     ofItemAtIRI: (OFIRI *)IRI
{
	OFIRIHandler *IRIHandler;

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

	if ((IRIHandler = [OFIRIHandler handlerForIRI: IRI]) == nil)
		@throw [OFUnsupportedProtocolException exceptionWithIRI: IRI];

	return [IRIHandler extendedAttributeDataForName: name ofItemAtIRI: IRI];
}

#ifdef OF_FILE_MANAGER_SUPPORTS_EXTENDED_ATTRIBUTES
- (OFData *)extendedAttributeDataForName: (OFString *)name
			    ofItemAtPath: (OFString *)path
{
	void *pool = objc_autoreleasePoolPush();
	OFData *ret;

	ret = [self
	    extendedAttributeDataForName: name
			     ofItemAtIRI: [OFIRI fileIRIWithPath: path]];
	ret = [ret retain];

	objc_autoreleasePoolPop(pool);

	return [ret autorelease];
}
#endif

- (void)setExtendedAttributeData: (OFData *)data
			 forName: (OFString *)name
		     ofItemAtIRI: (OFIRI *)IRI
{
	OFIRIHandler *IRIHandler;

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

	if ((IRIHandler = [OFIRIHandler handlerForIRI: IRI]) == nil)
		@throw [OFUnsupportedProtocolException exceptionWithIRI: IRI];

	[IRIHandler setExtendedAttributeData: data
				     forName: name
				 ofItemAtIRI: IRI];
}

#ifdef OF_FILE_MANAGER_SUPPORTS_EXTENDED_ATTRIBUTES
- (void)setExtendedAttributeData: (OFData *)data
			 forName: (OFString *)name
		    ofItemAtPath: (OFString *)path
{
	void *pool = objc_autoreleasePoolPush();
	[self setExtendedAttributeData: data
			       forName: name
			   ofItemAtIRI: [OFIRI fileIRIWithPath: path]];
	objc_autoreleasePoolPop(pool);
}
#endif

- (void)removeExtendedAttributeForName: (OFString *)name
			   ofItemAtIRI: (OFIRI *)IRI
{
	OFIRIHandler *IRIHandler;

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

	if ((IRIHandler = [OFIRIHandler handlerForIRI: IRI]) == nil)
		@throw [OFUnsupportedProtocolException exceptionWithIRI: IRI];

	[IRIHandler removeExtendedAttributeForName: name ofItemAtIRI: IRI];
}

#ifdef OF_FILE_MANAGER_SUPPORTS_EXTENDED_ATTRIBUTES
- (void)removeExtendedAttributeForName: (OFString *)name
			  ofItemAtPath: (OFString *)path
{
	void *pool = objc_autoreleasePoolPush();
	[self removeExtendedAttributeForName: name
				 ofItemAtIRI: [OFIRI fileIRIWithPath: path]];
	objc_autoreleasePoolPop(pool);
}
#endif
@end

@implementation OFDefaultFileManager




OF_SINGLETON_METHODS













@end

@implementation OFDictionary (FileAttributes)
- (unsigned long long)fileSize
{
	return [attributeForKeyOrException(self, OFFileSize)
	    unsignedLongLongValue];
968
969
970
971
972
973
974





975
	return attributeForKeyOrException(self, OFFileCreationDate);
}

- (OFString *)fileSymbolicLinkDestination
{
	return attributeForKeyOrException(self, OFFileSymbolicLinkDestination);
}





@end







>
>
>
>
>

1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
	return attributeForKeyOrException(self, OFFileCreationDate);
}

- (OFString *)fileSymbolicLinkDestination
{
	return attributeForKeyOrException(self, OFFileSymbolicLinkDestination);
}

- (OFArray OF_GENERIC(OFString *) *)fileExtendedAttributesNames
{
	return attributeForKeyOrException(self, OFFileExtendedAttributesNames);
}
@end

Modified src/OFFileManagerConstants.inc from [7a3eb9bf4f] to [ba42fe98b1].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
24
25
26
27
28
29
30


31
32
33
34
35
36
37
38
39
40
    @"OFFileGroupOwnerAccountName";
const OFFileAttributeKey OFFileLastAccessDate = @"OFFileLastAccessDate";
const OFFileAttributeKey OFFileModificationDate = @"OFFileModificationDate";
const OFFileAttributeKey OFFileStatusChangeDate = @"OFFileStatusChangeDate";
const OFFileAttributeKey OFFileCreationDate = @"OFFileCreationDate";
const OFFileAttributeKey OFFileSymbolicLinkDestination =
    @"OFFileSymbolicLinkDestination";



const OFFileAttributeType OFFileTypeRegular = @"OFFileTypeRegular";
const OFFileAttributeType OFFileTypeDirectory = @"OFFileTypeDirectory";
const OFFileAttributeType OFFileTypeSymbolicLink = @"OFFileTypeSymbolicLink";
const OFFileAttributeType OFFileTypeFIFO = @"OFFileTypeFIFO";
const OFFileAttributeType OFFileTypeCharacterSpecial =
    @"OFFileTypeCharacterSpecial";
const OFFileAttributeType OFFileTypeBlockSpecial = @"OFFileTypeBlockSpecial";
const OFFileAttributeType OFFileTypeSocket = @"OFFileTypeSocket";
const OFFileAttributeType OFFileTypeUnknown = @"OFFileTypeUnknown";







>
>










24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
    @"OFFileGroupOwnerAccountName";
const OFFileAttributeKey OFFileLastAccessDate = @"OFFileLastAccessDate";
const OFFileAttributeKey OFFileModificationDate = @"OFFileModificationDate";
const OFFileAttributeKey OFFileStatusChangeDate = @"OFFileStatusChangeDate";
const OFFileAttributeKey OFFileCreationDate = @"OFFileCreationDate";
const OFFileAttributeKey OFFileSymbolicLinkDestination =
    @"OFFileSymbolicLinkDestination";
const OFFileAttributeKey OFFileExtendedAttributesNames =
    @"OFFileExtendedAttributesNames";

const OFFileAttributeType OFFileTypeRegular = @"OFFileTypeRegular";
const OFFileAttributeType OFFileTypeDirectory = @"OFFileTypeDirectory";
const OFFileAttributeType OFFileTypeSymbolicLink = @"OFFileTypeSymbolicLink";
const OFFileAttributeType OFFileTypeFIFO = @"OFFileTypeFIFO";
const OFFileAttributeType OFFileTypeCharacterSpecial =
    @"OFFileTypeCharacterSpecial";
const OFFileAttributeType OFFileTypeBlockSpecial = @"OFFileTypeBlockSpecial";
const OFFileAttributeType OFFileTypeSocket = @"OFFileTypeSocket";
const OFFileAttributeType OFFileTypeUnknown = @"OFFileTypeUnknown";

Modified src/OFGZIPStream.h from [40a91bbae5] to [bf332d7a3d].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFGZIPStream.m from [947da42ac6] to [51e839e54b].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
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
{
	if (_stream == nil)
		@throw [OFNotOpenException exceptionWithObject: self];

	return _stream.atEndOfStream;
}

- (bool)hasDataInReadBuffer
{
	if (_state == OFGZIPStreamStateData)
		return (super.hasDataInReadBuffer ||
		    _inflateStream.hasDataInReadBuffer);

	return (super.hasDataInReadBuffer || _stream.hasDataInReadBuffer);
}

- (void)close
{
	if (_stream == nil)
		@throw [OFNotOpenException exceptionWithObject: self];

	[_stream release];
	_stream = nil;

	[super close];
}
@end







|


<
|
|
|













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
{
	if (_stream == nil)
		@throw [OFNotOpenException exceptionWithObject: self];

	return _stream.atEndOfStream;
}

- (bool)lowlevelHasDataInReadBuffer
{
	if (_state == OFGZIPStreamStateData)

		return _inflateStream.hasDataInReadBuffer;
	else
		return _stream.hasDataInReadBuffer;
}

- (void)close
{
	if (_stream == nil)
		@throw [OFNotOpenException exceptionWithObject: self];

	[_stream release];
	_stream = nil;

	[super close];
}
@end

Modified src/OFHMAC.h from [2d8e8879fb] to [3a6b613bd4].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFHMAC.m from [2ceebc7fc2] to [14fcb32275].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFHTTPClient.h from [d5da950339] to [0e950c9026].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
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

OF_ASSUME_NONNULL_BEGIN

@class OFDictionary OF_GENERIC(KeyType, ObjectType);
@class OFHTTPClient;
@class OFHTTPRequest;
@class OFHTTPResponse;

@class OFStream;
@class OFTCPSocket;
@class OFTLSStream;
@class OFURI;

/**
 * @protocol OFHTTPClientDelegate OFHTTPClient.h ObjFW/OFHTTPClient.h
 *
 * @brief A delegate for OFHTTPClient.
 */
@protocol OFHTTPClientDelegate <OFObject>
/**
 * @brief A callback which is called when an OFHTTPClient performed a request.

 *
 * @param client The OFHTTPClient which performed the request
 * @param request The request the OFHTTPClient performed
 * @param response The response to the request performed, or nil on error
 * @param exception An exception if the request failed, or nil on success
 */
-      (void)client: (OFHTTPClient *)client
  didPerformRequest: (OFHTTPRequest *)request
	   response: (nullable OFHTTPResponse *)response
	  exception: (nullable id)exception;

@optional
/**
 * @brief A callback which is called when an OFHTTPClient creates a TCP socket.

 *
 * This can be used to tell the socket about a SOCKS5 proxy it should use for
 * this connection.
 *
 * @param client The OFHTTPClient that created a TCP socket
 * @param TCPSocket The socket created by the OFHTTPClient
 * @param request The request for which the TCP socket was created
 */
-	(void)client: (OFHTTPClient *)client
  didCreateTCPSocket: (OFTCPSocket *)TCPSocket
	     request: (OFHTTPRequest *)request;

/**
 * @brief A callback which is called when an OFHTTPClient creates a TLS stream.

 *
 * This can be used to tell the TLS stream about a client certificate it should
 * use before performing the TLS handshake.
 *
 * @param client The OFHTTPClient that created a TLS stream
 * @param TLSStream The TLS stream created by the OFHTTPClient
 * @param request The request for which the TLS stream was created
 */
-	(void)client: (OFHTTPClient *)client
  didCreateTLSStream: (OFTLSStream *)TLSStream
	     request: (OFHTTPRequest *)request;

/**
 * @brief A callback which is called when an OFHTTPClient wants to send the
 *	  body for a request.
 *
 * @param client The OFHTTPClient that wants to send the body
 * @param requestBody A stream into which the body of the request should be
 *		      written
 * @param request The request for which the OFHTTPClient wants to send the body
 */
-     (void)client: (OFHTTPClient *)client
  wantsRequestBody: (OFStream *)requestBody
	   request: (OFHTTPRequest *)request;

/**
 * @brief A callback which is called when an OFHTTPClient received headers.
 *
 * @param client The OFHTTPClient which received the headers
 * @param headers The headers received
 * @param statusCode The status code received
 * @param request The request for which the headers and status code have been
 *		  received
 */
-      (void)client: (OFHTTPClient *)client
  didReceiveHeaders: (OFDictionary OF_GENERIC(OFString *, OFString *) *)headers
	 statusCode: (short)statusCode
	    request: (OFHTTPRequest *)request;

/**
 * @brief A callback which is called when an OFHTTPClient wants to follow a
 *	  redirect.
 *
 * If you want to get the headers and data for each redirect, set the number of
 * redirects to 0 and perform a new OFHTTPClient for each redirect. However,
 * this callback will not be called then and you have to look at the status code
 * to detect a redirect.
 *
 * This callback will only be called if the OFHTTPClient will follow a
 * redirect. If the maximum number of redirects has been reached already, this
 * callback will not be called.
 *
 * @param client The OFHTTPClient which wants to follow a redirect
 * @param URI The URI to which it will follow a redirect
 * @param statusCode The status code for the redirection
 * @param request The request for which the OFHTTPClient wants to redirect.
 *		  You are allowed to change the request's headers from this
 *		  callback and they will be used when following the redirect
 *		  (e.g. to set the cookies for the new URI), however, keep in
 *		  mind that this will change the request you originally passed.
 * @param response The response indicating the redirect
 * @return A boolean whether the OFHTTPClient should follow the redirect
 */
-	       (bool)client: (OFHTTPClient *)client
  shouldFollowRedirectToURI: (OFURI *)URI
		 statusCode: (short)statusCode
		    request: (OFHTTPRequest *)request
		   response: (OFHTTPResponse *)response;
@end

/**
 * @class OFHTTPClient OFHTTPClient.h ObjFW/OFHTTPClient.h
 *
 * @brief A class for performing HTTP requests.
 */
OF_SUBCLASSING_RESTRICTED
@interface OFHTTPClient: OFObject
{
#ifdef OF_HTTP_CLIENT_M
@public
#endif
	OFObject <OFHTTPClientDelegate> *_Nullable _delegate;
	bool _allowsInsecureRedirects, _inProgress;
	OFStream *_Nullable _stream;
	OFURI *_Nullable _lastURI;
	bool _lastWasHEAD;
	OFHTTPResponse *_Nullable _lastResponse;
}

/**
 * @brief The delegate of the HTTP request.
 */







>



<








|
>













|
>













|
>













|
|











|













|
|











|




|





|



















|







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

OF_ASSUME_NONNULL_BEGIN

@class OFDictionary OF_GENERIC(KeyType, ObjectType);
@class OFHTTPClient;
@class OFHTTPRequest;
@class OFHTTPResponse;
@class OFIRI;
@class OFStream;
@class OFTCPSocket;
@class OFTLSStream;


/**
 * @protocol OFHTTPClientDelegate OFHTTPClient.h ObjFW/OFHTTPClient.h
 *
 * @brief A delegate for OFHTTPClient.
 */
@protocol OFHTTPClientDelegate <OFObject>
/**
 * @brief A callback which is called when an @ref OFHTTPClient performed a
 *	  request.
 *
 * @param client The OFHTTPClient which performed the request
 * @param request The request the OFHTTPClient performed
 * @param response The response to the request performed, or nil on error
 * @param exception An exception if the request failed, or nil on success
 */
-      (void)client: (OFHTTPClient *)client
  didPerformRequest: (OFHTTPRequest *)request
	   response: (nullable OFHTTPResponse *)response
	  exception: (nullable id)exception;

@optional
/**
 * @brief A callback which is called when an @ref OFHTTPClient creates a TCP
 *	  socket.
 *
 * This can be used to tell the socket about a SOCKS5 proxy it should use for
 * this connection.
 *
 * @param client The OFHTTPClient that created a TCP socket
 * @param TCPSocket The socket created by the OFHTTPClient
 * @param request The request for which the TCP socket was created
 */
-	(void)client: (OFHTTPClient *)client
  didCreateTCPSocket: (OFTCPSocket *)TCPSocket
	     request: (OFHTTPRequest *)request;

/**
 * @brief A callback which is called when an @ref OFHTTPClient creates a TLS
 *	  stream.
 *
 * This can be used to tell the TLS stream about a client certificate it should
 * use before performing the TLS handshake.
 *
 * @param client The OFHTTPClient that created a TLS stream
 * @param TLSStream The TLS stream created by the OFHTTPClient
 * @param request The request for which the TLS stream was created
 */
-	(void)client: (OFHTTPClient *)client
  didCreateTLSStream: (OFTLSStream *)TLSStream
	     request: (OFHTTPRequest *)request;

/**
 * @brief A callback which is called when an @ref OFHTTPClient wants to send
 *	  the body for a request.
 *
 * @param client The OFHTTPClient that wants to send the body
 * @param requestBody A stream into which the body of the request should be
 *		      written
 * @param request The request for which the OFHTTPClient wants to send the body
 */
-     (void)client: (OFHTTPClient *)client
  wantsRequestBody: (OFStream *)requestBody
	   request: (OFHTTPRequest *)request;

/**
 * @brief A callback which is called when an @ref OFHTTPClient received headers.
 *
 * @param client The OFHTTPClient which received the headers
 * @param headers The headers received
 * @param statusCode The status code received
 * @param request The request for which the headers and status code have been
 *		  received
 */
-      (void)client: (OFHTTPClient *)client
  didReceiveHeaders: (OFDictionary OF_GENERIC(OFString *, OFString *) *)headers
	 statusCode: (short)statusCode
	    request: (OFHTTPRequest *)request;

/**
 * @brief A callback which is called when an @ref OFHTTPClient wants to follow
 *	  a redirect.
 *
 * If you want to get the headers and data for each redirect, set the number of
 * redirects to 0 and perform a new OFHTTPClient for each redirect. However,
 * this callback will not be called then and you have to look at the status code
 * to detect a redirect.
 *
 * This callback will only be called if the OFHTTPClient will follow a
 * redirect. If the maximum number of redirects has been reached already, this
 * callback will not be called.
 *
 * @param client The OFHTTPClient which wants to follow a redirect
 * @param IRI The IRI to which it will follow a redirect
 * @param statusCode The status code for the redirection
 * @param request The request for which the OFHTTPClient wants to redirect.
 *		  You are allowed to change the request's headers from this
 *		  callback and they will be used when following the redirect
 *		  (e.g. to set the cookies for the new IRI), however, keep in
 *		  mind that this will change the request you originally passed.
 * @param response The response indicating the redirect
 * @return A boolean whether the OFHTTPClient should follow the redirect
 */
-	       (bool)client: (OFHTTPClient *)client
  shouldFollowRedirectToIRI: (OFIRI *)IRI
		 statusCode: (short)statusCode
		    request: (OFHTTPRequest *)request
		   response: (OFHTTPResponse *)response;
@end

/**
 * @class OFHTTPClient OFHTTPClient.h ObjFW/OFHTTPClient.h
 *
 * @brief A class for performing HTTP requests.
 */
OF_SUBCLASSING_RESTRICTED
@interface OFHTTPClient: OFObject
{
#ifdef OF_HTTP_CLIENT_M
@public
#endif
	OFObject <OFHTTPClientDelegate> *_Nullable _delegate;
	bool _allowsInsecureRedirects, _inProgress;
	OFStream *_Nullable _stream;
	OFIRI *_Nullable _lastIRI;
	bool _lastWasHEAD;
	OFHTTPResponse *_Nullable _lastResponse;
}

/**
 * @brief The delegate of the HTTP request.
 */
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
 *
 * @param request The request to perform
 * @return The OFHTTPResponse for the request
 * @throw OFHTTPRequestFailedException The HTTP request failed
 * @throw OFInvalidServerResponseException The server sent an invalid response
 * @throw OFUnsupportedVersionException The server responded in an unsupported
 *					version
 * @throw OFAlreadyConnectedException The client is already performing a request
 */
- (OFHTTPResponse *)performRequest: (OFHTTPRequest *)request;

/**
 * @brief Synchronously performs the specified HTTP request.
 *
 * @note You must not change the delegate while a synchronous request is
 *	 running! If you want to change the delegate during the request,
 *	 perform an asynchronous request instead!
 *
 * @param request The request to perform
 * @param redirects The maximum number of redirects after which no further
 *		    attempt is done to follow the redirect, but instead the
 *		    redirect is treated as an OFHTTPResponse
 * @return The OFHTTPResponse for the request
 * @throw OFHTTPRequestFailedException The HTTP request failed
 * @throw OFInvalidServerResponseException The server sent an invalid response
 * @throw OFUnsupportedVersionException The server responded in an unsupported
 *					version
 * @throw OFAlreadyConnectedException The client is already performing a request
 */
- (OFHTTPResponse *)performRequest: (OFHTTPRequest *)request
			 redirects: (unsigned int)redirects;

/**
 * @brief Asynchronously performs the specified HTTP request.
 *
 * @param request The request to perform
 * @throw OFAlreadyConnectedException The client is already performing a request
 */
- (void)asyncPerformRequest: (OFHTTPRequest *)request;

/**
 * @brief Asynchronously performs the specified HTTP request.
 *
 * @param request The request to perform
 * @param redirects The maximum number of redirects after which no further
 *		    attempt is done to follow the redirect, but instead the
 *		    redirect is treated as an OFHTTPResponse
 * @throw OFAlreadyConnectedException The client is already performing a request
 */
- (void)asyncPerformRequest: (OFHTTPRequest *)request
		  redirects: (unsigned int)redirects;

/**
 * @brief Closes connections that are still open due to keep-alive.
 */
- (void)close;
@end

OF_ASSUME_NONNULL_END







|



















|








|










|











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
 *
 * @param request The request to perform
 * @return The OFHTTPResponse for the request
 * @throw OFHTTPRequestFailedException The HTTP request failed
 * @throw OFInvalidServerResponseException The server sent an invalid response
 * @throw OFUnsupportedVersionException The server responded in an unsupported
 *					version
 * @throw OFAlreadyOpenException The client is already performing a request
 */
- (OFHTTPResponse *)performRequest: (OFHTTPRequest *)request;

/**
 * @brief Synchronously performs the specified HTTP request.
 *
 * @note You must not change the delegate while a synchronous request is
 *	 running! If you want to change the delegate during the request,
 *	 perform an asynchronous request instead!
 *
 * @param request The request to perform
 * @param redirects The maximum number of redirects after which no further
 *		    attempt is done to follow the redirect, but instead the
 *		    redirect is treated as an OFHTTPResponse
 * @return The OFHTTPResponse for the request
 * @throw OFHTTPRequestFailedException The HTTP request failed
 * @throw OFInvalidServerResponseException The server sent an invalid response
 * @throw OFUnsupportedVersionException The server responded in an unsupported
 *					version
 * @throw OFAlreadyOpenException The client is already performing a request
 */
- (OFHTTPResponse *)performRequest: (OFHTTPRequest *)request
			 redirects: (unsigned int)redirects;

/**
 * @brief Asynchronously performs the specified HTTP request.
 *
 * @param request The request to perform
 * @throw OFAlreadyOpenException The client is already performing a request
 */
- (void)asyncPerformRequest: (OFHTTPRequest *)request;

/**
 * @brief Asynchronously performs the specified HTTP request.
 *
 * @param request The request to perform
 * @param redirects The maximum number of redirects after which no further
 *		    attempt is done to follow the redirect, but instead the
 *		    redirect is treated as an OFHTTPResponse
 * @throw OFAlreadyOpenException The client is already performing a request
 */
- (void)asyncPerformRequest: (OFHTTPRequest *)request
		  redirects: (unsigned int)redirects;

/**
 * @brief Closes connections that are still open due to keep-alive.
 */
- (void)close;
@end

OF_ASSUME_NONNULL_END

Modified src/OFHTTPClient.m from [e887f99bf5] to [fa2090d82b].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
21
22
23
24
25
26
27

28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include <string.h>

#import "OFHTTPClient.h"
#import "OFData.h"
#import "OFDictionary.h"
#import "OFHTTPRequest.h"
#import "OFHTTPResponse.h"

#import "OFKernelEventObserver.h"
#import "OFNumber.h"
#import "OFRunLoop.h"
#import "OFString.h"
#import "OFTCPSocket.h"
#import "OFTLSStream.h"
#import "OFURI.h"

#import "OFAlreadyConnectedException.h"
#import "OFHTTPRequestFailedException.h"
#import "OFInvalidArgumentException.h"
#import "OFInvalidEncodingException.h"
#import "OFInvalidFormatException.h"
#import "OFInvalidServerResponseException.h"
#import "OFNotImplementedException.h"
#import "OFNotOpenException.h"







>






<

|







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

35
36
37
38
39
40
41
42
43
#include <string.h>

#import "OFHTTPClient.h"
#import "OFData.h"
#import "OFDictionary.h"
#import "OFHTTPRequest.h"
#import "OFHTTPResponse.h"
#import "OFIRI.h"
#import "OFKernelEventObserver.h"
#import "OFNumber.h"
#import "OFRunLoop.h"
#import "OFString.h"
#import "OFTCPSocket.h"
#import "OFTLSStream.h"


#import "OFAlreadyOpenException.h"
#import "OFHTTPRequestFailedException.h"
#import "OFInvalidArgumentException.h"
#import "OFInvalidEncodingException.h"
#import "OFInvalidFormatException.h"
#import "OFInvalidServerResponseException.h"
#import "OFNotImplementedException.h"
#import "OFNotOpenException.h"
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
@end

static OFString *
constructRequestString(OFHTTPRequest *request)
{
	void *pool = objc_autoreleasePoolPush();
	OFHTTPRequestMethod method = request.method;
	OFURI *URI = request.URI;
	OFString *path;
	OFString *user = URI.user, *password = URI.password;
	OFMutableString *requestString;
	OFMutableDictionary OF_GENERIC(OFString *, OFString *) *headers;
	bool hasContentLength, chunked;
	OFEnumerator OF_GENERIC(OFString *) *keyEnumerator, *objectEnumerator;
	OFString *key, *object;

	if (URI.path.length > 0)
		path = URI.percentEncodedPath;
	else
		path = @"/";

	requestString = [OFMutableString stringWithFormat:
	    @"%s %@", OFHTTPRequestMethodName(method), path];

	if (URI.query != nil) {
		[requestString appendString: @"?"];
		[requestString appendString: URI.percentEncodedQuery];
	}

	[requestString appendString: @" HTTP/"];
	[requestString appendString: request.protocolVersionString];
	[requestString appendString: @"\r\n"];

	headers = [[request.headers mutableCopy] autorelease];
	if (headers == nil)
		headers = [OFMutableDictionary dictionary];

	if ([headers objectForKey: @"Host"] == nil) {
		OFNumber *port = URI.port;

		if (port != nil) {
			OFString *host = [OFString stringWithFormat:
			    @"%@:%@", URI.percentEncodedHost, port];

			[headers setObject: host forKey: @"Host"];
		} else
			[headers setObject: URI.percentEncodedHost
				    forKey: @"Host"];
	}

	if ((user.length > 0 || password.length > 0) &&
	    [headers objectForKey: @"Authorization"] == nil) {
		OFMutableData *authorizationData = [OFMutableData data];
		OFString *authorization;







|

|






|
|




|

|

|











|



|



|







113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
@end

static OFString *
constructRequestString(OFHTTPRequest *request)
{
	void *pool = objc_autoreleasePoolPush();
	OFHTTPRequestMethod method = request.method;
	OFIRI *IRI = request.IRI.IRIByAddingPercentEncodingForUnicodeCharacters;
	OFString *path;
	OFString *user = IRI.user, *password = IRI.password;
	OFMutableString *requestString;
	OFMutableDictionary OF_GENERIC(OFString *, OFString *) *headers;
	bool hasContentLength, chunked;
	OFEnumerator OF_GENERIC(OFString *) *keyEnumerator, *objectEnumerator;
	OFString *key, *object;

	if (IRI.path.length > 0)
		path = IRI.percentEncodedPath;
	else
		path = @"/";

	requestString = [OFMutableString stringWithFormat:
	    @"%@ %@", OFHTTPRequestMethodString(method), path];

	if (IRI.query != nil) {
		[requestString appendString: @"?"];
		[requestString appendString: IRI.percentEncodedQuery];
	}

	[requestString appendString: @" HTTP/"];
	[requestString appendString: request.protocolVersionString];
	[requestString appendString: @"\r\n"];

	headers = [[request.headers mutableCopy] autorelease];
	if (headers == nil)
		headers = [OFMutableDictionary dictionary];

	if ([headers objectForKey: @"Host"] == nil) {
		OFNumber *port = IRI.port;

		if (port != nil) {
			OFString *host = [OFString stringWithFormat:
			    @"%@:%@", IRI.percentEncodedHost, port];

			[headers setObject: host forKey: @"Host"];
		} else
			[headers setObject: IRI.percentEncodedHost
				    forKey: @"Host"];
	}

	if ((user.length > 0 || password.length > 0) &&
	    [headers objectForKey: @"Authorization"] == nil) {
		OFMutableData *authorizationData = [OFMutableData data];
		OFString *authorization;
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
		authorization = [OFString stringWithFormat:
		    @"Basic %@", authorizationData.stringByBase64Encoding];

		[headers setObject: authorization forKey: @"Authorization"];
	}

	if ([headers objectForKey: @"User-Agent"] == nil)
		[headers setObject: @"Something using ObjFW "
				    @"<https://objfw.nil.im/>"
			    forKey: @"User-Agent"];

	if (request.protocolVersion.major == 1 &&
	    request.protocolVersion.minor == 0 &&
	    [headers objectForKey: @"Connection"] == nil)
		[headers setObject: @"keep-alive" forKey: @"Connection"];








|
|







174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
		authorization = [OFString stringWithFormat:
		    @"Basic %@", authorizationData.stringByBase64Encoding];

		[headers setObject: authorization forKey: @"Authorization"];
	}

	if ([headers objectForKey: @"User-Agent"] == nil)
		[headers setObject: @"OFHTTPClient (ObjFW's HTTP client class "
				    @"<https://objfw.nil.im/>)"
			    forKey: @"User-Agent"];

	if (request.protocolVersion.major == 1 &&
	    request.protocolVersion.minor == 0 &&
	    [headers objectForKey: @"Connection"] == nil)
		[headers setObject: @"keep-alive" forKey: @"Connection"];

295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
		 didPerformRequest: _request
			  response: nil
			 exception: exception];
}

- (void)createResponseWithStreamOrThrow: (OFStream *)stream
{
	OFURI *URI = _request.URI;
	OFHTTPClientResponse *response;
	OFString *connectionHeader;
	bool keepAlive;
	OFString *location;
	id exception;

	response = [[[OFHTTPClientResponse alloc] initWithStream: stream]







|







295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
		 didPerformRequest: _request
			  response: nil
			 exception: exception];
}

- (void)createResponseWithStreamOrThrow: (OFStream *)stream
{
	OFIRI *IRI = _request.IRI;
	OFHTTPClientResponse *response;
	OFString *connectionHeader;
	bool keepAlive;
	OFString *location;
	id exception;

	response = [[[OFHTTPClientResponse alloc] initWithStream: stream]
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
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
			keepAlive = false;
	}

	if (keepAlive) {
		response.of_keepAlive = true;

		_client->_stream = [stream retain];
		_client->_lastURI = [URI copy];
		_client->_lastWasHEAD =
		    (_request.method == OFHTTPRequestMethodHead);
		_client->_lastResponse = [response retain];
	}

	if (_redirects > 0 && (_status == 301 || _status == 302 ||
	    _status == 303 || _status == 307) &&
	    (location = [_serverHeaders objectForKey: @"Location"]) != nil) {
		bool follow = true;
		OFURI *newURI;
		OFString *newURIScheme;

		newURI = [OFURI URIWithString: location relativeToURI: URI];
		newURIScheme = newURI.scheme;

		if ([newURIScheme caseInsensitiveCompare: @"http"] !=
		    OFOrderedSame &&
		    [newURIScheme caseInsensitiveCompare: @"https"] !=
		    OFOrderedSame)
			follow = false;

		if (!_client->_allowsInsecureRedirects &&
		    [URI.scheme caseInsensitiveCompare: @"https"] ==
		    OFOrderedSame &&
		    [newURIScheme caseInsensitiveCompare: @"http"] ==
		    OFOrderedSame)
			follow = false;

		if (follow && [_client->_delegate respondsToSelector:
		    @selector(client:shouldFollowRedirectToURI:statusCode:
		    request:response:)])
			follow = [_client->_delegate client: _client
				  shouldFollowRedirectToURI: newURI
						 statusCode: _status
						    request: _request
						   response: response];
		else if (follow)
			follow = defaultShouldFollow(_request.method, _status);

		if (follow) {
			OFDictionary OF_GENERIC(OFString *, OFString *)
			    *headers = _request.headers;
			OFHTTPRequest *newRequest =
			    [[_request copy] autorelease];
			OFMutableDictionary *newHeaders =
			    [[headers mutableCopy] autorelease];

			if (![newURI.host isEqual: URI.host])
				[newHeaders removeObjectForKey: @"Host"];

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

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

				newRequest.method = OFHTTPRequestMethodGet;
			}

			newRequest.URI = newURI;
			newRequest.headers = newHeaders;

			_client->_inProgress = false;

			[_client asyncPerformRequest: newRequest
					   redirects: _redirects - 1];
			return;







|









|
|

|
|

|

|




|

|




|


|














|








<
|
<
<
<
<
<
<
<








|







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
			keepAlive = false;
	}

	if (keepAlive) {
		response.of_keepAlive = true;

		_client->_stream = [stream retain];
		_client->_lastIRI = [IRI copy];
		_client->_lastWasHEAD =
		    (_request.method == OFHTTPRequestMethodHead);
		_client->_lastResponse = [response retain];
	}

	if (_redirects > 0 && (_status == 301 || _status == 302 ||
	    _status == 303 || _status == 307) &&
	    (location = [_serverHeaders objectForKey: @"Location"]) != nil) {
		bool follow = true;
		OFIRI *newIRI;
		OFString *newIRIScheme;

		newIRI = [OFIRI IRIWithString: location relativeToIRI: IRI];
		newIRIScheme = newIRI.scheme;

		if ([newIRIScheme caseInsensitiveCompare: @"http"] !=
		    OFOrderedSame &&
		    [newIRIScheme caseInsensitiveCompare: @"https"] !=
		    OFOrderedSame)
			follow = false;

		if (!_client->_allowsInsecureRedirects &&
		    [IRI.scheme caseInsensitiveCompare: @"https"] ==
		    OFOrderedSame &&
		    [newIRIScheme caseInsensitiveCompare: @"http"] ==
		    OFOrderedSame)
			follow = false;

		if (follow && [_client->_delegate respondsToSelector:
		    @selector(client:shouldFollowRedirectToIRI:statusCode:
		    request:response:)])
			follow = [_client->_delegate client: _client
				  shouldFollowRedirectToIRI: newIRI
						 statusCode: _status
						    request: _request
						   response: response];
		else if (follow)
			follow = defaultShouldFollow(_request.method, _status);

		if (follow) {
			OFDictionary OF_GENERIC(OFString *, OFString *)
			    *headers = _request.headers;
			OFHTTPRequest *newRequest =
			    [[_request copy] autorelease];
			OFMutableDictionary *newHeaders =
			    [[headers mutableCopy] autorelease];

			if (![newIRI.host isEqual: IRI.host])
				[newHeaders removeObjectForKey: @"Host"];

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

				for (OFString *key in headers)







					if ([key hasPrefix: @"Content-"] ||
					    [key hasPrefix: @"Transfer-"])
						[newHeaders
						    removeObjectForKey: key];

				newRequest.method = OFHTTPRequestMethodGet;
			}

			newRequest.IRI = newIRI;
			newRequest.headers = newHeaders;

			_client->_inProgress = false;

			[_client asyncPerformRequest: newRequest
					   redirects: _redirects - 1];
			return;
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
	 exception: (id)exception
{
	if (exception != nil) {
		[self raiseException: exception];
		return;
	}

	sock.canBlock = false;

	if ([_client->_delegate respondsToSelector:
	    @selector(client:didCreateTCPSocket:request:)])
		[_client->_delegate client: _client
			didCreateTCPSocket: sock
				   request: _request];

	if ([_request.URI.scheme caseInsensitiveCompare: @"https"] ==
	    OFOrderedSame) {
		OFTLSStream *stream;
		@try {
			stream = [OFTLSStream streamWithStream: sock];
		} @catch (OFNotImplementedException *e) {
			[self raiseException:
			    [OFUnsupportedProtocolException
			    exceptionWithURI: _request.URI]];
			return;
		}

		if ([_client->_delegate respondsToSelector:
		    @selector(client:didCreateTLSStream:request:)])
			[_client->_delegate client: _client
				didCreateTLSStream: stream
					   request: _request];

		stream.delegate = self;
		[stream asyncPerformClientHandshakeWithHost: _request.URI.host];

	} else {
		sock.delegate = self;
		[self performSelector: @selector(handleStream:)
			   withObject: sock
			   afterDelay: 0];
	}
}







<
<






|







|










|
>







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
	 exception: (id)exception
{
	if (exception != nil) {
		[self raiseException: exception];
		return;
	}



	if ([_client->_delegate respondsToSelector:
	    @selector(client:didCreateTCPSocket:request:)])
		[_client->_delegate client: _client
			didCreateTCPSocket: sock
				   request: _request];

	if ([_request.IRI.scheme caseInsensitiveCompare: @"https"] ==
	    OFOrderedSame) {
		OFTLSStream *stream;
		@try {
			stream = [OFTLSStream streamWithStream: sock];
		} @catch (OFNotImplementedException *e) {
			[self raiseException:
			    [OFUnsupportedProtocolException
			    exceptionWithIRI: _request.IRI]];
			return;
		}

		if ([_client->_delegate respondsToSelector:
		    @selector(client:didCreateTLSStream:request:)])
			[_client->_delegate client: _client
				didCreateTLSStream: stream
					   request: _request];

		stream.delegate = self;
		[stream asyncPerformClientHandshakeWithHost: _request.IRI
		    .IRIByAddingPercentEncodingForUnicodeCharacters.host];
	} else {
		sock.delegate = self;
		[self performSelector: @selector(handleStream:)
			   withObject: sock
			   afterDelay: 0];
	}
}
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731

732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
	[self performSelector: @selector(handleStream:)
		   withObject: stream
		   afterDelay: 0];
}

- (void)start
{
	OFURI *URI = _request.URI;
	OFStream *stream;

	/* Can we reuse the last socket? */
	if (_client->_stream != nil && !_client->_stream.atEndOfStream &&
	    [_client->_lastURI.scheme isEqual: URI.scheme] &&
	    [_client->_lastURI.host isEqual: URI.host] &&
	    (_client->_lastURI.port == URI.port ||
	    [_client->_lastURI.port isEqual: URI.port]) &&
	    (_client->_lastWasHEAD || _client->_lastResponse.atEndOfStream)) {
		/*
		 * Set _stream to nil, so that in case of an error it won't be
		 * reused. If everything is successful, we set _stream again
		 * at the end.
		 */
		stream = [_client->_stream autorelease];
		_client->_stream = nil;

		[_client->_lastURI release];
		_client->_lastURI = nil;

		[_client->_lastResponse release];
		_client->_lastResponse = nil;

		stream.delegate = self;

		[self performSelector: @selector(handleStream:)
			   withObject: stream
			   afterDelay: 0];
	} else
		[self closeAndReconnect];
}

- (void)closeAndReconnect
{
	@try {
		OFURI *URI = _request.URI;

		OFTCPSocket *sock;
		uint16_t port;
		OFNumber *URIPort;

		[_client close];

		sock = [OFTCPSocket socket];

		if ([URI.scheme caseInsensitiveCompare: @"https"] ==
		    OFOrderedSame)
			port = 443;
		else
			port = 80;

		URIPort = URI.port;
		if (URIPort != nil)
			port = URIPort.unsignedShortValue;

		sock.delegate = self;
		[sock asyncConnectToHost: URI.host port: port];
	} @catch (id e) {
		[self raiseException: e];
	}
}
@end

@implementation OFHTTPClientRequestBodyStream







|




|
|
|
|









|
|
















|
>


|





|





|
|
|


|







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
	[self performSelector: @selector(handleStream:)
		   withObject: stream
		   afterDelay: 0];
}

- (void)start
{
	OFIRI *IRI = _request.IRI;
	OFStream *stream;

	/* Can we reuse the last socket? */
	if (_client->_stream != nil && !_client->_stream.atEndOfStream &&
	    [_client->_lastIRI.scheme isEqual: IRI.scheme] &&
	    [_client->_lastIRI.host isEqual: IRI.host] &&
	    (_client->_lastIRI.port == IRI.port ||
	    [_client->_lastIRI.port isEqual: IRI.port]) &&
	    (_client->_lastWasHEAD || _client->_lastResponse.atEndOfStream)) {
		/*
		 * Set _stream to nil, so that in case of an error it won't be
		 * reused. If everything is successful, we set _stream again
		 * at the end.
		 */
		stream = [_client->_stream autorelease];
		_client->_stream = nil;

		[_client->_lastIRI release];
		_client->_lastIRI = nil;

		[_client->_lastResponse release];
		_client->_lastResponse = nil;

		stream.delegate = self;

		[self performSelector: @selector(handleStream:)
			   withObject: stream
			   afterDelay: 0];
	} else
		[self closeAndReconnect];
}

- (void)closeAndReconnect
{
	@try {
		OFIRI *IRI =
		    _request.IRI.IRIByAddingPercentEncodingForUnicodeCharacters;
		OFTCPSocket *sock;
		uint16_t port;
		OFNumber *IRIPort;

		[_client close];

		sock = [OFTCPSocket socket];

		if ([IRI.scheme caseInsensitiveCompare: @"https"] ==
		    OFOrderedSame)
			port = 443;
		else
			port = 80;

		IRIPort = IRI.port;
		if (IRIPort != nil)
			port = IRIPort.unsignedShortValue;

		sock.delegate = self;
		[sock asyncConnectToHost: IRI.host port: port];
	} @catch (id e) {
		[self raiseException: e];
	}
}
@end

@implementation OFHTTPClientRequestBodyStream
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
	if (_stream == nil)
		return -1;

	return ((OFStream <OFReadyForReadingObserving> *)_stream)
	    .fileDescriptorForReading;
}

- (bool)hasDataInReadBuffer
{
	return (super.hasDataInReadBuffer || _stream.hasDataInReadBuffer);
}

- (void)close
{
	if (_stream == nil)
		@throw [OFNotOpenException exceptionWithObject: self];








|

|







1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
	if (_stream == nil)
		return -1;

	return ((OFStream <OFReadyForReadingObserving> *)_stream)
	    .fileDescriptorForReading;
}

- (bool)lowlevelHasDataInReadBuffer
{
	return _stream.hasDataInReadBuffer;
}

- (void)close
{
	if (_stream == nil)
		@throw [OFNotOpenException exceptionWithObject: self];

1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
		[_delegate     client: client
		    didReceiveHeaders: headers
			   statusCode: statusCode
			      request: request];
}

-	       (bool)client: (OFHTTPClient *)client
  shouldFollowRedirectToURI: (OFURI *)URI
		 statusCode: (short)statusCode
		    request: (OFHTTPRequest *)request
		   response: (OFHTTPResponse *)response
{
	if ([_delegate respondsToSelector: @selector(
	    client:shouldFollowRedirectToURI:statusCode:request:response:)])
		return [_delegate      client: client
		    shouldFollowRedirectToURI: URI
				   statusCode: statusCode
				      request: request
				     response: response];
	else
		return defaultShouldFollow(request.method, statusCode);
}
@end







|





|

|







1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
		[_delegate     client: client
		    didReceiveHeaders: headers
			   statusCode: statusCode
			      request: request];
}

-	       (bool)client: (OFHTTPClient *)client
  shouldFollowRedirectToIRI: (OFIRI *)IRI
		 statusCode: (short)statusCode
		    request: (OFHTTPRequest *)request
		   response: (OFHTTPResponse *)response
{
	if ([_delegate respondsToSelector: @selector(
	    client:shouldFollowRedirectToIRI:statusCode:request:response:)])
		return [_delegate      client: client
		    shouldFollowRedirectToIRI: IRI
				   statusCode: statusCode
				      request: request
				     response: response];
	else
		return defaultShouldFollow(request.method, statusCode);
}
@end
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
	[self asyncPerformRequest: request redirects: defaultRedirects];
}

- (void)asyncPerformRequest: (OFHTTPRequest *)request
		  redirects: (unsigned int)redirects
{
	void *pool = objc_autoreleasePoolPush();
	OFURI *URI = request.URI;
	OFString *scheme = URI.scheme;

	if ([scheme caseInsensitiveCompare: @"http"] != OFOrderedSame &&
	    [scheme caseInsensitiveCompare: @"https"] != OFOrderedSame)
		@throw [OFUnsupportedProtocolException exceptionWithURI: URI];

	if (_inProgress)
		@throw [OFAlreadyConnectedException exception];

	_inProgress = true;

	[[[[OFHTTPClientRequestHandler alloc]
	    initWithClient: self
		   request: request
		 redirects: redirects] autorelease] start];

	objc_autoreleasePoolPop(pool);
}

- (void)close
{
	[_stream release];
	_stream = nil;

	[_lastURI release];
	_lastURI = nil;

	[_lastResponse release];
	_lastResponse = nil;
}
@end







|
|



|


|
















|
|





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
	[self asyncPerformRequest: request redirects: defaultRedirects];
}

- (void)asyncPerformRequest: (OFHTTPRequest *)request
		  redirects: (unsigned int)redirects
{
	void *pool = objc_autoreleasePoolPush();
	OFIRI *IRI = request.IRI;
	OFString *scheme = IRI.scheme;

	if ([scheme caseInsensitiveCompare: @"http"] != OFOrderedSame &&
	    [scheme caseInsensitiveCompare: @"https"] != OFOrderedSame)
		@throw [OFUnsupportedProtocolException exceptionWithIRI: IRI];

	if (_inProgress)
		@throw [OFAlreadyOpenException exceptionWithObject: self];

	_inProgress = true;

	[[[[OFHTTPClientRequestHandler alloc]
	    initWithClient: self
		   request: request
		 redirects: redirects] autorelease] start];

	objc_autoreleasePoolPop(pool);
}

- (void)close
{
	[_stream release];
	_stream = nil;

	[_lastIRI release];
	_lastIRI = nil;

	[_lastResponse release];
	_lastResponse = nil;
}
@end

Modified src/OFHTTPCookie.h from [ff53970b1e] to [cdc87e0419].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
17
18
19
20
21
22
23

24
25
26
27
28
29
30
31
32
#import "OFString.h"

OF_ASSUME_NONNULL_BEGIN

@class OFArray OF_GENERIC(ObjectType);
@class OFDate;
@class OFDictionary OF_GENERIC(KeyType, ObjectType);

@class OFMutableArray OF_GENERIC(ObjectType);
@class OFURI;

/**
 * @class OFHTTPCookie OFHTTPCookie.h ObjFW/OFHTTPCookie.h
 *
 * @brief A class for storing and manipulating HTTP cookies.
 */
OF_SUBCLASSING_RESTRICTED







>

<







17
18
19
20
21
22
23
24
25

26
27
28
29
30
31
32
#import "OFString.h"

OF_ASSUME_NONNULL_BEGIN

@class OFArray OF_GENERIC(ObjectType);
@class OFDate;
@class OFDictionary OF_GENERIC(KeyType, ObjectType);
@class OFIRI;
@class OFMutableArray OF_GENERIC(ObjectType);


/**
 * @class OFHTTPCookie OFHTTPCookie.h ObjFW/OFHTTPCookie.h
 *
 * @brief A class for storing and manipulating HTTP cookies.
 */
OF_SUBCLASSING_RESTRICTED
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
/**
 * @brief An array of other attributes.
 */
@property (readonly, nonatomic)
    OFMutableArray OF_GENERIC(OFString *) *extensions;

/**
 * @brief Parses the specified response header fields for the specified URI and
 *	  returns an array of cookies.
 *
 * @param headerFields The response header fields to parse
 * @param URI The URI for the response header fields to parse
 * @return An array of cookies
 * @throw OFInvalidFormatException The specified response header has an invalid
 *				   format
 */
+ (OFArray OF_GENERIC(OFHTTPCookie *) *)cookiesWithResponseHeaderFields:
    (OFDictionary OF_GENERIC(OFString *, OFString *) *)headerFields
    forURI: (OFURI *)URI;

/**
 * @brief Returns the request header fields for the specified cookies.
 *
 * @param cookies The cookies to return the request header fields for
 * @return The request header fields for the specified cookies
 */







|



|






|







76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
/**
 * @brief An array of other attributes.
 */
@property (readonly, nonatomic)
    OFMutableArray OF_GENERIC(OFString *) *extensions;

/**
 * @brief Parses the specified response header fields for the specified IRI and
 *	  returns an array of cookies.
 *
 * @param headerFields The response header fields to parse
 * @param IRI The IRI for the response header fields to parse
 * @return An array of cookies
 * @throw OFInvalidFormatException The specified response header has an invalid
 *				   format
 */
+ (OFArray OF_GENERIC(OFHTTPCookie *) *)cookiesWithResponseHeaderFields:
    (OFDictionary OF_GENERIC(OFString *, OFString *) *)headerFields
    forIRI: (OFIRI *)IRI;

/**
 * @brief Returns the request header fields for the specified cookies.
 *
 * @param cookies The cookies to return the request header fields for
 * @return The request header fields for the specified cookies
 */

Modified src/OFHTTPCookie.m from [a7d6a07918] to [5ea98ab91a].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#import "OFHTTPCookie.h"
#import "OFArray.h"
#import "OFDate.h"
#import "OFDictionary.h"
#import "OFURI.h"

#import "OFInvalidFormatException.h"

static void
handleAttribute(OFHTTPCookie *cookie, OFString *name, OFString *value)
{
	OFString *lowercaseName = name.lowercaseString;

|



















|







1
2
3
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.
 */

#include "config.h"

#import "OFHTTPCookie.h"
#import "OFArray.h"
#import "OFDate.h"
#import "OFDictionary.h"
#import "OFIRI.h"

#import "OFInvalidFormatException.h"

static void
handleAttribute(OFHTTPCookie *cookie, OFString *name, OFString *value)
{
	OFString *lowercaseName = name.lowercaseString;
58
59
60
61
62
63
64
65
66
67
68
69
70

71
72
73
74
75
76
77
@implementation OFHTTPCookie
@synthesize name = _name, value = _value, domain = _domain, path = _path;
@synthesize expires = _expires, secure = _secure, HTTPOnly = _HTTPOnly;
@synthesize extensions = _extensions;

+ (OFArray OF_GENERIC(OFHTTPCookie *) *)cookiesWithResponseHeaderFields:
    (OFDictionary OF_GENERIC(OFString *, OFString *) *)headerFields
    forURI: (OFURI *)URI
{
	OFMutableArray OF_GENERIC(OFHTTPCookie *) *ret = [OFMutableArray array];
	void *pool = objc_autoreleasePoolPush();
	OFString *string = [headerFields objectForKey: @"Set-Cookie"];
	OFString *domain = URI.host;

	const OFUnichar *characters = string.characters;
	size_t length = string.length, last = 0;
	enum {
		statePreName,
		stateName,
		stateExpectValue,
		stateValue,







|




|
>







58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
@implementation OFHTTPCookie
@synthesize name = _name, value = _value, domain = _domain, path = _path;
@synthesize expires = _expires, secure = _secure, HTTPOnly = _HTTPOnly;
@synthesize extensions = _extensions;

+ (OFArray OF_GENERIC(OFHTTPCookie *) *)cookiesWithResponseHeaderFields:
    (OFDictionary OF_GENERIC(OFString *, OFString *) *)headerFields
    forIRI: (OFIRI *)IRI
{
	OFMutableArray OF_GENERIC(OFHTTPCookie *) *ret = [OFMutableArray array];
	void *pool = objc_autoreleasePoolPush();
	OFString *string = [headerFields objectForKey: @"Set-Cookie"];
	OFString *domain = IRI.IRIByAddingPercentEncodingForUnicodeCharacters
	    .host;
	const OFUnichar *characters = string.characters;
	size_t length = string.length, last = 0;
	enum {
		statePreName,
		stateName,
		stateExpectValue,
		stateValue,

Modified src/OFHTTPCookieManager.h from [3cc0432376] to [1fb91d1f1b].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

22
23
24
25
26
27
28
29
30
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#import "OFObject.h"

OF_ASSUME_NONNULL_BEGIN

@class OFArray OF_GENERIC(ObjectType);
@class OFHTTPCookie;

@class OFMutableArray OF_GENERIC(ObjectType);
@class OFURI;

/**
 * @class OFHTTPCookieManager OFHTTPCookieManager.h ObjFW/OFHTTPCookieManager.h
 *
 * @brief A class for managing cookies for multiple domains.
 */
OF_SUBCLASSING_RESTRICTED

|



















>

<







1
2
3
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.
 */

#import "OFObject.h"

OF_ASSUME_NONNULL_BEGIN

@class OFArray OF_GENERIC(ObjectType);
@class OFHTTPCookie;
@class OFIRI;
@class OFMutableArray OF_GENERIC(ObjectType);


/**
 * @class OFHTTPCookieManager OFHTTPCookieManager.h ObjFW/OFHTTPCookieManager.h
 *
 * @brief A class for managing cookies for multiple domains.
 */
OF_SUBCLASSING_RESTRICTED
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
 * @brief Create a new cookie manager.
 *
 * @return A new, autoreleased OFHTTPCookieManager
 */
+ (instancetype)manager;

/**
 * @brief Adds the specified cookie for the specified URI.
 *
 * @warning This modifies the cookie (e.g. it sets the domain if it is unset)!
 *	    If you do not want this, pass a copy!
 *
 * @param cookie The cookie to add to the manager
 * @param URI The URI for which the cookie should be added
 */
- (void)addCookie: (OFHTTPCookie *)cookie forURI: (OFURI *)URI;

/**
 * @brief Adds the specified cookies for the specified URI.
 *
 * @warning This modifies the cookies (e.g. it sets the domain if it is unset)!
 *	    If you do not want this, pass copies!
 *
 * @param cookies An array of cookies to add to the manager
 * @param URI The URI for which the cookies should be added
 */
- (void)addCookies: (OFArray OF_GENERIC(OFHTTPCookie *) *)cookies
	    forURI: (OFURI *)URI;

/**
 * @brief Returns the cookies for the specified URI.
 *
 * @param URI The URI for which the cookies should be returned
 * @return The cookies for the specified URI
 */
- (OFArray OF_GENERIC(OFHTTPCookie *) *)cookiesForURI: (OFURI *)URI;

/**
 * @brief Purges all expired cookies.
 */
- (void)purgeExpiredCookies;
@end

OF_ASSUME_NONNULL_END







|





|

|


|





|


|


|

|
|

|








42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
 * @brief Create a new cookie manager.
 *
 * @return A new, autoreleased OFHTTPCookieManager
 */
+ (instancetype)manager;

/**
 * @brief Adds the specified cookie for the specified IRI.
 *
 * @warning This modifies the cookie (e.g. it sets the domain if it is unset)!
 *	    If you do not want this, pass a copy!
 *
 * @param cookie The cookie to add to the manager
 * @param IRI The IRI for which the cookie should be added
 */
- (void)addCookie: (OFHTTPCookie *)cookie forIRI: (OFIRI *)IRI;

/**
 * @brief Adds the specified cookies for the specified IRI.
 *
 * @warning This modifies the cookies (e.g. it sets the domain if it is unset)!
 *	    If you do not want this, pass copies!
 *
 * @param cookies An array of cookies to add to the manager
 * @param IRI The IRI for which the cookies should be added
 */
- (void)addCookies: (OFArray OF_GENERIC(OFHTTPCookie *) *)cookies
	    forIRI: (OFIRI *)IRI;

/**
 * @brief Returns the cookies for the specified IRI.
 *
 * @param IRI The IRI for which the cookies should be returned
 * @return The cookies for the specified IRI
 */
- (OFArray OF_GENERIC(OFHTTPCookie *) *)cookiesForIRI: (OFIRI *)IRI;

/**
 * @brief Purges all expired cookies.
 */
- (void)purgeExpiredCookies;
@end

OF_ASSUME_NONNULL_END

Modified src/OFHTTPCookieManager.m from [1dd74fe07e] to [3e1112d548].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#import "OFHTTPCookieManager.h"
#import "OFArray.h"
#import "OFDate.h"
#import "OFHTTPCookie.h"
#import "OFURI.h"

@implementation OFHTTPCookieManager
+ (instancetype)manager
{
	return [[[self alloc] init] autorelease];
}


|



















|







1
2
3
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.
 */

#include "config.h"

#import "OFHTTPCookieManager.h"
#import "OFArray.h"
#import "OFDate.h"
#import "OFHTTPCookie.h"
#import "OFIRI.h"

@implementation OFHTTPCookieManager
+ (instancetype)manager
{
	return [[[self alloc] init] autorelease];
}

49
50
51
52
53
54
55
56
57
58
59
60


61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
}

- (OFArray OF_GENERIC(OFHTTPCookie *) *)cookies
{
	return [[_cookies copy] autorelease];
}

- (void)addCookie: (OFHTTPCookie *)cookie forURI: (OFURI *)URI
{
	void *pool = objc_autoreleasePoolPush();
	OFString *cookieDomain, *URIHost;
	size_t i;



	if (![cookie.path hasPrefix: @"/"])
		cookie.path = @"/";

	if (cookie.secure &&
	    [URI.scheme caseInsensitiveCompare: @"https"] != OFOrderedSame) {
		objc_autoreleasePoolPop(pool);
		return;
	}

	cookieDomain = cookie.domain.lowercaseString;
	cookie.domain = cookieDomain;

	URIHost = URI.host.lowercaseString;
	if (![cookieDomain isEqual: URIHost]) {
		URIHost = [@"." stringByAppendingString: URIHost];

		if (![cookieDomain hasSuffix: URIHost]) {
			objc_autoreleasePoolPop(pool);
			return;
		}
	}

	i = 0;
	for (OFHTTPCookie *iter in _cookies) {







|


|

>
>





|







|
|
|

|







49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
}

- (OFArray OF_GENERIC(OFHTTPCookie *) *)cookies
{
	return [[_cookies copy] autorelease];
}

- (void)addCookie: (OFHTTPCookie *)cookie forIRI: (OFIRI *)IRI
{
	void *pool = objc_autoreleasePoolPush();
	OFString *cookieDomain, *IRIHost;
	size_t i;

	IRI = IRI.IRIByAddingPercentEncodingForUnicodeCharacters;

	if (![cookie.path hasPrefix: @"/"])
		cookie.path = @"/";

	if (cookie.secure &&
	    [IRI.scheme caseInsensitiveCompare: @"https"] != OFOrderedSame) {
		objc_autoreleasePoolPop(pool);
		return;
	}

	cookieDomain = cookie.domain.lowercaseString;
	cookie.domain = cookieDomain;

	IRIHost = IRI.host.lowercaseString;
	if (![cookieDomain isEqual: IRIHost]) {
		IRIHost = [@"." stringByAppendingString: IRIHost];

		if (![cookieDomain hasSuffix: IRIHost]) {
			objc_autoreleasePoolPop(pool);
			return;
		}
	}

	i = 0;
	for (OFHTTPCookie *iter in _cookies) {
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111

112


113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170


171
172
173
174
175
176
177

	[_cookies addObject: cookie];

	objc_autoreleasePoolPop(pool);
}

- (void)addCookies: (OFArray OF_GENERIC(OFHTTPCookie *) *)cookies
	    forURI: (OFURI *)URI
{
	for (OFHTTPCookie *cookie in cookies)
		[self addCookie: cookie forURI: URI];
}

- (OFArray OF_GENERIC(OFHTTPCookie *) *)cookiesForURI: (OFURI *)URI
{
	OFMutableArray *ret = [OFMutableArray array];




	for (OFHTTPCookie *cookie in _cookies) {
		void *pool;
		OFDate *expires;
		OFString *cookieDomain, *URIHost, *cookiePath, *URIPath;
		bool match;

		expires = cookie.expires;
		if (expires != nil && expires.timeIntervalSinceNow <= 0)
			continue;

		if (cookie.secure && [URI.scheme caseInsensitiveCompare:
		    @"https"] != OFOrderedSame)
			continue;

		pool = objc_autoreleasePoolPush();

		cookieDomain = cookie.domain.lowercaseString;
		URIHost = URI.host.lowercaseString;
		if ([cookieDomain hasPrefix: @"."]) {
			if ([URIHost hasSuffix: cookieDomain])
				match = true;
			else {
				cookieDomain =
				    [cookieDomain substringFromIndex: 1];

				match = [cookieDomain isEqual: URIHost];
			}
		} else
			match = [cookieDomain isEqual: URIHost];

		if (!match) {
			objc_autoreleasePoolPop(pool);
			continue;
		}

		cookiePath = cookie.path;
		URIPath = URI.path;
		if (![cookiePath isEqual: @"/"]) {
			if ([cookiePath isEqual: URIPath])
				match = true;
			else {
				if (![cookiePath hasSuffix: @"/"])
					cookiePath = [cookiePath
					    stringByAppendingString: @"/"];

				match = [URIPath hasPrefix: cookiePath];
			}

			if (!match) {
				objc_autoreleasePoolPop(pool);
				continue;
			}
		}

		[ret addObject: cookie];
	}

	[ret makeImmutable];



	return ret;
}

- (void)purgeExpiredCookies
{
	for (size_t i = 0, count = _cookies.count; i < count; i++) {







|


|


|


>

>
>

|

|






|



|


|

|





|


|


|




|

|






|



|








>
>







98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184

	[_cookies addObject: cookie];

	objc_autoreleasePoolPop(pool);
}

- (void)addCookies: (OFArray OF_GENERIC(OFHTTPCookie *) *)cookies
	    forIRI: (OFIRI *)IRI
{
	for (OFHTTPCookie *cookie in cookies)
		[self addCookie: cookie forIRI: IRI];
}

- (OFArray OF_GENERIC(OFHTTPCookie *) *)cookiesForIRI: (OFIRI *)IRI
{
	OFMutableArray *ret = [OFMutableArray array];
	void *pool = objc_autoreleasePoolPush();

	IRI = IRI.IRIByAddingPercentEncodingForUnicodeCharacters;

	for (OFHTTPCookie *cookie in _cookies) {
		void *pool2;
		OFDate *expires;
		OFString *cookieDomain, *IRIHost, *cookiePath, *IRIPath;
		bool match;

		expires = cookie.expires;
		if (expires != nil && expires.timeIntervalSinceNow <= 0)
			continue;

		if (cookie.secure && [IRI.scheme caseInsensitiveCompare:
		    @"https"] != OFOrderedSame)
			continue;

		pool2 = objc_autoreleasePoolPush();

		cookieDomain = cookie.domain.lowercaseString;
		IRIHost = IRI.host.lowercaseString;
		if ([cookieDomain hasPrefix: @"."]) {
			if ([IRIHost hasSuffix: cookieDomain])
				match = true;
			else {
				cookieDomain =
				    [cookieDomain substringFromIndex: 1];

				match = [cookieDomain isEqual: IRIHost];
			}
		} else
			match = [cookieDomain isEqual: IRIHost];

		if (!match) {
			objc_autoreleasePoolPop(pool2);
			continue;
		}

		cookiePath = cookie.path;
		IRIPath = IRI.path;
		if (![cookiePath isEqual: @"/"]) {
			if ([cookiePath isEqual: IRIPath])
				match = true;
			else {
				if (![cookiePath hasSuffix: @"/"])
					cookiePath = [cookiePath
					    stringByAppendingString: @"/"];

				match = [IRIPath hasPrefix: cookiePath];
			}

			if (!match) {
				objc_autoreleasePoolPop(pool2);
				continue;
			}
		}

		[ret addObject: cookie];
	}

	[ret makeImmutable];

	objc_autoreleasePoolPop(pool);

	return ret;
}

- (void)purgeExpiredCookies
{
	for (size_t i = 0, count = _cookies.count; i < count; i++) {

Renamed and modified src/OFHTTPURIHandler.h [1fbd933246] to src/OFHTTPIRIHandler.h [8964894884].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#import "OFURIHandler.h"

OF_ASSUME_NONNULL_BEGIN

@interface OFHTTPURIHandler: OFURIHandler
@end

OF_ASSUME_NONNULL_END

|













|



|



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 "OFIRIHandler.h"

OF_ASSUME_NONNULL_BEGIN

@interface OFHTTPIRIHandler: OFIRIHandler
@end

OF_ASSUME_NONNULL_END

Renamed and modified src/OFHTTPURIHandler.m [9e6fa9d3fe] to src/OFHTTPIRIHandler.m [1cda4f35c9].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#import "OFHTTPURIHandler.h"
#import "OFHTTPClient.h"
#import "OFHTTPRequest.h"
#import "OFHTTPResponse.h"

@implementation OFHTTPURIHandler
- (OFStream *)openItemAtURI: (OFURI *)URI mode: (OFString *)mode
{
	void *pool = objc_autoreleasePoolPush();
	OFHTTPClient *client = [OFHTTPClient client];
	OFHTTPRequest *request = [OFHTTPRequest requestWithURI: URI];
	OFHTTPResponse *response = [client performRequest: request];

	[response retain];

	objc_autoreleasePoolPop(pool);

	return [response autorelease];
}
@end

|















|




|
|



|









1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
/*
 * Copyright (c) 2008-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 "OFHTTPIRIHandler.h"
#import "OFHTTPClient.h"
#import "OFHTTPRequest.h"
#import "OFHTTPResponse.h"

@implementation OFHTTPIRIHandler
- (OFStream *)openItemAtIRI: (OFIRI *)IRI mode: (OFString *)mode
{
	void *pool = objc_autoreleasePoolPush();
	OFHTTPClient *client = [OFHTTPClient client];
	OFHTTPRequest *request = [OFHTTPRequest requestWithIRI: IRI];
	OFHTTPResponse *response = [client performRequest: request];

	[response retain];

	objc_autoreleasePoolPop(pool);

	return [response autorelease];
}
@end

Modified src/OFHTTPRequest.h from [1278addd47] to [2743b8de7d].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#import "OFObject.h"
#import "OFSocket.h"
#import "OFString.h"

OF_ASSUME_NONNULL_BEGIN

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

/** @file */

/**
 * @brief The type of an HTTP request.
 */

|



















|

|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/*
 * Copyright (c) 2008-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 "OFObject.h"
#import "OFSocket.h"
#import "OFString.h"

OF_ASSUME_NONNULL_BEGIN

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

/** @file */

/**
 * @brief The type of an HTTP request.
 */
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
} OFHTTPRequestMethod;

/**
 * @struct OFHTTPRequestProtocolVersion OFHTTPRequest.h ObjFW/OFHTTPRequest.h
 *
 * @brief The HTTP version of the HTTP request.
 */
typedef struct OF_BOXABLE {
	/** The major of the HTTP version */
	unsigned char major;
	/** The minor of the HTTP version */
	unsigned char minor;
} OFHTTPRequestProtocolVersion;

/**
 * @class OFHTTPRequest OFHTTPRequest.h ObjFW/OFHTTPRequest.h
 *
 * @brief A class for storing HTTP requests.
 */
OF_SUBCLASSING_RESTRICTED
@interface OFHTTPRequest: OFObject <OFCopying>
{
	OFURI *_URI;
	OFHTTPRequestMethod _method;
	OFHTTPRequestProtocolVersion _protocolVersion;
	OFDictionary OF_GENERIC(OFString *, OFString *) *_Nullable _headers;
	OFSocketAddress _remoteAddress;
	bool _hasRemoteAddress;
}

/**
 * @brief The URI of the HTTP request.
 */
@property (copy, nonatomic) OFURI *URI;

/**
 * @brief The protocol version of the HTTP request.
 *
 * @throw OFUnsupportedVersionException The specified version cannot be set
 *					because it is not supported
 */







|














|








|

|







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
} OFHTTPRequestMethod;

/**
 * @struct OFHTTPRequestProtocolVersion OFHTTPRequest.h ObjFW/OFHTTPRequest.h
 *
 * @brief The HTTP version of the HTTP request.
 */
typedef struct OF_BOXABLE OFHTTPRequestProtocolVersion {
	/** The major of the HTTP version */
	unsigned char major;
	/** The minor of the HTTP version */
	unsigned char minor;
} OFHTTPRequestProtocolVersion;

/**
 * @class OFHTTPRequest OFHTTPRequest.h ObjFW/OFHTTPRequest.h
 *
 * @brief A class for storing HTTP requests.
 */
OF_SUBCLASSING_RESTRICTED
@interface OFHTTPRequest: OFObject <OFCopying>
{
	OFIRI *_IRI;
	OFHTTPRequestMethod _method;
	OFHTTPRequestProtocolVersion _protocolVersion;
	OFDictionary OF_GENERIC(OFString *, OFString *) *_Nullable _headers;
	OFSocketAddress _remoteAddress;
	bool _hasRemoteAddress;
}

/**
 * @brief The IRI of the HTTP request.
 */
@property (copy, nonatomic) OFIRI *IRI;

/**
 * @brief The protocol version of the HTTP request.
 *
 * @throw OFUnsupportedVersionException The specified version cannot be set
 *					because it is not supported
 */
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158























159

160
161
162
163
164
 * @brief The remote address from which the request originates.
 *
 * @note The setter creates a copy of the remote address.
 */
@property OF_NULLABLE_PROPERTY (nonatomic) const OFSocketAddress *remoteAddress;

/**
 * @brief Creates a new OFHTTPRequest with the specified URI.
 *
 * @param URI The URI for the request
 * @return A new, autoreleased OFHTTPRequest
 */
+ (instancetype)requestWithURI: (OFURI *)URI;

/**
 * @brief Initializes an already allocated OFHTTPRequest with the specified URI.
 *
 * @param URI The URI for the request
 * @return An initialized OFHTTPRequest
 */
- (instancetype)initWithURI: (OFURI *)URI;

- (instancetype)init OF_UNAVAILABLE;
@end

#ifdef __cplusplus
extern "C" {
#endif
/**
 * @brief Returns a C string describing the specified request method.
 *
 * @param method The request method which should be described as a C string
 * @return A C string describing the specified request method
 */
extern const char *_Nullable OFHTTPRequestMethodName(
    OFHTTPRequestMethod method);

/**
 * @brief Returns the request method for the specified string.
 *
 * @param string The string for which the request method should be returned
 * @return The request method for the specified string
 * @throw OFInvalidFormatException The specified string is not a valid HTTP
 *				   request method
 */























extern OFHTTPRequestMethod OFHTTPRequestMethodParseName(OFString *string);

#ifdef __cplusplus
}
#endif

OF_ASSUME_NONNULL_END







|

|


|


|

|


|








|

|
|

|










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





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
 * @brief The remote address from which the request originates.
 *
 * @note The setter creates a copy of the remote address.
 */
@property OF_NULLABLE_PROPERTY (nonatomic) const OFSocketAddress *remoteAddress;

/**
 * @brief Creates a new OFHTTPRequest with the specified IRI.
 *
 * @param IRI The IRI for the request
 * @return A new, autoreleased OFHTTPRequest
 */
+ (instancetype)requestWithIRI: (OFIRI *)IRI;

/**
 * @brief Initializes an already allocated OFHTTPRequest with the specified IRI.
 *
 * @param IRI The IRI for the request
 * @return An initialized OFHTTPRequest
 */
- (instancetype)initWithIRI: (OFIRI *)IRI;

- (instancetype)init OF_UNAVAILABLE;
@end

#ifdef __cplusplus
extern "C" {
#endif
/**
 * @brief Returns a string describing the specified request method.
 *
 * @param method The request method which should be described as a string
 * @return A string describing the specified request method
 */
extern OFString *_Nullable OFHTTPRequestMethodString(
    OFHTTPRequestMethod method);

/**
 * @brief Returns the request method for the specified string.
 *
 * @param string The string for which the request method should be returned
 * @return The request method for the specified string
 * @throw OFInvalidFormatException The specified string is not a valid HTTP
 *				   request method
 */
extern OFHTTPRequestMethod OFHTTPRequestMethodParseString(OFString *string);

/**
 * @brief Returns a C string describing the specified request method.
 *
 * @deprecated Use @ref OFHTTPRequestMethodString instead.
 *
 * @param method The request method which should be described as a C string
 * @return A C string describing the specified request method
 */
extern const char *_Nullable OFHTTPRequestMethodName(OFHTTPRequestMethod method)
    OF_DEPRECATED(ObjFW, 1, 1, "Use OFHTTPRequestMethodString instead");

/**
 * @brief Returns the request method for the specified string.
 *
 * @deprecated Use @ref OFHTTPRequestMethodParseString instead.
 *
 * @param string The string for which the request method should be returned
 * @return The request method for the specified string
 * @throw OFInvalidFormatException The specified string is not a valid HTTP
 *				   request method
 */
extern OFHTTPRequestMethod OFHTTPRequestMethodParseName(OFString *string)
    OF_DEPRECATED(ObjFW, 1, 1, "Use OFHTTPRequestMethodParseString instead");
#ifdef __cplusplus
}
#endif

OF_ASSUME_NONNULL_END

Modified src/OFHTTPRequest.m from [c85955ea02] to [3110dfe070].

1
2
3
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
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#include <string.h>

#import "OFHTTPRequest.h"
#import "OFString.h"
#import "OFURI.h"
#import "OFDictionary.h"
#import "OFData.h"
#import "OFArray.h"

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

const char *
OFHTTPRequestMethodName(OFHTTPRequestMethod method)
{
	switch (method) {
	case OFHTTPRequestMethodOptions:
		return "OPTIONS";
	case OFHTTPRequestMethodGet:
		return "GET";
	case OFHTTPRequestMethodHead:
		return "HEAD";
	case OFHTTPRequestMethodPost:
		return "POST";
	case OFHTTPRequestMethodPut:
		return "PUT";
	case OFHTTPRequestMethodDelete:
		return "DELETE";
	case OFHTTPRequestMethodTrace:
		return "TRACE";
	case OFHTTPRequestMethodConnect:
		return "CONNECT";
	}

	return NULL;
}

OFHTTPRequestMethod
OFHTTPRequestMethodParseName(OFString *string)
{
	if ([string isEqual: @"OPTIONS"])
		return OFHTTPRequestMethodOptions;
	if ([string isEqual: @"GET"])
		return OFHTTPRequestMethodGet;
	if ([string isEqual: @"HEAD"])
		return OFHTTPRequestMethodHead;
	if ([string isEqual: @"POST"])
		return OFHTTPRequestMethodPost;
	if ([string isEqual: @"PUT"])
		return OFHTTPRequestMethodPut;
	if ([string isEqual: @"DELETE"])
		return OFHTTPRequestMethodDelete;
	if ([string isEqual: @"TRACE"])
		return OFHTTPRequestMethodTrace;
	if ([string isEqual: @"CONNECT"])
		return OFHTTPRequestMethodConnect;

	@throw [OFInvalidFormatException exception];
}















@implementation OFHTTPRequest
@synthesize URI = _URI, method = _method, headers = _headers;

+ (instancetype)requestWithURI: (OFURI *)URI
{
	return [[[self alloc] initWithURI: URI] autorelease];
}

- (instancetype)initWithURI: (OFURI *)URI
{
	self = [super init];

	@try {
		_URI = [URI copy];
		_method = OFHTTPRequestMethodGet;
		_protocolVersion.major = 1;
		_protocolVersion.minor = 1;
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (instancetype)init
{
	OF_INVALID_INIT_METHOD
}

- (void)dealloc
{
	[_URI release];
	[_headers release];

	[super dealloc];
}

- (void)setRemoteAddress: (const OFSocketAddress *)remoteAddress
{

|


















|
|

|
|






|
|



|

|

|

|

|

|

|

|


|



|





















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

|

|

|


|




|


















|







1
2
3
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
/*
 * 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 "OFHTTPRequest.h"
#import "OFArray.h"
#import "OFData.h"
#import "OFDictionary.h"
#import "OFIRI.h"
#import "OFString.h"

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

OFString *
OFHTTPRequestMethodString(OFHTTPRequestMethod method)
{
	switch (method) {
	case OFHTTPRequestMethodOptions:
		return @"OPTIONS";
	case OFHTTPRequestMethodGet:
		return @"GET";
	case OFHTTPRequestMethodHead:
		return @"HEAD";
	case OFHTTPRequestMethodPost:
		return @"POST";
	case OFHTTPRequestMethodPut:
		return @"PUT";
	case OFHTTPRequestMethodDelete:
		return @"DELETE";
	case OFHTTPRequestMethodTrace:
		return @"TRACE";
	case OFHTTPRequestMethodConnect:
		return @"CONNECT";
	}

	return nil;
}

OFHTTPRequestMethod
OFHTTPRequestMethodParseString(OFString *string)
{
	if ([string isEqual: @"OPTIONS"])
		return OFHTTPRequestMethodOptions;
	if ([string isEqual: @"GET"])
		return OFHTTPRequestMethodGet;
	if ([string isEqual: @"HEAD"])
		return OFHTTPRequestMethodHead;
	if ([string isEqual: @"POST"])
		return OFHTTPRequestMethodPost;
	if ([string isEqual: @"PUT"])
		return OFHTTPRequestMethodPut;
	if ([string isEqual: @"DELETE"])
		return OFHTTPRequestMethodDelete;
	if ([string isEqual: @"TRACE"])
		return OFHTTPRequestMethodTrace;
	if ([string isEqual: @"CONNECT"])
		return OFHTTPRequestMethodConnect;

	@throw [OFInvalidFormatException exception];
}

/* Deprecated */
const char *
OFHTTPRequestMethodName(OFHTTPRequestMethod method)
{
	return OFHTTPRequestMethodString(method).UTF8String;
}

/* Deprecated */
OFHTTPRequestMethod
OFHTTPRequestMethodParseName(OFString *string)
{
	return OFHTTPRequestMethodParseString(string);
}

@implementation OFHTTPRequest
@synthesize IRI = _IRI, method = _method, headers = _headers;

+ (instancetype)requestWithIRI: (OFIRI *)IRI
{
	return [[[self alloc] initWithIRI: IRI] autorelease];
}

- (instancetype)initWithIRI: (OFIRI *)IRI
{
	self = [super init];

	@try {
		_IRI = [IRI copy];
		_method = OFHTTPRequestMethodGet;
		_protocolVersion.major = 1;
		_protocolVersion.minor = 1;
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (instancetype)init
{
	OF_INVALID_INIT_METHOD
}

- (void)dealloc
{
	[_IRI release];
	[_headers release];

	[super dealloc];
}

- (void)setRemoteAddress: (const OFSocketAddress *)remoteAddress
{
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
		return &_remoteAddress;

	return NULL;
}

- (id)copy
{
	OFHTTPRequest *copy = [[OFHTTPRequest alloc] initWithURI: _URI];

	@try {
		copy->_method = _method;
		copy->_protocolVersion = _protocolVersion;
		copy.headers = _headers;
		copy.remoteAddress = self.remoteAddress;
	} @catch (id e) {







|







143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
		return &_remoteAddress;

	return NULL;
}

- (id)copy
{
	OFHTTPRequest *copy = [[OFHTTPRequest alloc] initWithIRI: _IRI];

	@try {
		copy->_method = _method;
		copy->_protocolVersion = _protocolVersion;
		copy.headers = _headers;
		copy.remoteAddress = self.remoteAddress;
	} @catch (id e) {
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
		return false;

	request = object;

	if (request->_method != _method ||
	    request->_protocolVersion.major != _protocolVersion.major ||
	    request->_protocolVersion.minor != _protocolVersion.minor ||
	    ![request->_URI isEqual: _URI] ||
	    ![request->_headers isEqual: _headers])
		return false;

	if (request.remoteAddress != self.remoteAddress &&
	    !OFSocketAddressEqual(request.remoteAddress, self.remoteAddress))
		return false;

	return true;
}

- (unsigned long)hash
{
	unsigned long hash;

	OFHashInit(&hash);

	OFHashAddByte(&hash, _method);
	OFHashAddByte(&hash, _protocolVersion.major);
	OFHashAddByte(&hash, _protocolVersion.minor);
	OFHashAddHash(&hash, _URI.hash);
	OFHashAddHash(&hash, _headers.hash);
	if (_hasRemoteAddress)
		OFHashAddHash(&hash, OFSocketAddressHash(&_remoteAddress));

	OFHashFinalize(&hash);

	return hash;







|



















|







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
		return false;

	request = object;

	if (request->_method != _method ||
	    request->_protocolVersion.major != _protocolVersion.major ||
	    request->_protocolVersion.minor != _protocolVersion.minor ||
	    ![request->_IRI isEqual: _IRI] ||
	    ![request->_headers isEqual: _headers])
		return false;

	if (request.remoteAddress != self.remoteAddress &&
	    !OFSocketAddressEqual(request.remoteAddress, self.remoteAddress))
		return false;

	return true;
}

- (unsigned long)hash
{
	unsigned long hash;

	OFHashInit(&hash);

	OFHashAddByte(&hash, _method);
	OFHashAddByte(&hash, _protocolVersion.major);
	OFHashAddByte(&hash, _protocolVersion.minor);
	OFHashAddHash(&hash, _IRI.hash);
	OFHashAddHash(&hash, _headers.hash);
	if (_hasRemoteAddress)
		OFHashAddHash(&hash, OFSocketAddressHash(&_remoteAddress));

	OFHashFinalize(&hash);

	return hash;
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
					   _protocolVersion.major,
					   _protocolVersion.minor];
}

- (OFString *)description
{
	void *pool = objc_autoreleasePoolPush();
	const char *method = OFHTTPRequestMethodName(_method);
	OFString *indentedHeaders, *remoteAddress, *ret;

	indentedHeaders = [_headers.description
	    stringByReplacingOccurrencesOfString: @"\n"
				      withString: @"\n\t"];

	if (_hasRemoteAddress)
		remoteAddress = OFSocketAddressString(&_remoteAddress);
	else
		remoteAddress = nil;

	ret = [[OFString alloc] initWithFormat:
	    @"<%@:\n\tURI = %@\n"
	    @"\tMethod = %s\n"
	    @"\tHeaders = %@\n"
	    @"\tRemote address = %@\n"
	    @">",
	    self.class, _URI, method, indentedHeaders, remoteAddress];

	objc_autoreleasePoolPop(pool);

	return [ret autorelease];
}
@end







|












|
|



|






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
					   _protocolVersion.major,
					   _protocolVersion.minor];
}

- (OFString *)description
{
	void *pool = objc_autoreleasePoolPush();
	OFString *method = OFHTTPRequestMethodString(_method);
	OFString *indentedHeaders, *remoteAddress, *ret;

	indentedHeaders = [_headers.description
	    stringByReplacingOccurrencesOfString: @"\n"
				      withString: @"\n\t"];

	if (_hasRemoteAddress)
		remoteAddress = OFSocketAddressString(&_remoteAddress);
	else
		remoteAddress = nil;

	ret = [[OFString alloc] initWithFormat:
	    @"<%@:\n\tIRI = %@\n"
	    @"\tMethod = %@\n"
	    @"\tHeaders = %@\n"
	    @"\tRemote address = %@\n"
	    @">",
	    self.class, _IRI, method, indentedHeaders, remoteAddress];

	objc_autoreleasePoolPop(pool);

	return [ret autorelease];
}
@end

Modified src/OFHTTPResponse.h from [3c482db81b] to [d5e8497e61].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFHTTPResponse.m from [17a72a5d36] to [3a885482aa].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
210
211
212
213
214
215
216


217
218
219
220

221
222
223
224
225
226
227
						length: length - last];
		value = value.stringByDeletingTrailingWhitespaces;

		if ([name isEqual: @"charset"])
			charset = value;
	}



	@try {
		ret = OFStringEncodingParseName(charset);
	} @catch (OFInvalidArgumentException *e) {
		ret = OFStringEncodingAutodetect;

	}

	return ret;
}

@implementation OFHTTPResponse
@synthesize statusCode = _statusCode, headers = _headers;







>
>
|
|
|
<
>







210
211
212
213
214
215
216
217
218
219
220
221

222
223
224
225
226
227
228
229
						length: length - last];
		value = value.stringByDeletingTrailingWhitespaces;

		if ([name isEqual: @"charset"])
			charset = value;
	}

	ret = OFStringEncodingAutodetect;
	if (charset != nil) {
		@try {
			ret = OFStringEncodingParseName(charset);
		} @catch (OFInvalidArgumentException *e) {

		}
	}

	return ret;
}

@implementation OFHTTPResponse
@synthesize statusCode = _statusCode, headers = _headers;

Modified src/OFHTTPServer.h from [ba5fc5aae1] to [4313a7362c].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
	OFArray *_threadPool;
#endif
}

/**
 * @brief The host on which the HTTP server will listen.
 *
 * @throw OFAlreadyConnectedException The host could not be set because
 *				      @ref start had already been called
 */
@property OF_NULLABLE_PROPERTY (copy, nonatomic) OFString *host;

/**
 * @brief The port on which the HTTP server will listen.
 *
 * @throw OFAlreadyConnectedException The port could not be set because
 *				      @ref start had already been called
 */
@property (nonatomic) uint16_t port;

/**
 * @brief The delegate for the HTTP server.
 */
@property OF_NULLABLE_PROPERTY (assign, nonatomic)
    id <OFHTTPServerDelegate> delegate;

#ifdef OF_HAVE_THREADS
/**
 * @brief The number of threads the OFHTTPServer should use.
 *
 * If this is larger than 1 (the default), one thread will be used to accept
 * incoming connections and all others will be used to handle connections.
 *
 * For maximum CPU utilization, set this to `[OFSystemInfo numberOfCPUs] + 1`.
 *
 * @throw OFAlreadyConnectedException The number of threads could not be set
 *				      because @ref start had already been called
 */
@property (nonatomic) size_t numberOfThreads;
#endif

/**
 * @brief The server name the server presents to clients.
 *







|
|






|
|


















|
|







102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
	OFArray *_threadPool;
#endif
}

/**
 * @brief The host on which the HTTP server will listen.
 *
 * @throw OFAlreadyOpenException The host could not be set because @ref start
 *				  had already been called
 */
@property OF_NULLABLE_PROPERTY (copy, nonatomic) OFString *host;

/**
 * @brief The port on which the HTTP server will listen.
 *
 * @throw OFAlreadyOpenException The port could not be set because @ref start
 *				 had already been called
 */
@property (nonatomic) uint16_t port;

/**
 * @brief The delegate for the HTTP server.
 */
@property OF_NULLABLE_PROPERTY (assign, nonatomic)
    id <OFHTTPServerDelegate> delegate;

#ifdef OF_HAVE_THREADS
/**
 * @brief The number of threads the OFHTTPServer should use.
 *
 * If this is larger than 1 (the default), one thread will be used to accept
 * incoming connections and all others will be used to handle connections.
 *
 * For maximum CPU utilization, set this to `[OFSystemInfo numberOfCPUs] + 1`.
 *
 * @throw OFAlreadyOpenException The number of threads could not be set because
 *				 @ref start had already been called
 */
@property (nonatomic) size_t numberOfThreads;
#endif

/**
 * @brief The server name the server presents to clients.
 *
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
 * @return A new HTTP server
 */
+ (instancetype)server;

/**
 * @brief Starts the HTTP server in the current thread's run loop.
 *
 * @throw OFAlreadyConnectedException The server had already been started
 */
- (void)start;

/**
 * @brief Stops the HTTP server, meaning it will not accept any new incoming
 *	  connections, but still handle existing connections until they are
 *	  finished or timed out.
 */
- (void)stop;
@end

OF_ASSUME_NONNULL_END







|












154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
 * @return A new HTTP server
 */
+ (instancetype)server;

/**
 * @brief Starts the HTTP server in the current thread's run loop.
 *
 * @throw OFAlreadyOpenException The server had already been started
 */
- (void)start;

/**
 * @brief Stops the HTTP server, meaning it will not accept any new incoming
 *	  connections, but still handle existing connections until they are
 *	  finished or timed out.
 */
- (void)stop;
@end

OF_ASSUME_NONNULL_END

Modified src/OFHTTPServer.m from [e75cf57b42] to [871d0707f6].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
24
25
26
27
28
29
30

31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#import "OFHTTPServer.h"
#import "OFArray.h"
#import "OFData.h"
#import "OFDate.h"
#import "OFDictionary.h"
#import "OFHTTPRequest.h"
#import "OFHTTPResponse.h"

#import "OFNumber.h"
#import "OFSocket+Private.h"
#import "OFTCPSocket.h"
#import "OFThread.h"
#import "OFTimer.h"
#import "OFURI.h"

#import "OFAlreadyConnectedException.h"
#import "OFInvalidArgumentException.h"
#import "OFInvalidEncodingException.h"
#import "OFInvalidFormatException.h"
#import "OFNotOpenException.h"
#import "OFOutOfMemoryException.h"
#import "OFOutOfRangeException.h"
#import "OFTruncatedDataException.h"







>





<

|







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

37
38
39
40
41
42
43
44
45
#import "OFHTTPServer.h"
#import "OFArray.h"
#import "OFData.h"
#import "OFDate.h"
#import "OFDictionary.h"
#import "OFHTTPRequest.h"
#import "OFHTTPResponse.h"
#import "OFIRI.h"
#import "OFNumber.h"
#import "OFSocket+Private.h"
#import "OFTCPSocket.h"
#import "OFThread.h"
#import "OFTimer.h"


#import "OFAlreadyOpenException.h"
#import "OFInvalidArgumentException.h"
#import "OFInvalidEncodingException.h"
#import "OFInvalidFormatException.h"
#import "OFNotOpenException.h"
#import "OFOutOfMemoryException.h"
#import "OFOutOfRangeException.h"
#import "OFTruncatedDataException.h"
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392

	pos = [line rangeOfString: @" "].location;
	if (pos == OFNotFound)
		return [self sendErrorAndClose: 400];

	method = [line substringToIndex: pos];
	@try {
		_method = OFHTTPRequestMethodParseName(method);
	} @catch (OFInvalidArgumentException *e) {
		return [self sendErrorAndClose: 405];
	}

	@try {
		OFRange range = OFMakeRange(pos + 1, line.length - pos - 10);








|







378
379
380
381
382
383
384
385
386
387
388
389
390
391
392

	pos = [line rangeOfString: @" "].location;
	if (pos == OFNotFound)
		return [self sendErrorAndClose: 400];

	method = [line substringToIndex: pos];
	@try {
		_method = OFHTTPRequestMethodParseString(method);
	} @catch (OFInvalidArgumentException *e) {
		return [self sendErrorAndClose: 405];
	}

	@try {
		OFRange range = OFMakeRange(pos + 1, line.length - pos - 10);

510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
			      date, _server.name];
	return false;
}

- (void)createResponse
{
	void *pool = objc_autoreleasePoolPush();
	OFMutableURI *URI;
	OFHTTPRequest *request;
	OFHTTPServerResponse *response;
	size_t pos;

	[_timer invalidate];
	[_timer release];
	_timer = nil;

	if (_host == nil || _port == 0) {
		if (_HTTPMinorVersion > 0) {
			[self sendErrorAndClose: 400];
			return;
		}

		[_host release];
		_host = [_server.host copy];
		_port = [_server port];
	}

	URI = [OFMutableURI URIWithScheme: @"http"];
	URI.host = _host;
	if (_port != 80)
		URI.port = [OFNumber numberWithUnsignedShort: _port];

	@try {
		if ((pos = [_path rangeOfString: @"?"].location) !=
		    OFNotFound) {
			OFString *path, *query;

			path = [_path substringToIndex: pos];
			query = [_path substringFromIndex: pos + 1];

			URI.percentEncodedPath = path;
			URI.percentEncodedQuery = query;
		} else
			URI.percentEncodedPath = _path;
	} @catch (OFInvalidFormatException *e) {
		objc_autoreleasePoolPop(pool);
		[self sendErrorAndClose: 400];
		return;
	}

	[URI makeImmutable];

	request = [OFHTTPRequest requestWithURI: URI];
	request.method = _method;
	request.protocolVersion =
	    (OFHTTPRequestProtocolVersion){ 1, _HTTPMinorVersion };
	request.headers = _headers;
	request.remoteAddress = _socket.remoteAddress;

	response = [[[OFHTTPServerResponse alloc]







|



















|
|

|









|
|

|






|

|







510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
			      date, _server.name];
	return false;
}

- (void)createResponse
{
	void *pool = objc_autoreleasePoolPush();
	OFMutableIRI *IRI;
	OFHTTPRequest *request;
	OFHTTPServerResponse *response;
	size_t pos;

	[_timer invalidate];
	[_timer release];
	_timer = nil;

	if (_host == nil || _port == 0) {
		if (_HTTPMinorVersion > 0) {
			[self sendErrorAndClose: 400];
			return;
		}

		[_host release];
		_host = [_server.host copy];
		_port = [_server port];
	}

	IRI = [OFMutableIRI IRIWithScheme: @"http"];
	IRI.host = _host;
	if (_port != 80)
		IRI.port = [OFNumber numberWithUnsignedShort: _port];

	@try {
		if ((pos = [_path rangeOfString: @"?"].location) !=
		    OFNotFound) {
			OFString *path, *query;

			path = [_path substringToIndex: pos];
			query = [_path substringFromIndex: pos + 1];

			IRI.percentEncodedPath = path;
			IRI.percentEncodedQuery = query;
		} else
			IRI.percentEncodedPath = _path;
	} @catch (OFInvalidFormatException *e) {
		objc_autoreleasePoolPop(pool);
		[self sendErrorAndClose: 400];
		return;
	}

	[IRI makeImmutable];

	request = [OFHTTPRequest requestWithIRI: IRI];
	request.method = _method;
	request.protocolVersion =
	    (OFHTTPRequestProtocolVersion){ 1, _HTTPMinorVersion };
	request.headers = _headers;
	request.remoteAddress = _socket.remoteAddress;

	response = [[[OFHTTPServerResponse alloc]
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747

		objc_autoreleasePoolPop(pool);

		return 0;
	}
}

- (bool)hasDataInReadBuffer
{
	return (super.hasDataInReadBuffer || _socket.hasDataInReadBuffer);
}

- (int)fileDescriptorForReading
{
	return _socket.fileDescriptorForReading;
}








|

|







731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747

		objc_autoreleasePoolPop(pool);

		return 0;
	}
}

- (bool)lowlevelHasDataInReadBuffer
{
	return _socket.hasDataInReadBuffer;
}

- (int)fileDescriptorForReading
{
	return _socket.fileDescriptorForReading;
}

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
}

- (void)setHost: (OFString *)host
{
	OFString *old;

	if (_listeningSocket != nil)
		@throw [OFAlreadyConnectedException exception];

	old = _host;
	_host = [host copy];
	[old release];
}

- (OFString *)host
{
	return _host;
}

- (void)setPort: (uint16_t)port
{
	if (_listeningSocket != nil)
		@throw [OFAlreadyConnectedException exception];

	_port = port;
}

- (uint16_t)port
{
	return _port;
}

#ifdef OF_HAVE_THREADS
- (void)setNumberOfThreads: (size_t)numberOfThreads
{
	if (numberOfThreads == 0)
		@throw [OFInvalidArgumentException exception];

	if (_listeningSocket != nil)
		@throw [OFAlreadyConnectedException exception];

	_numberOfThreads = numberOfThreads;
}

- (size_t)numberOfThreads
{
	return _numberOfThreads;
}
#endif

- (void)start
{
	void *pool = objc_autoreleasePoolPush();


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

	if (_listeningSocket != nil)
		@throw [OFAlreadyConnectedException exception];

	_listeningSocket = [[OFTCPSocket alloc] init];
	_port = [_listeningSocket bindToHost: _host port: _port];

	[_listeningSocket listen];

#ifdef OF_HAVE_THREADS
	if (_numberOfThreads > 1) {
		OFMutableArray *threads =
		    [OFMutableArray arrayWithCapacity: _numberOfThreads - 1];








|














|
















|













>





|


|
>







800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
}

- (void)setHost: (OFString *)host
{
	OFString *old;

	if (_listeningSocket != nil)
		@throw [OFAlreadyOpenException exceptionWithObject: self];

	old = _host;
	_host = [host copy];
	[old release];
}

- (OFString *)host
{
	return _host;
}

- (void)setPort: (uint16_t)port
{
	if (_listeningSocket != nil)
		@throw [OFAlreadyOpenException exceptionWithObject: self];

	_port = port;
}

- (uint16_t)port
{
	return _port;
}

#ifdef OF_HAVE_THREADS
- (void)setNumberOfThreads: (size_t)numberOfThreads
{
	if (numberOfThreads == 0)
		@throw [OFInvalidArgumentException exception];

	if (_listeningSocket != nil)
		@throw [OFAlreadyOpenException exceptionWithObject: self];

	_numberOfThreads = numberOfThreads;
}

- (size_t)numberOfThreads
{
	return _numberOfThreads;
}
#endif

- (void)start
{
	void *pool = objc_autoreleasePoolPush();
	OFSocketAddress address;

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

	if (_listeningSocket != nil)
		@throw [OFAlreadyOpenException exceptionWithObject: self];

	_listeningSocket = [[OFTCPSocket alloc] init];
	address = [_listeningSocket bindToHost: _host port: _port];
	_port = OFSocketAddressIPPort(&address);
	[_listeningSocket listen];

#ifdef OF_HAVE_THREADS
	if (_numberOfThreads > 1) {
		OFMutableArray *threads =
		    [OFMutableArray arrayWithCapacity: _numberOfThreads - 1];

Modified src/OFHostAddressResolver.h from [5c6783fd03] to [7dde2d23ba].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFHostAddressResolver.m from [3275d58c93] to [a01496cb7f].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
149
150
151
152
153
154
155
156



157
158
159
160
161
162
163
164
}

- (void)sendQueries
{
	OFString *domainName;

	if (!_isFQDN) {
		OFString *searchDomain = [_settings->_searchDomains



		    objectAtIndex: _searchDomainIndex];

		domainName = [OFString stringWithFormat: @"%@.%@",
							 _host, searchDomain];
	} else
		domainName = _host;

#ifdef OF_HAVE_IPV6







|
>
>
>
|







149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
}

- (void)sendQueries
{
	OFString *domainName;

	if (!_isFQDN) {
		OFString *searchDomain = @"";

		if (_searchDomainIndex < _settings->_searchDomains.count)
			searchDomain = [_settings->_searchDomains
			    objectAtIndex: _searchDomainIndex];

		domainName = [OFString stringWithFormat: @"%@.%@",
							 _host, searchDomain];
	} else
		domainName = _host;

#ifdef OF_HAVE_IPV6
284
285
286
287
288
289
290
291

292
293
294
295
296
297
298
		    addresses, exception);

		objc_autoreleasePoolPop(pool);
		return;
	} @catch (OFInvalidFormatException *e) {
	}

	if ((aliases = [_settings->_staticHosts objectForKey: _host]) != nil) {

		OFMutableData *addresses = [OFMutableData
		    dataWithItemSize: sizeof(OFSocketAddress)];
		id exception = nil;

		for (OFString *alias in aliases) {
			OFSocketAddress address;








|
>







287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
		    addresses, exception);

		objc_autoreleasePoolPop(pool);
		return;
	} @catch (OFInvalidFormatException *e) {
	}

	if ((aliases = [_settings->_staticHosts objectForKey:
	    _host.lowercaseString]) != nil) {
		OFMutableData *addresses = [OFMutableData
		    dataWithItemSize: sizeof(OFSocketAddress)];
		id exception = nil;

		for (OFString *alias in aliases) {
			OFSocketAddress address;

Modified src/OFHuffmanTree.h from [0152a399af] to [94605a6084].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFHuffmanTree.m from [13f0a946b0] to [aace55cc82].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFINICategory+Private.h from [6b757dc025] to [08ccd04496].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFINICategory.h from [8e0c968abf] to [47ccd5fcd2].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
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

- (instancetype)init OF_UNAVAILABLE;

/**
 * @brief Returns the string for the specified key, or `nil` if it does not
 *	  exist.
 *
 * If the specified key is a multi-key (see @ref stringArrayForKey:), the value
 * of the first key/value pair found is returned.
 *
 * @param key The key for which the string should be returned
 * @return The string for the specified key, or `nil` if it does not exist
 */
- (nullable OFString *)stringForKey: (OFString *)key;

/**
 * @brief Returns the string for the specified key or the specified default
 *	  value if it does not exist.
 *
 * If the specified key is a multi-key (see @ref stringArrayForKey:), the value
 * of the first key/value pair found is returned.
 *
 * @param key The key for which the string should be returned
 * @param defaultValue The value to return if the key does not exist
 * @return The string for the specified key or the specified default value if
 *	   it does not exist
 */
- (nullable OFString *)stringForKey: (OFString *)key
		       defaultValue: (nullable OFString *)defaultValue;

/**
 * @brief Returns the long long for the specified key or the specified default
 *	  value if it does not exist.
 *
 * If the specified key is a multi-key (see @ref stringArrayForKey:), the value
 * of the first key/value pair found is returned.
 *
 * @param key The key for which the long long should be returned
 * @param defaultValue The value to return if the key does not exist
 * @return The long long for the specified key or the specified default value
 *	   if it does not exist
 * @throw OFInvalidFormatException The specified key is not in the correct
 *				   format for a long long
 */
- (long long)longLongForKey: (OFString *)key
	       defaultValue: (long long)defaultValue;

/**
 * @brief Returns the bool for the specified key or the specified default value
 *	  if it does not exist.
 *
 * If the specified key is a multi-key (see @ref stringArrayForKey:), the value
 * of the first key/value pair found is returned.
 *
 * @param key The key for which the bool should be returned
 * @param defaultValue The value to return if the key does not exist
 * @return The bool for the specified key or the specified default value if it
 *	   does not exist
 * @throw OFInvalidFormatException The specified key is not in the correct
 *				   format for a bool
 */
- (bool)boolForKey: (OFString *)key defaultValue: (bool)defaultValue;

/**
 * @brief Returns the float for the specified key or the specified default
 *	  value if it does not exist.
 *
 * If the specified key is a multi-key (see @ref stringArrayForKey:), the value
 * of the first key/value pair found is returned.
 *
 * @param key The key for which the float should be returned
 * @param defaultValue The value to return if the key does not exist
 * @return The float for the specified key or the specified default value if it
 *	   does not exist
 * @throw OFInvalidFormatException The specified key is not in the correct
 *				   format for a float
 */
- (float)floatForKey: (OFString *)key defaultValue: (float)defaultValue;

/**
 * @brief Returns the double for the specified key or the specified default
 *	  value if it does not exist.
 *
 * If the specified key is a multi-key (see @ref stringArrayForKey:), the value
 * of the first key/value pair found is returned.
 *
 * @param key The key for which the double should be returned
 * @param defaultValue The value to return if the key does not exist
 * @return The double for the specified key or the specified default value if
 *	   it does not exist
 * @throw OFInvalidFormatException The specified key is not in the correct
 *				   format for a double
 */
- (double)doubleForKey: (OFString *)key defaultValue: (double)defaultValue;

/**
 * @brief Returns an array of strings for the specified multi-key, or an empty
 *	  array if the key does not exist.
 *
 * A multi-key is a key which exists several times in the same category. Each
 * occurrence of the key/value pair adds the respective value to the array.
 *
 * @param key The multi-key for which the array should be returned
 * @return The array for the specified key, or an empty array if it does not
 *	   exist
 */
- (OFArray OF_GENERIC(OFString *) *)stringArrayForKey: (OFString *)key;

/**
 * @brief Sets the value of the specified key to the specified string.
 *
 * If the specified key is a multi-key (see @ref stringArrayForKey:), the value
 * of the first key/value pair found is changed.
 *
 * @param string The string to which the key should be set
 * @param key The key for which the new value should be set
 */
- (void)setString: (OFString *)string forKey: (OFString *)key;

/**
 * @brief Sets the value of the specified key to the specified long long.
 *
 * If the specified key is a multi-key (see @ref stringArrayForKey:), the value
 * of the first key/value pair found is changed.
 *
 * @param longLong The long long to which the key should be set
 * @param key The key for which the new value should be set
 */
- (void)setLongLong: (long long)longLong forKey: (OFString *)key;

/**
 * @brief Sets the value of the specified key to the specified bool.
 *
 * If the specified key is a multi-key (see @ref stringArrayForKey:), the value
 * of the first key/value pair found is changed.
 *
 * @param bool_ The bool to which the key should be set
 * @param key The key for which the new value should be set
 */
- (void)setBool: (bool)bool_ forKey: (OFString *)key;

/**
 * @brief Sets the value of the specified key to the specified float.
 *
 * If the specified key is a multi-key (see @ref stringArrayForKey:), the value
 * of the first key/value pair found is changed.
 *
 * @param float_ The float to which the key should be set
 * @param key The key for which the new value should be set
 */
- (void)setFloat: (float)float_ forKey: (OFString *)key;

/**
 * @brief Sets the value of the specified key to the specified double.
 *
 * If the specified key is a multi-key (see @ref stringArrayForKey:), the value
 * of the first key/value pair found is changed.
 *
 * @param double_ The double to which the key should be set
 * @param key The key for which the new value should be set
 */
- (void)setDouble: (double)double_ forKey: (OFString *)key;

/**
 * @brief Sets the specified multi-key to the specified array of strings.
 *
 * It replaces the first occurrence of the multi-key with several key/value
 * pairs and removes all following occurrences. If the multi-key does not exist
 * yet, it is appended to the section.
 *
 * See also @ref stringArrayForKey: for more information about multi-keys.
 *
 * @param array The array of strings to which the multi-key should be set
 * @param key The multi-key for which the new values should be set
 */
- (void)setStringArray: (OFArray OF_GENERIC(OFString *) *)array
		forKey: (OFString *)key;

/**
 * @brief Removes the value for the specified key
 *
 * If the specified key is a multi-key (see @ref stringArrayForKey:), all
 * key/value pairs matching the specified key are removed.
 *
 * @param key The key of the value to remove
 */
- (void)removeValueForKey: (OFString *)key;
@end

OF_ASSUME_NONNULL_END







|





|





|







|
|


|
|

|









|
|


|
|

|









|


|


|









|


|
|

|









|












|




|


|


|




|


|


|




|


|


|




|


|


|




|


|


|








|

|


|
|




|








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

- (instancetype)init OF_UNAVAILABLE;

/**
 * @brief Returns the string for the specified key, or `nil` if it does not
 *	  exist.
 *
 * If the specified key is a multi-key (see @ref arrayValueForKey:), the value
 * of the first key/value pair found is returned.
 *
 * @param key The key for which the string should be returned
 * @return The string for the specified key, or `nil` if it does not exist
 */
- (nullable OFString *)stringValueForKey: (OFString *)key;

/**
 * @brief Returns the string for the specified key or the specified default
 *	  value if it does not exist.
 *
 * If the specified key is a multi-key (see @ref arrayValueForKey:), the value
 * of the first key/value pair found is returned.
 *
 * @param key The key for which the string should be returned
 * @param defaultValue The value to return if the key does not exist
 * @return The string for the specified key or the specified default value if
 *	   it does not exist
 */
- (nullable OFString *)stringValueForKey: (OFString *)key
			    defaultValue: (nullable OFString *)defaultValue;

/**
 * @brief Returns the long long value for the specified key or the specified
 *	  default value if it does not exist.
 *
 * If the specified key is a multi-key (see @ref arrayValueForKey:), the value
 * of the first key/value pair found is returned.
 *
 * @param key The key for which the long long should be returned
 * @param defaultValue The value to return if the key does not exist
 * @return The long long for the specified key or the specified default value
 *	   if it does not exist
 * @throw OFInvalidFormatException The specified key is not in the correct
 *				   format for a long long
 */
- (long long)longLongValueForKey: (OFString *)key
		    defaultValue: (long long)defaultValue;

/**
 * @brief Returns the bool value for the specified key or the specified default
 *	  value if it does not exist.
 *
 * If the specified key is a multi-key (see @ref arrayValueForKey:), the value
 * of the first key/value pair found is returned.
 *
 * @param key The key for which the bool should be returned
 * @param defaultValue The value to return if the key does not exist
 * @return The bool for the specified key or the specified default value if it
 *	   does not exist
 * @throw OFInvalidFormatException The specified key is not in the correct
 *				   format for a bool
 */
- (bool)boolValueForKey: (OFString *)key defaultValue: (bool)defaultValue;

/**
 * @brief Returns the float value for the specified key or the specified default
 *	  value if it does not exist.
 *
 * If the specified key is a multi-key (see @ref arrayValueForKey:), the value
 * of the first key/value pair found is returned.
 *
 * @param key The key for which the float should be returned
 * @param defaultValue The value to return if the key does not exist
 * @return The float for the specified key or the specified default value if it
 *	   does not exist
 * @throw OFInvalidFormatException The specified key is not in the correct
 *				   format for a float
 */
- (float)floatValueForKey: (OFString *)key defaultValue: (float)defaultValue;

/**
 * @brief Returns the double value for the specified key or the specified
 *	  default value if it does not exist.
 *
 * If the specified key is a multi-key (see @ref arrayValueForKey:), the value
 * of the first key/value pair found is returned.
 *
 * @param key The key for which the double should be returned
 * @param defaultValue The value to return if the key does not exist
 * @return The double for the specified key or the specified default value if
 *	   it does not exist
 * @throw OFInvalidFormatException The specified key is not in the correct
 *				   format for a double
 */
- (double)doubleValueForKey: (OFString *)key defaultValue: (double)defaultValue;

/**
 * @brief Returns an array of strings for the specified multi-key, or an empty
 *	  array if the key does not exist.
 *
 * A multi-key is a key which exists several times in the same category. Each
 * occurrence of the key/value pair adds the respective value to the array.
 *
 * @param key The multi-key for which the array should be returned
 * @return The array for the specified key, or an empty array if it does not
 *	   exist
 */
- (OFArray OF_GENERIC(OFString *) *)arrayValueForKey: (OFString *)key;

/**
 * @brief Sets the value of the specified key to the specified string.
 *
 * If the specified key is a multi-key (see @ref arrayValueForKey:), the value
 * of the first key/value pair found is changed.
 *
 * @param stringValue The string to which the key should be set
 * @param key The key for which the new value should be set
 */
- (void)setStringValue: (OFString *)stringValue forKey: (OFString *)key;

/**
 * @brief Sets the value of the specified key to the specified long long.
 *
 * If the specified key is a multi-key (see @ref arrayValueForKey:), the value
 * of the first key/value pair found is changed.
 *
 * @param longLongValue The long long to which the key should be set
 * @param key The key for which the new value should be set
 */
- (void)setLongLongValue: (long long)longLongValue forKey: (OFString *)key;

/**
 * @brief Sets the value of the specified key to the specified bool.
 *
 * If the specified key is a multi-key (see @ref arrayValueForKey:), the value
 * of the first key/value pair found is changed.
 *
 * @param boolValue The bool to which the key should be set
 * @param key The key for which the new value should be set
 */
- (void)setBoolValue: (bool)boolValue forKey: (OFString *)key;

/**
 * @brief Sets the value of the specified key to the specified float.
 *
 * If the specified key is a multi-key (see @ref arrayValueForKey:), the value
 * of the first key/value pair found is changed.
 *
 * @param floatValue The float to which the key should be set
 * @param key The key for which the new value should be set
 */
- (void)setFloatValue: (float)floatValue forKey: (OFString *)key;

/**
 * @brief Sets the value of the specified key to the specified double.
 *
 * If the specified key is a multi-key (see @ref arrayValueForKey:), the value
 * of the first key/value pair found is changed.
 *
 * @param doubleValue The double to which the key should be set
 * @param key The key for which the new value should be set
 */
- (void)setDoubleValue: (double)doubleValue forKey: (OFString *)key;

/**
 * @brief Sets the specified multi-key to the specified array of strings.
 *
 * It replaces the first occurrence of the multi-key with several key/value
 * pairs and removes all following occurrences. If the multi-key does not exist
 * yet, it is appended to the section.
 *
 * See also @ref arrayValueForKey: for more information about multi-keys.
 *
 * @param arrayValue The array of strings to which the multi-key should be set
 * @param key The multi-key for which the new values should be set
 */
- (void)setArrayValue: (OFArray OF_GENERIC(OFString *) *)arrayValue
	       forKey: (OFString *)key;

/**
 * @brief Removes the value for the specified key
 *
 * If the specified key is a multi-key (see @ref arrayValueForKey:), all
 * key/value pairs matching the specified key are removed.
 *
 * @param key The key of the value to remove
 */
- (void)removeValueForKey: (OFString *)key;
@end

OF_ASSUME_NONNULL_END

Modified src/OFINICategory.m from [1db2d24df3] to [e1d77cfa79].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
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

		comment->_comment = [line copy];

		[_lines addObject: comment];
	}
}

- (OFString *)stringForKey: (OFString *)key
{
	return [self stringForKey: key defaultValue: nil];
}

- (OFString *)stringForKey: (OFString *)key
	      defaultValue: (OFString *)defaultValue
{
	for (id line in _lines) {
		OFINICategoryPair *pair;

		if (![line isKindOfClass: [OFINICategoryPair class]])
			continue;

		pair = line;

		if ([pair->_key isEqual: key])
			return [[pair->_value copy] autorelease];
	}

	return defaultValue;
}

- (long long)longLongForKey: (OFString *)key
	       defaultValue: (long long)defaultValue
{
	void *pool = objc_autoreleasePoolPush();
	OFString *value = [self stringForKey: key defaultValue: nil];
	long long ret;

	if (value != nil)
		ret = [value longLongValueWithBase: 0];
	else
		ret = defaultValue;

	objc_autoreleasePoolPop(pool);

	return ret;
}

- (bool)boolForKey: (OFString *)key defaultValue: (bool)defaultValue
{
	void *pool = objc_autoreleasePoolPush();
	OFString *value = [self stringForKey: key defaultValue: nil];
	bool ret;

	if (value != nil) {
		if ([value isEqual: @"true"])
			ret = true;
		else if ([value isEqual: @"false"])
			ret = false;
		else
			@throw [OFInvalidFormatException exception];
	} else
		ret = defaultValue;

	objc_autoreleasePoolPop(pool);

	return ret;
}

- (float)floatForKey: (OFString *)key defaultValue: (float)defaultValue
{
	void *pool = objc_autoreleasePoolPush();
	OFString *value = [self stringForKey: key defaultValue: nil];
	float ret;

	if (value != nil)
		ret = value.floatValue;
	else
		ret = defaultValue;

	objc_autoreleasePoolPop(pool);

	return ret;
}

- (double)doubleForKey: (OFString *)key defaultValue: (double)defaultValue
{
	void *pool = objc_autoreleasePoolPush();
	OFString *value = [self stringForKey: key defaultValue: nil];
	double ret;

	if (value != nil)
		ret = value.doubleValue;
	else
		ret = defaultValue;

	objc_autoreleasePoolPop(pool);

	return ret;
}

- (OFArray OF_GENERIC(OFString *) *)stringArrayForKey: (OFString *)key
{
	OFMutableArray *ret = [OFMutableArray array];
	void *pool = objc_autoreleasePoolPush();

	for (id line in _lines) {
		OFINICategoryPair *pair;








|

|


|
|
















|
|


|












|


|

















|


|












|


|












|







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

		comment->_comment = [line copy];

		[_lines addObject: comment];
	}
}

- (OFString *)stringValueForKey: (OFString *)key
{
	return [self stringValueForKey: key defaultValue: nil];
}

- (OFString *)stringValueForKey: (OFString *)key
		   defaultValue: (OFString *)defaultValue
{
	for (id line in _lines) {
		OFINICategoryPair *pair;

		if (![line isKindOfClass: [OFINICategoryPair class]])
			continue;

		pair = line;

		if ([pair->_key isEqual: key])
			return [[pair->_value copy] autorelease];
	}

	return defaultValue;
}

- (long long)longLongValueForKey: (OFString *)key
		    defaultValue: (long long)defaultValue
{
	void *pool = objc_autoreleasePoolPush();
	OFString *value = [self stringValueForKey: key defaultValue: nil];
	long long ret;

	if (value != nil)
		ret = [value longLongValueWithBase: 0];
	else
		ret = defaultValue;

	objc_autoreleasePoolPop(pool);

	return ret;
}

- (bool)boolValueForKey: (OFString *)key defaultValue: (bool)defaultValue
{
	void *pool = objc_autoreleasePoolPush();
	OFString *value = [self stringValueForKey: key defaultValue: nil];
	bool ret;

	if (value != nil) {
		if ([value isEqual: @"true"])
			ret = true;
		else if ([value isEqual: @"false"])
			ret = false;
		else
			@throw [OFInvalidFormatException exception];
	} else
		ret = defaultValue;

	objc_autoreleasePoolPop(pool);

	return ret;
}

- (float)floatValueForKey: (OFString *)key defaultValue: (float)defaultValue
{
	void *pool = objc_autoreleasePoolPush();
	OFString *value = [self stringValueForKey: key defaultValue: nil];
	float ret;

	if (value != nil)
		ret = value.floatValue;
	else
		ret = defaultValue;

	objc_autoreleasePoolPop(pool);

	return ret;
}

- (double)doubleValueForKey: (OFString *)key defaultValue: (double)defaultValue
{
	void *pool = objc_autoreleasePoolPush();
	OFString *value = [self stringValueForKey: key defaultValue: nil];
	double ret;

	if (value != nil)
		ret = value.doubleValue;
	else
		ret = defaultValue;

	objc_autoreleasePoolPop(pool);

	return ret;
}

- (OFArray OF_GENERIC(OFString *) *)arrayValueForKey: (OFString *)key
{
	OFMutableArray *ret = [OFMutableArray array];
	void *pool = objc_autoreleasePoolPush();

	for (id line in _lines) {
		OFINICategoryPair *pair;

291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
	objc_autoreleasePoolPop(pool);

	[ret makeImmutable];

	return ret;
}

- (void)setString: (OFString *)string forKey: (OFString *)key
{
	void *pool = objc_autoreleasePoolPush();
	OFINICategoryPair *pair;

	for (id line in _lines) {
		if (![line isKindOfClass: [OFINICategoryPair class]])
			continue;







|







291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
	objc_autoreleasePoolPop(pool);

	[ret makeImmutable];

	return ret;
}

- (void)setStringValue: (OFString *)string forKey: (OFString *)key
{
	void *pool = objc_autoreleasePoolPush();
	OFINICategoryPair *pair;

	for (id line in _lines) {
		if (![line isKindOfClass: [OFINICategoryPair class]])
			continue;
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

		@throw e;
	}

	objc_autoreleasePoolPop(pool);
}

- (void)setLongLong: (long long)longLong forKey: (OFString *)key
{
	void *pool = objc_autoreleasePoolPush();

	[self setString: [OFString stringWithFormat: @"%lld", longLong]

		 forKey: key];

	objc_autoreleasePoolPop(pool);
}

- (void)setBool: (bool)bool_ forKey: (OFString *)key
{
	[self setString: (bool_ ? @"true" : @"false") forKey: key];
}

- (void)setFloat: (float)float_ forKey: (OFString *)key
{
	void *pool = objc_autoreleasePoolPush();

	[self setString: [OFString stringWithFormat: @"%g", float_]










		 forKey: key];

	objc_autoreleasePoolPop(pool);
}

- (void)setDouble: (double)double_ forKey: (OFString *)key
{
	void *pool = objc_autoreleasePoolPush();

	[self setString: [OFString stringWithFormat: @"%g", double_]
		 forKey: key];

	objc_autoreleasePoolPop(pool);
}

- (void)setStringArray: (OFArray OF_GENERIC(OFString *) *)array
		forKey: (OFString *)key
{
	void *pool;
	OFMutableArray *pairs;
	id const *lines;
	size_t count;
	bool replaced;

	if (array.count == 0) {
		[self removeValueForKey: key];
		return;
	}

	pool = objc_autoreleasePoolPush();

	pairs = [OFMutableArray arrayWithCapacity: array.count];

	for (OFString *string in array) {
		OFINICategoryPair *pair;

		if (![string isKindOfClass: [OFString class]])
			@throw [OFInvalidArgumentException exception];

		pair = [[[OFINICategoryPair alloc] init] autorelease];
		pair->_key = [key copy];







|



|
>
|




|

|


|



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




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







|






|

|







331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373










374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399

		@throw e;
	}

	objc_autoreleasePoolPop(pool);
}

- (void)setLongLongValue: (long long)longLongValue forKey: (OFString *)key
{
	void *pool = objc_autoreleasePoolPush();

	[self setStringValue: [OFString stringWithFormat:
				  @"%lld", longLongValue]
		      forKey: key];

	objc_autoreleasePoolPop(pool);
}

- (void)setBoolValue: (bool)boolValue forKey: (OFString *)key
{
	[self setStringValue: (boolValue ? @"true" : @"false") forKey: key];
}

- (void)setFloatValue: (float)floatValue forKey: (OFString *)key
{
	void *pool = objc_autoreleasePoolPush();

	[self setStringValue: [OFString stringWithFormat: @"%g", floatValue]
		      forKey: key];

	objc_autoreleasePoolPop(pool);
}

- (void)setDoubleValue: (double)doubleValue forKey: (OFString *)key
{
	void *pool = objc_autoreleasePoolPush();

	[self setStringValue: [OFString stringWithFormat: @"%g", doubleValue]
		      forKey: key];

	objc_autoreleasePoolPop(pool);
}











- (void)setArrayValue: (OFArray OF_GENERIC(OFString *) *)arrayValue
	       forKey: (OFString *)key
{
	void *pool;
	OFMutableArray *pairs;
	id const *lines;
	size_t count;
	bool replaced;

	if (arrayValue.count == 0) {
		[self removeValueForKey: key];
		return;
	}

	pool = objc_autoreleasePoolPush();

	pairs = [OFMutableArray arrayWithCapacity: arrayValue.count];

	for (OFString *string in arrayValue) {
		OFINICategoryPair *pair;

		if (![string isKindOfClass: [OFString class]])
			@throw [OFInvalidArgumentException exception];

		pair = [[[OFINICategoryPair alloc] init] autorelease];
		pair->_key = [key copy];
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432

			if (!replaced) {
				[_lines insertObjectsFromArray: pairs
						       atIndex: i];

				replaced = true;
				/* Continue after inserted pairs */
				i += array.count - 1;
			} else
				i--;	/* Continue at same position */

			lines = _lines.objects;
			count = _lines.count;

			continue;







|







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

			if (!replaced) {
				[_lines insertObjectsFromArray: pairs
						       atIndex: i];

				replaced = true;
				/* Continue after inserted pairs */
				i += arrayValue.count - 1;
			} else
				i--;	/* Continue at same position */

			lines = _lines.objects;
			count = _lines.count;

			continue;

Modified src/OFINIFile.h from [f35fd21473] to [a491fd2c94].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#import "OFObject.h"
#import "OFString.h"
#import "OFINICategory.h"

OF_ASSUME_NONNULL_BEGIN


@class OFMutableArray OF_GENERIC(ObjectType);
@class OFURI;

/**
 * @class OFINIFile OFINIFile.h ObjFW/OFINIFile.h
 *
 * @brief A class for reading, creating and modifying INI files.
 */
OF_SUBCLASSING_RESTRICTED
@interface OFINIFile: OFObject
{
	OFMutableArray OF_GENERIC(OFINICategory *) *_categories;
}

/**
 * @brief All categories in the INI file.
 */
@property (readonly, nonatomic) OFArray OF_GENERIC(OFINICategory *) *categories;

/**
 * @brief Creates a new OFINIFile with the contents of the specified file.
 *
 * @param URI The URI to the file whose contents the OFINIFile should contain
 *
 * @return A new, autoreleased OFINIFile with the contents of the specified file
 * @throw OFInvalidFormatException The format of the specified INI file is
 *				   invalid
 * @throw OFInvalidEncodingException The INI file is not in the specified
 *				     encoding
 */
+ (instancetype)fileWithURI: (OFURI *)URI;

/**
 * @brief Creates a new OFINIFile with the contents of the specified file in
 *	  the specified encoding.
 *
 * @param URI The URI to the file whose contents the OFINIFile should contain
 * @param encoding The encoding of the specified file
 * @return A new, autoreleased OFINIFile with the contents of the specified file
 * @throw OFInvalidFormatException The format of the specified INI file is
 *				   invalid
 * @throw OFInvalidEncodingException The INI file is not in the specified
 *				     encoding
 */
+ (instancetype)fileWithURI: (OFURI *)URI encoding: (OFStringEncoding)encoding;

- (instancetype)init OF_UNAVAILABLE;

/**
 * @brief Initializes an already allocated OFINIFile with the contents of the
 *	  specified file.
 *
 * @param URI The URI to the file whose contents the OFINIFile should contain
 *
 * @return An initialized OFINIFile with the contents of the specified file
 * @throw OFInvalidFormatException The format of the specified INI file is
 *				   invalid
 * @throw OFInvalidEncodingException The INI file is not in the specified
 *				     encoding
 */
- (instancetype)initWithURI: (OFURI *)URI;

/**
 * @brief Initializes an already allocated OFINIFile with the contents of the
 *	  specified file in the specified encoding.
 *
 * @param URI The URI to the file whose contents the OFINIFile should contain
 * @param encoding The encoding of the specified file
 * @return An initialized OFINIFile with the contents of the specified file
 * @throw OFInvalidFormatException The format of the specified INI file is
 *				   invalid
 * @throw OFInvalidEncodingException The INI file is not in the specified
 *				     encoding
 */
- (instancetype)initWithURI: (OFURI *)URI
		   encoding: (OFStringEncoding)encoding
    OF_DESIGNATED_INITIALIZER;

/**
 * @brief Returns an @ref OFINICategory for the category with the specified
 *	  name.
 *
 * @param name The name of the category for which an @ref OFINICategory should
 *	       be returned
 *
 * @return An @ref OFINICategory for the category with the specified name
 */
- (OFINICategory *)categoryForName: (OFString *)name;

/**
 * @brief Writes the contents of the OFINIFile to a file.
 *
 * @param URI The URI of the file to write to
 */
- (void)writeToURI: (OFURI *)URI;

/**
 * @brief Writes the contents of the OFINIFile to a file in the specified
 *	  encoding.
 *
 * @param URI The URI of the file to write to
 * @param encoding The encoding to use
 */
- (void)writeToURI: (OFURI *)URI encoding: (OFStringEncoding)encoding;
@end

OF_ASSUME_NONNULL_END

|



















>

<




















|







|





|







|







|







|





|







|

















|

|





|


|



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
/*
 * Copyright (c) 2008-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 "OFObject.h"
#import "OFString.h"
#import "OFINICategory.h"

OF_ASSUME_NONNULL_BEGIN

@class OFIRI;
@class OFMutableArray OF_GENERIC(ObjectType);


/**
 * @class OFINIFile OFINIFile.h ObjFW/OFINIFile.h
 *
 * @brief A class for reading, creating and modifying INI files.
 */
OF_SUBCLASSING_RESTRICTED
@interface OFINIFile: OFObject
{
	OFMutableArray OF_GENERIC(OFINICategory *) *_categories;
}

/**
 * @brief All categories in the INI file.
 */
@property (readonly, nonatomic) OFArray OF_GENERIC(OFINICategory *) *categories;

/**
 * @brief Creates a new OFINIFile with the contents of the specified file.
 *
 * @param IRI The IRI to the file whose contents the OFINIFile should contain
 *
 * @return A new, autoreleased OFINIFile with the contents of the specified file
 * @throw OFInvalidFormatException The format of the specified INI file is
 *				   invalid
 * @throw OFInvalidEncodingException The INI file is not in the specified
 *				     encoding
 */
+ (instancetype)fileWithIRI: (OFIRI *)IRI;

/**
 * @brief Creates a new OFINIFile with the contents of the specified file in
 *	  the specified encoding.
 *
 * @param IRI The IRI to the file whose contents the OFINIFile should contain
 * @param encoding The encoding of the specified file
 * @return A new, autoreleased OFINIFile with the contents of the specified file
 * @throw OFInvalidFormatException The format of the specified INI file is
 *				   invalid
 * @throw OFInvalidEncodingException The INI file is not in the specified
 *				     encoding
 */
+ (instancetype)fileWithIRI: (OFIRI *)IRI encoding: (OFStringEncoding)encoding;

- (instancetype)init OF_UNAVAILABLE;

/**
 * @brief Initializes an already allocated OFINIFile with the contents of the
 *	  specified file.
 *
 * @param IRI The IRI to the file whose contents the OFINIFile should contain
 *
 * @return An initialized OFINIFile with the contents of the specified file
 * @throw OFInvalidFormatException The format of the specified INI file is
 *				   invalid
 * @throw OFInvalidEncodingException The INI file is not in the specified
 *				     encoding
 */
- (instancetype)initWithIRI: (OFIRI *)IRI;

/**
 * @brief Initializes an already allocated OFINIFile with the contents of the
 *	  specified file in the specified encoding.
 *
 * @param IRI The IRI to the file whose contents the OFINIFile should contain
 * @param encoding The encoding of the specified file
 * @return An initialized OFINIFile with the contents of the specified file
 * @throw OFInvalidFormatException The format of the specified INI file is
 *				   invalid
 * @throw OFInvalidEncodingException The INI file is not in the specified
 *				     encoding
 */
- (instancetype)initWithIRI: (OFIRI *)IRI
		   encoding: (OFStringEncoding)encoding
    OF_DESIGNATED_INITIALIZER;

/**
 * @brief Returns an @ref OFINICategory for the category with the specified
 *	  name.
 *
 * @param name The name of the category for which an @ref OFINICategory should
 *	       be returned
 *
 * @return An @ref OFINICategory for the category with the specified name
 */
- (OFINICategory *)categoryForName: (OFString *)name;

/**
 * @brief Writes the contents of the OFINIFile to a file.
 *
 * @param IRI The IRI of the file to write to
 */
- (void)writeToIRI: (OFIRI *)IRI;

/**
 * @brief Writes the contents of the OFINIFile to a file in the specified
 *	  encoding.
 *
 * @param IRI The IRI of the file to write to
 * @param encoding The encoding to use
 */
- (void)writeToIRI: (OFIRI *)IRI encoding: (OFStringEncoding)encoding;
@end

OF_ASSUME_NONNULL_END

Modified src/OFINIFile.m from [7850530cf1] to [35c3a72b71].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87

#include <errno.h>

#import "OFINIFile.h"
#import "OFArray.h"
#import "OFINICategory+Private.h"
#import "OFINICategory.h"
#import "OFStream.h"
#import "OFString.h"
#import "OFURI.h"
#import "OFURIHandler.h"

#import "OFInvalidFormatException.h"
#import "OFOpenItemFailedException.h"

OF_DIRECT_MEMBERS
@interface OFINIFile ()
- (void)of_parseURI: (OFURI *)URI encoding: (OFStringEncoding)encoding;
@end

static bool
isWhitespaceLine(OFString *line)
{
	const char *cString = line.UTF8String;
	size_t length = line.UTF8StringLength;

	for (size_t i = 0; i < length; i++)
		if (!OFASCIIIsSpace(cString[i]))
			return false;

	return true;
}

@implementation OFINIFile
@synthesize categories = _categories;

+ (instancetype)fileWithURI: (OFURI *)URI
{
	return [[[self alloc] initWithURI: URI] autorelease];
}

+ (instancetype)fileWithURI: (OFURI *)URI encoding: (OFStringEncoding)encoding
{
	return [[[self alloc] initWithURI: URI encoding: encoding] autorelease];
}

- (instancetype)init
{
	OF_INVALID_INIT_METHOD
}

- (instancetype)initWithURI: (OFURI *)URI
{
	return [self initWithURI: URI encoding: OFStringEncodingAutodetect];
}

- (instancetype)initWithURI: (OFURI *)URI encoding: (OFStringEncoding)encoding
{
	self = [super init];

	@try {
		_categories = [[OFMutableArray alloc] init];

		[self of_parseURI: URI encoding: encoding];
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}







|
|
|
|






|


















|

|


|

|







|

|


|






|







17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87

#include <errno.h>

#import "OFINIFile.h"
#import "OFArray.h"
#import "OFINICategory+Private.h"
#import "OFINICategory.h"
#import "OFIRI.h"
#import "OFIRIHandler.h"
#import "OFStream.h"
#import "OFString.h"

#import "OFInvalidFormatException.h"
#import "OFOpenItemFailedException.h"

OF_DIRECT_MEMBERS
@interface OFINIFile ()
- (void)of_parseIRI: (OFIRI *)IRI encoding: (OFStringEncoding)encoding;
@end

static bool
isWhitespaceLine(OFString *line)
{
	const char *cString = line.UTF8String;
	size_t length = line.UTF8StringLength;

	for (size_t i = 0; i < length; i++)
		if (!OFASCIIIsSpace(cString[i]))
			return false;

	return true;
}

@implementation OFINIFile
@synthesize categories = _categories;

+ (instancetype)fileWithIRI: (OFIRI *)IRI
{
	return [[[self alloc] initWithIRI: IRI] autorelease];
}

+ (instancetype)fileWithIRI: (OFIRI *)IRI encoding: (OFStringEncoding)encoding
{
	return [[[self alloc] initWithIRI: IRI encoding: encoding] autorelease];
}

- (instancetype)init
{
	OF_INVALID_INIT_METHOD
}

- (instancetype)initWithIRI: (OFIRI *)IRI
{
	return [self initWithIRI: IRI encoding: OFStringEncodingAutodetect];
}

- (instancetype)initWithIRI: (OFIRI *)IRI encoding: (OFStringEncoding)encoding
{
	self = [super init];

	@try {
		_categories = [[OFMutableArray alloc] init];

		[self of_parseIRI: IRI encoding: encoding];
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
	[_categories addObject: category];

	objc_autoreleasePoolPop(pool);

	return category;
}

- (void)of_parseURI: (OFURI *)URI encoding: (OFStringEncoding)encoding
{
	void *pool = objc_autoreleasePoolPush();
	OFStream *file;
	OFINICategory *category = nil;
	OFString *line;

	if (encoding == OFStringEncodingAutodetect)
		encoding = OFStringEncodingUTF8;

	@try {
		file = [OFURIHandler openItemAtURI: URI mode: @"r"];
	} @catch (OFOpenItemFailedException *e) {
		/* Handle missing file like an empty file */
		if (e.errNo == ENOENT)
			return;

		@throw e;
	}







|










|







106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
	[_categories addObject: category];

	objc_autoreleasePoolPop(pool);

	return category;
}

- (void)of_parseIRI: (OFIRI *)IRI encoding: (OFStringEncoding)encoding
{
	void *pool = objc_autoreleasePoolPush();
	OFStream *file;
	OFINICategory *category = nil;
	OFString *line;

	if (encoding == OFStringEncodingAutodetect)
		encoding = OFStringEncodingUTF8;

	@try {
		file = [OFIRIHandler openItemAtIRI: IRI mode: @"r"];
	} @catch (OFOpenItemFailedException *e) {
		/* Handle missing file like an empty file */
		if (e.errNo == ENOENT)
			return;

		@throw e;
	}
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
			[category of_parseLine: line];
		}
	}

	objc_autoreleasePoolPop(pool);
}

- (void)writeToURI: (OFURI *)URI
{
	[self writeToURI: URI encoding: OFStringEncodingUTF8];
}

- (void)writeToURI: (OFURI *)URI encoding: (OFStringEncoding)encoding
{
	void *pool = objc_autoreleasePoolPush();
	OFStream *file = [OFURIHandler openItemAtURI: URI mode: @"w"];
	bool first = true;

	for (OFINICategory *category in _categories)
		if ([category of_writeToStream: file
				      encoding: encoding
					 first: first])
			first = false;







|

|


|


|







152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
			[category of_parseLine: line];
		}
	}

	objc_autoreleasePoolPop(pool);
}

- (void)writeToIRI: (OFIRI *)IRI
{
	[self writeToIRI: IRI encoding: OFStringEncodingUTF8];
}

- (void)writeToIRI: (OFIRI *)IRI encoding: (OFStringEncoding)encoding
{
	void *pool = objc_autoreleasePoolPush();
	OFStream *file = [OFIRIHandler openItemAtIRI: IRI mode: @"w"];
	bool first = true;

	for (OFINICategory *category in _categories)
		if ([category of_writeToStream: file
				      encoding: encoding
					 first: first])
			first = false;

Modified src/OFINIFileSettings.h from [125e92a3e8] to [2ce815bb92].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#import "OFSettings.h"

OF_ASSUME_NONNULL_BEGIN

@class OFINIFile;
@class OFString;
@class OFURI;

@interface OFINIFileSettings: OFSettings
{
	OFURI *_fileURI;
	OFINIFile *_INIFile;
}
@end

OF_ASSUME_NONNULL_END

|


















|
|



|





1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/*
 * Copyright (c) 2008-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 "OFSettings.h"

OF_ASSUME_NONNULL_BEGIN

@class OFINIFile;
@class OFIRI;
@class OFString;

@interface OFINIFileSettings: OFSettings
{
	OFIRI *_fileIRI;
	OFINIFile *_INIFile;
}
@end

OF_ASSUME_NONNULL_END

Modified src/OFINIFileSettings.m from [b3d1a39e2b] to [00ccb3ae74].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#import "OFINIFileSettings.h"
#import "OFArray.h"
#import "OFINIFile.h"
#import "OFString.h"
#import "OFSystemInfo.h"
#import "OFURI.h"

@implementation OFINIFileSettings
- (instancetype)initWithApplicationName: (OFString *)applicationName
{
	self = [super initWithApplicationName: applicationName];

	@try {
		void *pool = objc_autoreleasePoolPush();
		OFString *fileName;

		fileName = [applicationName stringByAppendingString: @".ini"];
		_fileURI = [[[OFSystemInfo userConfigURI]
		    URIByAppendingPathComponent: fileName] copy];
		_INIFile = [[OFINIFile alloc] initWithURI: _fileURI];

		objc_autoreleasePoolPop(pool);
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (void)dealloc
{
	[_fileURI release];
	[_INIFile release];

	[super dealloc];
}

- (void)of_getCategory: (OFString **)category
		andKey: (OFString **)key

|


















|
|
|











|
|
|












|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
/*
 * Copyright (c) 2008-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 "OFINIFileSettings.h"
#import "OFArray.h"
#import "OFINIFile.h"
#import "OFIRI.h"
#import "OFString.h"
#import "OFSystemInfo.h"

@implementation OFINIFileSettings
- (instancetype)initWithApplicationName: (OFString *)applicationName
{
	self = [super initWithApplicationName: applicationName];

	@try {
		void *pool = objc_autoreleasePoolPush();
		OFString *fileName;

		fileName = [applicationName stringByAppendingString: @".ini"];
		_fileIRI = [[[OFSystemInfo userConfigIRI]
		    IRIByAppendingPathComponent: fileName] copy];
		_INIFile = [[OFINIFile alloc] initWithIRI: _fileIRI];

		objc_autoreleasePoolPop(pool);
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (void)dealloc
{
	[_fileIRI release];
	[_INIFile release];

	[super dealloc];
}

- (void)of_getCategory: (OFString **)category
		andKey: (OFString **)key
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

- (void)setString: (OFString *)string forPath: (OFString *)path
{
	void *pool = objc_autoreleasePoolPush();
	OFString *category, *key;

	[self of_getCategory: &category andKey: &key forPath: path];
	[[_INIFile categoryForName: category] setString: string forKey: key];


	objc_autoreleasePoolPop(pool);
}

- (void)setLongLong: (long long)longLong forPath: (OFString *)path
{
	void *pool = objc_autoreleasePoolPush();
	OFString *category, *key;

	[self of_getCategory: &category andKey: &key forPath: path];
	[[_INIFile categoryForName: category] setLongLong: longLong
						   forKey: key];

	objc_autoreleasePoolPop(pool);
}

- (void)setBool: (bool)bool_ forPath: (OFString *)path
{
	void *pool = objc_autoreleasePoolPush();
	OFString *category, *key;

	[self of_getCategory: &category andKey: &key forPath: path];
	[[_INIFile categoryForName: category] setBool: bool_ forKey: key];

	objc_autoreleasePoolPop(pool);
}

- (void)setFloat: (float)float_ forPath: (OFString *)path
{
	void *pool = objc_autoreleasePoolPush();
	OFString *category, *key;

	[self of_getCategory: &category andKey: &key forPath: path];
	[[_INIFile categoryForName: category] setFloat: float_ forKey: key];


	objc_autoreleasePoolPop(pool);
}

- (void)setDouble: (double)double_ forPath: (OFString *)path
{
	void *pool = objc_autoreleasePoolPush();
	OFString *category, *key;

	[self of_getCategory: &category andKey: &key forPath: path];
	[[_INIFile categoryForName: category] setDouble: double_ forKey: key];


	objc_autoreleasePoolPop(pool);
}

- (void)setStringArray: (OFArray OF_GENERIC(OFString *) *)array
	       forPath: (OFString *)path
{
	void *pool = objc_autoreleasePoolPush();
	OFString *category, *key;

	[self of_getCategory: &category andKey: &key forPath: path];
	[[_INIFile categoryForName: category] setStringArray: array
						      forKey: key];

	objc_autoreleasePoolPop(pool);
}

- (OFString *)stringForPath: (OFString *)path
	       defaultValue: (OFString *)defaultValue
{
	void *pool = objc_autoreleasePoolPush();
	OFString *category, *key, *ret;

	[self of_getCategory: &category andKey: &key forPath: path];
	ret = [[_INIFile categoryForName: category] stringForKey: key

						    defaultValue: defaultValue];

	[ret retain];
	objc_autoreleasePoolPop(pool);
	return [ret autorelease];
}

- (long long)longLongForPath: (OFString *)path
		defaultValue: (long long)defaultValue
{
	void *pool = objc_autoreleasePoolPush();
	OFString *category, *key;
	long long ret;

	[self of_getCategory: &category andKey: &key forPath: path];
	ret = [[_INIFile categoryForName: category]
	    longLongForKey: key
	      defaultValue: defaultValue];

	objc_autoreleasePoolPop(pool);

	return ret;
}

- (bool)boolForPath: (OFString *)path defaultValue: (bool)defaultValue
{
	void *pool = objc_autoreleasePoolPush();
	OFString *category, *key;
	bool ret;

	[self of_getCategory: &category andKey: &key forPath: path];
	ret = [[_INIFile categoryForName: category] boolForKey: key

						  defaultValue: defaultValue];

	objc_autoreleasePoolPop(pool);

	return ret;
}

- (float)floatForPath: (OFString *)path defaultValue: (float)defaultValue
{
	void *pool = objc_autoreleasePoolPush();
	OFString *category, *key;
	float ret;

	[self of_getCategory: &category andKey: &key forPath: path];
	ret = [[_INIFile categoryForName: category] floatForKey: key

						   defaultValue: defaultValue];

	objc_autoreleasePoolPop(pool);

	return ret;
}

- (double)doubleForPath: (OFString *)path defaultValue: (double)defaultValue
{
	void *pool = objc_autoreleasePoolPush();
	OFString *category, *key;
	double ret;

	[self of_getCategory: &category andKey: &key forPath: path];
	ret = [[_INIFile categoryForName: category] doubleForKey: key

						    defaultValue: defaultValue];

	objc_autoreleasePoolPop(pool);

	return ret;
}

- (OFArray OF_GENERIC(OFString *) *)stringArrayForPath: (OFString *)path
{
	void *pool = objc_autoreleasePoolPush();
	OFString *category, *key;
	OFArray *ret;

	[self of_getCategory: &category andKey: &key forPath: path];
	ret = [[_INIFile categoryForName: category] stringArrayForKey: key];

	[ret retain];
	objc_autoreleasePoolPop(pool);
	return [ret autorelease];
}

- (void)removeValueForPath: (OFString *)path
{
	void *pool = objc_autoreleasePoolPush();
	OFString *category, *key;

	[self of_getCategory: &category andKey: &key forPath: path];
	[[_INIFile categoryForName: category] removeValueForKey: key];

	objc_autoreleasePoolPop(pool);
}

- (void)save
{
	[_INIFile writeToURI: _fileURI];
}
@end







|
>










|
|










|










|
>










|
>











|
|











|
>
|















|
|













|
>
|













|
>
|













|
>
|













|



















|


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

- (void)setString: (OFString *)string forPath: (OFString *)path
{
	void *pool = objc_autoreleasePoolPush();
	OFString *category, *key;

	[self of_getCategory: &category andKey: &key forPath: path];
	[[_INIFile categoryForName: category] setStringValue: string
						      forKey: key];

	objc_autoreleasePoolPop(pool);
}

- (void)setLongLong: (long long)longLong forPath: (OFString *)path
{
	void *pool = objc_autoreleasePoolPush();
	OFString *category, *key;

	[self of_getCategory: &category andKey: &key forPath: path];
	[[_INIFile categoryForName: category] setLongLongValue: longLong
							forKey: key];

	objc_autoreleasePoolPop(pool);
}

- (void)setBool: (bool)bool_ forPath: (OFString *)path
{
	void *pool = objc_autoreleasePoolPush();
	OFString *category, *key;

	[self of_getCategory: &category andKey: &key forPath: path];
	[[_INIFile categoryForName: category] setBoolValue: bool_ forKey: key];

	objc_autoreleasePoolPop(pool);
}

- (void)setFloat: (float)float_ forPath: (OFString *)path
{
	void *pool = objc_autoreleasePoolPush();
	OFString *category, *key;

	[self of_getCategory: &category andKey: &key forPath: path];
	[[_INIFile categoryForName: category] setFloatValue: float_
						     forKey: key];

	objc_autoreleasePoolPop(pool);
}

- (void)setDouble: (double)double_ forPath: (OFString *)path
{
	void *pool = objc_autoreleasePoolPush();
	OFString *category, *key;

	[self of_getCategory: &category andKey: &key forPath: path];
	[[_INIFile categoryForName: category] setDoubleValue: double_
						      forKey: key];

	objc_autoreleasePoolPop(pool);
}

- (void)setStringArray: (OFArray OF_GENERIC(OFString *) *)array
	       forPath: (OFString *)path
{
	void *pool = objc_autoreleasePoolPush();
	OFString *category, *key;

	[self of_getCategory: &category andKey: &key forPath: path];
	[[_INIFile categoryForName: category] setArrayValue: array
						     forKey: key];

	objc_autoreleasePoolPop(pool);
}

- (OFString *)stringForPath: (OFString *)path
	       defaultValue: (OFString *)defaultValue
{
	void *pool = objc_autoreleasePoolPush();
	OFString *category, *key, *ret;

	[self of_getCategory: &category andKey: &key forPath: path];
	ret = [[_INIFile categoryForName: category]
	    stringValueForKey: key
		 defaultValue: defaultValue];

	[ret retain];
	objc_autoreleasePoolPop(pool);
	return [ret autorelease];
}

- (long long)longLongForPath: (OFString *)path
		defaultValue: (long long)defaultValue
{
	void *pool = objc_autoreleasePoolPush();
	OFString *category, *key;
	long long ret;

	[self of_getCategory: &category andKey: &key forPath: path];
	ret = [[_INIFile categoryForName: category]
	    longLongValueForKey: key
		   defaultValue: defaultValue];

	objc_autoreleasePoolPop(pool);

	return ret;
}

- (bool)boolForPath: (OFString *)path defaultValue: (bool)defaultValue
{
	void *pool = objc_autoreleasePoolPush();
	OFString *category, *key;
	bool ret;

	[self of_getCategory: &category andKey: &key forPath: path];
	ret = [[_INIFile categoryForName: category]
	    boolValueForKey: key
	       defaultValue: defaultValue];

	objc_autoreleasePoolPop(pool);

	return ret;
}

- (float)floatForPath: (OFString *)path defaultValue: (float)defaultValue
{
	void *pool = objc_autoreleasePoolPush();
	OFString *category, *key;
	float ret;

	[self of_getCategory: &category andKey: &key forPath: path];
	ret = [[_INIFile categoryForName: category]
	    floatValueForKey: key
		defaultValue: defaultValue];

	objc_autoreleasePoolPop(pool);

	return ret;
}

- (double)doubleForPath: (OFString *)path defaultValue: (double)defaultValue
{
	void *pool = objc_autoreleasePoolPush();
	OFString *category, *key;
	double ret;

	[self of_getCategory: &category andKey: &key forPath: path];
	ret = [[_INIFile categoryForName: category]
	    doubleValueForKey: key
		 defaultValue: defaultValue];

	objc_autoreleasePoolPop(pool);

	return ret;
}

- (OFArray OF_GENERIC(OFString *) *)stringArrayForPath: (OFString *)path
{
	void *pool = objc_autoreleasePoolPush();
	OFString *category, *key;
	OFArray *ret;

	[self of_getCategory: &category andKey: &key forPath: path];
	ret = [[_INIFile categoryForName: category] arrayValueForKey: key];

	[ret retain];
	objc_autoreleasePoolPop(pool);
	return [ret autorelease];
}

- (void)removeValueForPath: (OFString *)path
{
	void *pool = objc_autoreleasePoolPush();
	OFString *category, *key;

	[self of_getCategory: &category andKey: &key forPath: path];
	[[_INIFile categoryForName: category] removeValueForKey: key];

	objc_autoreleasePoolPop(pool);
}

- (void)save
{
	[_INIFile writeToIRI: _fileIRI];
}
@end

Modified src/OFIPXSocket.h from [8dc615311a] to [cb24c9ad99].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
 * @class OFIPXSocket OFIPXSocket.h ObjFW/OFIPXSocket.h
 *
 * @brief A class which provides methods to create and use IPX sockets.
 *
 * Addresses are of type @ref OFSocketAddress. You can use
 * @ref OFSocketAddressMakeIPX to create an address or
 * @ref OFSocketAddressIPXNetwork to get the IPX network,
 * @ref OFSocketAddressIPXNode to get the IPX node and
 * @ref OFSocketAddressIPXPort to get the port (sometimes also called
 * socket number).
 *
 * @warning Even though the OFCopying protocol is implemented, it does *not*
 *	    return an independent copy of the socket, but instead retains it.
 *	    This is so that the socket can be used as a key for a dictionary,
 *	    so context can be associated with a socket. Using a socket in more







|







31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
 * @class OFIPXSocket OFIPXSocket.h ObjFW/OFIPXSocket.h
 *
 * @brief A class which provides methods to create and use IPX sockets.
 *
 * Addresses are of type @ref OFSocketAddress. You can use
 * @ref OFSocketAddressMakeIPX to create an address or
 * @ref OFSocketAddressIPXNetwork to get the IPX network,
 * @ref OFSocketAddressGetIPXNode to get the IPX node and
 * @ref OFSocketAddressIPXPort to get the port (sometimes also called
 * socket number).
 *
 * @warning Even though the OFCopying protocol is implemented, it does *not*
 *	    return an independent copy of the socket, but instead retains it.
 *	    This is so that the socket can be used as a key for a dictionary,
 *	    so context can be associated with a socket. Using a socket in more
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
 * @param node The IPX network to bind to. An all zero node means the
 *	       computer's node.
 * @param port The port (sometimes called socket number) to bind to. 0 means to
 *	       pick one and return via the returned socket address.
 * @param packetType The packet type to use on the socket
 * @return The address on which this socket can be reached
 * @throw OFBindIPXSocketFailedException Binding failed
 * @throw OFAlreadyConnectedException The socket is already bound
 */
- (OFSocketAddress)
    bindToNetwork: (uint32_t)network
	     node: (const unsigned char [_Nonnull IPX_NODE_LEN])node
	     port: (uint16_t)port
       packetType: (uint8_t)packetType;
@end

OF_ASSUME_NONNULL_END







|









71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
 * @param node The IPX network to bind to. An all zero node means the
 *	       computer's node.
 * @param port The port (sometimes called socket number) to bind to. 0 means to
 *	       pick one and return via the returned socket address.
 * @param packetType The packet type to use on the socket
 * @return The address on which this socket can be reached
 * @throw OFBindIPXSocketFailedException Binding failed
 * @throw OFAlreadyOpenException The socket is already bound
 */
- (OFSocketAddress)
    bindToNetwork: (uint32_t)network
	     node: (const unsigned char [_Nonnull IPX_NODE_LEN])node
	     port: (uint16_t)port
       packetType: (uint8_t)packetType;
@end

OF_ASSUME_NONNULL_END

Modified src/OFIPXSocket.m from [1dc137a6b3] to [e59c8c17f2].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
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
# include <fcntl.h>
#endif

#import "OFIPXSocket.h"
#import "OFSocket.h"
#import "OFSocket+Private.h"

#import "OFAlreadyConnectedException.h"
#import "OFBindIPXSocketFailedException.h"





@implementation OFIPXSocket
@dynamic delegate;

- (OFSocketAddress)bindToNetwork: (uint32_t)network
			    node: (const unsigned char [IPX_NODE_LEN])node
			    port: (uint16_t)port
		      packetType: (uint8_t)packetType
{
	OFSocketAddress address;
	int protocol = 0;
#if SOCK_CLOEXEC == 0 && defined(HAVE_FCNTL_H) && defined(FD_CLOEXEC)
	int flags;
#endif

	if (_socket != OFInvalidSocketHandle)
		@throw [OFAlreadyConnectedException exceptionWithSocket: self];

	address = OFSocketAddressMakeIPX(network, node, port);

#ifdef OF_WINDOWS
	protocol = NSPROTO_IPX + packetType;
#else
	_packetType = address.sockaddr.ipx.sipx_type = packetType;
#endif

	if ((_socket = socket(address.sockaddr.ipx.sipx_family,
	    SOCK_DGRAM | SOCK_CLOEXEC, protocol)) == OFInvalidSocketHandle)







|

>
>
>
>
















|



|







21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# include <fcntl.h>
#endif

#import "OFIPXSocket.h"
#import "OFSocket.h"
#import "OFSocket+Private.h"

#import "OFAlreadyOpenException.h"
#import "OFBindIPXSocketFailedException.h"

#ifndef NSPROTO_IPX
# define NSPROTO_IPX 0
#endif

@implementation OFIPXSocket
@dynamic delegate;

- (OFSocketAddress)bindToNetwork: (uint32_t)network
			    node: (const unsigned char [IPX_NODE_LEN])node
			    port: (uint16_t)port
		      packetType: (uint8_t)packetType
{
	OFSocketAddress address;
	int protocol = 0;
#if SOCK_CLOEXEC == 0 && defined(HAVE_FCNTL_H) && defined(FD_CLOEXEC)
	int flags;
#endif

	if (_socket != OFInvalidSocketHandle)
		@throw [OFAlreadyOpenException exceptionWithObject: self];

	address = OFSocketAddressMakeIPX(network, node, port);

#if defined(OF_WINDOWS) || defined(OF_FREEBSD)
	protocol = NSPROTO_IPX + packetType;
#else
	_packetType = address.sockaddr.ipx.sipx_type = packetType;
#endif

	if ((_socket = socket(address.sockaddr.ipx.sipx_family,
	    SOCK_DGRAM | SOCK_CLOEXEC, protocol)) == OFInvalidSocketHandle)
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
				  socket: self
				   errNo: EAFNOSUPPORT];
	}

	return address;
}

#ifndef OF_WINDOWS
- (void)sendBuffer: (const void *)buffer
	    length: (size_t)length
	  receiver: (const OFSocketAddress *)receiver
{
	OFSocketAddress fixedReceiver;

	memcpy(&fixedReceiver, receiver, sizeof(fixedReceiver));







|







122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
				  socket: self
				   errNo: EAFNOSUPPORT];
	}

	return address;
}

#if !defined(OF_WINDOWS) && !defined(OF_FREEBSD)
- (void)sendBuffer: (const void *)buffer
	    length: (size_t)length
	  receiver: (const OFSocketAddress *)receiver
{
	OFSocketAddress fixedReceiver;

	memcpy(&fixedReceiver, receiver, sizeof(fixedReceiver));

Renamed and modified src/OFURI+Private.h [c5dc8bc44b] to src/OFIRI+Private.h [daf5febfe9].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#import "OFURI.h"

OF_ASSUME_NONNULL_BEGIN

@interface OFURI ()
- (instancetype)of_init OF_METHOD_FAMILY(init);
@end

OF_ASSUME_NONNULL_END

|













|



|




1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/*
 * Copyright (c) 2008-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 "OFIRI.h"

OF_ASSUME_NONNULL_BEGIN

@interface OFIRI ()
- (instancetype)of_init OF_METHOD_FAMILY(init);
@end

OF_ASSUME_NONNULL_END

Renamed and modified src/OFURI.h [90c837e175] to src/OFIRI.h [30cbd259c9].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

31


32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159





160

161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#import "OFObject.h"
#import "OFCharacterSet.h"
#import "OFSerialization.h"

OF_ASSUME_NONNULL_BEGIN

@class OFArray OF_GENERIC(ObjectType);
@class OFDictionary OF_GENERIC(KeyType, ObjectType);
@class OFNumber;
@class OFPair OF_GENERIC(FirstType, SecondType);
@class OFString;

/**
 * @class OFURI OFURI.h ObjFW/OFURI.h
 *

 * @brief A class for parsing URIs as per RFC 3986 and accessing parts of it.


 */
@interface OFURI: OFObject <OFCopying, OFMutableCopying, OFSerialization>
{
	OFString *_scheme;
	OFString *_Nullable _percentEncodedHost;
	OFNumber *_Nullable _port;
	OFString *_Nullable _percentEncodedUser;
	OFString *_Nullable _percentEncodedPassword;
	OFString *_percentEncodedPath;
	OFString *_Nullable _percentEncodedQuery;
	OFString *_Nullable _percentEncodedFragment;
	OF_RESERVE_IVARS(OFURI, 4)
}

/**
 * @brief The scheme part of the URI.
 */
@property (readonly, copy, nonatomic) OFString *scheme;

/**
 * @brief The host part of the URI.
 */
@property OF_NULLABLE_PROPERTY (readonly, copy, nonatomic) OFString *host;

/**
 * @brief The host part of the URI in percent-encoded form.
 */
@property OF_NULLABLE_PROPERTY (readonly, copy, nonatomic)
    OFString *percentEncodedHost;

/**
 * @brief The port part of the URI.
 */
@property OF_NULLABLE_PROPERTY (readonly, copy, nonatomic) OFNumber *port;

/**
 * @brief The user part of the URI.
 */
@property OF_NULLABLE_PROPERTY (readonly, copy, nonatomic) OFString *user;

/**
 * @brief The user part of the URI in percent-encoded form.
 */
@property OF_NULLABLE_PROPERTY (readonly, copy, nonatomic)
    OFString *percentEncodedUser;

/**
 * @brief The password part of the URI.
 */
@property OF_NULLABLE_PROPERTY (readonly, copy, nonatomic) OFString *password;

/**
 * @brief The password part of the URI in percent-encoded form.
 */
@property OF_NULLABLE_PROPERTY (readonly, copy, nonatomic)
    OFString *percentEncodedPassword;

/**
 * @brief The path part of the URI.
 */
@property (readonly, copy, nonatomic) OFString *path;

/**
 * @brief The path part of the URI in percent-encoded form.
 */
@property (readonly, copy, nonatomic) OFString *percentEncodedPath;

/**
 * @brief The path of the URI split into components.
 *
 * The first component must always be `/` to designate the root.
 */
@property (readonly, copy, nonatomic)
    OFArray OF_GENERIC(OFString *) *pathComponents;

/**
 * @brief The last path component of the URI.
 *
 * Returns the empty string if the path is the root.
 */
@property (readonly, copy, nonatomic) OFString *lastPathComponent;

/**
 * @brief The query part of the URI.
 */
@property OF_NULLABLE_PROPERTY (readonly, copy, nonatomic) OFString *query;

/**
 * @brief The query part of the URI in percent-encoded form.
 */
@property OF_NULLABLE_PROPERTY (readonly, copy, nonatomic)
    OFString *percentEncodedQuery;

/**
 * @brief The query part of the URI as an array.
 *
 * For example, a query like `key1=value1&key2=value2` would correspond to the
 * following array:
 *
 *     @[
 *         [OFPair pairWithFirstObject: @"key1" secondObject: @"value1"],
 *         [OFPair pairWithFirstObject: @"key2" secondObject: @"value2"],
 *     ]
 *
 * @throw OFInvalidFormatException The query is not in the correct format
 */
@property OF_NULLABLE_PROPERTY (readonly, copy, nonatomic)
    OFArray OF_GENERIC(OFPair OF_GENERIC(OFString *, OFString *) *) *queryItems;

/**
 * @brief The fragment part of the URI.
 */
@property OF_NULLABLE_PROPERTY (readonly, copy, nonatomic) OFString *fragment;

/**
 * @brief The fragment part of the URI in URI-encoded form.
 */
@property OF_NULLABLE_PROPERTY (readonly, copy, nonatomic)
    OFString *percentEncodedFragment;

/**
 * @brief The URI as a string.
 */
@property (readonly, nonatomic) OFString *string;

/**
 * @brief The URI with relative subpaths resolved.
 */





@property (readonly, nonatomic) OFURI *URIByStandardizingPath;


#ifdef OF_HAVE_FILES
/**
 * @brief The local file system representation for a file URI.
 *
 * @note This only exists for URIs with the file scheme and throws an exception
 *	 otherwise.
 */
@property OF_NULLABLE_PROPERTY (readonly, nonatomic)
    OFString *fileSystemRepresentation;
#endif

/**
 * @brief Creates a new URI with the specified string.
 *
 * @param string A string describing a URI
 * @return A new, autoreleased OFURI
 * @throw OFInvalidFormatException The specified string is not a valid URI
 *				   string
 */
+ (instancetype)URIWithString: (OFString *)string;

/**
 * @brief Creates a new URI with the specified string relative to the
 *	  specified URI.
 *
 * @param string A string describing a relative or absolute URI
 * @param URI An URI to which the string is relative
 * @return A new, autoreleased OFURI
 * @throw OFInvalidFormatException The specified string is not a valid URI
 *				   string
 */
+ (instancetype)URIWithString: (OFString *)string relativeToURI: (OFURI *)URI;

#ifdef OF_HAVE_FILES
/**
 * @brief Creates a new URI with the specified local file path.
 *
 * If a directory exists at the specified path, a slash is appended if there is
 * no slash yet.
 *
 * @param path The local file path
 * @return A new, autoreleased OFURI
 * @throw OFInvalidFormatException The specified path is not a valid path
 */
+ (instancetype)fileURIWithPath: (OFString *)path;

/**
 * @brief Creates a new URI with the specified local file path.
 *
 * @param path The local file path
 * @param isDirectory Whether the path is a directory, in which case a slash is
 *		      appened if there is no slash yet
 * @return An initialized OFURI
 */
+ (instancetype)fileURIWithPath: (OFString *)path
		    isDirectory: (bool)isDirectory;
#endif

/**
 * @brief Initializes an already allocated OFURI with the specified string.
 *
 * @param string A string describing a URI
 * @return An initialized OFURI
 * @throw OFInvalidFormatException The specified string is not a valid URI
 *				   string
 */
- (instancetype)initWithString: (OFString *)string;

/**
 * @brief Initializes an already allocated OFURI with the specified string and
 *	  relative URI.
 *
 * @param string A string describing a relative or absolute URI
 * @param URI A URI to which the string is relative
 * @return An initialized OFURI
 * @throw OFInvalidFormatException The specified string is not a valid URI
 *				   string
 */
- (instancetype)initWithString: (OFString *)string relativeToURI: (OFURI *)URI;

#ifdef OF_HAVE_FILES
/**
 * @brief Initializes an already allocated OFURI with the specified local file
 *	  path.
 *
 * If a directory exists at the specified path, a slash is appended if there is
 * no slash yet.
 *
 * @param path The local file path
 * @return An initialized OFURI
 * @throw OFInvalidFormatException The specified path is not a valid path
 */
- (instancetype)initFileURIWithPath: (OFString *)path;

/**
 * @brief Initializes an already allocated OFURI with the specified local file
 *	  path.
 *
 * @param path The local file path
 * @param isDirectory Whether the path is a directory, in which case a slash is
 *		      appened if there is no slash yet
 * @return An initialized OFURI
 */
- (instancetype)initFileURIWithPath: (OFString *)path
			isDirectory: (bool)isDirectory;
#endif

- (instancetype)init OF_UNAVAILABLE;

/**
 * @brief Returns a new URI with the specified path component appended.
 *
 * If the URI is a file URI, the file system is queried whether the appended
 * component is a directory.
 *
 * @param component The path component to append. If it starts with the slash,
 *		    the component is not appended, but replaces the path
 *		    instead.
 * @return A new URI with the specified path component appended
 */
- (OFURI *)URIByAppendingPathComponent: (OFString *)component;

/**
 * @brief Returns a new URI with the specified path component appended.
 *
 * @param component The path component to append. If it starts with the slash,
 *		    the component is not appended, but replaces the path
 *		    instead.
 * @param isDirectory Whether the appended component is a directory, meaning
 *		      that the URI path should have a trailing slash
 * @return A new URI with the specified path component appended
 */
- (OFURI *)URIByAppendingPathComponent: (OFString *)component
			   isDirectory: (bool)isDirectory;
@end

@interface OFCharacterSet (URICharacterSets)
#ifdef OF_HAVE_CLASS_PROPERTIES
@property (class, readonly, nonatomic)
    OFCharacterSet *URISchemeAllowedCharacterSet;
@property (class, readonly, nonatomic)
    OFCharacterSet *URIHostAllowedCharacterSet;
@property (class, readonly, nonatomic)
    OFCharacterSet *URIUserAllowedCharacterSet;
@property (class, readonly, nonatomic)
    OFCharacterSet *URIPasswordAllowedCharacterSet;
@property (class, readonly, nonatomic)
    OFCharacterSet *URIPathAllowedCharacterSet;
@property (class, readonly, nonatomic)
    OFCharacterSet *URIQueryAllowedCharacterSet;
@property (class, readonly, nonatomic)
    OFCharacterSet *URIQueryKeyValueAllowedCharacterSet;
@property (class, readonly, nonatomic)
    OFCharacterSet *URIFragmentAllowedCharacterSet;
#endif

/**
 * @brief Returns the characters allowed in the scheme part of a URI.
 *
 * @return The characters allowed in the scheme part of a URI.
 */
+ (OFCharacterSet *)URISchemeAllowedCharacterSet;

/**
 * @brief Returns the characters allowed in the host part of a URI.
 *
 * @return The characters allowed in the host part of a URI.
 */
+ (OFCharacterSet *)URIHostAllowedCharacterSet;

/**
 * @brief Returns the characters allowed in the user part of a URI.
 *
 * @return The characters allowed in the user part of a URI.
 */
+ (OFCharacterSet *)URIUserAllowedCharacterSet;

/**
 * @brief Returns the characters allowed in the password part of a URI.
 *
 * @return The characters allowed in the password part of a URI.
 */
+ (OFCharacterSet *)URIPasswordAllowedCharacterSet;

/**
 * @brief Returns the characters allowed in the path part of a URI.
 *
 * @return The characters allowed in the path part of a URI.
 */
+ (OFCharacterSet *)URIPathAllowedCharacterSet;

/**
 * @brief Returns the characters allowed in the query part of a URI.
 *
 * @return The characters allowed in the query part of a URI.
 */
+ (OFCharacterSet *)URIQueryAllowedCharacterSet;

/**
 * @brief Returns the characters allowed in a key/value in the query part of a
 *	  URI.
 *
 * @return The characters allowed in a key/value in the query part of a URI.
 */
+ (OFCharacterSet *)URIQueryKeyValueAllowedCharacterSet;

/**
 * @brief Returns the characters allowed in the fragment part of a URI.
 *
 * @return The characters allowed in the fragment part of a URI.
 */
+ (OFCharacterSet *)URIFragmentAllowedCharacterSet;
@end

#ifdef __cplusplus
extern "C" {
#endif
extern bool OFURIIsIPv6Host(OFString *host);
extern void OFURIVerifyIsEscaped(OFString *, OFCharacterSet *, bool);
#ifdef __cplusplus
}
#endif

OF_ASSUME_NONNULL_END

#import "OFMutableURI.h"

|















<










|

>
|
>
>

|









|



|




|




|





|




|




|





|




|





|




|




|







|






|




|





|















|




|





|




|

>
>
>
>
>
|
>



|

|







|

|
|
|


|


|
|

|
|
|
|


|



|





|


|


|




|

|




|

|
|
|





|
|

|
|
|
|


|



|






|


|


|





|

|






|

|





|

|


|





|
|

|



|


|

|

|

|

|

|

|

|



|

|

|


|

|

|


|

|

|


|

|

|


|

|

|


|

|

|



|

|

|


|

|

|





|
|






|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
/*
 * Copyright (c) 2008-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 "OFObject.h"
#import "OFCharacterSet.h"


OF_ASSUME_NONNULL_BEGIN

@class OFArray OF_GENERIC(ObjectType);
@class OFDictionary OF_GENERIC(KeyType, ObjectType);
@class OFNumber;
@class OFPair OF_GENERIC(FirstType, SecondType);
@class OFString;

/**
 * @class OFIRI OFIRI.h ObjFW/OFIRI.h
 *
 * @brief A class for representing IRIs, URIs, URLs and URNs, for parsing them
 *	  as well as accessing parts of them.
 *
 * This class follows RFC 3976 and RFC 3987.
 */
@interface OFIRI: OFObject <OFCopying, OFMutableCopying>
{
	OFString *_scheme;
	OFString *_Nullable _percentEncodedHost;
	OFNumber *_Nullable _port;
	OFString *_Nullable _percentEncodedUser;
	OFString *_Nullable _percentEncodedPassword;
	OFString *_percentEncodedPath;
	OFString *_Nullable _percentEncodedQuery;
	OFString *_Nullable _percentEncodedFragment;
	OF_RESERVE_IVARS(OFIRI, 4)
}

/**
 * @brief The scheme part of the IRI.
 */
@property (readonly, copy, nonatomic) OFString *scheme;

/**
 * @brief The host part of the IRI.
 */
@property OF_NULLABLE_PROPERTY (readonly, copy, nonatomic) OFString *host;

/**
 * @brief The host part of the IRI in percent-encoded form.
 */
@property OF_NULLABLE_PROPERTY (readonly, copy, nonatomic)
    OFString *percentEncodedHost;

/**
 * @brief The port part of the IRI.
 */
@property OF_NULLABLE_PROPERTY (readonly, copy, nonatomic) OFNumber *port;

/**
 * @brief The user part of the IRI.
 */
@property OF_NULLABLE_PROPERTY (readonly, copy, nonatomic) OFString *user;

/**
 * @brief The user part of the IRI in percent-encoded form.
 */
@property OF_NULLABLE_PROPERTY (readonly, copy, nonatomic)
    OFString *percentEncodedUser;

/**
 * @brief The password part of the IRI.
 */
@property OF_NULLABLE_PROPERTY (readonly, copy, nonatomic) OFString *password;

/**
 * @brief The password part of the IRI in percent-encoded form.
 */
@property OF_NULLABLE_PROPERTY (readonly, copy, nonatomic)
    OFString *percentEncodedPassword;

/**
 * @brief The path part of the IRI.
 */
@property (readonly, copy, nonatomic) OFString *path;

/**
 * @brief The path part of the IRI in percent-encoded form.
 */
@property (readonly, copy, nonatomic) OFString *percentEncodedPath;

/**
 * @brief The path of the IRI split into components.
 *
 * The first component must always be `/` to designate the root.
 */
@property (readonly, copy, nonatomic)
    OFArray OF_GENERIC(OFString *) *pathComponents;

/**
 * @brief The last path component of the IRI.
 *
 * Returns the empty string if the path is the root.
 */
@property (readonly, copy, nonatomic) OFString *lastPathComponent;

/**
 * @brief The query part of the IRI.
 */
@property OF_NULLABLE_PROPERTY (readonly, copy, nonatomic) OFString *query;

/**
 * @brief The query part of the IRI in percent-encoded form.
 */
@property OF_NULLABLE_PROPERTY (readonly, copy, nonatomic)
    OFString *percentEncodedQuery;

/**
 * @brief The query part of the IRI as an array.
 *
 * For example, a query like `key1=value1&key2=value2` would correspond to the
 * following array:
 *
 *     @[
 *         [OFPair pairWithFirstObject: @"key1" secondObject: @"value1"],
 *         [OFPair pairWithFirstObject: @"key2" secondObject: @"value2"],
 *     ]
 *
 * @throw OFInvalidFormatException The query is not in the correct format
 */
@property OF_NULLABLE_PROPERTY (readonly, copy, nonatomic)
    OFArray OF_GENERIC(OFPair OF_GENERIC(OFString *, OFString *) *) *queryItems;

/**
 * @brief The fragment part of the IRI.
 */
@property OF_NULLABLE_PROPERTY (readonly, copy, nonatomic) OFString *fragment;

/**
 * @brief The fragment part of the IRI in percent-encoded form.
 */
@property OF_NULLABLE_PROPERTY (readonly, copy, nonatomic)
    OFString *percentEncodedFragment;

/**
 * @brief The IRI as a string.
 */
@property (readonly, nonatomic) OFString *string;

/**
 * @brief The IRI with relative subpaths resolved.
 */
@property (readonly, nonatomic) OFIRI *IRIByStandardizingPath;

/**
 * @brief The IRI with percent-encoding added for all Unicode characters.
 */
@property (readonly, nonatomic)
    OFIRI *IRIByAddingPercentEncodingForUnicodeCharacters;

#ifdef OF_HAVE_FILES
/**
 * @brief The local file system representation for a file IRI.
 *
 * @note This only exists for IRIs with the file scheme and throws an exception
 *	 otherwise.
 */
@property OF_NULLABLE_PROPERTY (readonly, nonatomic)
    OFString *fileSystemRepresentation;
#endif

/**
 * @brief Creates a new IRI with the specified string.
 *
 * @param string A string describing an IRI
 * @return A new, autoreleased OFIRI
 * @throw OFInvalidFormatException The specified string is not a valid IRI
 *				   string
 */
+ (instancetype)IRIWithString: (OFString *)string;

/**
 * @brief Creates a new IRI with the specified string relative to the
 *	  specified IRI.
 *
 * @param string A string describing a relative or absolute IRI
 * @param IRI An IRI to which the string is relative
 * @return A new, autoreleased OFIRI
 * @throw OFInvalidFormatException The specified string is not a valid IRI
 *				   string
 */
+ (instancetype)IRIWithString: (OFString *)string relativeToIRI: (OFIRI *)IRI;

#ifdef OF_HAVE_FILES
/**
 * @brief Creates a new IRI with the specified local file path.
 *
 * If a directory exists at the specified path, a slash is appended if there is
 * no slash yet.
 *
 * @param path The local file path
 * @return A new, autoreleased OFIRI
 * @throw OFInvalidFormatException The specified path is not a valid path
 */
+ (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

/**
 * @brief Initializes an already allocated OFIRI with the specified string.
 *
 * @param string A string describing an IRI
 * @return An initialized OFIRI
 * @throw OFInvalidFormatException The specified string is not a valid IRI
 *				   string
 */
- (instancetype)initWithString: (OFString *)string;

/**
 * @brief Initializes an already allocated OFIRI with the specified string and
 *	  relative IRI.
 *
 * @param string A string describing a relative or absolute IRI
 * @param IRI An IRI to which the string is relative
 * @return An initialized OFIRI
 * @throw OFInvalidFormatException The specified string is not a valid IRI
 *				   string
 */
- (instancetype)initWithString: (OFString *)string relativeToIRI: (OFIRI *)IRI;

#ifdef OF_HAVE_FILES
/**
 * @brief Initializes an already allocated OFIRI with the specified local file
 *	  path.
 *
 * If a directory exists at the specified path, a slash is appended if there is
 * no slash yet.
 *
 * @param path The local file path
 * @return An initialized OFIRI
 * @throw OFInvalidFormatException The specified path is not a valid path
 */
- (instancetype)initFileIRIWithPath: (OFString *)path;

/**
 * @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;

/**
 * @brief Returns a new IRI with the specified path component appended.
 *
 * If the IRI is a file IRI, the file system is queried whether the appended
 * component is a directory.
 *
 * @param component The path component to append. If it starts with the slash,
 *		    the component is not appended, but replaces the path
 *		    instead.
 * @return A new IRI with the specified path component appended
 */
- (OFIRI *)IRIByAppendingPathComponent: (OFString *)component;

/**
 * @brief Returns a new IRI with the specified path component appended.
 *
 * @param component The path component to append. If it starts with the slash,
 *		    the component is not appended, but replaces the path
 *		    instead.
 * @param isDirectory Whether the appended component is a directory, meaning
 *		      that the IRI path should have a trailing slash
 * @return A new IRI with the specified path component appended
 */
- (OFIRI *)IRIByAppendingPathComponent: (OFString *)component
			   isDirectory: (bool)isDirectory;
@end

@interface OFCharacterSet (IRICharacterSets)
#ifdef OF_HAVE_CLASS_PROPERTIES
@property (class, readonly, nonatomic)
    OFCharacterSet *IRISchemeAllowedCharacterSet;
@property (class, readonly, nonatomic)
    OFCharacterSet *IRIHostAllowedCharacterSet;
@property (class, readonly, nonatomic)
    OFCharacterSet *IRIUserAllowedCharacterSet;
@property (class, readonly, nonatomic)
    OFCharacterSet *IRIPasswordAllowedCharacterSet;
@property (class, readonly, nonatomic)
    OFCharacterSet *IRIPathAllowedCharacterSet;
@property (class, readonly, nonatomic)
    OFCharacterSet *IRIQueryAllowedCharacterSet;
@property (class, readonly, nonatomic)
    OFCharacterSet *IRIQueryKeyValueAllowedCharacterSet;
@property (class, readonly, nonatomic)
    OFCharacterSet *IRIFragmentAllowedCharacterSet;
#endif

/**
 * @brief Returns the characters allowed in the scheme part of an IRI.
 *
 * @return The characters allowed in the scheme part of an IRI.
 */
+ (OFCharacterSet *)IRISchemeAllowedCharacterSet;

/**
 * @brief Returns the characters allowed in the host part of an IRI.
 *
 * @return The characters allowed in the host part of an IRI.
 */
+ (OFCharacterSet *)IRIHostAllowedCharacterSet;

/**
 * @brief Returns the characters allowed in the user part of an IRI.
 *
 * @return The characters allowed in the user part of an IRI.
 */
+ (OFCharacterSet *)IRIUserAllowedCharacterSet;

/**
 * @brief Returns the characters allowed in the password part of an IRI.
 *
 * @return The characters allowed in the password part of an IRI.
 */
+ (OFCharacterSet *)IRIPasswordAllowedCharacterSet;

/**
 * @brief Returns the characters allowed in the path part of an IRI.
 *
 * @return The characters allowed in the path part of an IRI.
 */
+ (OFCharacterSet *)IRIPathAllowedCharacterSet;

/**
 * @brief Returns the characters allowed in the query part of an IRI.
 *
 * @return The characters allowed in the query part of an IRI.
 */
+ (OFCharacterSet *)IRIQueryAllowedCharacterSet;

/**
 * @brief Returns the characters allowed in a key/value in the query part of a
 *	  IRI.
 *
 * @return The characters allowed in a key/value in the query part of an IRI.
 */
+ (OFCharacterSet *)IRIQueryKeyValueAllowedCharacterSet;

/**
 * @brief Returns the characters allowed in the fragment part of an IRI.
 *
 * @return The characters allowed in the fragment part of an IRI.
 */
+ (OFCharacterSet *)IRIFragmentAllowedCharacterSet;
@end

#ifdef __cplusplus
extern "C" {
#endif
extern bool OFIRIIsIPv6Host(OFString *host);
extern void OFIRIVerifyIsEscaped(OFString *, OFCharacterSet *, bool);
#ifdef __cplusplus
}
#endif

OF_ASSUME_NONNULL_END

#import "OFMutableIRI.h"

Renamed and modified src/OFURI.m [fd812a6a57] to src/OFIRI.m [0bb8a821c7].

1
2
3
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
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#include <stdlib.h>
#include <string.h>

#import "OFURI.h"
#import "OFArray.h"
#import "OFDictionary.h"
#ifdef OF_HAVE_FILES
# import "OFFileManager.h"
# import "OFFileURIHandler.h"
#endif
#import "OFNumber.h"
#import "OFOnce.h"
#import "OFPair.h"
#import "OFString.h"
#import "OFXMLElement.h"

#import "OFInvalidArgumentException.h"
#import "OFInvalidFormatException.h"
#import "OFOutOfMemoryException.h"

@interface OFURIAllowedCharacterSetBase: OFCharacterSet
@end

@interface OFURIAllowedCharacterSet: OFURIAllowedCharacterSetBase
@end

@interface OFURISchemeAllowedCharacterSet: OFURIAllowedCharacterSetBase
@end

@interface OFURIPathAllowedCharacterSet: OFURIAllowedCharacterSetBase
@end

@interface OFURIQueryOrFragmentAllowedCharacterSet: OFURIAllowedCharacterSetBase
@end

@interface OFURIQueryKeyValueAllowedCharacterSet: OFURIAllowedCharacterSetBase



@end

OF_DIRECT_MEMBERS
@interface OFInvertedCharacterSetWithoutPercent: OFCharacterSet
{
	OFCharacterSet *_characterSet;
	bool (*_characterIsMember)(id, SEL, OFUnichar);
}

- (instancetype)initWithCharacterSet: (OFCharacterSet *)characterSet;
@end

static OFCharacterSet *URIAllowedCharacterSet = nil;
static OFCharacterSet *URISchemeAllowedCharacterSet = nil;
static OFCharacterSet *URIPathAllowedCharacterSet = nil;
static OFCharacterSet *URIQueryOrFragmentAllowedCharacterSet = nil;
static OFCharacterSet *URIQueryKeyValueAllowedCharacterSet = nil;


static OFOnceControl URIAllowedCharacterSetOnce = OFOnceControlInitValue;
static OFOnceControl URIQueryOrFragmentAllowedCharacterSetOnce =
    OFOnceControlInitValue;

static void
initURIAllowedCharacterSet(void)
{
	URIAllowedCharacterSet = [[OFURIAllowedCharacterSet alloc] init];
}

static void
initURISchemeAllowedCharacterSet(void)
{
	URISchemeAllowedCharacterSet =
	    [[OFURISchemeAllowedCharacterSet alloc] init];
}

static void
initURIPathAllowedCharacterSet(void)
{
	URIPathAllowedCharacterSet =
	    [[OFURIPathAllowedCharacterSet alloc] init];
}

static void
initURIQueryOrFragmentAllowedCharacterSet(void)
{
	URIQueryOrFragmentAllowedCharacterSet =
	    [[OFURIQueryOrFragmentAllowedCharacterSet alloc] init];
}

static void
initURIQueryKeyValueAllowedCharacterSet(void)
{
	URIQueryKeyValueAllowedCharacterSet =
	    [[OFURIQueryKeyValueAllowedCharacterSet alloc] init];
}








bool
OFURIIsIPv6Host(OFString *host)
{
	const char *UTF8String = host.UTF8String;
	bool hasColon = false;

	while (*UTF8String != '\0') {
		if (!OFASCIIIsDigit(*UTF8String) && *UTF8String != ':' &&
		    (*UTF8String < 'a' || *UTF8String > 'f') &&
		    (*UTF8String < 'A' || *UTF8String > 'F'))
			return false;

		if (*UTF8String == ':')
			hasColon = true;

		UTF8String++;
	}

	return hasColon;
}


@implementation OFURIAllowedCharacterSetBase
- (instancetype)autorelease
{

	return self;
}

- (instancetype)retain






























{
	return self;
}

- (void)release


{
}

- (unsigned int)retainCount




{
	return OFMaxRetainCount;
}



@end

@implementation OFURIAllowedCharacterSet
- (bool)characterIsMember: (OFUnichar)character
{
	if (character < CHAR_MAX && OFASCIIIsAlnum(character))
		return true;




	switch (character) {
	case '-':
	case '.':
	case '_':
	case '~':
	case '!':

|


















|




|





<





|


|


|


|


|


|
>
>
>












|
|
|
|
|
>

|
<
<


|

|



|

|
|



|

|
|



|

|
|



|

|
|


>
>
>
>
>
>
>

|



















>
|
<

>
|
<
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|


<
>
>

<
|
|
>
>
>
>
|
|

>
>
>


|




>
>
>







1
2
3
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
/*
 * 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 <stdlib.h>
#include <string.h>

#import "OFIRI.h"
#import "OFArray.h"
#import "OFDictionary.h"
#ifdef OF_HAVE_FILES
# import "OFFileManager.h"
# import "OFFileIRIHandler.h"
#endif
#import "OFNumber.h"
#import "OFOnce.h"
#import "OFPair.h"
#import "OFString.h"


#import "OFInvalidArgumentException.h"
#import "OFInvalidFormatException.h"
#import "OFOutOfMemoryException.h"

@interface OFIRIAllowedCharacterSetBase: OFCharacterSet
@end

@interface OFIRIAllowedCharacterSet: OFIRIAllowedCharacterSetBase
@end

@interface OFIRISchemeAllowedCharacterSet: OFIRIAllowedCharacterSetBase
@end

@interface OFIRIPathAllowedCharacterSet: OFIRIAllowedCharacterSetBase
@end

@interface OFIRIQueryAllowedCharacterSet: OFIRIAllowedCharacterSetBase
@end

@interface OFIRIQueryKeyValueAllowedCharacterSet: OFIRIAllowedCharacterSetBase
@end

@interface OFIRIFragmentAllowedCharacterSet: OFIRIAllowedCharacterSetBase
@end

OF_DIRECT_MEMBERS
@interface OFInvertedCharacterSetWithoutPercent: OFCharacterSet
{
	OFCharacterSet *_characterSet;
	bool (*_characterIsMember)(id, SEL, OFUnichar);
}

- (instancetype)initWithCharacterSet: (OFCharacterSet *)characterSet;
@end

static OFCharacterSet *IRIAllowedCharacterSet = nil;
static OFCharacterSet *IRISchemeAllowedCharacterSet = nil;
static OFCharacterSet *IRIPathAllowedCharacterSet = nil;
static OFCharacterSet *IRIQueryAllowedCharacterSet = nil;
static OFCharacterSet *IRIQueryKeyValueAllowedCharacterSet = nil;
static OFCharacterSet *IRIFragmentAllowedCharacterSet = nil;

static OFOnceControl IRIAllowedCharacterSetOnce = OFOnceControlInitValue;



static void
initIRIAllowedCharacterSet(void)
{
	IRIAllowedCharacterSet = [[OFIRIAllowedCharacterSet alloc] init];
}

static void
initIRISchemeAllowedCharacterSet(void)
{
	IRISchemeAllowedCharacterSet =
	    [[OFIRISchemeAllowedCharacterSet alloc] init];
}

static void
initIRIPathAllowedCharacterSet(void)
{
	IRIPathAllowedCharacterSet =
	    [[OFIRIPathAllowedCharacterSet alloc] init];
}

static void
initIRIQueryAllowedCharacterSet(void)
{
	IRIQueryAllowedCharacterSet =
	    [[OFIRIQueryAllowedCharacterSet alloc] init];
}

static void
initIRIQueryKeyValueAllowedCharacterSet(void)
{
	IRIQueryKeyValueAllowedCharacterSet =
	    [[OFIRIQueryKeyValueAllowedCharacterSet alloc] init];
}

static void
initIRIFragmentAllowedCharacterSet(void)
{
	IRIFragmentAllowedCharacterSet =
	    [[OFIRIFragmentAllowedCharacterSet alloc] init];
}

bool
OFIRIIsIPv6Host(OFString *host)
{
	const char *UTF8String = host.UTF8String;
	bool hasColon = false;

	while (*UTF8String != '\0') {
		if (!OFASCIIIsDigit(*UTF8String) && *UTF8String != ':' &&
		    (*UTF8String < 'a' || *UTF8String > 'f') &&
		    (*UTF8String < 'A' || *UTF8String > 'F'))
			return false;

		if (*UTF8String == ':')
			hasColon = true;

		UTF8String++;
	}

	return hasColon;
}

static bool
isUnicode(OFUnichar character)

{
	if (character >= 0xA0 && character <= 0xD7FF)
		return true;

	if (character >= 0xF900 && character <= 0xFDCF)
		return true;
	if (character >= 0xFDF0 && character <= 0xFFEF)
		return true;
	if (character >= 0x10000 && character <= 0x1FFFD)
		return true;
	if (character >= 0x20000 && character <= 0x2FFFD)
		return true;
	if (character >= 0x30000 && character <= 0x3FFFD)
		return true;
	if (character >= 0x40000 && character <= 0x4FFFD)
		return true;
	if (character >= 0x50000 && character <= 0x5FFFD)
		return true;
	if (character >= 0x60000 && character <= 0x6FFFD)
		return true;
	if (character >= 0x70000 && character <= 0x7FFFD)
		return true;
	if (character >= 0x80000 && character <= 0x8FFFD)
		return true;
	if (character >= 0x90000 && character <= 0x9FFFD)
		return true;
	if (character >= 0xA0000 && character <= 0xAFFFD)
		return true;
	if (character >= 0xB0000 && character <= 0xBFFFD)
		return true;
	if (character >= 0xC0000 && character <= 0xCFFFD)
		return true;
	if (character >= 0xD0000 && character <= 0xDFFFD)
		return true;
	if (character >= 0xE0000 && character <= 0xEFFFD)
		return true;

	return false;
}


static bool
isUnicodePrivate(OFUnichar character)
{

	if (character >= 0xE00 && character <= 0xF8FF)
		return true;
	if (character >= 0xF0000 && character <= 0xFFFFD)
		return true;
	if (character >= 0x100000 && character <= 0x10FFFD)
		return true;

	return false;
}

@implementation OFIRIAllowedCharacterSetBase
OF_SINGLETON_METHODS
@end

@implementation OFIRIAllowedCharacterSet
- (bool)characterIsMember: (OFUnichar)character
{
	if (character < CHAR_MAX && OFASCIIIsAlnum(character))
		return true;

	if (isUnicode(character))
		return true;

	switch (character) {
	case '-':
	case '.':
	case '_':
	case '~':
	case '!':
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202



203
204
205
206
207
208
209
		return true;
	default:
		return false;
	}
}
@end

@implementation OFURISchemeAllowedCharacterSet
- (bool)characterIsMember: (OFUnichar)character
{
	if (character < CHAR_MAX && OFASCIIIsAlnum(character))
		return true;

	switch (character) {
	case '+':
	case '-':
	case '.':
		return true;
	default:
		return false;
	}
}
@end

@implementation OFURIPathAllowedCharacterSet
- (bool)characterIsMember: (OFUnichar)character
{
	if (character < CHAR_MAX && OFASCIIIsAlnum(character))
		return true;




	switch (character) {
	case '-':
	case '.':
	case '_':
	case '~':
	case '!':







|
















|




>
>
>







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
		return true;
	default:
		return false;
	}
}
@end

@implementation OFIRISchemeAllowedCharacterSet
- (bool)characterIsMember: (OFUnichar)character
{
	if (character < CHAR_MAX && OFASCIIIsAlnum(character))
		return true;

	switch (character) {
	case '+':
	case '-':
	case '.':
		return true;
	default:
		return false;
	}
}
@end

@implementation OFIRIPathAllowedCharacterSet
- (bool)characterIsMember: (OFUnichar)character
{
	if (character < CHAR_MAX && OFASCIIIsAlnum(character))
		return true;

	if (isUnicode(character))
		return true;

	switch (character) {
	case '-':
	case '.':
	case '_':
	case '~':
	case '!':
223
224
225
226
227
228
229
230
231
232
233
234



235
236
237
238
239
240
241
		return true;
	default:
		return false;
	}
}
@end

@implementation OFURIQueryOrFragmentAllowedCharacterSet
- (bool)characterIsMember: (OFUnichar)character
{
	if (character < CHAR_MAX && OFASCIIIsAlnum(character))
		return true;




	switch (character) {
	case '-':
	case '.':
	case '_':
	case '~':
	case '!':







|




>
>
>







274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
		return true;
	default:
		return false;
	}
}
@end

@implementation OFIRIQueryAllowedCharacterSet
- (bool)characterIsMember: (OFUnichar)character
{
	if (character < CHAR_MAX && OFASCIIIsAlnum(character))
		return true;

	if (isUnicode(character) || isUnicodePrivate(character))
		return true;

	switch (character) {
	case '-':
	case '.':
	case '_':
	case '~':
	case '!':
256
257
258
259
260
261
262
263
264
265
266
267





































268
269
270
271
272
273
274
275

276
277
278
279
280
281
282

283
284
285
286
287
288
289
		return true;
	default:
		return false;
	}
}
@end

@implementation OFURIQueryKeyValueAllowedCharacterSet
- (bool)characterIsMember: (OFUnichar)character
{
	if (character < CHAR_MAX && OFASCIIIsAlnum(character))
		return true;






































	switch (character) {
	case '-':
	case '.':
	case '_':
	case '~':
	case '!':
	case '$':

	case '\'':
	case '(':
	case ')':
	case '*':
	case '+':
	case ',':
	case ';':

	case ':':
	case '@':
	case '/':
	case '?':
		return true;
	default:
		return false;







|




>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>








>







>







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
		return true;
	default:
		return false;
	}
}
@end

@implementation OFIRIQueryKeyValueAllowedCharacterSet
- (bool)characterIsMember: (OFUnichar)character
{
	if (character < CHAR_MAX && OFASCIIIsAlnum(character))
		return true;

	if (isUnicode(character) || isUnicodePrivate(character))
		return true;

	switch (character) {
	case '-':
	case '.':
	case '_':
	case '~':
	case '!':
	case '$':
	case '\'':
	case '(':
	case ')':
	case '*':
	case '+':
	case ',':
	case ';':
	case ':':
	case '@':
	case '/':
	case '?':
		return true;
	default:
		return false;
	}
}
@end

@implementation OFIRIFragmentAllowedCharacterSet
- (bool)characterIsMember: (OFUnichar)character
{
	if (character < CHAR_MAX && OFASCIIIsAlnum(character))
		return true;

	if (isUnicode(character))
		return true;

	switch (character) {
	case '-':
	case '.':
	case '_':
	case '~':
	case '!':
	case '$':
	case '&':
	case '\'':
	case '(':
	case ')':
	case '*':
	case '+':
	case ',':
	case ';':
	case '=':
	case ':':
	case '@':
	case '/':
	case '?':
		return true;
	default:
		return false;
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
{
	return (character != '%' && !_characterIsMember(_characterSet,
	    @selector(characterIsMember:), character));
}
@end

void
OFURIVerifyIsEscaped(OFString *string, OFCharacterSet *characterSet,
    bool allowPercent)
{
	void *pool = objc_autoreleasePoolPush();

	if (allowPercent)
		characterSet = [[[OFInvertedCharacterSetWithoutPercent alloc]
		    initWithCharacterSet: characterSet] autorelease];
	else
		characterSet = characterSet.invertedSet;

	if ([string indexOfCharacterFromSet: characterSet] != OFNotFound)
		@throw [OFInvalidFormatException exception];

	objc_autoreleasePoolPop(pool);
}

@implementation OFCharacterSet (URICharacterSets)
+ (OFCharacterSet *)URISchemeAllowedCharacterSet
{
	static OFOnceControl onceControl = OFOnceControlInitValue;
	OFOnce(&onceControl, initURISchemeAllowedCharacterSet);

	return URISchemeAllowedCharacterSet;
}

+ (OFCharacterSet *)URIHostAllowedCharacterSet
{
	OFOnce(&URIAllowedCharacterSetOnce, initURIAllowedCharacterSet);

	return URIAllowedCharacterSet;
}

+ (OFCharacterSet *)URIUserAllowedCharacterSet
{
	OFOnce(&URIAllowedCharacterSetOnce, initURIAllowedCharacterSet);

	return URIAllowedCharacterSet;
}

+ (OFCharacterSet *)URIPasswordAllowedCharacterSet
{
	OFOnce(&URIAllowedCharacterSetOnce, initURIAllowedCharacterSet);

	return URIAllowedCharacterSet;
}

+ (OFCharacterSet *)URIPathAllowedCharacterSet
{
	static OFOnceControl onceControl = OFOnceControlInitValue;
	OFOnce(&onceControl, initURIPathAllowedCharacterSet);

	return URIPathAllowedCharacterSet;
}

+ (OFCharacterSet *)URIQueryAllowedCharacterSet
{
	OFOnce(&URIQueryOrFragmentAllowedCharacterSetOnce,
	    initURIQueryOrFragmentAllowedCharacterSet);

	return URIQueryOrFragmentAllowedCharacterSet;
}

+ (OFCharacterSet *)URIQueryKeyValueAllowedCharacterSet
{
	static OFOnceControl onceControl = OFOnceControlInitValue;
	OFOnce(&onceControl, initURIQueryKeyValueAllowedCharacterSet);

	return URIQueryKeyValueAllowedCharacterSet;
}

+ (OFCharacterSet *)URIFragmentAllowedCharacterSet
{
	OFOnce(&URIQueryOrFragmentAllowedCharacterSetOnce,
	    initURIQueryOrFragmentAllowedCharacterSet);

	return URIQueryOrFragmentAllowedCharacterSet;
}
@end

@implementation OFURI
+ (instancetype)URI
{
	return [[[self alloc] init] autorelease];
}

+ (instancetype)URIWithString: (OFString *)string
{
	return [[[self alloc] initWithString: string] autorelease];
}

+ (instancetype)URIWithString: (OFString *)string
		relativeToURI: (OFURI *)URI
{
	return [[[self alloc] initWithString: string
			       relativeToURI: URI] autorelease];
}

#ifdef OF_HAVE_FILES
+ (instancetype)fileURIWithPath: (OFString *)path
{
	return [[[self alloc] initFileURIWithPath: path] autorelease];
}

+ (instancetype)fileURIWithPath: (OFString *)path
		    isDirectory: (bool)isDirectory
{
	return [[[self alloc] initFileURIWithPath: path
				      isDirectory: isDirectory] autorelease];
}
#endif

static void
parseUserInfo(OFURI *self, const char *UTF8String, size_t length)
{
	const char *colon;

	if ((colon = memchr(UTF8String, ':', length)) != NULL) {
		self->_percentEncodedUser = [[OFString alloc]
		    initWithUTF8String: UTF8String
				length: colon - UTF8String];
		self->_percentEncodedPassword = [[OFString alloc]
		    initWithUTF8String: colon + 1
				length: length - (colon - UTF8String) - 1];

		OFURIVerifyIsEscaped(self->_percentEncodedPassword,
		    [OFCharacterSet URIPasswordAllowedCharacterSet], true);
	} else
		self->_percentEncodedUser = [[OFString alloc]
		    initWithUTF8String: UTF8String
				length: length];

	OFURIVerifyIsEscaped(self->_percentEncodedUser,
	    [OFCharacterSet URIUserAllowedCharacterSet], true);
}

static void
parseHostPort(OFURI *self, const char *UTF8String, size_t length)
{
	OFString *portString;

	if (*UTF8String == '[') {
		const char *end = memchr(UTF8String, ']', length);

		if (end == NULL)







|
















|
|


|

|


|

|

|


|

|

|


|

|

|


|


|

|


|

|
|

|


|


|

|


|

|
|

|



|
|




|




|
<


|



|

|


<
|

|





|











|
|





|
|



|







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
{
	return (character != '%' && !_characterIsMember(_characterSet,
	    @selector(characterIsMember:), character));
}
@end

void
OFIRIVerifyIsEscaped(OFString *string, OFCharacterSet *characterSet,
    bool allowPercent)
{
	void *pool = objc_autoreleasePoolPush();

	if (allowPercent)
		characterSet = [[[OFInvertedCharacterSetWithoutPercent alloc]
		    initWithCharacterSet: characterSet] autorelease];
	else
		characterSet = characterSet.invertedSet;

	if ([string indexOfCharacterFromSet: characterSet] != OFNotFound)
		@throw [OFInvalidFormatException exception];

	objc_autoreleasePoolPop(pool);
}

@implementation OFCharacterSet (IRICharacterSets)
+ (OFCharacterSet *)IRISchemeAllowedCharacterSet
{
	static OFOnceControl onceControl = OFOnceControlInitValue;
	OFOnce(&onceControl, initIRISchemeAllowedCharacterSet);

	return IRISchemeAllowedCharacterSet;
}

+ (OFCharacterSet *)IRIHostAllowedCharacterSet
{
	OFOnce(&IRIAllowedCharacterSetOnce, initIRIAllowedCharacterSet);

	return IRIAllowedCharacterSet;
}

+ (OFCharacterSet *)IRIUserAllowedCharacterSet
{
	OFOnce(&IRIAllowedCharacterSetOnce, initIRIAllowedCharacterSet);

	return IRIAllowedCharacterSet;
}

+ (OFCharacterSet *)IRIPasswordAllowedCharacterSet
{
	OFOnce(&IRIAllowedCharacterSetOnce, initIRIAllowedCharacterSet);

	return IRIAllowedCharacterSet;
}

+ (OFCharacterSet *)IRIPathAllowedCharacterSet
{
	static OFOnceControl onceControl = OFOnceControlInitValue;
	OFOnce(&onceControl, initIRIPathAllowedCharacterSet);

	return IRIPathAllowedCharacterSet;
}

+ (OFCharacterSet *)IRIQueryAllowedCharacterSet
{
	static OFOnceControl onceControl = OFOnceControlInitValue;
	OFOnce(&onceControl, initIRIQueryAllowedCharacterSet);

	return IRIQueryAllowedCharacterSet;
}

+ (OFCharacterSet *)IRIQueryKeyValueAllowedCharacterSet
{
	static OFOnceControl onceControl = OFOnceControlInitValue;
	OFOnce(&onceControl, initIRIQueryKeyValueAllowedCharacterSet);

	return IRIQueryKeyValueAllowedCharacterSet;
}

+ (OFCharacterSet *)IRIFragmentAllowedCharacterSet
{
	static OFOnceControl onceControl = OFOnceControlInitValue;
	OFOnce(&onceControl, initIRIFragmentAllowedCharacterSet);

	return IRIFragmentAllowedCharacterSet;
}
@end

@implementation OFIRI
+ (instancetype)IRI
{
	return [[[self alloc] init] autorelease];
}

+ (instancetype)IRIWithString: (OFString *)string
{
	return [[[self alloc] initWithString: string] autorelease];
}

+ (instancetype)IRIWithString: (OFString *)string relativeToIRI: (OFIRI *)IRI

{
	return [[[self alloc] initWithString: string
			       relativeToIRI: IRI] autorelease];
}

#ifdef OF_HAVE_FILES
+ (instancetype)fileIRIWithPath: (OFString *)path
{
	return [[[self alloc] initFileIRIWithPath: path] autorelease];
}


+ (instancetype)fileIRIWithPath: (OFString *)path isDirectory: (bool)isDirectory
{
	return [[[self alloc] initFileIRIWithPath: path
				      isDirectory: isDirectory] autorelease];
}
#endif

static void
parseUserInfo(OFIRI *self, const char *UTF8String, size_t length)
{
	const char *colon;

	if ((colon = memchr(UTF8String, ':', length)) != NULL) {
		self->_percentEncodedUser = [[OFString alloc]
		    initWithUTF8String: UTF8String
				length: colon - UTF8String];
		self->_percentEncodedPassword = [[OFString alloc]
		    initWithUTF8String: colon + 1
				length: length - (colon - UTF8String) - 1];

		OFIRIVerifyIsEscaped(self->_percentEncodedPassword,
		    [OFCharacterSet IRIPasswordAllowedCharacterSet], true);
	} else
		self->_percentEncodedUser = [[OFString alloc]
		    initWithUTF8String: UTF8String
				length: length];

	OFIRIVerifyIsEscaped(self->_percentEncodedUser,
	    [OFCharacterSet IRIUserAllowedCharacterSet], true);
}

static void
parseHostPort(OFIRI *self, const char *UTF8String, size_t length)
{
	OFString *portString;

	if (*UTF8String == '[') {
		const char *end = memchr(UTF8String, ']', length);

		if (end == NULL)
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
			    initWithUTF8String: UTF8String
					length: length];

			UTF8String += length;
			length = 0;
		}

		OFURIVerifyIsEscaped(self->_percentEncodedHost,
		    [OFCharacterSet URIHostAllowedCharacterSet], true);
	}

	if (length == 0)
		return;

	if (length <= 1 || *UTF8String != ':')
		@throw [OFInvalidFormatException exception];







|
|







589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
			    initWithUTF8String: UTF8String
					length: length];

			UTF8String += length;
			length = 0;
		}

		OFIRIVerifyIsEscaped(self->_percentEncodedHost,
		    [OFCharacterSet IRIHostAllowedCharacterSet], true);
	}

	if (length == 0)
		return;

	if (length <= 1 || *UTF8String != ':')
		@throw [OFInvalidFormatException exception];
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
		@throw [OFInvalidFormatException exception];

	self->_port = [[OFNumber alloc] initWithUnsignedShort:
	    (unsigned short)portString.unsignedLongLongValue];
}

static size_t
parseAuthority(OFURI *self, const char *UTF8String, size_t length)
{
	size_t ret;
	const char *slash, *at;

	if ((slash = memchr(UTF8String, '/', length)) != NULL)
		length = slash - UTF8String;








|







616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
		@throw [OFInvalidFormatException exception];

	self->_port = [[OFNumber alloc] initWithUnsignedShort:
	    (unsigned short)portString.unsignedLongLongValue];
}

static size_t
parseAuthority(OFIRI *self, const char *UTF8String, size_t length)
{
	size_t ret;
	const char *slash, *at;

	if ((slash = memchr(UTF8String, '/', length)) != NULL)
		length = slash - UTF8String;

558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
	const char *fragment, *query;

	if ((fragment = memchr(UTF8String, '#', length)) != NULL) {
		*fragmentString = [OFString
		    stringWithUTF8String: fragment + 1
				  length: length - (fragment - UTF8String) - 1];

		OFURIVerifyIsEscaped(*fragmentString,
		    [OFCharacterSet URIQueryAllowedCharacterSet], true);

		length = fragment - UTF8String;
	}

	if ((query = memchr(UTF8String, '?', length)) != NULL) {
		*queryString = [OFString
		    stringWithUTF8String: query + 1
				  length: length - (query - UTF8String) - 1];

		OFURIVerifyIsEscaped(*queryString,
		    [OFCharacterSet URIFragmentAllowedCharacterSet], true);

		length = query - UTF8String;
	}

	*pathString = [OFString stringWithUTF8String: UTF8String
					      length: length];

	OFURIVerifyIsEscaped(*pathString,
	    [OFCharacterSet URIQueryAllowedCharacterSet], true);
}

- (instancetype)initWithString: (OFString *)string
{
	self = [super init];

	@try {







|
|









|
|







|
|







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
	const char *fragment, *query;

	if ((fragment = memchr(UTF8String, '#', length)) != NULL) {
		*fragmentString = [OFString
		    stringWithUTF8String: fragment + 1
				  length: length - (fragment - UTF8String) - 1];

		OFIRIVerifyIsEscaped(*fragmentString,
		    [OFCharacterSet IRIQueryAllowedCharacterSet], true);

		length = fragment - UTF8String;
	}

	if ((query = memchr(UTF8String, '?', length)) != NULL) {
		*queryString = [OFString
		    stringWithUTF8String: query + 1
				  length: length - (query - UTF8String) - 1];

		OFIRIVerifyIsEscaped(*queryString,
		    [OFCharacterSet IRIFragmentAllowedCharacterSet], true);

		length = query - UTF8String;
	}

	*pathString = [OFString stringWithUTF8String: UTF8String
					      length: length];

	OFIRIVerifyIsEscaped(*pathString,
	    [OFCharacterSet IRIPathAllowedCharacterSet], true);
}

- (instancetype)initWithString: (OFString *)string
{
	self = [super init];

	@try {
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
		    colon - UTF8String < 1 || !OFASCIIIsAlpha(UTF8String[0]))
			@throw [OFInvalidFormatException exception];

		_scheme = [[[OFString stringWithUTF8String: UTF8String
						    length: colon - UTF8String]
		    lowercaseString] copy];

		OFURIVerifyIsEscaped(_scheme,
		    [OFCharacterSet URISchemeAllowedCharacterSet], false);

		length -= colon - UTF8String + 1;
		UTF8String = colon + 1;

		if (length >= 2 && UTF8String[0] == '/' &&
		    UTF8String[1] == '/') {
			size_t authorityLength;







|
|







692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
		    colon - UTF8String < 1 || !OFASCIIIsAlpha(UTF8String[0]))
			@throw [OFInvalidFormatException exception];

		_scheme = [[[OFString stringWithUTF8String: UTF8String
						    length: colon - UTF8String]
		    lowercaseString] copy];

		OFIRIVerifyIsEscaped(_scheme,
		    [OFCharacterSet IRISchemeAllowedCharacterSet], false);

		length -= colon - UTF8String + 1;
		UTF8String = colon + 1;

		if (length >= 2 && UTF8String[0] == '/' &&
		    UTF8String[1] == '/') {
			size_t authorityLength;
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
	else
		[components replaceObjectAtIndex: components.count - 1
				      withObject: path];

	return [components componentsJoinedByString: @"/"];
}

- (instancetype)initWithString: (OFString *)string relativeToURI: (OFURI *)URI
{
	bool absolute;

	@try {
		absolute = isAbsolute(string);
	} @catch (id e) {
		[self release];







|







781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
	else
		[components replaceObjectAtIndex: components.count - 1
				      withObject: path];

	return [components componentsJoinedByString: @"/"];
}

- (instancetype)initWithString: (OFString *)string relativeToIRI: (OFIRI *)IRI
{
	bool absolute;

	@try {
		absolute = isAbsolute(string);
	} @catch (id e) {
		[self release];
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
	@try {
		void *pool = objc_autoreleasePoolPush();
		const char *UTF8String = string.UTF8String;
		size_t length = string.UTF8StringLength;
		bool hasAuthority = false;
		OFString *path, *query = nil, *fragment = nil;

		_scheme = [URI->_scheme copy];

		if (length >= 2 && UTF8String[0] == '/' &&
		    UTF8String[1] == '/') {
			size_t authorityLength;

			hasAuthority = true;

			UTF8String += 2;
			length -= 2;

			authorityLength = parseAuthority(self,
			    UTF8String, length);

			UTF8String += authorityLength;
			length -= authorityLength;

			if (length > 0)
				OFEnsure(UTF8String[0] == '/');
		} else {
			_percentEncodedHost = [URI->_percentEncodedHost copy];
			_port = [URI->_port copy];
			_percentEncodedUser = [URI->_percentEncodedUser copy];
			_percentEncodedPassword =
			    [URI->_percentEncodedPassword copy];
		}

		parsePathQueryFragment(UTF8String, length,
		    &path, &query, &fragment);
		_percentEncodedFragment = [fragment copy];

		if (hasAuthority) {
			_percentEncodedPath = [path copy];
			_percentEncodedQuery = [query copy];
		} else {
			if (path.length == 0) {
				_percentEncodedPath =
				    [URI->_percentEncodedPath copy];
				_percentEncodedQuery = (query != nil
				    ? [query copy]
				    : [URI->_percentEncodedQuery copy]);
			} else {
				if ([path hasPrefix: @"/"])
					_percentEncodedPath = [path copy];
				else
					_percentEncodedPath = [merge(
					    URI->_percentEncodedPath, path)
					    copy];

				_percentEncodedQuery = [query copy];
			}
		}

		objc_autoreleasePoolPop(pool);
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

#ifdef OF_HAVE_FILES
- (instancetype)initFileURIWithPath: (OFString *)path
{
	bool isDirectory;

	@try {
		void *pool = objc_autoreleasePoolPush();
		isDirectory = [path of_isDirectoryPath];
		objc_autoreleasePoolPop(pool);
	} @catch (id e) {
		[self release];
		@throw e;
	}

	self = [self initFileURIWithPath: path isDirectory: isDirectory];

	return self;
}

- (instancetype)initFileURIWithPath: (OFString *)path
			isDirectory: (bool)isDirectory
{
	self = [super init];

	@try {
		void *pool = objc_autoreleasePoolPush();
		OFString *percentEncodedHost = nil;

		if (!path.absolutePath) {
			OFString *currentDirectoryPath = [OFFileManager
			    defaultManager].currentDirectoryPath;

			path = [currentDirectoryPath
			    stringByAppendingPathComponent: path];
			path = path.stringByStandardizingPath;
		}

		path = [path of_pathToURIPathWithPercentEncodedHost:
		    &percentEncodedHost];
		_percentEncodedHost = [percentEncodedHost copy];

		if (isDirectory && ![path hasSuffix: @"/"])
			path = [path stringByAppendingString: @"/"];

		_scheme = @"file";
		_percentEncodedPath = [[path
		    stringByAddingPercentEncodingWithAllowedCharacters:
		    [OFCharacterSet URIPathAllowedCharacterSet]] copy];

		objc_autoreleasePoolPop(pool);
	} @catch (id e) {
		[self release];
		@throw e;
	}








|



















|
|
|

|












|


|





|
















|












|




|

















|









|







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
	@try {
		void *pool = objc_autoreleasePoolPush();
		const char *UTF8String = string.UTF8String;
		size_t length = string.UTF8StringLength;
		bool hasAuthority = false;
		OFString *path, *query = nil, *fragment = nil;

		_scheme = [IRI->_scheme copy];

		if (length >= 2 && UTF8String[0] == '/' &&
		    UTF8String[1] == '/') {
			size_t authorityLength;

			hasAuthority = true;

			UTF8String += 2;
			length -= 2;

			authorityLength = parseAuthority(self,
			    UTF8String, length);

			UTF8String += authorityLength;
			length -= authorityLength;

			if (length > 0)
				OFEnsure(UTF8String[0] == '/');
		} else {
			_percentEncodedHost = [IRI->_percentEncodedHost copy];
			_port = [IRI->_port copy];
			_percentEncodedUser = [IRI->_percentEncodedUser copy];
			_percentEncodedPassword =
			    [IRI->_percentEncodedPassword copy];
		}

		parsePathQueryFragment(UTF8String, length,
		    &path, &query, &fragment);
		_percentEncodedFragment = [fragment copy];

		if (hasAuthority) {
			_percentEncodedPath = [path copy];
			_percentEncodedQuery = [query copy];
		} else {
			if (path.length == 0) {
				_percentEncodedPath =
				    [IRI->_percentEncodedPath copy];
				_percentEncodedQuery = (query != nil
				    ? [query copy]
				    : [IRI->_percentEncodedQuery copy]);
			} else {
				if ([path hasPrefix: @"/"])
					_percentEncodedPath = [path copy];
				else
					_percentEncodedPath = [merge(
					    IRI->_percentEncodedPath, path)
					    copy];

				_percentEncodedQuery = [query copy];
			}
		}

		objc_autoreleasePoolPop(pool);
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

#ifdef OF_HAVE_FILES
- (instancetype)initFileIRIWithPath: (OFString *)path
{
	bool isDirectory;

	@try {
		void *pool = objc_autoreleasePoolPush();
		isDirectory = [path of_isDirectoryPath];
		objc_autoreleasePoolPop(pool);
	} @catch (id e) {
		[self release];
		@throw e;
	}

	self = [self initFileIRIWithPath: path isDirectory: isDirectory];

	return self;
}

- (instancetype)initFileIRIWithPath: (OFString *)path
			isDirectory: (bool)isDirectory
{
	self = [super init];

	@try {
		void *pool = objc_autoreleasePoolPush();
		OFString *percentEncodedHost = nil;

		if (!path.absolutePath) {
			OFString *currentDirectoryPath = [OFFileManager
			    defaultManager].currentDirectoryPath;

			path = [currentDirectoryPath
			    stringByAppendingPathComponent: path];
			path = path.stringByStandardizingPath;
		}

		path = [path of_pathToIRIPathWithPercentEncodedHost:
		    &percentEncodedHost];
		_percentEncodedHost = [percentEncodedHost copy];

		if (isDirectory && ![path hasSuffix: @"/"])
			path = [path stringByAppendingString: @"/"];

		_scheme = @"file";
		_percentEncodedPath = [[path
		    stringByAddingPercentEncodingWithAllowedCharacters:
		    [OFCharacterSet IRIPathAllowedCharacterSet]] copy];

		objc_autoreleasePoolPop(pool);
	} @catch (id e) {
		[self release];
		@throw e;
	}

844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
}

- (instancetype)of_init
{
	return [super init];
}

- (instancetype)initWithSerialization: (OFXMLElement *)element
{
	void *pool = objc_autoreleasePoolPush();
	OFString *stringValue;

	@try {
		if (![element.name isEqual: self.className] ||
		    ![element.namespace isEqual: OFSerializationNS])
			@throw [OFInvalidArgumentException exception];

		stringValue = element.stringValue;
	} @catch (id e) {
		[self release];
		@throw e;
	}

	self = [self initWithString: stringValue];

	objc_autoreleasePoolPop(pool);

	return self;
}

- (void)dealloc
{
	[_scheme release];
	[_percentEncodedHost release];
	[_port release];
	[_percentEncodedUser release];
	[_percentEncodedPassword release];
	[_percentEncodedPath release];
	[_percentEncodedQuery release];
	[_percentEncodedFragment release];

	[super dealloc];
}

- (bool)isEqual: (id)object
{
	OFURI *URI;

	if (object == self)
		return true;

	if (![object isKindOfClass: [OFURI class]])
		return false;

	URI = object;

	if (![URI->_scheme isEqual: _scheme])
		return false;
	if (URI->_percentEncodedHost != _percentEncodedHost &&
	    ![URI->_percentEncodedHost isEqual: _percentEncodedHost])
		return false;
	if (URI->_port != _port && ![URI->_port isEqual: _port])
		return false;
	if (URI->_percentEncodedUser != _percentEncodedUser &&
	    ![URI->_percentEncodedUser isEqual: _percentEncodedUser])
		return false;
	if (URI->_percentEncodedPassword != _percentEncodedPassword &&
	    ![URI->_percentEncodedPassword isEqual: _percentEncodedPassword])
		return false;
	if (![URI->_percentEncodedPath isEqual: _percentEncodedPath])
		return false;
	if (URI->_percentEncodedQuery != _percentEncodedQuery &&
	    ![URI->_percentEncodedQuery isEqual: _percentEncodedQuery])
		return false;
	if (URI->_percentEncodedFragment != _percentEncodedFragment &&
	    ![URI->_percentEncodedFragment isEqual: _percentEncodedFragment])
		return false;

	return true;
}

- (unsigned long)hash
{







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
















|




|


|

|

|
|

|

|
|

|
|

|

|
|

|
|







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
}

- (instancetype)of_init
{
	return [super init];
}
























- (void)dealloc
{
	[_scheme release];
	[_percentEncodedHost release];
	[_port release];
	[_percentEncodedUser release];
	[_percentEncodedPassword release];
	[_percentEncodedPath release];
	[_percentEncodedQuery release];
	[_percentEncodedFragment release];

	[super dealloc];
}

- (bool)isEqual: (id)object
{
	OFIRI *IRI;

	if (object == self)
		return true;

	if (![object isKindOfClass: [OFIRI class]])
		return false;

	IRI = object;

	if (![IRI->_scheme isEqual: _scheme])
		return false;
	if (IRI->_percentEncodedHost != _percentEncodedHost &&
	    ![IRI->_percentEncodedHost isEqual: _percentEncodedHost])
		return false;
	if (IRI->_port != _port && ![IRI->_port isEqual: _port])
		return false;
	if (IRI->_percentEncodedUser != _percentEncodedUser &&
	    ![IRI->_percentEncodedUser isEqual: _percentEncodedUser])
		return false;
	if (IRI->_percentEncodedPassword != _percentEncodedPassword &&
	    ![IRI->_percentEncodedPassword isEqual: _percentEncodedPassword])
		return false;
	if (![IRI->_percentEncodedPath isEqual: _percentEncodedPath])
		return false;
	if (IRI->_percentEncodedQuery != _percentEncodedQuery &&
	    ![IRI->_percentEncodedQuery isEqual: _percentEncodedQuery])
		return false;
	if (IRI->_percentEncodedFragment != _percentEncodedFragment &&
	    ![IRI->_percentEncodedFragment isEqual: _percentEncodedFragment])
		return false;

	return true;
}

- (unsigned long)hash
{
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
- (OFString *)host
{
	if ([_percentEncodedHost hasPrefix: @"["] &&
	    [_percentEncodedHost hasSuffix: @"]"]) {
		OFString *host = [_percentEncodedHost substringWithRange:
		    OFMakeRange(1, _percentEncodedHost.length - 2)];

		if (!OFURIIsIPv6Host(host))
			@throw [OFInvalidArgumentException exception];

		return host;
	}

	return _percentEncodedHost.stringByRemovingPercentEncoding;
}







|







1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
- (OFString *)host
{
	if ([_percentEncodedHost hasPrefix: @"["] &&
	    [_percentEncodedHost hasSuffix: @"]"]) {
		OFString *host = [_percentEncodedHost substringWithRange:
		    OFMakeRange(1, _percentEncodedHost.length - 2)];

		if (!OFIRIIsIPv6Host(host))
			@throw [OFInvalidArgumentException exception];

		return host;
	}

	return _percentEncodedHost.stringByRemovingPercentEncoding;
}
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
#endif
	OFMutableArray *ret;
	size_t count;

#ifdef OF_HAVE_FILES
	if (isFile) {
		OFString *path = [_percentEncodedPath
		    of_URIPathToPathWithPercentEncodedHost: nil];
		ret = [[path.pathComponents mutableCopy] autorelease];

		if (![ret.firstObject isEqual: @"/"])
			[ret insertObject: @"/" atIndex: 0];
	} else
#endif
		ret = [[[_percentEncodedPath componentsSeparatedByString: @"/"]
		    mutableCopy] autorelease];

	count = ret.count;

	if (count > 0 && [ret.firstObject length] == 0)
		[ret replaceObjectAtIndex: 0 withObject: @"/"];

	for (size_t i = 0; i < count; i++) {
		OFString *component = [ret objectAtIndex: i];

#ifdef OF_HAVE_FILES
		if (isFile)
			component =
			    [component of_pathComponentToURIPathComponent];
#endif

		component = component.stringByRemovingPercentEncoding;
		[ret replaceObjectAtIndex: i withObject: component];
	}

	[ret makeImmutable];







|




















|







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
#endif
	OFMutableArray *ret;
	size_t count;

#ifdef OF_HAVE_FILES
	if (isFile) {
		OFString *path = [_percentEncodedPath
		    of_IRIPathToPathWithPercentEncodedHost: nil];
		ret = [[path.pathComponents mutableCopy] autorelease];

		if (![ret.firstObject isEqual: @"/"])
			[ret insertObject: @"/" atIndex: 0];
	} else
#endif
		ret = [[[_percentEncodedPath componentsSeparatedByString: @"/"]
		    mutableCopy] autorelease];

	count = ret.count;

	if (count > 0 && [ret.firstObject length] == 0)
		[ret replaceObjectAtIndex: 0 withObject: @"/"];

	for (size_t i = 0; i < count; i++) {
		OFString *component = [ret objectAtIndex: i];

#ifdef OF_HAVE_FILES
		if (isFile)
			component =
			    [component of_pathComponentToIRIPathComponent];
#endif

		component = component.stringByRemovingPercentEncoding;
		[ret replaceObjectAtIndex: i withObject: component];
	}

	[ret makeImmutable];
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
- (id)copy
{
	return [self retain];
}

- (id)mutableCopy
{
	OFURI *copy = [[OFMutableURI alloc] initWithScheme: _scheme];

	@try {
		copy->_percentEncodedHost = [_percentEncodedHost copy];
		copy->_port = [_port copy];
		copy->_percentEncodedUser = [_percentEncodedUser copy];
		copy->_percentEncodedPassword = [_percentEncodedPassword copy];
		copy->_percentEncodedPath = [_percentEncodedPath copy];







|







1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
- (id)copy
{
	return [self retain];
}

- (id)mutableCopy
{
	OFIRI *copy = [[OFMutableIRI alloc] initWithScheme: _scheme];

	@try {
		copy->_percentEncodedHost = [_percentEncodedHost copy];
		copy->_port = [_port copy];
		copy->_percentEncodedUser = [_percentEncodedUser copy];
		copy->_percentEncodedPassword = [_percentEncodedPassword copy];
		copy->_percentEncodedPath = [_percentEncodedPath copy];
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253



























1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
	if (![_scheme isEqual: @"file"])
		@throw [OFInvalidArgumentException exception];

	if (![_percentEncodedPath hasPrefix: @"/"])
		@throw [OFInvalidFormatException exception];

	path = [self.path
	    of_URIPathToPathWithPercentEncodedHost: _percentEncodedHost];

	[path retain];

	objc_autoreleasePoolPop(pool);

	return [path autorelease];
}
#endif

- (OFURI *)URIByAppendingPathComponent: (OFString *)component
{
	OFMutableURI *URI = [[self mutableCopy] autorelease];
	[URI appendPathComponent: component];
	[URI makeImmutable];
	return URI;
}

- (OFURI *)URIByAppendingPathComponent: (OFString *)component
			   isDirectory: (bool)isDirectory
{
	OFMutableURI *URI = [[self mutableCopy] autorelease];
	[URI appendPathComponent: component isDirectory: isDirectory];
	[URI makeImmutable];
	return URI;
}

- (OFURI *)URIByStandardizingPath
{
	OFMutableURI *URI = [[self mutableCopy] autorelease];
	[URI standardizePath];
	[URI makeImmutable];
	return URI;



























}

- (OFString *)description
{
	return [OFString stringWithFormat: @"<%@: %@>",
					   self.class, self.string];
}

- (OFXMLElement *)XMLElementBySerializing
{
	void *pool = objc_autoreleasePoolPush();
	OFXMLElement *element;

	element = [OFXMLElement elementWithName: self.className
				      namespace: OFSerializationNS
				    stringValue: self.string];

	[element retain];

	objc_autoreleasePoolPop(pool);

	return [element autorelease];
}
@end







|









|

|
|
|
|


|


|
|
|
|


|

|
|
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

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
	if (![_scheme isEqual: @"file"])
		@throw [OFInvalidArgumentException exception];

	if (![_percentEncodedPath hasPrefix: @"/"])
		@throw [OFInvalidFormatException exception];

	path = [self.path
	    of_IRIPathToPathWithPercentEncodedHost: _percentEncodedHost];

	[path retain];

	objc_autoreleasePoolPop(pool);

	return [path autorelease];
}
#endif

- (OFIRI *)IRIByAppendingPathComponent: (OFString *)component
{
	OFMutableIRI *IRI = [[self mutableCopy] autorelease];
	[IRI appendPathComponent: component];
	[IRI makeImmutable];
	return IRI;
}

- (OFIRI *)IRIByAppendingPathComponent: (OFString *)component
			   isDirectory: (bool)isDirectory
{
	OFMutableIRI *IRI = [[self mutableCopy] autorelease];
	[IRI appendPathComponent: component isDirectory: isDirectory];
	[IRI makeImmutable];
	return IRI;
}

- (OFIRI *)IRIByStandardizingPath
{
	OFMutableIRI *IRI = [[self mutableCopy] autorelease];
	[IRI standardizePath];
	[IRI makeImmutable];
	return IRI;
}

- (OFIRI *)IRIByAddingPercentEncodingForUnicodeCharacters
{
	OFMutableIRI *IRI = [[self mutableCopy] autorelease];
	void *pool = objc_autoreleasePoolPush();
	OFCharacterSet *ASCII =
	    [OFCharacterSet characterSetWithRange: OFMakeRange(0, 0x80)];

	IRI.percentEncodedHost = [_percentEncodedHost
	    stringByAddingPercentEncodingWithAllowedCharacters: ASCII];
	IRI.percentEncodedUser = [_percentEncodedUser
	    stringByAddingPercentEncodingWithAllowedCharacters: ASCII];
	IRI.percentEncodedPassword = [_percentEncodedPassword
	    stringByAddingPercentEncodingWithAllowedCharacters: ASCII];
	IRI.percentEncodedPath = [_percentEncodedPath
	    stringByAddingPercentEncodingWithAllowedCharacters: ASCII];
	IRI.percentEncodedQuery = [_percentEncodedQuery
	    stringByAddingPercentEncodingWithAllowedCharacters: ASCII];
	IRI.percentEncodedFragment = [_percentEncodedFragment
	    stringByAddingPercentEncodingWithAllowedCharacters: ASCII];

	[IRI makeImmutable];

	objc_autoreleasePoolPop(pool);

	return IRI;
}

- (OFString *)description
{
	return [OFString stringWithFormat: @"<%@: %@>",
					   self.class, self.string];
}
















@end

Renamed and modified src/OFURIHandler.h [09864efcca] to src/OFIRIHandler.h [91924a5c3a].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132




133
134
135
136
137
138
139
140
141
142







143
144
145
146
147
148
149
150


151
152
153
154
155
156
157
158


159
160
161
162
163
164
165



166
167
168
169
170
171
172
173
174
175
176




177
178
179
180
181
182
183
184
185



186
187
188
189
190
191
192
193
194
195
196
197
198





199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214



215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234



235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252



253

254























































255
256
257
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#import "OFFileManager.h"
#import "OFObject.h"
#import "OFString.h"

OF_ASSUME_NONNULL_BEGIN

@class OFArray OF_GENERIC(ObjectType);

@class OFDate;
@class OFStream;
@class OFURI;

/**
 * @class OFURIHandler OFURIHandler.h ObjFW/OFURIHandler.h
 *
 * @brief A handler for a URI scheme.
 */
@interface OFURIHandler: OFObject
{
	OFString *_scheme;
	OF_RESERVE_IVARS(OFURIHandler, 4)
}

/**
 * @brief The scheme this OFURIHandler handles.
 */
@property (readonly, nonatomic) OFString *scheme;

/**
 * @brief Registers the specified class as the handler for the specified scheme.
 *
 * If the same class is specified for two schemes, one instance of it is
 * created per scheme.
 *
 * @param class_ The class to register as the handler for the specified scheme
 * @param scheme The scheme for which to register the handler
 * @return Whether the class was successfully registered. If a handler for the
 *	   same scheme is already registered, registration fails.
 */
+ (bool)registerClass: (Class)class_ forScheme: (OFString *)scheme;

/**
 * @brief Returns the handler for the specified URI.
 *
 * @return The handler for the specified URI.
 * @throw OFUnsupportedProtocolException The specified URI is not supported
 */
+ (OFURIHandler *)handlerForURI: (OFURI *)URI;

/**
 * @brief Opens the item at the specified URI.
 *
 * @param URI The URI of the item which should be opened
 * @param mode The mode in which the file should be opened.@n
 *	       Possible modes are:
 *	       @n
 *	       Mode           | Description
 *	       ---------------|-------------------------------------
 *	       `r`            | Read-only
 *	       `r+`           | Read-write
 *	       `w`            | Write-only, create or truncate
 *	       `wx`           | Write-only, create or fail, exclusive
 *	       `w+`           | Read-write, create or truncate
 *	       `w+x`          | Read-write, create or fail, exclusive
 *	       `a`            | Write-only, create or append
 *	       `a+`           | Read-write, create or append
 *	       @n
 *	       The handler is allowed to not implement all modes and is also
 *	       allowed to implement additional, scheme-specific modes.
 * @return The opened stream if it was successfully opened
 * @throw OFOpenItemFailedException Opening the item failed
 * @throw OFUnsupportedProtocolException The specified URI is not supported
 */
+ (OFStream *)openItemAtURI: (OFURI *)URI mode: (OFString *)mode;

- (instancetype)init OF_UNAVAILABLE;

/**
 * @brief Initializes the handler for the specified scheme.
 *
 * @param scheme The scheme to initialize for
 * @return An initialized URI handler
 */
- (instancetype)initWithScheme: (OFString *)scheme OF_DESIGNATED_INITIALIZER;

/**
 * @brief Opens the item at the specified URI.
 *
 * @param URI The URI of the item which should be opened
 * @param mode The mode in which the file should be opened.@n
 *	       Possible modes are:
 *	       @n
 *	       Mode           | Description
 *	       ---------------|-------------------------------------
 *	       `r`            | Read-only
 *	       `r+`           | Read-write
 *	       `w`            | Write-only, create or truncate
 *	       `wx`           | Write-only, create or fail, exclusive
 *	       `w+`           | Read-write, create or truncate
 *	       `w+x`          | Read-write, create or fail, exclusive
 *	       `a`            | Write-only, create or append
 *	       `a+`           | Read-write, create or append
 *	       @n
 *	       The handler is allowed to not implement all modes and is also
 *	       allowed to implement additional, scheme-specific modes.
 * @return The opened stream if it was successfully opened
 * @throw OFOpenItemFailedException Opening the item failed
 * @throw OFUnsupportedProtocolException The specified URI is not supported by
 *					 the handler
 */
- (OFStream *)openItemAtURI: (OFURI *)URI mode: (OFString *)mode;

/**
 * @brief Returns the attributes for the item at the specified URI.
 *
 * @param URI The URI to return the attributes for
 * @return A dictionary of attributes for the specified URI, with the keys of
 *	   type @ref OFFileAttributeKey




 */
- (OFFileAttributes)attributesOfItemAtURI: (OFURI *)URI;

/**
 * @brief Sets the attributes for the item at the specified URI.
 *
 * All attributes not part of the dictionary are left unchanged.
 *
 * @param attributes The attributes to set for the specified URI
 * @param URI The URI of the item to set the attributes for







 */
- (void)setAttributes: (OFFileAttributes)attributes ofItemAtURI: (OFURI *)URI;

/**
 * @brief Checks whether a file exists at the specified URI.
 *
 * @param URI The URI to check
 * @return A boolean whether there is a file at the specified URI


 */
- (bool)fileExistsAtURI: (OFURI *)URI;

/**
 * @brief Checks whether a directory exists at the specified URI.
 *
 * @param URI The URI to check
 * @return A boolean whether there is a directory at the specified URI


 */
- (bool)directoryExistsAtURI: (OFURI *)URI;

/**
 * @brief Creates a directory at the specified URI.
 *
 * @param URI The URI of the directory to create



 */
- (void)createDirectoryAtURI: (OFURI *)URI;

/**
 * @brief Returns an array with the URIs of the items in the specified
 *	  directory.
 *
 * @note `.` and `..` are not part of the returned array.
 *
 * @param URI The URI to the directory whose items should be returned
 * @return An array with the URIs of the items in the specified directory




 */
- (OFArray OF_GENERIC(OFURI *) *)contentsOfDirectoryAtURI: (OFURI *)URI;

/**
 * @brief Removes the item at the specified URI.
 *
 * If the item at the specified URI is a directory, it is removed recursively.
 *
 * @param URI The URI to the item which should be removed



 */
- (void)removeItemAtURI: (OFURI *)URI;

/**
 * @brief Creates a hard link for the specified item.
 *
 * The destination URI must have a full path, which means it must include the
 * name of the item.
 *
 * This method is not available for all URIs.
 *
 * @param source The URI to the item for which a link should be created
 * @param destination The URI to the item which should link to the source





 */
- (void)linkItemAtURI: (OFURI *)source toURI: (OFURI *)destination;

/**
 * @brief Creates a symbolic link for an item.
 *
 * The destination URI must have a full path, which means it must include the
 * name of the item.
 *
 * This method is not available for all URIs.
 *
 * @note On Windows, this requires at least Windows Vista and administrator
 *	 privileges!
 *
 * @param URI The URI to the item which should symbolically link to the target
 * @param target The target of the symbolic link



 */
- (void)createSymbolicLinkAtURI: (OFURI *)URI
	    withDestinationPath: (OFString *)target;

/**
 * @brief Tries to efficiently copy an item. If a copy would only be possible
 *	  by reading the entire item and then writing it, it returns false.
 *
 * The destination URI must have a full path, which means it must include the
 * name of the item.
 *
 * If an item already exists, the copy operation fails. This is also the case
 * if a directory is copied and an item already exists in the destination
 * directory.
 *
 * @param source The file, directory or symbolic link to copy
 * @param destination The destination URI
 * @return True if an efficient copy was performed, false if an efficient copy
 *	   was not possible. Note that errors while performing a copy are
 *	   reported via exceptions and not by returning false!



 */
- (bool)copyItemAtURI: (OFURI *)source toURI: (OFURI *)destination;

/**
 * @brief Tries to efficiently move an item. If a move would only be possible
 *	  by copying the source and deleting it, it returns false.
 *
 * The destination URI must have a full path, which means it must include the
 * name of the item.
 *
 * If the destination is on a different logical device or uses a different
 * scheme, an efficient move is not possible and false is returned.
 *
 * @param source The item to rename
 * @param destination The new name for the item
 * @return True if an efficient move was performed, false if an efficient move
 *	   was not possible. Note that errors while performing a move are
 *	   reported via exceptions and not by returning false!



 */

- (bool)moveItemAtURI: (OFURI *)source toURI: (OFURI *)destination;























































@end

OF_ASSUME_NONNULL_END

|




















>

|
|


|

|

|


|



|

















|

|
|

|


|

|


















|

|







|




|

|


















|


|


|

|
|

>
>
>
>

|


|



|
|
>
>
>
>
>
>
>

|


|

|
|
>
>

|


|

|
|
>
>

|


|

|
>
>
>

|


|




|
|
>
>
>
>

|


|

|

|
>
>
>

|




|


|

|
|
>
>
>
>
>

|




|


|




|

>
>
>

|






|







|



>
>
>

|





|










>
>
>

>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
/*
 * Copyright (c) 2008-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 "OFFileManager.h"
#import "OFObject.h"
#import "OFString.h"

OF_ASSUME_NONNULL_BEGIN

@class OFArray OF_GENERIC(ObjectType);
@class OFData;
@class OFDate;
@class OFIRI;
@class OFStream;

/**
 * @class OFIRIHandler OFIRIHandler.h ObjFW/OFIRIHandler.h
 *
 * @brief A handler for an IRI scheme.
 */
@interface OFIRIHandler: OFObject
{
	OFString *_scheme;
	OF_RESERVE_IVARS(OFIRIHandler, 4)
}

/**
 * @brief The scheme this OFIRIHandler handles.
 */
@property (readonly, nonatomic) OFString *scheme;

/**
 * @brief Registers the specified class as the handler for the specified scheme.
 *
 * If the same class is specified for two schemes, one instance of it is
 * created per scheme.
 *
 * @param class_ The class to register as the handler for the specified scheme
 * @param scheme The scheme for which to register the handler
 * @return Whether the class was successfully registered. If a handler for the
 *	   same scheme is already registered, registration fails.
 */
+ (bool)registerClass: (Class)class_ forScheme: (OFString *)scheme;

/**
 * @brief Returns the handler for the specified IRI.
 *
 * @return The handler for the specified IRI.
 * @throw OFUnsupportedProtocolException The specified IRI is not supported
 */
+ (OFIRIHandler *)handlerForIRI: (OFIRI *)IRI;

/**
 * @brief Opens the item at the specified IRI.
 *
 * @param IRI The IRI of the item which should be opened
 * @param mode The mode in which the file should be opened.@n
 *	       Possible modes are:
 *	       @n
 *	       Mode           | Description
 *	       ---------------|-------------------------------------
 *	       `r`            | Read-only
 *	       `r+`           | Read-write
 *	       `w`            | Write-only, create or truncate
 *	       `wx`           | Write-only, create or fail, exclusive
 *	       `w+`           | Read-write, create or truncate
 *	       `w+x`          | Read-write, create or fail, exclusive
 *	       `a`            | Write-only, create or append
 *	       `a+`           | Read-write, create or append
 *	       @n
 *	       The handler is allowed to not implement all modes and is also
 *	       allowed to implement additional, scheme-specific modes.
 * @return The opened stream if it was successfully opened
 * @throw OFOpenItemFailedException Opening the item failed
 * @throw OFUnsupportedProtocolException The specified IRI is not supported
 */
+ (OFStream *)openItemAtIRI: (OFIRI *)IRI mode: (OFString *)mode;

- (instancetype)init OF_UNAVAILABLE;

/**
 * @brief Initializes the handler for the specified scheme.
 *
 * @param scheme The scheme to initialize for
 * @return An initialized IRI handler
 */
- (instancetype)initWithScheme: (OFString *)scheme OF_DESIGNATED_INITIALIZER;

/**
 * @brief Opens the item at the specified IRI.
 *
 * @param IRI The IRI of the item which should be opened
 * @param mode The mode in which the file should be opened.@n
 *	       Possible modes are:
 *	       @n
 *	       Mode           | Description
 *	       ---------------|-------------------------------------
 *	       `r`            | Read-only
 *	       `r+`           | Read-write
 *	       `w`            | Write-only, create or truncate
 *	       `wx`           | Write-only, create or fail, exclusive
 *	       `w+`           | Read-write, create or truncate
 *	       `w+x`          | Read-write, create or fail, exclusive
 *	       `a`            | Write-only, create or append
 *	       `a+`           | Read-write, create or append
 *	       @n
 *	       The handler is allowed to not implement all modes and is also
 *	       allowed to implement additional, scheme-specific modes.
 * @return The opened stream if it was successfully opened
 * @throw OFOpenItemFailedException Opening the item failed
 * @throw OFUnsupportedProtocolException The specified IRI is not supported by
 *					 the handler
 */
- (OFStream *)openItemAtIRI: (OFIRI *)IRI mode: (OFString *)mode;

/**
 * @brief Returns the attributes for the item at the specified IRI.
 *
 * @param IRI The IRI to return the attributes for
 * @return A dictionary of attributes for the specified IRI, with the keys of
 *	   type @ref OFFileAttributeKey
 * @throw OFGetItemAttributesFailedException Failed to get the attributes of
 *					     the item
 * @throw OFUnsupportedProtocolException The handler cannot handle the IRI's
 *					 scheme
 */
- (OFFileAttributes)attributesOfItemAtIRI: (OFIRI *)IRI;

/**
 * @brief Sets the attributes for the item at the specified IRI.
 *
 * All attributes not part of the dictionary are left unchanged.
 *
 * @param attributes The attributes to set for the specified IRI
 * @param IRI The IRI of the item to set the attributes for
 * @@throw OFSetItemAttributesFailedException Failed to set the attributes of
 *					      the item
 * @throw OFUnsupportedProtocolException The handler cannot handle the IRI's
 *					 scheme
 * @throw OFNotImplementedException Setting one or more of the specified
 *				    attributes is not implemented for the
 *				    specified item
 */
- (void)setAttributes: (OFFileAttributes)attributes ofItemAtIRI: (OFIRI *)IRI;

/**
 * @brief Checks whether a file exists at the specified IRI.
 *
 * @param IRI The IRI to check
 * @return A boolean whether there is a file at the specified IRI
 * @throw OFUnsupportedProtocolException The handler cannot handle the IRI's
 *					 scheme
 */
- (bool)fileExistsAtIRI: (OFIRI *)IRI;

/**
 * @brief Checks whether a directory exists at the specified IRI.
 *
 * @param IRI The IRI to check
 * @return A boolean whether there is a directory at the specified IRI
 * @throw OFUnsupportedProtocolException The handler cannot handle the IRI's
 *					 scheme
 */
- (bool)directoryExistsAtIRI: (OFIRI *)IRI;

/**
 * @brief Creates a directory at the specified IRI.
 *
 * @param IRI The IRI of the directory to create
 * @throw OFCreateDirectoryFailedException Creating the directory failed
 * @throw OFUnsupportedProtocolException The handler cannot handle the IRI's
 *					 scheme
 */
- (void)createDirectoryAtIRI: (OFIRI *)IRI;

/**
 * @brief Returns an array with the IRIs of the items in the specified
 *	  directory.
 *
 * @note `.` and `..` are not part of the returned array.
 *
 * @param IRI The IRI to the directory whose items should be returned
 * @return An array with the IRIs of the items in the specified directory
 * @throw OFOpenItemFailedException Opening the directory failed
 * @throw OFReadFailedException Reading from the directory failed
 * @throw OFUnsupportedProtocolException The handler cannot handle the IRI's
 *					 scheme
 */
- (OFArray OF_GENERIC(OFIRI *) *)contentsOfDirectoryAtIRI: (OFIRI *)IRI;

/**
 * @brief Removes the item at the specified IRI.
 *
 * If the item at the specified IRI is a directory, it is removed recursively.
 *
 * @param IRI The IRI to the item which should be removed
 * @throw OFRemoveItemFailedException Removing the item failed
 * @throw OFUnsupportedProtocolException The handler cannot handle the IRI's
 *					 scheme
 */
- (void)removeItemAtIRI: (OFIRI *)IRI;

/**
 * @brief Creates a hard link for the specified item.
 *
 * The destination IRI must have a full path, which means it must include the
 * name of the item.
 *
 * This method is not available for all IRIs.
 *
 * @param source The IRI to the item for which a link should be created
 * @param destination The IRI to the item which should link to the source
 * @throw OFLinkItemFailedException Linking the item failed
 * @throw OFUnsupportedProtocolException The handler cannot handle the scheme
 *					 of one of the IRIs
 * @throw OFNotImplementedException Hardlinks are not implemented for the
 *				    specified IRI
 */
- (void)linkItemAtIRI: (OFIRI *)source toIRI: (OFIRI *)destination;

/**
 * @brief Creates a symbolic link for an item.
 *
 * The destination IRI must have a full path, which means it must include the
 * name of the item.
 *
 * This method is not available for all IRIs.
 *
 * @note On Windows, this requires at least Windows Vista and administrator
 *	 privileges!
 *
 * @param IRI The IRI to the item which should symbolically link to the target
 * @param target The target of the symbolic link
 * @throw OFCreateSymbolicLinkFailed Creating a symbolic link failed
 * @throw OFUnsupportedProtocolException The handler cannot handle the IRI's
 *					 scheme
 */
- (void)createSymbolicLinkAtIRI: (OFIRI *)IRI
	    withDestinationPath: (OFString *)target;

/**
 * @brief Tries to efficiently copy an item. If a copy would only be possible
 *	  by reading the entire item and then writing it, it returns false.
 *
 * The destination IRI must have a full path, which means it must include the
 * name of the item.
 *
 * If an item already exists, the copy operation fails. This is also the case
 * if a directory is copied and an item already exists in the destination
 * directory.
 *
 * @param source The file, directory or symbolic link to copy
 * @param destination The destination IRI
 * @return True if an efficient copy was performed, false if an efficient copy
 *	   was not possible. Note that errors while performing a copy are
 *	   reported via exceptions and not by returning false!
 * @throw OFCopyItemFailedException Copying failed
 * @throw OFUnsupportedProtocolException The handler cannot handle the IRI's
 *					 scheme
 */
- (bool)copyItemAtIRI: (OFIRI *)source toIRI: (OFIRI *)destination;

/**
 * @brief Tries to efficiently move an item. If a move would only be possible
 *	  by copying the source and deleting it, it returns false.
 *
 * The destination IRI must have a full path, which means it must include the
 * name of the item.
 *
 * If the destination is on a different logical device or uses a different
 * scheme, an efficient move is not possible and false is returned.
 *
 * @param source The item to rename
 * @param destination The new name for the item
 * @return True if an efficient move was performed, false if an efficient move
 *	   was not possible. Note that errors while performing a move are
 *	   reported via exceptions and not by returning false!
 * @throw OFMoveItemFailedException Moving failed
 * @throw OFUnsupportedProtocolException The handler cannot handle the IRI's
 *					 scheme
 */
- (bool)moveItemAtIRI: (OFIRI *)source toIRI: (OFIRI *)destination;

/**
 * @brief Returns the extended attribute data for the specified name of the
 *	  item at the specified IRI.
 *
 * This method is not available for all IRIs.
 *
 * @param name The name of the extended attribute
 * @param IRI The IRI of the item to return the extended attribute from
 * @throw OFGetItemAttributesFailedException Getting the extended attribute
 *					     failed
 * @throw OFUnsupportedProtocolException The handler cannot handle the IRI's
 *					 scheme
 * @throw OFNotImplementedException Getting extended attributes is not
 *				    implemented for the specified item
 */
- (OFData *)extendedAttributeDataForName: (OFString *)name
			     ofItemAtIRI: (OFIRI *)IRI;

/**
 * @brief Sets the extended attribute data for the specified name of the item
 *	  at the specified IRI.
 *
 * This method is not available for all IRIs.
 *
 * @param data The data for the extended attribute
 * @param name The name of the extended attribute
 * @param IRI The IRI of the item to set the extended attribute on
 * @throw OFSetItemAttributesFailedException Setting the extended attribute
 *					     failed
 * @throw OFUnsupportedProtocolException The handler cannot handle the IRI's
 *					 scheme
 * @throw OFNotImplementedException Setting extended attributes is not
 *				    implemented for the specified item
 */
- (void)setExtendedAttributeData: (OFData *)data
			 forName: (OFString *)name
		     ofItemAtIRI: (OFIRI *)IRI;

/**
 * @brief Removes the extended attribute for the specified name wof the item at
 *	  the specified IRI.
 *
 * This method is not available for all IRIs.
 *
 * @param name The name of the extended attribute to remove
 * @param IRI The IRI of the item to remove the extended attribute from
 * @throw OFSetItemAttributesFailedException Removing the extended attribute
 *					     failed
 * @throw OFUnsupportedProtocolException The handler cannot handle the IRI's
 *					 scheme
 * @throw OFNotImplementedException Removing extended attributes is not
 *				    implemented for the specified item
 */
- (void)removeExtendedAttributeForName: (OFString *)name
			   ofItemAtIRI: (OFIRI *)IRI;
@end

OF_ASSUME_NONNULL_END

Renamed and modified src/OFURIHandler.m [1cc8c8dac2] to src/OFIRIHandler.m [da6515064f].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#import "OFURIHandler.h"
#import "OFDictionary.h"
#import "OFNumber.h"
#import "OFURI.h"

#ifdef OF_HAVE_THREADS
# import "OFMutex.h"
#endif

#import "OFArchiveURIHandler.h"
#import "OFEmbeddedURIHandler.h"
#ifdef OF_HAVE_FILES
# import "OFFileURIHandler.h"
#endif
#if defined(OF_HAVE_SOCKETS) && defined(OF_HAVE_THREADS)
# import "OFHTTPURIHandler.h"
#endif

#import "OFUnsupportedProtocolException.h"

static OFMutableDictionary OF_GENERIC(OFString *, OFURIHandler *) *handlers;
#ifdef OF_HAVE_THREADS
static OFMutex *mutex;

static void
releaseMutex(void)
{
	[mutex release];
}
#endif

@implementation OFURIHandler
@synthesize scheme = _scheme;

+ (void)initialize
{
	if (self != [OFURIHandler class])
		return;

	handlers = [[OFMutableDictionary alloc] init];
#ifdef OF_HAVE_THREADS
	mutex = [[OFMutex alloc] init];
	atexit(releaseMutex);
#endif

	[self registerClass: [OFEmbeddedURIHandler class]
		  forScheme: @"embedded"];
#ifdef OF_HAVE_FILES
	[self registerClass: [OFFileURIHandler class] forScheme: @"file"];
#endif
#if defined(OF_HAVE_SOCKETS) && defined(OF_HAVE_THREADS)
	[self registerClass: [OFHTTPURIHandler class] forScheme: @"http"];
	[self registerClass: [OFHTTPURIHandler class] forScheme: @"https"];
#endif
	[self registerClass: [OFArchiveURIHandler class] forScheme: @"gzip"];
	[self registerClass: [OFArchiveURIHandler class] forScheme: @"lha"];
	[self registerClass: [OFArchiveURIHandler class] forScheme: @"tar"];
	[self registerClass: [OFArchiveURIHandler class] forScheme: @"zip"];
}

+ (bool)registerClass: (Class)class forScheme: (OFString *)scheme
{
#ifdef OF_HAVE_THREADS
	[mutex lock];
	@try {
#endif
		OFURIHandler *handler;

		if ([handlers objectForKey: scheme] != nil)
			return false;

		handler = [[class alloc] initWithScheme: scheme];
		@try {
			[handlers setObject: handler forKey: scheme];
		} @finally {
			[handler release];
		}
#ifdef OF_HAVE_THREADS
	} @finally {
		[mutex unlock];
	}
#endif

	return true;
}

+ (OFURIHandler *)handlerForURI: (OFURI *)URI
{
	OF_KINDOF(OFURIHandler *) handler;

#ifdef OF_HAVE_THREADS
	[mutex lock];
	@try {
#endif
		handler = [handlers objectForKey: URI.scheme];
#ifdef OF_HAVE_THREADS
	} @finally {
		[mutex unlock];
	}
#endif

	if (handler == nil)
		@throw [OFUnsupportedProtocolException exceptionWithURI: URI];

	return handler;
}

+ (OFStream *)openItemAtURI: (OFURI *)URI mode: (OFString *)mode
{
	return [[self handlerForURI: URI] openItemAtURI: URI mode: mode];
}

- (instancetype)init
{
	OF_INVALID_INIT_METHOD
}


|















|

|
|





|
|

|


|




|










|




|








|


|


|
|

|
|
|
|








|



















|

|





|







|




|

|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
/*
 * Copyright (c) 2008-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 "OFIRIHandler.h"
#import "OFDictionary.h"
#import "OFIRI.h"
#import "OFNumber.h"

#ifdef OF_HAVE_THREADS
# import "OFMutex.h"
#endif

#import "OFArchiveIRIHandler.h"
#import "OFEmbeddedIRIHandler.h"
#ifdef OF_HAVE_FILES
# import "OFFileIRIHandler.h"
#endif
#if defined(OF_HAVE_SOCKETS) && defined(OF_HAVE_THREADS)
# import "OFHTTPIRIHandler.h"
#endif

#import "OFUnsupportedProtocolException.h"

static OFMutableDictionary OF_GENERIC(OFString *, OFIRIHandler *) *handlers;
#ifdef OF_HAVE_THREADS
static OFMutex *mutex;

static void
releaseMutex(void)
{
	[mutex release];
}
#endif

@implementation OFIRIHandler
@synthesize scheme = _scheme;

+ (void)initialize
{
	if (self != [OFIRIHandler class])
		return;

	handlers = [[OFMutableDictionary alloc] init];
#ifdef OF_HAVE_THREADS
	mutex = [[OFMutex alloc] init];
	atexit(releaseMutex);
#endif

	[self registerClass: [OFEmbeddedIRIHandler class]
		  forScheme: @"embedded"];
#ifdef OF_HAVE_FILES
	[self registerClass: [OFFileIRIHandler class] forScheme: @"file"];
#endif
#if defined(OF_HAVE_SOCKETS) && defined(OF_HAVE_THREADS)
	[self registerClass: [OFHTTPIRIHandler class] forScheme: @"http"];
	[self registerClass: [OFHTTPIRIHandler class] forScheme: @"https"];
#endif
	[self registerClass: [OFArchiveIRIHandler class] forScheme: @"gzip"];
	[self registerClass: [OFArchiveIRIHandler class] forScheme: @"lha"];
	[self registerClass: [OFArchiveIRIHandler class] forScheme: @"tar"];
	[self registerClass: [OFArchiveIRIHandler class] forScheme: @"zip"];
}

+ (bool)registerClass: (Class)class forScheme: (OFString *)scheme
{
#ifdef OF_HAVE_THREADS
	[mutex lock];
	@try {
#endif
		OFIRIHandler *handler;

		if ([handlers objectForKey: scheme] != nil)
			return false;

		handler = [[class alloc] initWithScheme: scheme];
		@try {
			[handlers setObject: handler forKey: scheme];
		} @finally {
			[handler release];
		}
#ifdef OF_HAVE_THREADS
	} @finally {
		[mutex unlock];
	}
#endif

	return true;
}

+ (OFIRIHandler *)handlerForIRI: (OFIRI *)IRI
{
	OF_KINDOF(OFIRIHandler *) handler;

#ifdef OF_HAVE_THREADS
	[mutex lock];
	@try {
#endif
		handler = [handlers objectForKey: IRI.scheme];
#ifdef OF_HAVE_THREADS
	} @finally {
		[mutex unlock];
	}
#endif

	if (handler == nil)
		@throw [OFUnsupportedProtocolException exceptionWithIRI: IRI];

	return handler;
}

+ (OFStream *)openItemAtIRI: (OFIRI *)IRI mode: (OFString *)mode
{
	return [[self handlerForIRI: IRI] openItemAtIRI: IRI mode: mode];
}

- (instancetype)init
{
	OF_INVALID_INIT_METHOD
}

149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206




207

208
209
210
211





212



213


214




215
216
- (void)dealloc
{
	[_scheme release];

	[super dealloc];
}

- (OFStream *)openItemAtURI: (OFURI *)URI mode: (OFString *)mode
{
	OF_UNRECOGNIZED_SELECTOR
}

- (OFFileAttributes)attributesOfItemAtURI: (OFURI *)URI
{
	OF_UNRECOGNIZED_SELECTOR
}

- (void)setAttributes: (OFFileAttributes)attributes ofItemAtURI: (OFURI *)URI
{
	OF_UNRECOGNIZED_SELECTOR
}

- (bool)fileExistsAtURI: (OFURI *)URI
{
	OF_UNRECOGNIZED_SELECTOR
}

- (bool)directoryExistsAtURI: (OFURI *)URI
{
	OF_UNRECOGNIZED_SELECTOR
}

- (void)createDirectoryAtURI: (OFURI *)URI
{
	OF_UNRECOGNIZED_SELECTOR
}

- (OFArray OF_GENERIC(OFURI *) *)contentsOfDirectoryAtURI: (OFURI *)URI
{
	OF_UNRECOGNIZED_SELECTOR
}

- (void)removeItemAtURI: (OFURI *)URI
{
	OF_UNRECOGNIZED_SELECTOR
}

- (void)linkItemAtURI: (OFURI *)source toURI: (OFURI *)destination
{
	OF_UNRECOGNIZED_SELECTOR
}

- (void)createSymbolicLinkAtURI: (OFURI *)destination
	    withDestinationPath: (OFString *)source
{
	OF_UNRECOGNIZED_SELECTOR
}





- (bool)copyItemAtURI: (OFURI *)source toURI: (OFURI *)destination

{
	return false;
}






- (bool)moveItemAtURI: (OFURI *)source toURI: (OFURI *)destination



{


	return false;




}
@end







|




|




|




|




|




|




|




|




|




|





>
>
>
>
|
>




>
>
>
>
>
|
>
>
>

>
>
|
>
>
>
>


149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
- (void)dealloc
{
	[_scheme release];

	[super dealloc];
}

- (OFStream *)openItemAtIRI: (OFIRI *)IRI mode: (OFString *)mode
{
	OF_UNRECOGNIZED_SELECTOR
}

- (OFFileAttributes)attributesOfItemAtIRI: (OFIRI *)IRI
{
	OF_UNRECOGNIZED_SELECTOR
}

- (void)setAttributes: (OFFileAttributes)attributes ofItemAtIRI: (OFIRI *)IRI
{
	OF_UNRECOGNIZED_SELECTOR
}

- (bool)fileExistsAtIRI: (OFIRI *)IRI
{
	OF_UNRECOGNIZED_SELECTOR
}

- (bool)directoryExistsAtIRI: (OFIRI *)IRI
{
	OF_UNRECOGNIZED_SELECTOR
}

- (void)createDirectoryAtIRI: (OFIRI *)IRI
{
	OF_UNRECOGNIZED_SELECTOR
}

- (OFArray OF_GENERIC(OFIRI *) *)contentsOfDirectoryAtIRI: (OFIRI *)IRI
{
	OF_UNRECOGNIZED_SELECTOR
}

- (void)removeItemAtIRI: (OFIRI *)IRI
{
	OF_UNRECOGNIZED_SELECTOR
}

- (void)linkItemAtIRI: (OFIRI *)source toIRI: (OFIRI *)destination
{
	OF_UNRECOGNIZED_SELECTOR
}

- (void)createSymbolicLinkAtIRI: (OFIRI *)destination
	    withDestinationPath: (OFString *)source
{
	OF_UNRECOGNIZED_SELECTOR
}

- (bool)copyItemAtIRI: (OFIRI *)source toIRI: (OFIRI *)destination
{
	return false;
}

- (bool)moveItemAtIRI: (OFIRI *)source toIRI: (OFIRI *)destination
{
	return false;
}

- (OFData *)extendedAttributeDataForName: (OFString *)name
			     ofItemAtIRI: (OFIRI *)IRI
{
	OF_UNRECOGNIZED_SELECTOR
}

- (void)setExtendedAttributeData: (OFData *)data
			 forName: (OFString *)name
		     ofItemAtIRI: (OFIRI *)IRI
{
	OF_UNRECOGNIZED_SELECTOR
}

- (void)removeExtendedAttributeForName: (OFString *)name
			   ofItemAtIRI: (OFIRI *)IRI
{
	OF_UNRECOGNIZED_SELECTOR
}
@end

Modified src/OFInflate64Stream.h from [2f3dc057f8] to [81962f8340].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
66
67
68
69
70
71
72








73
74
75
76
77
78
79
			int state;
			uint16_t value, length, distance, extraBits;
		} huffman;
	} _context;
	bool _inLastBlock, _atEndOfStream;
}









/**
 * @brief Creates a new OFInflate64Stream with the specified underlying stream.
 *
 * @param stream The underlying stream to which compressed data is written or
 *		 from which compressed data is read
 * @return A new, autoreleased OFInflate64Stream
 */







>
>
>
>
>
>
>
>







66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
			int state;
			uint16_t value, length, distance, extraBits;
		} huffman;
	} _context;
	bool _inLastBlock, _atEndOfStream;
}

/**
 * @brief The underlying stream of the inflate stream.
 *
 * Setting this can be useful if the the data to be inflated is coming from
 * multiple streams, such as split across multiple files.
 */
@property (retain, nonatomic) OFStream *underlyingStream;

/**
 * @brief Creates a new OFInflate64Stream with the specified underlying stream.
 *
 * @param stream The underlying stream to which compressed data is written or
 *		 from which compressed data is read
 * @return A new, autoreleased OFInflate64Stream
 */

Modified src/OFInflate64Stream.m from [96e65e9055] to [97f84392a9].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFInflateStream.h from [fe62e030fd] to [894d68d12f].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
66
67
68
69
70
71
72








73
74
75
76
77
78
79
			int state;
			uint16_t value, length, distance, extraBits;
		} huffman;
	} _context;
	bool _inLastBlock, _atEndOfStream;
}









/**
 * @brief Creates a new OFInflateStream with the specified underlying stream.
 *
 * @param stream The underlying stream to which compressed data is written or
 *		 from which compressed data is read
 * @return A new, autoreleased OFInflateStream
 */







>
>
>
>
>
>
>
>







66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
			int state;
			uint16_t value, length, distance, extraBits;
		} huffman;
	} _context;
	bool _inLastBlock, _atEndOfStream;
}

/**
 * @brief The underlying stream of the inflate stream.
 *
 * Setting this can be useful if the the data to be inflated is coming from
 * multiple streams, such as split across multiple files.
 */
@property (retain, nonatomic) OFStream *underlyingStream;

/**
 * @brief Creates a new OFInflateStream with the specified underlying stream.
 *
 * @param stream The underlying stream to which compressed data is written or
 *		 from which compressed data is read
 * @return A new, autoreleased OFInflateStream
 */

Modified src/OFInflateStream.m from [28d4702177] to [6ae6dfa239].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#include <stdlib.h>
#include <string.h>

#include <assert.h>

#ifndef OF_INFLATE64_STREAM_M
# import "OFInflateStream.h"
#else
# import "OFInflate64Stream.h"
# define OFInflateStream OFInflate64Stream
#endif
#import "OFHuffmanTree.h"

|


















<
<







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20


21
22
23
24
25
26
27
/*
 * Copyright (c) 2008-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 <stdlib.h>
#include <string.h>



#ifndef OF_INFLATE64_STREAM_M
# import "OFInflateStream.h"
#else
# import "OFInflate64Stream.h"
# define OFInflateStream OFInflate64Stream
#endif
#import "OFHuffmanTree.h"
98
99
100
101
102
103
104


105
106
107
108
109
110
111
112
113
114
115
116
117
#endif
static const uint8_t codeLengthsOrder[19] = {
	16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
};
static OFHuffmanTree fixedLitLenTree, fixedDistTree;

@implementation OFInflateStream


static OF_INLINE bool
tryReadBits(OFInflateStream *stream, uint16_t *bits, uint8_t count)
{
	uint16_t ret = stream->_savedBits;

	assert(stream->_savedBitsLength < count);

	for (uint_fast8_t i = stream->_savedBitsLength; i < count; i++) {
		if OF_UNLIKELY (stream->_bitIndex == 8) {
			if OF_LIKELY (stream->_bufferIndex <
			    stream->_bufferLength)
				stream->_byte =
				    stream->_buffer[stream->_bufferIndex++];







>
>





|







96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
#endif
static const uint8_t codeLengthsOrder[19] = {
	16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
};
static OFHuffmanTree fixedLitLenTree, fixedDistTree;

@implementation OFInflateStream
@synthesize underlyingStream = _stream;

static OF_INLINE bool
tryReadBits(OFInflateStream *stream, uint16_t *bits, uint8_t count)
{
	uint16_t ret = stream->_savedBits;

	OFAssert(stream->_savedBitsLength < count);

	for (uint_fast8_t i = stream->_savedBitsLength; i < count; i++) {
		if OF_UNLIKELY (stream->_bitIndex == 8) {
			if OF_LIKELY (stream->_bufferIndex <
			    stream->_bufferLength)
				stream->_byte =
				    stream->_buffer[stream->_bufferIndex++];
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686

- (int)fileDescriptorForReading
{
	return ((id <OFReadyForReadingObserving>)_stream)
	    .fileDescriptorForReading;
}

- (bool)hasDataInReadBuffer
{
	return (super.hasDataInReadBuffer || _stream.hasDataInReadBuffer ||
	    _bufferLength - _bufferIndex > 0);
}

- (void)close
{
	if (_stream == nil)
		@throw [OFNotOpenException exceptionWithObject: self];







|

|







670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686

- (int)fileDescriptorForReading
{
	return ((id <OFReadyForReadingObserving>)_stream)
	    .fileDescriptorForReading;
}

- (bool)lowlevelHasDataInReadBuffer
{
	return (_stream.hasDataInReadBuffer ||
	    _bufferLength - _bufferIndex > 0);
}

- (void)close
{
	if (_stream == nil)
		@throw [OFNotOpenException exceptionWithObject: self];

Modified src/OFInvertedCharacterSet.h from [d4b8559d77] to [e7d1fd5a23].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFInvertedCharacterSet.m from [1e78ebb0a4] to [c4614051f1].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFInvocation.h from [ab7d9433d5] to [3b94fe4d77].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFInvocation.m from [5937b080ad] to [7d5d9bca30].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFJSONRepresentation.h from [2bd85161f3] to [e721055d97].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFKernelEventObserver.h from [81efdafa0c] to [eb3d0cf38f].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
/**
 * @brief This callback is called when an object did get ready for writing.
 *
 * @param object The object which did become ready for writing
 */
- (void)objectIsReadyForWriting: (id)object;

#ifdef OF_AMIGAOS
/**
 * @brief This callback is called when an Exec Signal was received.
 *
 * @note This is only available on AmigaOS!
 */
- (void)execSignalWasReceived: (ULONG)signalMask;
#endif







|







60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
/**
 * @brief This callback is called when an object did get ready for writing.
 *
 * @param object The object which did become ready for writing
 */
- (void)objectIsReadyForWriting: (id)object;

#if defined(OF_AMIGAOS) || defined(DOXYGEN)
/**
 * @brief This callback is called when an Exec Signal was received.
 *
 * @note This is only available on AmigaOS!
 */
- (void)execSignalWasReceived: (ULONG)signalMask;
#endif
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
@interface OFKernelEventObserver: OFObject
{
	OFMutableArray OF_GENERIC(id <OFReadyForReadingObserving>)
	    *_readObjects;
	OFMutableArray OF_GENERIC(id <OFReadyForWritingObserving>)
	    *_writeObjects;
	id <OFKernelEventObserverDelegate> _Nullable _delegate;
#if defined(OF_AMIGAOS)
	struct Task *_waitingTask;
	ULONG _cancelSignal;
#elif defined(OF_HAVE_PIPE)
	int _cancelFD[2];
#else
	OFSocketHandle _cancelFD[2];
	struct sockaddr_in _cancelAddr;
#endif
#ifdef OF_AMIGAOS
	ULONG _execSignalMask;
#endif
	OF_RESERVE_IVARS(OFKernelEventObserver, 4)
}

/**
 * @brief The delegate for the OFKernelEventObserver.
 */
@property OF_NULLABLE_PROPERTY (assign, nonatomic)
    id <OFKernelEventObserverDelegate> delegate;

#ifdef OF_AMIGAOS
/**
 * @brief A mask of Exec Signals to wait for.
 *
 * @note This is only available on AmigaOS!
 */
@property (nonatomic) ULONG execSignalMask;
#endif

/**
 * @brief Creates a new OFKernelEventObserver.
 *
 * @return A new, autoreleased OFKernelEventObserver
 */
+ (instancetype)observer;







|


|

|


|
|

|









|






|







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
@interface OFKernelEventObserver: OFObject
{
	OFMutableArray OF_GENERIC(id <OFReadyForReadingObserving>)
	    *_readObjects;
	OFMutableArray OF_GENERIC(id <OFReadyForWritingObserving>)
	    *_writeObjects;
	id <OFKernelEventObserverDelegate> _Nullable _delegate;
# if defined(OF_AMIGAOS)
	struct Task *_waitingTask;
	ULONG _cancelSignal;
# elif defined(OF_HAVE_PIPE)
	int _cancelFD[2];
# else
	OFSocketHandle _cancelFD[2];
	struct sockaddr_in _cancelAddr;
# endif
# ifdef OF_AMIGAOS
	ULONG _execSignalMask;
# endif
	OF_RESERVE_IVARS(OFKernelEventObserver, 4)
}

/**
 * @brief The delegate for the OFKernelEventObserver.
 */
@property OF_NULLABLE_PROPERTY (assign, nonatomic)
    id <OFKernelEventObserverDelegate> delegate;

# if defined(OF_AMIGAOS) || defined(DOXYGEN)
/**
 * @brief A mask of Exec Signals to wait for.
 *
 * @note This is only available on AmigaOS!
 */
@property (nonatomic) ULONG execSignalMask;
# endif

/**
 * @brief Creates a new OFKernelEventObserver.
 *
 * @return A new, autoreleased OFKernelEventObserver
 */
+ (instancetype)observer;

Modified src/OFKernelEventObserver.m from [8d008316fd] to [fd95409b3f].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
44
45
46
47
48
49
50

51

52
53
54
55
56
57
58
#endif

#import "OFInitializationFailedException.h"
#import "OFInvalidArgumentException.h"
#import "OFOutOfRangeException.h"

#ifdef OF_AMIGAOS

# include <proto/exec.h>

#endif

@implementation OFKernelEventObserver
@synthesize delegate = _delegate;
#ifdef OF_AMIGAOS
@synthesize execSignalMask = _execSignalMask;
#endif







>

>







44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#endif

#import "OFInitializationFailedException.h"
#import "OFInvalidArgumentException.h"
#import "OFOutOfRangeException.h"

#ifdef OF_AMIGAOS
# define Class IntuitionClass
# include <proto/exec.h>
# undef Class
#endif

@implementation OFKernelEventObserver
@synthesize delegate = _delegate;
#ifdef OF_AMIGAOS
@synthesize execSignalMask = _execSignalMask;
#endif
202
203
204
205
206
207
208
209
210
211




212
213

214
215
216
217
218
219
220

- (bool)of_processReadBuffers
{
	void *pool = objc_autoreleasePoolPush();
	bool foundInReadBuffer = false;

	for (id object in [[_readObjects copy] autorelease]) {
		void *pool2 = objc_autoreleasePoolPush();

		if ([object isKindOfClass: [OFStream class]] &&




		    [object hasDataInReadBuffer] &&
		    ![(OFStream *)object of_isWaitingForDelimiter]) {

			if ([_delegate respondsToSelector:
			    @selector(objectIsReadyForReading:)])
				[_delegate objectIsReadyForReading: object];

			foundInReadBuffer = true;
		}








|

|
>
>
>
>
|
|
>







204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227

- (bool)of_processReadBuffers
{
	void *pool = objc_autoreleasePoolPush();
	bool foundInReadBuffer = false;

	for (id object in [[_readObjects copy] autorelease]) {
		void *pool2;

		if (![object isKindOfClass: [OFStream class]])
			continue;

		pool2 = objc_autoreleasePoolPush();

		if ([object hasDataInReadBuffer] &&
		    (![object of_isWaitingForDelimiter] ||
		    [object lowlevelHasDataInReadBuffer])) {
			if ([_delegate respondsToSelector:
			    @selector(objectIsReadyForReading:)])
				[_delegate objectIsReadyForReading: object];

			foundInReadBuffer = true;
		}

Modified src/OFKeyValueCoding.h from [3568d90874] to [88d8e5ab72].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFKqueueKernelEventObserver.h from [79cac968ba] to [26eeb86ead].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFKqueueKernelEventObserver.m from [ef6117c8da] to [a5e350273f].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the 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 <assert.h>
#include <errno.h>

#ifdef HAVE_FCNTL_H
# include <fcntl.h>
#endif
#include "unistd_wrapper.h"


|















<







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

18
19
20
21
22
23
24
/*
 * Copyright (c) 2008-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 <errno.h>

#ifdef HAVE_FCNTL_H
# include <fcntl.h>
#endif
#include "unistd_wrapper.h"

184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
			@throw [OFObserveKernelEventsFailedException
			    exceptionWithObserver: self
					    errNo: (int)eventList[i].data];

		if (eventList[i].ident == (uintptr_t)_cancelFD[0]) {
			char buffer;

			assert(eventList[i].filter == EVFILT_READ);
			OFEnsure(read(_cancelFD[0], &buffer, 1) == 1);

			continue;
		}

		pool = objc_autoreleasePoolPush();








|







183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
			@throw [OFObserveKernelEventsFailedException
			    exceptionWithObserver: self
					    errNo: (int)eventList[i].data];

		if (eventList[i].ident == (uintptr_t)_cancelFD[0]) {
			char buffer;

			OFAssert(eventList[i].filter == EVFILT_READ);
			OFEnsure(read(_cancelFD[0], &buffer, 1) == 1);

			continue;
		}

		pool = objc_autoreleasePoolPush();

206
207
208
209
210
211
212
213
214
215
216
217
218
219
		case EVFILT_WRITE:
			if ([_delegate respondsToSelector:
			    @selector(objectIsReadyForWriting:)])
				[_delegate objectIsReadyForWriting:
				    (id)eventList[i].udata];
			break;
		default:
			assert(0);
		}

		objc_autoreleasePoolPop(pool);
	}
}
@end







|






205
206
207
208
209
210
211
212
213
214
215
216
217
218
		case EVFILT_WRITE:
			if ([_delegate respondsToSelector:
			    @selector(objectIsReadyForWriting:)])
				[_delegate objectIsReadyForWriting:
				    (id)eventList[i].udata];
			break;
		default:
			OFAssert(0);
		}

		objc_autoreleasePoolPop(pool);
	}
}
@end

Modified src/OFLHAArchive.h from [038ec719a6] to [ef6819705d].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#import "OFObject.h"
#import "OFKernelEventObserver.h"
#import "OFLHAArchiveEntry.h"
#import "OFString.h"

OF_ASSUME_NONNULL_BEGIN

@class OFStream;
@class OFURI;

/**
 * @class OFLHAArchive OFLHAArchive.h ObjFW/OFLHAArchive.h
 *
 * @brief A class for accessing and manipulating LHA files.
 */
OF_SUBCLASSING_RESTRICTED

|




















|
|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/*
 * Copyright (c) 2008-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 "OFObject.h"
#import "OFKernelEventObserver.h"
#import "OFLHAArchiveEntry.h"
#import "OFString.h"

OF_ASSUME_NONNULL_BEGIN

@class OFIRI;
@class OFStream;

/**
 * @class OFLHAArchive OFLHAArchive.h ObjFW/OFLHAArchive.h
 *
 * @brief A class for accessing and manipulating LHA files.
 */
OF_SUBCLASSING_RESTRICTED
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
 * @return A new, autoreleased OFLHAArchive
 */
+ (instancetype)archiveWithStream: (OFStream *)stream mode: (OFString *)mode;

/**
 * @brief Creates a new OFLHAArchive object with the specified file.
 *
 * @param URI The URI to the LHA file
 * @param mode The mode for the LHA file. Valid modes are "r" for reading,
 *	       "w" for creating a new file and "a" for appending to an existing
 *	       archive.
 * @return A new, autoreleased OFLHAArchive
 */
+ (instancetype)archiveWithURI: (OFURI *)URI mode: (OFString *)mode;

/**
 * @brief Creates a URI for accessing a the specified file within the specified
 *	  LHA archive.
 *
 * @param path The path of the file within the archive
 * @param URI The URI of the archive
 * @return A URI for accessing the specified file within the specified LHA
 *	   archive
 */
+ (OFURI *)URIForFilePath: (OFString *)path inArchiveWithURI: (OFURI *)URI;

- (instancetype)init OF_UNAVAILABLE;

/**
 * @brief Initializes an already allocated OFLHAArchive object with the
 *	  specified stream.
 *







|





|


|
|


|
|


|







57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
 * @return A new, autoreleased OFLHAArchive
 */
+ (instancetype)archiveWithStream: (OFStream *)stream mode: (OFString *)mode;

/**
 * @brief Creates a new OFLHAArchive object with the specified file.
 *
 * @param IRI The IRI to the LHA file
 * @param mode The mode for the LHA file. Valid modes are "r" for reading,
 *	       "w" for creating a new file and "a" for appending to an existing
 *	       archive.
 * @return A new, autoreleased OFLHAArchive
 */
+ (instancetype)archiveWithIRI: (OFIRI *)IRI mode: (OFString *)mode;

/**
 * @brief Creates an IRI for accessing a the specified file within the
 *	  specified LHA archive.
 *
 * @param path The path of the file within the archive
 * @param IRI The IRI of the archive
 * @return An IRI for accessing the specified file within the specified LHA
 *	   archive
 */
+ (OFIRI *)IRIForFilePath: (OFString *)path inArchiveWithIRI: (OFIRI *)IRI;

- (instancetype)init OF_UNAVAILABLE;

/**
 * @brief Initializes an already allocated OFLHAArchive object with the
 *	  specified stream.
 *
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
- (instancetype)initWithStream: (OFStream *)stream
			  mode: (OFString *)mode OF_DESIGNATED_INITIALIZER;

/**
 * @brief Initializes an already allocated OFLHAArchive object with the
 *	  specified file.
 *
 * @param URI The URI to the LHA file
 * @param mode The mode for the LHA file. Valid modes are "r" for reading,
 *	       "w" for creating a new file and "a" for appending to an existing
 *	       archive.
 * @return An initialized OFLHAArchive
 */
- (instancetype)initWithURI: (OFURI *)URI mode: (OFString *)mode;

/**
 * @brief Returns the next entry from the LHA archive or `nil` if all entries
 *	  have been read.
 *
 * @note This is only available in read mode.
 *







|





|







96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
- (instancetype)initWithStream: (OFStream *)stream
			  mode: (OFString *)mode OF_DESIGNATED_INITIALIZER;

/**
 * @brief Initializes an already allocated OFLHAArchive object with the
 *	  specified file.
 *
 * @param IRI The IRI to the LHA file
 * @param mode The mode for the LHA file. Valid modes are "r" for reading,
 *	       "w" for creating a new file and "a" for appending to an existing
 *	       archive.
 * @return An initialized OFLHAArchive
 */
- (instancetype)initWithIRI: (OFIRI *)IRI mode: (OFString *)mode;

/**
 * @brief Returns the next entry from the LHA archive or `nil` if all entries
 *	  have been read.
 *
 * @note This is only available in read mode.
 *

Modified src/OFLHAArchive.m from [fa04eb799a] to [653818a552].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
18
19
20
21
22
23
24
25
26


27
28
29
30
31
32
33
34
35
36
37
38
39
#include "config.h"

#include <errno.h>

#import "OFLHAArchive.h"
#import "OFLHAArchiveEntry.h"
#import "OFLHAArchiveEntry+Private.h"
#import "OFArchiveURIHandler.h"
#import "OFCRC16.h"


#import "OFLHADecompressingStream.h"
#import "OFSeekableStream.h"
#import "OFStream.h"
#import "OFString.h"
#import "OFURI.h"
#import "OFURIHandler.h"

#import "OFChecksumMismatchException.h"
#import "OFInvalidArgumentException.h"
#import "OFNotImplementedException.h"
#import "OFNotOpenException.h"
#import "OFOutOfRangeException.h"
#import "OFTruncatedDataException.h"







|

>
>




<
<







18
19
20
21
22
23
24
25
26
27
28
29
30
31
32


33
34
35
36
37
38
39
#include "config.h"

#include <errno.h>

#import "OFLHAArchive.h"
#import "OFLHAArchiveEntry.h"
#import "OFLHAArchiveEntry+Private.h"
#import "OFArchiveIRIHandler.h"
#import "OFCRC16.h"
#import "OFIRI.h"
#import "OFIRIHandler.h"
#import "OFLHADecompressingStream.h"
#import "OFSeekableStream.h"
#import "OFStream.h"
#import "OFString.h"



#import "OFChecksumMismatchException.h"
#import "OFInvalidArgumentException.h"
#import "OFNotImplementedException.h"
#import "OFNotOpenException.h"
#import "OFOutOfRangeException.h"
#import "OFTruncatedDataException.h"
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
@synthesize encoding = _encoding;

+ (instancetype)archiveWithStream: (OFStream *)stream mode: (OFString *)mode
{
	return [[[self alloc] initWithStream: stream mode: mode] autorelease];
}

+ (instancetype)archiveWithURI: (OFURI *)URI mode: (OFString *)mode
{
	return [[[self alloc] initWithURI: URI mode: mode] autorelease];
}

+ (OFURI *)URIForFilePath: (OFString *)path inArchiveWithURI: (OFURI *)URI
{
	return OFArchiveURIHandlerURIForFileInArchive(@"lha", path, URI);
}

- (instancetype)init
{
	OF_INVALID_INIT_METHOD
}








|

|


|

|







84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
@synthesize encoding = _encoding;

+ (instancetype)archiveWithStream: (OFStream *)stream mode: (OFString *)mode
{
	return [[[self alloc] initWithStream: stream mode: mode] autorelease];
}

+ (instancetype)archiveWithIRI: (OFIRI *)IRI mode: (OFString *)mode
{
	return [[[self alloc] initWithIRI: IRI mode: mode] autorelease];
}

+ (OFIRI *)IRIForFilePath: (OFString *)path inArchiveWithIRI: (OFIRI *)IRI
{
	return OFArchiveIRIHandlerIRIForFileInArchive(@"lha", path, IRI);
}

- (instancetype)init
{
	OF_INVALID_INIT_METHOD
}

132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
		[self release];
		@throw e;
	}

	return self;
}

- (instancetype)initWithURI: (OFURI *)URI mode: (OFString *)mode
{
	void *pool = objc_autoreleasePoolPush();
	OFStream *stream;

	@try {
		if ([mode isEqual: @"a"])
			stream = [OFURIHandler openItemAtURI: URI mode: @"r+"];
		else
			stream = [OFURIHandler openItemAtURI: URI mode: mode];
	} @catch (id e) {
		[self release];
		@throw e;
	}

	self = [self initWithStream: stream mode: mode];








|






|

|







132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
		[self release];
		@throw e;
	}

	return self;
}

- (instancetype)initWithIRI: (OFIRI *)IRI mode: (OFString *)mode
{
	void *pool = objc_autoreleasePoolPush();
	OFStream *stream;

	@try {
		if ([mode isEqual: @"a"])
			stream = [OFIRIHandler openItemAtIRI: IRI mode: @"r+"];
		else
			stream = [OFIRIHandler openItemAtIRI: IRI mode: mode];
	} @catch (id e) {
		[self release];
		@throw e;
	}

	self = [self initWithStream: stream mode: mode];

171
172
173
174
175
176
177













178
179
180
181
182
183
184
- (OFLHAArchiveEntry *)nextEntry
{
	char header[21];
	size_t headerLen;

	if (_mode != modeRead)
		@throw [OFInvalidArgumentException exception];














	[_currentEntry release];
	_currentEntry = nil;

	[(OFLHAArchiveFileReadStream *)_lastReturnedStream of_skip];
	@try {
		[_lastReturnedStream close];







>
>
>
>
>
>
>
>
>
>
>
>
>







171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
- (OFLHAArchiveEntry *)nextEntry
{
	char header[21];
	size_t headerLen;

	if (_mode != modeRead)
		@throw [OFInvalidArgumentException exception];

	if (_currentEntry != nil && _lastReturnedStream == nil) {
		/*
		 * No read stream was created since the last call to
		 * -[nextEntry]. Create it so that we can properly skip the
		 *  data.
		 */
		void *pool = objc_autoreleasePoolPush();

		[self streamForReadingCurrentEntry];

		objc_autoreleasePoolPop(pool);
	}

	[_currentEntry release];
	_currentEntry = nil;

	[(OFLHAArchiveFileReadStream *)_lastReturnedStream of_skip];
	@try {
		[_lastReturnedStream close];
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
			@throw [OFTruncatedDataException exception];
		}

		headerLen += [_stream readIntoBuffer: header + headerLen
					      length: 21 - headerLen];
	}

	_currentEntry= [[OFLHAArchiveEntry alloc]
	    of_initWithHeader: header
		       stream: _stream
		     encoding: _encoding];

	return _currentEntry;
}








|







211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
			@throw [OFTruncatedDataException exception];
		}

		headerLen += [_stream readIntoBuffer: header + headerLen
					      length: 21 - headerLen];
	}

	_currentEntry = [[OFLHAArchiveEntry alloc]
	    of_initWithHeader: header
		       stream: _stream
		     encoding: _encoding];

	return _currentEntry;
}

Modified src/OFLHAArchiveEntry+Private.h from [521b95b2fc] to [03ffa14328].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFLHAArchiveEntry.h from [89ea23a8c1] to [2cbe09afd2].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFLHAArchiveEntry.m from [b338459827] to [79302ee500].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFLHADecompressingStream.h from [1061027b73] to [d0e10c1486].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFLHADecompressingStream.m from [1c43fdd671] to [e5ba07f07c].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#include <assert.h>

#import "OFLHADecompressingStream.h"
#import "OFKernelEventObserver.h"

#import "OFHuffmanTree.h"

#import "OFInvalidFormatException.h"
#import "OFNotOpenException.h"

|















<
<







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17


18
19
20
21
22
23
24
/*
 * Copyright (c) 2008-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 "OFLHADecompressingStream.h"
#import "OFKernelEventObserver.h"

#import "OFHuffmanTree.h"

#import "OFInvalidFormatException.h"
#import "OFNotOpenException.h"
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
@synthesize bytesConsumed = _bytesConsumed;

static OF_INLINE bool
tryReadBits(OFLHADecompressingStream *stream, uint16_t *bits, uint8_t count)
{
	uint16_t ret = stream->_savedBits;

	assert(stream->_savedBitsLength < count);

	for (uint_fast8_t i = stream->_savedBitsLength; i < count; i++) {
		if OF_UNLIKELY (stream->_bitIndex == 8) {
			if OF_LIKELY (stream->_bufferIndex <
			    stream->_bufferLength)
				stream->_byte =
				    stream->_buffer[stream->_bufferIndex++];







|







44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
@synthesize bytesConsumed = _bytesConsumed;

static OF_INLINE bool
tryReadBits(OFLHADecompressingStream *stream, uint16_t *bits, uint8_t count)
{
	uint16_t ret = stream->_savedBits;

	OFAssert(stream->_savedBitsLength < count);

	for (uint_fast8_t i = stream->_savedBitsLength; i < count; i++) {
		if OF_UNLIKELY (stream->_bitIndex == 8) {
			if OF_LIKELY (stream->_bufferIndex <
			    stream->_bufferLength)
				stream->_byte =
				    stream->_buffer[stream->_bufferIndex++];
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521

- (int)fileDescriptorForReading
{
	return ((id <OFReadyForReadingObserving>)_stream)
	    .fileDescriptorForReading;
}

- (bool)hasDataInReadBuffer
{
	return (super.hasDataInReadBuffer || _stream.hasDataInReadBuffer ||
	    _bufferLength - _bufferIndex > 0);
}

- (void)close
{
	if (_stream == nil)
		@throw [OFNotOpenException exceptionWithObject: self];







|

|







503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519

- (int)fileDescriptorForReading
{
	return ((id <OFReadyForReadingObserving>)_stream)
	    .fileDescriptorForReading;
}

- (bool)lowlevelHasDataInReadBuffer
{
	return (_stream.hasDataInReadBuffer ||
	    _bufferLength - _bufferIndex > 0);
}

- (void)close
{
	if (_stream == nil)
		@throw [OFNotOpenException exceptionWithObject: self];

Modified src/OFList.h from [f2ae387af6] to [72f0b22ce8].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#import "OFObject.h"
#import "OFCollection.h"
#import "OFEnumerator.h"
#import "OFSerialization.h"

OF_ASSUME_NONNULL_BEGIN

/** @file */

/*
 * Make clang's -Wdocumentation shut about about using @struct on someting it

|
















<







1
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 "OFObject.h"
#import "OFCollection.h"
#import "OFEnumerator.h"


OF_ASSUME_NONNULL_BEGIN

/** @file */

/*
 * Make clang's -Wdocumentation shut about about using @struct on someting it
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
#endif

/**
 * @class OFList OFList.h ObjFW/OFList.h
 *
 * @brief A class which provides easy to use double-linked lists.
 */
@interface OFList OF_GENERIC(ObjectType): OFObject <OFCopying, OFCollection,
    OFSerialization>
#if !defined(OF_HAVE_GENERICS) && !defined(DOXYGEN)
# define ObjectType id
#endif
{
	OFListItem _Nullable _firstListItem;
	OFListItem _Nullable _lastListItem;
	size_t _count;







|
<







76
77
78
79
80
81
82
83

84
85
86
87
88
89
90
#endif

/**
 * @class OFList OFList.h ObjFW/OFList.h
 *
 * @brief A class which provides easy to use double-linked lists.
 */
@interface OFList OF_GENERIC(ObjectType): OFObject <OFCopying, OFCollection>

#if !defined(OF_HAVE_GENERICS) && !defined(DOXYGEN)
# define ObjectType id
#endif
{
	OFListItem _Nullable _firstListItem;
	OFListItem _Nullable _lastListItem;
	size_t _count;

Modified src/OFList.m from [18864abbc2] to [fff0146310].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the 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>
#include <assert.h>

#import "OFList.h"
#import "OFString.h"
#import "OFXMLElement.h"
#import "OFArray.h"

#import "OFEnumerationMutationException.h"
#import "OFInvalidArgumentException.h"

struct _OFListItem {
	struct _OFListItem *previous, *next;

|
















<



<







1
2
3
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"

#include <string.h>


#import "OFList.h"
#import "OFString.h"

#import "OFArray.h"

#import "OFEnumerationMutationException.h"
#import "OFInvalidArgumentException.h"

struct _OFListItem {
	struct _OFListItem *previous, *next;
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
@synthesize firstListItem = _firstListItem, lastListItem = _lastListItem;

+ (instancetype)list
{
	return [[[self alloc] init] autorelease];
}

- (instancetype)initWithSerialization: (OFXMLElement *)element
{
	self = [self init];

	@try {
		void *pool = objc_autoreleasePoolPush();

		if (![element.name isEqual: self.className] ||
		    ![element.namespace isEqual: OFSerializationNS])
			@throw [OFInvalidArgumentException exception];

		for (OFXMLElement *child in
		    [element elementsForNamespace: OFSerializationNS]) {
			void *pool2 = objc_autoreleasePoolPush();

			[self appendObject: child.objectByDeserializing];

			objc_autoreleasePoolPop(pool2);
		}

		objc_autoreleasePoolPop(pool);
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (void)dealloc
{
	OFListItem next;

	for (OFListItem iter = _firstListItem; iter != NULL; iter = next) {
		[iter->object release];
		next = iter->next;







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







64
65
66
67
68
69
70





























71
72
73
74
75
76
77
@synthesize firstListItem = _firstListItem, lastListItem = _lastListItem;

+ (instancetype)list
{
	return [[[self alloc] init] autorelease];
}






























- (void)dealloc
{
	OFListItem next;

	for (OFListItem iter = _firstListItem; iter != NULL; iter = next) {
		[iter->object release];
		next = iter->next;
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
	for (iter = _firstListItem, iter2 = list.firstListItem;
	    iter != NULL && iter2 != NULL;
	    iter = iter->next, iter2 = iter2->next)
		if (![iter->object isEqual: iter2->object])
			return false;

	/* One is bigger than the other even though we checked the count */
	assert(iter == NULL && iter2 == NULL);

	return true;
}

- (bool)containsObject: (id)object
{
	if (_count == 0)







|







221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
	for (iter = _firstListItem, iter2 = list.firstListItem;
	    iter != NULL && iter2 != NULL;
	    iter = iter->next, iter2 = iter2->next)
		if (![iter->object isEqual: iter2->object])
			return false;

	/* One is bigger than the other even though we checked the count */
	OFAssert(iter == NULL && iter2 == NULL);

	return true;
}

- (bool)containsObject: (id)object
{
	if (_count == 0)
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
	[ret appendString: @"\n]"];

	[ret makeImmutable];

	return ret;
}

- (OFXMLElement *)XMLElementBySerializing
{
	OFXMLElement *element =
	    [OFXMLElement elementWithName: self.className
				namespace: OFSerializationNS];

	for (OFListItem iter = _firstListItem;
	    iter != NULL; iter = iter->next) {
		void *pool = objc_autoreleasePoolPush();

		[element addChild: [iter->object XMLElementBySerializing]];

		objc_autoreleasePoolPop(pool);
	}

	return element;
}

- (int)countByEnumeratingWithState: (OFFastEnumerationState *)state
			   objects: (id *)objects
			     count: (int)count
{
	OFListItem listItem;

	memcpy(&listItem, state->extra, sizeof(listItem));







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







339
340
341
342
343
344
345


















346
347
348
349
350
351
352
	[ret appendString: @"\n]"];

	[ret makeImmutable];

	return ret;
}



















- (int)countByEnumeratingWithState: (OFFastEnumerationState *)state
			   objects: (id *)objects
			     count: (int)count
{
	OFListItem listItem;

	memcpy(&listItem, state->extra, sizeof(listItem));

Modified src/OFLocale.h from [ca12b9c93f] to [5b6f1c91ee].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19


20
21
22
23
24
25
26
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#import "OFObject.h"
#import "OFString.h"

OF_ASSUME_NONNULL_BEGIN



/** @file */

/**
 * @def OF_LOCALIZED
 *
 * @brief Returns the localized string for the specified ID with the specified

|

















>
>







1
2
3
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.
 */

#import "OFObject.h"
#import "OFString.h"

OF_ASSUME_NONNULL_BEGIN

@class OFIRI;

/** @file */

/**
 * @def OF_LOCALIZED
 *
 * @brief Returns the localized string for the specified ID with the specified
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
/**
 * @brief Returns the decimal point of the system's locale.
 *
 * @return The decimal point of the system's locale
 */
+ (nullable OFString *)decimalSeparator;

#ifdef OF_HAVE_FILES
/**
 * @brief Adds a directory to scan for localizations.
 *
 * @param path The path to the directory to scan for localizations
 */
+ (void)addLocalizationDirectory: (OFString *)path;
#endif

/**
 * @brief Initializes the current OFLocale.
 *
 * @warning This sets the locale via `setlocale()`!
 *
 * @warning You should never call this yourself, except if you do not use
 *	    @ref OFApplication. In this case, you need to allocate exactly one
 *	    instance of OFLocale, which will become the current locale, and
 *	    call this method.
 */
- (instancetype)init;

#ifdef OF_HAVE_FILES
/**
 * @brief Adds a directory to scan for localizations.
 *
 * @param path The path to the directory to scan for localizations 
 */
- (void)addLocalizationDirectory: (OFString *)path;
#endif

/**
 * @brief Returns the localized string for the specified ID, using the fallback
 *	  string if it cannot be looked up or is missing.
 *
 * @note This takes a variadic argument, terminated by `nil`, that consists of
 *	 pairs of variable names and variable values, which will be replaced







<



|

|
<













<



|

|
<







136
137
138
139
140
141
142

143
144
145
146
147
148

149
150
151
152
153
154
155
156
157
158
159
160
161

162
163
164
165
166
167

168
169
170
171
172
173
174
/**
 * @brief Returns the decimal point of the system's locale.
 *
 * @return The decimal point of the system's locale
 */
+ (nullable OFString *)decimalSeparator;


/**
 * @brief Adds a directory to scan for localizations.
 *
 * @param IRI The IRI to the directory to scan for localizations
 */
+ (void)addLocalizationDirectoryIRI: (OFIRI *)IRI;


/**
 * @brief Initializes the current OFLocale.
 *
 * @warning This sets the locale via `setlocale()`!
 *
 * @warning You should never call this yourself, except if you do not use
 *	    @ref OFApplication. In this case, you need to allocate exactly one
 *	    instance of OFLocale, which will become the current locale, and
 *	    call this method.
 */
- (instancetype)init;


/**
 * @brief Adds a directory to scan for localizations.
 *
 * @param IRI The IRI to the directory to scan for localizations
 */
- (void)addLocalizationDirectoryIRI: (OFIRI *)IRI;


/**
 * @brief Returns the localized string for the specified ID, using the fallback
 *	  string if it cannot be looked up or is missing.
 *
 * @note This takes a variadic argument, terminated by `nil`, that consists of
 *	 pairs of variable names and variable values, which will be replaced

Modified src/OFLocale.m from [e8b5569b76] to [8178789b63].

1
2
3
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
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#include <locale.h>

#import "OFLocale.h"
#import "OFString.h"
#import "OFArray.h"
#import "OFDictionary.h"
#import "OFNumber.h"


#import "OFInitializationFailedException.h"
#import "OFInvalidArgumentException.h"
#import "OFInvalidFormatException.h"
#import "OFOpenItemFailedException.h"

#ifdef OF_AMIGAOS

# include <proto/dos.h>
# include <proto/exec.h>
# include <proto/locale.h>

#endif

static OFLocale *currentLocale = nil;
static OFDictionary *operatorPrecedences = nil;

#ifndef OF_AMIGAOS
static void

|


















|
|
|

>







>



>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
/*
 * Copyright (c) 2008-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 <locale.h>

#import "OFLocale.h"
#import "OFArray.h"
#import "OFDictionary.h"
#import "OFIRI.h"
#import "OFNumber.h"
#import "OFString.h"

#import "OFInitializationFailedException.h"
#import "OFInvalidArgumentException.h"
#import "OFInvalidFormatException.h"
#import "OFOpenItemFailedException.h"

#ifdef OF_AMIGAOS
# define Class IntuitionClass
# include <proto/dos.h>
# include <proto/exec.h>
# include <proto/locale.h>
# undef Class
#endif

static OFLocale *currentLocale = nil;
static OFDictionary *operatorPrecedences = nil;

#ifndef OF_AMIGAOS
static void
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382



383

384
385
386
387
388
389
390
}

+ (OFString *)decimalSeparator
{
	return currentLocale.decimalSeparator;
}

#ifdef OF_HAVE_FILES
+ (void)addLocalizationDirectory: (OFString *)path
{
	[currentLocale addLocalizationDirectory: path];
}
#endif

- (instancetype)init
{
	self = [super init];

	@try {
#ifndef OF_AMIGAOS
		char *locale, *messagesLocale = NULL;

		if (currentLocale != nil)
			@throw [OFInitializationFailedException
			    exceptionWithClass: self.class];




		_encoding = OFStringEncodingUTF8;

		_decimalSeparator = @".";
		_localizedStrings = [[OFMutableArray alloc] init];

		if ((locale = setlocale(LC_ALL, "")) != NULL)
			_decimalSeparator = [[OFString alloc]
			    initWithCString: localeconv()->decimal_point
				   encoding: _encoding];







<
|

|

<













>
>
>

>







360
361
362
363
364
365
366

367
368
369
370

371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
}

+ (OFString *)decimalSeparator
{
	return currentLocale.decimalSeparator;
}


+ (void)addLocalizationDirectoryIRI: (OFIRI *)IRI
{
	[currentLocale addLocalizationDirectoryIRI: IRI];
}


- (instancetype)init
{
	self = [super init];

	@try {
#ifndef OF_AMIGAOS
		char *locale, *messagesLocale = NULL;

		if (currentLocale != nil)
			@throw [OFInitializationFailedException
			    exceptionWithClass: self.class];

# ifdef OF_MSDOS
		_encoding = OFStringEncodingCodepage437;
# else
		_encoding = OFStringEncodingUTF8;
# endif
		_decimalSeparator = @".";
		_localizedStrings = [[OFMutableArray alloc] init];

		if ((locale = setlocale(LC_ALL, "")) != NULL)
			_decimalSeparator = [[OFString alloc]
			    initWithCString: localeconv()->decimal_point
				   encoding: _encoding];
490
491
492
493
494
495
496
497
498
499
500

501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
	[_countryCode release];
	[_decimalSeparator release];
	[_localizedStrings release];

	[super dealloc];
}

#ifdef OF_HAVE_FILES
- (void)addLocalizationDirectory: (OFString *)path
{
	void *pool;

	OFString *mapPath, *languageCode, *countryCode, *localizationFile;
	OFDictionary *map;

	if (_languageCode == nil)
		return;

	pool = objc_autoreleasePoolPush();

	mapPath = [path stringByAppendingPathComponent: @"localizations.json"];
	@try {
		map = [[OFString stringWithContentsOfFile: mapPath]
		     objectByParsingJSON];
	} @catch (OFOpenItemFailedException *e) {
		objc_autoreleasePoolPop(pool);
		return;
	}

	languageCode = _languageCode.lowercaseString;







<
|


>
|







|

|







495
496
497
498
499
500
501

502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
	[_countryCode release];
	[_decimalSeparator release];
	[_localizedStrings release];

	[super dealloc];
}


- (void)addLocalizationDirectoryIRI: (OFIRI *)IRI
{
	void *pool;
	OFIRI *mapIRI, *localizationIRI;
	OFString *languageCode, *countryCode, *localizationFile;
	OFDictionary *map;

	if (_languageCode == nil)
		return;

	pool = objc_autoreleasePoolPush();

	mapIRI = [IRI IRIByAppendingPathComponent: @"localizations.json"];
	@try {
		map = [[OFString stringWithContentsOfIRI: mapIRI]
		     objectByParsingJSON];
	} @catch (OFOpenItemFailedException *e) {
		objc_autoreleasePoolPop(pool);
		return;
	}

	languageCode = _languageCode.lowercaseString;
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
		    objectForKey: @""];

	if (localizationFile == nil) {
		objc_autoreleasePoolPop(pool);
		return;
	}

	localizationFile = [path stringByAppendingPathComponent:
	    [localizationFile stringByAppendingString: @".json"]];

	[_localizedStrings addObject: [[OFString stringWithContentsOfFile:
	    localizationFile] objectByParsingJSON]];

	objc_autoreleasePoolPop(pool);
}
#endif

- (OFString *)localizedStringForID: (OFConstantString *)ID
			  fallback: (id)fallback, ...
{
	OFString *ret;
	va_list args;








|


|
|



<







533
534
535
536
537
538
539
540
541
542
543
544
545
546
547

548
549
550
551
552
553
554
		    objectForKey: @""];

	if (localizationFile == nil) {
		objc_autoreleasePoolPop(pool);
		return;
	}

	localizationIRI = [IRI IRIByAppendingPathComponent:
	    [localizationFile stringByAppendingString: @".json"]];

	[_localizedStrings addObject: [[OFString stringWithContentsOfIRI:
	    localizationIRI] objectByParsingJSON]];

	objc_autoreleasePoolPop(pool);
}


- (OFString *)localizedStringForID: (OFConstantString *)ID
			  fallback: (id)fallback, ...
{
	OFString *ret;
	va_list args;

Modified src/OFLocking.h from [155544ed9e] to [5738e43f58].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFMD5Hash.h from [cdd5a3515e] to [ef3f22a9e8].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFMD5Hash.m from [190d96fa7c] to [a06b7ae21c].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFMapTable+Private.h from [34b0bddd51] to [2afd453132].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFMapTable.h from [382835ac81] to [442352c010].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
 */
OF_SUBCLASSING_RESTRICTED
@interface OFMapTable: OFObject <OFCopying, OFFastEnumeration>
{
	OFMapTableFunctions _keyFunctions, _objectFunctions;
	struct OFMapTableBucket *_Nonnull *_Nullable _buckets;
	uint32_t _count, _capacity;
	unsigned char _rotate;
	unsigned long _mutations;
}

/**
 * @brief The key functions used by the map table.
 */
@property (readonly, nonatomic) OFMapTableFunctions keyFunctions;







|







70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
 */
OF_SUBCLASSING_RESTRICTED
@interface OFMapTable: OFObject <OFCopying, OFFastEnumeration>
{
	OFMapTableFunctions _keyFunctions, _objectFunctions;
	struct OFMapTableBucket *_Nonnull *_Nullable _buckets;
	uint32_t _count, _capacity;
	unsigned char _rotation;
	unsigned long _mutations;
}

/**
 * @brief The key functions used by the map table.
 */
@property (readonly, nonatomic) OFMapTableFunctions keyFunctions;

Modified src/OFMapTable.m from [61602c79fe] to [810b88a011].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#define OF_MAP_TABLE_M

#include "config.h"

#include <stdlib.h>
#include <string.h>

#include <assert.h>

#import "OFMapTable.h"
#import "OFMapTable+Private.h"
#import "OFEnumerator.h"

#import "OFEnumerationMutationException.h"
#import "OFInvalidArgumentException.h"
#import "OFOutOfRangeException.h"

|




















<
<







1
2
3
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.
 */

#define OF_MAP_TABLE_M

#include "config.h"

#include <stdlib.h>
#include <string.h>



#import "OFMapTable.h"
#import "OFMapTable+Private.h"
#import "OFEnumerator.h"

#import "OFEnumerationMutationException.h"
#import "OFInvalidArgumentException.h"
#import "OFOutOfRangeException.h"
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169

		if (_capacity < minCapacity)
			_capacity = minCapacity;

		_buckets = OFAllocZeroedMemory(_capacity, sizeof(*_buckets));

		if (OFHashSeed != 0)
			_rotate = OFRandom16() & 31;
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}







|







153
154
155
156
157
158
159
160
161
162
163
164
165
166
167

		if (_capacity < minCapacity)
			_capacity = minCapacity;

		_buckets = OFAllocZeroedMemory(_capacity, sizeof(*_buckets));

		if (OFHashSeed != 0)
			_rotation = OFRandom16() & 31;
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}
185
186
187
188
189
190
191

192
193
194
195
196
197
198
}

static void
resizeForCount(OFMapTable *self, uint32_t count)
{
	uint32_t fullness, capacity;
	struct OFMapTableBucket **buckets;


	if (count > UINT32_MAX / sizeof(*self->_buckets) ||
	    count > UINT32_MAX / 8)
		@throw [OFOutOfRangeException exception];

	fullness = count * 8 / self->_capacity;








>







183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
}

static void
resizeForCount(OFMapTable *self, uint32_t count)
{
	uint32_t fullness, capacity;
	struct OFMapTableBucket **buckets;
	unsigned char newRotation;

	if (count > UINT32_MAX / sizeof(*self->_buckets) ||
	    count > UINT32_MAX / 8)
		@throw [OFOutOfRangeException exception];

	fullness = count * 8 / self->_capacity;

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
	 * below the minimum capacity.
	 */
	if ((capacity < self->_capacity && count > self->_count) ||
	    capacity < minCapacity)
		return;

	buckets = OFAllocZeroedMemory(capacity, sizeof(*buckets));


	for (uint32_t i = 0; i < self->_capacity; i++) {
		if (self->_buckets[i] != NULL &&
		    self->_buckets[i] != &deletedBucket) {
			uint32_t j, last;



			last = capacity;

			for (j = self->_buckets[i]->hash & (capacity - 1);
			    j < last && buckets[j] != NULL; j++);

			/* In case the last bucket is already used */
			if (j >= last) {
				last = self->_buckets[i]->hash & (capacity - 1);

				for (j = 0; j < last &&
				    buckets[j] != NULL; j++);
			}

			if (j >= last)
				@throw [OFOutOfRangeException exception];

			buckets[j] = self->_buckets[i];
		}
	}

	OFFreeMemory(self->_buckets);
	self->_buckets = buckets;
	self->_capacity = capacity;

}

static void
setObject(OFMapTable *restrict self, void *key, void *object, uint32_t hash)
{
	uint32_t i, last;
	void *old;

	if (key == NULL || object == NULL)
		@throw [OFInvalidArgumentException exception];

	hash = OFRotateLeft(hash, self->_rotate);
	last = self->_capacity;

	for (i = hash & (self->_capacity - 1);
	    i < last && self->_buckets[i] != NULL; i++) {
		if (self->_buckets[i] == &deletedBucket)
			continue;

		if (self->_keyFunctions.equal(self->_buckets[i]->key, key))
			break;
	}

	/* In case the last bucket is already used */
	if (i >= last) {
		last = hash & (self->_capacity - 1);

		for (i = 0; i < last && self->_buckets[i] != NULL; i++) {
			if (self->_buckets[i] == &deletedBucket)
				continue;

			if (self->_keyFunctions.equal(
			    self->_buckets[i]->key, key))
				break;
		}
	}

	/* Key not in map table */
	if (i >= last || self->_buckets[i] == NULL ||
	    self->_buckets[i] == &deletedBucket ||
	    !self->_keyFunctions.equal(self->_buckets[i]->key, key)) {
		struct OFMapTableBucket *bucket;

		resizeForCount(self, self->_count + 1);



		self->_mutations++;
		last = self->_capacity;

		for (i = hash & (self->_capacity - 1); i < last &&
		    self->_buckets[i] != NULL &&
		    self->_buckets[i] != &deletedBucket; i++);

		/* In case the last bucket is already used */
		if (i >= last) {
			last = hash & (self->_capacity - 1);

			for (i = 0; i < last && self->_buckets[i] != NULL &&
			    self->_buckets[i] != &deletedBucket; i++);
		}

		if (i >= last)
			@throw [OFOutOfRangeException exception];







>




|

>
>


|




|















>





|





|


|










|


















>
>




|





|







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
	 * below the minimum capacity.
	 */
	if ((capacity < self->_capacity && count > self->_count) ||
	    capacity < minCapacity)
		return;

	buckets = OFAllocZeroedMemory(capacity, sizeof(*buckets));
	newRotation = (OFHashSeed != 0 ? OFRandom16() & 31 : 0);

	for (uint32_t i = 0; i < self->_capacity; i++) {
		if (self->_buckets[i] != NULL &&
		    self->_buckets[i] != &deletedBucket) {
			uint32_t rotatedHash, j, last;

			rotatedHash = OFRotateLeft(self->_buckets[i]->hash,
			    newRotation);
			last = capacity;

			for (j = rotatedHash & (capacity - 1);
			    j < last && buckets[j] != NULL; j++);

			/* In case the last bucket is already used */
			if (j >= last) {
				last = rotatedHash & (capacity - 1);

				for (j = 0; j < last &&
				    buckets[j] != NULL; j++);
			}

			if (j >= last)
				@throw [OFOutOfRangeException exception];

			buckets[j] = self->_buckets[i];
		}
	}

	OFFreeMemory(self->_buckets);
	self->_buckets = buckets;
	self->_capacity = capacity;
	self->_rotation = newRotation;
}

static void
setObject(OFMapTable *restrict self, void *key, void *object, uint32_t hash)
{
	uint32_t rotatedHash, i, last;
	void *old;

	if (key == NULL || object == NULL)
		@throw [OFInvalidArgumentException exception];

	rotatedHash = OFRotateLeft(hash, self->_rotation);
	last = self->_capacity;

	for (i = rotatedHash & (self->_capacity - 1);
	    i < last && self->_buckets[i] != NULL; i++) {
		if (self->_buckets[i] == &deletedBucket)
			continue;

		if (self->_keyFunctions.equal(self->_buckets[i]->key, key))
			break;
	}

	/* In case the last bucket is already used */
	if (i >= last) {
		last = rotatedHash & (self->_capacity - 1);

		for (i = 0; i < last && self->_buckets[i] != NULL; i++) {
			if (self->_buckets[i] == &deletedBucket)
				continue;

			if (self->_keyFunctions.equal(
			    self->_buckets[i]->key, key))
				break;
		}
	}

	/* Key not in map table */
	if (i >= last || self->_buckets[i] == NULL ||
	    self->_buckets[i] == &deletedBucket ||
	    !self->_keyFunctions.equal(self->_buckets[i]->key, key)) {
		struct OFMapTableBucket *bucket;

		resizeForCount(self, self->_count + 1);
		/* Resizing can change the rotation */
		rotatedHash = OFRotateLeft(hash, self->_rotation);

		self->_mutations++;
		last = self->_capacity;

		for (i = rotatedHash & (self->_capacity - 1); i < last &&
		    self->_buckets[i] != NULL &&
		    self->_buckets[i] != &deletedBucket; i++);

		/* In case the last bucket is already used */
		if (i >= last) {
			last = rotatedHash & (self->_capacity - 1);

			for (i = 0; i < last && self->_buckets[i] != NULL &&
			    self->_buckets[i] != &deletedBucket; i++);
		}

		if (i >= last)
			@throw [OFOutOfRangeException exception];
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

- (unsigned long)hash
{
	unsigned long hash = 0;

	for (unsigned long i = 0; i < _capacity; i++) {
		if (_buckets[i] != NULL && _buckets[i] != &deletedBucket) {
			hash ^= OFRotateRight(_buckets[i]->hash, _rotate);
			hash ^= _objectFunctions.hash(_buckets[i]->object);
		}
	}

	return hash;
}

- (id)copy
{
	OFMapTable *copy = [[OFMapTable alloc]
	    initWithKeyFunctions: _keyFunctions
		 objectFunctions: _objectFunctions
			capacity: _capacity];

	@try {
		for (uint32_t i = 0; i < _capacity; i++)
			if (_buckets[i] != NULL &&
			    _buckets[i] != &deletedBucket)
				setObject(copy, _buckets[i]->key,
				    _buckets[i]->object,
				    OFRotateRight(_buckets[i]->hash, _rotate));
	} @catch (id e) {
		[copy release];
		@throw e;
	}

	return copy;
}

- (size_t)count
{
	return _count;
}

- (void *)objectForKey: (void *)key
{
	uint32_t i, hash, last;

	if (key == NULL)
		@throw [OFInvalidArgumentException exception];

	hash = OFRotateLeft((uint32_t)_keyFunctions.hash(key), _rotate);

	last = _capacity;


	for (i = hash & (_capacity - 1); i < last && _buckets[i] != NULL; i++) {
		if (_buckets[i] == &deletedBucket)
			continue;

		if (_keyFunctions.equal(_buckets[i]->key, key))
			return _buckets[i]->object;
	}

	if (i < last)
		return nil;

	/* In case the last bucket is already used */
	last = hash & (_capacity - 1);

	for (i = 0; i < last && _buckets[i] != NULL; i++) {
		if (_buckets[i] == &deletedBucket)
			continue;

		if (_keyFunctions.equal(_buckets[i]->key, key))
			return _buckets[i]->object;
	}

	return NULL;
}

- (void)setObject: (void *)object forKey: (void *)key
{
	setObject(self, key, object, (uint32_t)_keyFunctions.hash(key));
}

- (void)removeObjectForKey: (void *)key
{
	uint32_t i, hash, last;

	if (key == NULL)
		@throw [OFInvalidArgumentException exception];

	hash = OFRotateLeft((uint32_t)_keyFunctions.hash(key), _rotate);

	last = _capacity;


	for (i = hash & (_capacity - 1); i < last && _buckets[i] != NULL; i++) {
		if (_buckets[i] == &deletedBucket)
			continue;

		if (_keyFunctions.equal(_buckets[i]->key, key)) {
			_mutations++;

			_keyFunctions.release(_buckets[i]->key);







|



















|
<















|




|
>


>
|











|



















|




|
>


>
|







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

- (unsigned long)hash
{
	unsigned long hash = 0;

	for (unsigned long i = 0; i < _capacity; i++) {
		if (_buckets[i] != NULL && _buckets[i] != &deletedBucket) {
			hash ^= _buckets[i]->hash;
			hash ^= _objectFunctions.hash(_buckets[i]->object);
		}
	}

	return hash;
}

- (id)copy
{
	OFMapTable *copy = [[OFMapTable alloc]
	    initWithKeyFunctions: _keyFunctions
		 objectFunctions: _objectFunctions
			capacity: _capacity];

	@try {
		for (uint32_t i = 0; i < _capacity; i++)
			if (_buckets[i] != NULL &&
			    _buckets[i] != &deletedBucket)
				setObject(copy, _buckets[i]->key,
				    _buckets[i]->object, _buckets[i]->hash);

	} @catch (id e) {
		[copy release];
		@throw e;
	}

	return copy;
}

- (size_t)count
{
	return _count;
}

- (void *)objectForKey: (void *)key
{
	uint32_t i, rotatedHash, last;

	if (key == NULL)
		@throw [OFInvalidArgumentException exception];

	rotatedHash = OFRotateLeft((uint32_t)_keyFunctions.hash(key),
	    _rotation);
	last = _capacity;

	for (i = rotatedHash & (_capacity - 1);
	    i < last && _buckets[i] != NULL; i++) {
		if (_buckets[i] == &deletedBucket)
			continue;

		if (_keyFunctions.equal(_buckets[i]->key, key))
			return _buckets[i]->object;
	}

	if (i < last)
		return nil;

	/* In case the last bucket is already used */
	last = rotatedHash & (_capacity - 1);

	for (i = 0; i < last && _buckets[i] != NULL; i++) {
		if (_buckets[i] == &deletedBucket)
			continue;

		if (_keyFunctions.equal(_buckets[i]->key, key))
			return _buckets[i]->object;
	}

	return NULL;
}

- (void)setObject: (void *)object forKey: (void *)key
{
	setObject(self, key, object, (uint32_t)_keyFunctions.hash(key));
}

- (void)removeObjectForKey: (void *)key
{
	uint32_t i, rotatedHash, last;

	if (key == NULL)
		@throw [OFInvalidArgumentException exception];

	rotatedHash = OFRotateLeft((uint32_t)_keyFunctions.hash(key),
	    _rotation);
	last = _capacity;

	for (i = rotatedHash & (_capacity - 1);
	    i < last && _buckets[i] != NULL; i++) {
		if (_buckets[i] == &deletedBucket)
			continue;

		if (_keyFunctions.equal(_buckets[i]->key, key)) {
			_mutations++;

			_keyFunctions.release(_buckets[i]->key);
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
		}
	}

	if (i < last)
		return;

	/* In case the last bucket is already used */
	last = hash & (_capacity - 1);

	for (i = 0; i < last && _buckets[i] != NULL; i++) {
		if (_buckets[i] == &deletedBucket)
			continue;

		if (_keyFunctions.equal(_buckets[i]->key, key)) {
			_keyFunctions.release(_buckets[i]->key);







|







487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
		}
	}

	if (i < last)
		return;

	/* In case the last bucket is already used */
	last = rotatedHash & (_capacity - 1);

	for (i = 0; i < last && _buckets[i] != NULL; i++) {
		if (_buckets[i] == &deletedBucket)
			continue;

		if (_keyFunctions.equal(_buckets[i]->key, key)) {
			_keyFunctions.release(_buckets[i]->key);
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
	}

	_count = 0;
	_capacity = minCapacity;
	_buckets = OFResizeMemory(_buckets, _capacity, sizeof(*_buckets));

	/*
	 * Get a new random value for _rotate, so that it is not less secure
	 * than creating a new hash map.
	 */
	if (OFHashSeed != 0)
		_rotate = OFRandom16() & 31;
}

- (bool)containsObject: (void *)object
{
	if (object == NULL || _count == 0)
		return false;








|



|







531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
	}

	_count = 0;
	_capacity = minCapacity;
	_buckets = OFResizeMemory(_buckets, _capacity, sizeof(*_buckets));

	/*
	 * Get a new random value for _rotation, so that it is not less secure
	 * than creating a new hash map.
	 */
	if (OFHashSeed != 0)
		_rotation = OFRandom16() & 31;
}

- (bool)containsObject: (void *)object
{
	if (object == NULL || _count == 0)
		return false;

Added src/OFMatrix4x4.h version [c4c1c25c02].













































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
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 "OFObject.h"

OF_ASSUME_NONNULL_BEGIN

/**
 * @brief A 4x4 matrix of floats.
 */
OF_SUBCLASSING_RESTRICTED
@interface OFMatrix4x4: OFObject <OFCopying>
{
	float (*_values)[4];
}

#ifdef OF_HAVE_CLASS_PROPERTIES
@property (readonly, class) OFMatrix4x4 *identityMatrix;
#endif

/**
 * @brief A 2D array of the 4x4 floats of the matrix in row-major format.
 *
 * These may be modified directly.
 */
@property (readonly, nonatomic) float (*values)[4];

/**
 * @brief Returns the 4x4 identity matrix.
 */
+ (OFMatrix4x4 *)identityMatrix;

/**
 * @brief Creates a new 4x4 matrix with the specified values.
 *
 * @param values A 2D array of 4x4 floats in row-major format
 * @return A new, autoreleased OFMatrix4x4
 */
+ (instancetype)matrixWithValues: (const float [_Nonnull 4][4])values;

- (instancetype)init OF_UNAVAILABLE;

/**
 * @brief Initializes an already allocated 4x4 matrix with the specified values.
 *
 * @param values A 2D array of 4x4 floats in row-major format
 * @return An initialized OFMatrix4x4
 */
- (instancetype)initWithValues: (const float [_Nonnull 4][4])values
    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;

/**
 * @brief Translates the matrix with the specified vector.
 *
 * @param vector The vector to translate the matrix with
 */
- (void)translateWithVector: (OFVector3D)vector;

/**
 * @brief Scales the matrix with the specified vector.
 *
 * @param vector The vector to scale the matrix with
 */
- (void)scaleWithVector: (OFVector3D)vector;

/**
 * @brief Transforms the specified vector according to the matrix.
 *
 * @param vector The vector to transform
 * @return The transformed vector
 */
- (OFVector4D)transformedVector: (OFVector4D)vector;

/**
 * @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

Added src/OFMatrix4x4.m version [9ade524fc2].









































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
/*
 * 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 "OFMatrix4x4.h"
#import "OFString.h"
#import "OFSystemInfo.h"

#import "OFOnce.h"

static const float identityValues[4][4] = {
	{ 1, 0, 0, 0 },
	{ 0, 1, 0, 0 },
	{ 0, 0, 1, 0 },
	{ 0, 0, 0, 1 }
};

@implementation OFMatrix4x4
#if (defined(OF_AMD64) || defined(OF_X86)) && defined(__GNUC__)
# ifndef __clang__
#  pragma GCC push_options
#  pragma GCC target("sse")
# endif
static void
transformVectors_SSE(OFMatrix4x4 *self, SEL _cmd, OFVector4D *vectors,
    size_t count)
{
	OF_ALIGN(16) float tmp[4];

	__asm__ __volatile__ (
	    "test	%[count], %[count]\n\t"
	    "jz		0f\n"
	    "\n\t"
	    "movaps	(%[matrix]), %%xmm0\n\t"
	    "movaps	16(%[matrix]), %%xmm1\n\t"
	    "movaps	32(%[matrix]), %%xmm2\n\t"
# ifdef OF_AMD64
	    "movaps	48(%[matrix]), %%xmm8\n"
# endif
	    "\n\t"
	    "0:\n\t"
	    "movaps	(%[vectors]), %%xmm3\n"
	    "\n\t"
	    "movaps	%%xmm0, %%xmm4\n\t"
	    "mulps	%%xmm3, %%xmm4\n\t"
	    "movaps	%%xmm4, (%[tmp])\n\t"
	    "addss	4(%[tmp]), %%xmm4\n\t"
	    "addss	8(%[tmp]), %%xmm4\n\t"
	    "addss	12(%[tmp]), %%xmm4\n"
	    "\n\t"
	    "movaps	%%xmm1, %%xmm5\n\t"
	    "mulps	%%xmm3, %%xmm5\n\t"
	    "movaps	%%xmm5, (%[tmp])\n\t"
	    "addss	4(%[tmp]), %%xmm5\n\t"
	    "addss	8(%[tmp]), %%xmm5\n\t"
	    "addss	12(%[tmp]), %%xmm5\n"
	    "\n\t"
	    "movaps	%%xmm2, %%xmm6\n\t"
	    "mulps	%%xmm3, %%xmm6\n\t"
	    "movaps	%%xmm6, (%[tmp])\n\t"
	    "addss	4(%[tmp]), %%xmm6\n\t"
	    "addss	8(%[tmp]), %%xmm6\n\t"
	    "addss	12(%[tmp]), %%xmm6\n"
	    "\n\t"
# ifdef OF_AMD64
	    "movaps	%%xmm8, %%xmm7\n\t"
# else
	    "movaps	48(%[matrix]), %%xmm7\n\t"
# endif
	    "mulps	%%xmm3, %%xmm7\n\t"
	    "movaps	%%xmm7, (%[tmp])\n\t"
	    "addss	4(%[tmp]), %%xmm7\n\t"
	    "addss	8(%[tmp]), %%xmm7\n\t"
	    "addss	12(%[tmp]), %%xmm7\n"
	    "\n\t"
	    "movss	%%xmm4, (%[vectors])\n\t"
	    "movss	%%xmm5, 4(%[vectors])\n\t"
	    "movss	%%xmm6, 8(%[vectors])\n\t"
	    "movss	%%xmm7, 12(%[vectors])\n"
	    "\n\t"
	    "add	$16, %[vectors]\n\t"
	    "dec	%[count]\n\t"
	    "jnz	0b\n"
	    : [count] "+r" (count),
	      [vectors] "+r" (vectors)
	    : [matrix] "r" (self->_values),
	      [tmp] "r" (&tmp)
	    : "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7",
# ifdef OF_AMD64
	      "xmm8",
# endif
	      "memory"
	);
}
# ifndef __clang__
#  pragma GCC pop_options
# endif

# ifndef __clang__
#  pragma GCC push_options
#  pragma GCC target("3dnow")
# endif
static void
multiplyWithMatrix_3DNow(OFMatrix4x4 *self, SEL _cmd, OFMatrix4x4 *matrix)
{
	float (*left)[4] = matrix->_values, (*right)[4] = self->_values;
	float result[4][4], (*resultPtr)[4] = result;

	__asm__ __volatile__ (
	    "movl	$4, %%ecx\n\t"
	    "\n\t"
	    "0:\n\t"
	    "movd	(%[right]), %%mm0\n\t"
	    "punpckldq	16(%[right]), %%mm0\n\t"
	    "pfmul	(%[left]), %%mm0\n\t"
	    "movd	32(%[right]), %%mm1\n\t"
	    "punpckldq  48(%[right]), %%mm1\n\t"
	    "pfmul	8(%[left]), %%mm1\n\t"
	    "pfacc	%%mm1, %%mm0\n\t"
	    "pfacc	%%mm0, %%mm0\n\t"
	    "movd	%%mm0, (%[result])\n\t"
	    "movd	4(%[right]), %%mm0\n\t"
	    "punpckldq	20(%[right]), %%mm0\n\t"
	    "pfmul	(%[left]), %%mm0\n\t"
	    "movd	36(%[right]), %%mm1\n\t"
	    "punpckldq  52(%[right]), %%mm1\n\t"
	    "pfmul	8(%[left]), %%mm1\n\t"
	    "pfacc	%%mm1, %%mm0\n\t"
	    "pfacc	%%mm0, %%mm0\n\t"
	    "movd	%%mm0, 4(%[result])\n\t"
	    "movd	8(%[right]), %%mm0\n\t"
	    "punpckldq	24(%[right]), %%mm0\n\t"
	    "pfmul	(%[left]), %%mm0\n\t"
	    "movd	40(%[right]), %%mm1\n\t"
	    "punpckldq  56(%[right]), %%mm1\n\t"
	    "pfmul	8(%[left]), %%mm1\n\t"
	    "pfacc	%%mm1, %%mm0\n\t"
	    "pfacc	%%mm0, %%mm0\n\t"
	    "movd	%%mm0, 8(%[result])\n\t"
	    "movd	12(%[right]), %%mm0\n\t"
	    "punpckldq	28(%[right]), %%mm0\n\t"
	    "pfmul	(%[left]), %%mm0\n\t"
	    "movd	44(%[right]), %%mm1\n\t"
	    "punpckldq  60(%[right]), %%mm1\n\t"
	    "pfmul	8(%[left]), %%mm1\n\t"
	    "pfacc	%%mm1, %%mm0\n\t"
	    "pfacc	%%mm0, %%mm0\n\t"
	    "movd	%%mm0, 12(%[result])\n"
	    "\n\t"
	    "add	$16, %[result]\n\t"
	    "add	$16, %[left]\n\t"
	    "decl	%%ecx\n\t"
	    "jnz	0b\n"
	    "\n\t"
	    "femms"
	    : [result] "+r" (resultPtr),
	      [left] "+r" (left),
	      [right] "+r" (right)
	    :
	    : "ecx", "mm0", "mm1", "memory"
	);

	memcpy(self->_values, result, 16 * sizeof(float));
}

static void
transformVectors_3DNow(OFMatrix4x4 *self, SEL _cmd, OFVector4D *vectors,
    size_t count)
{
	__asm__ __volatile__ (
	    "test	%[count], %[count]\n\t"
	    "jz		0f\n"
	    "\n\t"
	    "0:\n\t"
	    "movq	(%[vectors]), %%mm0\n\t"
	    "movq	8(%[vectors]), %%mm1\n"
	    "\n\t"
	    "movq	%%mm0, %%mm2\n\t"
	    "movq	%%mm1, %%mm3\n\t"
	    "pfmul	(%[matrix]), %%mm2\n\t"
	    "pfmul	8(%[matrix]), %%mm3\n\t"
	    "pfacc	%%mm3, %%mm2\n\t"
	    "pfacc	%%mm2, %%mm2\n\t"
	    "\n\t"
	    "movq	%%mm0, %%mm3\n\t"
	    "movq	%%mm1, %%mm4\n\t"
	    "pfmul	16(%[matrix]), %%mm3\n\t"
	    "pfmul	24(%[matrix]), %%mm4\n\t"
	    "pfacc	%%mm4, %%mm3\n\t"
	    "pfacc	%%mm3, %%mm3\n\t"
	    "\n\t"
	    "punpckldq	%%mm3, %%mm2\n\t"
	    "movq	%%mm2, (%[vectors])\n"
	    "\n\t"
	    "movq	%%mm0, %%mm2\n\t"
	    "movq	%%mm1, %%mm3\n\t"
	    "pfmul	32(%[matrix]), %%mm2\n\t"
	    "pfmul	40(%[matrix]), %%mm3\n\t"
	    "pfacc	%%mm3, %%mm2\n\t"
	    "pfacc	%%mm2, %%mm2\n\t"
	    "\n\t"
	    "pfmul	48(%[matrix]), %%mm0\n\t"
	    "pfmul	56(%[matrix]), %%mm1\n\t"
	    "pfacc	%%mm1, %%mm0\n\t"
	    "pfacc	%%mm0, %%mm0\n\t"
	    "\n\t"
	    "punpckldq	%%mm0, %%mm2\n\t"
	    "movq	%%mm2, 8(%[vectors])\n"
	    "\n\t"
	    "add	$16, %[vectors]\n\t"
	    "dec	%[count]\n\t"
	    "jnz	0b\n"
	    "\n\t"
	    "0:\n\t"
	    "femms"
	    : [count] "+r" (count),
	      [vectors] "+r" (vectors)
	    : [matrix] "r" (self->_values)
	    : "mm0", "mm1", "mm2", "mm3", "mm4", "memory"
	);
}
# ifndef __clang__
#  pragma GCC pop_options
# endif

+ (void)initialize
{
	const char *typeEncoding;

	if (self != [OFMatrix4x4 class])
		return;

# define REPLACE(selector, func)					\
	typeEncoding = method_getTypeEncoding(				\
	    class_getInstanceMethod(self, selector));			\
	class_replaceMethod(self, selector, (IMP)func, typeEncoding);

	if ([OFSystemInfo supportsSSE]) {
		REPLACE(@selector(transformVectors:count:),
		    transformVectors_SSE)
	} else if ([OFSystemInfo supports3DNow]) {
		REPLACE(@selector(multiplyWithMatrix:),
		    multiplyWithMatrix_3DNow)
		REPLACE(@selector(transformVectors:count:),
		    transformVectors_3DNow)
	}

# undef REPLACE
}
#endif

+ (instancetype)alloc
{
	OFMatrix4x4 *instance;
	float (*values)[4];

	instance = OFAllocObject(self, 16 * sizeof(float), 16,
	    (void **)&values);
	instance->_values = values;

	return instance;
}

+ (OFMatrix4x4 *)identityMatrix
{
	return [[[OFMatrix4x4 alloc]
	    initWithValues: identityValues] autorelease];
}

+ (instancetype)matrixWithValues: (const float [4][4])values
{
	return [[[self alloc] initWithValues: values] autorelease];
}

- (instancetype)init
{
	OF_INVALID_INIT_METHOD
}

- (instancetype)initWithValues: (const float [4][4])values
{
	self = [super init];

	memcpy(_values, values, 16 * sizeof(float));

	return self;
}

- (float (*)[4])values
{
	return _values;
}

- (instancetype)copy
{
	return [[OFMatrix4x4 alloc]
	    initWithValues: (const float (*)[4])_values];
}

- (bool)isEqual: (OFMatrix4x4 *)matrix
{
	if (![matrix isKindOfClass: [OFMatrix4x4 class]])
		return false;

	return (memcmp(_values, matrix->_values, 16 * sizeof(float)) == 0);
}

- (unsigned long)hash
{
	unsigned long hash;

	OFHashInit(&hash);

	for (uint_fast8_t i = 0; i < 4; i++)
		for (uint_fast8_t j = 0; j < 4; j++)
			OFHashAddHash(&hash, OFFloatToRawUInt32(_values[i][j]));

	OFHashFinalize(&hash);

	return hash;
}

- (void)multiplyWithMatrix: (OFMatrix4x4 *)matrix
{
	float result[4][4];

	for (uint_fast8_t i = 0; i < 4; i++)
		for (uint_fast8_t j = 0; j < 4; j++)
			result[i][j] =
			    matrix->_values[i][0] * _values[0][j] +
			    matrix->_values[i][1] * _values[1][j] +
			    matrix->_values[i][2] * _values[2][j] +
			    matrix->_values[i][3] * _values[3][j];

	memcpy(_values, result, 16 * sizeof(float));
}

- (void)translateWithVector: (OFVector3D)vector
{
	OFMatrix4x4 *translation = [[OFMatrix4x4 alloc] initWithValues:
	    (const float [4][4]){
		{ 1, 0, 0, vector.x },
		{ 0, 1, 0, vector.y },
		{ 0, 0, 1, vector.z },
		{ 0, 0, 0, 1 }
	    }];
	[self multiplyWithMatrix: translation];
	[translation release];
}

- (void)scaleWithVector: (OFVector3D)vector
{
	OFMatrix4x4 *scale = [[OFMatrix4x4 alloc] initWithValues:
	    (const float [4][4]){
		{ vector.x, 0, 0, 0 },
		{ 0, vector.y, 0, 0 },
		{ 0, 0, vector.z, 0 },
		{ 0, 0, 0, 1 }
	    }];
	[self multiplyWithMatrix: scale];
	[scale release];
}

- (OFVector4D)transformedVector: (OFVector4D)vector
{
	OFVector4D copy = vector;

	[self transformVectors: &copy count: 1];

	return copy;
}

- (void)transformVectors: (OFVector4D *)vectors count: (size_t)count
{
	for (size_t i = 0; i < count; i++) {
		OFVector4D vector = vectors[i];

		vectors[i].x = _values[0][0] * vector.x +
		    _values[0][1] * vector.y + _values[0][2] * vector.z +
		    _values[0][3] * vector.w;
		vectors[i].y = _values[1][0] * vector.x +
		    _values[1][1] * vector.y + _values[1][2] * vector.z +
		    _values[1][3] * vector.w;
		vectors[i].z = _values[2][0] * vector.x +
		    _values[2][1] * vector.y + _values[2][2] * vector.z +
		    _values[2][3] * vector.w;
		vectors[i].w = _values[3][0] * vector.x +
		    _values[3][1] * vector.y + _values[3][2] * vector.z +
		    _values[3][3] * vector.w;
	}
}

- (OFString *)description
{
	return [OFString stringWithFormat:
	    @"<OFMatrix4x4: {\n"
	    @"\t%g %g %g %g\n"
	    @"\t%g %g %g %g\n"
	    @"\t%g %g %g %g\n"
	    @"\t%g %g %g %g\n"
	    @"}>",
	    _values[0][0], _values[0][1], _values[0][2], _values[0][3],
	    _values[1][0], _values[1][1], _values[1][2], _values[1][3],
	    _values[2][0], _values[2][1], _values[2][2], _values[2][3],
	    _values[3][0], _values[3][1], _values[3][2], _values[3][3]];
}
@end

Modified src/OFMemoryStream.h from [173e3dc728] to [69163637cb].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFMemoryStream.m from [d9d07c7da0] to [42008ee7f4].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFMessagePackExtension.h from [99c89d24f1] to [1bc2759629].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFMessagePackExtension.m from [a3971287d8] to [33ef9555ae].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFMessagePackRepresentation.h from [d2e100cc65] to [fa41ae8de0].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFMethodSignature.h from [996cafd8b2] to [11d7ad667f].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
53
54
55
56
57
58
59


60
61
62
63
64
65
66
67
68

69
70
71
72
73
74
75
 *
 * @param types The ObjC types of the method
 * @return A new, autoreleased OFMethodSignature
 * @throw OFInvalidFormatException The type encoding is invalid
 */
+ (instancetype)signatureWithObjCTypes: (const char *)types;



/**
 * @brief Initializes an already allocated OFMethodSignature with the specified
 *	  ObjC types.
 *
 * @param types The ObjC types of the method
 * @return An Initialized OFMethodSignature
 * @throw OFInvalidFormatException The type encoding is invalid
 */
- (instancetype)initWithObjCTypes: (const char *)types;


/**
 * @brief Returns the ObjC type for the argument at the specified index.
 *
 * @param index The index of the argument for which to return the ObjC type
 * @return The ObjC type for the argument at the specified index
 */







>
>








|
>







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
 *
 * @param types The ObjC types of the method
 * @return A new, autoreleased OFMethodSignature
 * @throw OFInvalidFormatException The type encoding is invalid
 */
+ (instancetype)signatureWithObjCTypes: (const char *)types;

- (instancetype)init OF_UNAVAILABLE;

/**
 * @brief Initializes an already allocated OFMethodSignature with the specified
 *	  ObjC types.
 *
 * @param types The ObjC types of the method
 * @return An Initialized OFMethodSignature
 * @throw OFInvalidFormatException The type encoding is invalid
 */
- (instancetype)initWithObjCTypes: (const char *)types
    OF_DESIGNATED_INITIALIZER;

/**
 * @brief Returns the ObjC type for the argument at the specified index.
 *
 * @param index The index of the argument for which to return the ObjC type
 * @return The ObjC type for the argument at the specified index
 */

Modified src/OFMethodSignature.m from [9c702fcecb] to [c6cbdf3c9e].

1
2
3
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
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#include <assert.h>
#include <ctype.h>

#import "OFMethodSignature.h"
#import "OFData.h"


#import "OFInvalidArgumentException.h"
#import "OFInvalidFormatException.h"
#import "OFOutOfRangeException.h"

#import "macros.h"

static size_t alignmentOfEncoding(const char **type, size_t *length,
    bool inStruct);
static size_t sizeOfEncoding(const char **type, size_t *length);

static size_t
alignmentOfArray(const char **type, size_t *length)
{
	size_t alignment;

	assert(*length > 0);

	(*type)++;
	(*length)--;

	while (*length > 0 && OFASCIIIsDigit(**type)) {
		(*type)++;
		(*length)--;

|















<




>
















|







1
2
3
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
/*
 * 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 <ctype.h>

#import "OFMethodSignature.h"
#import "OFData.h"
#import "OFString.h"

#import "OFInvalidArgumentException.h"
#import "OFInvalidFormatException.h"
#import "OFOutOfRangeException.h"

#import "macros.h"

static size_t alignmentOfEncoding(const char **type, size_t *length,
    bool inStruct);
static size_t sizeOfEncoding(const char **type, size_t *length);

static size_t
alignmentOfArray(const char **type, size_t *length)
{
	size_t alignment;

	OFAssert(*length > 0);

	(*type)++;
	(*length)--;

	while (*length > 0 && OFASCIIIsDigit(**type)) {
		(*type)++;
		(*length)--;
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
alignmentOfStruct(const char **type, size_t *length)
{
	size_t alignment = 0;
#if defined(OF_POWERPC) && defined(OF_MACOS)
	bool first = true;
#endif

	assert(*length > 0);

	(*type)++;
	(*length)--;

	/* Skip name */
	while (*length > 0 && **type != '=') {
		(*type)++;







|







61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
alignmentOfStruct(const char **type, size_t *length)
{
	size_t alignment = 0;
#if defined(OF_POWERPC) && defined(OF_MACOS)
	bool first = true;
#endif

	OFAssert(*length > 0);

	(*type)++;
	(*length)--;

	/* Skip name */
	while (*length > 0 && **type != '=') {
		(*type)++;
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
}

static size_t
alignmentOfUnion(const char **type, size_t *length)
{
	size_t alignment = 0;

	assert(*length > 0);

	(*type)++;
	(*length)--;

	/* Skip name */
	while (*length > 0 && **type != '=') {
		(*type)++;







|







107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
}

static size_t
alignmentOfUnion(const char **type, size_t *length)
{
	size_t alignment = 0;

	OFAssert(*length > 0);

	(*type)++;
	(*length)--;

	/* Skip name */
	while (*length > 0 && **type != '=') {
		(*type)++;
142
143
144
145
146
147
148

149
150
151
152
153
154
155
156
	(*type)++;
	(*length)--;

	return alignment;
}

static size_t

#if defined(__clang__) && __clang_major__ == 3 && __clang_minor__ <= 7
/* Work around an ICE in Clang 3.7.0 on Windows/x86 */
__attribute__((__optnone__))
#endif
alignmentOfEncoding(const char **type, size_t *length, bool inStruct)
{
	size_t alignment;








>
|







142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
	(*type)++;
	(*length)--;

	return alignment;
}

static size_t
#if defined(__clang__) && __has_attribute(__optnone__) && \
    __clang_major__ == 3 && __clang_minor__ <= 7
/* Work around an ICE in Clang 3.7.0 on Windows/x86 */
__attribute__((__optnone__))
#endif
alignmentOfEncoding(const char **type, size_t *length, bool inStruct)
{
	size_t alignment;

288
289
290
291
292
293
294
295
296
297
298
299
300
301
302

static size_t
sizeOfArray(const char **type, size_t *length)
{
	size_t count = 0;
	size_t size;

	assert(*length > 0);

	(*type)++;
	(*length)--;

	while (*length > 0 && OFASCIIIsDigit(**type)) {
		count = count * 10 + **type - '0';








|







289
290
291
292
293
294
295
296
297
298
299
300
301
302
303

static size_t
sizeOfArray(const char **type, size_t *length)
{
	size_t count = 0;
	size_t size;

	OFAssert(*length > 0);

	(*type)++;
	(*length)--;

	while (*length > 0 && OFASCIIIsDigit(**type)) {
		count = count * 10 + **type - '0';

328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
	const char *typeCopy = *type;
	size_t lengthCopy = *length;
	size_t alignment = alignmentOfStruct(&typeCopy, &lengthCopy);
#if defined(OF_POWERPC) && defined(OF_MACOS)
	bool first = true;
#endif

	assert(*length > 0);

	(*type)++;
	(*length)--;

	/* Skip name */
	while (*length > 0 && **type != '=') {
		(*type)++;







|







329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
	const char *typeCopy = *type;
	size_t lengthCopy = *length;
	size_t alignment = alignmentOfStruct(&typeCopy, &lengthCopy);
#if defined(OF_POWERPC) && defined(OF_MACOS)
	bool first = true;
#endif

	OFAssert(*length > 0);

	(*type)++;
	(*length)--;

	/* Skip name */
	while (*length > 0 && **type != '=') {
		(*type)++;
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
}

static size_t
sizeOfUnion(const char **type, size_t *length)
{
	size_t size = 0;

	assert(*length > 0);

	(*type)++;
	(*length)--;

	/* Skip name */
	while (*length > 0 && **type != '=') {
		(*type)++;







|







402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
}

static size_t
sizeOfUnion(const char **type, size_t *length)
{
	size_t size = 0;

	OFAssert(*length > 0);

	(*type)++;
	(*length)--;

	/* Skip name */
	while (*length > 0 && **type != '=') {
		(*type)++;
436
437
438
439
440
441
442





443
444
445
446
447
448
449
	(*type)++;
	(*length)--;

	return size;
}

static size_t





sizeOfEncoding(const char **type, size_t *length)
{
	size_t size;

	if (*length == 0)
		@throw [OFInvalidFormatException exception];








>
>
>
>
>







437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
	(*type)++;
	(*length)--;

	return size;
}

static size_t
#if defined(__clang__) && __has_attribute(__optnone__) && \
    __clang_major__ == 3 && __clang_minor__ <= 7
/* Work around an ICE in Clang 3.7.0 on Windows/x86 */
__attribute__((__optnone__))
#endif
sizeOfEncoding(const char **type, size_t *length)
{
	size_t size;

	if (*length == 0)
		@throw [OFInvalidFormatException exception];

581
582
583
584
585
586
587





588
589
590
591
592
593
594
}

@implementation OFMethodSignature
+ (instancetype)signatureWithObjCTypes: (const char*)types
{
	return [[[self alloc] initWithObjCTypes: types] autorelease];
}






- (instancetype)initWithObjCTypes: (const char *)types
{
	self = [super init];

	@try {
		size_t length;







>
>
>
>
>







587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
}

@implementation OFMethodSignature
+ (instancetype)signatureWithObjCTypes: (const char*)types
{
	return [[[self alloc] initWithObjCTypes: types] autorelease];
}

- (instancetype)init
{
	OF_INVALID_INIT_METHOD
}

- (instancetype)initWithObjCTypes: (const char *)types
{
	self = [super init];

	@try {
		size_t length;

Modified src/OFMutableArchiveEntry.h from [ffb170561c] to [b33a39ff2a].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFMutableArray.h from [43a8133fa8] to [0bd3e8dd33].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
49
50
51
52
53
54
55







56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
 *	  number of objects.
 *
 * @param capacity The initial capacity for the OFMutableArray
 * @return A new autoreleased OFMutableArray
 */
+ (instancetype)arrayWithCapacity: (size_t)capacity;








/**
 * @brief Initializes an already allocated OFMutableArray with enough memory to
 *	  hold the specified number of objects.
 *
 * @param capacity The initial capacity for the OFMutableArray
 * @return An initialized OFMutableArray
 */
- (instancetype)initWithCapacity: (size_t)capacity;

/**
 * @brief Adds an object to the end of the array.
 *
 * @param object An object to add
 */
- (void)addObject: (ObjectType)object;







>
>
>
>
>
>
>







|







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
 *	  number of objects.
 *
 * @param capacity The initial capacity for the OFMutableArray
 * @return A new autoreleased OFMutableArray
 */
+ (instancetype)arrayWithCapacity: (size_t)capacity;

/**
 * @brief Initializes an OFMutableArray with no objects.
 *
 * @return An initialized OFMutableArray
 */
- (instancetype)init OF_DESIGNATED_INITIALIZER;

/**
 * @brief Initializes an already allocated OFMutableArray with enough memory to
 *	  hold the specified number of objects.
 *
 * @param capacity The initial capacity for the OFMutableArray
 * @return An initialized OFMutableArray
 */
- (instancetype)initWithCapacity: (size_t)capacity OF_DESIGNATED_INITIALIZER;

/**
 * @brief Adds an object to the end of the array.
 *
 * @param object An object to add
 */
- (void)addObject: (ObjectType)object;
198
199
200
201
202
203
204











205
206
207
208
209
210
211
 *
 * @param selector The selector to use to sort the array. It's signature
 *		   should be the same as that of -[compare:].
 * @param options The options to use when sorting the array
 */
- (void)sortUsingSelector: (SEL)selector options: (OFArraySortOptions)options;












#ifdef OF_HAVE_BLOCKS
/**
 * @brief Sorts the array using the specified comparator and options.
 *
 * @param comparator The comparator to use to sort the array
 * @param options The options to use when sorting the array
 */







>
>
>
>
>
>
>
>
>
>
>







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
 *
 * @param selector The selector to use to sort the array. It's signature
 *		   should be the same as that of -[compare:].
 * @param options The options to use when sorting the array
 */
- (void)sortUsingSelector: (SEL)selector options: (OFArraySortOptions)options;

/**
 * @brief Sorts the array using the specified function and options.
 *
 * @param compare The function to use to sort the array
 * @param context Context passed to the function to compare
 * @param options The options to use when sorting the array
 */
- (void)sortUsingFunction: (OFCompareFunction)compare
		  context: (nullable void *)context
		  options: (OFArraySortOptions)options;

#ifdef OF_HAVE_BLOCKS
/**
 * @brief Sorts the array using the specified comparator and options.
 *
 * @param comparator The comparator to use to sort the array
 * @param options The options to use when sorting the array
 */

Modified src/OFMutableArray.m from [ba1c079bde] to [0029147821].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86

87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214

215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241








242
243

244
245
246
247
248
249



250
251
252
253
254
255
256
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#include <stdlib.h>
#include <string.h>

#include <assert.h>

#import "OFMutableArray.h"
#import "OFMutableAdjacentArray.h"

#import "OFEnumerationMutationException.h"
#import "OFInvalidArgumentException.h"
#import "OFOutOfRangeException.h"

static struct {
	Class isa;
} placeholder;

@interface OFMutableArrayPlaceholder: OFMutableArray
@end

static OFComparisonResult
compare(id left, id right, SEL selector)
{
	OFComparisonResult (*comparator)(id, SEL, id) =
	    (OFComparisonResult (*)(id, SEL, id))
	    [left methodForSelector: selector];

	return comparator(left, selector, right);
}

static void
quicksort(OFMutableArray *array, size_t left, size_t right, SEL selector,
    OFArraySortOptions options)
{
	OFComparisonResult ascending, descending;

	if (options & OFArraySortDescending) {
		ascending = OFOrderedDescending;
		descending = OFOrderedAscending;
	} else {
		ascending = OFOrderedAscending;
		descending = OFOrderedDescending;
	}

	while (left < right) {
		size_t i = left;
		size_t j = right - 1;
		id pivot = [array objectAtIndex: right];

		do {
			while (compare([array objectAtIndex: i], pivot,
			    selector) != descending && i < right)
				i++;

			while (compare([array objectAtIndex: j], pivot,
			    selector) != ascending && j > left)
				j--;

			if (i < j)
				[array exchangeObjectAtIndex: i
					   withObjectAtIndex: j];
		} while (i < j);

		if (compare([array objectAtIndex: i], pivot, selector) ==
		    descending)
			[array exchangeObjectAtIndex: i
				   withObjectAtIndex: right];

		if (i > 0)
			quicksort(array, left, i - 1, selector, options);


		left = i + 1;
	}
}

#ifdef OF_HAVE_BLOCKS
static void
quicksortWithBlock(OFMutableArray *array, size_t left, size_t right,
    OFComparator comparator, OFArraySortOptions options)
{
	OFComparisonResult ascending, descending;

	if (options & OFArraySortDescending) {
		ascending = OFOrderedDescending;
		descending = OFOrderedAscending;
	} else {
		ascending = OFOrderedAscending;
		descending = OFOrderedDescending;
	}

	while (left < right) {
		size_t i = left;
		size_t j = right - 1;
		id pivot = [array objectAtIndex: right];

		do {
			while (comparator([array objectAtIndex: i], pivot) !=
			    descending && i < right)
				i++;

			while (comparator([array objectAtIndex: j], pivot) !=
			    ascending && j > left)
				j--;

			if (i < j)
				[array exchangeObjectAtIndex: i
					   withObjectAtIndex: j];
		} while (i < j);

		if (comparator([array objectAtIndex: i], pivot) == descending)
			[array exchangeObjectAtIndex: i
				   withObjectAtIndex: right];

		if (i > 0)
			quicksortWithBlock(array, left, i - 1, comparator,
			    options);

		left = i + 1;
	}
}
#endif

@implementation OFMutableArrayPlaceholder
- (instancetype)init
{
	return (id)[[OFMutableAdjacentArray alloc] init];
}

- (instancetype)initWithCapacity: (size_t)capacity
{
	return (id)[[OFMutableAdjacentArray alloc] initWithCapacity: capacity];
}

- (instancetype)initWithObject: (id)object
{
	return (id)[[OFMutableAdjacentArray alloc] initWithObject: object];
}

- (instancetype)initWithObjects: (id)firstObject, ...
{
	id ret;
	va_list arguments;

	va_start(arguments, firstObject);
	ret = [[OFMutableAdjacentArray alloc] initWithObject: firstObject
						   arguments: arguments];
	va_end(arguments);

	return ret;
}

- (instancetype)initWithObject: (id)firstObject arguments: (va_list)arguments
{
	return (id)[[OFMutableAdjacentArray alloc] initWithObject: firstObject
							arguments: arguments];
}

- (instancetype)initWithArray: (OFArray *)array
{
	return (id)[[OFMutableAdjacentArray alloc] initWithArray: array];
}

- (instancetype)initWithObjects: (id const *)objects count: (size_t)count
{
	return (id)[[OFMutableAdjacentArray alloc] initWithObjects: objects
							     count: count];
}

- (instancetype)initWithSerialization: (OFXMLElement *)element
{
	return (id)[[OFMutableAdjacentArray alloc]
	    initWithSerialization: element];
}

- (instancetype)retain
{
	return self;
}

- (instancetype)autorelease
{
	return self;
}

- (void)release
{
}

- (void)dealloc
{
	OF_DEALLOC_UNSUPPORTED
}
@end

@implementation OFMutableArray
+ (void)initialize
{
	if (self == [OFMutableArray class])

		placeholder.isa = [OFMutableArrayPlaceholder class];
}

+ (instancetype)alloc
{
	if (self == [OFMutableArray class])
		return (id)&placeholder;

	return [super alloc];
}

+ (instancetype)arrayWithCapacity: (size_t)capacity
{
	return [[[self alloc] initWithCapacity: capacity] autorelease];
}

- (instancetype)init
{
	if ([self isMemberOfClass: [OFMutableArray class]]) {
		@try {
			[self doesNotRecognizeSelector: _cmd];
			abort();
		} @catch (id e) {
			[self release];
			@throw e;
		}
	}









	return [super init];

}

- (instancetype)initWithCapacity: (size_t)capacity
{
	OF_INVALID_INIT_METHOD
}




- (id)copy
{
	return [[OFArray alloc] initWithArray: self];
}

- (void)addObject: (id)object

|


















<
<

|









|


<
<
<
<
<
<
<
<
<
<

|
|


















|



|







|





|
>





<
<
<
<
<
<
|
<
<
<
<
<
<
<
|
<
<
<
<
|
<
<
<
<
|
<
<
<
|
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<

<
<


|




|




|








|








|





|




|


|
<
<
<
<
<
|
<
<
<
<
|
<
|
<
<
|
<
<
<
<
<
<
<
<






>
|

















<
<
<
<
<
|
<
|
|
>
>
>
>
>
>
>
>
|
<
>






>
>
>







1
2
3
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
/*
 * 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 <stdlib.h>
#include <string.h>



#import "OFMutableArray.h"
#import "OFConcreteMutableArray.h"

#import "OFEnumerationMutationException.h"
#import "OFInvalidArgumentException.h"
#import "OFOutOfRangeException.h"

static struct {
	Class isa;
} placeholder;

@interface OFPlaceholderMutableArray: OFMutableArray
@end











static void
quicksort(OFMutableArray *array, size_t left, size_t right,
    OFCompareFunction compare, void *context, OFArraySortOptions options)
{
	OFComparisonResult ascending, descending;

	if (options & OFArraySortDescending) {
		ascending = OFOrderedDescending;
		descending = OFOrderedAscending;
	} else {
		ascending = OFOrderedAscending;
		descending = OFOrderedDescending;
	}

	while (left < right) {
		size_t i = left;
		size_t j = right - 1;
		id pivot = [array objectAtIndex: right];

		do {
			while (compare([array objectAtIndex: i], pivot,
			    context) != descending && i < right)
				i++;

			while (compare([array objectAtIndex: j], pivot,
			    context) != ascending && j > left)
				j--;

			if (i < j)
				[array exchangeObjectAtIndex: i
					   withObjectAtIndex: j];
		} while (i < j);

		if (compare([array objectAtIndex: i], pivot, context) ==
		    descending)
			[array exchangeObjectAtIndex: i
				   withObjectAtIndex: right];

		if (i > 0)
			quicksort(array, left, i - 1, compare, context,
			    options);

		left = i + 1;
	}
}







@implementation OFPlaceholderMutableArray







#ifdef __clang__




/* We intentionally don't call into super, so silence the warning. */




# pragma clang diagnostic push



# pragma clang diagnostic ignored "-Wunknown-pragmas"




# pragma clang diagnostic ignored "-Wobjc-designated-initializers"











#endif


- (instancetype)init
{
	return (id)[[OFConcreteMutableArray alloc] init];
}

- (instancetype)initWithCapacity: (size_t)capacity
{
	return (id)[[OFConcreteMutableArray alloc] initWithCapacity: capacity];
}

- (instancetype)initWithObject: (id)object
{
	return (id)[[OFConcreteMutableArray alloc] initWithObject: object];
}

- (instancetype)initWithObjects: (id)firstObject, ...
{
	id ret;
	va_list arguments;

	va_start(arguments, firstObject);
	ret = [[OFConcreteMutableArray alloc] initWithObject: firstObject
						   arguments: arguments];
	va_end(arguments);

	return ret;
}

- (instancetype)initWithObject: (id)firstObject arguments: (va_list)arguments
{
	return (id)[[OFConcreteMutableArray alloc] initWithObject: firstObject
							arguments: arguments];
}

- (instancetype)initWithArray: (OFArray *)array
{
	return (id)[[OFConcreteMutableArray alloc] initWithArray: array];
}

- (instancetype)initWithObjects: (id const *)objects count: (size_t)count
{
	return (id)[[OFConcreteMutableArray alloc] initWithObjects: objects
							     count: count];
}
#ifdef __clang__





# pragma clang diagnostic pop




#endif




OF_SINGLETON_METHODS








@end

@implementation OFMutableArray
+ (void)initialize
{
	if (self == [OFMutableArray class])
		object_setClass((id)&placeholder,
		    [OFPlaceholderMutableArray class]);
}

+ (instancetype)alloc
{
	if (self == [OFMutableArray class])
		return (id)&placeholder;

	return [super alloc];
}

+ (instancetype)arrayWithCapacity: (size_t)capacity
{
	return [[[self alloc] initWithCapacity: capacity] autorelease];
}

- (instancetype)init
{





	return [super init];

}

#ifdef __clang__
/* We intentionally don't call into super, so silence the warning. */
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wunknown-pragmas"
# pragma clang diagnostic ignored "-Wobjc-designated-initializers"
#endif
- (instancetype)initWithObjects: (id const *)objects
			  count: (size_t)count
{

	OF_INVALID_INIT_METHOD
}

- (instancetype)initWithCapacity: (size_t)capacity
{
	OF_INVALID_INIT_METHOD
}
#ifdef __clang__
# pragma clang diagnostic pop
#endif

- (id)copy
{
	return [[OFArray alloc] initWithArray: self];
}

- (void)addObject: (id)object
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
	}
}

- (void)sort
{
	[self sortUsingSelector: @selector(compare:) options: 0];
}












- (void)sortUsingSelector: (SEL)selector
		  options: (OFArraySortOptions)options
{
	size_t count = self.count;

	if (count == 0 || count == 1)
		return;

	quicksort(self, 0, count - 1, selector, options);













}

#ifdef OF_HAVE_BLOCKS








- (void)sortUsingComparator: (OFComparator)comparator
		    options: (OFArraySortOptions)options
{
	size_t count = self.count;

	if (count == 0 || count == 1)
		return;

	quicksortWithBlock(self, 0, count - 1, comparator, options);
}
#endif

- (void)reverse
{
	size_t i, j, count = self.count;








>
>
>
>
>
>
>
>
>
>
>









|
>
>
>
>
>
>
>
>
>
>
>
>
>



>
>
>
>
>
>
>
>








|







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
	}
}

- (void)sort
{
	[self sortUsingSelector: @selector(compare:) options: 0];
}

static OFComparisonResult
selectorCompare(id left, id right, void *context)
{
	SEL selector = context;
	OFComparisonResult (*comparator)(id, SEL, id) =
	    (OFComparisonResult (*)(id, SEL, id))
	    [left methodForSelector: selector];

	return comparator(left, selector, right);
}

- (void)sortUsingSelector: (SEL)selector
		  options: (OFArraySortOptions)options
{
	size_t count = self.count;

	if (count == 0 || count == 1)
		return;

	quicksort(self, 0, count - 1, selectorCompare, (void *)selector,
	    options);
}

- (void)sortUsingFunction: (OFCompareFunction)compare
		  context: (void *)context
		  options: (OFArraySortOptions)options
{
	size_t count = self.count;

	if (count == 0 || count == 1)
		return;

	quicksort(self, 0, count - 1, compare, context, options);
}

#ifdef OF_HAVE_BLOCKS
static OFComparisonResult
blockCompare(id left, id right, void *context)
{
	OFComparator block = (OFComparator)context;

	return block(left, right);
}

- (void)sortUsingComparator: (OFComparator)comparator
		    options: (OFArraySortOptions)options
{
	size_t count = self.count;

	if (count == 0 || count == 1)
		return;

	quicksort(self, 0, count - 1, blockCompare, comparator, options);
}
#endif

- (void)reverse
{
	size_t i, j, count = self.count;

Modified src/OFMutableData.h from [23548715da] to [c6c96cb2c2].

1
2
3
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
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#import "OFData.h"

OF_ASSUME_NONNULL_BEGIN

@class OFString;
@class OFURI;

/**
 * @class OFMutableData OFMutableData.h ObjFW/OFMutableData.h
 *
 * @brief A class for storing and manipulating arbitrary data in an array.
 */
@interface OFMutableData: OFData
{
	size_t _capacity;
	OF_RESERVE_IVARS(OFMutableData, 4)
}

/**
 * @brief All items of the OFMutableData as a C array.
 *
 * @warning The pointer is only valid until the OFMutableData is changed!
 *
 * Modifying the returned array directly is allowed and will change the contents
 * of the data.

|

















<
<
<






<
<
<
<
<







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19



20
21
22
23
24
25





26
27
28
29
30
31
32
/*
 * Copyright (c) 2008-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 "OFData.h"

OF_ASSUME_NONNULL_BEGIN




/**
 * @class OFMutableData OFMutableData.h ObjFW/OFMutableData.h
 *
 * @brief A class for storing and manipulating arbitrary data in an array.
 */
@interface OFMutableData: OFData





/**
 * @brief All items of the OFMutableData as a C array.
 *
 * @warning The pointer is only valid until the OFMutableData is changed!
 *
 * Modifying the returned array directly is allowed and will change the contents
 * of the data.
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

/**
 * @brief The last item of the OFMutableData or `NULL`.
 */
@property OF_NULLABLE_PROPERTY (readonly, nonatomic) void *mutableLastItem
    OF_RETURNS_INNER_POINTER;

/**
 * @brief Creates a new OFMutableData with an item size of 1.
 *
 * @return A new autoreleased OFMutableData
 */
+ (instancetype)data;

/**
 * @brief Creates a new OFMutableData whose items all have the same specified
 *	  size.
 *
 * @param itemSize The size of a single element in the OFMutableData
 * @return A new autoreleased OFMutableData
 */
+ (instancetype)dataWithItemSize: (size_t)itemSize;

/**
 * @brief Creates a new OFMutableData with enough memory to hold the specified
 *	  number of items which all have an item size of 1.
 *
 * @param capacity The initial capacity for the OFMutableData
 * @return A new autoreleased OFMutableData
 */
+ (instancetype)dataWithCapacity: (size_t)capacity;

/**
 * @brief Creates a new OFMutableData with enough memory to hold the specified
 *	  number of items which all have the same specified size.
 *
 * @param itemSize The size of a single element in the OFMutableData
 * @param capacity The initial capacity for the OFMutableData
 * @return A new autoreleased OFMutableData
 */
+ (instancetype)dataWithItemSize: (size_t)itemSize capacity: (size_t)capacity;

/**
 * @brief Initializes an already allocated OFMutableData with an item size of 1.
 *
 * @return An initialized OFMutableData
 */
- (instancetype)init;

/**
 * @brief Initializes an already allocated OFMutableData whose items all have
 *	  the same size.
 *
 * @param itemSize The size of a single element in the OFMutableData
 * @return An initialized OFMutableData
 */
- (instancetype)initWithItemSize: (size_t)itemSize;

/**
 * @brief Initializes an already allocated OFMutableData with enough memory to
 *	  hold the the specified number of items which all have an item size of
 *	  1.
 *
 * @param capacity The initial capacity for the OFMutableData
 * @return An initialized OFMutableData







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<



















<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







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

/**
 * @brief The last item of the OFMutableData or `NULL`.
 */
@property OF_NULLABLE_PROPERTY (readonly, nonatomic) void *mutableLastItem
    OF_RETURNS_INNER_POINTER;

















/**
 * @brief Creates a new OFMutableData with enough memory to hold the specified
 *	  number of items which all have an item size of 1.
 *
 * @param capacity The initial capacity for the OFMutableData
 * @return A new autoreleased OFMutableData
 */
+ (instancetype)dataWithCapacity: (size_t)capacity;

/**
 * @brief Creates a new OFMutableData with enough memory to hold the specified
 *	  number of items which all have the same specified size.
 *
 * @param itemSize The size of a single element in the OFMutableData
 * @param capacity The initial capacity for the OFMutableData
 * @return A new autoreleased OFMutableData
 */
+ (instancetype)dataWithItemSize: (size_t)itemSize capacity: (size_t)capacity;

















/**
 * @brief Initializes an already allocated OFMutableData with enough memory to
 *	  hold the the specified number of items which all have an item size of
 *	  1.
 *
 * @param capacity The initial capacity for the OFMutableData
 * @return An initialized OFMutableData

Modified src/OFMutableData.m from [b4151ce5ed] to [6d7690e898].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28





























































































29







30
31


32

33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140

141
142
143
144
145
146
147
148
149
150
151
152

153

154
155
156
157
158
159
160



161
162
163
164
165
166
167
168


169
170
171
172

173

174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280

281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#include <stdlib.h>
#include <string.h>
#include <limits.h>

#import "OFMutableData.h"
#import "OFString.h"

#import "OFInvalidArgumentException.h"
#import "OFOutOfMemoryException.h"
#import "OFOutOfRangeException.h"






























































































@implementation OFMutableData







+ (instancetype)data
{


	return [[[self alloc] init] autorelease];

}

+ (instancetype)dataWithItemSize: (size_t)itemSize
{
	return [[[self alloc] initWithItemSize: itemSize] autorelease];
}

+ (instancetype)dataWithCapacity: (size_t)capacity
{
	return [[[self alloc] initWithCapacity: capacity] autorelease];
}

+ (instancetype)dataWithItemSize: (size_t)itemSize capacity: (size_t)capacity
{
	return [[[self alloc] initWithItemSize: itemSize
				      capacity: capacity] autorelease];
}

- (instancetype)init
{
	self = [super init];

	_itemSize = 1;
	_freeWhenDone = true;

	return self;
}

- (instancetype)initWithItemSize: (size_t)itemSize
{
	self = [super init];

	@try {
		if (itemSize == 0)
			@throw [OFInvalidArgumentException exception];

		_itemSize = itemSize;
		_freeWhenDone = true;
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (instancetype)initWithCapacity: (size_t)capacity
{
	return [self initWithItemSize: 1
			     capacity: capacity];
}

- (instancetype)initWithItemSize: (size_t)itemSize capacity: (size_t)capacity
{
	self = [super init];

	@try {
		if (itemSize == 0)
			@throw [OFInvalidArgumentException exception];

		_items = OFAllocMemory(capacity, itemSize);
		_itemSize = itemSize;
		_capacity = capacity;
		_freeWhenDone = true;
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (instancetype)initWithItems: (const void *)items
			count: (size_t)count
		     itemSize: (size_t)itemSize
{
	self = [super initWithItems: items count: count itemSize: itemSize];

	_capacity = _count;

	return self;
}

- (instancetype)initWithItemsNoCopy: (void *)items
			      count: (size_t)count
			   itemSize: (size_t)itemSize
		       freeWhenDone: (bool)freeWhenDone
{
	self = [self initWithItems: items count: count itemSize: itemSize];

	if (freeWhenDone)
		OFFreeMemory(items);

	return self;
}

- (instancetype)initWithStringRepresentation: (OFString *)string
{
	self = [super initWithStringRepresentation: string];

	_capacity = _count;

	return self;
}

- (void *)mutableItems
{
	return _items;

}

- (void *)mutableItemAtIndex: (size_t)idx
{
	if (idx >= _count)
		@throw [OFOutOfRangeException exception];

	return _items + idx * _itemSize;
}

- (void *)mutableFirstItem
{

	if (_items == NULL || _count == 0)

		return NULL;

	return _items;
}

- (void *)mutableLastItem
{



	if (_items == NULL || _count == 0)
		return NULL;

	return _items + (_count - 1) * _itemSize;
}

- (OFData *)subdataWithRange: (OFRange)range
{


	if (range.length > SIZE_MAX - range.location ||
	    range.location + range.length > _count)
		@throw [OFOutOfRangeException exception];


	return [OFData dataWithItems: _items + (range.location * _itemSize)

			       count: range.length
			    itemSize: _itemSize];
}

- (void)addItem: (const void *)item
{
	if (SIZE_MAX - _count < 1)
		@throw [OFOutOfRangeException exception];

	if (_count + 1 > _capacity) {
		_items = OFResizeMemory(_items, _count + 1, _itemSize);
		_capacity = _count + 1;
	}

	memcpy(_items + _count * _itemSize, item, _itemSize);

	_count++;
}

- (void)insertItem: (const void *)item atIndex: (size_t)idx
{
	[self insertItems: item atIndex: idx count: 1];
}

- (void)addItems: (const void *)items count: (size_t)count
{
	if (count > SIZE_MAX - _count)
		@throw [OFOutOfRangeException exception];

	if (_count + count > _capacity) {
		_items = OFResizeMemory(_items, _count + count, _itemSize);
		_capacity = _count + count;
	}

	memcpy(_items + _count * _itemSize, items, count * _itemSize);
	_count += count;
}

- (void)insertItems: (const void *)items
	    atIndex: (size_t)idx
	      count: (size_t)count
{
	if (count > SIZE_MAX - _count || idx > _count)
		@throw [OFOutOfRangeException exception];

	if (_count + count > _capacity) {
		_items = OFResizeMemory(_items, _count + count, _itemSize);
		_capacity = _count + count;
	}

	memmove(_items + (idx + count) * _itemSize, _items + idx * _itemSize,
	    (_count - idx) * _itemSize);
	memcpy(_items + idx * _itemSize, items, count * _itemSize);

	_count += count;
}

- (void)increaseCountBy: (size_t)count
{
	if (count > SIZE_MAX - _count)
		@throw [OFOutOfRangeException exception];

	if (_count + count > _capacity) {
		_items = OFResizeMemory(_items, _count + count, _itemSize);
		_capacity = _count + count;
	}

	memset(_items + _count * _itemSize, '\0', count * _itemSize);
	_count += count;
}

- (void)removeItemAtIndex: (size_t)idx
{
	[self removeItemsInRange: OFMakeRange(idx, 1)];
}

- (void)removeItemsInRange: (OFRange)range
{
	if (range.length > SIZE_MAX - range.location ||
	    range.location + range.length > _count)
		@throw [OFOutOfRangeException exception];

	memmove(_items + range.location * _itemSize,
	    _items + (range.location + range.length) * _itemSize,
	    (_count - range.location - range.length) * _itemSize);

	_count -= range.length;
	@try {
		_items = OFResizeMemory(_items, _count, _itemSize);
		_capacity = _count;
	} @catch (OFOutOfMemoryException *e) {
		/* We don't really care, as we only made it smaller */
	}
}

- (void)removeLastItem
{
	if (_count == 0)
		return;

	_count--;
	@try {
		_items = OFResizeMemory(_items, _count, _itemSize);
		_capacity = _count;
	} @catch (OFOutOfMemoryException *e) {
		/* We don't care, as we only made it smaller */
	}

}

- (void)removeAllItems
{
	OFFreeMemory(_items);
	_items = NULL;
	_count = 0;
	_capacity = 0;
}

- (id)copy
{
	return [[OFData alloc] initWithItems: _items
				       count: _count
				    itemSize: _itemSize];
}

- (void)makeImmutable
{
	if (_capacity != _count) {
		@try {
			_items = OFResizeMemory(_items, _count, _itemSize);
			_capacity = _count;
		} @catch (OFOutOfMemoryException *e) {
			/* We don't care, as we only made it smaller */
		}
	}

	object_setClass(self, [OFData class]);
}
@end

|




















|

<
<


>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
>
>
>
>
>
|

>
>
|
>


















<
<
<
<
<
<
<
<
<
<


<
<
<
<
<
<
<
<
<
<
<
<
<
|




|
<




<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<















<
<
<
<
<
<
<
<
<


<
>




|


|




>
|
>


|




>
>
>
|


|




>
>

|


>
|
>

|




<
<
|
<
<
<
<
<
<
<
<









<
<
|
<
<
<
<
<
<
<






<
<
|
<
<
<
<
<
<
<
<
<
<




<
<
|
<
<
<
<
<
<
<









<
<
<
|
<
<
<
<
<
<
<
<
<
<
<




|
<

|
|
<
<
<
<
|
>




<
<
|
<




|
|
|




<
<
<
<
<
<
|
<
<
<
<

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24


25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151










152
153













154
155
156
157
158
159

160
161
162
163

164

























165
166
167
168
169
170
171
172
173
174
175
176
177
178
179









180
181

182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230


231








232
233
234
235
236
237
238
239
240


241







242
243
244
245
246
247


248










249
250
251
252


253







254
255
256
257
258
259
260
261
262



263











264
265
266
267
268

269
270
271




272
273
274
275
276
277


278

279
280
281
282
283
284
285
286
287
288
289






290




291
/*
 * 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 <stdlib.h>
#include <string.h>
#include <limits.h>

#import "OFMutableData.h"
#import "OFConcreteMutableData.h"



#import "OFOutOfRangeException.h"

static struct {
	Class isa;
} placeholder;

@interface OFPlaceholderMutableData: OFMutableData
@end

@implementation OFPlaceholderMutableData
- (instancetype)init
{
	return (id)[[OFConcreteMutableData alloc] init];
}

- (instancetype)initWithItemSize: (size_t)itemSize
{
	return (id)[[OFConcreteMutableData alloc] initWithItemSize: itemSize];
}

- (instancetype)initWithItems: (const void *)items count: (size_t)count
{
	return (id)[[OFConcreteMutableData alloc] initWithItems: items
							  count: count];
}

- (instancetype)initWithItems: (const void *)items
			count: (size_t)count
		     itemSize: (size_t)itemSize
{
	return (id)[[OFConcreteMutableData alloc] initWithItems: items
							  count: count
						       itemSize: itemSize];
}

- (instancetype)initWithItemsNoCopy: (void *)items
			      count: (size_t)count
		       freeWhenDone: (bool)freeWhenDone
{
	return (id)[[OFConcreteMutableData alloc]
	    initWithItemsNoCopy: items
			  count: count
		   freeWhenDone: freeWhenDone];
}

- (instancetype)initWithItemsNoCopy: (void *)items
			      count: (size_t)count
			   itemSize: (size_t)itemSize
		       freeWhenDone: (bool)freeWhenDone
{
	return (id)[[OFConcreteMutableData alloc]
	    initWithItemsNoCopy: items
			  count: count
		       itemSize: itemSize
		   freeWhenDone: freeWhenDone];
}

#ifdef OF_HAVE_FILES
- (instancetype)initWithContentsOfFile: (OFString *)path
{
	return (id)[[OFConcreteMutableData alloc] initWithContentsOfFile: path];
}
#endif

- (instancetype)initWithContentsOfIRI: (OFIRI *)IRI
{
	return (id)[[OFConcreteMutableData alloc] initWithContentsOfIRI: IRI];
}

- (instancetype)initWithStringRepresentation: (OFString *)string
{
	return (id)[[OFConcreteMutableData alloc]
	    initWithStringRepresentation: string];
}

- (instancetype)initWithBase64EncodedString: (OFString *)string
{
	return (id)[[OFConcreteMutableData alloc]
	    initWithBase64EncodedString: string];
}

- (instancetype)initWithCapacity: (size_t)capacity
{
	return (id)[[OFConcreteMutableData alloc] initWithCapacity: capacity];
}

- (instancetype)initWithItemSize: (size_t)itemSize capacity: (size_t)capacity
{
	return (id)[[OFConcreteMutableData alloc] initWithItemSize: itemSize
							  capacity: capacity];
}

OF_SINGLETON_METHODS
@end

@implementation OFMutableData
+ (void)initialize
{
	if (self == [OFMutableData class])
		object_setClass((id)&placeholder,
		    [OFPlaceholderMutableData class]);
}

+ (instancetype)alloc
{
	if (self == [OFMutableData class])
		return (id)&placeholder;

	return [super alloc];
}

+ (instancetype)dataWithItemSize: (size_t)itemSize
{
	return [[[self alloc] initWithItemSize: itemSize] autorelease];
}

+ (instancetype)dataWithCapacity: (size_t)capacity
{
	return [[[self alloc] initWithCapacity: capacity] autorelease];
}

+ (instancetype)dataWithItemSize: (size_t)itemSize capacity: (size_t)capacity
{
	return [[[self alloc] initWithItemSize: itemSize
				      capacity: capacity] autorelease];
}











- (instancetype)initWithItemSize: (size_t)itemSize
{













	return [self initWithItemSize: 1 capacity: 0];
}

- (instancetype)initWithCapacity: (size_t)capacity
{
	return [self initWithItemSize: 1 capacity: capacity];

}

- (instancetype)initWithItemSize: (size_t)itemSize capacity: (size_t)capacity
{

	OF_INVALID_INIT_METHOD

























}

- (instancetype)initWithItemsNoCopy: (void *)items
			      count: (size_t)count
			   itemSize: (size_t)itemSize
		       freeWhenDone: (bool)freeWhenDone
{
	self = [self initWithItems: items count: count itemSize: itemSize];

	if (freeWhenDone)
		OFFreeMemory(items);

	return self;
}










- (void *)mutableItems
{

	OF_UNRECOGNIZED_SELECTOR
}

- (void *)mutableItemAtIndex: (size_t)idx
{
	if (idx >= self.count)
		@throw [OFOutOfRangeException exception];

	return (unsigned char *)self.mutableItems + idx * self.itemSize;
}

- (void *)mutableFirstItem
{
	void *mutableItems = self.mutableItems;

	if (mutableItems == NULL || self.count == 0)
		return NULL;

	return mutableItems;
}

- (void *)mutableLastItem
{
	unsigned char *mutableItems = self.mutableItems;
	size_t count = self.count;

	if (mutableItems == NULL || count == 0)
		return NULL;

	return mutableItems + (count - 1) * self.itemSize;
}

- (OFData *)subdataWithRange: (OFRange)range
{
	size_t itemSize;

	if (range.length > SIZE_MAX - range.location ||
	    range.location + range.length > self.count)
		@throw [OFOutOfRangeException exception];

	itemSize = self.itemSize;
	return [OFData dataWithItems: (unsigned char *)self.mutableItems +
				      (range.location * itemSize)
			       count: range.length
			    itemSize: itemSize];
}

- (void)addItem: (const void *)item
{


	[self insertItems: item atIndex: self.count count: 1];








}

- (void)insertItem: (const void *)item atIndex: (size_t)idx
{
	[self insertItems: item atIndex: idx count: 1];
}

- (void)addItems: (const void *)items count: (size_t)count
{


	[self insertItems: items atIndex: self.count count: count];







}

- (void)insertItems: (const void *)items
	    atIndex: (size_t)idx
	      count: (size_t)count
{


	OF_UNRECOGNIZED_SELECTOR










}

- (void)increaseCountBy: (size_t)count
{


	OF_UNRECOGNIZED_SELECTOR







}

- (void)removeItemAtIndex: (size_t)idx
{
	[self removeItemsInRange: OFMakeRange(idx, 1)];
}

- (void)removeItemsInRange: (OFRange)range
{



	OF_UNRECOGNIZED_SELECTOR











}

- (void)removeLastItem
{
	size_t count = self.count;


	if (count == 0)
		return;





	[self removeItemsInRange: OFMakeRange(count - 1, 1)];
}

- (void)removeAllItems
{


	[self removeItemsInRange: OFMakeRange(0, self.count)];

}

- (id)copy
{
	return [[OFData alloc] initWithItems: self.mutableItems
				       count: self.count
				    itemSize: self.itemSize];
}

- (void)makeImmutable
{






}




@end

Modified src/OFMutableDictionary.h from [851a8f19f7] to [30d990b8d9].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
50
51
52
53
54
55
56







57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
 *	  specified number of objects.
 *
 * @param capacity The initial capacity for the OFMutableDictionary
 * @return A new autoreleased OFMutableDictionary
 */
+ (instancetype)dictionaryWithCapacity: (size_t)capacity;








/**
 * @brief Initializes an already allocated OFMutableDictionary with enough
 *	  memory to hold the specified number of objects.
 *
 * @param capacity The initial capacity for the OFMutableDictionary
 * @return An initialized OFMutableDictionary
 */
- (instancetype)initWithCapacity: (size_t)capacity;

/**
 * @brief Sets an object for a key.
 *
 * A key can be any object that conforms to the OFCopying protocol.
 *
 * @param key The key to set







>
>
>
>
>
>
>







|







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
 *	  specified number of objects.
 *
 * @param capacity The initial capacity for the OFMutableDictionary
 * @return A new autoreleased OFMutableDictionary
 */
+ (instancetype)dictionaryWithCapacity: (size_t)capacity;

/**
 * @brief Initializes an already allocated OFMutableDictionary to be empty.
 *
 * @return An initialized OFMutableDictionary
 */
- (instancetype)init OF_DESIGNATED_INITIALIZER;

/**
 * @brief Initializes an already allocated OFMutableDictionary with enough
 *	  memory to hold the specified number of objects.
 *
 * @param capacity The initial capacity for the OFMutableDictionary
 * @return An initialized OFMutableDictionary
 */
- (instancetype)initWithCapacity: (size_t)capacity OF_DESIGNATED_INITIALIZER;

/**
 * @brief Sets an object for a key.
 *
 * A key can be any object that conforms to the OFCopying protocol.
 *
 * @param key The key to set

Modified src/OFMutableDictionary.m from [459ca84c71] to [851457fb25].

1
2
3
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
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#include <stdlib.h>

#import "OFMutableMapTableDictionary.h"
#import "OFArray.h"
#import "OFString.h"

static struct {
	Class isa;
} placeholder;

@interface OFMutableDictionaryPlaceholder: OFDictionary
@end

@implementation OFMutableDictionaryPlaceholder
- (instancetype)init
{
	return (id)[[OFMutableMapTableDictionary alloc] init];
}

- (instancetype)initWithDictionary: (OFDictionary *)dictionary
{
	return (id)[[OFMutableMapTableDictionary alloc]
	    initWithDictionary: dictionary];
}

- (instancetype)initWithObject: (id)object forKey: (id)key
{
	return (id)[[OFMutableMapTableDictionary alloc] initWithObject: object
								forKey: key];
}

- (instancetype)initWithObjects: (OFArray *)objects forKeys: (OFArray *)keys
{
	return (id)[[OFMutableMapTableDictionary alloc] initWithObjects: objects
								forKeys: keys];
}

- (instancetype)initWithObjects: (id const *)objects
			forKeys: (id const *)keys
			  count: (size_t)count
{
	return (id)[[OFMutableMapTableDictionary alloc] initWithObjects: objects
								forKeys: keys
								  count: count];
}

- (instancetype)initWithKeysAndObjects: (id)firstKey, ...
{
	id ret;
	va_list arguments;

	va_start(arguments, firstKey);
	ret = (id)[[OFMutableMapTableDictionary alloc] initWithKey: firstKey
							 arguments: arguments];
	va_end(arguments);

	return ret;
}

- (instancetype)initWithKey: (id)firstKey arguments: (va_list)arguments
{
	return (id)[[OFMutableMapTableDictionary alloc] initWithKey: firstKey
							  arguments: arguments];
}

- (instancetype)initWithSerialization: (OFXMLElement *)element
{
	return (id)[[OFMutableMapTableDictionary alloc]
	    initWithSerialization: element];
}

- (instancetype)initWithCapacity: (size_t)capacity
{
	return (id)[[OFMutableMapTableDictionary alloc]
	    initWithCapacity: capacity];
}

- (instancetype)retain
{
	return self;
}

- (instancetype)autorelease
{
	return self;
}

- (void)release
{
}

- (void)dealloc
{
	OF_DEALLOC_UNSUPPORTED
}
@end

@implementation OFMutableDictionary
+ (void)initialize
{
	if (self == [OFMutableDictionary class])

		placeholder.isa = [OFMutableDictionaryPlaceholder class];
}

+ (instancetype)alloc
{
	if (self == [OFMutableDictionary class])
		return (id)&placeholder;

	return [super alloc];
}

+ (instancetype)dictionaryWithCapacity: (size_t)capacity
{
	return [[[self alloc] initWithCapacity: capacity] autorelease];
}

- (instancetype)init
{
	if ([self isMemberOfClass: [OFMutableDictionary class]]) {
		@try {
			[self doesNotRecognizeSelector: _cmd];
		} @catch (id e) {
			[self release];
			@throw e;
		}








		abort();
	}


	return [super init];

}

- (instancetype)initWithCapacity: (size_t)capacity
{
	OF_INVALID_INIT_METHOD
}




- (void)setObject: (id)object forKey: (id)key
{
	OF_UNRECOGNIZED_SELECTOR
}

- (void)setObject: (id)object forKeyedSubscript: (id)key

|

















|







|


|


|




|





|





|







|










|








|



<
<
<
<
<
<


|



<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<






>
|

















<
<
<
<
|
<
|

>
>
>
>
>
>
>
|
<
>
|
<
>






>
>
>







1
2
3
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
/*
 * 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 <stdlib.h>

#import "OFConcreteMutableDictionary.h"
#import "OFArray.h"
#import "OFString.h"

static struct {
	Class isa;
} placeholder;

@interface OFPlaceholderMutableDictionary: OFDictionary
@end

@implementation OFPlaceholderMutableDictionary
- (instancetype)init
{
	return (id)[[OFConcreteMutableDictionary alloc] init];
}

- (instancetype)initWithDictionary: (OFDictionary *)dictionary
{
	return (id)[[OFConcreteMutableDictionary alloc]
	    initWithDictionary: dictionary];
}

- (instancetype)initWithObject: (id)object forKey: (id)key
{
	return (id)[[OFConcreteMutableDictionary alloc] initWithObject: object
								forKey: key];
}

- (instancetype)initWithObjects: (OFArray *)objects forKeys: (OFArray *)keys
{
	return (id)[[OFConcreteMutableDictionary alloc] initWithObjects: objects
								forKeys: keys];
}

- (instancetype)initWithObjects: (id const *)objects
			forKeys: (id const *)keys
			  count: (size_t)count
{
	return (id)[[OFConcreteMutableDictionary alloc] initWithObjects: objects
								forKeys: keys
								  count: count];
}

- (instancetype)initWithKeysAndObjects: (id)firstKey, ...
{
	id ret;
	va_list arguments;

	va_start(arguments, firstKey);
	ret = (id)[[OFConcreteMutableDictionary alloc] initWithKey: firstKey
							 arguments: arguments];
	va_end(arguments);

	return ret;
}

- (instancetype)initWithKey: (id)firstKey arguments: (va_list)arguments
{
	return (id)[[OFConcreteMutableDictionary alloc] initWithKey: firstKey
							  arguments: arguments];
}







- (instancetype)initWithCapacity: (size_t)capacity
{
	return (id)[[OFConcreteMutableDictionary alloc]
	    initWithCapacity: capacity];
}





OF_SINGLETON_METHODS













@end

@implementation OFMutableDictionary
+ (void)initialize
{
	if (self == [OFMutableDictionary class])
		object_setClass((id)&placeholder,
		    [OFPlaceholderMutableDictionary class]);
}

+ (instancetype)alloc
{
	if (self == [OFMutableDictionary class])
		return (id)&placeholder;

	return [super alloc];
}

+ (instancetype)dictionaryWithCapacity: (size_t)capacity
{
	return [[[self alloc] initWithCapacity: capacity] autorelease];
}

- (instancetype)init
{




	return [super init];

}

#ifdef __clang__
/* We intentionally don't call into super, so silence the warning. */
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wunknown-pragmas"
# pragma clang diagnostic ignored "-Wobjc-designated-initializers"
#endif
- (instancetype)initWithObjects: (id const *)objects
			forKeys: (id const *)keys

			  count: (size_t)count
{

	OF_INVALID_INIT_METHOD
}

- (instancetype)initWithCapacity: (size_t)capacity
{
	OF_INVALID_INIT_METHOD
}
#ifdef __clang__
# pragma clang diagnostic pop
#endif

- (void)setObject: (id)object forKey: (id)key
{
	OF_UNRECOGNIZED_SELECTOR
}

- (void)setObject: (id)object forKeyedSubscript: (id)key

Renamed and modified src/OFMutableURI.h [9400cfdc05] to src/OFMutableIRI.h [e8a4ec8dda].

1
2
3
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
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#import "OFURI.h"

OF_ASSUME_NONNULL_BEGIN

/**
 * @class OFMutableURI OFMutableURI.h ObjFW/OFMutableURI.h
 *
 * @brief A class for parsing URIs as per RFC 3986 and accessing and modifying
 *	  parts of it.


 */
@interface OFMutableURI: OFURI
{
	OF_RESERVE_IVARS(OFMutableURI, 4)
}

/**
 * @brief The scheme part of the URI.
 *
 * @throw OFInvalidFormatException The scheme being set is not in the correct
 *				   format
 */
@property (readwrite, copy, nonatomic) OFString *scheme;

/**
 * @brief The host part of the URI.
 */
@property OF_NULLABLE_PROPERTY (readwrite, copy, nonatomic) OFString *host;

/**
 * @brief The host part of the URI in percent-encoded form.
 *
 * Setting this retains the original percent-encoding used - if more characters
 * than necessary are percent-encoded, it is kept this way.
 *
 * @throw OFInvalidFormatException The host being set is not in the correct
 *				   format
 */
@property OF_NULLABLE_PROPERTY (readwrite, copy, nonatomic)
    OFString *percentEncodedHost;

/**
 * @brief The port part of the URI.
 *
 * @throw OFInvalidArgumentException The port is not valid (e.g. negative or
 *				     too big)
 */
@property OF_NULLABLE_PROPERTY (readwrite, copy, nonatomic) OFNumber *port;

/**
 * @brief The user part of the URI.
 */
@property OF_NULLABLE_PROPERTY (readwrite, copy, nonatomic) OFString *user;

/**
 * @brief The user part of the URI in percent-encoded form.
 *
 * Setting this retains the original percent-encoding used - if more characters
 * than necessary are percent-encoded, it is kept this way.
 *
 * @throw OFInvalidFormatException The user being set is not in the correct
 *				   format
 */
@property OF_NULLABLE_PROPERTY (readwrite, copy, nonatomic)
    OFString *percentEncodedUser;

/**
 * @brief The password part of the URI.
 */
@property OF_NULLABLE_PROPERTY (readwrite, copy, nonatomic) OFString *password;

/**
 * @brief The password part of the URI in URI-encoded form.
 *
 * Setting this retains the original percent-encoding used - if more characters
 * than necessary are percent-encoded, it is kept this way.
 *
 * @throw OFInvalidFormatException The password being set is not in the correct
 *				   format
 */
@property OF_NULLABLE_PROPERTY (readwrite, copy, nonatomic)
    OFString *percentEncodedPassword;

/**
 * @brief The path part of the URI.
 */
@property (readwrite, copy, nonatomic) OFString *path;

/**
 * @brief The path part of the URI in percent-encoded form.
 *
 * Setting this retains the original percent-encoding used - if more characters
 * than necessary are percent-encoded, it is kept this way.
 *
 * @throw OFInvalidFormatException The path being set is not in the correct
 *				   format
 */
@property (readwrite, copy, nonatomic) OFString *percentEncodedPath;

/**
 * @brief The path of the URI split into components.
 *
 * The first component must always be empty to designate the root.
 *
 * @throw OFInvalidFormatException The path components being set are not in the
 *				   correct format
 */
@property (readwrite, copy, nonatomic)
    OFArray OF_GENERIC(OFString *) *pathComponents;

/**
 * @brief The query part of the URI.
 */
@property OF_NULLABLE_PROPERTY (readwrite, copy, nonatomic) OFString *query;

/**
 * @brief The query part of the URI in percent-encoded form.
 *
 * Setting this retains the original percent-encoding used - if more characters
 * than necessary are percent-encoded, it is kept this way.
 *
 * @throw OFInvalidFormatException The query being set is not in the correct
 *				   format
 */
@property OF_NULLABLE_PROPERTY (readwrite, copy, nonatomic)
    OFString *percentEncodedQuery;

/**
 * @brief The query part of the URI as an array.
 *
 * For example, a query like `key1=value1&key2=value2` would correspond to the
 * following array:
 *
 *     @[
 *         [OFPair pairWithFirstObject: @"key1" secondObject: @"value1"],
 *         [OFPair pairWithFirstObject: @"key2" secondObject: @"value2"],
 *     ]
 *
 * @throw OFInvalidFormatException The query is not in the correct format
 */
@property OF_NULLABLE_PROPERTY (readwrite, copy, nonatomic)
    OFArray OF_GENERIC(OFPair OF_GENERIC(OFString *, OFString *) *) *queryItems;

/**
 * @brief The fragment part of the URI.
 */
@property OF_NULLABLE_PROPERTY (readwrite, copy, nonatomic) OFString *fragment;

/**
 * @brief The fragment part of the URI in percent-encoded form.
 *
 * Setting this retains the original percent-encoding used - if more characters
 * than necessary are percent-encoded, it is kept this way.
 *
 * @throw OFInvalidFormatException The fragment being set is not in the correct
 *				   format
 */
@property OF_NULLABLE_PROPERTY (readwrite, copy, nonatomic)
    OFString *percentEncodedFragment;

/**
 * @brief Creates a new mutable URI with the specified schemed.
 *
 * @param scheme The scheme for the URI
 * @return A new, autoreleased OFMutableURI
 */
+ (instancetype)URIWithScheme: (OFString *)scheme;

/**
 * @brief Initializes an already allocated mutable URI with the specified
 *	  schemed.
 *
 * @param scheme The scheme for the URI
 * @return An initialized OFMutableURI
 */
- (instancetype)initWithScheme: (OFString *)scheme;

/**
 * @brief Appends the specified path component.
 *
 * @param component The component to append

|













|




|

|
|
>
>

|

|



|







|




|











|







|




|











|




|











|




|










|










|




|











|















|




|











|

|
|

|


|


|
|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
/*
 * Copyright (c) 2008-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 "OFIRI.h"

OF_ASSUME_NONNULL_BEGIN

/**
 * @class OFMutableIRI OFMutableIRI.h ObjFW/OFMutableIRI.h
 *
 * @brief A class for representing IRIs, URIs, URLs and URNs, for parsing them,
 *	  accessing parts of them as well as modifying them.
 *
 * This class follows RFC 3976 and RFC 3987.
 */
@interface OFMutableIRI: OFIRI
{
	OF_RESERVE_IVARS(OFMutableIRI, 4)
}

/**
 * @brief The scheme part of the IRI.
 *
 * @throw OFInvalidFormatException The scheme being set is not in the correct
 *				   format
 */
@property (readwrite, copy, nonatomic) OFString *scheme;

/**
 * @brief The host part of the IRI.
 */
@property OF_NULLABLE_PROPERTY (readwrite, copy, nonatomic) OFString *host;

/**
 * @brief The host part of the IRI in percent-encoded form.
 *
 * Setting this retains the original percent-encoding used - if more characters
 * than necessary are percent-encoded, it is kept this way.
 *
 * @throw OFInvalidFormatException The host being set is not in the correct
 *				   format
 */
@property OF_NULLABLE_PROPERTY (readwrite, copy, nonatomic)
    OFString *percentEncodedHost;

/**
 * @brief The port part of the IRI.
 *
 * @throw OFInvalidArgumentException The port is not valid (e.g. negative or
 *				     too big)
 */
@property OF_NULLABLE_PROPERTY (readwrite, copy, nonatomic) OFNumber *port;

/**
 * @brief The user part of the IRI.
 */
@property OF_NULLABLE_PROPERTY (readwrite, copy, nonatomic) OFString *user;

/**
 * @brief The user part of the IRI in percent-encoded form.
 *
 * Setting this retains the original percent-encoding used - if more characters
 * than necessary are percent-encoded, it is kept this way.
 *
 * @throw OFInvalidFormatException The user being set is not in the correct
 *				   format
 */
@property OF_NULLABLE_PROPERTY (readwrite, copy, nonatomic)
    OFString *percentEncodedUser;

/**
 * @brief The password part of the IRI.
 */
@property OF_NULLABLE_PROPERTY (readwrite, copy, nonatomic) OFString *password;

/**
 * @brief The password part of the IRI in percent-encoded form.
 *
 * Setting this retains the original percent-encoding used - if more characters
 * than necessary are percent-encoded, it is kept this way.
 *
 * @throw OFInvalidFormatException The password being set is not in the correct
 *				   format
 */
@property OF_NULLABLE_PROPERTY (readwrite, copy, nonatomic)
    OFString *percentEncodedPassword;

/**
 * @brief The path part of the IRI.
 */
@property (readwrite, copy, nonatomic) OFString *path;

/**
 * @brief The path part of the IRI in percent-encoded form.
 *
 * Setting this retains the original percent-encoding used - if more characters
 * than necessary are percent-encoded, it is kept this way.
 *
 * @throw OFInvalidFormatException The path being set is not in the correct
 *				   format
 */
@property (readwrite, copy, nonatomic) OFString *percentEncodedPath;

/**
 * @brief The path of the IRI split into components.
 *
 * The first component must always be empty to designate the root.
 *
 * @throw OFInvalidFormatException The path components being set are not in the
 *				   correct format
 */
@property (readwrite, copy, nonatomic)
    OFArray OF_GENERIC(OFString *) *pathComponents;

/**
 * @brief The query part of the IRI.
 */
@property OF_NULLABLE_PROPERTY (readwrite, copy, nonatomic) OFString *query;

/**
 * @brief The query part of the IRI in percent-encoded form.
 *
 * Setting this retains the original percent-encoding used - if more characters
 * than necessary are percent-encoded, it is kept this way.
 *
 * @throw OFInvalidFormatException The query being set is not in the correct
 *				   format
 */
@property OF_NULLABLE_PROPERTY (readwrite, copy, nonatomic)
    OFString *percentEncodedQuery;

/**
 * @brief The query part of the IRI as an array.
 *
 * For example, a query like `key1=value1&key2=value2` would correspond to the
 * following array:
 *
 *     @[
 *         [OFPair pairWithFirstObject: @"key1" secondObject: @"value1"],
 *         [OFPair pairWithFirstObject: @"key2" secondObject: @"value2"],
 *     ]
 *
 * @throw OFInvalidFormatException The query is not in the correct format
 */
@property OF_NULLABLE_PROPERTY (readwrite, copy, nonatomic)
    OFArray OF_GENERIC(OFPair OF_GENERIC(OFString *, OFString *) *) *queryItems;

/**
 * @brief The fragment part of the IRI.
 */
@property OF_NULLABLE_PROPERTY (readwrite, copy, nonatomic) OFString *fragment;

/**
 * @brief The fragment part of the IRI in percent-encoded form.
 *
 * Setting this retains the original percent-encoding used - if more characters
 * than necessary are percent-encoded, it is kept this way.
 *
 * @throw OFInvalidFormatException The fragment being set is not in the correct
 *				   format
 */
@property OF_NULLABLE_PROPERTY (readwrite, copy, nonatomic)
    OFString *percentEncodedFragment;

/**
 * @brief Creates a new mutable IRI with the specified schemed.
 *
 * @param scheme The scheme for the IRI
 * @return A new, autoreleased OFMutableIRI
 */
+ (instancetype)IRIWithScheme: (OFString *)scheme;

/**
 * @brief Initializes an already allocated mutable IRI with the specified
 *	  schemed.
 *
 * @param scheme The scheme for the IRI
 * @return An initialized OFMutableIRI
 */
- (instancetype)initWithScheme: (OFString *)scheme;

/**
 * @brief Appends the specified path component.
 *
 * @param component The component to append
208
209
210
211
212
213
214
215
216
217
218
219
220

/**
 * @brief Resolves relative subpaths.
 */
- (void)standardizePath;

/**
 * @brief Converts the mutable URI to an immutable URI.
 */
- (void)makeImmutable;
@end

OF_ASSUME_NONNULL_END







|





210
211
212
213
214
215
216
217
218
219
220
221
222

/**
 * @brief Resolves relative subpaths.
 */
- (void)standardizePath;

/**
 * @brief Converts the mutable IRI to an immutable IRI.
 */
- (void)makeImmutable;
@end

OF_ASSUME_NONNULL_END

Renamed and modified src/OFMutableURI.m [375c07c449] to src/OFMutableIRI.m [df72f9042f].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#import "OFMutableURI.h"
#import "OFURI+Private.h"
#import "OFArray.h"
#import "OFDictionary.h"
#ifdef OF_HAVE_FILES
# import "OFFileManager.h"
#endif
#import "OFNumber.h"
#import "OFPair.h"
#import "OFString.h"

#import "OFInvalidArgumentException.h"
#import "OFInvalidFormatException.h"

@implementation OFMutableURI
@dynamic scheme, host, percentEncodedHost, port, user, percentEncodedUser;
@dynamic password, percentEncodedPassword, path, percentEncodedPath;
@dynamic pathComponents, query, percentEncodedQuery, queryItems, fragment;
@dynamic percentEncodedFragment;

+ (instancetype)URIWithScheme: (OFString *)scheme
{
	return [[[self alloc] initWithScheme: scheme] autorelease];
}

- (instancetype)initWithScheme: (OFString *)scheme
{
	self = [super of_init];

|















|
|












|





|







1
2
3
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 "OFMutableIRI.h"
#import "OFIRI+Private.h"
#import "OFArray.h"
#import "OFDictionary.h"
#ifdef OF_HAVE_FILES
# import "OFFileManager.h"
#endif
#import "OFNumber.h"
#import "OFPair.h"
#import "OFString.h"

#import "OFInvalidArgumentException.h"
#import "OFInvalidFormatException.h"

@implementation OFMutableIRI
@dynamic scheme, host, percentEncodedHost, port, user, percentEncodedUser;
@dynamic password, percentEncodedPassword, path, percentEncodedPath;
@dynamic pathComponents, query, percentEncodedQuery, queryItems, fragment;
@dynamic percentEncodedFragment;

+ (instancetype)IRIWithScheme: (OFString *)scheme
{
	return [[[self alloc] initWithScheme: scheme] autorelease];
}

- (instancetype)initWithScheme: (OFString *)scheme
{
	self = [super of_init];
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
{
	void *pool = objc_autoreleasePoolPush();
	OFString *old = _scheme;

	if (scheme.length < 1 || !OFASCIIIsAlpha(*scheme.UTF8String))
		@throw [OFInvalidFormatException exception];

	OFURIVerifyIsEscaped(scheme,
	    [OFCharacterSet URISchemeAllowedCharacterSet], false);

	_scheme = [scheme.lowercaseString copy];

	[old release];

	objc_autoreleasePoolPop(pool);
}

- (void)setHost: (OFString *)host
{
	void *pool = objc_autoreleasePoolPush();
	OFString *old = _percentEncodedHost;

	if (OFURIIsIPv6Host(host))
		_percentEncodedHost = [[OFString alloc]
		    initWithFormat: @"[%@]", host];
	else
		_percentEncodedHost = [[host
		    stringByAddingPercentEncodingWithAllowedCharacters:
		    [OFCharacterSet URIHostAllowedCharacterSet]] copy];

	[old release];

	objc_autoreleasePoolPop(pool);
}

- (void)setPercentEncodedHost: (OFString *)percentEncodedHost
{
	OFString *old;

	if ([percentEncodedHost hasPrefix: @"["] &&
	    [percentEncodedHost hasSuffix: @"]"]) {
		if (!OFURIIsIPv6Host([percentEncodedHost substringWithRange:
		    OFMakeRange(1, percentEncodedHost.length - 2)]))
			@throw [OFInvalidFormatException exception];
	} else if (percentEncodedHost != nil)
		OFURIVerifyIsEscaped(percentEncodedHost,
		    [OFCharacterSet URIHostAllowedCharacterSet], true);

	old = _percentEncodedHost;
	_percentEncodedHost = [percentEncodedHost copy];
	[old release];
}

- (void)setPort: (OFNumber *)port







|
|













|





|












|



|
|







59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
{
	void *pool = objc_autoreleasePoolPush();
	OFString *old = _scheme;

	if (scheme.length < 1 || !OFASCIIIsAlpha(*scheme.UTF8String))
		@throw [OFInvalidFormatException exception];

	OFIRIVerifyIsEscaped(scheme,
	    [OFCharacterSet IRISchemeAllowedCharacterSet], false);

	_scheme = [scheme.lowercaseString copy];

	[old release];

	objc_autoreleasePoolPop(pool);
}

- (void)setHost: (OFString *)host
{
	void *pool = objc_autoreleasePoolPush();
	OFString *old = _percentEncodedHost;

	if (OFIRIIsIPv6Host(host))
		_percentEncodedHost = [[OFString alloc]
		    initWithFormat: @"[%@]", host];
	else
		_percentEncodedHost = [[host
		    stringByAddingPercentEncodingWithAllowedCharacters:
		    [OFCharacterSet IRIHostAllowedCharacterSet]] copy];

	[old release];

	objc_autoreleasePoolPop(pool);
}

- (void)setPercentEncodedHost: (OFString *)percentEncodedHost
{
	OFString *old;

	if ([percentEncodedHost hasPrefix: @"["] &&
	    [percentEncodedHost hasSuffix: @"]"]) {
		if (!OFIRIIsIPv6Host([percentEncodedHost substringWithRange:
		    OFMakeRange(1, percentEncodedHost.length - 2)]))
			@throw [OFInvalidFormatException exception];
	} else if (percentEncodedHost != nil)
		OFIRIVerifyIsEscaped(percentEncodedHost,
		    [OFCharacterSet IRIHostAllowedCharacterSet], true);

	old = _percentEncodedHost;
	_percentEncodedHost = [percentEncodedHost copy];
	[old release];
}

- (void)setPort: (OFNumber *)port
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
- (void)setUser: (OFString *)user
{
	void *pool = objc_autoreleasePoolPush();
	OFString *old = _percentEncodedUser;

	_percentEncodedUser = [[user
	    stringByAddingPercentEncodingWithAllowedCharacters:
	    [OFCharacterSet URIUserAllowedCharacterSet]] copy];

	[old release];

	objc_autoreleasePoolPop(pool);
}

- (void)setPercentEncodedUser: (OFString *)percentEncodedUser
{
	OFString *old;

	if (percentEncodedUser != nil)
		OFURIVerifyIsEscaped(percentEncodedUser,
		    [OFCharacterSet URIUserAllowedCharacterSet], true);

	old = _percentEncodedUser;
	_percentEncodedUser = [percentEncodedUser copy];
	[old release];
}

- (void)setPassword: (OFString *)password
{
	void *pool = objc_autoreleasePoolPush();
	OFString *old = _percentEncodedPassword;

	_percentEncodedPassword = [[password
	    stringByAddingPercentEncodingWithAllowedCharacters:
	    [OFCharacterSet URIPasswordAllowedCharacterSet]] copy];

	[old release];

	objc_autoreleasePoolPop(pool);
}

- (void)setPercentEncodedPassword: (OFString *)percentEncodedPassword
{
	OFString *old;

	if (percentEncodedPassword != nil)
		OFURIVerifyIsEscaped(percentEncodedPassword,
		    [OFCharacterSet URIPasswordAllowedCharacterSet], true);

	old = _percentEncodedPassword;
	_percentEncodedPassword = [percentEncodedPassword copy];
	[old release];
}

- (void)setPath: (OFString *)path
{
	void *pool = objc_autoreleasePoolPush();
	OFString *old = _percentEncodedPath;

	_percentEncodedPath = [[path
	    stringByAddingPercentEncodingWithAllowedCharacters:
	    [OFCharacterSet URIPathAllowedCharacterSet]] copy];

	[old release];

	objc_autoreleasePoolPop(pool);
}

- (void)setPercentEncodedPath: (OFString *)percentEncodedPath
{
	OFString *old;

	OFURIVerifyIsEscaped(percentEncodedPath,
	    [OFCharacterSet URIPathAllowedCharacterSet], true);

	old = _percentEncodedPath;
	_percentEncodedPath = [percentEncodedPath copy];
	[old release];
}

- (void)setPathComponents: (OFArray *)components







|











|
|













|











|
|













|










|
|







123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
- (void)setUser: (OFString *)user
{
	void *pool = objc_autoreleasePoolPush();
	OFString *old = _percentEncodedUser;

	_percentEncodedUser = [[user
	    stringByAddingPercentEncodingWithAllowedCharacters:
	    [OFCharacterSet IRIUserAllowedCharacterSet]] copy];

	[old release];

	objc_autoreleasePoolPop(pool);
}

- (void)setPercentEncodedUser: (OFString *)percentEncodedUser
{
	OFString *old;

	if (percentEncodedUser != nil)
		OFIRIVerifyIsEscaped(percentEncodedUser,
		    [OFCharacterSet IRIUserAllowedCharacterSet], true);

	old = _percentEncodedUser;
	_percentEncodedUser = [percentEncodedUser copy];
	[old release];
}

- (void)setPassword: (OFString *)password
{
	void *pool = objc_autoreleasePoolPush();
	OFString *old = _percentEncodedPassword;

	_percentEncodedPassword = [[password
	    stringByAddingPercentEncodingWithAllowedCharacters:
	    [OFCharacterSet IRIPasswordAllowedCharacterSet]] copy];

	[old release];

	objc_autoreleasePoolPop(pool);
}

- (void)setPercentEncodedPassword: (OFString *)percentEncodedPassword
{
	OFString *old;

	if (percentEncodedPassword != nil)
		OFIRIVerifyIsEscaped(percentEncodedPassword,
		    [OFCharacterSet IRIPasswordAllowedCharacterSet], true);

	old = _percentEncodedPassword;
	_percentEncodedPassword = [percentEncodedPassword copy];
	[old release];
}

- (void)setPath: (OFString *)path
{
	void *pool = objc_autoreleasePoolPush();
	OFString *old = _percentEncodedPath;

	_percentEncodedPath = [[path
	    stringByAddingPercentEncodingWithAllowedCharacters:
	    [OFCharacterSet IRIPathAllowedCharacterSet]] copy];

	[old release];

	objc_autoreleasePoolPop(pool);
}

- (void)setPercentEncodedPath: (OFString *)percentEncodedPath
{
	OFString *old;

	OFIRIVerifyIsEscaped(percentEncodedPath,
	    [OFCharacterSet IRIPathAllowedCharacterSet], true);

	old = _percentEncodedPath;
	_percentEncodedPath = [percentEncodedPath copy];
	[old release];
}

- (void)setPathComponents: (OFArray *)components
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
- (void)setQuery: (OFString *)query
{
	void *pool = objc_autoreleasePoolPush();
	OFString *old = _percentEncodedQuery;

	_percentEncodedQuery = [[query
	    stringByAddingPercentEncodingWithAllowedCharacters:
	    [OFCharacterSet URIQueryAllowedCharacterSet]] copy];

	[old release];

	objc_autoreleasePoolPop(pool);
}

- (void)setPercentEncodedQuery: (OFString *)percentEncodedQuery
{
	OFString *old;

	if (percentEncodedQuery != nil)
		OFURIVerifyIsEscaped(percentEncodedQuery,
		    [OFCharacterSet URIQueryAllowedCharacterSet], true);

	old = _percentEncodedQuery;
	_percentEncodedQuery = [percentEncodedQuery copy];
	[old release];
}

- (void)setQueryItems:







|











|
|







222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
- (void)setQuery: (OFString *)query
{
	void *pool = objc_autoreleasePoolPush();
	OFString *old = _percentEncodedQuery;

	_percentEncodedQuery = [[query
	    stringByAddingPercentEncodingWithAllowedCharacters:
	    [OFCharacterSet IRIQueryAllowedCharacterSet]] copy];

	[old release];

	objc_autoreleasePoolPop(pool);
}

- (void)setPercentEncodedQuery: (OFString *)percentEncodedQuery
{
	OFString *old;

	if (percentEncodedQuery != nil)
		OFIRIVerifyIsEscaped(percentEncodedQuery,
		    [OFCharacterSet IRIQueryAllowedCharacterSet], true);

	old = _percentEncodedQuery;
	_percentEncodedQuery = [percentEncodedQuery copy];
	[old release];
}

- (void)setQueryItems:
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
		[_percentEncodedQuery release];
		_percentEncodedQuery = nil;
		return;
	}

	pool = objc_autoreleasePoolPush();
	percentEncodedQuery = [OFMutableString string];
	characterSet = [OFCharacterSet URIQueryKeyValueAllowedCharacterSet];

	for (OFPair OF_GENERIC(OFString *, OFString *) *item in queryItems) {
		OFString *key = [item.firstObject
		    stringByAddingPercentEncodingWithAllowedCharacters:
		    characterSet];
		OFString *value = [item.secondObject
		    stringByAddingPercentEncodingWithAllowedCharacters:







|







259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
		[_percentEncodedQuery release];
		_percentEncodedQuery = nil;
		return;
	}

	pool = objc_autoreleasePoolPush();
	percentEncodedQuery = [OFMutableString string];
	characterSet = [OFCharacterSet IRIQueryKeyValueAllowedCharacterSet];

	for (OFPair OF_GENERIC(OFString *, OFString *) *item in queryItems) {
		OFString *key = [item.firstObject
		    stringByAddingPercentEncodingWithAllowedCharacters:
		    characterSet];
		OFString *value = [item.secondObject
		    stringByAddingPercentEncodingWithAllowedCharacters:
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
- (void)setFragment: (OFString *)fragment
{
	void *pool = objc_autoreleasePoolPush();
	OFString *old = _percentEncodedFragment;

	_percentEncodedFragment = [[fragment
	    stringByAddingPercentEncodingWithAllowedCharacters:
	    [OFCharacterSet URIFragmentAllowedCharacterSet]] copy];

	[old release];

	objc_autoreleasePoolPop(pool);
}

- (void)setPercentEncodedFragment: (OFString *)percentEncodedFragment
{
	OFString *old;

	if (percentEncodedFragment != nil)
		OFURIVerifyIsEscaped(percentEncodedFragment,
		    [OFCharacterSet URIFragmentAllowedCharacterSet], true);

	old = _percentEncodedFragment;
	_percentEncodedFragment = [percentEncodedFragment copy];
	[old release];
}

- (id)copy
{
	OFMutableURI *copy = [self mutableCopy];

	[copy makeImmutable];

	return copy;
}

- (void)appendPathComponent: (OFString *)component
{
	[self appendPathComponent: component isDirectory: false];

#ifdef OF_HAVE_FILES
	if ([_scheme isEqual: @"file"] &&
	    ![_percentEncodedPath hasSuffix: @"/"] &&
	    [[OFFileManager defaultManager] directoryExistsAtURI: self]) {
		void *pool = objc_autoreleasePoolPush();
		OFString *path = [_percentEncodedPath
		    stringByAppendingString: @"/"];

		[_percentEncodedPath release];
		_percentEncodedPath = [path retain];








|











|
|








|













|







289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
- (void)setFragment: (OFString *)fragment
{
	void *pool = objc_autoreleasePoolPush();
	OFString *old = _percentEncodedFragment;

	_percentEncodedFragment = [[fragment
	    stringByAddingPercentEncodingWithAllowedCharacters:
	    [OFCharacterSet IRIFragmentAllowedCharacterSet]] copy];

	[old release];

	objc_autoreleasePoolPop(pool);
}

- (void)setPercentEncodedFragment: (OFString *)percentEncodedFragment
{
	OFString *old;

	if (percentEncodedFragment != nil)
		OFIRIVerifyIsEscaped(percentEncodedFragment,
		    [OFCharacterSet IRIFragmentAllowedCharacterSet], true);

	old = _percentEncodedFragment;
	_percentEncodedFragment = [percentEncodedFragment copy];
	[old release];
}

- (id)copy
{
	OFMutableIRI *copy = [self mutableCopy];

	[copy makeImmutable];

	return copy;
}

- (void)appendPathComponent: (OFString *)component
{
	[self appendPathComponent: component isDirectory: false];

#ifdef OF_HAVE_FILES
	if ([_scheme isEqual: @"file"] &&
	    ![_percentEncodedPath hasSuffix: @"/"] &&
	    [[OFFileManager defaultManager] directoryExistsAtIRI: self]) {
		void *pool = objc_autoreleasePoolPush();
		OFString *path = [_percentEncodedPath
		    stringByAppendingString: @"/"];

		[_percentEncodedPath release];
		_percentEncodedPath = [path retain];

350
351
352
353
354
355
356
357
358
359
360
361
362
363
364

	if ([component isEqual: @"/"] && [_percentEncodedPath hasSuffix: @"/"])
		return;

	pool = objc_autoreleasePoolPush();
	component = [component
	    stringByAddingPercentEncodingWithAllowedCharacters:
	    [OFCharacterSet URIPathAllowedCharacterSet]];

#if defined(OF_WINDOWS) || defined(OF_MSDOS)
	if ([_percentEncodedPath hasSuffix: @"/"] ||
	    ([_scheme isEqual: @"file"] &&
	    [_percentEncodedPath hasSuffix: @":"]))
#else
	if ([_percentEncodedPath hasSuffix: @"/"])







|







350
351
352
353
354
355
356
357
358
359
360
361
362
363
364

	if ([component isEqual: @"/"] && [_percentEncodedPath hasSuffix: @"/"])
		return;

	pool = objc_autoreleasePoolPush();
	component = [component
	    stringByAddingPercentEncodingWithAllowedCharacters:
	    [OFCharacterSet IRIPathAllowedCharacterSet]];

#if defined(OF_WINDOWS) || defined(OF_MSDOS)
	if ([_percentEncodedPath hasSuffix: @"/"] ||
	    ([_scheme isEqual: @"file"] &&
	    [_percentEncodedPath hasSuffix: @":"]))
#else
	if ([_percentEncodedPath hasSuffix: @"/"])
430
431
432
433
434
435
436
437
438
439
	self.percentEncodedPath = path;

	objc_autoreleasePoolPop(pool);
}

- (void)makeImmutable
{
	object_setClass(self, [OFURI class]);
}
@end







|


430
431
432
433
434
435
436
437
438
439
	self.percentEncodedPath = path;

	objc_autoreleasePoolPop(pool);
}

- (void)makeImmutable
{
	object_setClass(self, [OFIRI class]);
}
@end

Modified src/OFMutableLHAArchiveEntry.h from [5bfb2f1e47] to [e75545549c].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFMutableLHAArchiveEntry.m from [84adbb8df8] to [7c8fd92ff1].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFMutablePair.h from [fd02ba0f90] to [aaa198970d].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFMutablePair.m from [6901454ea9] to [3add5572dd].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFMutableSet.h from [c05177c6a6] to [f8ea63052f].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
34
35
36
37
38
39
40







41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
 *	  number of objects.
 *
 * @param capacity The initial capacity for the OFMutableSet
 * @return A new autoreleased OFMutableSet
 */
+ (instancetype)setWithCapacity: (size_t)capacity;








/**
 * @brief Initializes an already allocated OFMutableSet with enough memory to
 *	  hold the specified number of objects.
 *
 * @param capacity The initial capacity for the OFMutableSet
 * @return An initialized OFMutableSet
 */
- (instancetype)initWithCapacity: (size_t)capacity;

/**
 * @brief Adds the specified object to the set.
 *
 * @param object The object to add to the set
 */
- (void)addObject: (ObjectType)object;







>
>
>
>
>
>
>







|







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
 *	  number of objects.
 *
 * @param capacity The initial capacity for the OFMutableSet
 * @return A new autoreleased OFMutableSet
 */
+ (instancetype)setWithCapacity: (size_t)capacity;

/**
 * @brief Initializes an already allocated OFMutableSet to be empty.
 *
 * @return An initialized OFMutableSet
 */
- (instancetype)init OF_DESIGNATED_INITIALIZER;

/**
 * @brief Initializes an already allocated OFMutableSet with enough memory to
 *	  hold the specified number of objects.
 *
 * @param capacity The initial capacity for the OFMutableSet
 * @return An initialized OFMutableSet
 */
- (instancetype)initWithCapacity: (size_t)capacity OF_DESIGNATED_INITIALIZER;

/**
 * @brief Adds the specified object to the set.
 *
 * @param object The object to add to the set
 */
- (void)addObject: (ObjectType)object;

Modified src/OFMutableSet.m from [b126234b89] to [9ec1cd87e9].

1
2
3
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
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#include <stdlib.h>

#include <assert.h>

#import "OFMutableSet.h"

#import "OFMutableMapTableSet.h"

static struct {
	Class isa;
} placeholder;

@interface OFMutableSetPlaceholder: OFMutableSet
@end

@implementation OFMutableSetPlaceholder






- (instancetype)init
{
	return (id)[[OFMutableMapTableSet alloc] init];
}

- (instancetype)initWithSet: (OFSet *)set
{
	return (id)[[OFMutableMapTableSet alloc] initWithSet: set];
}

- (instancetype)initWithArray: (OFArray *)array
{
	return (id)[[OFMutableMapTableSet alloc] initWithArray: array];
}

- (instancetype)initWithObjects: (id)firstObject, ...
{
	id ret;
	va_list arguments;

	va_start(arguments, firstObject);
	ret = [[OFMutableMapTableSet alloc] initWithObject: firstObject
						 arguments: arguments];
	va_end(arguments);

	return ret;
}

- (instancetype)initWithObjects: (id const *)objects count: (size_t)count
{
	return (id)[[OFMutableMapTableSet alloc] initWithObjects: objects
							   count: count];
}

- (instancetype)initWithObject: (id)firstObject arguments: (va_list)arguments
{
	return (id)[[OFMutableMapTableSet alloc] initWithObject: firstObject
						      arguments: arguments];
}

- (instancetype)initWithSerialization: (OFXMLElement *)element
{
	return (id)[[OFMutableMapTableSet alloc]
	    initWithSerialization: element];
}

- (instancetype)initWithCapacity: (size_t)capacity
{
	return (id)[[OFMutableMapTableSet alloc] initWithCapacity: capacity];
}

- (instancetype)retain
{
	return self;
}

- (instancetype)autorelease
{
	return self;
}

- (void)release
{
}

- (void)dealloc
{
	OF_DEALLOC_UNSUPPORTED
}
@end

@implementation OFMutableSet
+ (void)initialize
{
	if (self == [OFMutableSet class])
		placeholder.isa = [OFMutableSetPlaceholder class];

}

+ (instancetype)alloc
{
	if (self == [OFMutableSet class])
		return (id)&placeholder;

	return [super alloc];
}

+ (instancetype)setWithCapacity: (size_t)capacity
{
	return [[[self alloc] initWithCapacity: capacity] autorelease];
}

- (instancetype)init
{
	if ([self isMemberOfClass: [OFMutableSet class]]) {
		@try {
			[self doesNotRecognizeSelector: _cmd];
			abort();
		} @catch (id e) {
			[self release];
			@throw e;
		}
	}








	return [super init];

}

- (instancetype)initWithCapacity: (size_t)capacity
{
	OF_INVALID_INIT_METHOD
}




- (id)copy
{
	return [[OFSet alloc] initWithSet: self];
}

- (void)addObject: (id)object

|

















<
<

>
|





|


|
>
>
>
>
>
>


|




|




|








|








|





|



<
<
<
<
<
<


|

|
<
<
<
<
|
<
<
<
<
|
<
|
<
|
<
<
<
<






|
>

















<
<
<
<
<
|
<
|
|
>
>
>
>
>
>
>
|
<
>






>
>
>







1
2
3
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
/*
 * 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 <stdlib.h>



#import "OFMutableSet.h"
#import "OFConcreteMutableSet.h"
#import "OFString.h"

static struct {
	Class isa;
} placeholder;

@interface OFPlaceholderMutableSet: OFMutableSet
@end

@implementation OFPlaceholderMutableSet
#ifdef __clang__
/* We intentionally don't call into super, so silence the warning. */
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wunknown-pragmas"
# pragma clang diagnostic ignored "-Wobjc-designated-initializers"
#endif
- (instancetype)init
{
	return (id)[[OFConcreteMutableSet alloc] init];
}

- (instancetype)initWithSet: (OFSet *)set
{
	return (id)[[OFConcreteMutableSet alloc] initWithSet: set];
}

- (instancetype)initWithArray: (OFArray *)array
{
	return (id)[[OFConcreteMutableSet alloc] initWithArray: array];
}

- (instancetype)initWithObjects: (id)firstObject, ...
{
	id ret;
	va_list arguments;

	va_start(arguments, firstObject);
	ret = [[OFConcreteMutableSet alloc] initWithObject: firstObject
						 arguments: arguments];
	va_end(arguments);

	return ret;
}

- (instancetype)initWithObjects: (id const *)objects count: (size_t)count
{
	return (id)[[OFConcreteMutableSet alloc] initWithObjects: objects
							   count: count];
}

- (instancetype)initWithObject: (id)firstObject arguments: (va_list)arguments
{
	return (id)[[OFConcreteMutableSet alloc] initWithObject: firstObject
						      arguments: arguments];
}







- (instancetype)initWithCapacity: (size_t)capacity
{
	return (id)[[OFConcreteMutableSet alloc] initWithCapacity: capacity];
}
#ifdef __clang__




# pragma clang diagnostic pop




#endif



OF_SINGLETON_METHODS




@end

@implementation OFMutableSet
+ (void)initialize
{
	if (self == [OFMutableSet class])
		object_setClass((id)&placeholder,
		    [OFPlaceholderMutableSet class]);
}

+ (instancetype)alloc
{
	if (self == [OFMutableSet class])
		return (id)&placeholder;

	return [super alloc];
}

+ (instancetype)setWithCapacity: (size_t)capacity
{
	return [[[self alloc] initWithCapacity: capacity] autorelease];
}

- (instancetype)init
{





	return [super init];

}

#ifdef __clang__
/* We intentionally don't call into super, so silence the warning. */
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wunknown-pragmas"
# pragma clang diagnostic ignored "-Wobjc-designated-initializers"
#endif
- (instancetype)initWithObjects: (id const *)objects count: (size_t)count
{

	OF_INVALID_INIT_METHOD
}

- (instancetype)initWithCapacity: (size_t)capacity
{
	OF_INVALID_INIT_METHOD
}
#ifdef __clang__
# pragma clang diagnostic pop
#endif

- (id)copy
{
	return [[OFSet alloc] initWithSet: self];
}

- (void)addObject: (id)object
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184

	cArray = OFAllocMemory(count, sizeof(id));
	@try {
		size_t i;

		i = 0;
		for (id object in self) {
			assert(i < count);
			cArray[i++] = object;
		}

		for (i = 0; i < count; i++)
			if (![set containsObject: cArray[i]])
				[self removeObject: cArray[i]];
	} @finally {







|







160
161
162
163
164
165
166
167
168
169
170
171
172
173
174

	cArray = OFAllocMemory(count, sizeof(id));
	@try {
		size_t i;

		i = 0;
		for (id object in self) {
			OFAssert(i < count);
			cArray[i++] = object;
		}

		for (i = 0; i < count; i++)
			if (![set containsObject: cArray[i]])
				[self removeObject: cArray[i]];
	} @finally {

Modified src/OFMutableString.h from [f372a7a142] to [b3cde87d6a].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the 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.
 */

#ifndef OBJFW_OF_MUTABLE_STRING_H
#define OBJFW_OF_MUTABLE_STRING_H

#include "OFString.h"

OF_ASSUME_NONNULL_BEGIN

#ifdef __OBJC__
/**
 * @class OFMutableString OFString.h ObjFW/OFString.h
 *
 * @brief A class for storing and modifying strings.
 */
@interface OFMutableString: OFString
/**

|













<
<
<
|



<







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15



16
17
18
19

20
21
22
23
24
25
26
/*
 * 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 "OFString.h"

OF_ASSUME_NONNULL_BEGIN


/**
 * @class OFMutableString OFString.h ObjFW/OFString.h
 *
 * @brief A class for storing and modifying strings.
 */
@interface OFMutableString: OFString
/**
206
207
208
209
210
211
212
213
214
215
216
217
- (void)deleteEnclosingWhitespaces;

/**
 * @brief Converts the mutable string to an immutable string.
 */
- (void)makeImmutable;
@end
#endif

OF_ASSUME_NONNULL_END

#endif







<


<
<
202
203
204
205
206
207
208

209
210


- (void)deleteEnclosingWhitespaces;

/**
 * @brief Converts the mutable string to an immutable string.
 */
- (void)makeImmutable;
@end


OF_ASSUME_NONNULL_END


Modified src/OFMutableString.m from [eb3bef8a08] to [62c36464cb].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
29
30
31
32
33
34
35
36
37
38
39






40
41
42
43
44
45
46

#import "unicode.h"

static struct {
	Class isa;
} placeholder;

@interface OFMutableStringPlaceholder: OFMutableString
@end

@implementation OFMutableStringPlaceholder






- (instancetype)init
{
	return (id)[[OFMutableUTF8String alloc] init];
}

- (instancetype)initWithUTF8String: (const char *)UTF8String
{







|


|
>
>
>
>
>
>







29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52

#import "unicode.h"

static struct {
	Class isa;
} placeholder;

@interface OFPlaceholderMutableString: OFMutableString
@end

@implementation OFPlaceholderMutableString
#ifdef __clang__
/* We intentionally don't call into super, so silence the warning. */
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wunknown-pragmas"
# pragma clang diagnostic ignored "-Wobjc-designated-initializers"
#endif
- (instancetype)init
{
	return (id)[[OFMutableUTF8String alloc] init];
}

- (instancetype)initWithUTF8String: (const char *)UTF8String
{
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
{
	return (id)[[OFMutableUTF8String alloc]
	    initWithContentsOfFile: path
			  encoding: encoding];
}
#endif

- (instancetype)initWithContentsOfURI: (OFURI *)URI
{
	return (id)[[OFMutableUTF8String alloc] initWithContentsOfURI: URI];
}

- (instancetype)initWithContentsOfURI: (OFURI *)URI
			     encoding: (OFStringEncoding)encoding
{
	return (id)[[OFMutableUTF8String alloc]
	    initWithContentsOfURI: URI
			 encoding: encoding];
}

- (instancetype)initWithSerialization: (OFXMLElement *)element
{
	return (id)[[OFMutableUTF8String alloc] initWithSerialization: element];
}

- (instancetype)retain
{
	return self;
}

- (instancetype)autorelease
{
	return self;
}

- (void)release
{
}

- (void)dealloc
{
	OF_DEALLOC_UNSUPPORTED
}
@end

@implementation OFMutableString
+ (void)initialize
{
	if (self == [OFMutableString class])

		placeholder.isa = [OFMutableStringPlaceholder class];
}

+ (instancetype)alloc
{
	if (self == [OFMutableString class])
		return (id)&placeholder;








|

|


|



|


|
<
<
<
<
|
<
<
<
<
|
<
|
<
<
|
<
<
<
<
<
<
<
<






>
|







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
{
	return (id)[[OFMutableUTF8String alloc]
	    initWithContentsOfFile: path
			  encoding: encoding];
}
#endif

- (instancetype)initWithContentsOfIRI: (OFIRI *)IRI
{
	return (id)[[OFMutableUTF8String alloc] initWithContentsOfIRI: IRI];
}

- (instancetype)initWithContentsOfIRI: (OFIRI *)IRI
			     encoding: (OFStringEncoding)encoding
{
	return (id)[[OFMutableUTF8String alloc]
	    initWithContentsOfIRI: IRI
			 encoding: encoding];
}
#ifdef __clang__




# pragma clang diagnostic pop




#endif




OF_SINGLETON_METHODS








@end

@implementation OFMutableString
+ (void)initialize
{
	if (self == [OFMutableString class])
		object_setClass((id)&placeholder,
		    [OFPlaceholderMutableString class]);
}

+ (instancetype)alloc
{
	if (self == [OFMutableString class])
		return (id)&placeholder;

Modified src/OFMutableTarArchiveEntry.h from [d5cbafa370] to [ccb599d957].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFMutableTarArchiveEntry.m from [693af0fda5] to [6c3a57c753].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFMutableTriple.h from [9e67514e20] to [525a6f0eb6].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFMutableTriple.m from [a54e7551cb] to [12a0fcca1c].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFMutableUTF8String.h from [681d1d0ba4] to [207e90fa06].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFMutableUTF8String.m from [57e4df0b5d] to [42226ecdbb].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the 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 <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>

#import "OFMutableUTF8String.h"
#import "OFASPrintF.h"
#import "OFString.h"
#import "OFUTF8String.h"

#import "OFInvalidArgumentException.h"

|


















<







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

21
22
23
24
25
26
27
/*
 * Copyright (c) 2008-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 <stdarg.h>
#include <stdlib.h>
#include <string.h>


#import "OFMutableUTF8String.h"
#import "OFASPrintF.h"
#import "OFString.h"
#import "OFUTF8String.h"

#import "OFInvalidArgumentException.h"
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
	char *newCString;
	bool isStart = true;

	if (!_s->isUTF8) {
		uint8_t t;
		const OFUnichar *const *table;

		assert(startTableSize >= 1 && middleTableSize >= 1);

		_s->hasHash = false;

		for (i = 0; i < _s->cStringLength; i++) {
			if (isStart)
				table = startTable;
			else







|







74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
	char *newCString;
	bool isStart = true;

	if (!_s->isUTF8) {
		uint8_t t;
		const OFUnichar *const *table;

		OFAssert(startTableSize >= 1 && middleTableSize >= 1);

		_s->hasHash = false;

		for (i = 0; i < _s->cStringLength; i++) {
			if (isStart)
				table = startTable;
			else
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
			OFFreeMemory(unicodeString);
			OFFreeMemory(newCString);
			@throw [OFInvalidEncodingException exception];
		}
		j += d;
	}

	assert(j == newCStringLength);
	newCString[j] = 0;
	OFFreeMemory(unicodeString);

	OFFreeMemory(_s->cString);
	_s->hasHash = false;
	_s->cString = newCString;
	_s->cStringLength = newCStringLength;







|







168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
			OFFreeMemory(unicodeString);
			OFFreeMemory(newCString);
			@throw [OFInvalidEncodingException exception];
		}
		j += d;
	}

	OFAssert(j == newCStringLength);
	newCString[j] = 0;
	OFFreeMemory(unicodeString);

	OFFreeMemory(_s->cString);
	_s->hasHash = false;
	_s->cString = newCString;
	_s->cStringLength = newCStringLength;

Modified src/OFMutableZIPArchiveEntry.h from [019337b54d] to [2122d6601a].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFMutableZIPArchiveEntry.m from [6a8c882277] to [f4a3f02da1].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFMutex.h from [60974c2165] to [fe684ec359].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFMutex.m from [91291c7344] to [64408a13e1].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Deleted src/OFNonretainedObjectValue.h version [3bd7c9c6b7].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the 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 "OFValue.h"

OF_ASSUME_NONNULL_BEGIN

@interface OFNonretainedObjectValue: OFValue
{
	id _object;
}

- (instancetype)initWithNonretainedObject: (id)object;
@end

OF_ASSUME_NONNULL_END
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
























































Deleted src/OFNonretainedObjectValue.m version [93108c2968].

1
2
3
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
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#import "OFNonretainedObjectValue.h"
#import "OFMethodSignature.h"

#import "OFOutOfRangeException.h"

@implementation OFNonretainedObjectValue
@synthesize nonretainedObjectValue = _object;

- (instancetype)initWithNonretainedObject: (id)object
{
	self = [super init];

	_object = object;

	return self;
}

- (const char *)objCType
{
	return @encode(id);
}

- (void)getValue: (void *)value size: (size_t)size
{
	if (size != sizeof(_object))
		@throw [OFOutOfRangeException exception];

	memcpy(value, &_object, sizeof(_object));
}

- (void *)pointerValue
{
	return _object;
}
@end
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<




































































































Modified src/OFNotification.h from [c3409634e1] to [375cdee9eb].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFNotification.m from [d51e2a4110] to [b8f33198aa].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFNotificationCenter.h from [2edf55e2db] to [48ab5bf0c4].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

OF_ASSUME_NONNULL_BEGIN

@class OFMutableDictionary OF_GENERIC(KeyType, ObjectType);
#ifdef OF_HAVE_THREADS
@class OFMutex;
#endif
@class OFNotificationCenterHandle;

#ifdef OF_HAVE_BLOCKS
/**
 * @brief A block which is called when a notification has been posted.
 *
 * @param notification The notification that has been posted
 */







<







18
19
20
21
22
23
24

25
26
27
28
29
30
31

OF_ASSUME_NONNULL_BEGIN

@class OFMutableDictionary OF_GENERIC(KeyType, ObjectType);
#ifdef OF_HAVE_THREADS
@class OFMutex;
#endif


#ifdef OF_HAVE_BLOCKS
/**
 * @brief A block which is called when a notification has been posted.
 *
 * @param notification The notification that has been posted
 */
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
+ (OFNotificationCenter *)defaultCenter;

/**
 * @brief Adds an observer for the specified notification and object.
 *
 * @param observer The object that should receive notifications
 * @param selector The selector to call on the observer on notifications. The
 *		   method must take exactly one object of type @ref
 *		   OFNotification.
 * @param name The name of the notification to observe
 * @param object The object that should be sending the notification, or `nil`
 *		 if the object should be ignored to determine what
 *		 notifications to deliver
 */
- (void)addObserver: (id)observer
	   selector: (SEL)selector







|
|







59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
+ (OFNotificationCenter *)defaultCenter;

/**
 * @brief Adds an observer for the specified notification and object.
 *
 * @param observer The object that should receive notifications
 * @param selector The selector to call on the observer on notifications. The
 *		   method must take exactly one object of type
 *		   @ref OFNotification.
 * @param name The name of the notification to observe
 * @param object The object that should be sending the notification, or `nil`
 *		 if the object should be ignored to determine what
 *		 notifications to deliver
 */
- (void)addObserver: (id)observer
	   selector: (SEL)selector
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
 * @param name The name of the notification to observe
 * @param object The object that should be sending the notification, or `nil`
 *		 if the object should be ignored to determine what
 *		 notifications to deliver
 * @param block The block to handle notifications
 * @return An opaque object to remove the observer again
 */
- (OFNotificationCenterHandle *)
    addObserverForName: (OFNotificationName)name
		object: (nullable id)object
	    usingBlock: (OFNotificationCenterBlock)block;

/**
 * @brief Removes an observer. The specified observer must be one returned by
 *	  @ref addObserver:selector:name:object:.
 *
 * @param observer The object that was returned when adding the observer
 */
- (void)removeObserver: (OFNotificationCenterHandle *)observer;
#endif

/**
 * @brief Posts the specified notification.
 *
 * @param notification The notification to post
 */







<
|
|
|







|







98
99
100
101
102
103
104

105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
 * @param name The name of the notification to observe
 * @param object The object that should be sending the notification, or `nil`
 *		 if the object should be ignored to determine what
 *		 notifications to deliver
 * @param block The block to handle notifications
 * @return An opaque object to remove the observer again
 */

- (id)addObserverForName: (OFNotificationName)name
		  object: (nullable id)object
	      usingBlock: (OFNotificationCenterBlock)block;

/**
 * @brief Removes an observer. The specified observer must be one returned by
 *	  @ref addObserver:selector:name:object:.
 *
 * @param observer The object that was returned when adding the observer
 */
- (void)removeObserver: (id)observer;
#endif

/**
 * @brief Posts the specified notification.
 *
 * @param notification The notification to post
 */

Modified src/OFNotificationCenter.m from [a7b0a81fd8] to [0b7b8e3a02].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
{
	self = [super init];

	@try {
		void *pool = objc_autoreleasePoolPush();

		_name = [name copy];
		_observer = [observer retain];
		_selector = selector;
		_object = [object retain];

		_selectorHash = [[OFString stringWithUTF8String:
		    sel_getName(_selector)] hash];

		objc_autoreleasePoolPop(pool);







|







65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
{
	self = [super init];

	@try {
		void *pool = objc_autoreleasePoolPush();

		_name = [name copy];
		_observer = observer;
		_selector = selector;
		_object = [object retain];

		_selectorHash = [[OFString stringWithUTF8String:
		    sel_getName(_selector)] hash];

		objc_autoreleasePoolPop(pool);
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
	return self;
}
#endif

- (void)dealloc
{
	[_name release];
	[_observer release];
	[_object release];
#ifdef OF_HAVE_BLOCKS
	[_block release];
#endif

	[super dealloc];
}







<







104
105
106
107
108
109
110

111
112
113
114
115
116
117
	return self;
}
#endif

- (void)dealloc
{
	[_name release];

	[_object release];
#ifdef OF_HAVE_BLOCKS
	[_block release];
#endif

	[super dealloc];
}
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273







274
275
276
277
278
279
280
281
						       object: object]
	    autorelease]];

	objc_autoreleasePoolPop(pool);
}

#ifdef OF_HAVE_BLOCKS
- (OFNotificationCenterHandle *)
    addObserverForName: (OFNotificationName)name
		object: (id)object
	    usingBlock: (OFNotificationCenterBlock)block
{
	void *pool = objc_autoreleasePoolPush();
	OFNotificationCenterHandle *handle =
	    [[[OFNotificationCenterHandle alloc] initWithName: name
						       object: object
							block: block]
	    autorelease];

	[self of_addObserver: handle];

	[handle retain];

	objc_autoreleasePoolPop(pool);

	return [handle autorelease];
}
#endif

- (void)removeObserver: (OFNotificationCenterHandle *)handle
{







	void *pool = objc_autoreleasePoolPush();

	/* {} required to avoid -Wmisleading-indentation false positive. */
	if (![handle isKindOfClass: [OFNotificationCenterHandle class]]) {
		@throw [OFInvalidArgumentException exception];
	}

#ifdef OF_HAVE_THREADS







<
|
|
|


















|

>
>
>
>
>
>
>
|







242
243
244
245
246
247
248

249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
						       object: object]
	    autorelease]];

	objc_autoreleasePoolPop(pool);
}

#ifdef OF_HAVE_BLOCKS

- (id)addObserverForName: (OFNotificationName)name
		  object: (id)object
	      usingBlock: (OFNotificationCenterBlock)block
{
	void *pool = objc_autoreleasePoolPush();
	OFNotificationCenterHandle *handle =
	    [[[OFNotificationCenterHandle alloc] initWithName: name
						       object: object
							block: block]
	    autorelease];

	[self of_addObserver: handle];

	[handle retain];

	objc_autoreleasePoolPop(pool);

	return [handle autorelease];
}
#endif

- (void)removeObserver: (id)handle_
{
	OFNotificationCenterHandle *handle;
	void *pool;

	if (![handle_ isKindOfClass: [OFNotificationCenterHandle class]])
		@throw [OFInvalidArgumentException exception];

	handle = handle_;
	pool = objc_autoreleasePoolPush();

	/* {} required to avoid -Wmisleading-indentation false positive. */
	if (![handle isKindOfClass: [OFNotificationCenterHandle class]]) {
		@throw [OFInvalidArgumentException exception];
	}

#ifdef OF_HAVE_THREADS
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
					userInfo: userInfo]];

	objc_autoreleasePoolPop(pool);
}
@end

@implementation OFDefaultNotificationCenter
- (instancetype)autorelease
{
	return self;
}

- (instancetype)retain
{
	return self;
}

- (void)release
{
}

- (unsigned int)retainCount
{
	return OFMaxRetainCount;
}
@end







<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<

379
380
381
382
383
384
385




386













387
					userInfo: userInfo]];

	objc_autoreleasePoolPop(pool);
}
@end

@implementation OFDefaultNotificationCenter




OF_SINGLETON_METHODS













@end

Modified src/OFNull.h from [37abd599a7] to [ed5233e238].

1
2
3
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
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#import "OFObject.h"
#import "OFASN1DERRepresentation.h"
#import "OFJSONRepresentation.h"
#import "OFMessagePackRepresentation.h"
#import "OFSerialization.h"

OF_ASSUME_NONNULL_BEGIN

/**
 * @class OFNull OFNull.h ObjFW/OFNull.h
 *
 * @brief A class for representing null values in collections.
 */
OF_SUBCLASSING_RESTRICTED
@interface OFNull: OFObject <OFCopying, OFSerialization, OFJSONRepresentation,
    OFMessagePackRepresentation, OFASN1DERRepresentation>
/**
 * @brief Returns an OFNull singleton.
 *
 * @return An OFNull singleton
 */
+ (OFNull *)null;
@end

OF_ASSUME_NONNULL_END

|

















<









|










1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
/*
 * Copyright (c) 2008-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 "OFObject.h"
#import "OFASN1DERRepresentation.h"
#import "OFJSONRepresentation.h"
#import "OFMessagePackRepresentation.h"


OF_ASSUME_NONNULL_BEGIN

/**
 * @class OFNull OFNull.h ObjFW/OFNull.h
 *
 * @brief A class for representing null values in collections.
 */
OF_SUBCLASSING_RESTRICTED
@interface OFNull: OFObject <OFCopying, OFJSONRepresentation,
    OFMessagePackRepresentation, OFASN1DERRepresentation>
/**
 * @brief Returns an OFNull singleton.
 *
 * @return An OFNull singleton
 */
+ (OFNull *)null;
@end

OF_ASSUME_NONNULL_END

Modified src/OFNull.m from [d09a652926] to [bd50904874].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#import "OFNull.h"
#import "OFString.h"
#import "OFXMLElement.h"
#import "OFData.h"

#import "OFInvalidArgumentException.h"

@interface OFNull ()
- (OFString *)
    of_JSONRepresentationWithOptions: (OFJSONRepresentationOptions)options
			       depth: (size_t)depth;

|
















|
<
|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

20
21
22
23
24
25
26
27
/*
 * Copyright (c) 2008-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 "OFNull.h"
#import "OFData.h"

#import "OFString.h"

#import "OFInvalidArgumentException.h"

@interface OFNull ()
- (OFString *)
    of_JSONRepresentationWithOptions: (OFJSONRepresentationOptions)options
			       depth: (size_t)depth;
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
}

+ (OFNull *)null
{
	return null;
}

- (instancetype)initWithSerialization: (OFXMLElement *)element
{
	void *pool;

	[self release];

	pool = objc_autoreleasePoolPush();

	if (![element.name isEqual: self.className] ||
	    ![element.namespace isEqual: OFSerializationNS])
		@throw [OFInvalidArgumentException exception];

	objc_autoreleasePoolPop(pool);

	return [OFNull null];
}

- (OFString *)description
{
	return @"<null>";
}

- (id)copy
{
	return self;
}

- (OFXMLElement *)XMLElementBySerializing
{
	void *pool = objc_autoreleasePoolPush();
	OFXMLElement *element;

	element = [OFXMLElement elementWithName: self.className
				      namespace: OFSerializationNS];

	[element retain];

	objc_autoreleasePoolPop(pool);

	return [element autorelease];
}

- (OFString *)JSONRepresentation
{
	return [self of_JSONRepresentationWithOptions: 0 depth: 0];
}

- (OFString *)JSONRepresentationWithOptions:
    (OFJSONRepresentationOptions)options







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<










<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







36
37
38
39
40
41
42

















43
44
45
46
47
48
49
50
51
52















53
54
55
56
57
58
59
}

+ (OFNull *)null
{
	return null;
}


















- (OFString *)description
{
	return @"<null>";
}

- (id)copy
{
	return self;
}
















- (OFString *)JSONRepresentation
{
	return [self of_JSONRepresentationWithOptions: 0 depth: 0];
}

- (OFString *)JSONRepresentationWithOptions:
    (OFJSONRepresentationOptions)options
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

- (OFData *)ASN1DERRepresentation
{
	const unsigned char bytes[] = { OFASN1TagNumberNull, 0 };
	return [OFData dataWithItems: bytes count: sizeof(bytes)];
}

- (instancetype)autorelease
{
	return self;
}

- (instancetype)retain
{
	return self;
}

- (void)release
{
}

- (unsigned int)retainCount
{
	return OFMaxRetainCount;
}

- (void)dealloc
{
	OF_DEALLOC_UNSUPPORTED
}
@end







<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

76
77
78
79
80
81
82




83


















84

- (OFData *)ASN1DERRepresentation
{
	const unsigned char bytes[] = { OFASN1TagNumberNull, 0 };
	return [OFData dataWithItems: bytes count: sizeof(bytes)];
}





OF_SINGLETON_METHODS


















@end

Modified src/OFNumber.h from [eff21822aa] to [e8b2d0d74a].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
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

#ifdef OF_HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif

#import "OFJSONRepresentation.h"
#import "OFMessagePackRepresentation.h"
#import "OFSerialization.h"
#import "OFValue.h"

OF_ASSUME_NONNULL_BEGIN

/** @file */

/**
 * @class OFNumber OFNumber.h ObjFW/OFNumber.h
 *
 * @brief Provides a way to store a number in an object.
 */
#ifndef OF_NUMBER_M
OF_SUBCLASSING_RESTRICTED
#endif
@interface OFNumber: OFValue <OFComparing, OFSerialization,
    OFJSONRepresentation, OFMessagePackRepresentation>
{
	union {
		double float_;
		long long signed_;
		unsigned long long unsigned_;
	} _value;
	const char *_typeEncoding;
}

/**
 * @brief The OFNumber as a `bool`.
 */
@property (readonly, nonatomic) bool boolValue;

/**
 * @brief The OFNumber as a `signed char`.







<











<
<
<
|
|
<
<
<
<
<
<
<
<
<







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

#ifdef OF_HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif

#import "OFJSONRepresentation.h"
#import "OFMessagePackRepresentation.h"

#import "OFValue.h"

OF_ASSUME_NONNULL_BEGIN

/** @file */

/**
 * @class OFNumber OFNumber.h ObjFW/OFNumber.h
 *
 * @brief Provides a way to store a number in an object.
 */



@interface OFNumber: OFValue <OFComparing, OFJSONRepresentation,
    OFMessagePackRepresentation>









/**
 * @brief The OFNumber as a `bool`.
 */
@property (readonly, nonatomic) bool boolValue;

/**
 * @brief The OFNumber as a `signed char`.
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
@property (readonly, nonatomic) double doubleValue;

/**
 * @brief The OFNumber as a string.
 */
@property (readonly, nonatomic) OFString *stringValue;

+ (instancetype)valueWithBytes: (const void *)bytes
		      objCType: (const char *)objCType OF_UNAVAILABLE;
+ (instancetype)valueWithPointer: (const void *)pointer OF_UNAVAILABLE;
+ (instancetype)valueWithNonretainedObject: (id)object OF_UNAVAILABLE;
+ (instancetype)valueWithRange: (OFRange)range OF_UNAVAILABLE;
+ (instancetype)valueWithPoint: (OFPoint)point OF_UNAVAILABLE;
+ (instancetype)valueWithSize: (OFSize)size OF_UNAVAILABLE;
+ (instancetype)valueWithRect: (OFRect)rect OF_UNAVAILABLE;








<
<







107
108
109
110
111
112
113


114
115
116
117
118
119
120
@property (readonly, nonatomic) double doubleValue;

/**
 * @brief The OFNumber as a string.
 */
@property (readonly, nonatomic) OFString *stringValue;



+ (instancetype)valueWithPointer: (const void *)pointer OF_UNAVAILABLE;
+ (instancetype)valueWithNonretainedObject: (id)object OF_UNAVAILABLE;
+ (instancetype)valueWithRange: (OFRange)range OF_UNAVAILABLE;
+ (instancetype)valueWithPoint: (OFPoint)point OF_UNAVAILABLE;
+ (instancetype)valueWithSize: (OFSize)size OF_UNAVAILABLE;
+ (instancetype)valueWithRect: (OFRect)rect OF_UNAVAILABLE;

233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
 * @brief Creates a new OFNumber with the specified `double`.
 *
 * @param value The `double` value which the OFNumber should contain
 * @return A new autoreleased OFNumber
 */
+ (instancetype)numberWithDouble: (double)value;

- (instancetype)init OF_UNAVAILABLE;
- (instancetype)initWithBytes: (const void *)bytes
		     objCType: (const char *)objCType OF_UNAVAILABLE;

/**
 * @brief Initializes an already allocated OFNumber with the specified `bool`.
 *
 * @param value The `bool` value which the OFNumber should contain
 * @return An initialized OFNumber
 */
- (instancetype)initWithBool: (bool)value;







<
<
<
<







218
219
220
221
222
223
224




225
226
227
228
229
230
231
 * @brief Creates a new OFNumber with the specified `double`.
 *
 * @param value The `double` value which the OFNumber should contain
 * @return A new autoreleased OFNumber
 */
+ (instancetype)numberWithDouble: (double)value;





/**
 * @brief Initializes an already allocated OFNumber with the specified `bool`.
 *
 * @param value The `bool` value which the OFNumber should contain
 * @return An initialized OFNumber
 */
- (instancetype)initWithBool: (bool)value;

Modified src/OFNumber.m from [0d84e74204] to [e5b90c57f3].

1
2
3
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
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#define OF_NUMBER_M

#include "config.h"

#include <math.h>

#import "OFNumber.h"
#import "OFString.h"
#import "OFXMLElement.h"
#import "OFXMLAttribute.h"
#import "OFData.h"

#import "OFInvalidArgumentException.h"
#import "OFInvalidFormatException.h"
#import "OFOutOfRangeException.h"

@interface OFNumber ()
+ (instancetype)of_alloc;
- (OFString *)
    of_JSONRepresentationWithOptions: (OFJSONRepresentationOptions)options
			       depth: (size_t)depth;
@end

@interface OFNumberPlaceholder: OFNumber
@end

@interface OFNumberSingleton: OFNumber
@end

#ifdef OF_OBJFW_RUNTIME
enum Tag {
	tagChar,
	tagShort,
	tagInt,
	tagLong,
	tagLongLong,
	tagUnsignedChar,
	tagUnsignedShort,
	tagUnsignedInt,
	tagUnsignedLong,
	tagUnsignedLongLong,
};
static const uint_fast8_t tagBits = 4;
static const uintptr_t tagMask = 0xF;

@interface OFTaggedPointerNumber: OFNumberSingleton
@end
#endif

static struct {
	Class isa;
} placeholder;

#define SINGLETON(var, sel, val)				\
	static OFNumberSingleton *var;				\
								\
	static void						\
	var##Init(void)						\
	{							\
		var = [[OFNumberSingleton alloc] sel val];	\
	}
SINGLETON(falseNumber, initWithBool:, false)
SINGLETON(trueNumber, initWithBool:, true)
SINGLETON(charZeroNumber, initWithChar:, 0)
SINGLETON(shortZeroNumber, initWithShort:, 0)
SINGLETON(intZeroNumber, initWithInt:, 0)
SINGLETON(longZeroNumber, initWithLong:, 0)
SINGLETON(longLongZeroNumber, initWithLongLong:, 0)
SINGLETON(unsignedCharZeroNumber, initWithUnsignedChar:, 0)
SINGLETON(unsignedShortZeroNumber, initWithUnsignedShort:, 0)
SINGLETON(unsignedIntZeroNumber, initWithUnsignedInt:, 0)
SINGLETON(unsignedLongZeroNumber, initWithUnsignedLong:, 0)
SINGLETON(unsignedLongLongZeroNumber, initWithUnsignedLongLong:, 0)
SINGLETON(floatZeroNumber, initWithFloat:, 0)
SINGLETON(doubleZeroNumber, initWithDouble:, 0)
#undef SINGLETON

#ifdef OF_OBJFW_RUNTIME
static int numberTag;
#endif

static bool
isUnsigned(OFNumber *number)
{
	switch (*number.objCType) {
	case 'B':
		return true;
	case 'C':
		return true;
	case 'S':
		return true;
	case 'I':
		return true;
	case 'L':
		return true;
	case 'Q':
		return true;
	default:
		return false;
	}
}

static bool
isSigned(OFNumber *number)
{
	switch (*number.objCType) {
	case 'c':
		return true;
	case 's':
		return true;
	case 'i':
		return true;
	case 'l':
		return true;
	case 'q':
		return true;
	default:
		return false;
	}
}

static bool
isFloat(OFNumber *number)
{
	switch (*number.objCType) {
	case 'f':
		return true;
	case 'd':
		return true;
	default:
		return false;
	}
}

@implementation OFNumberPlaceholder
- (instancetype)initWithBool: (bool)value
{
	if (value) {
		static OFOnceControl onceControl = OFOnceControlInitValue;
		OFOnce(&onceControl, trueNumberInit);
		return (id)trueNumber;
	} else {

|













<
<





|
|
|
|






<





|


|


<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<




|
|
|
|
|
|
|

















<
<
<
<





<

<

<

<

<












<

<

<

<












<







|







1
2
3
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
/*
 * 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 <math.h>

#import "OFNumber.h"
#import "OFConcreteNumber.h"
#import "OFData.h"
#import "OFString.h"
#import "OFTaggedPointerNumber.h"

#import "OFInvalidArgumentException.h"
#import "OFInvalidFormatException.h"
#import "OFOutOfRangeException.h"

@interface OFNumber ()

- (OFString *)
    of_JSONRepresentationWithOptions: (OFJSONRepresentationOptions)options
			       depth: (size_t)depth;
@end

@interface OFPlaceholderNumber: OFNumber
@end

@interface OFConcreteNumberSingleton: OFConcreteNumber
@end





















static struct {
	Class isa;
} placeholder;

#define SINGLETON(var, sel, val)					\
	static OFConcreteNumberSingleton *var;				\
									\
	static void							\
	var##Init(void)							\
	{								\
		var = [[OFConcreteNumberSingleton alloc] sel val];	\
	}
SINGLETON(falseNumber, initWithBool:, false)
SINGLETON(trueNumber, initWithBool:, true)
SINGLETON(charZeroNumber, initWithChar:, 0)
SINGLETON(shortZeroNumber, initWithShort:, 0)
SINGLETON(intZeroNumber, initWithInt:, 0)
SINGLETON(longZeroNumber, initWithLong:, 0)
SINGLETON(longLongZeroNumber, initWithLongLong:, 0)
SINGLETON(unsignedCharZeroNumber, initWithUnsignedChar:, 0)
SINGLETON(unsignedShortZeroNumber, initWithUnsignedShort:, 0)
SINGLETON(unsignedIntZeroNumber, initWithUnsignedInt:, 0)
SINGLETON(unsignedLongZeroNumber, initWithUnsignedLong:, 0)
SINGLETON(unsignedLongLongZeroNumber, initWithUnsignedLongLong:, 0)
SINGLETON(floatZeroNumber, initWithFloat:, 0)
SINGLETON(doubleZeroNumber, initWithDouble:, 0)
#undef SINGLETON





static bool
isUnsigned(OFNumber *number)
{
	switch (*number.objCType) {
	case 'B':

	case 'C':

	case 'S':

	case 'I':

	case 'L':

	case 'Q':
		return true;
	default:
		return false;
	}
}

static bool
isSigned(OFNumber *number)
{
	switch (*number.objCType) {
	case 'c':

	case 's':

	case 'i':

	case 'l':

	case 'q':
		return true;
	default:
		return false;
	}
}

static bool
isFloat(OFNumber *number)
{
	switch (*number.objCType) {
	case 'f':

	case 'd':
		return true;
	default:
		return false;
	}
}

@implementation OFPlaceholderNumber
- (instancetype)initWithBool: (bool)value
{
	if (value) {
		static OFOnceControl onceControl = OFOnceControlInitValue;
		OFOnce(&onceControl, trueNumberInit);
		return (id)trueNumber;
	} else {
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
- (instancetype)initWithChar: (signed char)value
{
	if (value == 0) {
		static OFOnceControl onceControl = OFOnceControlInitValue;
		OFOnce(&onceControl, charZeroNumberInit);
		return (id)charZeroNumber;
#ifdef OF_OBJFW_RUNTIME
	} else if ((unsigned char)value <= (UINTPTR_MAX >> tagBits)) {
		id ret = objc_createTaggedPointer(numberTag,
		    ((uintptr_t)(unsigned char)value << tagBits) | tagChar);

		if (ret != nil)
			return ret;
#endif
	}

	return (id)[[OFNumber of_alloc] initWithChar: value];
}

- (instancetype)initWithShort: (short)value
{
	if (value == 0) {
		static OFOnceControl onceControl = OFOnceControlInitValue;
		OFOnce(&onceControl, shortZeroNumberInit);
		return (id)shortZeroNumber;
#ifdef OF_OBJFW_RUNTIME
	} else if ((unsigned short)value <= (UINTPTR_MAX >> tagBits)) {
		id ret = objc_createTaggedPointer(numberTag,
		    ((uintptr_t)(unsigned short)value << tagBits) | tagShort);

		if (ret != nil)
			return ret;
#endif
	}

	return (id)[[OFNumber of_alloc] initWithShort: value];
}

- (instancetype)initWithInt: (int)value
{
	if (value == 0) {
		static OFOnceControl onceControl = OFOnceControlInitValue;
		OFOnce(&onceControl, intZeroNumberInit);
		return (id)intZeroNumber;
#ifdef OF_OBJFW_RUNTIME
	} else if ((unsigned int)value <= (UINTPTR_MAX >> tagBits)) {
		id ret = objc_createTaggedPointer(numberTag,
		    ((uintptr_t)(unsigned int)value << tagBits) | tagInt);

		if (ret != nil)
			return ret;
#endif
	}

	return (id)[[OFNumber of_alloc] initWithInt: value];
}

- (instancetype)initWithLong: (long)value
{
	if (value == 0) {
		static OFOnceControl onceControl = OFOnceControlInitValue;
		OFOnce(&onceControl, longZeroNumberInit);
		return (id)longZeroNumber;
#ifdef OF_OBJFW_RUNTIME
	} else if ((unsigned long)value <= (UINTPTR_MAX >> tagBits)) {
		id ret = objc_createTaggedPointer(numberTag,
		    ((uintptr_t)(unsigned long)value << tagBits) | tagLong);

		if (ret != nil)
			return ret;
#endif
	}

	return (id)[[OFNumber of_alloc] initWithLong: value];
}

- (instancetype)initWithLongLong: (long long)value
{
	if (value == 0) {
		static OFOnceControl onceControl = OFOnceControlInitValue;
		OFOnce(&onceControl, longLongZeroNumberInit);
		return (id)longLongZeroNumber;
#ifdef OF_OBJFW_RUNTIME
	} else if ((unsigned long long)value <= (UINTPTR_MAX >> tagBits)) {
		id ret = objc_createTaggedPointer(numberTag,
		    ((uintptr_t)(unsigned long long)value << tagBits) |
		    tagLongLong);

		if (ret != nil)
			return ret;
#endif
	}

	return (id)[[OFNumber of_alloc] initWithLongLong: value];
}

- (instancetype)initWithUnsignedChar: (unsigned char)value
{
	if (value == 0) {
		static OFOnceControl onceControl = OFOnceControlInitValue;
		OFOnce(&onceControl, unsignedCharZeroNumberInit);
		return (id)unsignedCharZeroNumber;
#ifdef OF_OBJFW_RUNTIME
	} else if (value <= (UINTPTR_MAX >> tagBits)) {
		id ret = objc_createTaggedPointer(numberTag,
		    ((uintptr_t)value << tagBits) | tagUnsignedChar);

		if (ret != nil)
			return ret;
#endif
	}

	return (id)[[OFNumber of_alloc] initWithUnsignedChar: value];
}

- (instancetype)initWithUnsignedShort: (unsigned short)value
{
	if (value == 0) {
		static OFOnceControl onceControl = OFOnceControlInitValue;
		OFOnce(&onceControl, unsignedShortZeroNumberInit);
		return (id)unsignedShortZeroNumber;
#ifdef OF_OBJFW_RUNTIME
	} else if (value <= (UINTPTR_MAX >> tagBits)) {
		id ret = objc_createTaggedPointer(numberTag,
		    ((uintptr_t)value << tagBits) | tagUnsignedShort);

		if (ret != nil)
			return ret;
#endif
	}

	return (id)[[OFNumber of_alloc] initWithUnsignedShort: value];
}

- (instancetype)initWithUnsignedInt: (unsigned int)value
{
	if (value == 0) {
		static OFOnceControl onceControl = OFOnceControlInitValue;
		OFOnce(&onceControl, unsignedIntZeroNumberInit);
		return (id)unsignedIntZeroNumber;
#ifdef OF_OBJFW_RUNTIME
	} else if (value <= (UINTPTR_MAX >> tagBits)) {
		id ret = objc_createTaggedPointer(numberTag,
		    ((uintptr_t)value << tagBits) | tagUnsignedInt);

		if (ret != nil)
			return ret;
#endif
	}

	return (id)[[OFNumber of_alloc] initWithUnsignedInt: value];
}

- (instancetype)initWithUnsignedLong: (unsigned long)value
{
	if (value == 0) {
		static OFOnceControl onceControl = OFOnceControlInitValue;
		OFOnce(&onceControl, unsignedLongZeroNumberInit);
		return (id)unsignedLongZeroNumber;
#ifdef OF_OBJFW_RUNTIME
	} else if (value <= (UINTPTR_MAX >> tagBits)) {
		id ret = objc_createTaggedPointer(numberTag,
		    ((uintptr_t)value << tagBits) | tagUnsignedLong);

		if (ret != nil)
			return ret;
#endif
	}

	return (id)[[OFNumber of_alloc] initWithUnsignedLong: value];
}

- (instancetype)initWithUnsignedLongLong: (unsigned long long)value
{
	if (value == 0) {
		static OFOnceControl onceControl = OFOnceControlInitValue;
		OFOnce(&onceControl, unsignedLongLongZeroNumberInit);
		return (id)unsignedLongLongZeroNumber;
#ifdef OF_OBJFW_RUNTIME
	} else if (value <= (UINTPTR_MAX >> tagBits)) {
		id ret = objc_createTaggedPointer(numberTag,
		    ((uintptr_t)value << tagBits) | tagUnsignedLongLong);

		if (ret != nil)
			return ret;
#endif
	}

	return (id)[[OFNumber of_alloc] initWithUnsignedLongLong: value];
}

- (instancetype)initWithFloat: (float)value
{
	if (value == 0) {
		static OFOnceControl onceControl = OFOnceControlInitValue;
		OFOnce(&onceControl, floatZeroNumberInit);
		return (id)floatZeroNumber;
	}

	return (id)[[OFNumber of_alloc] initWithFloat: value];
}

- (instancetype)initWithDouble: (double)value
{
	if (value == 0) {
		static OFOnceControl onceControl = OFOnceControlInitValue;
		OFOnce(&onceControl, doubleZeroNumberInit);
		return (id)doubleZeroNumber;
	}

	return (id)[[OFNumber of_alloc] initWithDouble: value];
}

- (instancetype)initWithSerialization: (OFXMLElement *)element
{
	return (id)[[OFNumber of_alloc] initWithSerialization: element];
}
#ifdef __clang__
# pragma clang diagnostic pop
#endif
@end

@implementation OFNumberSingleton
- (instancetype)autorelease
{
	return self;
}

- (instancetype)retain
{
	return self;
}

- (void)release
{
}

- (unsigned int)retainCount
{
	return OFMaxRetainCount;
}
@end

#ifdef OF_OBJFW_RUNTIME
@implementation OFTaggedPointerNumber
- (const char *)objCType
{
	uintptr_t value = object_getTaggedPointerValue(self);

	switch (value & tagMask) {
	case tagChar:
		return @encode(signed char);
	case tagShort:
		return @encode(short);
	case tagInt:
		return @encode(int);
	case tagLong:
		return @encode(long);
	case tagLongLong:
		return @encode(long long);
	case tagUnsignedChar:
		return @encode(unsigned char);
	case tagUnsignedShort:
		return @encode(unsigned short);
	case tagUnsignedInt:
		return @encode(unsigned int);
	case tagUnsignedLong:
		return @encode(unsigned long);
	case tagUnsignedLongLong:
		return @encode(unsigned long long);
	default:
		@throw [OFInvalidArgumentException exception];
	}
}

# define RETURN_VALUE							  \
	uintptr_t value = object_getTaggedPointerValue(self);		  \
									  \
	switch (value & tagMask) {					  \
	case tagChar:							  \
		return (signed char)(unsigned char)(value >> tagBits);	  \
	case tagShort:							  \
		return (short)(unsigned short)(value >> tagBits);	  \
	case tagInt:							  \
		return (int)(unsigned int)(value >> tagBits);		  \
	case tagLong:							  \
		return (long)(unsigned long)(value >> tagBits);		  \
	case tagLongLong:						  \
		return (long long)(unsigned long long)(value >> tagBits); \
	case tagUnsignedChar:						  \
		return (unsigned char)(value >> tagBits);		  \
	case tagUnsignedShort:						  \
		return (unsigned short)(value >> tagBits);		  \
	case tagUnsignedInt:						  \
		return (unsigned int)(value >> tagBits);		  \
	case tagUnsignedLong:						  \
		return (unsigned long)(value >> tagBits);		  \
	case tagUnsignedLongLong:					  \
		return (unsigned long long)(value >> tagBits);		  \
	default:							  \
		@throw [OFInvalidArgumentException exception];		  \
	}
- (long long)longLongValue
{
	RETURN_VALUE
}

- (unsigned long long)unsignedLongLongValue
{
	RETURN_VALUE
}

- (double)doubleValue
{
	RETURN_VALUE
}
@end
# undef RETURN_VALUE
#endif

@implementation OFNumber
+ (void)initialize
{
	if (self != [OFNumber class])
		return;

	placeholder.isa = [OFNumberPlaceholder class];

#ifdef OF_OBJFW_RUNTIME
	numberTag =
	    objc_registerTaggedPointerClass([OFTaggedPointerNumber class]);
#endif
}

+ (instancetype)of_alloc
{
	return [super alloc];
}

+ (instancetype)alloc
{
	if (self == [OFNumber class])
		return (id)&placeholder;

	return [super alloc];
}

+ (instancetype)valueWithBytes: (const void *)bytes
		      objCType: (const char *)objCType
{
	OF_UNRECOGNIZED_SELECTOR
}

+ (instancetype)valueWithPointer: (const void *)pointer
{
	OF_UNRECOGNIZED_SELECTOR
}

+ (instancetype)valueWithNonretainedObject: (id)object
{







|
|
|






|









|
|
|






|









|
|
|






|









|
|
|






|









|
|
<
|






|









|
|
<






|









|
|
<






|









|
|
<






|









|
|
<






|









|
|
|






|










|










|
<
<
<
<
<




<

<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<


<
|
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

<
<




|
<
|
<
<
<
<
<
<
<
<
<
<
<










<
<
<
<
<
<







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
- (instancetype)initWithChar: (signed char)value
{
	if (value == 0) {
		static OFOnceControl onceControl = OFOnceControlInitValue;
		OFOnce(&onceControl, charZeroNumberInit);
		return (id)charZeroNumber;
#ifdef OF_OBJFW_RUNTIME
	} else if ((unsigned char)value <=
	    (UINTPTR_MAX >> OFTaggedPointerNumberTagBits)) {
		id ret = [OFTaggedPointerNumber numberWithChar: value];

		if (ret != nil)
			return ret;
#endif
	}

	return (id)[[OFConcreteNumber alloc] initWithChar: value];
}

- (instancetype)initWithShort: (short)value
{
	if (value == 0) {
		static OFOnceControl onceControl = OFOnceControlInitValue;
		OFOnce(&onceControl, shortZeroNumberInit);
		return (id)shortZeroNumber;
#ifdef OF_OBJFW_RUNTIME
	} else if ((unsigned short)value <=
	    (UINTPTR_MAX >> OFTaggedPointerNumberTagBits)) {
		id ret = [OFTaggedPointerNumber numberWithShort: value];

		if (ret != nil)
			return ret;
#endif
	}

	return (id)[[OFConcreteNumber alloc] initWithShort: value];
}

- (instancetype)initWithInt: (int)value
{
	if (value == 0) {
		static OFOnceControl onceControl = OFOnceControlInitValue;
		OFOnce(&onceControl, intZeroNumberInit);
		return (id)intZeroNumber;
#ifdef OF_OBJFW_RUNTIME
	} else if ((unsigned int)value <=
	    (UINTPTR_MAX >> OFTaggedPointerNumberTagBits)) {
		id ret = [OFTaggedPointerNumber numberWithInt: value];

		if (ret != nil)
			return ret;
#endif
	}

	return (id)[[OFConcreteNumber alloc] initWithInt: value];
}

- (instancetype)initWithLong: (long)value
{
	if (value == 0) {
		static OFOnceControl onceControl = OFOnceControlInitValue;
		OFOnce(&onceControl, longZeroNumberInit);
		return (id)longZeroNumber;
#ifdef OF_OBJFW_RUNTIME
	} else if ((unsigned long)value <=
	    (UINTPTR_MAX >> OFTaggedPointerNumberTagBits)) {
		id ret = [OFTaggedPointerNumber numberWithLong: value];

		if (ret != nil)
			return ret;
#endif
	}

	return (id)[[OFConcreteNumber alloc] initWithLong: value];
}

- (instancetype)initWithLongLong: (long long)value
{
	if (value == 0) {
		static OFOnceControl onceControl = OFOnceControlInitValue;
		OFOnce(&onceControl, longLongZeroNumberInit);
		return (id)longLongZeroNumber;
#ifdef OF_OBJFW_RUNTIME
	} else if ((unsigned long long)value <=
	    (UINTPTR_MAX >> OFTaggedPointerNumberTagBits)) {

		id ret = [OFTaggedPointerNumber numberWithLongLong: value];

		if (ret != nil)
			return ret;
#endif
	}

	return (id)[[OFConcreteNumber alloc] initWithLongLong: value];
}

- (instancetype)initWithUnsignedChar: (unsigned char)value
{
	if (value == 0) {
		static OFOnceControl onceControl = OFOnceControlInitValue;
		OFOnce(&onceControl, unsignedCharZeroNumberInit);
		return (id)unsignedCharZeroNumber;
#ifdef OF_OBJFW_RUNTIME
	} else if (value <= (UINTPTR_MAX >> OFTaggedPointerNumberTagBits)) {
		id ret = [OFTaggedPointerNumber numberWithUnsignedChar: value];


		if (ret != nil)
			return ret;
#endif
	}

	return (id)[[OFConcreteNumber alloc] initWithUnsignedChar: value];
}

- (instancetype)initWithUnsignedShort: (unsigned short)value
{
	if (value == 0) {
		static OFOnceControl onceControl = OFOnceControlInitValue;
		OFOnce(&onceControl, unsignedShortZeroNumberInit);
		return (id)unsignedShortZeroNumber;
#ifdef OF_OBJFW_RUNTIME
	} else if (value <= (UINTPTR_MAX >> OFTaggedPointerNumberTagBits)) {
		id ret = [OFTaggedPointerNumber numberWithUnsignedShort: value];


		if (ret != nil)
			return ret;
#endif
	}

	return (id)[[OFConcreteNumber alloc] initWithUnsignedShort: value];
}

- (instancetype)initWithUnsignedInt: (unsigned int)value
{
	if (value == 0) {
		static OFOnceControl onceControl = OFOnceControlInitValue;
		OFOnce(&onceControl, unsignedIntZeroNumberInit);
		return (id)unsignedIntZeroNumber;
#ifdef OF_OBJFW_RUNTIME
	} else if (value <= (UINTPTR_MAX >> OFTaggedPointerNumberTagBits)) {
		id ret = [OFTaggedPointerNumber numberWithUnsignedInt: value];


		if (ret != nil)
			return ret;
#endif
	}

	return (id)[[OFConcreteNumber alloc] initWithUnsignedInt: value];
}

- (instancetype)initWithUnsignedLong: (unsigned long)value
{
	if (value == 0) {
		static OFOnceControl onceControl = OFOnceControlInitValue;
		OFOnce(&onceControl, unsignedLongZeroNumberInit);
		return (id)unsignedLongZeroNumber;
#ifdef OF_OBJFW_RUNTIME
	} else if (value <= (UINTPTR_MAX >> OFTaggedPointerNumberTagBits)) {
		id ret = [OFTaggedPointerNumber numberWithUnsignedLong: value];


		if (ret != nil)
			return ret;
#endif
	}

	return (id)[[OFConcreteNumber alloc] initWithUnsignedLong: value];
}

- (instancetype)initWithUnsignedLongLong: (unsigned long long)value
{
	if (value == 0) {
		static OFOnceControl onceControl = OFOnceControlInitValue;
		OFOnce(&onceControl, unsignedLongLongZeroNumberInit);
		return (id)unsignedLongLongZeroNumber;
#ifdef OF_OBJFW_RUNTIME
	} else if (value <= (UINTPTR_MAX >> OFTaggedPointerNumberTagBits)) {
		id ret = [OFTaggedPointerNumber
		    numberWithUnsignedLongLong: value];

		if (ret != nil)
			return ret;
#endif
	}

	return (id)[[OFConcreteNumber alloc] initWithUnsignedLongLong: value];
}

- (instancetype)initWithFloat: (float)value
{
	if (value == 0) {
		static OFOnceControl onceControl = OFOnceControlInitValue;
		OFOnce(&onceControl, floatZeroNumberInit);
		return (id)floatZeroNumber;
	}

	return (id)[[OFConcreteNumber alloc] initWithFloat: value];
}

- (instancetype)initWithDouble: (double)value
{
	if (value == 0) {
		static OFOnceControl onceControl = OFOnceControlInitValue;
		OFOnce(&onceControl, doubleZeroNumberInit);
		return (id)doubleZeroNumber;
	}

	return (id)[[OFConcreteNumber alloc] initWithDouble: value];





}
#ifdef __clang__
# pragma clang diagnostic pop
#endif







OF_SINGLETON_METHODS













@end


@implementation OFConcreteNumberSingleton



OF_SINGLETON_METHODS



































































@end



@implementation OFNumber
+ (void)initialize
{
	if (self == [OFNumber class])

		object_setClass((id)&placeholder, [OFPlaceholderNumber class]);











}

+ (instancetype)alloc
{
	if (self == [OFNumber class])
		return (id)&placeholder;

	return [super alloc];
}







+ (instancetype)valueWithPointer: (const void *)pointer
{
	OF_UNRECOGNIZED_SELECTOR
}

+ (instancetype)valueWithNonretainedObject: (id)object
{
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
}

+ (instancetype)numberWithDouble: (double)value
{
	return [[[self alloc] initWithDouble: value] autorelease];
}

- (instancetype)init
{
	OF_INVALID_INIT_METHOD
}

- (instancetype)initWithBytes: (const void *)bytes
		     objCType: (const char *)objCType
{
	OF_INVALID_INIT_METHOD
}

- (instancetype)initWithBool: (bool)value
{
	self = [super init];

	_value.unsigned_ = value;
	_typeEncoding = @encode(bool);

	return self;
}

- (instancetype)initWithChar: (signed char)value
{
	self = [super init];

	_value.signed_ = value;
	_typeEncoding = @encode(signed char);

	return self;
}

- (instancetype)initWithShort: (short)value
{
	self = [super init];

	_value.signed_ = value;
	_typeEncoding = @encode(short);

	return self;
}

- (instancetype)initWithInt: (int)value
{
	self = [super init];

	_value.signed_ = value;
	_typeEncoding = @encode(int);

	return self;
}

- (instancetype)initWithLong: (long)value
{
	self = [super init];

	_value.signed_ = value;
	_typeEncoding = @encode(long);

	return self;
}

- (instancetype)initWithLongLong: (long long)value
{
	self = [super init];

	_value.signed_ = value;
	_typeEncoding = @encode(long long);

	return self;
}

- (instancetype)initWithUnsignedChar: (unsigned char)value
{
	self = [super init];

	_value.unsigned_ = value;
	_typeEncoding = @encode(unsigned long);

	return self;
}

- (instancetype)initWithUnsignedShort: (unsigned short)value
{
	self = [super init];

	_value.unsigned_ = value;
	_typeEncoding = @encode(unsigned short);

	return self;
}

- (instancetype)initWithUnsignedInt: (unsigned int)value
{
	self = [super init];

	_value.unsigned_ = value;
	_typeEncoding = @encode(unsigned int);

	return self;
}

- (instancetype)initWithUnsignedLong: (unsigned long)value
{
	self = [super init];

	_value.unsigned_ = value;
	_typeEncoding = @encode(unsigned long);

	return self;
}

- (instancetype)initWithUnsignedLongLong: (unsigned long long)value
{
	self = [super init];

	_value.unsigned_ = value;
	_typeEncoding = @encode(unsigned long long);

	return self;
}

- (instancetype)initWithPtrDiff: (ptrdiff_t)value
{
	self = [super init];

	_value.signed_ = value;
	_typeEncoding = @encode(ptrdiff_t);

	return self;
}

- (instancetype)initWithIntPtr: (intptr_t)value
{
	self = [super init];

	_value.signed_ = value;
	_typeEncoding = @encode(intptr_t);

	return self;
}

- (instancetype)initWithUIntPtr: (uintptr_t)value
{
	self = [super init];

	_value.unsigned_ = value;
	_typeEncoding = @encode(uintptr_t);

	return self;
}

- (instancetype)initWithFloat: (float)value
{
	self = [super init];

	_value.float_ = value;
	_typeEncoding = @encode(float);

	return self;
}

- (instancetype)initWithDouble: (double)value
{
	self = [super init];

	_value.float_ = value;
	_typeEncoding = @encode(double);

	return self;
}

- (instancetype)initWithSerialization: (OFXMLElement *)element
{
	self = [super init];

	@try {
		void *pool = objc_autoreleasePoolPush();
		OFString *typeString;

		if (![element.name isEqual: @"OFNumber"] ||
		    ![element.namespace isEqual: OFSerializationNS])
			@throw [OFInvalidArgumentException exception];

		typeString = [element attributeForName: @"type"].stringValue;

		if ([typeString isEqual: @"bool"]) {
			OFString *stringValue = element.stringValue;
			if ([stringValue isEqual: @"true"])
				self = [self initWithBool: true];
			else if ([stringValue isEqual: @"false"])
				self = [self initWithBool: false];
			else
				@throw [OFInvalidArgumentException exception];
		} else if ([typeString isEqual: @"float"]) {
			unsigned long long value =
			    [element unsignedLongLongValueWithBase: 16];

			if (value > UINT64_MAX)
				@throw [OFOutOfRangeException exception];

			self = [self initWithDouble: OFFromBigEndianDouble(
			    OFRawUInt64ToDouble(OFToBigEndian64(value)))];
		} else if ([typeString isEqual: @"signed"])
			self = [self initWithLongLong: element.longLongValue];
		else if ([typeString isEqual: @"unsigned"])
			self = [self initWithUnsignedLongLong:
			    element.unsignedLongLongValue];
		else
			@throw [OFInvalidArgumentException exception];

		objc_autoreleasePoolPop(pool);
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (const char *)objCType
{
	return _typeEncoding;
}

- (void)getValue: (void *)value size: (size_t)size
{
	switch (*self.objCType) {
#define CASE(enc, type, property)					\
	case enc: {							\
		type tmp = (type)self.property;				\
									\
		if (size != sizeof(type))				\
			@throw [OFOutOfRangeException exception];	\
									\
		memcpy(value, &tmp, size);				\
		break;							\
	}
	CASE('B', bool, unsignedLongLongValue)
	CASE('c', signed char, longLongValue)
	CASE('s', short, longLongValue)
	CASE('i', int, longLongValue)
	CASE('l', long, longLongValue)
	CASE('q', long long, longLongValue)
	CASE('C', unsigned char, unsignedLongLongValue)
	CASE('S', unsigned short, unsignedLongLongValue)
	CASE('I', unsigned int, unsignedLongLongValue)
	CASE('L', unsigned long, unsignedLongLongValue)
	CASE('Q', unsigned long long, unsignedLongLongValue)
	CASE('f', float, doubleValue)
	CASE('d', double, doubleValue)
#undef CASE
	default:
		@throw [OFInvalidFormatException exception];
	}
}

- (long long)longLongValue
{
	if (isFloat(self))
		return _value.float_;
	else if (isSigned(self))
		return _value.signed_;
	else if (isUnsigned(self))
		return _value.unsigned_;
	else
		@throw [OFInvalidFormatException exception];

}

- (unsigned long long)unsignedLongLongValue
{
	if (isFloat(self))
		return _value.float_;
	else if (isSigned(self))
		return _value.signed_;
	else if (isUnsigned(self))
		return _value.unsigned_;
	else
		@throw [OFInvalidFormatException exception];
}

- (double)doubleValue
{
	if (isFloat(self))
		return _value.float_;
	else if (isSigned(self))
		return _value.signed_;
	else if (isUnsigned(self))
		return _value.unsigned_;
	else
		@throw [OFInvalidFormatException exception];
}

- (bool)boolValue
{
	return (bool)self.unsignedLongLongValue;
}








<
<
<
<
<
<
<
<
<
<
<


<
|
<
<
<
<




<
<
<
|
<
<




<
|
<
<
<
<




<
|
<
<
<
<




<
|
<
<
<
<




<
<
<
|
<
<




<
|
<
<
<
<




<
<
<
|
<
<




<
<
<
|
<
<




<
<
<
|
|
<
|
<


<
|
<
|
|
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<


<
|
<
<
<
<




<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
|
<
<

<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<


<
<
<
<
<
<
<
<
>




|
<
<
<
<
<
<
<




|
<
<
<
<
<
<
<







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
}

+ (instancetype)numberWithDouble: (double)value
{
	return [[[self alloc] initWithDouble: value] autorelease];
}












- (instancetype)initWithBool: (bool)value
{

	return [self initWithBytes: &value objCType: @encode(bool)];




}

- (instancetype)initWithChar: (signed char)value
{



	return [self initWithBytes: &value objCType: @encode(signed char)];


}

- (instancetype)initWithShort: (short)value
{

	return [self initWithBytes: &value objCType: @encode(short)];




}

- (instancetype)initWithInt: (int)value
{

	return [self initWithBytes: &value objCType: @encode(int)];




}

- (instancetype)initWithLong: (long)value
{

	return [self initWithBytes: &value objCType: @encode(long)];




}

- (instancetype)initWithLongLong: (long long)value
{



	return [self initWithBytes: &value objCType: @encode(long long)];


}

- (instancetype)initWithUnsignedChar: (unsigned char)value
{

	return [self initWithBytes: &value objCType: @encode(unsigned char)];




}

- (instancetype)initWithUnsignedShort: (unsigned short)value
{



	return [self initWithBytes: &value objCType: @encode(unsigned short)];


}

- (instancetype)initWithUnsignedInt: (unsigned int)value
{



	return [self initWithBytes: &value objCType: @encode(unsigned int)];


}

- (instancetype)initWithUnsignedLong: (unsigned long)value
{



	return [self initWithBytes: &value objCType: @encode(unsigned long)];
}



- (instancetype)initWithUnsignedLongLong: (unsigned long long)value
{

	return [self initWithBytes: &value

			  objCType: @encode(unsigned long long)];
}

































- (instancetype)initWithFloat: (float)value
{

	return [self initWithBytes: &value objCType: @encode(float)];




}

- (instancetype)initWithDouble: (double)value
{

























	return [self initWithBytes: &value objCType: @encode(double)];







}



























































- (long long)longLongValue
{








	OF_UNRECOGNIZED_SELECTOR
}

- (unsigned long long)unsignedLongLongValue
{
	OF_UNRECOGNIZED_SELECTOR







}

- (double)doubleValue
{
	OF_UNRECOGNIZED_SELECTOR







}

- (bool)boolValue
{
	return (bool)self.unsignedLongLongValue;
}

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
- (OFString *)description
{
	return [self stringValue];
}

- (OFString *)stringValue
{
	if (*self.objCType == 'B')
		return (self.boolValue ? @"true" : @"false");
	if (isFloat(self))
		return [OFString stringWithFormat: @"%g", self.doubleValue];
	if (isSigned(self))
		return [OFString stringWithFormat: @"%lld", self.longLongValue];
	if (isUnsigned(self))
		return [OFString stringWithFormat: @"%llu",
						   self.unsignedLongLongValue];

	@throw [OFInvalidFormatException exception];
}

- (OFXMLElement *)XMLElementBySerializing
{
	void *pool = objc_autoreleasePoolPush();
	OFXMLElement *element;

	element = [OFXMLElement elementWithName: @"OFNumber"
				      namespace: OFSerializationNS
				    stringValue: self.description];

	if (*self.objCType == 'B')
		[element addAttributeWithName: @"type" stringValue: @"bool"];
	else if (isFloat(self)) {
		[element addAttributeWithName: @"type" stringValue: @"float"];
		element.stringValue = [OFString
		    stringWithFormat: @"%016" PRIx64,
		    OFFromBigEndian64(OFDoubleToRawUInt64(OFToBigEndianDouble(
		    self.doubleValue)))];
	} else if (isSigned(self))
		[element addAttributeWithName: @"type" stringValue: @"signed"];
	else if (isUnsigned(self))
		[element addAttributeWithName: @"type"
				  stringValue: @"unsigned"];
	else
		@throw [OFInvalidFormatException exception];

	[element retain];

	objc_autoreleasePoolPop(pool);

	return [element autorelease];
}

- (OFString *)JSONRepresentation
{
	return [self of_JSONRepresentationWithOptions: 0 depth: 0];
}

- (OFString *)JSONRepresentationWithOptions:
    (OFJSONRepresentationOptions)options
{
	return [self of_JSONRepresentationWithOptions: options depth: 0];
}

- (OFString *)
    of_JSONRepresentationWithOptions: (OFJSONRepresentationOptions)options
			       depth: (size_t)depth
{
	double doubleValue;

	if (*self.objCType == 'B')
		return (self.boolValue ? @"true" : @"false");

	doubleValue = self.doubleValue;
	if (isinf(doubleValue)) {
		if (options & OFJSONRepresentationOptionJSON5) {
			if (doubleValue > 0)
				return @"Infinity";
			else
				return @"-Infinity";
		} else
			@throw [OFInvalidArgumentException exception];
	}

	return self.description;
}

- (OFData *)messagePackRepresentation
{
	OFMutableData *data;
	const char *typeEncoding = self.objCType;




	if (*typeEncoding == 'B') {
		uint8_t type = (self.boolValue ? 0xC3 : 0xC2);
		data = [OFMutableData dataWithItems: &type count: 1];
	} else if (*typeEncoding == 'f') {
		uint8_t type = 0xCA;
		float tmp = OFToBigEndianFloat(self.floatValue);







|












<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

















|




















>
>
>







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
- (OFString *)description
{
	return [self stringValue];
}

- (OFString *)stringValue
{
	if (self.objCType[0] == 'B' && self.objCType[1] == '\0')
		return (self.boolValue ? @"true" : @"false");
	if (isFloat(self))
		return [OFString stringWithFormat: @"%g", self.doubleValue];
	if (isSigned(self))
		return [OFString stringWithFormat: @"%lld", self.longLongValue];
	if (isUnsigned(self))
		return [OFString stringWithFormat: @"%llu",
						   self.unsignedLongLongValue];

	@throw [OFInvalidFormatException exception];
}

































- (OFString *)JSONRepresentation
{
	return [self of_JSONRepresentationWithOptions: 0 depth: 0];
}

- (OFString *)JSONRepresentationWithOptions:
    (OFJSONRepresentationOptions)options
{
	return [self of_JSONRepresentationWithOptions: options depth: 0];
}

- (OFString *)
    of_JSONRepresentationWithOptions: (OFJSONRepresentationOptions)options
			       depth: (size_t)depth
{
	double doubleValue;

	if (self.objCType[0] == 'B' && self.objCType[1] == '\0')
		return (self.boolValue ? @"true" : @"false");

	doubleValue = self.doubleValue;
	if (isinf(doubleValue)) {
		if (options & OFJSONRepresentationOptionJSON5) {
			if (doubleValue > 0)
				return @"Infinity";
			else
				return @"-Infinity";
		} else
			@throw [OFInvalidArgumentException exception];
	}

	return self.description;
}

- (OFData *)messagePackRepresentation
{
	OFMutableData *data;
	const char *typeEncoding = self.objCType;

	if (typeEncoding[0] == '\0' || typeEncoding[1] != '\0')
		@throw [OFInvalidFormatException exception];

	if (*typeEncoding == 'B') {
		uint8_t type = (self.boolValue ? 0xC3 : 0xC2);
		data = [OFMutableData dataWithItems: &type count: 1];
	} else if (*typeEncoding == 'f') {
		uint8_t type = 0xCA;
		float tmp = OFToBigEndianFloat(self.floatValue);

Modified src/OFObject+KeyValueCoding.h from [c0e7932d00] to [28be5bdc22].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFObject+KeyValueCoding.m from [8a83d2aa9e] to [0a5cddfb6b].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Deleted src/OFObject+Serialization.h version [ed19e260ae].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#import "OFObject.h"

OF_ASSUME_NONNULL_BEGIN

@class OFString;

#ifdef __cplusplus
extern "C" {
#endif
extern int _OFObject_Serialization_reference;
#ifdef __cplusplus
}
#endif

@interface OFObject (OFSerialization)
/**
 * @brief The object serialized as a string.
 */
@property (readonly, nonatomic) OFString *stringBySerializing;
@end

OF_ASSUME_NONNULL_END
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<










































































Deleted src/OFObject+Serialization.m version [0bfdaef011].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#include <stdlib.h>

#import "OFObject.h"
#import "OFObject+Serialization.h"
#import "OFSerialization.h"
#import "OFString.h"
#import "OFXMLElement.h"

int _OFObject_Serialization_reference;

@implementation OFObject (Serialization)
- (OFString *)stringBySerializing
{
	void *pool;
	OFXMLElement *element;
	OFXMLElement *root;
	OFString *ret;

	if (![self conformsToProtocol: @protocol(OFSerialization)]) {
		[self doesNotRecognizeSelector: _cmd];
		abort();
	}

	pool = objc_autoreleasePoolPush();
	element = ((id <OFSerialization>)self).XMLElementBySerializing;

	root = [OFXMLElement elementWithName: @"serialization"
				   namespace: OFSerializationNS];
	[root addAttributeWithName: @"version" stringValue: @"1"];
	[root addChild: element];

	ret = [@"<?xml version='1.0' encoding='UTF-8'?>\n"
	    stringByAppendingString: [root XMLStringWithIndentation: 2]];

	[ret retain];

	objc_autoreleasePoolPop(pool);

	return [ret autorelease];
}
@end
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<




















































































































Modified src/OFObject.h from [698abcee0b] to [f6921949eb].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#ifndef OBJFW_OF_OBJECT_H
#define OBJFW_OF_OBJECT_H

#include "objfw-defs.h"

#ifndef __STDC_LIMIT_MACROS
# define __STDC_LIMIT_MACROS
#endif
#ifndef __STDC_CONSTANT_MACROS
# define __STDC_CONSTANT_MACROS
#endif

#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#include <limits.h>

#include "macros.h"

#include "OFOnce.h"

/*
 * Some versions of MinGW require <winsock2.h> to be included before
 * <windows.h>. Do this here to make sure this is always done in the correct
 * order, even if another header includes just <windows.h>.
 */
#ifdef __MINGW32__

|













<
<
<
















|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15



16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
/*
 * Copyright (c) 2008-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 "objfw-defs.h"

#ifndef __STDC_LIMIT_MACROS
# define __STDC_LIMIT_MACROS
#endif
#ifndef __STDC_CONSTANT_MACROS
# define __STDC_CONSTANT_MACROS
#endif

#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#include <limits.h>

#include "macros.h"

#import "OFOnce.h"

/*
 * Some versions of MinGW require <winsock2.h> to be included before
 * <windows.h>. Do this here to make sure this is always done in the correct
 * order, even if another header includes just <windows.h>.
 */
#ifdef __MINGW32__
59
60
61
62
63
64
65











66
67
68
69
70
71
72
	OFOrderedAscending = -1,
	/** Both objects are equal */
	OFOrderedSame = 0,
	/** The left object is bigger than the right */
	OFOrderedDescending = 1
} OFComparisonResult;












#ifdef OF_HAVE_BLOCKS
/**
 * @brief A comparator to compare two objects.
 *
 * @param left The left object
 * @param right The right object
 * @return The order of the objects







>
>
>
>
>
>
>
>
>
>
>







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
	OFOrderedAscending = -1,
	/** Both objects are equal */
	OFOrderedSame = 0,
	/** The left object is bigger than the right */
	OFOrderedDescending = 1
} OFComparisonResult;

/**
 * @brief A function to compare two objects.
 *
 * @param left The left object
 * @param right The right object
 * @param context Context passed along for comparing
 * @return The order of the objects
 */
typedef OFComparisonResult (*OFCompareFunction)(id _Nonnull left,
    id _Nonnull right, void *_Nullable context);

#ifdef OF_HAVE_BLOCKS
/**
 * @brief A comparator to compare two objects.
 *
 * @param left The left object
 * @param right The right object
 * @return The order of the objects
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
} OFByteOrder;

/**
 * @struct OFRange OFObject.h ObjFW/OFObject.h
 *
 * @brief A range.
 */
typedef struct OF_BOXABLE {
	/** The start of the range */
	size_t location;
	/** The length of the range */
	size_t length;
} OFRange;

/**







|







99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
} OFByteOrder;

/**
 * @struct OFRange OFObject.h ObjFW/OFObject.h
 *
 * @brief A range.
 */
typedef struct OF_BOXABLE OFRange {
	/** The start of the range */
	size_t location;
	/** The length of the range */
	size_t length;
} OFRange;

/**
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
 * @brief A time interval in seconds.
 */
typedef double OFTimeInterval;

/**
 * @struct OFPoint OFObject.h ObjFW/OFObject.h
 *
 * @brief A point.
 */
typedef struct OF_BOXABLE {
	/** The x coordinate of the point */
	float x;
	/** The y coordinate of the point */
	float y;
} OFPoint;

/**







|

|







148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
 * @brief A time interval in seconds.
 */
typedef double OFTimeInterval;

/**
 * @struct OFPoint OFObject.h ObjFW/OFObject.h
 *
 * @brief A point in 2D space.
 */
typedef struct OF_BOXABLE OFPoint {
	/** The x coordinate of the point */
	float x;
	/** The y coordinate of the point */
	float y;
} OFPoint;

/**
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
}

/**
 * @struct OFSize OFObject.h ObjFW/OFObject.h
 *
 * @brief A size.
 */
typedef struct OF_BOXABLE {
	/** The width of the size */
	float width;
	/** The height of the size */
	float height;
} OFSize;

/**







|







196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
}

/**
 * @struct OFSize OFObject.h ObjFW/OFObject.h
 *
 * @brief A size.
 */
typedef struct OF_BOXABLE OFSize {
	/** The width of the size */
	float width;
	/** The height of the size */
	float height;
} OFSize;

/**
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
}

/**
 * @struct OFRect OFObject.h ObjFW/OFObject.h
 *
 * @brief A rectangle.
 */
typedef struct OF_BOXABLE {
	/** The point from where the rectangle originates */
	OFPoint origin;
	/** The size of the rectangle */
	OFSize size;
} OFRect;

/**







|







242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
}

/**
 * @struct OFRect OFObject.h ObjFW/OFObject.h
 *
 * @brief A rectangle.
 */
typedef struct OF_BOXABLE OFRect {
	/** The point from where the rectangle originates */
	OFPoint origin;
	/** The size of the rectangle */
	OFSize size;
} OFRect;

/**
277
278
279
280
281
282
283














































































































284
285
286
287
288
289
290
{
	if (!OFEqualPoints(rect1.origin, rect2.origin))
		return false;

	if (!OFEqualSizes(rect1.size, rect2.size))
		return false;















































































































	return true;
}

/**
 * @brief Adds the specified byte to the hash.
 *
 * @param hash A pointer to a hash to add the byte to







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
{
	if (!OFEqualPoints(rect1.origin, rect2.origin))
		return false;

	if (!OFEqualSizes(rect1.size, rect2.size))
		return false;

	return true;
}

/**
 * @struct OFVector3D OFObject.h ObjFW/OFObject.h
 *
 * @brief A vector in 3D space.
 */
typedef struct OF_BOXABLE OFVector3D {
	/** The x coordinate of the vector */
	float x;
	/** The y coordinate of the vector */
	float y;
	/** The z coordinate of the vector */
	float z;
} OFVector3D;

/**
 * @brief Creates a new OFVector3D.
 *
 * @param x The x coordinate of the vector
 * @param y The x coordinate of the vector
 * @param z The z coordinate of the vector
 * @return An OFVector3D with the specified coordinates
 */
static OF_INLINE OFVector3D OF_CONST_FUNC
OFMakeVector3D(float x, float y, float z)
{
	OFVector3D vector = { x, y, z };

	return vector;
}

/**
 * @brief Returns whether the two vectors are equal.
 *
 * @param vector1 The first vector for the comparison
 * @param vector2 The second vectors for the comparison
 * @return Whether the two vectors are equal
 */
static OF_INLINE bool
OFEqualVectors3D(OFVector3D vector1, OFVector3D vector2)
{
	if (vector1.x != vector2.x)
		return false;

	if (vector1.y != vector2.y)
		return false;

	if (vector1.z != vector2.z)
		return false;

	return true;
}

/**
 * @struct OFVector4D OFObject.h ObjFW/OFObject.h
 *
 * @brief A vector in 4D space.
 */
typedef struct OF_ALIGN(16) OF_BOXABLE OFVector4D {
	/** The x coordinate of the vector */
	float x;
	/** The y coordinate of the vector */
	float y;
	/** The z coordinate of the vector */
	float z;
	/** The w coordinate of the vector */
	float w;
} OFVector4D;

/**
 * @brief Creates a new OFVector4D.
 *
 * @param x The x coordinate of the vector
 * @param y The x coordinate of the vector
 * @param z The z coordinate of the vector
 * @param w The w coordinate of the vector
 * @return An OFVector4D with the specified coordinates
 */
static OF_INLINE OFVector4D OF_CONST_FUNC
OFMakeVector4D(float x, float y, float z, float w)
{
	OFVector4D vector = { x, y, z, w };

	return vector;
}

/**
 * @brief Returns whether the two vectors are equal.
 *
 * @param vector1 The first vector for the comparison
 * @param vector2 The second vectors for the comparison
 * @return Whether the two vectors are equal
 */
static OF_INLINE bool
OFEqualVectors4D(OFVector4D vector1, OFVector4D vector2)
{
	if (vector1.x != vector2.x)
		return false;

	if (vector1.y != vector2.y)
		return false;

	if (vector1.z != vector2.z)
		return false;

	if (vector1.w != vector2.w)
		return false;

	return true;
}

/**
 * @brief Adds the specified byte to the hash.
 *
 * @param hash A pointer to a hash to add the byte to
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
	tmp += tmp << 15;

	*hash = tmp;
}

static const size_t OFNotFound = SIZE_MAX;

#ifdef __OBJC__
@class OFMethodSignature;
@class OFString;
@class OFThread;

/**
 * @protocol OFObject OFObject.h ObjFW/OFObject.h
 *







<







450
451
452
453
454
455
456

457
458
459
460
461
462
463
	tmp += tmp << 15;

	*hash = tmp;
}

static const size_t OFNotFound = SIZE_MAX;


@class OFMethodSignature;
@class OFString;
@class OFThread;

/**
 * @protocol OFObject OFObject.h ObjFW/OFObject.h
 *
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
/**
 * @brief Retain a weak reference to this object.
 *
 * @return Whether a weak reference to this object has been retained
 */
- (bool)retainWeakReference;
@end
#endif

/**
 * @class OFObject OFObject.h ObjFW/OFObject.h
 *
 * @brief The root class for all other classes inside ObjFW.
 */
#ifdef __OBJC__
OF_ROOT_CLASS
@interface OFObject <OFObject>
{
@private
# ifndef __clang_analyzer__
	Class _isa;
# else
	Class _isa __attribute__((__unused__));
# endif
}

# ifdef OF_HAVE_CLASS_PROPERTIES
#  ifndef __cplusplus
@property (class, readonly, nonatomic) Class class;
#  else
@property (class, readonly, nonatomic, getter=class) Class class_;
#  endif
@property (class, readonly, nonatomic) OFString *className;
@property (class, readonly, nullable, nonatomic) Class superclass;
@property (class, readonly, nonatomic) OFString *description;
# endif

# ifndef __cplusplus
@property (readonly, nonatomic) Class class;
# else
@property (readonly, nonatomic, getter=class) Class class_;
#endif
@property OF_NULLABLE_PROPERTY (readonly, nonatomic) Class superclass;
@property (readonly, nonatomic) unsigned long hash;
@property (readonly, nonatomic) unsigned int retainCount;
@property (readonly, nonatomic) bool isProxy;
@property (readonly, nonatomic) bool allowsWeakReference;







<






<




|

|

|


|
|

|

|



|

|

|







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
/**
 * @brief Retain a weak reference to this object.
 *
 * @return Whether a weak reference to this object has been retained
 */
- (bool)retainWeakReference;
@end


/**
 * @class OFObject OFObject.h ObjFW/OFObject.h
 *
 * @brief The root class for all other classes inside ObjFW.
 */

OF_ROOT_CLASS
@interface OFObject <OFObject>
{
@private
#ifndef __clang_analyzer__
	Class _isa;
#else
	Class _isa __attribute__((__unused__));
#endif
}

#ifdef OF_HAVE_CLASS_PROPERTIES
# ifndef __cplusplus
@property (class, readonly, nonatomic) Class class;
# else
@property (class, readonly, nonatomic, getter=class) Class class_;
# endif
@property (class, readonly, nonatomic) OFString *className;
@property (class, readonly, nullable, nonatomic) Class superclass;
@property (class, readonly, nonatomic) OFString *description;
#endif

#ifndef __cplusplus
@property (readonly, nonatomic) Class class;
#else
@property (readonly, nonatomic, getter=class) Class class_;
#endif
@property OF_NULLABLE_PROPERTY (readonly, nonatomic) Class superclass;
@property (readonly, nonatomic) unsigned long hash;
@property (readonly, nonatomic) unsigned int retainCount;
@property (readonly, nonatomic) bool isProxy;
@property (readonly, nonatomic) bool allowsWeakReference;
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
 * @return The allocated object
 * @throw OFAllocFailedException There was not enough memory to allocate the
 *				 object
 * @throw OFInitializationFailedException The instance could not be constructed
 */
+ (instancetype)alloc;

/**
 * @brief Calls @ref alloc on `self` and then `init` on the returned object.
 *
 * @return An allocated and initialized object
 */
+ (instancetype)new;

/**
 * @brief Returns the class.
 *
 * @return The class
 */
+ (Class)class;








<
<
<
<
<
<
<







770
771
772
773
774
775
776







777
778
779
780
781
782
783
 * @return The allocated object
 * @throw OFAllocFailedException There was not enough memory to allocate the
 *				 object
 * @throw OFInitializationFailedException The instance could not be constructed
 */
+ (instancetype)alloc;








/**
 * @brief Returns the class.
 *
 * @return The class
 */
+ (Class)class;

940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
- (void)performSelector: (SEL)selector
	     withObject: (nullable id)object1
	     withObject: (nullable id)object2
	     withObject: (nullable id)object3
	     withObject: (nullable id)object4
	     afterDelay: (OFTimeInterval)delay;

# ifdef OF_HAVE_THREADS
/**
 * @brief Performs the specified selector on the specified thread.
 *
 * @param selector The selector to perform
 * @param thread The thread on which to perform the selector
 * @param waitUntilDone Whether to wait until the perform finished
 */







|







1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
- (void)performSelector: (SEL)selector
	     withObject: (nullable id)object1
	     withObject: (nullable id)object2
	     withObject: (nullable id)object3
	     withObject: (nullable id)object4
	     afterDelay: (OFTimeInterval)delay;

#ifdef OF_HAVE_THREADS
/**
 * @brief Performs the specified selector on the specified thread.
 *
 * @param selector The selector to perform
 * @param thread The thread on which to perform the selector
 * @param waitUntilDone Whether to wait until the perform finished
 */
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
- (void)performSelector: (SEL)selector
	       onThread: (OFThread *)thread
	     withObject: (nullable id)object1
	     withObject: (nullable id)object2
	     withObject: (nullable id)object3
	     withObject: (nullable id)object4
	     afterDelay: (OFTimeInterval)delay;
# endif

/**
 * @brief This method is called when @ref resolveClassMethod: or
 *	  @ref resolveInstanceMethod: returned false. It should return a target
 *	  to which the message should be forwarded.
 *
 * @note When the message should not be forwarded, you should not return `nil`,







|







1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
- (void)performSelector: (SEL)selector
	       onThread: (OFThread *)thread
	     withObject: (nullable id)object1
	     withObject: (nullable id)object2
	     withObject: (nullable id)object3
	     withObject: (nullable id)object4
	     afterDelay: (OFTimeInterval)delay;
#endif

/**
 * @brief This method is called when @ref resolveClassMethod: or
 *	  @ref resolveInstanceMethod: returned false. It should return a target
 *	  to which the message should be forwarded.
 *
 * @note When the message should not be forwarded, you should not return `nil`,
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
 *	    returns!
 *
 * @param selector The selector not understood by the receiver
 * @throw OFNotImplementedException
 */
- (void)doesNotRecognizeSelector: (SEL)selector OF_NO_RETURN;
@end
#else
typedef void OFObject;
#endif

#ifdef __OBJC__
/**
 * @protocol OFCopying OFObject.h ObjFW/OFObject.h
 *
 * @brief A protocol for the creation of copies.
 */
@protocol OFCopying
/**







<
<
<

<







1332
1333
1334
1335
1336
1337
1338



1339

1340
1341
1342
1343
1344
1345
1346
 *	    returns!
 *
 * @param selector The selector not understood by the receiver
 * @throw OFNotImplementedException
 */
- (void)doesNotRecognizeSelector: (SEL)selector OF_NO_RETURN;
@end





/**
 * @protocol OFCopying OFObject.h ObjFW/OFObject.h
 *
 * @brief A protocol for the creation of copies.
 */
@protocol OFCopying
/**
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
 * @brief Compares the object to another object.
 *
 * @param object An object to compare the object to
 * @return The result of the comparison
 */
- (OFComparisonResult)compare: (id <OFComparing>)object;
@end
#endif

#ifdef __cplusplus
extern "C" {
#endif
/**
 * @brief Allocates memory for the specified number of items of the specified
 *	  size.







<







1384
1385
1386
1387
1388
1389
1390

1391
1392
1393
1394
1395
1396
1397
 * @brief Compares the object to another object.
 *
 * @param object An object to compare the object to
 * @return The result of the comparison
 */
- (OFComparisonResult)compare: (id <OFComparing>)object;
@end


#ifdef __cplusplus
extern "C" {
#endif
/**
 * @brief Allocates memory for the specified number of items of the specified
 *	  size.
1361
1362
1363
1364
1365
1366
1367







1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
extern void *_Nullable objc_destructInstance(id _Nullable object);
# endif
#endif
extern id OFAllocObject(Class class_, size_t extraSize, size_t extraAlignment,
    void *_Nullable *_Nullable extra);
extern void OF_NO_RETURN_FUNC OFMethodNotFound(id self, SEL _cmd);








/**
 * @brief Returns 16 bit or non-cryptographical randomness.
 *
 * @return 16 bit or non-cryptographical randomness
 */
extern uint16_t OFRandom16(void);

/**
 * @brief Returns 32 bit or non-cryptographical randomness.
 *
 * @return 32 bit or non-cryptographical randomness
 */
extern uint32_t OFRandom32(void);

/**
 * @brief Returns 64 bit or non-cryptographical randomness.
 *
 * @return 64 bit or non-cryptographical randomness
 */
extern uint64_t OFRandom64(void);

/**
 * @brief Initializes the specified hash.
 *
 * @param hash A pointer to the hash to initialize
 */
extern void OFHashInit(unsigned long *_Nonnull hash);
#ifdef __cplusplus
}
#endif

OF_ASSUME_NONNULL_END

#include "OFBlock.h"

#ifdef __OBJC__
# import "OFObject+KeyValueCoding.h"
# import "OFObject+Serialization.h"
#endif

#endif







>
>
>
>
>
>
>




















<
<
<
<
<
<
<






|
<
<
|
<
<
<
<
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497







1498
1499
1500
1501
1502
1503
1504


1505




extern void *_Nullable objc_destructInstance(id _Nullable object);
# endif
#endif
extern id OFAllocObject(Class class_, size_t extraSize, size_t extraAlignment,
    void *_Nullable *_Nullable extra);
extern void OF_NO_RETURN_FUNC OFMethodNotFound(id self, SEL _cmd);

/**
 * @brief Initializes the specified hash.
 *
 * @param hash A pointer to the hash to initialize
 */
extern void OFHashInit(unsigned long *_Nonnull hash);

/**
 * @brief Returns 16 bit or non-cryptographical randomness.
 *
 * @return 16 bit or non-cryptographical randomness
 */
extern uint16_t OFRandom16(void);

/**
 * @brief Returns 32 bit or non-cryptographical randomness.
 *
 * @return 32 bit or non-cryptographical randomness
 */
extern uint32_t OFRandom32(void);

/**
 * @brief Returns 64 bit or non-cryptographical randomness.
 *
 * @return 64 bit or non-cryptographical randomness
 */
extern uint64_t OFRandom64(void);







#ifdef __cplusplus
}
#endif

OF_ASSUME_NONNULL_END

#import "OFBlock.h"


#import "OFObject+KeyValueCoding.h"




Modified src/OFObject.m from [0477c3fb09] to [70b0e206af].

1
2
3
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
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "unistd_wrapper.h"

#include <assert.h>

#ifdef OF_APPLE_RUNTIME
# include <dlfcn.h>
#endif

#ifdef HAVE_GETRANDOM
# include <sys/random.h>
#endif

#import "OFObject.h"
#import "OFArray.h"
#ifdef OF_HAVE_ATOMIC_OPS
# import "OFAtomic.h"
#endif
#import "OFLocale.h"
#import "OFMethodSignature.h"
#import "OFRunLoop.h"
#if !defined(OF_HAVE_ATOMIC_OPS) && defined(OF_HAVE_THREADS)
# import "OFPlainMutex.h"	/* For OFSpinlock */
#endif

#import "OFString.h"
#import "OFThread.h"
#import "OFTimer.h"
#import "OFValue.h"

#import "OFAllocFailedException.h"
#import "OFEnumerationMutationException.h"

|




















<
<



















>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22


23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
/*
 * Copyright (c) 2008-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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "unistd_wrapper.h"



#ifdef OF_APPLE_RUNTIME
# include <dlfcn.h>
#endif

#ifdef HAVE_GETRANDOM
# include <sys/random.h>
#endif

#import "OFObject.h"
#import "OFArray.h"
#ifdef OF_HAVE_ATOMIC_OPS
# import "OFAtomic.h"
#endif
#import "OFLocale.h"
#import "OFMethodSignature.h"
#import "OFRunLoop.h"
#if !defined(OF_HAVE_ATOMIC_OPS) && defined(OF_HAVE_THREADS)
# import "OFPlainMutex.h"	/* For OFSpinlock */
#endif
#import "OFStdIOStream.h"
#import "OFString.h"
#import "OFThread.h"
#import "OFTimer.h"
#import "OFValue.h"

#import "OFAllocFailedException.h"
#import "OFEnumerationMutationException.h"
61
62
63
64
65
66
67

68

69
70
71
72
73
74
75
#endif

#ifdef OF_WINDOWS
# include <windows.h>
#endif

#ifdef OF_AMIGAOS

# include <proto/exec.h>

#endif

#ifdef OF_APPLE_RUNTIME
extern id _Nullable _objc_rootAutorelease(id _Nullable object);
#endif
#if defined(OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR)
extern id OFForward(id, SEL, ...);







>

>







60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
#endif

#ifdef OF_WINDOWS
# include <windows.h>
#endif

#ifdef OF_AMIGAOS
# define Class IntuitionClass
# include <proto/exec.h>
# undef Class
#endif

#ifdef OF_APPLE_RUNTIME
extern id _Nullable _objc_rootAutorelease(id _Nullable object);
#endif
#if defined(OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR)
extern id OFForward(id, SEL, ...);
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
	return method_getTypeEncoding(method);
}

#if !defined(OF_APPLE_RUNTIME) || defined(__OBJC2__)
static void
uncaughtExceptionHandler(id exception)
{
	OFString *description = [exception description];
	OFArray OF_GENERIC(OFValue *) *stackTraceAddresses = nil;
	OFArray OF_GENERIC(OFString *) *stackTraceSymbols = nil;
	OFStringEncoding encoding = [OFLocale encoding];

	fprintf(stderr, "\nRuntime error: Unhandled exception:\n%s\n",
	    [description cStringWithEncoding: encoding]);

	if ([exception respondsToSelector: @selector(stackTraceAddresses)])
		stackTraceAddresses = [exception stackTraceAddresses];

	if (stackTraceAddresses != nil) {
		size_t count = stackTraceAddresses.count;

		if ([exception respondsToSelector:
		    @selector(stackTraceSymbols)])
			stackTraceSymbols = [exception stackTraceSymbols];

		if (stackTraceSymbols.count != count)
			stackTraceSymbols = nil;


		fputs("\nStack trace:\n", stderr);

		if (stackTraceSymbols != nil) {
			for (size_t i = 0; i < count; i++) {
				void *address = [[stackTraceAddresses
				    objectAtIndex: i] pointerValue];
				const char *symbol = [[stackTraceSymbols
				    objectAtIndex: i]
				    cStringWithEncoding: encoding];

				fprintf(stderr, "  %p  %s\n", address, symbol);
			}
		} else {
			for (size_t i = 0; i < count; i++) {
				void *address = [[stackTraceAddresses
				    objectAtIndex: i] pointerValue];

				fprintf(stderr, "  %p\n", address);
			}
		}

		fputs("\n", stderr);
	}

	abort();
}
#endif

static void







<




|
|














>
|









|






|


<
<







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
	return method_getTypeEncoding(method);
}

#if !defined(OF_APPLE_RUNTIME) || defined(__OBJC2__)
static void
uncaughtExceptionHandler(id exception)
{

	OFArray OF_GENERIC(OFValue *) *stackTraceAddresses = nil;
	OFArray OF_GENERIC(OFString *) *stackTraceSymbols = nil;
	OFStringEncoding encoding = [OFLocale encoding];

	OFLog(@"Runtime error: Unhandled exception:");
	OFLog(@"%@", exception);

	if ([exception respondsToSelector: @selector(stackTraceAddresses)])
		stackTraceAddresses = [exception stackTraceAddresses];

	if (stackTraceAddresses != nil) {
		size_t count = stackTraceAddresses.count;

		if ([exception respondsToSelector:
		    @selector(stackTraceSymbols)])
			stackTraceSymbols = [exception stackTraceSymbols];

		if (stackTraceSymbols.count != count)
			stackTraceSymbols = nil;

		OFLog(@"");
		OFLog(@"Stack trace:");

		if (stackTraceSymbols != nil) {
			for (size_t i = 0; i < count; i++) {
				void *address = [[stackTraceAddresses
				    objectAtIndex: i] pointerValue];
				const char *symbol = [[stackTraceSymbols
				    objectAtIndex: i]
				    cStringWithEncoding: encoding];

				OFLog(@"  %p  %s", address, symbol);
			}
		} else {
			for (size_t i = 0; i < count; i++) {
				void *address = [[stackTraceAddresses
				    objectAtIndex: i] pointerValue];

				OFLog(@"  %p", address);
			}
		}


	}

	abort();
}
#endif

static void
333
334
335
336
337
338
339
340
341

342
343
344
345
346

347
348
349
350
351
352
353
354
{
	OFObject *instance;
	size_t instanceSize;

	instanceSize = class_getInstanceSize(class);

	if OF_UNLIKELY (extraAlignment > 1)
		extraAlignment = ((instanceSize + extraAlignment - 1) &
		    ~(extraAlignment - 1)) - extraAlignment;


	instance = calloc(1, PRE_IVARS_ALIGN + instanceSize +
	    extraAlignment + extraSize);

	if OF_UNLIKELY (instance == nil) {

		allocFailedException.isa = [OFAllocFailedException class];
		@throw (id)&allocFailedException;
	}

	((struct PreIvars *)instance)->retainCount = 1;

#if !defined(OF_HAVE_ATOMIC_OPS) && !defined(OF_AMIGAOS)
	if OF_UNLIKELY (OFSpinlockNew(







|
|
>





>
|







332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
{
	OFObject *instance;
	size_t instanceSize;

	instanceSize = class_getInstanceSize(class);

	if OF_UNLIKELY (extraAlignment > 1)
		extraAlignment = OFRoundUpToPowerOf2(extraAlignment,
		    PRE_IVARS_ALIGN + instanceSize) -
		    PRE_IVARS_ALIGN - instanceSize;

	instance = calloc(1, PRE_IVARS_ALIGN + instanceSize +
	    extraAlignment + extraSize);

	if OF_UNLIKELY (instance == nil) {
		object_setClass((id)&allocFailedException,
		    [OFAllocFailedException class]);
		@throw (id)&allocFailedException;
	}

	((struct PreIvars *)instance)->retainCount = 1;

#if !defined(OF_HAVE_ATOMIC_OPS) && !defined(OF_AMIGAOS)
	if OF_UNLIKELY (OFSpinlockNew(
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
}

/* References for static linking */
void
_references_to_categories_of_OFObject(void)
{
	_OFObject_KeyValueCoding_reference = 1;
	_OFObject_Serialization_reference = 1;
}

@implementation OFObject
+ (void)load
{
#if !defined(OF_APPLE_RUNTIME) || defined(__OBJC2__)
	objc_setUncaughtExceptionHandler(uncaughtExceptionHandler);







<







385
386
387
388
389
390
391

392
393
394
395
396
397
398
}

/* References for static linking */
void
_references_to_categories_of_OFObject(void)
{
	_OFObject_KeyValueCoding_reference = 1;

}

@implementation OFObject
+ (void)load
{
#if !defined(OF_APPLE_RUNTIME) || defined(__OBJC2__)
	objc_setUncaughtExceptionHandler(uncaughtExceptionHandler);
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
}

+ (instancetype)alloc
{
	return OFAllocObject(self, 0, 0, NULL);
}

+ (instancetype)new
{
	return [[self alloc] init];
}

+ (Class)class
{
	return self;
}

+ (OFString *)className
{







<
<
<
<
<







436
437
438
439
440
441
442





443
444
445
446
447
448
449
}

+ (instancetype)alloc
{
	return OFAllocObject(self, 0, 0, NULL);
}






+ (Class)class
{
	return self;
}

+ (OFString *)className
{
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
+ (bool)instancesRespondToSelector: (SEL)selector
{
	return class_respondsToSelector(self, selector);
}

+ (bool)conformsToProtocol: (Protocol *)protocol
{
	Class c;

	for (c = self; c != Nil; c = class_getSuperclass(c))
		if (class_conformsToProtocol(c, protocol))
			return true;

	return false;
}

+ (IMP)instanceMethodForSelector: (SEL)selector
{







<
|
<
|







468
469
470
471
472
473
474

475

476
477
478
479
480
481
482
483
+ (bool)instancesRespondToSelector: (SEL)selector
{
	return class_respondsToSelector(self, selector);
}

+ (bool)conformsToProtocol: (Protocol *)protocol
{

	for (Class iter = self; iter != Nil; iter = class_getSuperclass(iter))

		if (class_conformsToProtocol(iter, protocol))
			return true;

	return false;
}

+ (IMP)instanceMethodForSelector: (SEL)selector
{
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
	}

	[self inheritMethodsFromClass: superclass];
}

+ (bool)resolveClassMethod: (SEL)selector
{
	return NO;
}

+ (bool)resolveInstanceMethod: (SEL)selector
{
	return NO;
}

- (instancetype)init
{
	return self;
}








|




|







571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
	}

	[self inheritMethodsFromClass: superclass];
}

+ (bool)resolveClassMethod: (SEL)selector
{
	return false;
}

+ (bool)resolveInstanceMethod: (SEL)selector
{
	return false;
}

- (instancetype)init
{
	return self;
}

1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
#endif

	return self;
}

- (unsigned int)retainCount
{
	assert(PRE_IVARS->retainCount >= 0);
	return PRE_IVARS->retainCount;
}

- (void)release
{
#if defined(OF_HAVE_ATOMIC_OPS)
	OFReleaseMemoryBarrier();







|







1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
#endif

	return self;
}

- (unsigned int)retainCount
{
	OFAssert(PRE_IVARS->retainCount >= 0);
	return PRE_IVARS->retainCount;
}

- (void)release
{
#if defined(OF_HAVE_ATOMIC_OPS)
	OFReleaseMemoryBarrier();

Modified src/OFOnce.h from [fef3956998] to [bf8ec17725].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
27
28
29
30
31
32
33




34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#elif defined(OF_AMIGAOS) || !defined(OF_HAVE_THREADS)
typedef int OFOnceControl;
# define OFOnceControlInitValue 0
#endif

OF_ASSUME_NONNULL_BEGIN





#ifdef __cplusplus
extern "C" {
#endif
/**
 * @brief Executes the specified function exactly once in the application's
 *	  lifetime, even in a multi-threaded environment.
 *
 * @param control An OFOnceControl. This should be a static variable
 *		  preinitialized to `OFOnceControlInitValue`.
 * @param function The function to execute once
 */
extern void OFOnce(OFOnceControl *control, void (*function)(void));
#ifdef __cplusplus
}
#endif

OF_ASSUME_NONNULL_END







>
>
>
>











|





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
#elif defined(OF_AMIGAOS) || !defined(OF_HAVE_THREADS)
typedef int OFOnceControl;
# define OFOnceControlInitValue 0
#endif

OF_ASSUME_NONNULL_BEGIN

/** @file */

typedef void (*OFOnceFunction)(void);

#ifdef __cplusplus
extern "C" {
#endif
/**
 * @brief Executes the specified function exactly once in the application's
 *	  lifetime, even in a multi-threaded environment.
 *
 * @param control An OFOnceControl. This should be a static variable
 *		  preinitialized to `OFOnceControlInitValue`.
 * @param function The function to execute once
 */
extern void OFOnce(OFOnceControl *control, OFOnceFunction function);
#ifdef __cplusplus
}
#endif

OF_ASSUME_NONNULL_END

Modified src/OFOnce.m from [72d5ba7049] to [644a3b7851].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
20
21
22
23
24
25
26

27

28
29
30
31
32
33
34
#import "OFOnce.h"
#if defined(OF_HAVE_THREADS) && defined(OF_HAVE_ATOMIC_OPS)
# import "OFAtomic.h"
# import "OFPlainMutex.h"
#endif

#ifdef OF_AMIGAOS

# include <proto/exec.h>

#endif

void
OFOnce(OFOnceControl *control, void (*function)(void))
{
#if !defined(OF_HAVE_THREADS)
	if (*control == 0) {







>

>







20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#import "OFOnce.h"
#if defined(OF_HAVE_THREADS) && defined(OF_HAVE_ATOMIC_OPS)
# import "OFAtomic.h"
# import "OFPlainMutex.h"
#endif

#ifdef OF_AMIGAOS
# define Class IntuitionClass
# include <proto/exec.h>
# undef Class
#endif

void
OFOnce(OFOnceControl *control, void (*function)(void))
{
#if !defined(OF_HAVE_THREADS)
	if (*control == 0) {

Modified src/OFOptionsParser.h from [14db018626] to [bd62509c33].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFOptionsParser.m from [c0426ac296] to [e6b89648b2].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFPBKDF2.h from [fc763da9ca] to [6171bc59fb].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
/**
 * @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 param The parameters to use
 */
extern void OFPBKDF2(OFPBKDF2Parameters param);
#ifdef __cplusplus
}
#endif

OF_ASSUME_NONNULL_END







|

|





62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
/**
 * @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

Modified src/OFPBKDF2.m from [cca92e4a20] to [fe93b27f28].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFPair.h from [96e09802be] to [fed105f267].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFPair.m from [22c01e92c3] to [400992c36d].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFPlainCondition.h from [fd9b66a9ca] to [04d5d12d8a].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
extern int OFPlainConditionNew(OFPlainCondition *condition);
extern int OFPlainConditionSignal(OFPlainCondition *condition);
extern int OFPlainConditionBroadcast(OFPlainCondition *condition);
extern int OFPlainConditionWait(OFPlainCondition *condition,
    OFPlainMutex *mutex);
extern int OFPlainConditionTimedWait(OFPlainCondition *condition,
    OFPlainMutex *mutex, OFTimeInterval timeout);
#ifdef OF_AMIGAOS
extern int OFPlainConditionWaitOrExecSignal(OFPlainCondition *condition,
    OFPlainMutex *mutex, ULONG *signalMask);
extern int OFPlainConditionTimedWaitOrExecSignal(OFPlainCondition *condition,
    OFPlainMutex *mutex, OFTimeInterval timeout, ULONG *signalMask);
#endif
extern int OFPlainConditionFree(OFPlainCondition *condition);
#ifdef __cplusplus
}
#endif







|









52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
extern int OFPlainConditionNew(OFPlainCondition *condition);
extern int OFPlainConditionSignal(OFPlainCondition *condition);
extern int OFPlainConditionBroadcast(OFPlainCondition *condition);
extern int OFPlainConditionWait(OFPlainCondition *condition,
    OFPlainMutex *mutex);
extern int OFPlainConditionTimedWait(OFPlainCondition *condition,
    OFPlainMutex *mutex, OFTimeInterval timeout);
#if defined(OF_AMIGAOS) || defined(DOXYGEN)
extern int OFPlainConditionWaitOrExecSignal(OFPlainCondition *condition,
    OFPlainMutex *mutex, ULONG *signalMask);
extern int OFPlainConditionTimedWaitOrExecSignal(OFPlainCondition *condition,
    OFPlainMutex *mutex, OFTimeInterval timeout, ULONG *signalMask);
#endif
extern int OFPlainConditionFree(OFPlainCondition *condition);
#ifdef __cplusplus
}
#endif

Modified src/OFPlainCondition.m from [b7456714c7] to [c7059a3826].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFPlainMutex.h from [e51d623af9] to [0ae494272d].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFPlainMutex.m from [0367193fde] to [4cae991e6c].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFPlainThread.h from [312286356e] to [c8f995008d].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include "platform.h"

#if !defined(OF_HAVE_THREADS) || \
    (!defined(OF_HAVE_PTHREADS) && !defined(OF_WINDOWS) && !defined(OF_AMIGAOS))
# error No threads available!
#endif

#import "macros.h"

#if defined(OF_HAVE_PTHREADS)
# include <pthread.h>
typedef pthread_t OFPlainThread;
#elif defined(OF_WINDOWS)
# include <windows.h>
typedef HANDLE OFPlainThread;







|







18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include "platform.h"

#if !defined(OF_HAVE_THREADS) || \
    (!defined(OF_HAVE_PTHREADS) && !defined(OF_WINDOWS) && !defined(OF_AMIGAOS))
# error No threads available!
#endif

#import "OFObject.h"

#if defined(OF_HAVE_PTHREADS)
# include <pthread.h>
typedef pthread_t OFPlainThread;
#elif defined(OF_WINDOWS)
# include <windows.h>
typedef HANDLE OFPlainThread;

Modified src/OFPlainThread.m from [ef8a973be8] to [ea60125ff8].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFPlugin.h from [a9cf165ddb] to [273d4a698a].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFPlugin.m from [dfbf2c9e77] to [bf328ddc1e].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Deleted src/OFPointValue.h version [42acb9db9a].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the 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 "OFValue.h"

OF_ASSUME_NONNULL_BEGIN

@interface OFPointValue: OFValue
{
	OFPoint _point;
}

- (instancetype)initWithPoint: (OFPoint)point;
@end

OF_ASSUME_NONNULL_END
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
























































Deleted src/OFPointValue.m version [d80a9e47ec].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the 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 "OFPointValue.h"
#import "OFMethodSignature.h"
#import "OFString.h"

#import "OFOutOfRangeException.h"

@implementation OFPointValue
@synthesize pointValue = _point;

- (instancetype)initWithPoint: (OFPoint)point
{
	self = [super init];

	_point = point;

	return self;
}

- (const char *)objCType
{
	return @encode(OFPoint);
}

- (void)getValue: (void *)value size: (size_t)size
{
	if (size != sizeof(_point))
		@throw [OFOutOfRangeException exception];

	memcpy(value, &_point, sizeof(_point));
}

- (OFString *)description
{
	return [OFString stringWithFormat:
	    @"<OFValue: OFPoint { %f, %f }>", _point.x, _point.y];
}
@end
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<








































































































Deleted src/OFPointerValue.h version [9280ad762d].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the 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 "OFValue.h"

OF_ASSUME_NONNULL_BEGIN

@interface OFPointerValue: OFValue
{
	void *_pointer;
}

- (instancetype)initWithPointer: (const void *)pointer;
@end

OF_ASSUME_NONNULL_END
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
























































Deleted src/OFPointerValue.m version [0b6a62e87f].

1
2
3
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
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#import "OFPointerValue.h"
#import "OFMethodSignature.h"

#import "OFOutOfRangeException.h"

@implementation OFPointerValue
@synthesize pointerValue = _pointer;

- (instancetype)initWithPointer: (const void *)pointer
{
	self = [super init];

	_pointer = (void *)pointer;

	return self;
}

- (const char *)objCType
{
	return @encode(void *);
}

- (void)getValue: (void *)value size: (size_t)size
{
	if (size != sizeof(_pointer))
		@throw [OFOutOfRangeException exception];

	memcpy(value, &_pointer, sizeof(_pointer));
}

- (id)nonretainedObjectValue
{
	return _pointer;
}
@end
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<




































































































Modified src/OFPollKernelEventObserver.h from [1b31db8247] to [bc38220d7f].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFPollKernelEventObserver.m from [e4119778c6] to [5e31dea6aa].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#define __NO_EXT_QNX

#include "config.h"

#include <assert.h>
#include <errno.h>

#ifdef HAVE_POLL_H
# include <poll.h>
#endif

#import "OFPollKernelEventObserver.h"

|

















<







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

20
21
22
23
24
25
26
/*
 * 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.
 */

#define __NO_EXT_QNX

#include "config.h"


#include <errno.h>

#ifdef HAVE_POLL_H
# include <poll.h>
#endif

#import "OFPollKernelEventObserver.h"
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202

	if (events < 0)
		@throw [OFObserveKernelEventsFailedException
		    exceptionWithObserver: self
				    errNo: errno];

	for (size_t i = 0; i < nFDs; i++) {
		assert(FDs[i].fd <= _maxFD);

		if (FDs[i].revents & POLLIN) {
			void *pool2;

			if (FDs[i].fd == _cancelFD[0]) {
				char buffer;








|







187
188
189
190
191
192
193
194
195
196
197
198
199
200
201

	if (events < 0)
		@throw [OFObserveKernelEventsFailedException
		    exceptionWithObserver: self
				    errNo: errno];

	for (size_t i = 0; i < nFDs; i++) {
		OFAssert(FDs[i].fd <= _maxFD);

		if (FDs[i].revents & POLLIN) {
			void *pool2;

			if (FDs[i].fd == _cancelFD[0]) {
				char buffer;

Modified src/OFRIPEMD160Hash.h from [6a4a8d87d4] to [80819cf1f6].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFRIPEMD160Hash.m from [a6c68d768d] to [61b51851c2].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFRangeCharacterSet.h from [c903dba907] to [2d498537ab].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFRangeCharacterSet.m from [4870541066] to [0051a0a8d9].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Deleted src/OFRangeValue.h version [3251ae1de3].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the 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 "OFValue.h"

OF_ASSUME_NONNULL_BEGIN

@interface OFRangeValue: OFValue
{
	OFRange _range;
}

- (instancetype)initWithRange: (OFRange)range;
@end

OF_ASSUME_NONNULL_END
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
























































Deleted src/OFRangeValue.m version [72e3ffee04].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#import "OFRangeValue.h"
#import "OFMethodSignature.h"
#import "OFString.h"

#import "OFOutOfRangeException.h"

@implementation OFRangeValue
@synthesize rangeValue = _range;

- (instancetype)initWithRange: (OFRange)range
{
	self = [super init];

	_range = range;

	return self;
}

- (const char *)objCType
{
	return @encode(OFRange);
}

- (void)getValue: (void *)value size: (size_t)size
{
	if (size != sizeof(_range))
		@throw [OFOutOfRangeException exception];

	memcpy(value, &_range, sizeof(_range));
}

- (OFString *)description
{
	return [OFString stringWithFormat:
	    @"<OFValue: OFRange { %zu, %zu }>",
	    _range.location, _range.length];
}
@end
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<










































































































Deleted src/OFRectValue.h version [83e8354a4a].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the 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 "OFValue.h"

OF_ASSUME_NONNULL_BEGIN

@interface OFRectValue: OFValue
{
	OFRect _rect;
}

- (instancetype)initWithRect: (OFRect)rect;
@end

OF_ASSUME_NONNULL_END
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
























































Deleted src/OFRectValue.m version [0064a9b262].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the 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 "OFRectValue.h"
#import "OFMethodSignature.h"
#import "OFString.h"

#import "OFOutOfRangeException.h"

@implementation OFRectValue
@synthesize rectValue = _rect;

- (instancetype)initWithRect: (OFRect)rect
{
	self = [super init];

	_rect = rect;

	return self;
}

- (const char *)objCType
{
	return @encode(OFRect);
}

- (void)getValue: (void *)value size: (size_t)size
{
	if (size != sizeof(_rect))
		@throw [OFOutOfRangeException exception];

	memcpy(value, &_rect, sizeof(_rect));
}

- (OFString *)description
{
	return [OFString stringWithFormat:
	    @"<OFValue: OFRect { %f, %f, %f, %f }>",
	    _rect.origin.x, _rect.origin.y,
	    _rect.size.width, _rect.size.height];
}
@end
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<












































































































Modified src/OFRecursiveMutex.h from [e91aa73730] to [4610d1dd76].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFRecursiveMutex.m from [cb58226e3c] to [0f680fdecc].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFRunLoop+Private.h from [1af8d65653] to [ef59d3e619].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFRunLoop.h from [e058e5f18b] to [a6e92cc2f1].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
 * @brief Adds an OFTimer to the run loop for the specified mode.
 *
 * @param timer The timer to add
 * @param mode The run loop mode in which to run the timer
 */
- (void)addTimer: (OFTimer *)timer forMode: (OFRunLoopMode)mode;

#ifdef OF_AMIGAOS
/**
 * @brief Adds an Exec Signal to the run loop.
 *
 * If a signal is added multiple times, the specified methods will be performed
 * in the order added.
 *
 * @note This is only available on AmigaOS!







|







99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
 * @brief Adds an OFTimer to the run loop for the specified mode.
 *
 * @param timer The timer to add
 * @param mode The run loop mode in which to run the timer
 */
- (void)addTimer: (OFTimer *)timer forMode: (OFRunLoopMode)mode;

#if defined(OF_AMIGAOS) || defined(DOXYGEN)
/**
 * @brief Adds an Exec Signal to the run loop.
 *
 * If a signal is added multiple times, the specified methods will be performed
 * in the order added.
 *
 * @note This is only available on AmigaOS!

Modified src/OFRunLoop.m from [ccade11e78] to [d9a35ac974].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the 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 <assert.h>
#include <errno.h>

#import "OFRunLoop.h"
#import "OFRunLoop+Private.h"
#import "OFArray.h"
#import "OFData.h"
#import "OFDictionary.h"

|















<







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

18
19
20
21
22
23
24
/*
 * Copyright (c) 2008-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 <errno.h>

#import "OFRunLoop.h"
#import "OFRunLoop+Private.h"
#import "OFArray.h"
#import "OFData.h"
#import "OFDictionary.h"
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
	/*
	 * Retain the queue so that it doesn't disappear from us because the
	 * handler called -[cancelAsyncRequests].
	 */
	OFList OF_GENERIC(OF_KINDOF(OFRunLoopReadQueueItem *)) *queue =
	    [[_readQueues objectForKey: object] retain];

	assert(queue != nil);

	@try {
		if (![queue.firstObject handleObject: object]) {
			OFListItem listItem = queue.firstListItem;

			/*
			 * The handler might have called -[cancelAsyncRequests]







|







269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
	/*
	 * Retain the queue so that it doesn't disappear from us because the
	 * handler called -[cancelAsyncRequests].
	 */
	OFList OF_GENERIC(OF_KINDOF(OFRunLoopReadQueueItem *)) *queue =
	    [[_readQueues objectForKey: object] retain];

	OFAssert(queue != nil);

	@try {
		if (![queue.firstObject handleObject: object]) {
			OFListItem listItem = queue.firstListItem;

			/*
			 * The handler might have called -[cancelAsyncRequests]
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
{
	/*
	 * Retain the queue so that it doesn't disappear from us because the
	 * handler called -[cancelAsyncRequests].
	 */
	OFList *queue = [[_writeQueues objectForKey: object] retain];

	assert(queue != nil);

	@try {
		if (![queue.firstObject handleObject: object]) {
			OFListItem listItem = queue.firstListItem;

			/*
			 * The handler might have called -[cancelAsyncRequests]







|







313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
{
	/*
	 * Retain the queue so that it doesn't disappear from us because the
	 * handler called -[cancelAsyncRequests].
	 */
	OFList *queue = [[_writeQueues objectForKey: object] retain];

	OFAssert(queue != nil);

	@try {
		if (![queue.firstObject handleObject: object]) {
			OFListItem listItem = queue.firstListItem;

			/*
			 * The handler might have called -[cancelAsyncRequests]
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
	OFRunLoopState *state = stateForMode(runLoop, mode, false);
	OFList *queue;

	if (state == nil)
		return;

	if ((queue = [state->_writeQueues objectForKey: object]) != nil) {
		assert(queue.count > 0);

		/*
		 * Clear the queue now, in case this has been called from a
		 * handler, as otherwise, we'd do the cleanups below twice.
		 */
		[queue removeAllObjects];

		[state->_kernelEventObserver removeObjectForWriting: object];
		[state->_writeQueues removeObjectForKey: object];
	}

	if ((queue = [state->_readQueues objectForKey: object]) != nil) {
		assert(queue.count > 0);

		/*
		 * Clear the queue now, in case this has been called from a
		 * handler, as otherwise, we'd do the cleanups below twice.
		 */
		[queue removeAllObjects];








|












|







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
	OFRunLoopState *state = stateForMode(runLoop, mode, false);
	OFList *queue;

	if (state == nil)
		return;

	if ((queue = [state->_writeQueues objectForKey: object]) != nil) {
		OFAssert(queue.count > 0);

		/*
		 * Clear the queue now, in case this has been called from a
		 * handler, as otherwise, we'd do the cleanups below twice.
		 */
		[queue removeAllObjects];

		[state->_kernelEventObserver removeObjectForWriting: object];
		[state->_writeQueues removeObjectForKey: object];
	}

	if ((queue = [state->_readQueues objectForKey: object]) != nil) {
		OFAssert(queue.count > 0);

		/*
		 * Clear the queue now, in case this has been called from a
		 * handler, as otherwise, we'd do the cleanups below twice.
		 */
		[queue removeAllObjects];

1611
1612
1613
1614
1615
1616
1617

1618
1619
1620
1621
1622
1623
1624
#ifdef OF_HAVE_THREADS
			} @finally {
				[state->_timersQueueMutex unlock];
			}
#endif

			if (timer.valid) {

				[timer fire];
				return;
			}
		}

#ifdef OF_HAVE_THREADS
		[state->_timersQueueMutex lock];







>







1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
#ifdef OF_HAVE_THREADS
			} @finally {
				[state->_timersQueueMutex unlock];
			}
#endif

			if (timer.valid) {
				[timer of_reschedule];
				[timer fire];
				return;
			}
		}

#ifdef OF_HAVE_THREADS
		[state->_timersQueueMutex lock];

Modified src/OFRunLoopConstants.inc from [04d2ca961c] to [cae26aaa61].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFSHA1Hash.h from [c7a73ceb16] to [6159f2cdbb].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFSHA1Hash.m from [6da836d4ff] to [64db3263c1].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFSHA224Hash.h from [ecc593c441] to [14bf0912c3].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFSHA224Hash.m from [5e5ae70827] to [bc9785af40].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFSHA224Or256Hash.h from [9235d0cf7a] to [82f7c1770b].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFSHA224Or256Hash.m from [de7aa6c8f4] to [1df2737893].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFSHA256Hash.h from [29c7ad23a9] to [19f7cd6de3].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFSHA256Hash.m from [d082eb2586] to [a74963906d].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFSHA384Hash.h from [7c87550526] to [85294aa18f].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFSHA384Hash.m from [30d7ff4a68] to [af0bafa5f3].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFSHA384Or512Hash.h from [889dffbb99] to [7d6e3a012c].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFSHA384Or512Hash.m from [f0d2e79fad] to [600cda42b7].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFSHA512Hash.h from [b25fc86287] to [15b795ddf1].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFSHA512Hash.m from [b08066342d] to [015be46bb0].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFSPXSocket.h from [62171025db] to [8cb486db9e].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
 * @brief Connect the OFSPXSocket to the specified destination.
 *
 * @param network The network on which the node to connect to is
 * @param node The node to connect to
 * @param port The port (sometimes also called socket number) on the node to
 *	       connect to
 * @throw OFConnectSPXSocketFailedException Connecting failed
 * @throw OFAlreadyConnectedException The socket is already connected or bound
 */
- (void)connectToNetwork: (uint32_t)network
		    node: (const unsigned char [_Nonnull IPX_NODE_LEN])node
		    port: (uint16_t)port;

/**
 * @brief Asynchronously connect the OFSPXSocket to the specified destination.







|







86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
 * @brief Connect the OFSPXSocket to the specified destination.
 *
 * @param network The network on which the node to connect to is
 * @param node The node to connect to
 * @param port The port (sometimes also called socket number) on the node to
 *	       connect to
 * @throw OFConnectSPXSocketFailedException Connecting failed
 * @throw OFAlreadyOpenException The socket is already connected or bound
 */
- (void)connectToNetwork: (uint32_t)network
		    node: (const unsigned char [_Nonnull IPX_NODE_LEN])node
		    port: (uint16_t)port;

/**
 * @brief Asynchronously connect the OFSPXSocket to the specified destination.
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
 * @param network The IPX network to bind to. 0 means the current network.
 * @param node The IPX network to bind to. An all zero node means the
 *	       computer's node.
 * @param port The port (sometimes called socket number) to bind to. 0 means to
 *	       pick one and return via the returned socket address.
 * @return The address on which this socket can be reached
 * @throw OFBindIPXSocketFailedException Binding failed
 * @throw OFAlreadyConnectedException The socket is already connected or bound
 */
- (OFSocketAddress)
    bindToNetwork: (uint32_t)network
	     node: (const unsigned char [_Nonnull IPX_NODE_LEN])node
	     port: (uint16_t)port;
@end

OF_ASSUME_NONNULL_END







|








160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
 * @param network The IPX network to bind to. 0 means the current network.
 * @param node The IPX network to bind to. An all zero node means the
 *	       computer's node.
 * @param port The port (sometimes called socket number) to bind to. 0 means to
 *	       pick one and return via the returned socket address.
 * @return The address on which this socket can be reached
 * @throw OFBindIPXSocketFailedException Binding failed
 * @throw OFAlreadyOpenException The socket is already connected or bound
 */
- (OFSocketAddress)
    bindToNetwork: (uint32_t)network
	     node: (const unsigned char [_Nonnull IPX_NODE_LEN])node
	     port: (uint16_t)port;
@end

OF_ASSUME_NONNULL_END

Modified src/OFSPXSocket.m from [4bb1b2f501] to [c7e845a580].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

#import "OFSPXSocket.h"
#import "OFRunLoop.h"
#import "OFRunLoop+Private.h"
#import "OFSocket.h"
#import "OFSocket+Private.h"

#import "OFAlreadyConnectedException.h"
#import "OFBindIPXSocketFailedException.h"
#import "OFConnectSPXSocketFailedException.h"
#import "OFNotOpenException.h"

#ifndef NSPROTO_SPX
# define NSPROTO_SPX 0
#endif







|







19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

#import "OFSPXSocket.h"
#import "OFRunLoop.h"
#import "OFRunLoop+Private.h"
#import "OFSocket.h"
#import "OFSocket+Private.h"

#import "OFAlreadyOpenException.h"
#import "OFBindIPXSocketFailedException.h"
#import "OFConnectSPXSocketFailedException.h"
#import "OFNotOpenException.h"

#ifndef NSPROTO_SPX
# define NSPROTO_SPX 0
#endif
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
			   errNo: (int *)errNo
{
#if SOCK_CLOEXEC == 0 && defined(HAVE_FCNTL) && defined(FD_CLOEXEC)
	int flags;
#endif

	if (_socket != OFInvalidSocketHandle)
		@throw [OFAlreadyConnectedException exceptionWithSocket: self];

	if ((_socket = socket(address->sockaddr.ipx.sipx_family,
	    SOCK_SEQPACKET | SOCK_CLOEXEC, NSPROTO_SPX)) ==
	    OFInvalidSocketHandle) {
		*errNo = OFSocketErrNo();
		return false;
	}







|







181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
			   errNo: (int *)errNo
{
#if SOCK_CLOEXEC == 0 && defined(HAVE_FCNTL) && defined(FD_CLOEXEC)
	int flags;
#endif

	if (_socket != OFInvalidSocketHandle)
		@throw [OFAlreadyOpenException exceptionWithObject: self];

	if ((_socket = socket(address->sockaddr.ipx.sipx_family,
	    SOCK_SEQPACKET | SOCK_CLOEXEC, NSPROTO_SPX)) ==
	    OFInvalidSocketHandle) {
		*errNo = OFSocketErrNo();
		return false;
	}
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
{
	OFSocketAddress address;
#if SOCK_CLOEXEC == 0 && defined(HAVE_FCNTL_H) && defined(FD_CLOEXEC)
	int flags;
#endif

	if (_socket != OFInvalidSocketHandle)
		@throw [OFAlreadyConnectedException exceptionWithSocket: self];

	address = OFSocketAddressMakeIPX(network, node, port);

	if ((_socket = socket(address.sockaddr.ipx.sipx_family,
	    SOCK_SEQPACKET | SOCK_CLOEXEC, NSPROTO_SPX)) ==
	    OFInvalidSocketHandle)
		@throw [OFBindIPXSocketFailedException







|







319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
{
	OFSocketAddress address;
#if SOCK_CLOEXEC == 0 && defined(HAVE_FCNTL_H) && defined(FD_CLOEXEC)
	int flags;
#endif

	if (_socket != OFInvalidSocketHandle)
		@throw [OFAlreadyOpenException exceptionWithObject: self];

	address = OFSocketAddressMakeIPX(network, node, port);

	if ((_socket = socket(address.sockaddr.ipx.sipx_family,
	    SOCK_SEQPACKET | SOCK_CLOEXEC, NSPROTO_SPX)) ==
	    OFInvalidSocketHandle)
		@throw [OFBindIPXSocketFailedException

Modified src/OFSPXStreamSocket.h from [454aa9fc7f] to [3937a43366].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
 * @brief Connect the OFSPXStreamSocket to the specified destination.
 *
 * @param network The network on which the node to connect to is
 * @param node The node to connect to
 * @param port The port (sometimes also called socket number) on the node to
 *	       connect to
 * @throw OFConnectSPXSocketFailedException Connecting failed
 * @throw OFAlreadyConnectedException The socket is already connected or bound
 */
- (void)connectToNetwork: (uint32_t)network
		    node: (const unsigned char [_Nonnull IPX_NODE_LEN])node
		    port: (uint16_t)port;

/**
 * @brief Asynchronously connect the OFSPXStreamSocket to the specified







|







87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
 * @brief Connect the OFSPXStreamSocket to the specified destination.
 *
 * @param network The network on which the node to connect to is
 * @param node The node to connect to
 * @param port The port (sometimes also called socket number) on the node to
 *	       connect to
 * @throw OFConnectSPXSocketFailedException Connecting failed
 * @throw OFAlreadyOpenException The socket is already connected or bound
 */
- (void)connectToNetwork: (uint32_t)network
		    node: (const unsigned char [_Nonnull IPX_NODE_LEN])node
		    port: (uint16_t)port;

/**
 * @brief Asynchronously connect the OFSPXStreamSocket to the specified
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
 * @param network The IPX network to bind to. 0 means the current network.
 * @param node The IPX network to bind to. An all zero node means the
 *	       computer's node.
 * @param port The port (sometimes called socket number) to bind to. 0 means to
 *	       pick one and return via the returned socket address.
 * @return The address on which this socket can be reached
 * @throw OFBindIPXSocketFailedException Binding failed
 * @throw OFAlreadyConnectedException The socket is already connected or bound
 */
- (OFSocketAddress)
    bindToNetwork: (uint32_t)network
	     node: (const unsigned char [_Nonnull IPX_NODE_LEN])node
	     port: (uint16_t)port;
@end

OF_ASSUME_NONNULL_END







|








165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
 * @param network The IPX network to bind to. 0 means the current network.
 * @param node The IPX network to bind to. An all zero node means the
 *	       computer's node.
 * @param port The port (sometimes called socket number) to bind to. 0 means to
 *	       pick one and return via the returned socket address.
 * @return The address on which this socket can be reached
 * @throw OFBindIPXSocketFailedException Binding failed
 * @throw OFAlreadyOpenException The socket is already connected or bound
 */
- (OFSocketAddress)
    bindToNetwork: (uint32_t)network
	     node: (const unsigned char [_Nonnull IPX_NODE_LEN])node
	     port: (uint16_t)port;
@end

OF_ASSUME_NONNULL_END

Modified src/OFSPXStreamSocket.m from [3d76de2dbb] to [f585f31810].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

#import "OFSPXStreamSocket.h"
#import "OFRunLoop.h"
#import "OFRunLoop+Private.h"
#import "OFSocket.h"
#import "OFSocket+Private.h"

#import "OFAlreadyConnectedException.h"
#import "OFBindIPXSocketFailedException.h"
#import "OFConnectSPXSocketFailedException.h"
#import "OFNotOpenException.h"

#ifndef NSPROTO_SPX
# define NSPROTO_SPX 0
#endif







|







19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

#import "OFSPXStreamSocket.h"
#import "OFRunLoop.h"
#import "OFRunLoop+Private.h"
#import "OFSocket.h"
#import "OFSocket+Private.h"

#import "OFAlreadyOpenException.h"
#import "OFBindIPXSocketFailedException.h"
#import "OFConnectSPXSocketFailedException.h"
#import "OFNotOpenException.h"

#ifndef NSPROTO_SPX
# define NSPROTO_SPX 0
#endif
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
			   errNo: (int *)errNo
{
#if SOCK_CLOEXEC == 0 && defined(HAVE_FCNTL) && defined(FD_CLOEXEC)
	int flags;
#endif

	if (_socket != OFInvalidSocketHandle)
		@throw [OFAlreadyConnectedException exceptionWithSocket: self];

	if ((_socket = socket(address->sockaddr.ipx.sipx_family,
	    SOCK_STREAM | SOCK_CLOEXEC, NSPROTO_SPX)) ==
	    OFInvalidSocketHandle) {
		*errNo = OFSocketErrNo();
		return false;
	}







|







183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
			   errNo: (int *)errNo
{
#if SOCK_CLOEXEC == 0 && defined(HAVE_FCNTL) && defined(FD_CLOEXEC)
	int flags;
#endif

	if (_socket != OFInvalidSocketHandle)
		@throw [OFAlreadyOpenException exceptionWithObject: self];

	if ((_socket = socket(address->sockaddr.ipx.sipx_family,
	    SOCK_STREAM | SOCK_CLOEXEC, NSPROTO_SPX)) ==
	    OFInvalidSocketHandle) {
		*errNo = OFSocketErrNo();
		return false;
	}
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
{
	OFSocketAddress address;
#if SOCK_CLOEXEC == 0 && defined(HAVE_FCNTL_H) && defined(FD_CLOEXEC)
	int flags;
#endif

	if (_socket != OFInvalidSocketHandle)
		@throw [OFAlreadyConnectedException exceptionWithSocket: self];

	address = OFSocketAddressMakeIPX(network, node, port);

	if ((_socket = socket(address.sockaddr.ipx.sipx_family,
	    SOCK_STREAM | SOCK_CLOEXEC, NSPROTO_SPX)) == OFInvalidSocketHandle)
		@throw [OFBindIPXSocketFailedException
		    exceptionWithNetwork: network







|







321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
{
	OFSocketAddress address;
#if SOCK_CLOEXEC == 0 && defined(HAVE_FCNTL_H) && defined(FD_CLOEXEC)
	int flags;
#endif

	if (_socket != OFInvalidSocketHandle)
		@throw [OFAlreadyOpenException exceptionWithObject: self];

	address = OFSocketAddressMakeIPX(network, node, port);

	if ((_socket = socket(address.sockaddr.ipx.sipx_family,
	    SOCK_STREAM | SOCK_CLOEXEC, NSPROTO_SPX)) == OFInvalidSocketHandle)
		@throw [OFBindIPXSocketFailedException
		    exceptionWithNetwork: network

Modified src/OFSandbox.h from [021642ddcf] to [c3001072d2].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFSandbox.m from [de6e0ab02e] to [44d0d79336].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFScrypt.h from [7e18036f48] to [5600033ce1].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
    size_t blockSize);
extern void OFScryptROMix(uint32_t *buffer, size_t blockSize,
    size_t costFactor, uint32_t *tmp);

/**
 * @brief Derives a key from a password and a salt using scrypt.
 *
 * @param param The parameters to use
 */
extern void OFScrypt(OFScryptParameters param);
#ifdef __cplusplus
}
#endif

OF_ASSUME_NONNULL_END







|

|





66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
    size_t blockSize);
extern void OFScryptROMix(uint32_t *buffer, size_t blockSize,
    size_t costFactor, uint32_t *tmp);

/**
 * @brief Derives a key from a password and a salt using scrypt.
 *
 * @param parameters The parameters to use
 */
extern void OFScrypt(OFScryptParameters parameters);
#ifdef __cplusplus
}
#endif

OF_ASSUME_NONNULL_END

Modified src/OFScrypt.m from [730aa203eb] to [dd3b4bc37b].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFSecureData.h from [9dc679ab94] to [e09c6ef107].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
28
29
30
31
32
33
34



35
36
37
38
39
40
41
42
43
 *	    deallocated. Check the @ref allowsSwappableMemory property to see
 *	    whether a particular OFSecureData might be allocated in swappable
 *	    memory.
 */
OF_SUBCLASSING_RESTRICTED
@interface OFSecureData: OFData
{



	void *_page;
	bool _allowsSwappableMemory;
}

/**
 * @brief Whether the data may be stored in swappable memory.
 */
@property (readonly, nonatomic) bool allowsSwappableMemory;








>
>
>

<







28
29
30
31
32
33
34
35
36
37
38

39
40
41
42
43
44
45
 *	    deallocated. Check the @ref allowsSwappableMemory property to see
 *	    whether a particular OFSecureData might be allocated in swappable
 *	    memory.
 */
OF_SUBCLASSING_RESTRICTED
@interface OFSecureData: OFData
{
	unsigned char *_Nullable _items;
	size_t _count, _itemSize;
	bool _freeWhenDone, _allowsSwappableMemory;
	void *_page;

}

/**
 * @brief Whether the data may be stored in swappable memory.
 */
@property (readonly, nonatomic) bool allowsSwappableMemory;

100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
+ (instancetype)dataWithItemsNoCopy: (void *)items
			      count: (size_t)count
			   itemSize: (size_t)itemSize
		       freeWhenDone: (bool)freeWhenDone OF_UNAVAILABLE;
#ifdef OF_HAVE_FILES
+ (instancetype)dataWithContentsOfFile: (OFString *)path OF_UNAVAILABLE;
#endif
+ (instancetype)dataWithContentsOfURI: (OFURI *)URI OF_UNAVAILABLE;
+ (instancetype)dataWithStringRepresentation: (OFString *)string OF_UNAVAILABLE;
+ (instancetype)dataWithBase64EncodedString: (OFString *)string OF_UNAVAILABLE;

/**
 * @brief Initializes an already allocated OFSecureData with `count` items of
 *	  item size 1, all set to zero.
 *







|







102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
+ (instancetype)dataWithItemsNoCopy: (void *)items
			      count: (size_t)count
			   itemSize: (size_t)itemSize
		       freeWhenDone: (bool)freeWhenDone OF_UNAVAILABLE;
#ifdef OF_HAVE_FILES
+ (instancetype)dataWithContentsOfFile: (OFString *)path OF_UNAVAILABLE;
#endif
+ (instancetype)dataWithContentsOfIRI: (OFIRI *)IRI OF_UNAVAILABLE;
+ (instancetype)dataWithStringRepresentation: (OFString *)string OF_UNAVAILABLE;
+ (instancetype)dataWithBase64EncodedString: (OFString *)string OF_UNAVAILABLE;

/**
 * @brief Initializes an already allocated OFSecureData with `count` items of
 *	  item size 1, all set to zero.
 *
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
 * @return An initialized OFSecureData
 */
- (instancetype)initWithCount: (size_t)count
		     itemSize: (size_t)itemSize
	allowsSwappableMemory: (bool)allowsSwappableMemory
    OF_DESIGNATED_INITIALIZER;



- (instancetype)initWithItems: (const void *)items
			count: (size_t)count OF_UNAVAILABLE;
- (instancetype)initWithItems: (const void *)items
			count: (size_t)count
		     itemSize: (size_t)itemSize OF_UNAVAILABLE;
- (instancetype)initWithItemsNoCopy: (void *)items
			      count: (size_t)count
		       freeWhenDone: (bool)freeWhenDone OF_UNAVAILABLE;
- (instancetype)initWithItemsNoCopy: (void *)items
			      count: (size_t)count
			   itemSize: (size_t)itemSize
		       freeWhenDone: (bool)freeWhenDone OF_UNAVAILABLE;
#ifdef OF_HAVE_FILES
- (instancetype)initWithContentsOfFile: (OFString *)path OF_UNAVAILABLE;
#endif
- (instancetype)initWithContentsOfURI: (OFURI *)URI OF_UNAVAILABLE;
- (instancetype)initWithStringRepresentation: (OFString *)string OF_UNAVAILABLE;
- (instancetype)initWithBase64EncodedString: (OFString *)string OF_UNAVAILABLE;
- (instancetype)initWithSerialization: (OFXMLElement *)element OF_UNAVAILABLE;

/**
 * @brief Returns a specific item of the OFSecureData.
 *
 * Modifying the returned item directly is allowed and will change the contents
 * of the data array.
 *







>
>















|


<







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
 * @return An initialized OFSecureData
 */
- (instancetype)initWithCount: (size_t)count
		     itemSize: (size_t)itemSize
	allowsSwappableMemory: (bool)allowsSwappableMemory
    OF_DESIGNATED_INITIALIZER;

- (instancetype)init OF_UNAVAILABLE;
- (instancetype)initWithItemSize: (size_t)itemSize OF_UNAVAILABLE;
- (instancetype)initWithItems: (const void *)items
			count: (size_t)count OF_UNAVAILABLE;
- (instancetype)initWithItems: (const void *)items
			count: (size_t)count
		     itemSize: (size_t)itemSize OF_UNAVAILABLE;
- (instancetype)initWithItemsNoCopy: (void *)items
			      count: (size_t)count
		       freeWhenDone: (bool)freeWhenDone OF_UNAVAILABLE;
- (instancetype)initWithItemsNoCopy: (void *)items
			      count: (size_t)count
			   itemSize: (size_t)itemSize
		       freeWhenDone: (bool)freeWhenDone OF_UNAVAILABLE;
#ifdef OF_HAVE_FILES
- (instancetype)initWithContentsOfFile: (OFString *)path OF_UNAVAILABLE;
#endif
- (instancetype)initWithContentsOfIRI: (OFIRI *)IRI OF_UNAVAILABLE;
- (instancetype)initWithStringRepresentation: (OFString *)string OF_UNAVAILABLE;
- (instancetype)initWithBase64EncodedString: (OFString *)string OF_UNAVAILABLE;


/**
 * @brief Returns a specific item of the OFSecureData.
 *
 * Modifying the returned item directly is allowed and will change the contents
 * of the data array.
 *
183
184
185
186
187
188
189
190
191
192
193
194
195
- (void)zero;

- (OFString *)stringRepresentation OF_UNAVAILABLE;
- (OFString *)stringByBase64Encoding OF_UNAVAILABLE;
#ifdef OF_HAVE_FILES
- (void)writeToFile: (OFString *)path OF_UNAVAILABLE;
#endif
- (void)writeToURI: (OFURI *)URI OF_UNAVAILABLE;
- (OFXMLElement *)XMLElementBySerializing OF_UNAVAILABLE;
- (OFData *)messagePackRepresentation OF_UNAVAILABLE;
@end

OF_ASSUME_NONNULL_END







|
<




186
187
188
189
190
191
192
193

194
195
196
197
- (void)zero;

- (OFString *)stringRepresentation OF_UNAVAILABLE;
- (OFString *)stringByBase64Encoding OF_UNAVAILABLE;
#ifdef OF_HAVE_FILES
- (void)writeToFile: (OFString *)path OF_UNAVAILABLE;
#endif
- (void)writeToIRI: (OFIRI *)IRI OF_UNAVAILABLE;

- (OFData *)messagePackRepresentation OF_UNAVAILABLE;
@end

OF_ASSUME_NONNULL_END

Modified src/OFSecureData.m from [7420c1ca0e] to [d28acd1a78].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
{
	return [[[self alloc] initWithCount: count
				   itemSize: itemSize
		      allowsSwappableMemory: allowsSwappableMemory]
	    autorelease];
}

+ (instancetype)dataWithItems: (const void *)items
			count: (size_t)count
{
	OF_UNRECOGNIZED_SELECTOR
}

+ (instancetype)dataWithItems: (const void *)items
			count: (size_t)count
		     itemSize: (size_t)itemSize







|
<







336
337
338
339
340
341
342
343

344
345
346
347
348
349
350
{
	return [[[self alloc] initWithCount: count
				   itemSize: itemSize
		      allowsSwappableMemory: allowsSwappableMemory]
	    autorelease];
}

+ (instancetype)dataWithItems: (const void *)items count: (size_t)count

{
	OF_UNRECOGNIZED_SELECTOR
}

+ (instancetype)dataWithItems: (const void *)items
			count: (size_t)count
		     itemSize: (size_t)itemSize
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
#ifdef OF_HAVE_FILES
+ (instancetype)dataWithContentsOfFile: (OFString *)path
{
	OF_UNRECOGNIZED_SELECTOR
}
#endif

+ (instancetype)dataWithContentsOfURI: (OFURI *)URI
{
	OF_UNRECOGNIZED_SELECTOR
}

+ (instancetype)dataWithStringRepresentation: (OFString *)string
{
	OF_UNRECOGNIZED_SELECTOR
}

+ (instancetype)dataWithBase64EncodedString: (OFString *)string
{
	OF_UNRECOGNIZED_SELECTOR
}


- (instancetype)initWithCount: (size_t)count
	allowsSwappableMemory: (bool)allowsSwappableMemory
{
	return [self initWithCount: count
			  itemSize: 1
	     allowsSwappableMemory: allowsSwappableMemory];







|













<







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
#ifdef OF_HAVE_FILES
+ (instancetype)dataWithContentsOfFile: (OFString *)path
{
	OF_UNRECOGNIZED_SELECTOR
}
#endif

+ (instancetype)dataWithContentsOfIRI: (OFIRI *)IRI
{
	OF_UNRECOGNIZED_SELECTOR
}

+ (instancetype)dataWithStringRepresentation: (OFString *)string
{
	OF_UNRECOGNIZED_SELECTOR
}

+ (instancetype)dataWithBase64EncodedString: (OFString *)string
{
	OF_UNRECOGNIZED_SELECTOR
}


- (instancetype)initWithCount: (size_t)count
	allowsSwappableMemory: (bool)allowsSwappableMemory
{
	return [self initWithCount: count
			  itemSize: 1
	     allowsSwappableMemory: allowsSwappableMemory];
460
461
462
463
464
465
466










467
468
469
470
471
472
473
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}











- (instancetype)initWithItems: (const void *)items count: (size_t)count
{
	OF_INVALID_INIT_METHOD
}

- (instancetype)initWithItems: (const void *)items







>
>
>
>
>
>
>
>
>
>







458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (instancetype)init
{
	OF_INVALID_INIT_METHOD
}

- (instancetype)initWithItemSize: (size_t)itemSize
{
	OF_INVALID_INIT_METHOD
}

- (instancetype)initWithItems: (const void *)items count: (size_t)count
{
	OF_INVALID_INIT_METHOD
}

- (instancetype)initWithItems: (const void *)items
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
#ifdef OF_HAVE_FILES
- (instancetype)initWithContentsOfFile: (OFString *)path
{
	OF_INVALID_INIT_METHOD
}
#endif

- (instancetype)initWithContentsOfURI: (OFURI *)URI
{
	OF_INVALID_INIT_METHOD
}

- (instancetype)initWithStringRepresentation: (OFString *)string
{
	OF_INVALID_INIT_METHOD
}

- (instancetype)initWithBase64EncodedString: (OFString *)string
{
	OF_INVALID_INIT_METHOD
}

- (instancetype)initWithSerialization: (OFXMLElement *)element
{
	OF_INVALID_INIT_METHOD
}

- (void)dealloc
{
	[self zero];








|











<
<
<
<
<







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
#ifdef OF_HAVE_FILES
- (instancetype)initWithContentsOfFile: (OFString *)path
{
	OF_INVALID_INIT_METHOD
}
#endif

- (instancetype)initWithContentsOfIRI: (OFIRI *)IRI
{
	OF_INVALID_INIT_METHOD
}

- (instancetype)initWithStringRepresentation: (OFString *)string
{
	OF_INVALID_INIT_METHOD
}

- (instancetype)initWithBase64EncodedString: (OFString *)string
{





	OF_INVALID_INIT_METHOD
}

- (void)dealloc
{
	[self zero];

536
537
538
539
540
541
542



543
544















545
546
547
548
549
550
551
				freeMemory(_page, _items, _count * _itemSize);

			removePageIfEmpty(_page);
		}
	}
#endif




	[super dealloc];
}
















- (void *)mutableItems
{
	return _items;
}

- (void *)mutableItemAtIndex: (size_t)idx







>
>
>


>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
				freeMemory(_page, _items, _count * _itemSize);

			removePageIfEmpty(_page);
		}
	}
#endif

	if (_freeWhenDone)
		OFFreeMemory(_items);

	[super dealloc];
}

- (size_t)count
{
	return _count;
}

- (size_t)itemSize
{
	return _itemSize;
}

- (const void *)items
{
	return _items;
}

- (void *)mutableItems
{
	return _items;
}

- (void *)mutableItemAtIndex: (size_t)idx
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

	return copy;
}

- (bool)isEqual: (id)object
{
	OFData *otherData;

	unsigned char diff;

	if (object == self)
		return true;

	if (![object isKindOfClass: [OFData class]])
		return false;

	otherData = object;


	if (otherData->_count != _count || otherData->_itemSize != _itemSize)
		return false;

	diff = 0;

	for (size_t i = 0; i < _count * _itemSize; i++)
		diff |= otherData->_items[i] ^ _items[i];

	return (diff == 0);
}

- (OFString *)description
{
	return @"<OFSecureData>";







>









>

|





|







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

	return copy;
}

- (bool)isEqual: (id)object
{
	OFData *otherData;
	const unsigned char *otherDataItems;
	unsigned char diff;

	if (object == self)
		return true;

	if (![object isKindOfClass: [OFData class]])
		return false;

	otherData = object;
	otherDataItems = otherData.items;

	if (otherData.count != _count || otherData.itemSize != _itemSize)
		return false;

	diff = 0;

	for (size_t i = 0; i < _count * _itemSize; i++)
		diff |= otherDataItems[i] ^ _items[i];

	return (diff == 0);
}

- (OFString *)description
{
	return @"<OFSecureData>";
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
#ifdef OF_HAVE_FILES
- (void)writeToFile: (OFString *)path
{
	OF_UNRECOGNIZED_SELECTOR
}
#endif

- (void)writeToURI: (OFURI *)URI
{
	OF_UNRECOGNIZED_SELECTOR
}

- (OFXMLElement *)XMLElementBySerializing
{
	OF_UNRECOGNIZED_SELECTOR
}

- (OFData *)messagePackRepresentation
{
	OF_UNRECOGNIZED_SELECTOR
}
@end







|
<
<
<
<
<









650
651
652
653
654
655
656
657





658
659
660
661
662
663
664
665
666
#ifdef OF_HAVE_FILES
- (void)writeToFile: (OFString *)path
{
	OF_UNRECOGNIZED_SELECTOR
}
#endif

- (void)writeToIRI: (OFIRI *)IRI





{
	OF_UNRECOGNIZED_SELECTOR
}

- (OFData *)messagePackRepresentation
{
	OF_UNRECOGNIZED_SELECTOR
}
@end

Modified src/OFSeekableStream.h from [b1e0890846] to [0e5a829485].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
/** @file */

#if defined(OF_WINDOWS)
typedef __int64 OFStreamOffset;
#elif defined(OF_ANDROID)
typedef long long OFStreamOffset;
#elif defined(OF_MORPHOS)
typedef signed long long OFStreamOffset;
#elif defined(OF_HAVE_OFF64_T)
typedef off64_t OFStreamOffset;
#else
typedef off_t OFStreamOffset;
#endif

/**







|







33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
/** @file */

#if defined(OF_WINDOWS)
typedef __int64 OFStreamOffset;
#elif defined(OF_ANDROID)
typedef long long OFStreamOffset;
#elif defined(OF_MORPHOS)
typedef long long OFStreamOffset;
#elif defined(OF_HAVE_OFF64_T)
typedef off64_t OFStreamOffset;
#else
typedef off_t OFStreamOffset;
#endif

/**

Modified src/OFSeekableStream.m from [b6c980d4ae] to [ae8338b495].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFSelectKernelEventObserver.h from [87e3b347a2] to [8fb34fa65c].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFSelectKernelEventObserver.m from [178271bdfe] to [e50f11801b].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
34
35
36
37
38
39
40

41

42
43
44
45
46
47
48
#import "OFSocket+Private.h"

#import "OFInitializationFailedException.h"
#import "OFObserveKernelEventsFailedException.h"
#import "OFOutOfRangeException.h"

#ifdef OF_AMIGAOS

# include <proto/exec.h>

#endif

#ifdef OF_HPUX
/* FD_SET causes warnings on HP-UX/IA64. */
# pragma GCC diagnostic ignored "-Wstrict-aliasing"
#endif








>

>







34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#import "OFSocket+Private.h"

#import "OFInitializationFailedException.h"
#import "OFObserveKernelEventsFailedException.h"
#import "OFOutOfRangeException.h"

#ifdef OF_AMIGAOS
# define Class IntuitionClass
# include <proto/exec.h>
# undef Class
#endif

#ifdef OF_HPUX
/* FD_SET causes warnings on HP-UX/IA64. */
# pragma GCC diagnostic ignored "-Wstrict-aliasing"
#endif

Modified src/OFSequencedPacketSocket+Private.h from [779ca7e02d] to [6aad865b27].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFSequencedPacketSocket.h from [0f03522481] to [6a02d92297].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
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
 *	    than one thread at the same time is not thread-safe, even if copy
 *	    was called to create one "instance" for every thread!
 */
@interface OFSequencedPacketSocket: OFObject <OFCopying,
    OFReadyForReadingObserving, OFReadyForWritingObserving>
{
	OFSocketHandle _socket;




	bool _canBlock, _listening;
	OFSocketAddress _remoteAddress;
	id _Nullable _delegate;
	OF_RESERVE_IVARS(OFSequencedPacketSocket, 4)
}

/**
 * @brief Whether the socket can block.
 *
 * By default, a socket can block.
 *

 * @throw OFSetOptionFailedException The option could not be set
 */
@property (nonatomic) bool canBlock;

/**
 * @brief Whether the socket is a listening socket.
 */







>
>
>
>











>







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
 *	    than one thread at the same time is not thread-safe, even if copy
 *	    was called to create one "instance" for every thread!
 */
@interface OFSequencedPacketSocket: OFObject <OFCopying,
    OFReadyForReadingObserving, OFReadyForWritingObserving>
{
	OFSocketHandle _socket;
#ifdef OF_AMIGAOS
	LONG _socketID;	/* unused, reserved for ABI stability */
	int _family;	/* unused, reserved for ABI stability */
#endif
	bool _canBlock, _listening;
	OFSocketAddress _remoteAddress;
	id _Nullable _delegate;
	OF_RESERVE_IVARS(OFSequencedPacketSocket, 4)
}

/**
 * @brief Whether the socket can block.
 *
 * By default, a socket can block.
 *
 * @throw OFGetOptionFailedException The option could not be retrieved
 * @throw OFSetOptionFailedException The option could not be set
 */
@property (nonatomic) bool canBlock;

/**
 * @brief Whether the socket is a listening socket.
 */
363
364
365
366
367
368
369
























370
371
372
373
374
375
376
377
378
379
#endif

/**
 * @brief Cancels all pending asynchronous requests on the socket.
 */
- (void)cancelAsyncRequests;

























/**
 * @brief Closes the socket so that it can neither receive nor send any more
 *	  datagrams.
 *
 * @throw OFNotOpenException The socket is not open
 */
- (void)close;
@end

OF_ASSUME_NONNULL_END







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>










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
#endif

/**
 * @brief Cancels all pending asynchronous requests on the socket.
 */
- (void)cancelAsyncRequests;

/**
 * @brief Releases the socket from the current thread.
 *
 * This is necessary on some platforms in order to allow a different thread to
 * use the socket, e.g. on AmigaOS, but you should call it on all operating
 * systems before using the socket from a different thread.
 *
 * After calling this method, you must no longer use the socket until
 * @ref obtainSocketForCurrentThread has been called.
 */
- (void)releaseSocketFromCurrentThread;

/**
 * @brief Obtains the socket for the current thread.
 *
 * This is necessary on some platforms in order to allow a different thread to
 * use the socket, e.g. on AmigaOS, but you should call it on all operating
 * systems before using the socket from a different thread.
 *
 * You must only call this method after @ref releaseSocketFromCurrentThread has
 * been called from a different thread.
 */
- (void)obtainSocketForCurrentThread;

/**
 * @brief Closes the socket so that it can neither receive nor send any more
 *	  datagrams.
 *
 * @throw OFNotOpenException The socket is not open
 */
- (void)close;
@end

OF_ASSUME_NONNULL_END

Modified src/OFSequencedPacketSocket.m from [0b38781929] to [ddbcc80b65].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#ifndef _XOPEN_SOURCE_EXTENDED
# define _XOPEN_SOURCE_EXTENDED
#endif
#define _HPUX_ALT_XOPEN_SOCKET_API

#include <assert.h>
#include <errno.h>

#ifdef HAVE_FCNTL_H
# include <fcntl.h>
#endif

#import "OFSequencedPacketSocket.h"

|




















<







1
2
3
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.
 */

#include "config.h"

#ifndef _XOPEN_SOURCE_EXTENDED
# define _XOPEN_SOURCE_EXTENDED
#endif
#define _HPUX_ALT_XOPEN_SOCKET_API


#include <errno.h>

#ifdef HAVE_FCNTL_H
# include <fcntl.h>
#endif

#import "OFSequencedPacketSocket.h"
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372

# if defined(HAVE_FCNTL) && defined(FD_CLOEXEC)
	if ((flags = fcntl(client->_socket, F_GETFD, 0)) != -1)
		fcntl(client->_socket, F_SETFD, flags | FD_CLOEXEC);
# endif
#endif

	assert(client->_remoteAddress.length <=
	    (socklen_t)sizeof(client->_remoteAddress.sockaddr));

	switch (((struct sockaddr *)&client->_remoteAddress.sockaddr)
	    ->sa_family) {
	case AF_INET:
		client->_remoteAddress.family = OFSocketAddressFamilyIPv4;
		break;







|







357
358
359
360
361
362
363
364
365
366
367
368
369
370
371

# if defined(HAVE_FCNTL) && defined(FD_CLOEXEC)
	if ((flags = fcntl(client->_socket, F_GETFD, 0)) != -1)
		fcntl(client->_socket, F_SETFD, flags | FD_CLOEXEC);
# endif
#endif

	OFAssert(client->_remoteAddress.length <=
	    (socklen_t)sizeof(client->_remoteAddress.sockaddr));

	switch (((struct sockaddr *)&client->_remoteAddress.sockaddr)
	    ->sa_family) {
	case AF_INET:
		client->_remoteAddress.family = OFSocketAddressFamilyIPv4;
		break;
463
464
465
466
467
468
469
















470
471
472
473
474
475
476
477
478
479
480
481
482

	if (_socket > INT_MAX)
		@throw [OFOutOfRangeException exception];

	return (int)_socket;
#endif
}

















- (void)close
{
	if (_socket == OFInvalidSocketHandle)
		@throw [OFNotOpenException exceptionWithObject: self];

	_listening = false;
	memset(&_remoteAddress, 0, sizeof(_remoteAddress));

	closesocket(_socket);
	_socket = OFInvalidSocketHandle;
}
@end







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>













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

	if (_socket > INT_MAX)
		@throw [OFOutOfRangeException exception];

	return (int)_socket;
#endif
}

- (void)releaseSocketFromCurrentThread
{
	/*
	 * Currently a nop, as all supported OSes that have SOCK_SEQPACKET do
	 * not need anything to move sockets between threads.
	 */
}

- (void)obtainSocketForCurrentThread
{
	/*
	 * Currently a nop, as all supported OSes that have SOCK_SEQPACKET do
	 * not need anything to move sockets between threads.
	 */
}

- (void)close
{
	if (_socket == OFInvalidSocketHandle)
		@throw [OFNotOpenException exceptionWithObject: self];

	_listening = false;
	memset(&_remoteAddress, 0, sizeof(_remoteAddress));

	closesocket(_socket);
	_socket = OFInvalidSocketHandle;
}
@end

Deleted src/OFSerialization.h version [6c8c4c9563].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#import "OFObject.h"

OF_ASSUME_NONNULL_BEGIN

@class OFConstantString;
@class OFXMLElement;

/**
 * @protocol OFSerialization OFSerialization.h ObjFW/OFSerialization.h
 *
 * @brief A protocol for serializing objects.
 */
@protocol OFSerialization
/**
 * @brief The object serialized into an XML element.
 */
@property (readonly, nonatomic) OFXMLElement *XMLElementBySerializing;

/**
 * @brief Initializes the object with the specified XML element serialization.
 *
 * @param element An OFXMLElement with the serialized object
 * @return An initialized object
 * @throw OFInvalidFormatException The specified element is not of the correct
 *				   serialization format
 */
- (instancetype)initWithSerialization: (OFXMLElement *)element;
@end

#ifdef __cplusplus
extern "C" {
#endif
extern OFConstantString *const OFSerializationNS;
#ifdef __cplusplus
}
#endif

OF_ASSUME_NONNULL_END
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<










































































































Deleted src/OFSerialization.m version [0e1e99b940].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#import "OFSerialization.h"
#import "OFString.h"

OFConstantString *const OFSerializationNS =
    @"https://objfw.nil.im/serialization";
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<








































Modified src/OFSet.h from [4c0dd3a76f] to [dfe1ffa107].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# define __STDC_CONSTANT_MACROS
#endif

#include <stdarg.h>

#import "OFObject.h"
#import "OFCollection.h"
#import "OFSerialization.h"

OF_ASSUME_NONNULL_BEGIN

/** @file */

@class OFArray OF_GENERIC(ObjectType);








<







20
21
22
23
24
25
26

27
28
29
30
31
32
33
# define __STDC_CONSTANT_MACROS
#endif

#include <stdarg.h>

#import "OFObject.h"
#import "OFCollection.h"


OF_ASSUME_NONNULL_BEGIN

/** @file */

@class OFArray OF_GENERIC(ObjectType);

59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
 * @warning Do not mutate objects that are in a set! Changing the hash of
 *	    objects in a set breaks the internal representation of the set!
 *
 * @note Subclasses must implement @ref count, @ref containsObject: and
 *	 @ref objectEnumerator.
 */
@interface OFSet OF_GENERIC(ObjectType): OFObject <OFCollection, OFCopying,
    OFMutableCopying, OFSerialization>
#if !defined(OF_HAVE_GENERICS) && !defined(DOXYGEN)
# define ObjectType id
#endif
/**
 * @brief An array of all objects in the set.
 */
@property (readonly, nonatomic) OFArray OF_GENERIC(ObjectType) *allObjects;







|







58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
 * @warning Do not mutate objects that are in a set! Changing the hash of
 *	    objects in a set breaks the internal representation of the set!
 *
 * @note Subclasses must implement @ref count, @ref containsObject: and
 *	 @ref objectEnumerator.
 */
@interface OFSet OF_GENERIC(ObjectType): OFObject <OFCollection, OFCopying,
    OFMutableCopying>
#if !defined(OF_HAVE_GENERICS) && !defined(DOXYGEN)
# define ObjectType id
#endif
/**
 * @brief An array of all objects in the set.
 */
@property (readonly, nonatomic) OFArray OF_GENERIC(ObjectType) *allObjects;
114
115
116
117
118
119
120







121
122
123
124
125
126
127
 * @param objects An array of objects for the set
 * @param count The number of objects in the specified array
 * @return A new, autoreleased set with the specified objects
 */
+ (instancetype)setWithObjects: (ObjectType const _Nonnull *_Nonnull)objects
			 count: (size_t)count;








/**
 * @brief Initializes an already allocated set with the specified set.
 *
 * @param set The set to initialize the set with
 * @return An initialized set with the specified set
 */
- (instancetype)initWithSet: (OFSet OF_GENERIC(ObjectType) *)set;







>
>
>
>
>
>
>







113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
 * @param objects An array of objects for the set
 * @param count The number of objects in the specified array
 * @return A new, autoreleased set with the specified objects
 */
+ (instancetype)setWithObjects: (ObjectType const _Nonnull *_Nonnull)objects
			 count: (size_t)count;

/**
 * @brief Initializes an already allocated set to be empty.
 *
 * @return An initialized set
 */
- (instancetype)init OF_DESIGNATED_INITIALIZER;

/**
 * @brief Initializes an already allocated set with the specified set.
 *
 * @param set The set to initialize the set with
 * @return An initialized set with the specified set
 */
- (instancetype)initWithSet: (OFSet OF_GENERIC(ObjectType) *)set;
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
 * @brief Initializes an already allocated set with the specified objects.
 *
 * @param objects An array of objects for the set
 * @param count The number of objects in the specified array
 * @return An initialized set with the specified objects
 */
- (instancetype)initWithObjects: (ObjectType const _Nonnull *_Nonnull)objects
			  count: (size_t)count;

/**
 * @brief Returns an OFEnumerator to enumerate through all objects of the set.
 *
 * @return An OFEnumerator to enumerate through all objects of the set
 */
- (OFEnumerator OF_GENERIC(ObjectType) *)objectEnumerator;







|







163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
 * @brief Initializes an already allocated set with the specified objects.
 *
 * @param objects An array of objects for the set
 * @param count The number of objects in the specified array
 * @return An initialized set with the specified objects
 */
- (instancetype)initWithObjects: (ObjectType const _Nonnull *_Nonnull)objects
			  count: (size_t)count OF_DESIGNATED_INITIALIZER;

/**
 * @brief Returns an OFEnumerator to enumerate through all objects of the set.
 *
 * @return An OFEnumerator to enumerate through all objects of the set
 */
- (OFEnumerator OF_GENERIC(ObjectType) *)objectEnumerator;

Modified src/OFSet.m from [c2dcb9f429] to [13b08a9492].

1
2
3
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
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#include <stdlib.h>

#import "OFSet.h"
#import "OFArray.h"
#import "OFMapTableSet.h"
#import "OFNull.h"
#import "OFString.h"
#import "OFXMLElement.h"

static struct {
	Class isa;
} placeholder;

@interface OFSetPlaceholder: OFSet
@end

@implementation OFSetPlaceholder






- (instancetype)init
{
	return (id)[[OFMapTableSet alloc] init];
}

- (instancetype)initWithSet: (OFSet *)set
{
	return (id)[[OFMapTableSet alloc] initWithSet: set];
}

- (instancetype)initWithArray: (OFArray *)array
{
	return (id)[[OFMapTableSet alloc] initWithArray: array];
}

- (instancetype)initWithObjects: (id)firstObject, ...
{
	id ret;
	va_list arguments;

	va_start(arguments, firstObject);
	ret = [[OFMapTableSet alloc] initWithObject: firstObject
					  arguments: arguments];
	va_end(arguments);

	return ret;
}

- (instancetype)initWithObjects: (id const *)objects count: (size_t)count
{
	return (id)[[OFMapTableSet alloc] initWithObjects: objects
						    count: count];
}

- (instancetype)initWithObject: (id)firstObject arguments: (va_list)arguments
{
	return (id)[[OFMapTableSet alloc] initWithObject: firstObject
					       arguments: arguments];
}

- (instancetype)initWithSerialization: (OFXMLElement *)element
{
	return (id)[[OFMapTableSet alloc] initWithSerialization: element];
}

- (instancetype)retain
{
	return self;
}

- (instancetype)autorelease
{
	return self;
}

- (void)release
{
}

- (void)dealloc
{
	OF_DEALLOC_UNSUPPORTED
}
@end

@implementation OFSet
+ (void)initialize
{
	if (self == [OFSet class])
		placeholder.isa = [OFSetPlaceholder class];
}

+ (instancetype)alloc
{
	if (self == [OFSet class])
		return (id)&placeholder;


|



















|
|
|
|





|


|
>
>
>
>
>
>


|




|




|








|








|





|


|
<
<
<
<
|
<
<
<
<
|
<
|
<
<
|
<
<
<
<
<
<
<
<






|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80




81




82

83


84








85
86
87
88
89
90
91
92
93
94
95
96
97
98
/*
 * Copyright (c) 2008-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 <stdlib.h>

#import "OFSet.h"
#import "OFArray.h"
#import "OFConcreteSet.h"
#import "OFCountedSet.h"
#import "OFNull.h"
#import "OFString.h"

static struct {
	Class isa;
} placeholder;

@interface OFPlaceholderSet: OFSet
@end

@implementation OFPlaceholderSet
#ifdef __clang__
/* We intentionally don't call into super, so silence the warning. */
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wunknown-pragmas"
# pragma clang diagnostic ignored "-Wobjc-designated-initializers"
#endif
- (instancetype)init
{
	return (id)[[OFConcreteSet alloc] init];
}

- (instancetype)initWithSet: (OFSet *)set
{
	return (id)[[OFConcreteSet alloc] initWithSet: set];
}

- (instancetype)initWithArray: (OFArray *)array
{
	return (id)[[OFConcreteSet alloc] initWithArray: array];
}

- (instancetype)initWithObjects: (id)firstObject, ...
{
	id ret;
	va_list arguments;

	va_start(arguments, firstObject);
	ret = [[OFConcreteSet alloc] initWithObject: firstObject
					  arguments: arguments];
	va_end(arguments);

	return ret;
}

- (instancetype)initWithObjects: (id const *)objects count: (size_t)count
{
	return (id)[[OFConcreteSet alloc] initWithObjects: objects
						    count: count];
}

- (instancetype)initWithObject: (id)firstObject arguments: (va_list)arguments
{
	return (id)[[OFConcreteSet alloc] initWithObject: firstObject
					       arguments: arguments];
}
#ifdef __clang__




# pragma clang diagnostic pop




#endif




OF_SINGLETON_METHODS








@end

@implementation OFSet
+ (void)initialize
{
	if (self == [OFSet class])
		object_setClass((id)&placeholder, [OFPlaceholderSet class]);
}

+ (instancetype)alloc
{
	if (self == [OFSet class])
		return (id)&placeholder;

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
{
	return [[[self alloc] initWithObjects: objects
					count: count] autorelease];
}

- (instancetype)init
{
	if ([self isMemberOfClass: [OFSet class]]) {


		@try {
			[self doesNotRecognizeSelector: _cmd];
		} @catch (id e) {
			[self release];
			@throw e;
		}

		abort();
	}

	return [super init];
}

- (instancetype)initWithSet: (OFSet *)set
{


	OF_INVALID_INIT_METHOD



}

























- (instancetype)initWithArray: (OFArray *)array
{



	OF_INVALID_INIT_METHOD






}














- (instancetype)initWithObjects: (id const *)objects count: (size_t)count
{
	OF_INVALID_INIT_METHOD
}




- (instancetype)initWithObjects: (id)firstObject, ...
{
	id ret;
	va_list arguments;

	va_start(arguments, firstObject);
	ret = [self initWithObject: firstObject arguments: arguments];
	va_end(arguments);

	return ret;
}

- (instancetype)initWithObject: (id)firstObject arguments: (va_list)arguments
{



	OF_INVALID_INIT_METHOD


}










- (instancetype)initWithSerialization: (OFXMLElement *)element


{




	OF_INVALID_INIT_METHOD






}

- (size_t)count
{
	OF_UNRECOGNIZED_SELECTOR
}








|
>
>















>
>
|
>
>
>
|
>
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>


>
>
>
|
>
>
>
>
>
>
|

>
>
>
>
>
>
>
>
>
>
>
>
>




>
>
>















>
>
>
|
>
>
|
>
>
>

>
>
>
>
>
>
|
>
>
|
>
>
>
>
|
>
>
>
>
>
>







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
{
	return [[[self alloc] initWithObjects: objects
					count: count] autorelease];
}

- (instancetype)init
{
	if ([self isMemberOfClass: [OFSet class]] ||
	    [self isMemberOfClass: [OFMutableSet class]] ||
	    [self isMemberOfClass: [OFCountedSet class]]) {
		@try {
			[self doesNotRecognizeSelector: _cmd];
		} @catch (id e) {
			[self release];
			@throw e;
		}

		abort();
	}

	return [super init];
}

- (instancetype)initWithSet: (OFSet *)set
{
	id *objects = NULL;
	size_t count;

	@try {
		void *pool = objc_autoreleasePoolPush();
		size_t i = 0;

		count = set.count;
		objects = OFAllocMemory(count, sizeof(id));

		for (id object in set) {
			OFEnsure(i < count);
			objects[i++] = object;
		}

		objc_autoreleasePoolPop(pool);
	} @catch (id e) {
		OFFreeMemory(objects);

		[self release];
		@throw e;
	}

	@try {
		self = [self initWithObjects: objects count: count];
	} @finally {
		OFFreeMemory(objects);
	}

	return self;
}

- (instancetype)initWithArray: (OFArray *)array
{
	void *pool = objc_autoreleasePoolPush();
	size_t count;
	const id *objects;

	@try {
		count = array.count;
		objects = array.objects;
	} @catch (id e) {
		[self release];
		@throw e;
	}

	self = [self initWithObjects: objects count: count];

	objc_autoreleasePoolPop(pool);

	return self;
}

#ifdef __clang__
/* We intentionally don't call into super, so silence the warning. */
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wunknown-pragmas"
# pragma clang diagnostic ignored "-Wobjc-designated-initializers"
#endif
- (instancetype)initWithObjects: (id const *)objects count: (size_t)count
{
	OF_INVALID_INIT_METHOD
}
#ifdef __clang__
# pragma clang diagnostic pop
#endif

- (instancetype)initWithObjects: (id)firstObject, ...
{
	id ret;
	va_list arguments;

	va_start(arguments, firstObject);
	ret = [self initWithObject: firstObject arguments: arguments];
	va_end(arguments);

	return ret;
}

- (instancetype)initWithObject: (id)firstObject arguments: (va_list)arguments
{
	size_t count = 1;
	va_list argumentsCopy;
	id *objects;

	if (firstObject == nil)
		return [self init];

	va_copy(argumentsCopy, arguments);
	while (va_arg(argumentsCopy, id) != nil)
		count++;

	@try {
		objects = OFAllocMemory(count, sizeof(id));
	} @catch (id e) {
		[self release];
		@throw e;
	}

	@try {
		objects[0] = firstObject;

		for (size_t i = 1; i < count; i++) {
			objects[i] = va_arg(arguments, id);
			OFEnsure(objects[i] != nil);
		}

		self = [self initWithObjects: objects count: count];
	} @finally {
		OFFreeMemory(objects);
	}

	return self;
}

- (size_t)count
{
	OF_UNRECOGNIZED_SELECTOR
}

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
	OF_UNRECOGNIZED_SELECTOR
}

- (int)countByEnumeratingWithState: (OFFastEnumerationState *)state
			   objects: (id *)objects
			     count: (int)count
{

	OFEnumerator *enumerator;
	int i;

	memcpy(&enumerator, state->extra, sizeof(enumerator));

	if (enumerator == nil) {
		enumerator = [self objectEnumerator];
		memcpy(state->extra, &enumerator, sizeof(enumerator));
	}

	state->itemsPtr = objects;
	state->mutationsPtr = (unsigned long *)self;

	for (i = 0; i < count; i++) {
		id object = [enumerator nextObject];

		if (object == nil)
			return i;








>











|







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
	OF_UNRECOGNIZED_SELECTOR
}

- (int)countByEnumeratingWithState: (OFFastEnumerationState *)state
			   objects: (id *)objects
			     count: (int)count
{
	static unsigned long dummyMutations;
	OFEnumerator *enumerator;
	int i;

	memcpy(&enumerator, state->extra, sizeof(enumerator));

	if (enumerator == nil) {
		enumerator = [self objectEnumerator];
		memcpy(state->extra, &enumerator, sizeof(enumerator));
	}

	state->itemsPtr = objects;
	state->mutationsPtr = &dummyMutations;

	for (i = 0; i < count; i++) {
		id object = [enumerator nextObject];

		if (object == nil)
			return i;

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
	for (id object in self)
		if ([set containsObject: object])
			return true;

	return false;
}

- (OFXMLElement *)XMLElementBySerializing
{
	void *pool = objc_autoreleasePoolPush();
	OFXMLElement *element;

	if ([self isKindOfClass: [OFMutableSet class]])
		element = [OFXMLElement elementWithName: @"OFMutableSet"
					      namespace: OFSerializationNS];
	else
		element = [OFXMLElement elementWithName: @"OFSet"
					      namespace: OFSerializationNS];

	for (id <OFSerialization> object in self) {
		void *pool2 = objc_autoreleasePoolPush();
		[element addChild: object.XMLElementBySerializing];
		objc_autoreleasePoolPop(pool2);
	}

	[element retain];

	objc_autoreleasePoolPop(pool);

	return [element autorelease];
}

- (OFSet *)setByAddingObjectsFromSet: (OFSet *)set
{
	OFMutableSet *new = [[self mutableCopy] autorelease];
	[new unionSet: set];
	[new makeImmutable];
	return new;
}







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







428
429
430
431
432
433
434

























435
436
437
438
439
440
441
	for (id object in self)
		if ([set containsObject: object])
			return true;

	return false;
}


























- (OFSet *)setByAddingObjectsFromSet: (OFSet *)set
{
	OFMutableSet *new = [[self mutableCopy] autorelease];
	[new unionSet: set];
	[new makeImmutable];
	return new;
}

Modified src/OFSettings.h from [372d44cad4] to [cea23e990e].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFSettings.m from [206814d076] to [5381bbc2a1].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Deleted src/OFSizeValue.h version [d063d8cdb8].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the 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 "OFValue.h"

OF_ASSUME_NONNULL_BEGIN

@interface OFSizeValue: OFValue
{
	OFSize _size;
}

- (instancetype)initWithSize: (OFSize)size;
@end

OF_ASSUME_NONNULL_END
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
























































Deleted src/OFSizeValue.m version [86214acf8b].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the 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 "OFSizeValue.h"
#import "OFMethodSignature.h"
#import "OFString.h"

#import "OFOutOfRangeException.h"

@implementation OFSizeValue
@synthesize sizeValue = _size;

- (instancetype)initWithSize: (OFSize)size
{
	self = [super init];

	_size = size;

	return self;
}

- (const char *)objCType
{
	return @encode(OFSize);
}

- (void)getValue: (void *)value size: (size_t)size
{
	if (size != sizeof(_size))
		@throw [OFOutOfRangeException exception];

	memcpy(value, &_size, sizeof(_size));
}

- (OFString *)description
{
	return [OFString stringWithFormat:
	    @"<OFValue: OFSize { %f, %f }>", _size.width, _size.height];
}
@end
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<








































































































Modified src/OFSocket+Private.h from [00458f91c6] to [ed6fe14a59].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#ifdef HAVE_ARPA_INET_H
# include <arpa/inet.h>
#endif
#ifdef HAVE_NETDB_H
# include <netdb.h>
#endif

#include "OFSocket.h"

#ifndef INADDR_NONE
# define INADDR_NONE ((in_addr_t)-1)
#endif

#ifndef SOMAXCONN
/*







|







20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#ifdef HAVE_ARPA_INET_H
# include <arpa/inet.h>
#endif
#ifdef HAVE_NETDB_H
# include <netdb.h>
#endif

#import "OFSocket.h"

#ifndef INADDR_NONE
# define INADDR_NONE ((in_addr_t)-1)
#endif

#ifndef SOMAXCONN
/*

Modified src/OFSocket.h from [18fc1aa593] to [aea5f61629].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76


77
78
79
80
81
82
83
#  include <wsipx.h>
# endif
# ifdef OF_HAVE_APPLETALK
#  include <atalkwsh.h>
# endif
#endif

/** @file */

#ifdef OF_WII
# include <network.h>
#endif

#ifdef OF_PSP
# include <stdint.h>
#endif

#import "macros.h"

OF_ASSUME_NONNULL_BEGIN



#ifndef OF_WINDOWS
typedef int OFSocketHandle;
static const OFSocketHandle OFInvalidSocketHandle = -1;
#else
typedef SOCKET OFSocketHandle;
static const OFSocketHandle OFInvalidSocketHandle = INVALID_SOCKET;







<
<











>
>







57
58
59
60
61
62
63


64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
#  include <wsipx.h>
# endif
# ifdef OF_HAVE_APPLETALK
#  include <atalkwsh.h>
# endif
#endif



#ifdef OF_WII
# include <network.h>
#endif

#ifdef OF_PSP
# include <stdint.h>
#endif

#import "macros.h"

OF_ASSUME_NONNULL_BEGIN

/** @file */

#ifndef OF_WINDOWS
typedef int OFSocketHandle;
static const OFSocketHandle OFInvalidSocketHandle = -1;
#else
typedef SOCKET OFSocketHandle;
static const OFSocketHandle OFInvalidSocketHandle = INVALID_SOCKET;
132
133
134
135
136
137
138
139
140


141
142
143
144
145
146
147
148
149
150
151
152
153
154



155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171

172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190







191
192
193
194
195
196
197
#if !defined(OF_HAVE_UNIX_SOCKETS) && !defined(OF_MORPHOS) && !defined(OF_MINT)
struct sockaddr_un {
	sa_family_t sun_family;
	char sun_path[108];
};
#endif

#ifndef OF_HAVE_IPX
# define IPX_NODE_LEN 6


struct sockaddr_ipx {
	sa_family_t sipx_family;
	uint32_t sipx_network;
	unsigned char sipx_node[IPX_NODE_LEN];
	uint16_t sipx_port;
	uint8_t sipx_type;
};
#endif
#ifdef OF_WINDOWS
# define IPX_NODE_LEN 6
# define sipx_family sa_family
# define sipx_network sa_netnum
# define sipx_node sa_nodenum
# define sipx_port sa_socket



#endif

#ifndef OF_HAVE_APPLETALK
struct sockaddr_at {
	sa_family_t sat_family;
	uint8_t sat_port;
	struct at_addr {
		uint16_t s_net;
		uint8_t s_node;
	} sat_addr;
};
#endif
#ifdef OF_WINDOWS
# define sat_port sat_socket
#else
# define sat_net sat_addr.s_net
# define sat_node sat_addr.s_node

#endif

/**
 * @struct OFSocketAddress OFSocket.h ObjFW/OFSocket.h
 *
 * @brief A struct which represents a host / port pair for a socket.
 */
typedef struct OF_BOXABLE {
	OFSocketAddressFamily family;
	/*
	 * We can't use struct sockaddr as it can contain variable length
	 * arrays.
	 */
	union {
		struct sockaddr_in in;
		struct sockaddr_in6 in6;
		struct sockaddr_un un;
		struct sockaddr_ipx ipx;
		struct sockaddr_at at;







	} sockaddr;
	socklen_t length;
} OFSocketAddress;

#ifdef __cplusplus
extern "C" {
#endif







|

>
>







<
|





>
>
>






<
|
|
<

|
|
|
|
|
|
>







|











>
>
>
>
>
>
>







132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149

150
151
152
153
154
155
156
157
158
159
160
161
162
163
164

165
166

167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
#if !defined(OF_HAVE_UNIX_SOCKETS) && !defined(OF_MORPHOS) && !defined(OF_MINT)
struct sockaddr_un {
	sa_family_t sun_family;
	char sun_path[108];
};
#endif

#ifndef IPX_NODE_LEN
# define IPX_NODE_LEN 6
#endif
#if !defined(OF_HAVE_IPX)
struct sockaddr_ipx {
	sa_family_t sipx_family;
	uint32_t sipx_network;
	unsigned char sipx_node[IPX_NODE_LEN];
	uint16_t sipx_port;
	uint8_t sipx_type;
};

#elif defined(OF_WINDOWS)
# define IPX_NODE_LEN 6
# define sipx_family sa_family
# define sipx_network sa_netnum
# define sipx_node sa_nodenum
# define sipx_port sa_socket
#elif defined(OF_FREEBSD)
# define sipx_network sipx_addr.x_net.c_net
# define sipx_node sipx_addr.x_host.c_host
#endif

#ifndef OF_HAVE_APPLETALK
struct sockaddr_at {
	sa_family_t sat_family;
	uint8_t sat_port;

	uint16_t sat_net;
	uint8_t sat_node;

};
#else
# ifdef OF_WINDOWS
#  define sat_port sat_socket
# else
#  define sat_net sat_addr.s_net
#  define sat_node sat_addr.s_node
# endif
#endif

/**
 * @struct OFSocketAddress OFSocket.h ObjFW/OFSocket.h
 *
 * @brief A struct which represents a host / port pair for a socket.
 */
typedef struct OF_BOXABLE OFSocketAddress {
	OFSocketAddressFamily family;
	/*
	 * We can't use struct sockaddr as it can contain variable length
	 * arrays.
	 */
	union {
		struct sockaddr_in in;
		struct sockaddr_in6 in6;
		struct sockaddr_un un;
		struct sockaddr_ipx ipx;
		struct sockaddr_at at;
#ifdef OF_HAVE_SOCKADDR_STORAGE
		/*
		 * Required to make the ABI stable in case we want to add more
		 * address types later.
		 */
		struct sockaddr_storage storage;
#endif
	} sockaddr;
	socklen_t length;
} OFSocketAddress;

#ifdef __cplusplus
extern "C" {
#endif
276
277
278
279
280
281
282
283
284
285
286
287











288
289
290
291
292
293
294
extern unsigned long OFSocketAddressHash(
    const OFSocketAddress *_Nonnull address);

/**
 * @brief Converts the specified @ref OFSocketAddress to a string.
 *
 * @param address The address to convert to a string
 * @return The address as an IP string
 */
extern OFString *_Nonnull OFSocketAddressString(
    const OFSocketAddress *_Nonnull address);












/**
 * @brief Sets the IP port of the specified @ref OFSocketAddress.
 *
 * @param address The address on which to set the port
 * @param port The port to set on the address
 */
extern void OFSocketAddressSetIPPort(OFSocketAddress *_Nonnull address,







|




>
>
>
>
>
>
>
>
>
>
>







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
extern unsigned long OFSocketAddressHash(
    const OFSocketAddress *_Nonnull address);

/**
 * @brief Converts the specified @ref OFSocketAddress to a string.
 *
 * @param address The address to convert to a string
 * @return The address as a string, without the port
 */
extern OFString *_Nonnull OFSocketAddressString(
    const OFSocketAddress *_Nonnull address);

/**
 * @brief Returns a description for the specified @ref OFSocketAddress.
 *
 * This is similar to @ref OFSocketAddressString, but it also contains the port.
 *
 * @param address The address to return a description for
 * @return The address as an string, with the port
 */
extern OFString *_Nonnull OFSocketAddressDescription(
    const OFSocketAddress *_Nonnull address);

/**
 * @brief Sets the IP port of the specified @ref OFSocketAddress.
 *
 * @param address The address on which to set the port
 * @param port The port to set on the address
 */
extern void OFSocketAddressSetIPPort(OFSocketAddress *_Nonnull address,
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318

/**
 * @brief Gets the UNIX socket path of the specified @ref OFSocketAddress.
 *
 * @param address The address on which to get the UNIX socket path
 * @return The UNIX socket path
 */
extern OFString *_Nullable OFSocketAddressUNIXPath(
    const OFSocketAddress *_Nonnull address);

/**
 * @brief Sets the IPX network of the specified @ref OFSocketAddress.
 *
 * @param address The address on which to set the IPX network
 * @param network The IPX network to set on the address







|







325
326
327
328
329
330
331
332
333
334
335
336
337
338
339

/**
 * @brief Gets the UNIX socket path of the specified @ref OFSocketAddress.
 *
 * @param address The address on which to get the UNIX socket path
 * @return The UNIX socket path
 */
extern OFString *OFSocketAddressUNIXPath(
    const OFSocketAddress *_Nonnull address);

/**
 * @brief Sets the IPX network of the specified @ref OFSocketAddress.
 *
 * @param address The address on which to set the IPX network
 * @param network The IPX network to set on the address

Modified src/OFSocket.m from [3facc57fe7] to [df2e9d8f9d].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
49
50
51
52
53
54
55

56

57
58
59
60
61
62
63
#import "OFUnlockFailedException.h"

#ifdef HAVE_NET_IF_H
# include <net/if.h>
#endif

#ifdef OF_AMIGAOS

# include <proto/exec.h>

#endif

#ifdef OF_NINTENDO_3DS
# include <3ds/types.h>
# include <3ds/services/soc.h>
#endif








>

>







49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#import "OFUnlockFailedException.h"

#ifdef HAVE_NET_IF_H
# include <net/if.h>
#endif

#ifdef OF_AMIGAOS
# define Class IntuitionClass
# include <proto/exec.h>
# undef Class
#endif

#ifdef OF_NINTENDO_3DS
# include <3ds/types.h>
# include <3ds/services/soc.h>
#endif

426
427
428
429
430
431
432




























433
434
435
436
437
438
439
	number = [component unsignedLongLongValueWithBase: 16];

	if (number > UINT16_MAX)
		@throw [OFInvalidFormatException exception];

	return (uint16_t)number;
}





























OFSocketAddress
OFSocketAddressParseIPv6(OFString *IPv6, uint16_t port)
{
	void *pool = objc_autoreleasePoolPush();
	OFSocketAddress ret;
	struct sockaddr_in6 *addrIn6 = &ret.sockaddr.in6;







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
	number = [component unsignedLongLongValueWithBase: 16];

	if (number > UINT16_MAX)
		@throw [OFInvalidFormatException exception];

	return (uint16_t)number;
}

static OFString *
transformEmbeddedIPv4(OFString *IPv6)
{
	size_t lastColon = [IPv6
	    rangeOfString: @":"
		  options: OFStringSearchBackwards].location;
	OFString *IPv4;
	OFSocketAddress address;
	const struct sockaddr_in *addrIn;
	uint32_t addr;

	if (lastColon == OFNotFound)
		@throw [OFInvalidFormatException exception];

	IPv4 = [IPv6 substringWithRange:
	    OFMakeRange(lastColon + 1, IPv6.length - lastColon - 1)];
	IPv6 = [IPv6 substringWithRange: OFMakeRange(0, lastColon + 1)];

	address = OFSocketAddressParseIPv4(IPv4, 0);
	addrIn = &address.sockaddr.in;
	addr = OFFromBigEndian32(addrIn->sin_addr.s_addr);

	return [IPv6 stringByAppendingString:
	    [OFString stringWithFormat: @"%x%02x:%x%02x",
	    (addr & 0xFF000000) >> 24, (addr & 0x00FF0000) >> 16,
	    (addr & 0x0000FF00) >>  8, addr & 0x000000FF]];
}

OFSocketAddress
OFSocketAddressParseIPv6(OFString *IPv6, uint16_t port)
{
	void *pool = objc_autoreleasePoolPush();
	OFSocketAddress ret;
	struct sockaddr_in6 *addrIn6 = &ret.sockaddr.in6;
463
464
465
466
467
468
469



470
471
472
473
474
475
476
			    cStringWithEncoding: [OFLocale encoding]]);
#endif
		}

		if (addrIn6->sin6_scope_id == 0)
			@throw [OFInvalidArgumentException exception];
	}




	doubleColon = [IPv6 rangeOfString: @"::"].location;
	if (doubleColon != OFNotFound) {
		OFString *left = [IPv6 substringToIndex: doubleColon];
		OFString *right = [IPv6 substringFromIndex: doubleColon + 2];
		OFArray OF_GENERIC(OFString *) *leftComponents;
		OFArray OF_GENERIC(OFString *) *rightComponents;







>
>
>







493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
			    cStringWithEncoding: [OFLocale encoding]]);
#endif
		}

		if (addrIn6->sin6_scope_id == 0)
			@throw [OFInvalidArgumentException exception];
	}

	if ([IPv6 rangeOfString: @"."].location != OFNotFound)
		IPv6 = transformEmbeddedIPv4(IPv6);

	doubleColon = [IPv6 rangeOfString: @"::"].location;
	if (doubleColon != OFNotFound) {
		OFString *left = [IPv6 substringToIndex: doubleColon];
		OFString *right = [IPv6 substringFromIndex: doubleColon + 2];
		OFArray OF_GENERIC(OFString *) *leftComponents;
		OFArray OF_GENERIC(OFString *) *rightComponents;
553
554
555
556
557
558
559



560
561
562
563
564
565
566
		@throw [OFOutOfRangeException exception];

	memset(&ret, '\0', sizeof(ret));
	ret.family = OFSocketAddressFamilyUNIX;
	ret.length = (socklen_t)
	    (offsetof(struct sockaddr_un, sun_path) + length);




#ifdef AF_UNIX
	ret.sockaddr.un.sun_family = AF_UNIX;
#else
	ret.sockaddr.un.sun_family = AF_UNSPEC;
#endif
	memcpy(ret.sockaddr.un.sun_path,
	    [path cStringWithEncoding: encoding], length);







>
>
>







586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
		@throw [OFOutOfRangeException exception];

	memset(&ret, '\0', sizeof(ret));
	ret.family = OFSocketAddressFamilyUNIX;
	ret.length = (socklen_t)
	    (offsetof(struct sockaddr_un, sun_path) + length);

#ifdef HAVE_STRUCT_SOCKADDR_UN_SUN_LEN
	ret.sockaddr.un.sun_len = (uint8_t)length;
#endif
#ifdef AF_UNIX
	ret.sockaddr.un.sun_family = AF_UNIX;
#else
	ret.sockaddr.un.sun_family = AF_UNSPEC;
#endif
	memcpy(ret.sockaddr.un.sun_path,
	    [path cStringWithEncoding: encoding], length);
902
903
904
905
906
907
908




























909
910
911
912
913
914
915
916
917






918
919





























920
921
922
923
924
925
926
			[string appendFormat: @"%%%u", addrIn6->sin6_scope_id];
	}

	[string makeImmutable];

	return string;
}





























OFString *
OFSocketAddressString(const OFSocketAddress *address)
{
	switch (address->family) {
	case OFSocketAddressFamilyIPv4:
		return IPv4String(address);
	case OFSocketAddressFamilyIPv6:
		return IPv6String(address);






	default:
		@throw [OFInvalidArgumentException exception];





























	}
}

void
OFSocketAddressSetIPPort(OFSocketAddress *address, uint16_t port)
{
	switch (address->family) {







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>









>
>
>
>
>
>


>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
			[string appendFormat: @"%%%u", addrIn6->sin6_scope_id];
	}

	[string makeImmutable];

	return string;
}

static OFString *
IPXString(const OFSocketAddress *address)
{
	const struct sockaddr_ipx *addrIPX = &address->sockaddr.ipx;
	uint32_t network;
	uint64_t node;

	memcpy(&network, &addrIPX->sipx_network, sizeof(addrIPX->sipx_network));
	node = ((uint64_t)addrIPX->sipx_node[0] << 40) |
	    ((uint64_t)addrIPX->sipx_node[1] << 32) |
	    ((uint64_t)addrIPX->sipx_node[2] << 24) |
	    ((uint64_t)addrIPX->sipx_node[3] << 16) |
	    ((uint64_t)addrIPX->sipx_node[4] << 8) |
	    (uint64_t)addrIPX->sipx_node[5];

	return [OFString stringWithFormat: @"%" PRIX32 ".%" PRIX64,
	    OFFromBigEndian32(network), node];
}

static OFString *
appleTalkString(const OFSocketAddress *address)
{
	const struct sockaddr_at *addrAT = &address->sockaddr.at;

	return [OFString stringWithFormat: @"%" PRIu8 ".%" PRIu8,
	    OFFromBigEndian16(addrAT->sat_net), addrAT->sat_node];
}

OFString *
OFSocketAddressString(const OFSocketAddress *address)
{
	switch (address->family) {
	case OFSocketAddressFamilyIPv4:
		return IPv4String(address);
	case OFSocketAddressFamilyIPv6:
		return IPv6String(address);
	case OFSocketAddressFamilyUNIX:
		return OFSocketAddressUNIXPath(address);
	case OFSocketAddressFamilyIPX:
		return IPXString(address);
	case OFSocketAddressFamilyAppleTalk:
		return appleTalkString(address);
	default:
		@throw [OFInvalidArgumentException exception];
	}
}

OFString *
OFSocketAddressDescription(const OFSocketAddress *address)
{
	switch (address->family) {
	case OFSocketAddressFamilyIPv4:
		return [OFString
		    stringWithFormat: @"%@:%" PRIu16,
				      IPv4String(address),
				      OFSocketAddressIPPort(address)];
	case OFSocketAddressFamilyIPv6:
		return [OFString
		    stringWithFormat: @"[%@]:%" PRIu16,
				      IPv6String(address),
				      OFSocketAddressIPPort(address)];
	case OFSocketAddressFamilyIPX:
		return [OFString
		    stringWithFormat: @"%@.%" PRIX16,
				      IPXString(address),
				      OFSocketAddressIPXPort(address)];
	case OFSocketAddressFamilyAppleTalk:
		return [OFString
		    stringWithFormat: @"%@." PRIu8,
				      appleTalkString(address),
				      OFSocketAddressAppleTalkPort(address)];
	default:
		return OFSocketAddressString(address);
	}
}

void
OFSocketAddressSetIPPort(OFSocketAddress *address, uint16_t port)
{
	switch (address->family) {
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974

	length = address->length - offsetof(struct sockaddr_un, sun_path);

	for (socklen_t i = 0; i < length; i++)
		if (address->sockaddr.un.sun_path[i] == 0)
			length = i;

	if (length <= 0)
		return nil;

	return [OFString stringWithCString: address->sockaddr.un.sun_path
				  encoding: [OFLocale encoding]
				    length: length];
}

void
OFSocketAddressSetIPXNetwork(OFSocketAddress *address, uint32_t network)







<
<
<







1057
1058
1059
1060
1061
1062
1063



1064
1065
1066
1067
1068
1069
1070

	length = address->length - offsetof(struct sockaddr_un, sun_path);

	for (socklen_t i = 0; i < length; i++)
		if (address->sockaddr.un.sun_path[i] == 0)
			length = i;




	return [OFString stringWithCString: address->sockaddr.un.sun_path
				  encoding: [OFLocale encoding]
				    length: length];
}

void
OFSocketAddressSetIPXNetwork(OFSocketAddress *address, uint32_t network)

Modified src/OFSortedList.h from [3a5eb28c9b] to [89b2623e39].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFSortedList.m from [8d1674288f] to [ca3c0bf6b4].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFStdIOStream+Private.h from [9900a9e7b0] to [4e119ffb36].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFStdIOStream.h from [2dc46172ae] to [ae9c3b4c20].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFStdIOStream.m from [ef45e21ee6] to [b97df9550f].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
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

#import "OFStdIOStream.h"
#import "OFStdIOStream+Private.h"
#import "OFColor.h"
#import "OFDate.h"
#import "OFApplication.h"
#ifdef OF_WINDOWS
# include "OFWin32ConsoleStdIOStream.h"
#endif

#import "OFInitializationFailedException.h"
#import "OFInvalidArgumentException.h"
#import "OFNotOpenException.h"
#import "OFOutOfRangeException.h"
#import "OFReadFailedException.h"
#import "OFWriteFailedException.h"

#ifdef OF_IOS
# undef HAVE_ISATTY
#endif

#ifdef OF_AMIGAOS

# include <proto/exec.h>
# include <proto/dos.h>

# undef HAVE_ISATTY
#endif

#ifdef OF_WII_U
# define BOOL WUT_BOOL
# include <coreinit/debug.h>
# undef BOOL







|














>


>







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

#import "OFStdIOStream.h"
#import "OFStdIOStream+Private.h"
#import "OFColor.h"
#import "OFDate.h"
#import "OFApplication.h"
#ifdef OF_WINDOWS
# import "OFWin32ConsoleStdIOStream.h"
#endif

#import "OFInitializationFailedException.h"
#import "OFInvalidArgumentException.h"
#import "OFNotOpenException.h"
#import "OFOutOfRangeException.h"
#import "OFReadFailedException.h"
#import "OFWriteFailedException.h"

#ifdef OF_IOS
# undef HAVE_ISATTY
#endif

#ifdef OF_AMIGAOS
# define Class IntuitionClass
# include <proto/exec.h>
# include <proto/dos.h>
# undef Class
# undef HAVE_ISATTY
#endif

#ifdef OF_WII_U
# define BOOL WUT_BOOL
# include <coreinit/debug.h>
# undef BOOL
100
101
102
103
104
105
106



107
108
109
110
111
112
113
	date = [OFDate date];
	dateString = [date localDateStringWithFormat: @"%Y-%m-%d %H:%M:%S"];
#ifdef OF_HAVE_FILES
	me = [OFApplication programName].lastPathComponent;
#else
	me = [OFApplication programName];
#endif




	msg = [[[OFString alloc] initWithFormat: format
				      arguments: arguments] autorelease];

	[OFStdErr writeFormat: @"[%@.%03d %@(%d)] %@\n", dateString,
			       date.microsecond / 1000, me, getpid(), msg];








>
>
>







102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
	date = [OFDate date];
	dateString = [date localDateStringWithFormat: @"%Y-%m-%d %H:%M:%S"];
#ifdef OF_HAVE_FILES
	me = [OFApplication programName].lastPathComponent;
#else
	me = [OFApplication programName];
#endif

	if (me == nil)
		me = @"?";

	msg = [[[OFString alloc] initWithFormat: format
				      arguments: arguments] autorelease];

	[OFStdErr writeFormat: @"[%@.%03d %@(%d)] %@\n", dateString,
			       date.microsecond / 1000, me, getpid(), msg];

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
#else
	return false;
#endif
}

- (int)columns
{
#if defined(HAVE_SYS_IOCTL_H) && defined(TIOCGWINSZ) && \
    !defined(OF_AMIGAOS) && !defined(OF_WII_U)
	struct winsize ws;

	if (ioctl(_fd, TIOCGWINSZ, &ws) != 0)
		return -1;

	return ws.ws_col;
#else
	return -1;
#endif
}

- (int)rows
{
#if defined(HAVE_SYS_IOCTL_H) && defined(TIOCGWINSZ) && \
    !defined(OF_AMIGAOS) && !defined(OF_WII_U)
	struct winsize ws;

	if (ioctl(_fd, TIOCGWINSZ, &ws) != 0)
		return -1;

	return ws.ws_row;







|














|







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
#else
	return false;
#endif
}

- (int)columns
{
#if defined(HAVE_IOCTL) && defined(TIOCGWINSZ) && \
    !defined(OF_AMIGAOS) && !defined(OF_WII_U)
	struct winsize ws;

	if (ioctl(_fd, TIOCGWINSZ, &ws) != 0)
		return -1;

	return ws.ws_col;
#else
	return -1;
#endif
}

- (int)rows
{
#if defined(HAVE_IOCTL) && defined(TIOCGWINSZ) && \
    !defined(OF_AMIGAOS) && !defined(OF_WII_U)
	struct winsize ws;

	if (ioctl(_fd, TIOCGWINSZ, &ws) != 0)
		return -1;

	return ws.ws_row;

Added src/OFStrFTime.h version [c3ea31434b].













































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
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.
 */

#ifndef __STDC_LIMIT_MACROS
# define __STDC_LIMIT_MACROS
#endif
#ifndef __STDC_CONSTANT_MACROS
# define __STDC_CONSTANT_MACROS
#endif

#include <time.h>

#import "macros.h"

OF_ASSUME_NONNULL_BEGIN

#ifdef __cplusplus
extern "C" {
#endif
extern size_t OFStrFTime(char *buffer, size_t bufferLen, const char *format,
    struct tm *tm, short tz);
#ifdef __cplusplus
}
#endif

OF_ASSUME_NONNULL_END

Added src/OFStrFTime.m version [db5943ae95].









































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
/*
 * Copyright (c) 2008-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>
#include <time.h>

#import "OFStrFTime.h"
#import "macros.h"

static const char weekDays[7][4] = {
	"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
};
static const char monthNames[12][4] = {
	"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct",
	"Nov", "Dec"
};

size_t
OFStrFTime(char *buffer, size_t bufferLen, const char *format, struct tm *tm,
    short tz)
{
	enum {
		stateSearchConversionSpecifier,
		stateInConversionSpecifier
	} state = stateSearchConversionSpecifier;
	size_t j, formatLen;

	if (bufferLen == 0)
		return 0;

	formatLen = strlen(format);

	j = 0;
	for (size_t i = 0; i < formatLen; i++) {
		switch (state) {
		case stateSearchConversionSpecifier:
			if (format[i] == '%')
				state = stateInConversionSpecifier;
			else {
				if (j >= bufferLen)
					return 0;

				buffer[j++] = format[i];
			}

			break;
		case stateInConversionSpecifier:;
			const char *appendFormat;
			unsigned int value = 0;
			char append[5];
			int appendLen;

			switch (format[i]) {
			case '%':
				appendFormat = "%%";
				break;
			case 'a':
				if (tm->tm_wday > 6)
					return 0;

				appendFormat = weekDays[tm->tm_wday];
				break;
			case 'b':
				if (tm->tm_mon > 11)
					return 0;

				appendFormat = monthNames[tm->tm_mon];
				break;
			case 'd':
				appendFormat = "%02u";
				value = tm->tm_mday;
				break;
			case 'e':
				appendFormat = "%2u";
				value = tm->tm_mday;
				break;
			case 'H':
				appendFormat = "%02u";
				value = tm->tm_hour;
				break;
			case 'M':
				appendFormat = "%02u";
				value = tm->tm_min;
				break;
			case 'm':
				appendFormat = "%02u";
				value = tm->tm_mon + 1;
				break;
			case 'n':
				appendFormat = "\n";
				break;
			case 'S':
				appendFormat = "%02u";
				value = tm->tm_sec;
				break;
			case 't':
				appendFormat = "\t";
				break;
			case 'Y':
				appendFormat = "%4u";
				value = tm->tm_year + 1900;
				break;
			case 'y':
				appendFormat = "%02u";
				value = tm->tm_year;

				while (value > 100)
					value -= 100;

				break;
			case 'z':
				if (tz == 0)
					appendFormat = "Z";
				else if (tz >= 0) {
					appendFormat = "+%04u";
					value = tz;
				} else {
					appendFormat = "-%04u";
					value = -tz;
				}

				value = (value / 60) * 100 + (value % 60);
				break;
			default:
				return 0;
			}

			appendLen = snprintf(append, sizeof(append),
			    appendFormat, value);
			if (appendLen < 0 ||
			    (size_t)appendLen >= sizeof(append))
				return 0;

			if (bufferLen - j < (size_t)appendLen)
				return 0;

			memcpy(buffer + j, append, appendLen);
			j += appendLen;

			state = stateSearchConversionSpecifier;
		}
	}

	if (j >= bufferLen)
		return 0;

	buffer[j] = 0;

	return j;
}

Modified src/OFStrPTime.h from [0432d594e4] to [aeee53216f].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFStrPTime.m from [7afa230e7d] to [ca9eda8b60].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the 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>

#include <time.h>

#import "macros.h"

const char *
OFStrPTime(const char *buffer, const char *format, struct tm *tm, short *tz)
{
	enum {
		stateSearchConversionSpecifier,

|

















<
|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

20
21
22
23
24
25
26
27
/*
 * Copyright (c) 2008-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 "OFStrPTime.h"
#import "macros.h"

const char *
OFStrPTime(const char *buffer, const char *format, struct tm *tm, short *tz)
{
	enum {
		stateSearchConversionSpecifier,

Modified src/OFStream+Private.h from [571ecdcdc3] to [12da5edb5d].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#import "OFStream.h"

OF_ASSUME_NONNULL_BEGIN

OF_DIRECT_MEMBERS
@interface OFStream ()
@property (readonly, nonatomic, getter=of_isWaitingForDelimiter)
    bool of_waitingForDelimiter;
@end

OF_ASSUME_NONNULL_END

|

















<






1
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 "OFStream.h"

OF_ASSUME_NONNULL_BEGIN


@interface OFStream ()
@property (readonly, nonatomic, getter=of_isWaitingForDelimiter)
    bool of_waitingForDelimiter;
@end

OF_ASSUME_NONNULL_END

Modified src/OFStream.h from [a93512463b] to [80480e6665].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
214
215
216
217
218
219
220

221
222
223
224
225
226
227

/**
 * @brief Whether the stream can block.
 *
 * By default, a stream can block.
 * On Win32, setting this currently only works for sockets!
 *

 * @throw OFSetOptionFailedException The option could not be set
 */
@property (nonatomic) bool canBlock;

/**
 * @brief The delegate for asynchronous operations on the stream.
 *







>







214
215
216
217
218
219
220
221
222
223
224
225
226
227
228

/**
 * @brief Whether the stream can block.
 *
 * By default, a stream can block.
 * On Win32, setting this currently only works for sockets!
 *
 * @throw OFGetOptionFailedException The option could not be retrieved
 * @throw OFSetOptionFailedException The option could not be set
 */
@property (nonatomic) bool canBlock;

/**
 * @brief The delegate for asynchronous operations on the stream.
 *
1386
1387
1388
1389
1390
1391
1392












1393
1394
1395
 *
 * @note Override this method with your actual end of stream checking
 *	 implementation when subclassing!
 *
 * @return Whether the lowlevel is at the end of the stream
 */
- (bool)lowlevelIsAtEndOfStream;












@end

OF_ASSUME_NONNULL_END







>
>
>
>
>
>
>
>
>
>
>
>



1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
 *
 * @note Override this method with your actual end of stream checking
 *	 implementation when subclassing!
 *
 * @return Whether the lowlevel is at the end of the stream
 */
- (bool)lowlevelIsAtEndOfStream;

/**
 * @brief Returns whether the lowlevel has data in the read buffer.
 *
 * @warning Do not call this directly!
 *
 * @note Override this method in case your stream can buffer data itself, such
 *	 as when implementing @ref OFTLSStream. If not overridden, it always
 *	 returns false.
 * @return Whether the lowlevel has data in the read buffer
 */
- (bool)lowlevelHasDataInReadBuffer;
@end

OF_ASSUME_NONNULL_END

Modified src/OFStream.m from [e660892e5a] to [908730005b].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#define __NO_EXT_QNX

#include "config.h"

#include <assert.h>
#include <errno.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#ifdef HAVE_FCNTL_H

|

















<







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

20
21
22
23
24
25
26
/*
 * 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.
 */

#define __NO_EXT_QNX

#include "config.h"


#include <errno.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#ifdef HAVE_FCNTL_H
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
{
	OFFreeMemory(_readBufferMemory);
	OFFreeMemory(_writeBuffer);

	[super dealloc];
}

- (bool)lowlevelIsAtEndOfStream
{
	OF_UNRECOGNIZED_SELECTOR
}

- (size_t)lowlevelReadIntoBuffer: (void *)buffer length: (size_t)length
{
	OF_UNRECOGNIZED_SELECTOR
}

- (size_t)lowlevelWriteBuffer: (const void *)buffer length: (size_t)length
{
	OF_UNRECOGNIZED_SELECTOR
}











- (id)copy
{
	return [self retain];
}

- (bool)isAtEndOfStream







<
<
<
<
<









>
>
>
>
>
>
>
>
>
>







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
{
	OFFreeMemory(_readBufferMemory);
	OFFreeMemory(_writeBuffer);

	[super dealloc];
}






- (size_t)lowlevelReadIntoBuffer: (void *)buffer length: (size_t)length
{
	OF_UNRECOGNIZED_SELECTOR
}

- (size_t)lowlevelWriteBuffer: (const void *)buffer length: (size_t)length
{
	OF_UNRECOGNIZED_SELECTOR
}

- (bool)lowlevelIsAtEndOfStream
{
	OF_UNRECOGNIZED_SELECTOR
}

- (bool)lowlevelHasDataInReadBuffer
{
	return false;
}

- (id)copy
{
	return [self retain];
}

- (bool)isAtEndOfStream
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
			if (j == delimiterLength || _readBuffer[i] == '\0') {
				if (_readBuffer[i] == '\0')
					delimiterLength = 1;

				ret = [OFString
				    stringWithCString: _readBuffer
					     encoding: encoding
					      length: i + 1 - delimiterLength];

				_readBuffer += i + 1;
				_readBufferLength -= i + 1;

				_waitingForDelimiter = false;
				return ret;
			}







|







702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
			if (j == delimiterLength || _readBuffer[i] == '\0') {
				if (_readBuffer[i] == '\0')
					delimiterLength = 1;

				ret = [OFString
				    stringWithCString: _readBuffer
					     encoding: encoding
					       length: i + 1 - delimiterLength];

				_readBuffer += i + 1;
				_readBufferLength -= i + 1;

				_waitingForDelimiter = false;
				return ret;
			}
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
	} @finally {
		free(UTF8String);
	}
}

- (bool)hasDataInReadBuffer
{
	return (_readBufferLength > 0);
}

- (bool)canBlock
{
	return _canBlock;
}








|







1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
	} @finally {
		free(UTF8String);
	}
}

- (bool)hasDataInReadBuffer
{
	return (_readBufferLength > 0 || [self lowlevelHasDataInReadBuffer]);
}

- (bool)canBlock
{
	return _canBlock;
}

Modified src/OFStreamSocket+Private.h from [a23e5c50d7] to [523f6c5a2a].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFStreamSocket.h from [700ee89673] to [683f69fec6].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
62
63
64
65
66
67
68




69
70
71
72
73
74
75
 *
 * @brief A class which provides methods to create and use stream sockets.
 */
@interface OFStreamSocket: OFStream <OFReadyForReadingObserving,
    OFReadyForWritingObserving>
{
	OFSocketHandle _socket;




	bool _atEndOfStream, _listening;
	OFSocketAddress _remoteAddress;
	OF_RESERVE_IVARS(OFStreamSocket, 4)
}

/**
 * @brief Whether the socket is a listening socket.







>
>
>
>







62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
 *
 * @brief A class which provides methods to create and use stream sockets.
 */
@interface OFStreamSocket: OFStream <OFReadyForReadingObserving,
    OFReadyForWritingObserving>
{
	OFSocketHandle _socket;
#ifdef OF_AMIGAOS
	LONG _socketID;
	int _family;	/* unused, reserved for ABI stability */
#endif
	bool _atEndOfStream, _listening;
	OFSocketAddress _remoteAddress;
	OF_RESERVE_IVARS(OFStreamSocket, 4)
}

/**
 * @brief Whether the socket is a listening socket.
157
158
159
160
161
162
163
























164
165
166
 * @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: (OFStreamSocketAsyncAcceptBlock)block;
#endif
























@end

OF_ASSUME_NONNULL_END







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>



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
 * @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: (OFStreamSocketAsyncAcceptBlock)block;
#endif

/**
 * @brief Releases the socket from the current thread.
 *
 * This is necessary on some platforms in order to allow a different thread to
 * use the socket, e.g. on AmigaOS, but you should call it on all operating
 * systems before using the socket from a different thread.
 *
 * After calling this method, you must no longer use the socket until
 * @ref obtainSocketForCurrentThread has been called.
 */
- (void)releaseSocketFromCurrentThread;

/**
 * @brief Obtains the socket for the current thread.
 *
 * This is necessary on some platforms in order to allow a different thread to
 * use the socket, e.g. on AmigaOS, but you should call it on all operating
 * systems before using the socket from a different thread.
 *
 * You must only call this method after @ref releaseSocketFromCurrentThread has
 * been called from a different thread.
 */
- (void)obtainSocketForCurrentThread;
@end

OF_ASSUME_NONNULL_END

Modified src/OFStreamSocket.m from [efe4f02a49] to [f9f8a407eb].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
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

#ifndef _XOPEN_SOURCE_EXTENDED
# define _XOPEN_SOURCE_EXTENDED
#endif
#define __NO_EXT_QNX
#define _HPUX_ALT_XOPEN_SOCKET_API

#include <assert.h>
#include <errno.h>
#include <string.h>

#import "OFStreamSocket.h"
#import "OFStreamSocket+Private.h"
#import "OFRunLoop.h"
#import "OFRunLoop+Private.h"
#import "OFSocket+Private.h"

#import "OFAcceptSocketFailedException.h"

#import "OFInitializationFailedException.h"
#import "OFInvalidArgumentException.h"
#import "OFListenOnSocketFailedException.h"
#import "OFNotImplementedException.h"
#import "OFNotOpenException.h"

#import "OFOutOfRangeException.h"
#import "OFReadFailedException.h"
#import "OFSetOptionFailedException.h"
#import "OFWriteFailedException.h"





@implementation OFStreamSocket
@dynamic delegate;
@synthesize listening = _listening;

+ (void)initialize
{







<










>





>




>
>
>
>







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

#ifndef _XOPEN_SOURCE_EXTENDED
# define _XOPEN_SOURCE_EXTENDED
#endif
#define __NO_EXT_QNX
#define _HPUX_ALT_XOPEN_SOCKET_API


#include <errno.h>
#include <string.h>

#import "OFStreamSocket.h"
#import "OFStreamSocket+Private.h"
#import "OFRunLoop.h"
#import "OFRunLoop+Private.h"
#import "OFSocket+Private.h"

#import "OFAcceptSocketFailedException.h"
#import "OFAlreadyOpenException.h"
#import "OFInitializationFailedException.h"
#import "OFInvalidArgumentException.h"
#import "OFListenOnSocketFailedException.h"
#import "OFNotImplementedException.h"
#import "OFNotOpenException.h"
#import "OFOutOfMemoryException.h"
#import "OFOutOfRangeException.h"
#import "OFReadFailedException.h"
#import "OFSetOptionFailedException.h"
#import "OFWriteFailedException.h"

#if defined(OF_AMIGAOS) && !defined(UNIQUE_ID)
# define UNIQUE_ID -1
#endif

@implementation OFStreamSocket
@dynamic delegate;
@synthesize listening = _listening;

+ (void)initialize
{
68
69
70
71
72
73
74



75
76
77
78
79
80
81
	@try {
		if (self.class == [OFStreamSocket class]) {
			[self doesNotRecognizeSelector: _cmd];
			abort();
		}

		_socket = OFInvalidSocketHandle;



	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}







>
>
>







73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
	@try {
		if (self.class == [OFStreamSocket class]) {
			[self doesNotRecognizeSelector: _cmd];
			abort();
		}

		_socket = OFInvalidSocketHandle;
#ifdef OF_AMIGAOS
		_socketID = -1;
#endif
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}
239
240
241
242
243
244
245
246
247
248
249
250
251
252




253
254
255
256
257
258
259
				  errNo: OFSocketErrNo()];

	_listening = true;
}

- (instancetype)accept
{
	OFStreamSocket *client = [[[[self class] alloc] init] autorelease];
#if (!defined(HAVE_PACCEPT) && !defined(HAVE_ACCEPT4)) || !defined(SOCK_CLOEXEC)
# if defined(HAVE_FCNTL) && defined(FD_CLOEXEC)
	int flags;
# endif
#endif





	client->_remoteAddress.length =
	    (socklen_t)sizeof(client->_remoteAddress.sockaddr);

#if defined(HAVE_PACCEPT) && defined(SOCK_CLOEXEC)
	if ((client->_socket = paccept(_socket,
	    (struct sockaddr *)&client->_remoteAddress.sockaddr,
	    &client->_remoteAddress.length, NULL, SOCK_CLOEXEC)) ==







|






>
>
>
>







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
				  errNo: OFSocketErrNo()];

	_listening = true;
}

- (instancetype)accept
{
	OFStreamSocket *client;
#if (!defined(HAVE_PACCEPT) && !defined(HAVE_ACCEPT4)) || !defined(SOCK_CLOEXEC)
# if defined(HAVE_FCNTL) && defined(FD_CLOEXEC)
	int flags;
# endif
#endif

	if (_socket == OFInvalidSocketHandle)
		@throw [OFNotOpenException exceptionWithObject: self];

	client = [[[[self class] alloc] init] autorelease];
	client->_remoteAddress.length =
	    (socklen_t)sizeof(client->_remoteAddress.sockaddr);

#if defined(HAVE_PACCEPT) && defined(SOCK_CLOEXEC)
	if ((client->_socket = paccept(_socket,
	    (struct sockaddr *)&client->_remoteAddress.sockaddr,
	    &client->_remoteAddress.length, NULL, SOCK_CLOEXEC)) ==
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293

# if defined(HAVE_FCNTL) && defined(FD_CLOEXEC)
	if ((flags = fcntl(client->_socket, F_GETFD, 0)) != -1)
		fcntl(client->_socket, F_SETFD, flags | FD_CLOEXEC);
# endif
#endif

	assert(client->_remoteAddress.length <=
	    (socklen_t)sizeof(client->_remoteAddress.sockaddr));

	switch (((struct sockaddr *)&client->_remoteAddress.sockaddr)
	    ->sa_family) {
	case AF_INET:
		client->_remoteAddress.family = OFSocketAddressFamilyIPv4;
		break;







|







291
292
293
294
295
296
297
298
299
300
301
302
303
304
305

# if defined(HAVE_FCNTL) && defined(FD_CLOEXEC)
	if ((flags = fcntl(client->_socket, F_GETFD, 0)) != -1)
		fcntl(client->_socket, F_SETFD, flags | FD_CLOEXEC);
# endif
#endif

	OFAssert(client->_remoteAddress.length <=
	    (socklen_t)sizeof(client->_remoteAddress.sockaddr));

	switch (((struct sockaddr *)&client->_remoteAddress.sockaddr)
	    ->sa_family) {
	case AF_INET:
		client->_remoteAddress.family = OFSocketAddressFamilyIPv4;
		break;
352
353
354
355
356
357
358













































359
360
361
362
363
364
365
		@throw [OFInvalidArgumentException exception];

	if (_remoteAddress.length > (socklen_t)sizeof(_remoteAddress.sockaddr))
		@throw [OFOutOfRangeException exception];

	return &_remoteAddress;
}














































- (void)close
{
	if (_socket == OFInvalidSocketHandle)
		@throw [OFNotOpenException exceptionWithObject: self];

	_listening = false;







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
		@throw [OFInvalidArgumentException exception];

	if (_remoteAddress.length > (socklen_t)sizeof(_remoteAddress.sockaddr))
		@throw [OFOutOfRangeException exception];

	return &_remoteAddress;
}

- (void)releaseSocketFromCurrentThread
{
#ifdef OF_AMIGAOS
	if (_socket == OFInvalidSocketHandle)
		@throw [OFNotOpenException exceptionWithObject: self];

	if ((_socketID = ReleaseSocket(_socket, UNIQUE_ID)) == -1) {
		switch (Errno()) {
		case ENOMEM:
			@throw [OFOutOfMemoryException
			    exceptionWithRequestedSize: 0];
		case EBADF:
			@throw [OFNotOpenException exceptionWithObject: self];
		default:
			OFEnsure(0);
		}
	}

	_socket = OFInvalidSocketHandle;
#endif
}

- (void)obtainSocketForCurrentThread
{
#ifdef OF_AMIGAOS
	if (_socket != OFInvalidSocketHandle)
		@throw [OFAlreadyOpenException exceptionWithObject: self];

	if (_socketID == -1)
		@throw [OFNotOpenException exceptionWithObject: self];

	/*
	 * FIXME: We should store these, but that requires changing all
	 *	  subclasses. This only becomes a problem if IPv6 support ever
	 *	  gets added.
	 */
	_socket = ObtainSocket(_socketID, AF_INET, SOCK_STREAM, 0);
	if (_socket == OFInvalidSocketHandle)
		@throw [OFInitializationFailedException
		    exceptionWithClass: self.class];

	_socketID = -1;
#endif
}

- (void)close
{
	if (_socket == OFInvalidSocketHandle)
		@throw [OFNotOpenException exceptionWithObject: self];

	_listening = false;

Modified src/OFString+CryptographicHashing.h from [63c51821ee] to [4270693c1e].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFString+CryptographicHashing.m from [30b5bea6f8] to [ae529a7026].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFString+JSONParsing.h from [77287ce8c5] to [c70e87a861].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFString+JSONParsing.m from [5489126d7d] to [2a3fb814b9].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#include <stdlib.h>
#include <string.h>

#include <math.h>

#include <assert.h>

#import "OFString+JSONParsing.h"
#import "OFArray.h"
#import "OFDictionary.h"
#import "OFNumber.h"
#import "OFNull.h"

#import "OFInvalidJSONException.h"

|




















<
<







1
2
3
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.
 */

#include "config.h"

#include <stdlib.h>
#include <string.h>

#include <math.h>



#import "OFString+JSONParsing.h"
#import "OFArray.h"
#import "OFDictionary.h"
#import "OFNumber.h"
#import "OFNull.h"

#import "OFInvalidJSONException.h"
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
{
	void *pool = objc_autoreleasePoolPush();
	const char *pointer = self.UTF8String;
	const char *stop = pointer + self.UTF8StringLength;
	id object;
	size_t line = 1;

#ifdef __clang_analyzer__
	assert(pointer != NULL);
#endif

	object = nextObject(&pointer, stop, &line, depthLimit);
	skipWhitespacesAndComments(&pointer, stop, &line);

	if (pointer < stop || object == nil)
		@throw [OFInvalidJSONException exceptionWithString: self
							      line: line];








<
<
<
<







647
648
649
650
651
652
653




654
655
656
657
658
659
660
{
	void *pool = objc_autoreleasePoolPush();
	const char *pointer = self.UTF8String;
	const char *stop = pointer + self.UTF8StringLength;
	id object;
	size_t line = 1;





	object = nextObject(&pointer, stop, &line, depthLimit);
	skipWhitespacesAndComments(&pointer, stop, &line);

	if (pointer < stop || object == nil)
		@throw [OFInvalidJSONException exceptionWithString: self
							      line: line];

Modified src/OFString+PathAdditions.h from [01351c2d45] to [3d3edf170d].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
 *
 * @param extension The extension to append
 * @return A new, autoreleased OFString with the path extension appended
 */
- (OFString *)stringByAppendingPathExtension: (OFString *)extension;

- (bool)of_isDirectoryPath;
- (OFString *)of_pathToURIPathWithPercentEncodedHost:
    (OFString *__autoreleasing _Nullable *_Nonnull)percentEncodedHost;
- (OFString *)of_URIPathToPathWithPercentEncodedHost:
    (nullable OFString *)percentEncodedHost;
- (OFString *)of_pathComponentToURIPathComponent;
@end

OF_ASSUME_NONNULL_END







|

|

|



82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
 *
 * @param extension The extension to append
 * @return A new, autoreleased OFString with the path extension appended
 */
- (OFString *)stringByAppendingPathExtension: (OFString *)extension;

- (bool)of_isDirectoryPath;
- (OFString *)of_pathToIRIPathWithPercentEncodedHost:
    (OFString *__autoreleasing _Nullable *_Nonnull)percentEncodedHost;
- (OFString *)of_IRIPathToPathWithPercentEncodedHost:
    (nullable OFString *)percentEncodedHost;
- (OFString *)of_pathComponentToIRIPathComponent;
@end

OF_ASSUME_NONNULL_END

Modified src/OFString+PathAdditions.m from [dfeb40c068] to [d839db3f93].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFString+PercentEncoding.h from [8762d6fc4c] to [d073b82625].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
 * @brief The string with percent encoding removed.
 *
 * @throw OFInvalidFormatException The string is not in proper percent encoding
 */
@property (readonly, nonatomic) OFString *stringByRemovingPercentEncoding;

/**
 * @brief Percent-encodes a string for use in a URI, but does not escape the
 *	  specified allowed characters.
 *
 * @param allowedCharacters A character set of characters that should not be
 *			    escaped
 *
 * @return A new autoreleased string
 */
- (OFString *)stringByAddingPercentEncodingWithAllowedCharacters:
    (OFCharacterSet *)allowedCharacters;
@end

OF_ASSUME_NONNULL_END







|












32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
 * @brief The string with percent encoding removed.
 *
 * @throw OFInvalidFormatException The string is not in proper percent encoding
 */
@property (readonly, nonatomic) OFString *stringByRemovingPercentEncoding;

/**
 * @brief Percent-encodes a string for use in an IRI, but does not escape the
 *	  specified allowed characters.
 *
 * @param allowedCharacters A character set of characters that should not be
 *			    escaped
 *
 * @return A new autoreleased string
 */
- (OFString *)stringByAddingPercentEncodingWithAllowedCharacters:
    (OFCharacterSet *)allowedCharacters;
@end

OF_ASSUME_NONNULL_END

Modified src/OFString+PercentEncoding.m from [46a599b120] to [5ef379fffa].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFString+PropertyListParsing.h from [6aa9059d9b] to [d6db1511b1].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFString+PropertyListParsing.m from [4a79f533f5] to [b63320ba12].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Deleted src/OFString+Serialization.h version [6689bf6870].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#import "OFString.h"

OF_ASSUME_NONNULL_BEGIN

#ifdef __cplusplus
extern "C" {
#endif
extern int _OFString_Serialization_reference;
#ifdef __cplusplus
}
#endif

@interface OFString (Serialization)
/**
 * @brief The string interpreted as serialization and parsed as an object.
 *
 * @throw OFMalformedXMLException The XML was malformed
 * @throw OFUnboundNamespaceException A prefix was used that was not bound to
 *				      any namespace
 * @throw OFInvalidEncodingException The XML is not in the encoding it specified
 * @throw OFUnsupportedVersionException The serialization is in an unsupported
 *					version
 */
@property (readonly, nonatomic) id objectByDeserializing;
@end

OF_ASSUME_NONNULL_END
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<




















































































Deleted src/OFString+Serialization.m version [a02a87cd97].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#import "OFString.h"
#import "OFString+Serialization.h"
#import "OFSerialization.h"
#import "OFArray.h"
#import "OFXMLElement.h"
#import "OFXMLAttribute.h"

#import "OFInvalidArgumentException.h"
#import "OFMalformedXMLException.h"
#import "OFUnboundNamespaceException.h"
#import "OFUnsupportedVersionException.h"

int _OFString_Serialization_reference;

@implementation OFString (Serialization)
- (id)objectByDeserializing
{
	void *pool = objc_autoreleasePoolPush();
	OFXMLElement *root;
	OFString *version;
	OFArray *elements;
	id object;

	root = [OFXMLElement elementWithXMLString: self];

	version = [root attributeForName: @"version"].stringValue;
	if (version == nil)
		@throw [OFInvalidArgumentException exception];

	if (version.unsignedLongLongValue != 1)
		@throw [OFUnsupportedVersionException
		    exceptionWithVersion: version];

	elements = [root elementsForNamespace: OFSerializationNS];

	if (elements.count != 1)
		@throw [OFInvalidArgumentException exception];

	object = [[elements.firstObject objectByDeserializing] retain];

	objc_autoreleasePoolPop(pool);

	return [object autorelease];
}
@end
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<




























































































































Modified src/OFString+XMLEscaping.h from [5e7ff84170] to [db652d6d3e].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFString+XMLEscaping.m from [417a4985be] to [b6ac7c7c66].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the 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 <assert.h>
#include <stdlib.h>
#include <string.h>

#import "OFString.h"

#import "OFOutOfMemoryException.h"


|















<







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

18
19
20
21
22
23
24
/*
 * Copyright (c) 2008-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 <stdlib.h>
#include <string.h>

#import "OFString.h"

#import "OFOutOfMemoryException.h"

84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
			retLength += appendLen - 1;

			memcpy(retCString + j, append, appendLen);
			j += appendLen;
		} else
			retCString[j++] = string[i];
	}
	assert(j == retLength);

	objc_autoreleasePoolPop(pool);

	@try {
		ret = [OFString stringWithUTF8String: retCString
					      length: retLength];
	} @finally {
		OFFreeMemory(retCString);
	}
	return ret;
}
@end







|












83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
			retLength += appendLen - 1;

			memcpy(retCString + j, append, appendLen);
			j += appendLen;
		} else
			retCString[j++] = string[i];
	}
	OFAssert(j == retLength);

	objc_autoreleasePoolPop(pool);

	@try {
		ret = [OFString stringWithUTF8String: retCString
					      length: retLength];
	} @finally {
		OFFreeMemory(retCString);
	}
	return ret;
}
@end

Modified src/OFString+XMLUnescaping.h from [5fc70e7ddb] to [31d836e661].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFString+XMLUnescaping.m from [dd8350c1c8] to [4359af2fdb].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFString.h from [780687227d] to [f7726f73ab].

1
2
3
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-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#ifndef OBJFW_OF_STRING_H
#define OBJFW_OF_STRING_H

#ifndef __STDC_LIMIT_MACROS
# define __STDC_LIMIT_MACROS
#endif
#ifndef __STDC_CONSTANT_MACROS
# define __STDC_CONSTANT_MACROS
#endif

#include "objfw-defs.h"

#ifdef OF_HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif

#include <stdarg.h>
#include <stdint.h>
#ifdef OF_HAVE_INTTYPES_H
# include <inttypes.h>
#endif

#include "OFObject.h"
#ifdef __OBJC__
# import "OFSerialization.h"
# import "OFJSONRepresentation.h"
# import "OFMessagePackRepresentation.h"
#endif

OF_ASSUME_NONNULL_BEGIN

/** @file */

#ifdef __OBJC__

@class OFConstantString;
@class OFString;
#else
typedef void OFString;
#endif

#if defined(__cplusplus) && __cplusplus >= 201103L
typedef char16_t OFChar16;
typedef char32_t OFChar32;
#else
typedef uint_least16_t OFChar16;
typedef uint_least32_t OFChar32;

|













<
<
<



















|
<
<
|
|
<





|
>

|
<
|
<







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15



16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35


36
37

38
39
40
41
42
43
44
45
46

47

48
49
50
51
52
53
54
/*
 * Copyright (c) 2008-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.
 */




#ifndef __STDC_LIMIT_MACROS
# define __STDC_LIMIT_MACROS
#endif
#ifndef __STDC_CONSTANT_MACROS
# define __STDC_CONSTANT_MACROS
#endif

#include "objfw-defs.h"

#ifdef OF_HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif

#include <stdarg.h>
#include <stdint.h>
#ifdef OF_HAVE_INTTYPES_H
# include <inttypes.h>
#endif

#import "OFObject.h"


#import "OFJSONRepresentation.h"
#import "OFMessagePackRepresentation.h"


OF_ASSUME_NONNULL_BEGIN

/** @file */

@class OFArray OF_GENERIC(ObjectType);
@class OFCharacterSet;
@class OFConstantString;
@class OFIRI;

@class OFString;


#if defined(__cplusplus) && __cplusplus >= 201103L
typedef char16_t OFChar16;
typedef char32_t OFChar32;
#else
typedef uint_least16_t OFChar16;
typedef uint_least32_t OFChar32;
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
 * @param line The current line
 * @param stop A pointer to a variable that can be set to true to stop the
 *	       enumeration
 */
typedef void (^OFStringLineEnumerationBlock)(OFString *line, bool *stop);
#endif

#ifdef __OBJC__
@class OFArray OF_GENERIC(ObjectType);
@class OFCharacterSet;
@class OFURI;

/**
 * @class OFString OFString.h ObjFW/OFString.h
 *
 * @brief A class for handling strings.
 */
@interface OFString: OFObject <OFCopying, OFMutableCopying, OFComparing,
    OFSerialization, OFJSONRepresentation, OFMessagePackRepresentation>
/**
 * @brief The length of the string in Unicode codepoints.
 */
@property (readonly, nonatomic) size_t length;

/**
 * @brief The OFString as a UTF-8 encoded C string.
 *
 * The result is valid until the autorelease pool is released. If you want to
 * use the result outside the scope of the current autorelease pool, you have to
 * copy it.
 */
@property (readonly, nonatomic) const char *UTF8String OF_RETURNS_INNER_POINTER;

/**
 * @brief The number of bytes the string needs in UTF-8 encoding.
 */
@property (readonly, nonatomic) size_t UTF8StringLength;

/**







<
<
<
<
<






|












|







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
 * @param line The current line
 * @param stop A pointer to a variable that can be set to true to stop the
 *	       enumeration
 */
typedef void (^OFStringLineEnumerationBlock)(OFString *line, bool *stop);
#endif






/**
 * @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
 * use the result outside the scope of the current autorelease pool, you have to
 * copy it.
 */
@property (readonly, nonatomic) const char *UTF8String;

/**
 * @brief The number of bytes the string needs in UTF-8 encoding.
 */
@property (readonly, nonatomic) size_t UTF8StringLength;

/**
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
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
 *
 * The result is valid until the autorelease pool is released. If you want to
 * use the result outside the scope of the current autorelease pool, you have to
 * copy it.
 *
 * The returned string is *not* null-terminated.
 */
@property (readonly, nonatomic) const OFUnichar *characters
    OF_RETURNS_INNER_POINTER;

/**
 * @brief The string in UTF-16 encoding with native byte order.
 *
 * The result is valid until the autorelease pool is released. If you want to
 * use the result outside the scope of the current autorelease pool, you have to
 * copy it.
 *
 * The returned string is null-terminated.
 */
@property (readonly, nonatomic) const OFChar16 *UTF16String
    OF_RETURNS_INNER_POINTER;

/**
 * @brief The length of the string in UTF-16 characters.
 */
@property (readonly, nonatomic) size_t UTF16StringLength;

/**
 * @brief The string in UTF-32 encoding with native byte order.
 *
 * The result is valid until the autorelease pool is released. If you want to
 * use the result outside the scope of the current autorelease pool, you have to
 * copy it.
 *
 * The returned string is null-terminated.
 */
@property (readonly, nonatomic) const OFChar32 *UTF32String
    OF_RETURNS_INNER_POINTER;

/**
 * @brief The string with leading whitespaces deleted.
 */
@property (readonly, nonatomic) OFString *stringByDeletingLeadingWhitespaces;

/**
 * @brief The string with trailing whitespaces deleted.
 */
@property (readonly, nonatomic) OFString *stringByDeletingTrailingWhitespaces;

/**
 * @brief The string with leading and trailing whitespaces deleted.
 */
@property (readonly, nonatomic) OFString *stringByDeletingEnclosingWhitespaces;

# ifdef OF_HAVE_UNICODE_TABLES
/**
 * @brief The string in Unicode Normalization Form D (NFD).
 */
@property (readonly, nonatomic) OFString *decomposedStringWithCanonicalMapping;

/**
 * @brief The string in Unicode Normalization Form KD (NFKD).
 */
@property (readonly, nonatomic)
    OFString *decomposedStringWithCompatibilityMapping;
# endif

# ifdef OF_WINDOWS
/**
 * @brief The string with the Windows Environment Strings expanded.
 */
@property (readonly, nonatomic)
    OFString *stringByExpandingWindowsEnvironmentStrings;
# endif

/**
 * @brief Creates a new OFString.
 *
 * @return A new, autoreleased OFString
 */
+ (instancetype)string;







|
<










|
<















|
<
















<
<
<
<
<
|
<
<
<
<
<
<
<
<





|







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
 *
 * The result is valid until the autorelease pool is released. If you want to
 * use the result outside the scope of the current autorelease pool, you have to
 * copy it.
 *
 * The returned string is *not* null-terminated.
 */
@property (readonly, nonatomic) const OFUnichar *characters;


/**
 * @brief The string in UTF-16 encoding with native byte order.
 *
 * The result is valid until the autorelease pool is released. If you want to
 * use the result outside the scope of the current autorelease pool, you have to
 * copy it.
 *
 * The returned string is null-terminated.
 */
@property (readonly, nonatomic) const OFChar16 *UTF16String;


/**
 * @brief The length of the string in UTF-16 characters.
 */
@property (readonly, nonatomic) size_t UTF16StringLength;

/**
 * @brief The string in UTF-32 encoding with native byte order.
 *
 * The result is valid until the autorelease pool is released. If you want to
 * use the result outside the scope of the current autorelease pool, you have to
 * copy it.
 *
 * The returned string is null-terminated.
 */
@property (readonly, nonatomic) const OFChar32 *UTF32String;


/**
 * @brief The string with leading whitespaces deleted.
 */
@property (readonly, nonatomic) OFString *stringByDeletingLeadingWhitespaces;

/**
 * @brief The string with trailing whitespaces deleted.
 */
@property (readonly, nonatomic) OFString *stringByDeletingTrailingWhitespaces;

/**
 * @brief The string with leading and trailing whitespaces deleted.
 */
@property (readonly, nonatomic) OFString *stringByDeletingEnclosingWhitespaces;






#if defined(OF_WINDOWS) || defined(DOXYGEN)








/**
 * @brief The string with the Windows Environment Strings expanded.
 */
@property (readonly, nonatomic)
    OFString *stringByExpandingWindowsEnvironmentStrings;
#endif

/**
 * @brief Creates a new OFString.
 *
 * @return A new, autoreleased OFString
 */
+ (instancetype)string;
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
 * @return A new autoreleased OFString
 * @throw OFInvalidFormatException The specified format is invalid
 * @throw OFInvalidEncodingException The resulting string is not in not in UTF-8
 *				     encoding
 */
+ (instancetype)stringWithFormat: (OFConstantString *)format, ...;

# ifdef OF_HAVE_FILES
/**
 * @brief Creates a new OFString with the contents of the specified UTF-8
 *	  encoded file.
 *
 * @param path The path to the file
 * @return A new autoreleased OFString
 * @throw OFInvalidEncodingException The string is not properly UTF-8-encoded







|







498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
 * @return A new autoreleased OFString
 * @throw OFInvalidFormatException The specified format is invalid
 * @throw OFInvalidEncodingException The resulting string is not in not in UTF-8
 *				     encoding
 */
+ (instancetype)stringWithFormat: (OFConstantString *)format, ...;

#ifdef OF_HAVE_FILES
/**
 * @brief Creates a new OFString with the contents of the specified UTF-8
 *	  encoded file.
 *
 * @param path The path to the file
 * @return A new autoreleased OFString
 * @throw OFInvalidEncodingException The string is not properly UTF-8-encoded
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
 * @param path The path to the file
 * @param encoding The encoding of the file
 * @return A new autoreleased OFString
 * @throw OFInvalidEncodingException The string is not in the specified encoding
 */
+ (instancetype)stringWithContentsOfFile: (OFString *)path
				encoding: (OFStringEncoding)encoding;
# endif

/**
 * @brief Creates a new OFString with the contents of the specified URI.
 *
 * If the URI's scheme is file, it tries UTF-8 encoding.
 *
 * If the URI's scheme is http(s), it tries to detect the encoding from the HTTP
 * headers. If it could not detect the encoding using the HTTP headers, it tries
 * UTF-8.
 *
 * @param URI The URI to the contents for the string
 * @return A new autoreleased OFString
 * @throw OFInvalidEncodingException The string is not in the expected encoding
 */
+ (instancetype)stringWithContentsOfURI: (OFURI *)URI;

/**
 * @brief Creates a new OFString with the contents of the specified URI in the
 *	  specified encoding.
 *
 * @param URI The URI to the contents for the string
 * @param encoding The encoding to assume
 * @return A new autoreleased OFString
 * @throw OFInvalidEncodingException The string is not in the specified encoding
 */
+ (instancetype)stringWithContentsOfURI: (OFURI *)URI
			       encoding: (OFStringEncoding)encoding;








/**
 * @brief Initializes an already allocated OFString from a UTF-8 encoded C
 *	  string.
 *
 * @param UTF8String A UTF-8 encoded C string to initialize the OFString with
 * @return An initialized OFString
 * @throw OFInvalidEncodingException The string is not properly UTF-8-encoded







|


|

|

|



|



|


|


|




|


>
>
>
>
>
>
>







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
 * @param path The path to the file
 * @param encoding The encoding of the file
 * @return A new autoreleased OFString
 * @throw OFInvalidEncodingException The string is not in the specified encoding
 */
+ (instancetype)stringWithContentsOfFile: (OFString *)path
				encoding: (OFStringEncoding)encoding;
#endif

/**
 * @brief Creates a new OFString with the contents of the specified 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;

/**
 * @brief Creates a new OFString with the contents of the specified IRI in the
 *	  specified encoding.
 *
 * @param IRI The IRI to the contents for the string
 * @param encoding The encoding to assume
 * @return A new autoreleased OFString
 * @throw OFInvalidEncodingException The string is not in the specified encoding
 */
+ (instancetype)stringWithContentsOfIRI: (OFIRI *)IRI
			       encoding: (OFStringEncoding)encoding;

/**
 * @brief Initializes an already allocated OFString to be empty.
 *
 * @return An initialized OFString
 */
- (instancetype)init OF_DESIGNATED_INITIALIZER;

/**
 * @brief Initializes an already allocated OFString from a UTF-8 encoded C
 *	  string.
 *
 * @param UTF8String A UTF-8 encoded C string to initialize the OFString with
 * @return An initialized OFString
 * @throw OFInvalidEncodingException The string is not properly UTF-8-encoded
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
 * @throw OFInvalidFormatException The specified format is invalid
 * @throw OFInvalidEncodingException The resulting string is not in not in UTF-8
 *				     encoding
 */
- (instancetype)initWithFormat: (OFConstantString *)format
		     arguments: (va_list)arguments;

# ifdef OF_HAVE_FILES
/**
 * @brief Initializes an already allocated OFString with the contents of the
 *	  specified file in the specified encoding.
 *
 * @param path The path to the file
 * @return An initialized OFString
 * @throw OFInvalidEncodingException The string is not properly UTF-8-encoded







|







798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
 * @throw OFInvalidFormatException The specified format is invalid
 * @throw OFInvalidEncodingException The resulting string is not in not in UTF-8
 *				     encoding
 */
- (instancetype)initWithFormat: (OFConstantString *)format
		     arguments: (va_list)arguments;

#ifdef OF_HAVE_FILES
/**
 * @brief Initializes an already allocated OFString with the contents of the
 *	  specified file in the specified encoding.
 *
 * @param path The path to the file
 * @return An initialized OFString
 * @throw OFInvalidEncodingException The string is not properly UTF-8-encoded
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
 * @param path The path to the file
 * @param encoding The encoding of the file
 * @return An initialized OFString
 * @throw OFInvalidEncodingException The string is not in the specified encoding
 */
- (instancetype)initWithContentsOfFile: (OFString *)path
			      encoding: (OFStringEncoding)encoding;
# endif

/**
 * @brief Initializes an already allocated OFString with the contents of the
 *	  specified URI.
 *
 * If the URI's scheme is file, it tries UTF-8 encoding.
 *
 * If the URI's scheme is http(s), it tries to detect the encoding from the HTTP
 * headers. If it could not detect the encoding using the HTTP headers, it tries
 * UTF-8.
 *
 * @param URI The URI to the contents for the string
 * @return An initialized OFString
 * @throw OFInvalidEncodingException The string is not in the expected encoding
 */
- (instancetype)initWithContentsOfURI: (OFURI *)URI;

/**
 * @brief Initializes an already allocated OFString with the contents of the
 *	  specified URI in the specified encoding.
 *
 * @param URI The URI to the contents for the string
 * @param encoding The encoding to assume
 * @return An initialized OFString
 * @throw OFInvalidEncodingException The string is not in the specified encoding
 */
- (instancetype)initWithContentsOfURI: (OFURI *)URI
			     encoding: (OFStringEncoding)encoding;

/**
 * @brief Writes the OFString into the specified C string with the specified
 *	  encoding.
 *
 * @param cString The C string to write into







|



|

|

|



|



|



|

|




|







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
 * @param path The path to the file
 * @param encoding The encoding of the file
 * @return An initialized OFString
 * @throw OFInvalidEncodingException The string is not in the specified encoding
 */
- (instancetype)initWithContentsOfFile: (OFString *)path
			      encoding: (OFStringEncoding)encoding;
#endif

/**
 * @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;

/**
 * @brief Initializes an already allocated OFString with the contents of the
 *	  specified IRI in the specified encoding.
 *
 * @param IRI The IRI to the contents for the string
 * @param encoding The encoding to assume
 * @return An initialized OFString
 * @throw OFInvalidEncodingException The string is not in the specified encoding
 */
- (instancetype)initWithContentsOfIRI: (OFIRI *)IRI
			     encoding: (OFStringEncoding)encoding;

/**
 * @brief Writes the OFString into the specified C string with the specified
 *	  encoding.
 *
 * @param cString The C string to write into
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
 * copy it.
 *
 * @param encoding The encoding for the C string
 * @return The OFString as a C string in the specified encoding
 * @throw OFInvalidEncodingException The string cannot be represented in the
 *				     specified encoding
 */
- (const char *)cStringWithEncoding: (OFStringEncoding)encoding
    OF_RETURNS_INNER_POINTER;

/**
 * @brief Returns the OFString as a C string in the specified encoding,
 *	  replacing characters that cannot be represented in the specified
 *	  encoding with a question mark.
 *
 * The result is valid until the autorelease pool is released. If you want to
 * use the result outside the scope of the current autorelease pool, you have to
 * copy it.
 *
 * @param encoding The encoding for the C string
 * @return The OFString as a C string in the specified encoding
 */
- (const char *)lossyCStringWithEncoding: (OFStringEncoding)encoding
    OF_RETURNS_INNER_POINTER;

/**
 * @brief Returns the number of bytes the string needs in the specified
 *	  encoding.
 *
 * @param encoding The encoding for the string
 * @return The number of bytes the string needs in the specified encoding.







|
<













|
<







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
 * copy it.
 *
 * @param encoding The encoding for the C string
 * @return The OFString as a C string in the specified encoding
 * @throw OFInvalidEncodingException The string cannot be represented in the
 *				     specified encoding
 */
- (const char *)cStringWithEncoding: (OFStringEncoding)encoding;


/**
 * @brief Returns the OFString as a C string in the specified encoding,
 *	  replacing characters that cannot be represented in the specified
 *	  encoding with a question mark.
 *
 * The result is valid until the autorelease pool is released. If you want to
 * use the result outside the scope of the current autorelease pool, you have to
 * copy it.
 *
 * @param encoding The encoding for the C string
 * @return The OFString as a C string in the specified encoding
 */
- (const char *)lossyCStringWithEncoding: (OFStringEncoding)encoding;


/**
 * @brief Returns the number of bytes the string needs in the specified
 *	  encoding.
 *
 * @param encoding The encoding for the string
 * @return The number of bytes the string needs in the specified encoding.
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
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
 *
 * The returned string is null-terminated.
 *
 * @param byteOrder The byte order for the UTF-16 encoding
 * @return The string in UTF-16 encoding with the specified byte order
 * @throw OFInvalidEncodingException The string cannot be represented in UTF-16
 */
- (const OFChar16 *)UTF16StringWithByteOrder: (OFByteOrder)byteOrder
    OF_RETURNS_INNER_POINTER;

/**
 * @brief Returns the string in UTF-32 encoding with the specified byte order.
 *
 * The result is valid until the autorelease pool is released. If you want to
 * use the result outside the scope of the current autorelease pool, you have to
 * copy it.
 *
 * The returned string is null-terminated.
 *
 * @param byteOrder The byte order for the UTF-32 encoding
 * @return The string in UTF-32 encoding with the specified byte order
 */
- (const OFChar32 *)UTF32StringWithByteOrder: (OFByteOrder)byteOrder
    OF_RETURNS_INNER_POINTER;

/**
 * @brief Returns the string as OFData with the specified encoding.
 *
 * @param encoding The encoding to use for the returned OFData
 * @return The string as OFData with the specified encoding
 * @throw OFInvalidEncodingException The string cannot be represented in the
 *				     specified encoding
 */
- (OFData *)dataWithEncoding: (OFStringEncoding)encoding;

# ifdef OF_HAVE_FILES
/**
 * @brief Writes the string into the specified file using UTF-8 encoding.
 *
 * @param path The path of the file to write to
 */
- (void)writeToFile: (OFString *)path;

/**
 * @brief Writes the string into the specified file using the specified
 *	  encoding.
 *
 * @param path The path of the file to write to
 * @param encoding The encoding to use to write the string into the file
 * @throw OFInvalidEncodingException The string cannot be represented in the
 *				     specified encoding
 */
- (void)writeToFile: (OFString *)path encoding: (OFStringEncoding)encoding;
# endif

/**
 * @brief Writes the string to the specified URI using UTF-8 encoding.
 *
 * @param URI The URI to write to
 */
- (void)writeToURI: (OFURI *)URI;

/**
 * @brief Writes the string to the specified URI using the specified encoding.
 *
 * @param URI The URI to write to
 * @param encoding The encoding to use to write the string to the URI
 * @throw OFInvalidEncodingException The string cannot be represented in the
 *				     specified encoding
 */
- (void)writeToURI: (OFURI *)URI encoding: (OFStringEncoding)encoding;

# ifdef OF_HAVE_BLOCKS
/**
 * Enumerates all lines in the receiver using the specified block.
 *
 * @brief block The block to call for each line
 */
- (void)enumerateLinesUsingBlock: (OFStringLineEnumerationBlock)block;
# endif
@end
#endif

#ifdef __cplusplus
extern "C" {
#endif
/**
 * @brief Parses the specified string encoding name and returns the
 *	  OFStringEncoding for it.







|
<













|
<











|

















|


|

|

|


|

|
|



|

|






|

<







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
 *
 * The returned string is null-terminated.
 *
 * @param byteOrder The byte order for the UTF-16 encoding
 * @return The string in UTF-16 encoding with the specified byte order
 * @throw OFInvalidEncodingException The string cannot be represented in UTF-16
 */
- (const OFChar16 *)UTF16StringWithByteOrder: (OFByteOrder)byteOrder;


/**
 * @brief Returns the string in UTF-32 encoding with the specified byte order.
 *
 * The result is valid until the autorelease pool is released. If you want to
 * use the result outside the scope of the current autorelease pool, you have to
 * copy it.
 *
 * The returned string is null-terminated.
 *
 * @param byteOrder The byte order for the UTF-32 encoding
 * @return The string in UTF-32 encoding with the specified byte order
 */
- (const OFChar32 *)UTF32StringWithByteOrder: (OFByteOrder)byteOrder;


/**
 * @brief Returns the string as OFData with the specified encoding.
 *
 * @param encoding The encoding to use for the returned OFData
 * @return The string as OFData with the specified encoding
 * @throw OFInvalidEncodingException The string cannot be represented in the
 *				     specified encoding
 */
- (OFData *)dataWithEncoding: (OFStringEncoding)encoding;

#ifdef OF_HAVE_FILES
/**
 * @brief Writes the string into the specified file using UTF-8 encoding.
 *
 * @param path The path of the file to write to
 */
- (void)writeToFile: (OFString *)path;

/**
 * @brief Writes the string into the specified file using the specified
 *	  encoding.
 *
 * @param path The path of the file to write to
 * @param encoding The encoding to use to write the string into the file
 * @throw OFInvalidEncodingException The string cannot be represented in the
 *				     specified encoding
 */
- (void)writeToFile: (OFString *)path encoding: (OFStringEncoding)encoding;
#endif

/**
 * @brief Writes the string to the specified IRI using UTF-8 encoding.
 *
 * @param IRI The IRI to write to
 */
- (void)writeToIRI: (OFIRI *)IRI;

/**
 * @brief Writes the string to the specified IRI using the specified encoding.
 *
 * @param IRI The IRI to write to
 * @param encoding The encoding to use to write the string to the IRI
 * @throw OFInvalidEncodingException The string cannot be represented in the
 *				     specified encoding
 */
- (void)writeToIRI: (OFIRI *)IRI encoding: (OFStringEncoding)encoding;

#ifdef OF_HAVE_BLOCKS
/**
 * Enumerates all lines in the receiver using the specified block.
 *
 * @brief block The block to call for each line
 */
- (void)enumerateLinesUsingBlock: (OFStringLineEnumerationBlock)block;
#endif
@end


#ifdef __cplusplus
extern "C" {
#endif
/**
 * @brief Parses the specified string encoding name and returns the
 *	  OFStringEncoding for it.
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
extern size_t OFUTF32StringLength(const OFChar32 *);
#ifdef __cplusplus
}
#endif

OF_ASSUME_NONNULL_END

#include "OFConstantString.h"
#include "OFMutableString.h"
#ifdef __OBJC__
# import "OFString+CryptographicHashing.h"
# import "OFString+JSONParsing.h"
# ifdef OF_HAVE_FILES
#  import "OFString+PathAdditions.h"
# endif
# import "OFString+PercentEncoding.h"
# import "OFString+PropertyListParsing.h"
# import "OFString+Serialization.h"
# import "OFString+XMLEscaping.h"
# import "OFString+XMLUnescaping.h"
#endif

#if defined(__OBJC__) && !defined(NSINTEGER_DEFINED) && !__has_feature(modules)
/*
 * Very *ugly* hack required for string boxing literals to work.
 *
 * This hack is needed in order to work with `@class NSString` from Apple's
 * objc/NSString.h - which is included when using modules - as
 * @compatibility_alias does not work if @class has been used before.
 * For some reason, this makes Clang refer to OFString for string box literals
 * and not to NSString (which would result in a linker error, but would be the
 * correct behavior).
 *
 * TODO: Submit a patch for Clang that makes the boxing classes configurable!
 */
@interface NSString: OFString
@end
#endif

#endif







|
|
<
|
|
|
|
|
|
|
<
|
|
<

|















<
<
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


extern size_t OFUTF32StringLength(const OFChar32 *);
#ifdef __cplusplus
}
#endif

OF_ASSUME_NONNULL_END

#import "OFConstantString.h"
#import "OFMutableString.h"

#import "OFString+CryptographicHashing.h"
#import "OFString+JSONParsing.h"
#ifdef OF_HAVE_FILES
# import "OFString+PathAdditions.h"
#endif
#import "OFString+PercentEncoding.h"
#import "OFString+PropertyListParsing.h"

#import "OFString+XMLEscaping.h"
#import "OFString+XMLUnescaping.h"


#if !defined(NSINTEGER_DEFINED) && !__has_feature(modules)
/*
 * Very *ugly* hack required for string boxing literals to work.
 *
 * This hack is needed in order to work with `@class NSString` from Apple's
 * objc/NSString.h - which is included when using modules - as
 * @compatibility_alias does not work if @class has been used before.
 * For some reason, this makes Clang refer to OFString for string box literals
 * and not to NSString (which would result in a linker error, but would be the
 * correct behavior).
 *
 * TODO: Submit a patch for Clang that makes the boxing classes configurable!
 */
@interface NSString: OFString
@end
#endif


Modified src/OFString.m from [03372dc363] to [855db5cb26].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
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
#include <ctype.h>
#include <errno.h>
#include <math.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>

#if defined(HAVE_STRTOF_L) || defined(HAVE_STRTOD_L)
# include <locale.h>
#endif
#ifdef HAVE_XLOCALE_H
# include <xlocale.h>
#endif

#import "OFString.h"
#import "OFASPrintF.h"
#import "OFArray.h"
#import "OFCharacterSet.h"
#import "OFData.h"
#import "OFDictionary.h"
#ifdef OF_HAVE_FILES
# import "OFFile.h"
# import "OFFileManager.h"
#endif


#import "OFLocale.h"
#import "OFStream.h"
#import "OFSystemInfo.h"
#import "OFURI.h"
#import "OFURIHandler.h"
#import "OFUTF8String.h"
#import "OFUTF8String+Private.h"
#import "OFXMLElement.h"

#import "OFGetItemAttributesFailedException.h"
#import "OFInitializationFailedException.h"
#import "OFInvalidArgumentException.h"
#import "OFInvalidEncodingException.h"
#import "OFInvalidFormatException.h"
#import "OFNotImplementedException.h"







|
















>
>



<
<


<







18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46


47
48

49
50
51
52
53
54
55
#include <ctype.h>
#include <errno.h>
#include <math.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>

#if defined(HAVE_STRTOF_L) || defined(HAVE_STRTOD_L) || defined(HAVE_USELOCALE)
# include <locale.h>
#endif
#ifdef HAVE_XLOCALE_H
# include <xlocale.h>
#endif

#import "OFString.h"
#import "OFASPrintF.h"
#import "OFArray.h"
#import "OFCharacterSet.h"
#import "OFData.h"
#import "OFDictionary.h"
#ifdef OF_HAVE_FILES
# import "OFFile.h"
# import "OFFileManager.h"
#endif
#import "OFIRI.h"
#import "OFIRIHandler.h"
#import "OFLocale.h"
#import "OFStream.h"
#import "OFSystemInfo.h"


#import "OFUTF8String.h"
#import "OFUTF8String+Private.h"


#import "OFGetItemAttributesFailedException.h"
#import "OFInitializationFailedException.h"
#import "OFInvalidArgumentException.h"
#import "OFInvalidEncodingException.h"
#import "OFInvalidFormatException.h"
#import "OFNotImplementedException.h"
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# define INFINITY __builtin_inf()
#endif

static struct {
	Class isa;
} placeholder;

#if defined(HAVE_STRTOF_L) || defined(HAVE_STRTOD_L)
static locale_t cLocale;
#endif

@interface OFString ()
- (size_t)of_getCString: (char *)cString
	      maxLength: (size_t)maxLength
	       encoding: (OFStringEncoding)encoding
		  lossy: (bool)lossy OF_DIRECT;
- (const char *)of_cStringWithEncoding: (OFStringEncoding)encoding
				 lossy: (bool)lossy OF_DIRECT;
- (OFString *)
    of_JSONRepresentationWithOptions: (OFJSONRepresentationOptions)options
			       depth: (size_t)depth;
@end

@interface OFStringPlaceholder: OFString
@end

extern bool OFUnicodeToISO8859_2(const OFUnichar *, unsigned char *,
    size_t, bool);
extern bool OFUnicodeToISO8859_3(const OFUnichar *, unsigned char *,
    size_t, bool);
extern bool OFUnicodeToISO8859_15(const OFUnichar *, unsigned char *,







|















|







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
# define INFINITY __builtin_inf()
#endif

static struct {
	Class isa;
} placeholder;

#if defined(HAVE_STRTOF_L) || defined(HAVE_STRTOD_L) || defined(HAVE_USELOCALE)
static locale_t cLocale;
#endif

@interface OFString ()
- (size_t)of_getCString: (char *)cString
	      maxLength: (size_t)maxLength
	       encoding: (OFStringEncoding)encoding
		  lossy: (bool)lossy OF_DIRECT;
- (const char *)of_cStringWithEncoding: (OFStringEncoding)encoding
				 lossy: (bool)lossy OF_DIRECT;
- (OFString *)
    of_JSONRepresentationWithOptions: (OFJSONRepresentationOptions)options
			       depth: (size_t)depth;
@end

@interface OFPlaceholderString: OFString
@end

extern bool OFUnicodeToISO8859_2(const OFUnichar *, unsigned char *,
    size_t, bool);
extern bool OFUnicodeToISO8859_3(const OFUnichar *, unsigned char *,
    size_t, bool);
extern bool OFUnicodeToISO8859_15(const OFUnichar *, unsigned char *,
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
	_OFString_CryptographicHashing_reference = 1;
	_OFString_JSONParsing_reference = 1;
#ifdef OF_HAVE_FILES
	_OFString_PathAdditions_reference = 1;
#endif
	_OFString_PercentEncoding_reference = 1;
	_OFString_PropertyListParsing_reference = 1;
	_OFString_Serialization_reference = 1;
	_OFString_XMLEscaping_reference = 1;
	_OFString_XMLUnescaping_reference = 1;
}

void
_reference_to_OFConstantString(void)
{







<







130
131
132
133
134
135
136

137
138
139
140
141
142
143
	_OFString_CryptographicHashing_reference = 1;
	_OFString_JSONParsing_reference = 1;
#ifdef OF_HAVE_FILES
	_OFString_PathAdditions_reference = 1;
#endif
	_OFString_PercentEncoding_reference = 1;
	_OFString_PropertyListParsing_reference = 1;

	_OFString_XMLEscaping_reference = 1;
	_OFString_XMLUnescaping_reference = 1;
}

void
_reference_to_OFConstantString(void)
{
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
	size_t length = strlen(string);
	char *copy = (char *)OFAllocMemory(1, length + 1);
	memcpy(copy, string, length + 1);

	return copy;
}

#ifdef OF_HAVE_UNICODE_TABLES
static OFString *
decomposedString(OFString *self, const char *const *const *table, size_t size)
{
	OFMutableString *ret = [OFMutableString string];
	void *pool = objc_autoreleasePoolPush();
	const OFUnichar *characters = self.characters;
	size_t length = self.length;

	for (size_t i = 0; i < length; i++) {
		OFUnichar c = characters[i];
		const char *const *page;

		if (c >= size) {
			[ret appendCharacters: &c length: 1];
			continue;
		}

		page = table[c >> 8];
		if (page != NULL && page[c & 0xFF] != NULL)
			[ret appendUTF8String: page[c & 0xFF]];
		else
			[ret appendCharacters: &c length: 1];
	}

	objc_autoreleasePoolPop(pool);

	return ret;
}
#endif

@implementation OFStringPlaceholder
- (instancetype)init
{
	return (id)[[OFUTF8String alloc] init];
}

- (instancetype)initWithUTF8String: (const char *)UTF8String
{







<
|
<
<
<
<
<
<
|
<
<
<
|
<
<
<
<
|
<
<
<
<
<
<
|
<
|
<
<

<
<







342
343
344
345
346
347
348

349






350



351




352






353

354


355


356
357
358
359
360
361
362
	size_t length = strlen(string);
	char *copy = (char *)OFAllocMemory(1, length + 1);
	memcpy(copy, string, length + 1);

	return copy;
}


@implementation OFPlaceholderString






#ifdef __clang__



/* We intentionally don't call into super, so silence the warning. */




# pragma clang diagnostic push






# pragma clang diagnostic ignored "-Wunknown-pragmas"

# pragma clang diagnostic ignored "-Wobjc-designated-initializers"


#endif


- (instancetype)init
{
	return (id)[[OFUTF8String alloc] init];
}

- (instancetype)initWithUTF8String: (const char *)UTF8String
{
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
			      encoding: (OFStringEncoding)encoding
{
	return (id)[[OFUTF8String alloc] initWithContentsOfFile: path
						       encoding: encoding];
}
#endif

- (instancetype)initWithContentsOfURI: (OFURI *)URI
{
	return (id)[[OFUTF8String alloc] initWithContentsOfURI: URI];
}

- (instancetype)initWithContentsOfURI: (OFURI *)URI
			     encoding: (OFStringEncoding)encoding
{
	return (id)[[OFUTF8String alloc] initWithContentsOfURI: URI
						      encoding: encoding];
}

- (instancetype)initWithSerialization: (OFXMLElement *)element
{
	return (id)[[OFUTF8String alloc] initWithSerialization: element];
}

- (instancetype)retain
{
	return self;
}

- (instancetype)autorelease
{
	return self;
}

- (void)release
{
}

- (void)dealloc
{
	OF_DEALLOC_UNSUPPORTED
}
@end

@implementation OFString
+ (void)initialize
{
	if (self != [OFString class])
		return;

	placeholder.isa = [OFStringPlaceholder class];

#if defined(HAVE_STRTOF_L) || defined(HAVE_STRTOD_L)
	if ((cLocale = newlocale(LC_ALL_MASK, "C", NULL)) == NULL)
		@throw [OFInitializationFailedException
		    exceptionWithClass: self];
#endif
}

+ (instancetype)alloc







|

|


|


|


|
<
<
<
<
|
<
<
<
<
|
<
|
<
<
|
<
<
<
<
<
<
<
<








|

|







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
			      encoding: (OFStringEncoding)encoding
{
	return (id)[[OFUTF8String alloc] initWithContentsOfFile: path
						       encoding: encoding];
}
#endif

- (instancetype)initWithContentsOfIRI: (OFIRI *)IRI
{
	return (id)[[OFUTF8String alloc] initWithContentsOfIRI: IRI];
}

- (instancetype)initWithContentsOfIRI: (OFIRI *)IRI
			     encoding: (OFStringEncoding)encoding
{
	return (id)[[OFUTF8String alloc] initWithContentsOfIRI: IRI
						      encoding: encoding];
}
#ifdef __clang__




# pragma clang diagnostic pop




#endif




OF_SINGLETON_METHODS








@end

@implementation OFString
+ (void)initialize
{
	if (self != [OFString class])
		return;

	object_setClass((id)&placeholder, [OFPlaceholderString class]);

#if defined(HAVE_STRTOF_L) || defined(HAVE_STRTOD_L) || defined(HAVE_USELOCALE)
	if ((cLocale = newlocale(LC_ALL_MASK, "C", NULL)) == NULL)
		@throw [OFInitializationFailedException
		    exceptionWithClass: self];
#endif
}

+ (instancetype)alloc
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813

814
815
816
817
818
819
820
				encoding: (OFStringEncoding)encoding
{
	return [[[self alloc] initWithContentsOfFile: path
					    encoding: encoding] autorelease];
}
#endif

+ (instancetype)stringWithContentsOfURI: (OFURI *)URI
{
	return [[[self alloc] initWithContentsOfURI: URI] autorelease];
}

+ (instancetype)stringWithContentsOfURI: (OFURI *)URI
			       encoding: (OFStringEncoding)encoding
{
	return [[[self alloc] initWithContentsOfURI: URI
					   encoding: encoding] autorelease];
}

- (instancetype)init
{
	if ([self isMemberOfClass: [OFString class]]) {

		@try {
			[self doesNotRecognizeSelector: _cmd];
		} @catch (id e) {
			[self release];
			@throw e;
		}








|

|


|


|





|
>







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
				encoding: (OFStringEncoding)encoding
{
	return [[[self alloc] initWithContentsOfFile: path
					    encoding: encoding] autorelease];
}
#endif

+ (instancetype)stringWithContentsOfIRI: (OFIRI *)IRI
{
	return [[[self alloc] initWithContentsOfIRI: IRI] autorelease];
}

+ (instancetype)stringWithContentsOfIRI: (OFIRI *)IRI
			       encoding: (OFStringEncoding)encoding
{
	return [[[self alloc] initWithContentsOfIRI: IRI
					   encoding: encoding] autorelease];
}

- (instancetype)init
{
	if ([self isMemberOfClass: [OFString class]] ||
	    [self isMemberOfClass: [OFMutableString class]]) {
		@try {
			[self doesNotRecognizeSelector: _cmd];
		} @catch (id e) {
			[self release];
			@throw e;
		}

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
		       encoding: (OFStringEncoding)encoding
{
	return [self initWithCString: cString
			    encoding: encoding
			      length: strlen(cString)];
}







- (instancetype)initWithCString: (const char *)cString
		       encoding: (OFStringEncoding)encoding
			 length: (size_t)cStringLength
{
	OF_INVALID_INIT_METHOD
}




- (instancetype)initWithData: (OFData *)data
		    encoding: (OFStringEncoding)encoding
{
	@try {
		if (data.itemSize != 1)
			@throw [OFInvalidArgumentException exception];
	} @catch (id e) {
		[self release];
		@throw e;
	}

	self = [self initWithCString: data.items
			    encoding: encoding
			      length: data.count];

	return self;
}







- (instancetype)initWithString: (OFString *)string
{
	OF_INVALID_INIT_METHOD
}

- (instancetype)initWithCharacters: (const OFUnichar *)string
			    length: (size_t)length
{
	OF_INVALID_INIT_METHOD
}




- (instancetype)initWithUTF16String: (const OFChar16 *)string
{
	return [self initWithUTF16String: string
				  length: OFUTF16StringLength(string)
			       byteOrder: OFByteOrderNative];
}







>
>
>
>
>
>






>
>
>



















>
>
>
>
>
>










>
>
>







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
		       encoding: (OFStringEncoding)encoding
{
	return [self initWithCString: cString
			    encoding: encoding
			      length: strlen(cString)];
}

#ifdef __clang__
/* We intentionally don't call into super, so silence the warning. */
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wunknown-pragmas"
# pragma clang diagnostic ignored "-Wobjc-designated-initializers"
#endif
- (instancetype)initWithCString: (const char *)cString
		       encoding: (OFStringEncoding)encoding
			 length: (size_t)cStringLength
{
	OF_INVALID_INIT_METHOD
}
#ifdef __clang__
# pragma clang diagnostic pop
#endif

- (instancetype)initWithData: (OFData *)data
		    encoding: (OFStringEncoding)encoding
{
	@try {
		if (data.itemSize != 1)
			@throw [OFInvalidArgumentException exception];
	} @catch (id e) {
		[self release];
		@throw e;
	}

	self = [self initWithCString: data.items
			    encoding: encoding
			      length: data.count];

	return self;
}

#ifdef __clang__
/* We intentionally don't call into super, so silence the warning. */
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wunknown-pragmas"
# pragma clang diagnostic ignored "-Wobjc-designated-initializers"
#endif
- (instancetype)initWithString: (OFString *)string
{
	OF_INVALID_INIT_METHOD
}

- (instancetype)initWithCharacters: (const OFUnichar *)string
			    length: (size_t)length
{
	OF_INVALID_INIT_METHOD
}
#ifdef __clang__
# pragma clang diagnostic pop
#endif

- (instancetype)initWithUTF16String: (const OFChar16 *)string
{
	return [self initWithUTF16String: string
				  length: OFUTF16StringLength(string)
			       byteOrder: OFByteOrderNative];
}
925
926
927
928
929
930
931






932
933
934
935
936
937



938
939
940
941
942
943
944
			  byteOrder: (OFByteOrder)byteOrder
{
	return [self initWithUTF16String: string
				  length: OFUTF16StringLength(string)
			       byteOrder: byteOrder];
}







- (instancetype)initWithUTF16String: (const OFChar16 *)string
			     length: (size_t)length
			  byteOrder: (OFByteOrder)byteOrder
{
	OF_INVALID_INIT_METHOD
}




- (instancetype)initWithUTF32String: (const OFChar32 *)string
{
	return [self initWithUTF32String: string
				  length: OFUTF32StringLength(string)
			       byteOrder: OFByteOrderNative];
}







>
>
>
>
>
>






>
>
>







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
			  byteOrder: (OFByteOrder)byteOrder
{
	return [self initWithUTF16String: string
				  length: OFUTF16StringLength(string)
			       byteOrder: byteOrder];
}

#ifdef __clang__
/* We intentionally don't call into super, so silence the warning. */
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wunknown-pragmas"
# pragma clang diagnostic ignored "-Wobjc-designated-initializers"
#endif
- (instancetype)initWithUTF16String: (const OFChar16 *)string
			     length: (size_t)length
			  byteOrder: (OFByteOrder)byteOrder
{
	OF_INVALID_INIT_METHOD
}
#ifdef __clang__
# pragma clang diagnostic pop
#endif

- (instancetype)initWithUTF32String: (const OFChar32 *)string
{
	return [self initWithUTF32String: string
				  length: OFUTF32StringLength(string)
			       byteOrder: OFByteOrderNative];
}
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
			  byteOrder: (OFByteOrder)byteOrder
{
	return [self initWithUTF32String: string
				  length: OFUTF32StringLength(string)
			       byteOrder: byteOrder];
}







- (instancetype)initWithUTF32String: (const OFChar32 *)string
			     length: (size_t)length
			  byteOrder: (OFByteOrder)byteOrder
{
	OF_INVALID_INIT_METHOD
}




- (instancetype)initWithFormat: (OFConstantString *)format, ...
{
	id ret;
	va_list arguments;

	va_start(arguments, format);
	ret = [self initWithFormat: format arguments: arguments];
	va_end(arguments);

	return ret;
}







- (instancetype)initWithFormat: (OFConstantString *)format
		     arguments: (va_list)arguments
{
	OF_INVALID_INIT_METHOD
}




#ifdef OF_HAVE_FILES
- (instancetype)initWithContentsOfFile: (OFString *)path
{
	return [self initWithContentsOfFile: path
				   encoding: OFStringEncodingUTF8];
}

- (instancetype)initWithContentsOfFile: (OFString *)path
			      encoding: (OFStringEncoding)encoding
{
	char *buffer = NULL;
	OFStreamOffset fileSize;

	@try {
		void *pool = objc_autoreleasePoolPush();
		OFFile *file = [OFFile fileWithPath: path mode: @"r"];
		fileSize = [file seekToOffset: 0 whence: OFSeekEnd];

		if (fileSize < 0 || (unsigned long long)fileSize > SIZE_MAX)
			@throw [OFOutOfRangeException exception];

		/*
		 * We need one extra byte for the terminating zero if we want
		 * to use -[initWithUTF8StringNoCopy:length:freeWhenDone:].
		 */
		if (SIZE_MAX - (size_t)fileSize < 1)
			@throw [OFOutOfRangeException exception];

		[file seekToOffset: 0 whence: OFSeekSet];

		buffer = OFAllocMemory((size_t)fileSize + 1, 1);
		[file readIntoBuffer: buffer exactLength: (size_t)fileSize];
		buffer[(size_t)fileSize] = '\0';

		objc_autoreleasePoolPop(pool);
	} @catch (id e) {
		OFFreeMemory(buffer);
		[self release];

		@throw e;
	}

	if (encoding == OFStringEncodingUTF8) {
		@try {
			self = [self initWithUTF8StringNoCopy: buffer
						       length: (size_t)fileSize
						 freeWhenDone: true];
		} @catch (id e) {
			OFFreeMemory(buffer);
			@throw e;
		}
	} else {
		@try {
			self = [self initWithCString: buffer
					    encoding: encoding
					      length: (size_t)fileSize];
		} @finally {
			OFFreeMemory(buffer);
		}

	}

	return self;
}
#endif

- (instancetype)initWithContentsOfURI: (OFURI *)URI
{
	return [self initWithContentsOfURI: URI
				  encoding: OFStringEncodingAutodetect];
}

- (instancetype)initWithContentsOfURI: (OFURI *)URI
			     encoding: (OFStringEncoding)encoding
{
	void *pool = objc_autoreleasePoolPush();
	OFData *data;

	@try {
		data = [OFData dataWithContentsOfURI: URI];
	} @catch (id e) {
		[self release];
		@throw e;
	}

	/* FIXME: Detect encoding where we can. */
	if (encoding == OFStringEncodingAutodetect)
		encoding = OFStringEncodingUTF8;

	self = [self initWithCString: data.items
			    encoding: encoding
			      length: data.count * data.itemSize];

	objc_autoreleasePoolPop(pool);

	return self;
}

- (instancetype)initWithSerialization: (OFXMLElement *)element
{
	void *pool = objc_autoreleasePoolPush();
	OFString *stringValue;

	@try {
		if (![element.namespace isEqual: OFSerializationNS])
			@throw [OFInvalidArgumentException exception];

		if ([self isKindOfClass: [OFMutableString class]]) {
			if (![element.name isEqual: @"OFMutableString"])
				@throw [OFInvalidArgumentException exception];
		} else {
			if (![element.name isEqual: @"OFString"])
				@throw [OFInvalidArgumentException exception];
		}

		stringValue = element.stringValue;
	} @catch (id e) {
		[self release];
		@throw e;
	}

	self = [self initWithString: stringValue];

	objc_autoreleasePoolPop(pool);

	return self;
}

- (size_t)of_getCString: (char *)cString
	      maxLength: (size_t)maxLength







>
>
>
>
>
>






>
>
>













>
>
>
>
>
>





>
>
>











<
<
<
<
|
<
<
|
<
<

<
<
<
<
<
<
|
<
|
<
<
<
<
<

<

<



<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
|
>
|
<




|

|



|






|













<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







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
			  byteOrder: (OFByteOrder)byteOrder
{
	return [self initWithUTF32String: string
				  length: OFUTF32StringLength(string)
			       byteOrder: byteOrder];
}

#ifdef __clang__
/* We intentionally don't call into super, so silence the warning. */
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wunknown-pragmas"
# pragma clang diagnostic ignored "-Wobjc-designated-initializers"
#endif
- (instancetype)initWithUTF32String: (const OFChar32 *)string
			     length: (size_t)length
			  byteOrder: (OFByteOrder)byteOrder
{
	OF_INVALID_INIT_METHOD
}
#ifdef __clang__
# pragma clang diagnostic pop
#endif

- (instancetype)initWithFormat: (OFConstantString *)format, ...
{
	id ret;
	va_list arguments;

	va_start(arguments, format);
	ret = [self initWithFormat: format arguments: arguments];
	va_end(arguments);

	return ret;
}

#ifdef __clang__
/* We intentionally don't call into super, so silence the warning. */
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wunknown-pragmas"
# pragma clang diagnostic ignored "-Wobjc-designated-initializers"
#endif
- (instancetype)initWithFormat: (OFConstantString *)format
		     arguments: (va_list)arguments
{
	OF_INVALID_INIT_METHOD
}
#ifdef __clang__
# pragma clang diagnostic pop
#endif

#ifdef OF_HAVE_FILES
- (instancetype)initWithContentsOfFile: (OFString *)path
{
	return [self initWithContentsOfFile: path
				   encoding: OFStringEncodingUTF8];
}

- (instancetype)initWithContentsOfFile: (OFString *)path
			      encoding: (OFStringEncoding)encoding
{




	void *pool = objc_autoreleasePoolPush();


	OFIRI *IRI;









	@try {

		IRI = [OFIRI fileIRIWithPath: path];





	} @catch (id e) {

		[self release];

		@throw e;
	}












	self = [self initWithContentsOfIRI: IRI encoding: encoding];





	objc_autoreleasePoolPop(pool);


	return self;
}
#endif

- (instancetype)initWithContentsOfIRI: (OFIRI *)IRI
{
	return [self initWithContentsOfIRI: IRI
				  encoding: OFStringEncodingAutodetect];
}

- (instancetype)initWithContentsOfIRI: (OFIRI *)IRI
			     encoding: (OFStringEncoding)encoding
{
	void *pool = objc_autoreleasePoolPush();
	OFData *data;

	@try {
		data = [OFData dataWithContentsOfIRI: IRI];
	} @catch (id e) {
		[self release];
		@throw e;
	}

	/* FIXME: Detect encoding where we can. */
	if (encoding == OFStringEncodingAutodetect)
		encoding = OFStringEncodingUTF8;

	self = [self initWithCString: data.items
			    encoding: encoding
			      length: data.count * data.itemSize];































	objc_autoreleasePoolPop(pool);

	return self;
}

- (size_t)of_getCString: (char *)cString
	      maxLength: (size_t)maxLength
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
}

- (OFString *)description
{
	return [[self copy] autorelease];
}

- (OFXMLElement *)XMLElementBySerializing
{
	void *pool = objc_autoreleasePoolPush();
	OFXMLElement *element;
	OFString *className;

	if ([self isKindOfClass: [OFMutableString class]])
		className = @"OFMutableString";
	else
		className = @"OFString";

	element = [OFXMLElement elementWithName: className
				      namespace: OFSerializationNS
				    stringValue: self];

	[element retain];

	objc_autoreleasePoolPop(pool);

	return [element autorelease];
}

- (OFString *)JSONRepresentation
{
	return [self of_JSONRepresentationWithOptions: 0 depth: 0];
}

- (OFString *)JSONRepresentationWithOptions:
    (OFJSONRepresentationOptions)options







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







1611
1612
1613
1614
1615
1616
1617






















1618
1619
1620
1621
1622
1623
1624
}

- (OFString *)description
{
	return [[self copy] autorelease];
}























- (OFString *)JSONRepresentation
{
	return [self of_JSONRepresentationWithOptions: 0 depth: 0];
}

- (OFString *)JSONRepresentationWithOptions:
    (OFJSONRepresentationOptions)options
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446




2447
2448
2449
2450
2451
2452
2453
	    [stripped caseInsensitiveCompare: @"-INFINITY"] == OFOrderedSame)
		return -INFINITY;
	if ([stripped caseInsensitiveCompare: @"NAN"] == OFOrderedSame)
		return NAN;
	if ([stripped caseInsensitiveCompare: @"-NAN"] == OFOrderedSame)
		return -NAN;

#ifdef HAVE_STRTOF_L
	const char *UTF8String = self.UTF8String;
#else
	/*
	 * If we have no strtof_l, we have no other choice but to replace "."
	 * with the locale's decimal point.
	 */
	OFString *decimalSeparator = [OFLocale decimalSeparator];
	const char *UTF8String = [self
	    stringByReplacingOccurrencesOfString: @"."
				      withString: decimalSeparator].UTF8String;
#endif
	char *endPtr = NULL;
	float value;

	errno = 0;
#ifdef HAVE_STRTOF_L
	value = strtof_l(UTF8String, &endPtr, cLocale);




#else
	value = strtof(UTF8String, &endPtr);
#endif

	if (value == HUGE_VALF && errno == ERANGE)
		@throw [OFOutOfRangeException exception];








|















|

>
>
>
>







2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
	    [stripped caseInsensitiveCompare: @"-INFINITY"] == OFOrderedSame)
		return -INFINITY;
	if ([stripped caseInsensitiveCompare: @"NAN"] == OFOrderedSame)
		return NAN;
	if ([stripped caseInsensitiveCompare: @"-NAN"] == OFOrderedSame)
		return -NAN;

#if defined(HAVE_STRTOF_L) || defined(HAVE_USELOCALE)
	const char *UTF8String = self.UTF8String;
#else
	/*
	 * If we have no strtof_l, we have no other choice but to replace "."
	 * with the locale's decimal point.
	 */
	OFString *decimalSeparator = [OFLocale decimalSeparator];
	const char *UTF8String = [self
	    stringByReplacingOccurrencesOfString: @"."
				      withString: decimalSeparator].UTF8String;
#endif
	char *endPtr = NULL;
	float value;

	errno = 0;
#if defined(HAVE_STRTOF_L)
	value = strtof_l(UTF8String, &endPtr, cLocale);
#elif defined(HAVE_USELOCALE)
	locale_t previousLocale = uselocale(cLocale);
	value = strtof(UTF8String, &endPtr);
	uselocale(previousLocale);
#else
	value = strtof(UTF8String, &endPtr);
#endif

	if (value == HUGE_VALF && errno == ERANGE)
		@throw [OFOutOfRangeException exception];

2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499




2500
2501
2502
2503
2504
2505
2506
	    [stripped caseInsensitiveCompare: @"-INFINITY"] == OFOrderedSame)
		return -INFINITY;
	if ([stripped caseInsensitiveCompare: @"NAN"] == OFOrderedSame)
		return NAN;
	if ([stripped caseInsensitiveCompare: @"-NAN"] == OFOrderedSame)
		return -NAN;

#ifdef HAVE_STRTOD_L
	const char *UTF8String = self.UTF8String;
#else
	/*
	 * If we have no strtod_l, we have no other choice but to replace "."
	 * with the locale's decimal point.
	 */
	OFString *decimalSeparator = [OFLocale decimalSeparator];
	const char *UTF8String = [self
	    stringByReplacingOccurrencesOfString: @"."
				      withString: decimalSeparator].UTF8String;
#endif
	char *endPtr = NULL;
	double value;

	errno = 0;
#ifdef HAVE_STRTOD_L
	value = strtod_l(UTF8String, &endPtr, cLocale);




#else
	value = strtod(UTF8String, &endPtr);
#endif

	if (value == HUGE_VAL && errno == ERANGE)
		@throw [OFOutOfRangeException exception];








|















|

>
>
>
>







2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
	    [stripped caseInsensitiveCompare: @"-INFINITY"] == OFOrderedSame)
		return -INFINITY;
	if ([stripped caseInsensitiveCompare: @"NAN"] == OFOrderedSame)
		return NAN;
	if ([stripped caseInsensitiveCompare: @"-NAN"] == OFOrderedSame)
		return -NAN;

#if defined(HAVE_STRTOD_L) || defined(HAVE_USELOCALE)
	const char *UTF8String = self.UTF8String;
#else
	/*
	 * If we have no strtod_l, we have no other choice but to replace "."
	 * with the locale's decimal point.
	 */
	OFString *decimalSeparator = [OFLocale decimalSeparator];
	const char *UTF8String = [self
	    stringByReplacingOccurrencesOfString: @"."
				      withString: decimalSeparator].UTF8String;
#endif
	char *endPtr = NULL;
	double value;

	errno = 0;
#if defined(HAVE_STRTOD_L)
	value = strtod_l(UTF8String, &endPtr, cLocale);
#elif defined(HAVE_USELOCALE)
	locale_t previousLocale = uselocale(cLocale);
	value = strtod(UTF8String, &endPtr);
	uselocale(previousLocale);
#else
	value = strtod(UTF8String, &endPtr);
#endif

	if (value == HUGE_VAL && errno == ERANGE)
		@throw [OFOutOfRangeException exception];

2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
	[data retain];

	objc_autoreleasePoolPop(pool);

	return [data autorelease];
}

#ifdef OF_HAVE_UNICODE_TABLES
- (OFString *)decomposedStringWithCanonicalMapping
{
	return decomposedString(self, OFUnicodeDecompositionTable,
	    OFUnicodeDecompositionTableSize);
}

- (OFString *)decomposedStringWithCompatibilityMapping
{
	return decomposedString(self, OFUnicodeDecompositionCompatTable,
	    OFUnicodeDecompositionCompatTableSize);
}
#endif

#ifdef OF_WINDOWS
- (OFString *)stringByExpandingWindowsEnvironmentStrings
{
	if ([OFSystemInfo isWindowsNT]) {
		wchar_t buffer[512];
		size_t length;








<
<
<
<
<
<
<
<
<
<
<
<
<
<







2580
2581
2582
2583
2584
2585
2586














2587
2588
2589
2590
2591
2592
2593
	[data retain];

	objc_autoreleasePoolPop(pool);

	return [data autorelease];
}















#ifdef OF_WINDOWS
- (OFString *)stringByExpandingWindowsEnvironmentStrings
{
	if ([OFSystemInfo isWindowsNT]) {
		wchar_t buffer[512];
		size_t length;

2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
	void *pool = objc_autoreleasePoolPush();
	OFFile *file = [OFFile fileWithPath: path mode: @"w"];
	[file writeString: self encoding: encoding];
	objc_autoreleasePoolPop(pool);
}
#endif

- (void)writeToURI: (OFURI *)URI
{
	[self writeToURI: URI encoding: OFStringEncodingUTF8];
}

- (void)writeToURI: (OFURI *)URI encoding: (OFStringEncoding)encoding
{
	void *pool = objc_autoreleasePoolPush();
	OFStream *stream;

	stream = [OFURIHandler openItemAtURI: URI mode: @"w"];
	[stream writeString: self encoding: encoding];

	objc_autoreleasePoolPop(pool);
}

#ifdef OF_HAVE_BLOCKS
- (void)enumerateLinesUsingBlock: (OFStringLineEnumerationBlock)block







|

|


|




|







2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
	void *pool = objc_autoreleasePoolPush();
	OFFile *file = [OFFile fileWithPath: path mode: @"w"];
	[file writeString: self encoding: encoding];
	objc_autoreleasePoolPop(pool);
}
#endif

- (void)writeToIRI: (OFIRI *)IRI
{
	[self writeToIRI: IRI encoding: OFStringEncodingUTF8];
}

- (void)writeToIRI: (OFIRI *)IRI encoding: (OFStringEncoding)encoding
{
	void *pool = objc_autoreleasePoolPush();
	OFStream *stream;

	stream = [OFIRIHandler openItemAtIRI: IRI mode: @"w"];
	[stream writeString: self encoding: encoding];

	objc_autoreleasePoolPop(pool);
}

#ifdef OF_HAVE_BLOCKS
- (void)enumerateLinesUsingBlock: (OFStringLineEnumerationBlock)block

Modified src/OFSubarray.h from [06376fcb2e] to [22c9dfaeeb].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
19
20
21
22
23
24
25
26
27
28
29
30

@interface OFSubarray: OFArray
{
	OFArray *_array;
	OFRange _range;
}

+ (instancetype)arrayWithArray: (OFArray *)array range: (OFRange)range;
- (instancetype)initWithArray: (OFArray *)array range: (OFRange)range;
@end

OF_ASSUME_NONNULL_END







<




19
20
21
22
23
24
25

26
27
28
29

@interface OFSubarray: OFArray
{
	OFArray *_array;
	OFRange _range;
}


- (instancetype)initWithArray: (OFArray *)array range: (OFRange)range;
@end

OF_ASSUME_NONNULL_END

Modified src/OFSubarray.m from [0aad1eac45] to [36fb3a3953].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Added src/OFSubdata.h version [f381b2e69c].



























































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
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.
 */

#import "OFData.h"

OF_ASSUME_NONNULL_BEGIN

@interface OFSubdata: OFData
{
	OFData *_data;
	OFRange _range;
}

- (instancetype)initWithData: (OFData *)data range: (OFRange)range;
@end

OF_ASSUME_NONNULL_END

Added src/OFSubdata.m version [62733f57b0].























































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
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"

#import "OFSubdata.h"

@implementation OFSubdata
- (instancetype)initWithData: (OFData *)data range: (OFRange)range
{
	self = [super init];

	@try {
		/* Should usually be retain, as it's useless with a copy */
		_data = [data copy];
		_range = range;
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (void)dealloc
{
	[_data release];

	[super dealloc];
}

- (size_t)count
{
	return _range.length;
}

- (size_t)itemSize
{
	return _data.itemSize;
}

- (const void *)items
{
	return (const unsigned char *)_data.items +
	    (_range.location * _data.itemSize);
}
@end

Modified src/OFSubprocess.h from [1691c8fd4f] to [fe80ac7f23].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFSubprocess.m from [c37900d1dc] to [54c0453ebb].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Added src/OFSystemInfo+NetworkInterfaces.h version [d744983e16].













































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
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 "OFSystemInfo.h"

OF_ASSUME_NONNULL_BEGIN

/**
 * @brief A dictionary describing a network interface, as returned by
 *	  @ref networkInterfaces.
 *
 * Keys are of type @ref OFNetworkInterfaceKey.
 */
typedef OFDictionary OF_GENERIC(OFString *, id) *OFNetworkInterface;

/**
 * @brief A key of an @ref OFNetworkInterface.
 *
 * Possible values are:
 *
 *   * @ref OFNetworkInterfaceIndex
 */
typedef OFConstantString *OFNetworkInterfaceKey;

/**
 * @brief The index of a network interface.
 *
 * This maps to an @ref OFNumber.
 */
extern OFNetworkInterfaceKey OFNetworkInterfaceIndex;

/**
 * @brief The hardware address of a network interface.
 *
 * This maps to an @ref OFData.
 */
extern OFNetworkInterfaceKey OFNetworkInterfaceHardwareAddress;

/**
 * @brief The IPv4 addresses of a network interface.
 *
 * This maps to an @ref OFData of @ref OFSocketAddress.
 */
extern OFNetworkInterfaceKey OFNetworkInterfaceIPv4Addresses;

#ifdef OF_HAVE_IPV6
/**
 * @brief The IPv6 addresses of a network interface.
 *
 * This maps to an @ref OFData of @ref OFSocketAddress.
 */
extern OFNetworkInterfaceKey OFNetworkInterfaceIPv6Addresses;
#endif

#ifdef OF_HAVE_IPX
/**
 * @brief The IPX addresses of a network interface.
 *
 * This maps to an @ref OFData of @ref OFSocketAddress.
 */
extern OFNetworkInterfaceKey OFNetworkInterfaceIPXAddresses;
#endif

#ifdef OF_HAVE_APPLETALK
/**
 * @brief The AppleTalk addresses of a network interface.
 *
 * This maps to an @ref OFData of @ref OFSocketAddress.
 */
extern OFNetworkInterfaceKey OFNetworkInterfaceAppleTalkAddresses;
#endif

@interface OFSystemInfo (NetworkInterfaces)

#ifdef OF_HAVE_CLASS_PROPERTIES
@property (class, readonly, nullable, nonatomic)
    OFDictionary OF_GENERIC(OFString *, OFNetworkInterface) *networkInterfaces;
#endif

/**
 * @brief Returns the available (though not necessarily configured) network
 *	  interfaces.
 *
 * @return The available network interfaces
 */
+ (nullable OFDictionary OF_GENERIC(OFString *, OFNetworkInterface) *)
    networkInterfaces;
@end

OF_ASSUME_NONNULL_END

Added src/OFSystemInfo+NetworkInterfaces.m version [cd9fd7f23a].





















































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
/*
 * Copyright (c) 2008-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 "OFSystemInfo.h"

OFNetworkInterfaceKey OFNetworkInterfaceIndex = @"OFNetworkInterfaceIndex";
OFNetworkInterfaceKey OFNetworkInterfaceHardwareAddress =
    @"OFNetworkInterfaceHardwareAddress";
OFNetworkInterfaceKey OFNetworkInterfaceIPv4Addresses =
    @"OFNetworkInterfaceIPv4Addresses";
#ifdef OF_HAVE_IPV6
OFNetworkInterfaceKey OFNetworkInterfaceIPv6Addresses =
    @"OFNetworkInterfaceIPv6Addresses";
#endif
#ifdef OF_HAVE_IPX
OFNetworkInterfaceKey OFNetworkInterfaceIPXAddresses =
    @"OFNetworkInterfaceIPXAddresses";
#endif
#ifdef OF_HAVE_APPLETALK
OFNetworkInterfaceKey OFNetworkInterfaceAppleTalkAddresses =
    @"OFNetworkInterfaceAppleTalkAddresses";
#endif

#ifdef OF_WINDOWS
# include "platform/Windows/OFSystemInfo+NetworkInterfaces.m"
#else
# include "platform/POSIX/OFSystemInfo+NetworkInterfaces.m"
#endif

Modified src/OFSystemInfo.h from [8b4f866788] to [929ce1f306].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45


46
47
48
49
50
51
52
53
54
55



























56
57
58
59
60
61
62
63
64
65
66
67
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#import "OFObject.h"
#import "OFString.h"

OF_ASSUME_NONNULL_BEGIN


@class OFURI;

/**
 * @class OFSystemInfo OFSystemInfo.h ObjFW/OFSystemInfo.h
 *
 * @brief A class for querying information about the system.
 */
OF_SUBCLASSING_RESTRICTED
@interface OFSystemInfo: OFObject
#ifdef OF_HAVE_CLASS_PROPERTIES
@property (class, readonly, nonatomic) size_t pageSize;
@property (class, readonly, nonatomic) size_t numberOfCPUs;
@property (class, readonly, nonatomic) OFString *ObjFWVersion;
@property (class, readonly, nonatomic) unsigned short ObjFWVersionMajor;
@property (class, readonly, nonatomic) unsigned short ObjFWVersionMinor;
@property (class, readonly, nullable, nonatomic) OFString *operatingSystemName;
@property (class, readonly, nullable, nonatomic)
    OFString *operatingSystemVersion;
@property (class, readonly, nullable, nonatomic) OFURI *userDataURI;
@property (class, readonly, nullable, nonatomic) OFURI *userConfigURI;
@property (class, readonly, nullable, nonatomic) OFURI *temporaryDirectoryURI;
@property (class, readonly, nullable, nonatomic) OFString *CPUVendor;
@property (class, readonly, nullable, nonatomic) OFString *CPUModel;
# if defined(OF_X86_64) || defined(OF_X86) || defined(DOXYGEN)
@property (class, readonly, nonatomic) bool supportsMMX;


@property (class, readonly, nonatomic) bool supportsSSE;
@property (class, readonly, nonatomic) bool supportsSSE2;
@property (class, readonly, nonatomic) bool supportsSSE3;
@property (class, readonly, nonatomic) bool supportsSSSE3;
@property (class, readonly, nonatomic) bool supportsSSE41;
@property (class, readonly, nonatomic) bool supportsSSE42;
@property (class, readonly, nonatomic) bool supportsAVX;
@property (class, readonly, nonatomic) bool supportsAVX2;
@property (class, readonly, nonatomic) bool supportsAESNI;
@property (class, readonly, nonatomic) bool supportsSHAExtensions;



























# endif
# if defined(OF_POWERPC) || defined(OF_POWERPC64) || defined(DOXYGEN)
@property (class, readonly, nonatomic) bool supportsAltiVec;
# endif
# ifdef OF_WINDOWS
@property (class, readonly, nonatomic, getter=isWindowsNT) bool windowsNT;
# endif
#endif

/**
 * @brief Returns the size of a page.
 *

|


















>
|

















|
|
|


|

>
>










>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>




|







1
2
3
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
/*
 * 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 "OFObject.h"
#import "OFString.h"

OF_ASSUME_NONNULL_BEGIN

@class OFDictionary OF_GENERIC(KeyType, ObjectType);
@class OFIRI;

/**
 * @class OFSystemInfo OFSystemInfo.h ObjFW/OFSystemInfo.h
 *
 * @brief A class for querying information about the system.
 */
OF_SUBCLASSING_RESTRICTED
@interface OFSystemInfo: OFObject
#ifdef OF_HAVE_CLASS_PROPERTIES
@property (class, readonly, nonatomic) size_t pageSize;
@property (class, readonly, nonatomic) size_t numberOfCPUs;
@property (class, readonly, nonatomic) OFString *ObjFWVersion;
@property (class, readonly, nonatomic) unsigned short ObjFWVersionMajor;
@property (class, readonly, nonatomic) unsigned short ObjFWVersionMinor;
@property (class, readonly, nullable, nonatomic) OFString *operatingSystemName;
@property (class, readonly, nullable, nonatomic)
    OFString *operatingSystemVersion;
@property (class, readonly, nullable, nonatomic) OFIRI *userDataIRI;
@property (class, readonly, nullable, nonatomic) OFIRI *userConfigIRI;
@property (class, readonly, nullable, nonatomic) OFIRI *temporaryDirectoryIRI;
@property (class, readonly, nullable, nonatomic) OFString *CPUVendor;
@property (class, readonly, nullable, nonatomic) OFString *CPUModel;
# if defined(OF_AMD64) || defined(OF_X86) || defined(DOXYGEN)
@property (class, readonly, nonatomic) bool supportsMMX;
@property (class, readonly, nonatomic) bool supports3DNow;
@property (class, readonly, nonatomic) bool supportsEnhanced3DNow;
@property (class, readonly, nonatomic) bool supportsSSE;
@property (class, readonly, nonatomic) bool supportsSSE2;
@property (class, readonly, nonatomic) bool supportsSSE3;
@property (class, readonly, nonatomic) bool supportsSSSE3;
@property (class, readonly, nonatomic) bool supportsSSE41;
@property (class, readonly, nonatomic) bool supportsSSE42;
@property (class, readonly, nonatomic) bool supportsAVX;
@property (class, readonly, nonatomic) bool supportsAVX2;
@property (class, readonly, nonatomic) bool supportsAESNI;
@property (class, readonly, nonatomic) bool supportsSHAExtensions;
@property (class, readonly, nonatomic) bool supportsFusedMultiplyAdd;
@property (class, readonly, nonatomic) bool supportsF16C;
@property (class, readonly, nonatomic) bool supportsAVX512Foundation;
@property (class, readonly, nonatomic)
    bool supportsAVX512ConflictDetectionInstructions;
@property (class, readonly, nonatomic)
    bool supportsAVX512ExponentialAndReciprocalInstructions;
@property (class, readonly, nonatomic) bool supportsAVX512PrefetchInstructions;
@property (class, readonly, nonatomic)
    bool supportsAVX512VectorLengthExtensions;
@property (class, readonly, nonatomic)
    bool supportsAVX512DoublewordAndQuadwordInstructions;
@property (class, readonly, nonatomic)
    bool supportsAVX512ByteAndWordInstructions;
@property (class, readonly, nonatomic)
    bool supportsAVX512IntegerFusedMultiplyAdd;
@property (class, readonly, nonatomic)
    bool supportsAVX512VectorByteManipulationInstructions;
@property (class, readonly, nonatomic)
    bool supportsAVX512VectorPopulationCountInstruction;
@property (class, readonly, nonatomic)
    bool supportsAVX512VectorNeuralNetworkInstructions;
@property (class, readonly, nonatomic)
    bool supportsAVX512VectorByteManipulationInstructions2;
@property (class, readonly, nonatomic) bool supportsAVX512BitAlgorithms;
@property (class, readonly, nonatomic) bool supportsAVX512Float16Instructions;
@property (class, readonly, nonatomic) bool supportsAVX512BFloat16Instructions;
# endif
# if defined(OF_POWERPC) || defined(OF_POWERPC64) || defined(DOXYGEN)
@property (class, readonly, nonatomic) bool supportsAltiVec;
# endif
# if defined(OF_WINDOWS) || defined(DOXYGEN)
@property (class, readonly, nonatomic, getter=isWindowsNT) bool windowsNT;
# endif
#endif

/**
 * @brief Returns the size of a page.
 *
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




 * On macOS and iOS, it uses the `NSApplicationSupportDirectory` directory.@n
 * On Windows, it uses the `APPDATA` environment variable.@n
 * On Haiku, it uses the `B_USER_SETTINGS_DIRECTORY` directory.@n
 * On AmigaOS and MorphOS, it returns `PROGDIR:`.
 *
 * @return The path where user data for the application can be stored
 */
+ (nullable OFURI *)userDataURI;

/**
 * @brief Returns the path where user configuration for the application can be
 *	  stored.
 *
 * On UNIX systems, this adheres to the XDG Base Directory specification.@n
 * On macOS and iOS, it uses the `Preferences` directory inside of
 * `NSLibraryDirectory` directory.@n
 * On Windows, it uses the `APPDATA` environment variable.@n
 * On Haiku, it uses the `B_USER_SETTINGS_DIRECTORY` directory.
 * On AmigaOS and MorphOS, it returns `PROGDIR:`.
 *
 * @return The path where user configuration for the application can be stored
 */
+ (nullable OFURI *)userConfigURI;

/**
 * @brief Returns a path where temporary files for can be stored.
 * 
 * If possible, returns a temporary directory for the user, otherwise returns a
 * global temporary directory.
 *
 * On UNIX systems, this adheres to the XDG Base Directory specification and
 * returns `/tmp` if `XDG_RUNTIME_DIR` is not set.@n
 * On macOS and iOS, this uses `_CS_DARWIN_USER_TEMP_DIR`, falling back to
 * `/tmp` if this fails.@n
 * On Windows, it uses `GetTempPath`.@n
 * On Haiku, it uses the `B_SYSTEM_TEMP_DIRECTORY` directory.
 * On AmigaOS and MorphOS, it returns `T:`.
 *
 * @return A path where temporary files can be stored
 */
+ (nullable OFURI *)temporaryDirectoryURI;

/**
 * @brief Returns the vendor of the CPU.
 *
 * If the vendor could not be determined, `nil` is returned instead.
 *
 * @return The vendor of the CPU
 */
+ (nullable OFString *)CPUVendor;

/**
 * @brief Returns the model of the CPU.
 *
 * If the model could not be determined, `nil` is returned instead.
 *
 * @return The model of the CPU
 */
+ (nullable OFString *)CPUModel;

#if defined(OF_X86_64) || defined(OF_X86) || defined(DOXYGEN)
/**
 * @brief Returns whether the CPU supports MMX.
 *
 * @note This method is only available on x86 and x86_64.
 *
 * @return Whether the CPU supports MMX
 */
+ (bool)supportsMMX;



















/**
 * @brief Returns whether the CPU supports SSE.
 *
 * @warning This method only checks CPU support and assumes OS support!
 *
 * @note This method is only available on x86 and x86_64.
 *
 * @return Whether the CPU supports SSE
 */
+ (bool)supportsSSE;

/**
 * @brief Returns whether the CPU supports SSE2.
 *
 * @warning This method only checks CPU support and assumes OS support!
 *
 * @note This method is only available on x86 and x86_64.
 *
 * @return Whether the CPU supports SSE2
 */
+ (bool)supportsSSE2;

/**
 * @brief Returns whether the CPU supports SSE3.
 *
 * @warning This method only checks CPU support and assumes OS support!
 *
 * @note This method is only available on x86 and x86_64.
 *
 * @return Whether the CPU supports SSE3
 */
+ (bool)supportsSSE3;

/**
 * @brief Returns whether the CPU supports SSSE3.
 *
 * @warning This method only checks CPU support and assumes OS support!
 *
 * @note This method is only available on x86 and x86_64.
 *
 * @return Whether the CPU supports SSSE3
 */
+ (bool)supportsSSSE3;

/**
 * @brief Returns whether the CPU supports SSE4.1.
 *
 * @warning This method only checks CPU support and assumes OS support!
 *
 * @note This method is only available on x86 and x86_64.
 *
 * @return Whether the CPU supports SSE4.1
 */
+ (bool)supportsSSE41;

/**
 * @brief Returns whether the CPU supports SSE4.2.
 *
 * @warning This method only checks CPU support and assumes OS support!
 *
 * @note This method is only available on x86 and x86_64.
 *
 * @return Whether the CPU supports SSE4.2
 */
+ (bool)supportsSSE42;

/**
 * @brief Returns whether the CPU supports AVX.
 *
 * @warning This method only checks CPU support and assumes OS support!
 *
 * @note This method is only available on x86 and x86_64.
 *
 * @return Whether the CPU supports AVX
 */
+ (bool)supportsAVX;

/**
 * @brief Returns whether the CPU supports AVX2.
 *
 * @warning This method only checks CPU support and assumes OS support!
 *
 * @note This method is only available on x86 and x86_64.
 *
 * @return Whether the CPU supports AVX2
 */
+ (bool)supportsAVX2;

/**
 * @brief Returns whether the CPU supports AES-NI.
 *
 * @note This method is only available on x86 and x86_64.
 *
 * @return Whether the CPU supports AES-NI
 */
+ (bool)supportsAESNI;

/**
 * @brief Returns whether the CPU supports Intel SHA Extensions.
 *
 * @note This method is only available on x86 and x86_64.
 *
 * @return Whether the CPU supports Intel SHA Extensions
 */
+ (bool)supportsSHAExtensions;










































































































































































#endif

#if defined(OF_POWERPC) || defined(OF_POWERPC64)
/**
 * @brief Returns whether the CPU and OS support AltiVec.
 *
 * @note This method is only available on PowerPC and PowerPC 64.
 *
 * @return Whether the CPU and OS support AltiVec
 */
+ (bool)supportsAltiVec;
#endif

#ifdef OF_WINDOWS
/**
 * @brief Returns whether the application is running on Windows NT.
 *
 * @note This method is only available on Windows.
 *
 * @return Whether the application is running on Windows NT
 */
+ (bool)isWindowsNT;
#endif

+ (instancetype)alloc OF_UNAVAILABLE;
- (instancetype)init OF_UNAVAILABLE;
@end

OF_ASSUME_NONNULL_END











|














|

















|



















|



|





>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>



<
<
|








<
<
|








<
<
|








<
<
|








<
<
|








<
<
|






|

<
<
|

|




|

<
<
|

|






|








|




>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>


|










|















>
>
>
>
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
 * On macOS and iOS, it uses the `NSApplicationSupportDirectory` directory.@n
 * On Windows, it uses the `APPDATA` environment variable.@n
 * On Haiku, it uses the `B_USER_SETTINGS_DIRECTORY` directory.@n
 * On AmigaOS and MorphOS, it returns `PROGDIR:`.
 *
 * @return The path where user data for the application can be stored
 */
+ (nullable OFIRI *)userDataIRI;

/**
 * @brief Returns the path where user configuration for the application can be
 *	  stored.
 *
 * On UNIX systems, this adheres to the XDG Base Directory specification.@n
 * On macOS and iOS, it uses the `Preferences` directory inside of
 * `NSLibraryDirectory` directory.@n
 * On Windows, it uses the `APPDATA` environment variable.@n
 * On Haiku, it uses the `B_USER_SETTINGS_DIRECTORY` directory.
 * On AmigaOS and MorphOS, it returns `PROGDIR:`.
 *
 * @return The path where user configuration for the application can be stored
 */
+ (nullable OFIRI *)userConfigIRI;

/**
 * @brief Returns a path where temporary files for can be stored.
 * 
 * If possible, returns a temporary directory for the user, otherwise returns a
 * global temporary directory.
 *
 * On UNIX systems, this adheres to the XDG Base Directory specification and
 * returns `/tmp` if `XDG_RUNTIME_DIR` is not set.@n
 * On macOS and iOS, this uses `_CS_DARWIN_USER_TEMP_DIR`, falling back to
 * `/tmp` if this fails.@n
 * On Windows, it uses `GetTempPath`.@n
 * On Haiku, it uses the `B_SYSTEM_TEMP_DIRECTORY` directory.
 * On AmigaOS and MorphOS, it returns `T:`.
 *
 * @return A path where temporary files can be stored
 */
+ (nullable OFIRI *)temporaryDirectoryIRI;

/**
 * @brief Returns the vendor of the CPU.
 *
 * If the vendor could not be determined, `nil` is returned instead.
 *
 * @return The vendor of the CPU
 */
+ (nullable OFString *)CPUVendor;

/**
 * @brief Returns the model of the CPU.
 *
 * If the model could not be determined, `nil` is returned instead.
 *
 * @return The model of the CPU
 */
+ (nullable OFString *)CPUModel;

#if defined(OF_AMD64) || defined(OF_X86) || defined(DOXYGEN)
/**
 * @brief Returns whether the CPU supports MMX.
 *
 * @note This method is only available on AMD64 and x86.
 *
 * @return Whether the CPU supports MMX
 */
+ (bool)supportsMMX;

/**
 * @brief Returns whether the CPU supports 3DNow!.
 *
 * @note This method is only available on AMD64 and x86.
 *
 * @return Whether the CPU supports 3DNow!
 */
+ (bool)supports3DNow;

/**
 * @brief Returns whether the CPU supports enhanced 3DNow!.
 *
 * @note This method is only available on AMD64 and x86.
 *
 * @return Whether the CPU supports enhanced 3DNow!
 */
+ (bool)supportsEnhanced3DNow;

/**
 * @brief Returns whether the CPU supports SSE.
 *


 * @note This method is only available on AMD64 and x86.
 *
 * @return Whether the CPU supports SSE
 */
+ (bool)supportsSSE;

/**
 * @brief Returns whether the CPU supports SSE2.
 *


 * @note This method is only available on AMD64 and x86.
 *
 * @return Whether the CPU supports SSE2
 */
+ (bool)supportsSSE2;

/**
 * @brief Returns whether the CPU supports SSE3.
 *


 * @note This method is only available on AMD64 and x86.
 *
 * @return Whether the CPU supports SSE3
 */
+ (bool)supportsSSE3;

/**
 * @brief Returns whether the CPU supports SSSE3.
 *


 * @note This method is only available on AMD64 and x86.
 *
 * @return Whether the CPU supports SSSE3
 */
+ (bool)supportsSSSE3;

/**
 * @brief Returns whether the CPU supports SSE4.1.
 *


 * @note This method is only available on AMD64 and x86.
 *
 * @return Whether the CPU supports SSE4.1
 */
+ (bool)supportsSSE41;

/**
 * @brief Returns whether the CPU supports SSE4.2.
 *


 * @note This method is only available on AMD64 and x86.
 *
 * @return Whether the CPU supports SSE4.2
 */
+ (bool)supportsSSE42;

/**
 * @brief Returns whether the CPU and OS support AVX.
 *


 * @note This method is only available on AMD64 and x86.
 *
 * @return Whether the CPU and OS support AVX
 */
+ (bool)supportsAVX;

/**
 * @brief Returns whether the CPU and OS support AVX2.
 *


 * @note This method is only available on AMD64 and x86.
 *
 * @return Whether the CPU and OS support AVX2
 */
+ (bool)supportsAVX2;

/**
 * @brief Returns whether the CPU supports AES-NI.
 *
 * @note This method is only available on AMD64 and x86.
 *
 * @return Whether the CPU supports AES-NI
 */
+ (bool)supportsAESNI;

/**
 * @brief Returns whether the CPU supports Intel SHA Extensions.
 *
 * @note This method is only available on AMD64 and x86.
 *
 * @return Whether the CPU supports Intel SHA Extensions
 */
+ (bool)supportsSHAExtensions;

/**
 * @brief Returns whether the CPU supports fused multiply-add.
 *
 * @note This method is only available on AMD64 and x86.
 *
 * @return Whether the CPU supports fused multiply-add
 */
+ (bool)supportsFusedMultiplyAdd;

/**
 * @brief Returns whether the CPU supports F16C.
 *
 * @note This method is only available on AMD64 and x86.
 *
 * @return Whether the CPU supports F16C
 */
+ (bool)supportsF16C;

/**
 * @brief Returns whether the CPU and OS support AVX-512 Foundation.
 *
 * @note This method is only available on AMD64 and x86.
 *
 * @return Whether the CPU and OS support AVX-512 Foundation
 */
+ (bool)supportsAVX512Foundation;

/**
 * @brief Returns whether the CPU and OS support AVX-512 Conflict Detection
 *	  Instructions.
 *
 * @note This method is only available on AMD64 and x86.
 *
 * @return Whether the CPU and OS support AVX-512 Conflict Detection
 *	   Instructions
 */
+ (bool)supportsAVX512ConflictDetectionInstructions;

/**
 * @brief Returns whether the CPU and OS support AVX-512 Exponential and
 *	  Reciprocal Instructions.
 *
 * @note This method is only available on AMD64 and x86.
 *
 * @return Whether the CPU and OS support AVX-512 Exponential and Reciprocal
 *	   Instructions
 */
+ (bool)supportsAVX512ExponentialAndReciprocalInstructions;

/**
 * @brief Returns whether the CPU and OS support AVX-512 Prefetch Instructions.
 *
 * @note This method is only available on AMD64 and x86.
 *
 * @return Whether the CPU and OS support AVX-512 Prefetch Instructions
 */
+ (bool)supportsAVX512PrefetchInstructions;

/**
 * @brief Returns whether the CPU and OS support AVX-512 Vector Length
 *	  Extensions.
 *
 * @note This method is only available on AMD64 and x86.
 *
 * @return Whether the CPU and OS support AVX-512 Vector Length Extensions
 */
+ (bool)supportsAVX512VectorLengthExtensions;

/**
 * @brief Returns whether the CPU and OS support AVX-512 Doubleword and Quadword
 *	  Instructions.
 *
 * @note This method is only available on AMD64 and x86.
 *
 * @return Whether the CPU and OS support AVX-512 Doubleword and Quadword
 *	   Instructions
 */
+ (bool)supportsAVX512DoublewordAndQuadwordInstructions;

/**
 * @brief Returns whether the CPU and OS support AVX-512 Byte and Word
 *	  Instructions.
 *
 * @note This method is only available on AMD64 and x86.
 *
 * @return Whether the CPU and OS support AVX-512 Byte and Word Instructions
 */
+ (bool)supportsAVX512ByteAndWordInstructions;

/**
 * @brief Returns whether the CPU and OS support AVX-512 Integer Fused
 *	  Multiply-Add.
 *
 * @note This method is only available on AMD64 and x86.
 *
 * @return Whether the CPU and OS support AVX-512 Integer Fused Multiply-Add
 */
+ (bool)supportsAVX512IntegerFusedMultiplyAdd;

/**
 * @brief Returns whether the CPU and OS support AVX-512 Vector Byte
 *	  Manipulation Instructions.
 *
 * @note This method is only available on AMD64 and x86.
 *
 * @return Whether the CPU and OS support AVX-512 Vector Byte Manipulation
 *	   Instructions
 */
+ (bool)supportsAVX512VectorByteManipulationInstructions;

/**
 * @brief Returns whether the CPU and OS support the AVX-512 Vector Population
 *	  Count Instruction.
 *
 * @note This method is only available on AMD64 and x86.
 *
 * @return Whether the CPU and OS support AVX-512 the Vector Population Count
 *	   Instruction
 */
+ (bool)supportsAVX512VectorPopulationCountInstruction;

/**
 * @brief Returns whether the CPU and OS support AVX-512 Vector Neural Network
 *	  Instructions.
 *
 * @note This method is only available on AMD64 and x86.
 *
 * @return Whether the CPU and OS support AVX-512 Vector Neural Network
 *	   Instructions
 */
+ (bool)supportsAVX512VectorNeuralNetworkInstructions;

/**
 * @brief Returns whether the CPU and OS support AVX-512 Vector Byte
 *	  Manipulation Instructions 2.
 *
 * @note This method is only available on AMD64 and x86.
 *
 * @return Whether the CPU and OS support AVX-512 Vector Byte Manipulation
 *	   Instructions 2
 */
+ (bool)supportsAVX512VectorByteManipulationInstructions2;

/**
 * @brief Returns whether the CPU and OS support AVX-512 Bit Algorithms.
 *
 * @note This method is only available on AMD64 and x86.
 *
 * @return Whether the CPU and OS support AVX-512 Bit Algorithms
 */
+ (bool)supportsAVX512BitAlgorithms;

/**
 * @brief Returns whether the CPU and OS support AVX-512 Float16 Instructions.
 *
 * @note This method is only available on AMD64 and x86.
 *
 * @return Whether the CPU and OS support AVX-512 Float16 Instructions
 */
+ (bool)supportsAVX512Float16Instructions;

/**
 * @brief Returns whether the CPU and OS support AVX-512 BFloat16 Instructions.
 *
 * @note This method is only available on AMD64 and x86.
 *
 * @return Whether the CPU and OS support AVX-512 BFloat16 Instructions
 */
+ (bool)supportsAVX512BFloat16Instructions;
#endif

#if defined(OF_POWERPC) || defined(OF_POWERPC64) || defined(DOXYGEN)
/**
 * @brief Returns whether the CPU and OS support AltiVec.
 *
 * @note This method is only available on PowerPC and PowerPC 64.
 *
 * @return Whether the CPU and OS support AltiVec
 */
+ (bool)supportsAltiVec;
#endif

#if defined(OF_WINDOWS) || defined(DOXYGEN)
/**
 * @brief Returns whether the application is running on Windows NT.
 *
 * @note This method is only available on Windows.
 *
 * @return Whether the application is running on Windows NT
 */
+ (bool)isWindowsNT;
#endif

+ (instancetype)alloc OF_UNAVAILABLE;
- (instancetype)init OF_UNAVAILABLE;
@end

OF_ASSUME_NONNULL_END

#ifdef OF_HAVE_SOCKETS
# import "OFSystemInfo+NetworkInterfaces.h"
#endif

Modified src/OFSystemInfo.m from [9f095b0c1c] to [601054135e].

1
2
3
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-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#define __NO_EXT_QNX

#include "config.h"

#include <limits.h>	/* include any libc header to get the libc defines */



#include "unistd_wrapper.h"

#include "platform.h"

#ifdef HAVE_SYS_UTSNAME_H
# include <sys/utsname.h>
#endif
#if defined(OF_MACOS) || defined(OF_IOS) || defined(OF_NETBSD)
# include <sys/sysctl.h>
#endif

#ifdef OF_AMIGAOS

# include <exec/execbase.h>
# include <proto/exec.h>

#endif

#if defined(OF_AMIGAOS4)
# include <exec/exectags.h>
#elif defined(OF_MORPHOS)
# include <exec/system.h>
#endif

#ifdef OF_NINTENDO_SWITCH
# define id nx_id
# import <switch.h>
# undef nx_id
#endif





#import "OFSystemInfo.h"
#import "OFApplication.h"
#import "OFArray.h"

#import "OFDictionary.h"





#import "OFLocale.h"

#import "OFOnce.h"
#import "OFString.h"

#import "OFURI.h"


#if defined(OF_MACOS) || defined(OF_IOS)
# ifdef HAVE_SYSDIR_H
#  include <sysdir.h>
# endif
#endif
#ifdef OF_WINDOWS
# include <windows.h>
#endif
#ifdef OF_HAIKU
# include <FindDirectory.h>
#endif
#ifdef OF_QNX
# include <sys/syspage.h>
#endif


|


















>
>













>


>













>
>
>
>




>

>
>
>
>
>

>


>
|
>






<
<
<







1
2
3
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
/*
 * 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.
 */

#define __NO_EXT_QNX

#include "config.h"

#include <limits.h>	/* include any libc header to get the libc defines */
#include <setjmp.h>
#include <signal.h>

#include "unistd_wrapper.h"

#include "platform.h"

#ifdef HAVE_SYS_UTSNAME_H
# include <sys/utsname.h>
#endif
#if defined(OF_MACOS) || defined(OF_IOS) || defined(OF_NETBSD)
# include <sys/sysctl.h>
#endif

#ifdef OF_AMIGAOS
# define Class IntuitionClass
# include <exec/execbase.h>
# include <proto/exec.h>
# undef Class
#endif

#if defined(OF_AMIGAOS4)
# include <exec/exectags.h>
#elif defined(OF_MORPHOS)
# include <exec/system.h>
#endif

#ifdef OF_NINTENDO_SWITCH
# define id nx_id
# import <switch.h>
# undef nx_id
#endif

#ifdef OF_DJGPP
# include <dos.h>
#endif

#import "OFSystemInfo.h"
#import "OFApplication.h"
#import "OFArray.h"
#import "OFData.h"
#import "OFDictionary.h"
#ifdef OF_HAVE_FILES
# import "OFFile.h"
# import "OFFileManager.h"
#endif
#import "OFIRI.h"
#import "OFLocale.h"
#import "OFNumber.h"
#import "OFOnce.h"
#import "OFString.h"

#import "OFInvalidFormatException.h"
#import "OFOpenItemFailedException.h"

#if defined(OF_MACOS) || defined(OF_IOS)
# ifdef HAVE_SYSDIR_H
#  include <sysdir.h>
# endif
#endif



#ifdef OF_HAIKU
# include <FindDirectory.h>
#endif
#ifdef OF_QNX
# include <sys/syspage.h>
#endif

97
98
99
100
101
102
103
104
105
106
107

































108
109
110
111
112
113
114

extern NSSearchPathEnumerationState NSStartSearchPathEnumeration(
    NSSearchPathDirectory, NSSearchPathDomainMask);
extern NSSearchPathEnumerationState NSGetNextSearchPathEnumeration(
    NSSearchPathEnumerationState, char *);
#endif

#if defined(OF_X86_64) || defined(OF_X86)
struct X86Regs {
	uint32_t eax, ebx, ecx, edx;
};

































#endif

static size_t pageSize = 4096;
static size_t numberOfCPUs = 1;
static OFString *operatingSystemName = nil;
static OFString *operatingSystemVersion = nil;








|



>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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

extern NSSearchPathEnumerationState NSStartSearchPathEnumeration(
    NSSearchPathDirectory, NSSearchPathDomainMask);
extern NSSearchPathEnumerationState NSGetNextSearchPathEnumeration(
    NSSearchPathEnumerationState, char *);
#endif

#if defined(OF_AMD64) || defined(OF_X86)
struct X86Regs {
	uint32_t eax, ebx, ecx, edx;
};

static bool SSESupport;
static jmp_buf SSETestEnv;

static void
SSETestSIGILLHandler(int signum)
{
	longjmp(SSETestEnv, 1);
}

# ifndef __clang__
#  pragma GCC push_options
#  pragma GCC target("sse")
# endif
static void
SSETest(void)
{
	void (*oldHandler)(int) = signal(SIGILL, SSETestSIGILLHandler);

	if (setjmp(SSETestEnv) == 0) {
		__asm__ __volatile__ (
		    "movaps	%%xmm0, %%xmm0"
		    ::: "xmm0"	/* clang is unhappy if we don't clobber it */
		);
		SSESupport = true;
	} else
		SSESupport = false;

	signal(SIGILL, oldHandler);
}
# ifndef __clang__
#  pragma GCC pop_options
# endif
#endif

static size_t pageSize = 4096;
static size_t numberOfCPUs = 1;
static OFString *operatingSystemName = nil;
static OFString *operatingSystemVersion = nil;

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
	operatingSystemName = @"AmigaOS";
#elif defined(OF_MORPHOS)
	operatingSystemName = @"MorphOS";
#elif defined(OF_AMIGAOS4)
	operatingSystemName = @"AmigaOS 4";
#elif defined(OF_WII)
	operatingSystemName = @"Nintendo Wii";


#elif defined(NINTENDO_3DS)
	operatingSystemName = @"Nintendo 3DS";
#elif defined(OF_NINTENDO_DS)
	operatingSystemName = @"Nintendo DS";


#elif defined(OF_PSP)
	operatingSystemName = @"PlayStation Portable";
#elif defined(OF_MSDOS)
	operatingSystemName = @"MS-DOS";


#elif defined(HAVE_SYS_UTSNAME_H) && defined(HAVE_UNAME)
	struct utsname utsname;

	if (uname(&utsname) != 0)
		return;

	operatingSystemName = [[OFString alloc]
	    initWithCString: utsname.sysname
		   encoding: [OFLocale encoding]];
#endif
}

static void
initOperatingSystemVersion(void)
{







>
>




>
>


|
|
>
>

|

|



|







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
	operatingSystemName = @"AmigaOS";
#elif defined(OF_MORPHOS)
	operatingSystemName = @"MorphOS";
#elif defined(OF_AMIGAOS4)
	operatingSystemName = @"AmigaOS 4";
#elif defined(OF_WII)
	operatingSystemName = @"Nintendo Wii";
#elif defined(OF_WII_U)
	operatingSystemName = @"Nintendo Wii U";
#elif defined(NINTENDO_3DS)
	operatingSystemName = @"Nintendo 3DS";
#elif defined(OF_NINTENDO_DS)
	operatingSystemName = @"Nintendo DS";
#elif defined(OF_NINTENDO_SWITCH)
	operatingSystemName = @"Nintendo Switch";
#elif defined(OF_PSP)
	operatingSystemName = @"PlayStation Portable";
#elif defined(OF_DJGPP)
	operatingSystemName = [[OFString alloc]
	    initWithCString: _os_flavor
		   encoding: OFStringEncodingASCII];
#elif defined(HAVE_SYS_UTSNAME_H) && defined(HAVE_UNAME)
	struct utsname name;

	if (uname(&name) == -1)
		return;

	operatingSystemName = [[OFString alloc]
	    initWithCString: name.sysname
		   encoding: [OFLocale encoding]];
#endif
}

static void
initOperatingSystemVersion(void)
{
226
227
228
229
230
231
232



233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268

269



270
271
272
273
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
# endif
#elif defined(OF_ANDROID)
	/* TODO */
#elif defined(OF_AMIGAOS)
	operatingSystemVersion = [[OFString alloc]
	    initWithFormat: @"Kickstart %u.%u",
			    SysBase->LibNode.lib_Version, SysBase->SoftVer];



#elif defined(OF_WII) || defined(NINTENDO_3DS) || defined(OF_NINTENDO_DS) || \
    defined(OF_PSP) || defined(OF_MSDOS)
	/* Intentionally nothing */
#elif defined(HAVE_SYS_UTSNAME_H) && defined(HAVE_UNAME)
	struct utsname utsname;

	if (uname(&utsname) != 0)
		return;

	operatingSystemVersion = [[OFString alloc]
	    initWithCString: utsname.release
		   encoding: [OFLocale encoding]];
#endif
}

#ifdef OF_NINTENDO_SWITCH
static OFURI *tmpFSURI = nil;

static void
mountTmpFS(void)
{
	if (R_SUCCEEDED(fsdevMountTemporaryStorage("tmpfs")))
		tmpFSURI = [[OFURI alloc] initFileURIWithPath: @"tmpfs:/"
						  isDirectory: true];
}
#endif

#if defined(OF_X86_64) || defined(OF_X86)
static OF_INLINE struct X86Regs OF_CONST_FUNC
x86CPUID(uint32_t eax, uint32_t ecx)
{
	struct X86Regs regs;

# if defined(OF_X86_64) && defined(__GNUC__)
	__asm__ (
	    "cpuid"

	    : "=a"(regs.eax), "=b"(regs.ebx), "=c"(regs.ecx), "=d"(regs.edx)



	    : "a"(eax), "c"(ecx)
	);
# elif defined(OF_X86) && defined(__GNUC__)
	/*
	 * This workaround is required by older GCC versions when using -fPIC,
	 * as ebx is a special register in PIC code. Yes, GCC is indeed not
	 * able to just push a register onto the stack before the __asm__ block
	 * and to pop it afterwards.
	 */
	__asm__ (
	    "xchgl	%%ebx, %%edi\n\t"
	    "cpuid\n\t"
	    "xchgl	%%edi, %%ebx"

	    : "=a"(regs.eax), "=D"(regs.ebx), "=c"(regs.ecx), "=d"(regs.edx)



	    : "a"(eax), "c"(ecx)
	);
# else
	memset(&regs, 0, sizeof(regs));
# endif



















	return regs;
}
#endif

@implementation OFSystemInfo
+ (void)initialize
{
	long tmp;

	if (self != [OFSystemInfo class])
		return;










#if defined(OF_WINDOWS)
	SYSTEM_INFO si;
	GetSystemInfo(&si);
	pageSize = si.dwPageSize;
	numberOfCPUs = si.dwNumberOfProcessors;
#elif defined(OF_QNX)







>
>
>

|


|

|



|





|





|




|





|


>
|
>
>
>
|












>
|
>
>
>
|




>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>












>
>
>
>
>
>
>
>
>







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
# endif
#elif defined(OF_ANDROID)
	/* TODO */
#elif defined(OF_AMIGAOS)
	operatingSystemVersion = [[OFString alloc]
	    initWithFormat: @"Kickstart %u.%u",
			    SysBase->LibNode.lib_Version, SysBase->SoftVer];
#elif defined(OF_DJGPP)
	operatingSystemVersion = [[OFString alloc]
	    initWithFormat: @"%u.%u", _osmajor, _osminor];
#elif defined(OF_WII) || defined(NINTENDO_3DS) || defined(OF_NINTENDO_DS) || \
    defined(OF_PSP)
	/* Intentionally nothing */
#elif defined(HAVE_SYS_UTSNAME_H) && defined(HAVE_UNAME)
	struct utsname name;

	if (uname(&name) == -1)
		return;

	operatingSystemVersion = [[OFString alloc]
	    initWithCString: name.release
		   encoding: [OFLocale encoding]];
#endif
}

#ifdef OF_NINTENDO_SWITCH
static OFIRI *tmpFSIRI = nil;

static void
mountTmpFS(void)
{
	if (R_SUCCEEDED(fsdevMountTemporaryStorage("tmpfs")))
		tmpFSIRI = [[OFIRI alloc] initFileIRIWithPath: @"tmpfs:/"
						  isDirectory: true];
}
#endif

#if defined(OF_AMD64) || defined(OF_X86)
static OF_INLINE struct X86Regs OF_CONST_FUNC
x86CPUID(uint32_t eax, uint32_t ecx)
{
	struct X86Regs regs;

# if defined(OF_AMD64) && defined(__GNUC__)
	__asm__ (
	    "cpuid"
	    : "=a" (regs.eax),
	      "=b" (regs.ebx),
	      "=c" (regs.ecx),
	      "=d" (regs.edx)
	    : "a" (eax),
	      "c" (ecx)
	);
# elif defined(OF_X86) && defined(__GNUC__)
	/*
	 * This workaround is required by older GCC versions when using -fPIC,
	 * as ebx is a special register in PIC code. Yes, GCC is indeed not
	 * able to just push a register onto the stack before the __asm__ block
	 * and to pop it afterwards.
	 */
	__asm__ (
	    "xchgl	%%ebx, %%edi\n\t"
	    "cpuid\n\t"
	    "xchgl	%%edi, %%ebx"
	    : "=a" (regs.eax),
	      "=D" (regs.ebx),
	      "=c" (regs.ecx),
	      "=d" (regs.edx)
	    : "a" (eax),
	      "c" (ecx)
	);
# else
	memset(&regs, 0, sizeof(regs));
# endif

	return regs;
}

static OF_INLINE struct X86Regs
x86XCR(uint32_t ecx)
{
	struct X86Regs regs = { 0 };

	if (!(x86CPUID(1, 0).ecx & (1u << 27)))
		return regs;

	__asm__ (
	    "xgetbv"
	    : "=a" (regs.eax),
	      "=d" (regs.edx)
	    : "c" (ecx)
	);

	return regs;
}
#endif

@implementation OFSystemInfo
+ (void)initialize
{
	long tmp;

	if (self != [OFSystemInfo class])
		return;

#if defined(OF_AMD64) || defined(OF_X86)
	/*
	 * Do this as early as possible, as it involves signals.
	 * Required as cpuid can return SSE support while the OS has not
	 * enabled it.
	 */
	SSETest();
#endif

#if defined(OF_WINDOWS)
	SYSTEM_INFO si;
	GetSystemInfo(&si);
	pageSize = si.dwPageSize;
	numberOfCPUs = si.dwNumberOfProcessors;
#elif defined(OF_QNX)
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
{
	static OFOnceControl onceControl = OFOnceControlInitValue;
	OFOnce(&onceControl, initOperatingSystemVersion);

	return operatingSystemVersion;
}

+ (OFURI *)userDataURI
{
#ifdef OF_HAVE_FILES
# if defined(OF_MACOS) || defined(OF_IOS)
	char pathC[PATH_MAX];
	OFMutableString *path;

#  ifdef HAVE_SYSDIR_START_SEARCH_PATH_ENUMERATION







|







455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
{
	static OFOnceControl onceControl = OFOnceControlInitValue;
	OFOnce(&onceControl, initOperatingSystemVersion);

	return operatingSystemVersion;
}

+ (OFIRI *)userDataIRI
{
#ifdef OF_HAVE_FILES
# if defined(OF_MACOS) || defined(OF_IOS)
	char pathC[PATH_MAX];
	OFMutableString *path;

#  ifdef HAVE_SYSDIR_START_SEARCH_PATH_ENUMERATION
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432


433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468

		[path deleteCharactersInRange: OFMakeRange(0, 1)];
		[path insertString: home atIndex: 0];
	}

	[path makeImmutable];

	return [OFURI fileURIWithPath: path isDirectory: true];
# elif defined(OF_WINDOWS)
	OFDictionary *env = [OFApplication environment];
	OFString *appData;

	if ((appData = [env objectForKey: @"APPDATA"]) == nil)
		return nil;

	return [OFURI fileURIWithPath: appData isDirectory: true];
# elif defined(OF_HAIKU)
	char pathC[PATH_MAX];

	if (find_directory(B_USER_SETTINGS_DIRECTORY, 0, false,
	    pathC, PATH_MAX) != B_OK)
		return nil;

	return [OFURI fileURIWithPath: [OFString stringWithUTF8String: pathC]
			  isDirectory: true];
# elif defined(OF_AMIGAOS)
	return [OFURI fileURIWithPath: @"PROGDIR:" isDirectory: true];


# else
	OFDictionary *env = [OFApplication environment];
	OFString *var;
	OFURI *URI;
	void *pool;

	if ((var = [env objectForKey: @"XDG_DATA_HOME"]) != nil &&
	    var.length > 0)
		return [OFURI fileURIWithPath: var isDirectory: true];

	if ((var = [env objectForKey: @"HOME"]) == nil)
		return nil;

	pool = objc_autoreleasePoolPush();

	var = [OFString pathWithComponents: [OFArray arrayWithObjects:
	    var, @".local", @"share", nil]];
	URI = [[OFURI alloc] initFileURIWithPath: var isDirectory: true];

	objc_autoreleasePoolPop(pool);

	return [URI autorelease];
# endif
#else
	return nil;
#endif
}

+ (OFURI *)userConfigURI
{
#ifdef OF_HAVE_FILES
# if defined(OF_MACOS) || defined(OF_IOS)
	char pathC[PATH_MAX];
	OFMutableString *path;

#  ifdef HAVE_SYSDIR_START_SEARCH_PATH_ENUMERATION







|







|







|


|
>
>



|




|








|



|






|







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

		[path deleteCharactersInRange: OFMakeRange(0, 1)];
		[path insertString: home atIndex: 0];
	}

	[path makeImmutable];

	return [OFIRI fileIRIWithPath: path isDirectory: true];
# elif defined(OF_WINDOWS)
	OFDictionary *env = [OFApplication environment];
	OFString *appData;

	if ((appData = [env objectForKey: @"APPDATA"]) == nil)
		return nil;

	return [OFIRI fileIRIWithPath: appData isDirectory: true];
# elif defined(OF_HAIKU)
	char pathC[PATH_MAX];

	if (find_directory(B_USER_SETTINGS_DIRECTORY, 0, false,
	    pathC, PATH_MAX) != B_OK)
		return nil;

	return [OFIRI fileIRIWithPath: [OFString stringWithUTF8String: pathC]
			  isDirectory: true];
# elif defined(OF_AMIGAOS)
	return [OFIRI fileIRIWithPath: @"PROGDIR:" isDirectory: true];
# elif defined(OF_WII) || defined(OF_NINTENDO_3DS)
	return [[OFFileManager defaultManager] currentDirectoryIRI];
# else
	OFDictionary *env = [OFApplication environment];
	OFString *var;
	OFIRI *IRI;
	void *pool;

	if ((var = [env objectForKey: @"XDG_DATA_HOME"]) != nil &&
	    var.length > 0)
		return [OFIRI fileIRIWithPath: var isDirectory: true];

	if ((var = [env objectForKey: @"HOME"]) == nil)
		return nil;

	pool = objc_autoreleasePoolPush();

	var = [OFString pathWithComponents: [OFArray arrayWithObjects:
	    var, @".local", @"share", nil]];
	IRI = [[OFIRI alloc] initFileIRIWithPath: var isDirectory: true];

	objc_autoreleasePoolPop(pool);

	return [IRI autorelease];
# endif
#else
	return nil;
#endif
}

+ (OFIRI *)userConfigIRI
{
#ifdef OF_HAVE_FILES
# if defined(OF_MACOS) || defined(OF_IOS)
	char pathC[PATH_MAX];
	OFMutableString *path;

#  ifdef HAVE_SYSDIR_START_SEARCH_PATH_ENUMERATION
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522


523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599


600
601
602
603
604
605
606

607


608

609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
		[path deleteCharactersInRange: OFMakeRange(0, 1)];
		[path insertString: home atIndex: 0];
	}

	[path appendString: @"/Preferences"];
	[path makeImmutable];

	return [OFURI fileURIWithPath: path isDirectory: true];
# elif defined(OF_WINDOWS)
	OFDictionary *env = [OFApplication environment];
	OFString *appData;

	if ((appData = [env objectForKey: @"APPDATA"]) == nil)
		return nil;

	return [OFURI fileURIWithPath: appData isDirectory: true];
# elif defined(OF_HAIKU)
	char pathC[PATH_MAX];

	if (find_directory(B_USER_SETTINGS_DIRECTORY, 0, false,
	    pathC, PATH_MAX) != B_OK)
		return nil;

	return [OFURI fileURIWithPath: [OFString stringWithUTF8String: pathC]
			  isDirectory: true];
# elif defined(OF_AMIGAOS)
	return [OFURI fileURIWithPath: @"PROGDIR:" isDirectory: true];


# else
	OFDictionary *env = [OFApplication environment];
	OFString *var;

	if ((var = [env objectForKey: @"XDG_CONFIG_HOME"]) != nil &&
	    var.length > 0)
		return [OFURI fileURIWithPath: var isDirectory: true];

	if ((var = [env objectForKey: @"HOME"]) == nil)
		return nil;

	var = [var stringByAppendingPathComponent: @".config"];

	return [OFURI fileURIWithPath: var isDirectory: true];
# endif
#else
	return nil;
#endif
}

+ (OFURI *)temporaryDirectoryURI
{
#ifdef OF_HAVE_FILES
# if defined(OF_MACOS) || defined(OF_IOS)
	char buffer[PATH_MAX];
	size_t length;
	OFString *path;

	if ((length = confstr(_CS_DARWIN_USER_TEMP_DIR, buffer, PATH_MAX)) == 0)
		return [OFURI fileURIWithPath: @"/tmp" isDirectory: true];

	path = [OFString stringWithCString: buffer
				  encoding: [OFLocale encoding]
				    length: length - 1];

	return [OFURI fileURIWithPath: path isDirectory: true];
# elif defined(OF_WINDOWS)
	OFString *path;

	if ([self isWindowsNT]) {
		wchar_t buffer[PATH_MAX];

		if (!GetTempPathW(PATH_MAX, buffer))
			return nil;

		path = [OFString stringWithUTF16String: buffer];
	} else {
		char buffer[PATH_MAX];

		if (!GetTempPathA(PATH_MAX, buffer))
			return nil;

		path = [OFString stringWithCString: buffer
					  encoding: [OFLocale encoding]];
	}

	return [OFURI fileURIWithPath: path isDirectory: true];
# elif defined(OF_HAIKU)
	char pathC[PATH_MAX];

	if (find_directory(B_SYSTEM_TEMP_DIRECTORY, 0, false,
	    pathC, PATH_MAX) != B_OK)
		return nil;

	return [OFURI fileURIWithPath: [OFString stringWithUTF8String: pathC]
			  isDirectory: true];
# elif defined(OF_AMIGAOS)
	return [OFURI fileURIWithPath: @"T:" isDirectory: true];
# elif defined(OF_MSDOS)
	OFString *path = [[OFApplication environment] objectForKey: @"TEMP"];

	if (path == nil)
		return nil;

	return [OFURI fileURIWithPath: path isDirectory: true];
# elif defined(OF_MINT)
	return [OFURI fileURIWithPath: @"u:\\tmp" isDirectory: true];


# elif defined(OF_NINTENDO_SWITCH)
	static OFOnceControl onceControl = OFOnceControlInitValue;
	OFOnce(&onceControl, mountTmpFS);

	return tmpFSURI;
# else
	OFString *path =

	    [[OFApplication environment] objectForKey: @"XDG_RUNTIME_DIR"];




	if (path != nil)
		return [OFURI fileURIWithPath: path];

	return [OFURI fileURIWithPath: @"/tmp"];
# endif
#else
	return nil;
#endif
}

+ (OFString *)CPUVendor
{
#if (defined(OF_X86_64) || defined(OF_X86)) && defined(__GNUC__)
	struct X86Regs regs = x86CPUID(0, 0);
	uint32_t buffer[3];

	if (regs.eax == 0)
		return nil;

	buffer[0] = regs.ebx;







|







|







|


|
>
>






|






|






|








|





|




















|







|


|






|

|
>
>




|

|
>
|
>
>

>

|

|








|







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
		[path deleteCharactersInRange: OFMakeRange(0, 1)];
		[path insertString: home atIndex: 0];
	}

	[path appendString: @"/Preferences"];
	[path makeImmutable];

	return [OFIRI fileIRIWithPath: path isDirectory: true];
# elif defined(OF_WINDOWS)
	OFDictionary *env = [OFApplication environment];
	OFString *appData;

	if ((appData = [env objectForKey: @"APPDATA"]) == nil)
		return nil;

	return [OFIRI fileIRIWithPath: appData isDirectory: true];
# elif defined(OF_HAIKU)
	char pathC[PATH_MAX];

	if (find_directory(B_USER_SETTINGS_DIRECTORY, 0, false,
	    pathC, PATH_MAX) != B_OK)
		return nil;

	return [OFIRI fileIRIWithPath: [OFString stringWithUTF8String: pathC]
			  isDirectory: true];
# elif defined(OF_AMIGAOS)
	return [OFIRI fileIRIWithPath: @"PROGDIR:" isDirectory: true];
# elif defined(OF_WII) || defined(OF_NINTENDO_3DS)
	return [[OFFileManager defaultManager] currentDirectoryIRI];
# else
	OFDictionary *env = [OFApplication environment];
	OFString *var;

	if ((var = [env objectForKey: @"XDG_CONFIG_HOME"]) != nil &&
	    var.length > 0)
		return [OFIRI fileIRIWithPath: var isDirectory: true];

	if ((var = [env objectForKey: @"HOME"]) == nil)
		return nil;

	var = [var stringByAppendingPathComponent: @".config"];

	return [OFIRI fileIRIWithPath: var isDirectory: true];
# endif
#else
	return nil;
#endif
}

+ (OFIRI *)temporaryDirectoryIRI
{
#ifdef OF_HAVE_FILES
# if defined(OF_MACOS) || defined(OF_IOS)
	char buffer[PATH_MAX];
	size_t length;
	OFString *path;

	if ((length = confstr(_CS_DARWIN_USER_TEMP_DIR, buffer, PATH_MAX)) == 0)
		return [OFIRI fileIRIWithPath: @"/tmp" isDirectory: true];

	path = [OFString stringWithCString: buffer
				  encoding: [OFLocale encoding]
				    length: length - 1];

	return [OFIRI fileIRIWithPath: path isDirectory: true];
# elif defined(OF_WINDOWS)
	OFString *path;

	if ([self isWindowsNT]) {
		wchar_t buffer[PATH_MAX];

		if (!GetTempPathW(PATH_MAX, buffer))
			return nil;

		path = [OFString stringWithUTF16String: buffer];
	} else {
		char buffer[PATH_MAX];

		if (!GetTempPathA(PATH_MAX, buffer))
			return nil;

		path = [OFString stringWithCString: buffer
					  encoding: [OFLocale encoding]];
	}

	return [OFIRI fileIRIWithPath: path isDirectory: true];
# elif defined(OF_HAIKU)
	char pathC[PATH_MAX];

	if (find_directory(B_SYSTEM_TEMP_DIRECTORY, 0, false,
	    pathC, PATH_MAX) != B_OK)
		return nil;

	return [OFIRI fileIRIWithPath: [OFString stringWithUTF8String: pathC]
			  isDirectory: true];
# elif defined(OF_AMIGAOS)
	return [OFIRI fileIRIWithPath: @"T:" isDirectory: true];
# elif defined(OF_MSDOS)
	OFString *path = [[OFApplication environment] objectForKey: @"TEMP"];

	if (path == nil)
		return nil;

	return [OFIRI fileIRIWithPath: path isDirectory: true];
# elif defined(OF_MINT)
	return [OFIRI fileIRIWithPath: @"u:\\tmp" isDirectory: true];
# elif defined(OF_WII) || defined(OF_NINTENDO_3DS)
	return [[OFFileManager defaultManager] currentDirectoryIRI];
# elif defined(OF_NINTENDO_SWITCH)
	static OFOnceControl onceControl = OFOnceControlInitValue;
	OFOnce(&onceControl, mountTmpFS);

	return tmpFSIRI;
# else
	OFString *path;

	path = [[OFApplication environment] objectForKey: @"XDG_RUNTIME_DIR"];
	if (path != nil)
		return [OFIRI fileIRIWithPath: path isDirectory: true];

	path = [[OFApplication environment] objectForKey: @"TMPDIR"];
	if (path != nil)
		return [OFIRI fileIRIWithPath: path isDirectory: true];

	return [OFIRI fileIRIWithPath: @"/tmp" isDirectory: true];
# endif
#else
	return nil;
#endif
}

+ (OFString *)CPUVendor
{
#if (defined(OF_AMD64) || defined(OF_X86)) && defined(__GNUC__)
	struct X86Regs regs = x86CPUID(0, 0);
	uint32_t buffer[3];

	if (regs.eax == 0)
		return nil;

	buffer[0] = regs.ebx;
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
#else
	return nil;
#endif
}

+ (OFString *)CPUModel
{
#if (defined(OF_X86_64) || defined(OF_X86)) && defined(__GNUC__)
	struct X86Regs regs = x86CPUID(0x80000000, 0);
	uint32_t buffer[12];
	size_t i;

	if (regs.eax < 0x80000004)
		return nil;








|







738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
#else
	return nil;
#endif
}

+ (OFString *)CPUModel
{
#if (defined(OF_AMD64) || defined(OF_X86)) && defined(__GNUC__)
	struct X86Regs regs = x86CPUID(0x80000000, 0);
	uint32_t buffer[12];
	size_t i;

	if (regs.eax < 0x80000004)
		return nil;

696
697
698
699
700
701
702
703
704
705






706






707
708
709
710

711
712
713
714
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
	else
		return @"68000";
#else
	return nil;
#endif
}

#if defined(OF_X86_64) || defined(OF_X86)
+ (bool)supportsMMX
{






	return (x86CPUID(1, 0).edx & (1u << 23));






}

+ (bool)supportsSSE
{

	return (x86CPUID(1, 0).edx & (1u << 25));
}

+ (bool)supportsSSE2
{

	return (x86CPUID(1, 0).edx & (1u << 26));
}

+ (bool)supportsSSE3
{

	return (x86CPUID(1, 0).ecx & (1u << 0));
}

+ (bool)supportsSSSE3
{

	return (x86CPUID(1, 0).ecx & (1u << 9));
}

+ (bool)supportsSSE41
{

	return (x86CPUID(1, 0).ecx & (1u << 19));
}

+ (bool)supportsSSE42
{

	return (x86CPUID(1, 0).ecx & (1u << 20));
}

+ (bool)supportsAVX
{
	return (x86CPUID(1, 0).ecx & (1u << 28));

}

+ (bool)supportsAVX2
{
	return x86CPUID(0, 0).eax >= 7 && (x86CPUID(7, 0).ebx & (1u << 5));

}

+ (bool)supportsAESNI
{
	return (x86CPUID(1, 0).ecx & (1u << 25));
}

+ (bool)supportsSHAExtensions
{


	return (x86CPUID(7, 0).ebx & (1u << 29));


































































































}
#endif

#if defined(OF_POWERPC) || defined(OF_POWERPC64)
+ (bool)supportsAltiVec
{
# if defined(OF_MACOS)







|


>
>
>
>
>
>
|
>
>
>
>
>
>




>
|




>
|




>
|




>
|




>
|




>
|




|
>




|
>




|




>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
	else
		return @"68000";
#else
	return nil;
#endif
}

#if defined(OF_AMD64) || defined(OF_X86)
+ (bool)supportsMMX
{
	return (x86CPUID(0, 0).eax >= 1 && x86CPUID(1, 0).edx & (1u << 23));
}

+ (bool)supports3DNow
{
	return (x86CPUID(0x80000000, 0).eax >= 0x80000001 &&
	    x86CPUID(0x80000001, 0).edx & (1u << 31));
}

+ (bool)supportsEnhanced3DNow
{
	return (x86CPUID(0x80000000, 0).eax >= 0x80000001 &&
	    x86CPUID(0x80000001, 0).edx & (1u << 30));
}

+ (bool)supportsSSE
{
	return SSESupport &&
	    (x86CPUID(0, 0).eax >= 1 && x86CPUID(1, 0).edx & (1u << 25));
}

+ (bool)supportsSSE2
{
	return SSESupport &&
	    (x86CPUID(0, 0).eax >= 1 && x86CPUID(1, 0).edx & (1u << 26));
}

+ (bool)supportsSSE3
{
	return SSESupport &&
	    (x86CPUID(0, 0).eax >= 1 && x86CPUID(1, 0).ecx & (1u << 0));
}

+ (bool)supportsSSSE3
{
	return SSESupport &&
	    (x86CPUID(0, 0).eax >= 1 && x86CPUID(1, 0).ecx & (1u << 9));
}

+ (bool)supportsSSE41
{
	return SSESupport &&
	    (x86CPUID(0, 0).eax >= 1 && x86CPUID(1, 0).ecx & (1u << 19));
}

+ (bool)supportsSSE42
{
	return SSESupport &&
	    (x86CPUID(0, 0).eax >= 1 && x86CPUID(1, 0).ecx & (1u << 20));
}

+ (bool)supportsAVX
{
	return ((x86CPUID(0, 0).eax >= 1 && x86CPUID(1, 0).ecx & (1u << 28)) &&
	    (x86XCR(0).eax & 0x6) == 0x6);
}

+ (bool)supportsAVX2
{
	return ((x86CPUID(0, 0).eax >= 7 && (x86CPUID(7, 0).ebx & (1u << 5))) &&
	    (x86XCR(0).eax & 0x6) == 0x6);
}

+ (bool)supportsAESNI
{
	return (x86CPUID(0, 0).eax >= 1 && x86CPUID(1, 0).ecx & (1u << 25));
}

+ (bool)supportsSHAExtensions
{
	return (x86CPUID(0, 0).eax >= 7 && x86CPUID(7, 0).ebx & (1u << 29));
}

+ (bool)supportsFusedMultiplyAdd
{
	return (x86CPUID(0, 0).eax >= 1 && x86CPUID(1, 0).ecx & (1u << 12));
}

+ (bool)supportsF16C
{
	return (x86CPUID(0, 0).eax >= 1 && x86CPUID(1, 0).ecx & (1u << 29));
}

+ (bool)supportsAVX512Foundation
{
	return ((x86CPUID(0, 0).eax >= 7 && x86CPUID(7, 0).ebx & (1u << 16)) &&
	    (x86XCR(0).eax & 0xE6) == 0xE6);
}

+ (bool)supportsAVX512ConflictDetectionInstructions
{
	return ((x86CPUID(0, 0).eax >= 7 && x86CPUID(7, 0).ebx & (1u << 28)) &&
	    (x86XCR(0).eax & 0xE6) == 0xE6);
}

+ (bool)supportsAVX512ExponentialAndReciprocalInstructions
{
	return ((x86CPUID(0, 0).eax >= 7 && x86CPUID(7, 0).ebx & (1u << 27)) &&
	    (x86XCR(0).eax & 0xE6) == 0xE6);
}

+ (bool)supportsAVX512PrefetchInstructions
{
	return ((x86CPUID(0, 0).eax >= 7 && x86CPUID(7, 0).ebx & (1u << 26)) &&
	    (x86XCR(0).eax & 0xE6) == 0xE6);
}

+ (bool)supportsAVX512VectorLengthExtensions
{
	return ((x86CPUID(0, 0).eax >= 7 && x86CPUID(7, 0).ebx & (1u << 31)) &&
	    (x86XCR(0).eax & 0xE6) == 0xE6);
}

+ (bool)supportsAVX512DoublewordAndQuadwordInstructions
{
	return ((x86CPUID(0, 0).eax >= 7 && x86CPUID(7, 0).ebx & (1u << 17)) &&
	    (x86XCR(0).eax & 0xE6) == 0xE6);
}

+ (bool)supportsAVX512ByteAndWordInstructions
{
	return ((x86CPUID(0, 0).eax >= 7 && x86CPUID(7, 0).ebx & (1u << 30)) &&
	    (x86XCR(0).eax & 0xE6) == 0xE6);
}

+ (bool)supportsAVX512IntegerFusedMultiplyAdd
{
	return ((x86CPUID(0, 0).eax >= 7 && x86CPUID(7, 0).ebx & (1u << 21)) &&
	    (x86XCR(0).eax & 0xE6) == 0xE6);
}

+ (bool)supportsAVX512VectorByteManipulationInstructions
{
	return ((x86CPUID(0, 0).eax >= 7 && x86CPUID(7, 0).ecx & (1u << 1)) &&
	    (x86XCR(0).eax & 0xE6) == 0xE6);
}

+ (bool)supportsAVX512VectorPopulationCountInstruction
{
	return ((x86CPUID(0, 0).eax >= 7 && x86CPUID(7, 0).ecx & (1u << 14)) &&
	    (x86XCR(0).eax & 0xE6) == 0xE6);
}

+ (bool)supportsAVX512VectorNeuralNetworkInstructions
{
	return ((x86CPUID(0, 0).eax >= 7 && x86CPUID(7, 0).ecx & (1u << 11)) &&
	    (x86XCR(0).eax & 0xE6) == 0xE6);
}

+ (bool)supportsAVX512VectorByteManipulationInstructions2
{
	return ((x86CPUID(0, 0).eax >= 7 && x86CPUID(7, 0).ecx & (1u << 6)) &&
	    (x86XCR(0).eax & 0xE6) == 0xE6);
}

+ (bool)supportsAVX512BitAlgorithms
{
	return ((x86CPUID(0, 0).eax >= 7 && x86CPUID(7, 0).ecx & (1u << 12)) &&
	    (x86XCR(0).eax & 0xE6) == 0xE6);
}

+ (bool)supportsAVX512Float16Instructions
{
	return ((x86CPUID(0, 0).eax >= 7 && x86CPUID(7, 0).edx & (1u << 23)) &&
	    (x86XCR(0).eax & 0xE6) == 0xE6);
}

+ (bool)supportsAVX512BFloat16Instructions
{
	return ((x86CPUID(0, 0).eax >= 7 && x86CPUID(7, 1).eax & (1u << 5)) &&
	    (x86XCR(0).eax & 0xE6) == 0xE6);
}
#endif

#if defined(OF_POWERPC) || defined(OF_POWERPC64)
+ (bool)supportsAltiVec
{
# if defined(OF_MACOS)

Modified src/OFTCPSocket.h from [522e53453c] to [f802834c92].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
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

#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 OFSetOptionFailedException The option could not be set
 * @throw OFGetOptionFailedException The option could not be gotten
 */
@property (nonatomic) bool sendsKeepAlives;
#endif

#ifndef OF_WII
/**
 * @brief Whether sending segments can be delayed. Setting this to `false` sets
 *        TCP_NODELAY on the socket.
 *
 * @warning This is not available on the Wii!
 *
 * @throw OFSetOptionFailedException The option could not be set
 * @throw OFGetOptionFailedException The option could not be gotten
 */
@property (nonatomic) bool canDelaySendingSegments;
#endif

/**
 * @brief The host to use as a SOCKS5 proxy.
 */







|
|











|
|







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

#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;
#endif

#ifndef OF_WII
/**
 * @brief Whether sending segments can be delayed. Setting this to `false` sets
 *        TCP_NODELAY on the socket.
 *
 * @warning This is not available on the Wii!
 *
 * @throw OFGetOptionFailedException The option could not be retrieved
 * @throw OFSetOptionFailedException The option could not be set
 */
@property (nonatomic) bool canDelaySendingSegments;
#endif

/**
 * @brief The host to use as a SOCKS5 proxy.
 */
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167

/**
 * @brief Connects the OFTCPSocket to the specified destination.
 *
 * @param host The host to connect to
 * @param port The port on the host to connect to
 * @throw OFConnectIPSocketFailedException Connecting failed
 * @throw OFAlreadyConnectedException The socket is already connected or bound
 */
- (void)connectToHost: (OFString *)host port: (uint16_t)port;

/**
 * @brief Asynchronously connects the OFTCPSocket to the specified destination.
 *
 * @param host The host to connect to







|







153
154
155
156
157
158
159
160
161
162
163
164
165
166
167

/**
 * @brief Connects the OFTCPSocket to the specified destination.
 *
 * @param host The host to connect to
 * @param port The port on the host to connect to
 * @throw OFConnectIPSocketFailedException Connecting failed
 * @throw OFAlreadyOpenException The socket is already connected or bound
 */
- (void)connectToHost: (OFString *)host port: (uint16_t)port;

/**
 * @brief Asynchronously connects the OFTCPSocket to the specified destination.
 *
 * @param host The host to connect to
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
/**
 * @brief Binds the socket to the specified host and port.
 *
 * @param host The host to bind to. Use `@"0.0.0.0"` for IPv4 or `@"::"` for
 *	       IPv6 to bind to all.
 * @param port The port to bind to. If the port is 0, an unused port will be
 *	       chosen, which can be obtained using the return value.
 * @return The port the socket was bound to
 * @throw OFBindIPSocketFailedException Binding failed
 * @throw OFAlreadyConnectedException The socket is already connected or bound
 */
- (uint16_t)bindToHost: (OFString *)host port: (uint16_t)port;
@end

OF_ASSUME_NONNULL_END







|

|

|



209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
/**
 * @brief Binds the socket to the specified host and port.
 *
 * @param host The host to bind to. Use `@"0.0.0.0"` for IPv4 or `@"::"` for
 *	       IPv6 to bind to all.
 * @param port The port to bind to. If the port is 0, an unused port will be
 *	       chosen, which can be obtained using the return value.
 * @return The address the socket was bound to
 * @throw OFBindIPSocketFailedException Binding failed
 * @throw OFAlreadyOpenException The socket is already connected or bound
 */
- (OFSocketAddress)bindToHost: (OFString *)host port: (uint16_t)port;
@end

OF_ASSUME_NONNULL_END

Modified src/OFTCPSocket.m from [bab73573da] to [763f8308b6].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#import "OFRunLoop+Private.h"
#import "OFSocket.h"
#import "OFSocket+Private.h"
#import "OFString.h"
#import "OFTCPSocketSOCKS5Connector.h"
#import "OFThread.h"

#import "OFAlreadyConnectedException.h"
#import "OFBindIPSocketFailedException.h"
#import "OFGetOptionFailedException.h"
#import "OFNotImplementedException.h"
#import "OFNotOpenException.h"
#import "OFSetOptionFailedException.h"

static const OFRunLoopMode connectRunLoopMode =







|







39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#import "OFRunLoop+Private.h"
#import "OFSocket.h"
#import "OFSocket+Private.h"
#import "OFString.h"
#import "OFTCPSocketSOCKS5Connector.h"
#import "OFThread.h"

#import "OFAlreadyOpenException.h"
#import "OFBindIPSocketFailedException.h"
#import "OFGetOptionFailedException.h"
#import "OFNotImplementedException.h"
#import "OFNotOpenException.h"
#import "OFSetOptionFailedException.h"

static const OFRunLoopMode connectRunLoopMode =
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
			    errNo: (int *)errNo
{
#if SOCK_CLOEXEC == 0 && defined(HAVE_FCNTL) && defined(FD_CLOEXEC)
	int flags;
#endif

	if (_socket != OFInvalidSocketHandle)
		@throw [OFAlreadyConnectedException exceptionWithSocket: self];

	if ((_socket = socket(
	    ((struct sockaddr *)&address->sockaddr)->sa_family,
	    SOCK_STREAM | SOCK_CLOEXEC, 0)) == OFInvalidSocketHandle) {
		*errNo = OFSocketErrNo();
		return false;
	}







|







137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
			    errNo: (int *)errNo
{
#if SOCK_CLOEXEC == 0 && defined(HAVE_FCNTL) && defined(FD_CLOEXEC)
	int flags;
#endif

	if (_socket != OFInvalidSocketHandle)
		@throw [OFAlreadyOpenException exceptionWithObject: self];

	if ((_socket = socket(
	    ((struct sockaddr *)&address->sockaddr)->sa_family,
	    SOCK_STREAM | SOCK_CLOEXEC, 0)) == OFInvalidSocketHandle) {
		*errNo = OFSocketErrNo();
		return false;
	}
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
			   block: (delegate == nil ? block : NULL)] autorelease]
	    startWithRunLoopMode: runLoopMode];

	objc_autoreleasePoolPop(pool);
}
#endif

- (uint16_t)bindToHost: (OFString *)host port: (uint16_t)port
{
	const int one = 1;
	void *pool = objc_autoreleasePoolPush();
	OFData *socketAddresses;
	OFSocketAddress address;
#if SOCK_CLOEXEC == 0 && defined(HAVE_FCNTL) && defined(FD_CLOEXEC)
	int flags;
#endif

	if (_socket != OFInvalidSocketHandle)
		@throw [OFAlreadyConnectedException exceptionWithSocket: self];

	if (_SOCKS5Host != nil)
		@throw [OFNotImplementedException exceptionWithSelector: _cmd
								 object: self];

	socketAddresses = [[OFThread DNSResolver]
	    resolveAddressesForHost: host







|










|







285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
			   block: (delegate == nil ? block : NULL)] autorelease]
	    startWithRunLoopMode: runLoopMode];

	objc_autoreleasePoolPop(pool);
}
#endif

- (OFSocketAddress)bindToHost: (OFString *)host port: (uint16_t)port
{
	const int one = 1;
	void *pool = objc_autoreleasePoolPush();
	OFData *socketAddresses;
	OFSocketAddress address;
#if SOCK_CLOEXEC == 0 && defined(HAVE_FCNTL) && defined(FD_CLOEXEC)
	int flags;
#endif

	if (_socket != OFInvalidSocketHandle)
		@throw [OFAlreadyOpenException exceptionWithObject: self];

	if (_SOCKS5Host != nil)
		@throw [OFNotImplementedException exceptionWithSelector: _cmd
								 object: self];

	socketAddresses = [[OFThread DNSResolver]
	    resolveAddressesForHost: host
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409

410
411
412

413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
			while (rnd < 1024)
				rnd = (uint16_t)rand();

			OFSocketAddressSetIPPort(&address, rnd);

			if ((ret = bind(_socket,
			    (struct sockaddr *)&address.sockaddr,
			    address.length)) == 0) {
				port = rnd;
				break;
			}

			if (OFSocketErrNo() != EADDRINUSE) {
				int errNo = OFSocketErrNo();

				closesocket(_socket);
				_socket = OFInvalidSocketHandle;

				@throw [OFBindIPSocketFailedException
				    exceptionWithHost: host
						 port: port
					       socket: self
						errNo: errNo];
			}
		}
	}
#endif

	objc_autoreleasePoolPop(pool);

	if (port > 0)
		return port;

#if !defined(OF_HPUX) && !defined(OF_WII) && !defined(OF_NINTENDO_3DS)
	memset(&address, 0, sizeof(address));

	address.length = (socklen_t)sizeof(address.sockaddr);
	if (OFGetSockName(_socket, (struct sockaddr *)&address.sockaddr,
	    &address.length) != 0) {
		int errNo = OFSocketErrNo();

		closesocket(_socket);
		_socket = OFInvalidSocketHandle;

		@throw [OFBindIPSocketFailedException exceptionWithHost: host
								   port: port
								 socket: self
								  errNo: errNo];
	}

	switch (((struct sockaddr *)&address.sockaddr)->sa_family) {
	case AF_INET:
		return OFFromBigEndian16(address.sockaddr.in.sin_port);

# ifdef OF_HAVE_IPV6
	case AF_INET6:
		return OFFromBigEndian16(address.sockaddr.in6.sin6_port);

# endif
	default:
		closesocket(_socket);
		_socket = OFInvalidSocketHandle;

		@throw [OFBindIPSocketFailedException
		    exceptionWithHost: host
				 port: port
			       socket: self
				errNo: EAFNOSUPPORT];
	}
#else
	closesocket(_socket);
	_socket = OFInvalidSocketHandle;
	@throw [OFBindIPSocketFailedException exceptionWithHost: host
							   port: port
							 socket: self
							  errNo: EADDRNOTAVAIL];
#endif
}

#if !defined(OF_WII) && !defined(OF_NINTENDO_3DS)
- (void)setSendsKeepAlives: (bool)sendsKeepAlives
{
	int v = sendsKeepAlives;








|
<

<

















<
<
<
<
<



















|
>


|
>











|
|
|
|
<
|
<
<







357
358
359
360
361
362
363
364

365

366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382





383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422

423


424
425
426
427
428
429
430
			while (rnd < 1024)
				rnd = (uint16_t)rand();

			OFSocketAddressSetIPPort(&address, rnd);

			if ((ret = bind(_socket,
			    (struct sockaddr *)&address.sockaddr,
			    address.length)) == 0)

				break;


			if (OFSocketErrNo() != EADDRINUSE) {
				int errNo = OFSocketErrNo();

				closesocket(_socket);
				_socket = OFInvalidSocketHandle;

				@throw [OFBindIPSocketFailedException
				    exceptionWithHost: host
						 port: port
					       socket: self
						errNo: errNo];
			}
		}
	}
#endif






#if !defined(OF_HPUX) && !defined(OF_WII) && !defined(OF_NINTENDO_3DS)
	memset(&address, 0, sizeof(address));

	address.length = (socklen_t)sizeof(address.sockaddr);
	if (OFGetSockName(_socket, (struct sockaddr *)&address.sockaddr,
	    &address.length) != 0) {
		int errNo = OFSocketErrNo();

		closesocket(_socket);
		_socket = OFInvalidSocketHandle;

		@throw [OFBindIPSocketFailedException exceptionWithHost: host
								   port: port
								 socket: self
								  errNo: errNo];
	}

	switch (((struct sockaddr *)&address.sockaddr)->sa_family) {
	case AF_INET:
		address.family = OFSocketAddressFamilyIPv4;
		break;
# ifdef OF_HAVE_IPV6
	case AF_INET6:
		address.family = OFSocketAddressFamilyIPv6;
		break;
# endif
	default:
		closesocket(_socket);
		_socket = OFInvalidSocketHandle;

		@throw [OFBindIPSocketFailedException
		    exceptionWithHost: host
				 port: port
			       socket: self
				errNo: EAFNOSUPPORT];
	}
#endif

	objc_autoreleasePoolPop(pool);


	return address;


}

#if !defined(OF_WII) && !defined(OF_NINTENDO_3DS)
- (void)setSendsKeepAlives: (bool)sendsKeepAlives
{
	int v = sendsKeepAlives;

Modified src/OFTCPSocketSOCKS5Connector.h from [a83f3eec6d] to [0d7afbd365].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFTCPSocketSOCKS5Connector.m from [f6cfb53e62] to [02f9b053ee].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the 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 <assert.h>
#include <errno.h>

#import "OFTCPSocketSOCKS5Connector.h"
#import "OFData.h"
#import "OFRunLoop.h"
#import "OFString.h"


|















<







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

18
19
20
21
22
23
24
/*
 * Copyright (c) 2008-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 <errno.h>

#import "OFTCPSocketSOCKS5Connector.h"
#import "OFData.h"
#import "OFRunLoop.h"
#import "OFString.h"

264
265
266
267
268
269
270
271
272
273
274
275
276
277
278

		_SOCKS5State = stateReadAddress;
		[_socket asyncReadIntoBuffer: _buffer
				 exactLength: addressLength[0] + 2
				 runLoopMode: runLoopMode];
		return false;
	default:
		assert(0);
		return false;
	}
}

- (OFData *)stream: (OFStream *)sock
      didWriteData: (OFData *)data
      bytesWritten: (size_t)bytesWritten







|







263
264
265
266
267
268
269
270
271
272
273
274
275
276
277

		_SOCKS5State = stateReadAddress;
		[_socket asyncReadIntoBuffer: _buffer
				 exactLength: addressLength[0] + 2
				 runLoopMode: runLoopMode];
		return false;
	default:
		OFAssert(0);
		return false;
	}
}

- (OFData *)stream: (OFStream *)sock
      didWriteData: (OFData *)data
      bytesWritten: (size_t)bytesWritten
301
302
303
304
305
306
307
308
309
310
311
312

		_SOCKS5State = stateReadResponse;
		[_socket asyncReadIntoBuffer: _buffer
				 exactLength: 4
				 runLoopMode: runLoopMode];
		return nil;
	default:
		assert(0);
		return nil;
	}
}
@end







|




300
301
302
303
304
305
306
307
308
309
310
311

		_SOCKS5State = stateReadResponse;
		[_socket asyncReadIntoBuffer: _buffer
				 exactLength: 4
				 runLoopMode: runLoopMode];
		return nil;
	default:
		OFAssert(0);
		return nil;
	}
}
@end

Modified src/OFTLSKey.h from [daee12b5cc] to [3e85dcff17].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFTLSKey.m from [e3604d121c] to [283c37f643].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFTLSStream.h from [8cbbbbbe33] to [57d0bfe49e].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
57
58
59
60
61
62
63
64

65
66
67
68

69
70
71
72
73
74
75
76
77
 *
 * @brief A class that provides Transport Layer Security on top of a stream.
 *
 * This class is a class cluster and returns a suitable OFTLSStream subclass,
 * if available.
 *
 * Subclasses need to override @ref lowlevelReadIntoBuffer:length:,
 * @ref lowlevelWriteBuffer:length: and

 * @ref asyncPerformClientHandshakeWithHost:runLoopMode:. The method
 * @ref hasDataInReadBuffer should be overridden to return `true` if the TLS
 * stream has cached unprocessed data internally, while returning
 * `self.underlyingStream.hasDataInReadBuffer` if it does not have any

 * unprocessed data. In order to get access to the underlying stream,
 * @ref underlyingStream can be used.
 */
@interface OFTLSStream: OFStream <OFReadyForReadingObserving,
    OFReadyForWritingObserving>
{
	OFStream <OFReadyForReadingObserving, OFReadyForWritingObserving>
	    *_underlyingStream;
	bool _verifiesCertificates;







|
>
|
<
<
<
>
|
|







57
58
59
60
61
62
63
64
65
66



67
68
69
70
71
72
73
74
75
76
 *
 * @brief A class that provides Transport Layer Security on top of a stream.
 *
 * This class is a class cluster and returns a suitable OFTLSStream subclass,
 * if available.
 *
 * Subclasses need to override @ref lowlevelReadIntoBuffer:length:,
 * @ref lowlevelWriteBuffer:length:,
 * @ref lowlevelHasDataInReadBuffer and
 * @ref asyncPerformClientHandshakeWithHost:runLoopMode:.



 *
 * In order to get access to the underlying stream, @ref underlyingStream can
 * be used.
 */
@interface OFTLSStream: OFStream <OFReadyForReadingObserving,
    OFReadyForWritingObserving>
{
	OFStream <OFReadyForReadingObserving, OFReadyForWritingObserving>
	    *_underlyingStream;
	bool _verifiesCertificates;
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
 *	  stream.
 *
 * @param stream The stream to use as underlying stream. Must not be closed
 *		 before the TLS stream is closed.
 * @return A new, autoreleased TLS stream
 */
+ (instancetype)streamWithStream: (OFStream <OFReadyForReadingObserving,
				       OFReadyForWritingObserving> *)stream;

/**
 * @brief Initializes the TLS stream with the specified stream as its
 *	  underlying stream.
 *



 * @param stream The stream to use as underlying stream. Must not be closed
 *		 before the TLS stream is closed.
 * @return An initialized TLS stream
 */
- (instancetype)initWithStream: (OFStream <OFReadyForReadingObserving,
				     OFReadyForWritingObserving> *)stream
    OF_DESIGNATED_INITIALIZER;

/**
 * @brief Asynchronously performs the TLS client handshake for the specified
 *	  host and calls the delegate afterwards.
 *
 * @param host The host to perform the handshake with
 * @throw OFTLSHandshakeFailedException The TLS handshake failed
 * @throw OFAlreadyConnectedException The handshake was already performed
 */
- (void)asyncPerformClientHandshakeWithHost: (OFString *)host;

/**
 * @brief Asynchronously performs the TLS client handshake for the specified
 *	  host and calls the delegate afterwards.
 *
 * @param host The host to perform the handshake with
 * @param runLoopMode The run loop mode in which to perform the async handshake
 * @throw OFTLSHandshakeFailedException The TLS handshake failed
 * @throw OFAlreadyConnectedException The handshake was already performed
 */
- (void)asyncPerformClientHandshakeWithHost: (OFString *)host
				runLoopMode: (OFRunLoopMode)runLoopMode;

/**
 * @brief Performs the TLS client handshake for the specified host.
 *
 * @param host The host to perform the handshake with
 * @throw OFTLSHandshakeFailedException The TLS handshake failed
 * @throw OFAlreadyConnectedException The handshake was already performed
 */
- (void)performClientHandshakeWithHost: (OFString *)host;
@end

#ifdef __cplusplus
extern "C" {
#endif







|





>
>
>





|








|










|









|







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
 *	  stream.
 *
 * @param stream The stream to use as underlying stream. Must not be closed
 *		 before the TLS stream is closed.
 * @return A new, autoreleased TLS stream
 */
+ (instancetype)streamWithStream: (OFStream <OFReadyForReadingObserving,
				      OFReadyForWritingObserving> *)stream;

/**
 * @brief Initializes the TLS stream with the specified stream as its
 *	  underlying stream.
 *
 * @note The delegate of the specified stream will be changed to the TLS
 *	 stream. You must not change this before the TLS session is completed.
 *
 * @param stream The stream to use as underlying stream. Must not be closed
 *		 before the TLS stream is closed.
 * @return An initialized TLS stream
 */
- (instancetype)initWithStream: (OFStream <OFReadyForReadingObserving,
				    OFReadyForWritingObserving> *)stream
    OF_DESIGNATED_INITIALIZER;

/**
 * @brief Asynchronously performs the TLS client handshake for the specified
 *	  host and calls the delegate afterwards.
 *
 * @param host The host to perform the handshake with
 * @throw OFTLSHandshakeFailedException The TLS handshake failed
 * @throw OFAlreadyOpenException The handshake was already performed
 */
- (void)asyncPerformClientHandshakeWithHost: (OFString *)host;

/**
 * @brief Asynchronously performs the TLS client handshake for the specified
 *	  host and calls the delegate afterwards.
 *
 * @param host The host to perform the handshake with
 * @param runLoopMode The run loop mode in which to perform the async handshake
 * @throw OFTLSHandshakeFailedException The TLS handshake failed
 * @throw OFAlreadyOpenException The handshake was already performed
 */
- (void)asyncPerformClientHandshakeWithHost: (OFString *)host
				runLoopMode: (OFRunLoopMode)runLoopMode;

/**
 * @brief Performs the TLS client handshake for the specified host.
 *
 * @param host The host to perform the handshake with
 * @throw OFTLSHandshakeFailedException The TLS handshake failed
 * @throw OFAlreadyOpenException The handshake was already performed
 */
- (void)performClientHandshakeWithHost: (OFString *)host;
@end

#ifdef __cplusplus
extern "C" {
#endif

Modified src/OFTLSStream.m from [01bd29e506] to [27008f3718].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
}

- (size_t)lowlevelWriteBuffer: (const void *)buffer length: (size_t)length
{
	OF_UNRECOGNIZED_SELECTOR
}

- (bool)hasDataInReadBuffer
{
	return (super.hasDataInReadBuffer ||
	    _underlyingStream.hasDataInReadBuffer);
}

- (bool)lowlevelIsAtEndOfStream
{
	return _underlyingStream.atEndOfStream;
}

- (int)fileDescriptorForReading
{







<
<
<
<
<
<







137
138
139
140
141
142
143






144
145
146
147
148
149
150
}

- (size_t)lowlevelWriteBuffer: (const void *)buffer length: (size_t)length
{
	OF_UNRECOGNIZED_SELECTOR
}







- (bool)lowlevelIsAtEndOfStream
{
	return _underlyingStream.atEndOfStream;
}

- (int)fileDescriptorForReading
{

Added src/OFTaggedPointerColor.h version [c0b24035ec].





















































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/*
 * 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 "OFColor.h"

OF_ASSUME_NONNULL_BEGIN

@interface OFTaggedPointerColor: OFColor
+ (OFTaggedPointerColor *)colorWithRed: (uint8_t)red
				 green: (uint8_t)green
				  blue: (uint8_t)blue;
@end

OF_ASSUME_NONNULL_END

Added src/OFTaggedPointerColor.m version [6d7598a07e].











































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
/*
 * Copyright (c) 2008-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 "OFTaggedPointerColor.h"

static int colorTag;

@implementation OFTaggedPointerColor
+ (void)initialize
{
	if (self == [OFTaggedPointerColor class])
		colorTag = objc_registerTaggedPointerClass(self);
}

+ (OFTaggedPointerColor *)colorWithRed: (uint8_t)red
				 green: (uint8_t)green
				  blue: (uint8_t)blue
{
	return objc_createTaggedPointer(colorTag,
	    (uintptr_t)red << 16 | (uintptr_t)green << 8 | (uintptr_t)blue);
}

- (void)getRed: (float *)red
	 green: (float *)green
	  blue: (float *)blue
	 alpha: (float *)alpha
{
	uintptr_t value = object_getTaggedPointerValue(self);

	*red = (float)(value >> 16) / 255;
	*green = (float)((value >> 8) & 0xFF) / 255;
	*blue = (float)(value & 0xFF) / 255;

	if (alpha != NULL)
		*alpha = 1;
}

OF_SINGLETON_METHODS
@end

Added src/OFTaggedPointerDate.h version [0bb3e598cc].





















































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/*
 * 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 "OFDate.h"

OF_ASSUME_NONNULL_BEGIN

#if UINTPTR_MAX == UINT64_MAX
@interface OFTaggedPointerDate: OFDate
+ (OFTaggedPointerDate *)dateWithUInt64TimeIntervalSince1970: (uint64_t)value;
@end
#endif

OF_ASSUME_NONNULL_END

Added src/OFTaggedPointerDate.m version [db376cecc3].



























































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
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.
 */

#import "OFTaggedPointerDate.h"

#if UINTPTR_MAX == UINT64_MAX
static int dateTag;

@implementation OFTaggedPointerDate
+ (void)initialize
{
	if (self == [OFTaggedPointerDate class])
		dateTag = objc_registerTaggedPointerClass(self);
}

+ (OFTaggedPointerDate *)dateWithUInt64TimeIntervalSince1970: (uint64_t)value
{
	return objc_createTaggedPointer(dateTag, value & ~(UINT64_C(4) << 60));
}

- (OFTimeInterval)timeIntervalSince1970
{
	uint64_t value = (uint64_t)object_getTaggedPointerValue(self);

	value |= UINT64_C(4) << 60;

	return OFFromBigEndianDouble(OFRawUInt64ToDouble(OFToBigEndian64(
	    value)));
}

OF_SINGLETON_METHODS
@end
#endif

Added src/OFTaggedPointerNumber.h version [336b68721d].



















































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
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 "OFNumber.h"

OF_ASSUME_NONNULL_BEGIN

#define OFTaggedPointerNumberTagBits 4

@interface OFTaggedPointerNumber: OFNumber
@end

OF_ASSUME_NONNULL_END

Added src/OFTaggedPointerNumber.m version [fbe5f46d8b].













































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
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
/*
 * 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 "OFTaggedPointerNumber.h"

#import "OFInvalidFormatException.h"

enum Tag {
	tagChar,
	tagShort,
	tagInt,
	tagLong,
	tagLongLong,
	tagUnsignedChar,
	tagUnsignedShort,
	tagUnsignedInt,
	tagUnsignedLong,
	tagUnsignedLongLong,
};
static const uintptr_t tagMask = (1 << OFTaggedPointerNumberTagBits) - 1;
static int numberTag;

@implementation OFTaggedPointerNumber
+ (void)initialize
{
	if (self == [OFTaggedPointerNumber class])
		numberTag = objc_registerTaggedPointerClass(self);
}

+ (OFTaggedPointerNumber *)numberWithChar: (signed char)value
{
	return objc_createTaggedPointer(numberTag,
	    ((uintptr_t)(unsigned char)value << OFTaggedPointerNumberTagBits) |
	    tagChar);
}

+ (OFTaggedPointerNumber *)numberWithShort: (short)value
{
	return objc_createTaggedPointer(numberTag,
	    ((uintptr_t)(unsigned short)value << OFTaggedPointerNumberTagBits) |
	    tagShort);
}

+ (OFTaggedPointerNumber *)numberWithInt: (int)value
{
	return objc_createTaggedPointer(numberTag,
	    ((uintptr_t)(unsigned int)value << OFTaggedPointerNumberTagBits) |
	    tagInt);
}

+ (OFTaggedPointerNumber *)numberWithLong: (long)value
{
	return objc_createTaggedPointer(numberTag,
	    ((uintptr_t)(unsigned long)value << OFTaggedPointerNumberTagBits) |
	    tagLong);
}

+ (OFTaggedPointerNumber *)numberWithLongLong: (long long)value
{
	return objc_createTaggedPointer(numberTag,
	    ((uintptr_t)(unsigned long long)value <<
	    OFTaggedPointerNumberTagBits) | tagLongLong);
}

+ (OFTaggedPointerNumber *)numberWithUnsignedChar: (unsigned char)value
{
	return objc_createTaggedPointer(numberTag,
	    ((uintptr_t)value << OFTaggedPointerNumberTagBits) |
	    tagUnsignedChar);
}

+ (OFTaggedPointerNumber *)numberWithUnsignedShort: (unsigned short)value
{
	return objc_createTaggedPointer(numberTag,
	    ((uintptr_t)value << OFTaggedPointerNumberTagBits) |
	    tagUnsignedShort);
}

+ (OFTaggedPointerNumber *)numberWithUnsignedInt: (unsigned int)value
{
	return objc_createTaggedPointer(numberTag,
	    ((uintptr_t)value << OFTaggedPointerNumberTagBits) |
	    tagUnsignedInt);
}

+ (OFTaggedPointerNumber *)numberWithUnsignedLong: (unsigned long)value
{
	return objc_createTaggedPointer(numberTag,
	    ((uintptr_t)value << OFTaggedPointerNumberTagBits) |
	    tagUnsignedLong);
}

+ (OFTaggedPointerNumber *)numberWithUnsignedLongLong: (unsigned long long)value
{
	return objc_createTaggedPointer(numberTag,
	    ((uintptr_t)value << OFTaggedPointerNumberTagBits) |
	    tagUnsignedLongLong);
}

- (const char *)objCType
{
	uintptr_t value = object_getTaggedPointerValue(self);

	switch (value & tagMask) {
	case tagChar:
		return @encode(signed char);
	case tagShort:
		return @encode(short);
	case tagInt:
		return @encode(int);
	case tagLong:
		return @encode(long);
	case tagLongLong:
		return @encode(long long);
	case tagUnsignedChar:
		return @encode(unsigned char);
	case tagUnsignedShort:
		return @encode(unsigned short);
	case tagUnsignedInt:
		return @encode(unsigned int);
	case tagUnsignedLong:
		return @encode(unsigned long);
	case tagUnsignedLongLong:
		return @encode(unsigned long long);
	default:
		@throw [OFInvalidFormatException exception];
	}
}

#define RETURN_VALUE						\
	uintptr_t value = object_getTaggedPointerValue(self);	\
								\
	switch (value & tagMask) {				\
	case tagChar:						\
		return (signed char)(unsigned char)		\
		    (value >> OFTaggedPointerNumberTagBits);	\
	case tagShort:						\
		return (short)(unsigned short)			\
		    (value >> OFTaggedPointerNumberTagBits);	\
	case tagInt:						\
		return (int)(unsigned int)			\
		    (value >> OFTaggedPointerNumberTagBits);	\
	case tagLong:						\
		return (long)(unsigned long)			\
		    (value >> OFTaggedPointerNumberTagBits);	\
	case tagLongLong:					\
		return (long long)(unsigned long long)		\
		    (value >> OFTaggedPointerNumberTagBits);	\
	case tagUnsignedChar:					\
		return (unsigned char)				\
		    (value >> OFTaggedPointerNumberTagBits);	\
	case tagUnsignedShort:					\
		return (unsigned short)				\
		    (value >> OFTaggedPointerNumberTagBits);	\
	case tagUnsignedInt:					\
		return (unsigned int)				\
		    (value >> OFTaggedPointerNumberTagBits);	\
	case tagUnsignedLong:					\
		return (unsigned long)				\
		    (value >> OFTaggedPointerNumberTagBits);	\
	case tagUnsignedLongLong:				\
		return (unsigned long long)			\
		    (value >> OFTaggedPointerNumberTagBits);	\
	default:						\
		@throw [OFInvalidFormatException exception];	\
	}
- (long long)longLongValue
{
	RETURN_VALUE
}

- (unsigned long long)unsignedLongLongValue
{
	RETURN_VALUE
}

- (double)doubleValue
{
	RETURN_VALUE
}
#undef RETURN_VALUE

OF_SINGLETON_METHODS
@end

Modified src/OFTarArchive.h from [7f3061b033] to [f37cab3a6f].

1
2
3
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
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#import "OFObject.h"
#import "OFKernelEventObserver.h"
#import "OFString.h"
#import "OFTarArchiveEntry.h"

OF_ASSUME_NONNULL_BEGIN

@class OFStream;
@class OFURI;

/**
 * @class OFTarArchive OFTarArchive.h ObjFW/OFTarArchive.h
 *
 * @brief A class for accessing and manipulating tar archives.
 */
OF_SUBCLASSING_RESTRICTED
@interface OFTarArchive: OFObject
{
	OFStream *_stream;
	enum OFTarArchiveMode {
		OFTarArchiveModeRead,
		OFTarArchiveModeWrite,
		OFTarArchiveModeAppend
	} _mode;
	OFStringEncoding _encoding;
	OFTarArchiveEntry *_Nullable _currentEntry;
#ifdef OF_TAR_ARCHIVE_M
@public
#endif
	OFStream *_Nullable _lastReturnedStream;
}

|




















|
|










<
<
<
<
|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34




35
36
37
38
39
40
41
42
/*
 * Copyright (c) 2008-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 "OFObject.h"
#import "OFKernelEventObserver.h"
#import "OFString.h"
#import "OFTarArchiveEntry.h"

OF_ASSUME_NONNULL_BEGIN

@class OFIRI;
@class OFStream;

/**
 * @class OFTarArchive OFTarArchive.h ObjFW/OFTarArchive.h
 *
 * @brief A class for accessing and manipulating tar archives.
 */
OF_SUBCLASSING_RESTRICTED
@interface OFTarArchive: OFObject
{
	OFStream *_stream;




	uint_least8_t _mode;
	OFStringEncoding _encoding;
	OFTarArchiveEntry *_Nullable _currentEntry;
#ifdef OF_TAR_ARCHIVE_M
@public
#endif
	OFStream *_Nullable _lastReturnedStream;
}
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
 *				failed
 */
+ (instancetype)archiveWithStream: (OFStream *)stream mode: (OFString *)mode;

/**
 * @brief Creates a new OFTarArchive object with the specified file.
 *
 * @param URI The URI to the tar archive
 * @param mode The mode for the tar file. Valid modes are "r" for reading,
 *	       "w" for creating a new file and "a" for appending to an existing
 *	       archive.
 * @return A new, autoreleased OFTarArchive
 * @throw OFInvalidFormatException The archive has an invalid format
 * @throw OFSeekFailedException The archive was open in append mode and seeking
 *				failed
 */
+ (instancetype)archiveWithURI: (OFURI *)URI mode: (OFString *)mode;

/**
 * @brief Creates a URI for accessing a the specified file within the specified
 *	  tar archive.
 *
 * @param path The path of the file within the archive
 * @param URI The URI of the archive
 * @return A URI for accessing the specified file within the specified tar
 *	   archive
 */
+ (OFURI *)URIForFilePath: (OFString *)path inArchiveWithURI: (OFURI *)URI;

- (instancetype)init OF_UNAVAILABLE;

/**
 * @brief Initializes an already allocated OFTarArchive object with the
 *	  specified stream.
 *







|








|


|
|


|
|


|







60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
 *				failed
 */
+ (instancetype)archiveWithStream: (OFStream *)stream mode: (OFString *)mode;

/**
 * @brief Creates a new OFTarArchive object with the specified file.
 *
 * @param IRI The IRI to the tar archive
 * @param mode The mode for the tar file. Valid modes are "r" for reading,
 *	       "w" for creating a new file and "a" for appending to an existing
 *	       archive.
 * @return A new, autoreleased OFTarArchive
 * @throw OFInvalidFormatException The archive has an invalid format
 * @throw OFSeekFailedException The archive was open in append mode and seeking
 *				failed
 */
+ (instancetype)archiveWithIRI: (OFIRI *)IRI mode: (OFString *)mode;

/**
 * @brief Creates an IRI for accessing a the specified file within the
 *	  specified tar archive.
 *
 * @param path The path of the file within the archive
 * @param IRI The IRI of the archive
 * @return An IRI for accessing the specified file within the specified tar
 *	   archive
 */
+ (OFIRI *)IRIForFilePath: (OFString *)path inArchiveWithIRI: (OFIRI *)IRI;

- (instancetype)init OF_UNAVAILABLE;

/**
 * @brief Initializes an already allocated OFTarArchive object with the
 *	  specified stream.
 *
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
- (instancetype)initWithStream: (OFStream *)stream
			  mode: (OFString *)mode OF_DESIGNATED_INITIALIZER;

/**
 * @brief Initializes an already allocated OFTarArchive object with the
 *	  specified file.
 *
 * @param URI The URI to the tar archive
 * @param mode The mode for the tar file. Valid modes are "r" for reading,
 *	       "w" for creating a new file and "a" for appending to an existing
 *	       archive.
 * @return An initialized OFTarArchive
 * @throw OFInvalidFormatException The archive has an invalid format
 * @throw OFSeekFailedException The archive was open in append mode and seeking
 *				failed
 */
- (instancetype)initWithURI: (OFURI *)URI mode: (OFString *)mode;

/**
 * @brief Returns the next entry from the tar archive or `nil` if all entries
 *	  have been read.
 *
 * @note This is only available in read mode.
 *







|








|







105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
- (instancetype)initWithStream: (OFStream *)stream
			  mode: (OFString *)mode OF_DESIGNATED_INITIALIZER;

/**
 * @brief Initializes an already allocated OFTarArchive object with the
 *	  specified file.
 *
 * @param IRI The IRI to the tar archive
 * @param mode The mode for the tar file. Valid modes are "r" for reading,
 *	       "w" for creating a new file and "a" for appending to an existing
 *	       archive.
 * @return An initialized OFTarArchive
 * @throw OFInvalidFormatException The archive has an invalid format
 * @throw OFSeekFailedException The archive was open in append mode and seeking
 *				failed
 */
- (instancetype)initWithIRI: (OFIRI *)IRI mode: (OFString *)mode;

/**
 * @brief Returns the next entry from the tar archive or `nil` if all entries
 *	  have been read.
 *
 * @note This is only available in read mode.
 *

Modified src/OFTarArchive.m from [8086f04e85] to [bbedb2f448].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
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 "OFTarArchive.h"
#import "OFTarArchiveEntry.h"
#import "OFTarArchiveEntry+Private.h"
#import "OFArchiveURIHandler.h"
#import "OFDate.h"
#import "OFSeekableStream.h"
#import "OFStream.h"
#import "OFURI.h"
#import "OFURIHandler.h"

#import "OFInvalidArgumentException.h"
#import "OFInvalidFormatException.h"
#import "OFNotOpenException.h"
#import "OFOutOfRangeException.h"
#import "OFTruncatedDataException.h"
#import "OFWriteFailedException.h"







OF_DIRECT_MEMBERS
@interface OFTarArchiveFileReadStream: OFStream <OFReadyForReadingObserving>
{
	OFTarArchive *_archive;
	OFTarArchiveEntry *_entry;
	OFStream *_stream;







|

|
|
|
|







>
>
>
>
>
>







18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#include "config.h"

#include <errno.h>

#import "OFTarArchive.h"
#import "OFTarArchiveEntry.h"
#import "OFTarArchiveEntry+Private.h"
#import "OFArchiveIRIHandler.h"
#import "OFDate.h"
#import "OFIRI.h"
#import "OFIRIHandler.h"
#import "OFSeekableStream.h"
#import "OFStream.h"

#import "OFInvalidArgumentException.h"
#import "OFInvalidFormatException.h"
#import "OFNotOpenException.h"
#import "OFOutOfRangeException.h"
#import "OFTruncatedDataException.h"
#import "OFWriteFailedException.h"

enum {
	modeRead,
	modeWrite,
	modeAppend
};

OF_DIRECT_MEMBERS
@interface OFTarArchiveFileReadStream: OFStream <OFReadyForReadingObserving>
{
	OFTarArchive *_archive;
	OFTarArchiveEntry *_entry;
	OFStream *_stream;
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
@synthesize encoding = _encoding;

+ (instancetype)archiveWithStream: (OFStream *)stream mode: (OFString *)mode
{
	return [[[self alloc] initWithStream: stream mode: mode] autorelease];
}

+ (instancetype)archiveWithURI: (OFURI *)URI mode: (OFString *)mode
{
	return [[[self alloc] initWithURI: URI mode: mode] autorelease];
}

+ (OFURI *)URIForFilePath: (OFString *)path inArchiveWithURI: (OFURI *)URI
{
	return OFArchiveURIHandlerURIForFileInArchive(@"tar", path, URI);
}

- (instancetype)init
{
	OF_INVALID_INIT_METHOD
}

- (instancetype)initWithStream: (OFStream *)stream mode: (OFString *)mode
{
	self = [super init];

	@try {
		_stream = [stream retain];

		if ([mode isEqual: @"r"])
			_mode = OFTarArchiveModeRead;
		else if ([mode isEqual: @"w"])
			_mode = OFTarArchiveModeWrite;
		else if ([mode isEqual: @"a"])
			_mode = OFTarArchiveModeAppend;
		else
			@throw [OFInvalidArgumentException exception];

		if (_mode == OFTarArchiveModeAppend) {
			uint32_t buffer[1024 / sizeof(uint32_t)];
			bool empty = true;

			if (![_stream isKindOfClass: [OFSeekableStream class]])
				@throw [OFInvalidArgumentException exception];

			[(OFSeekableStream *)_stream seekToOffset: -1024







|

|


|

|















|

|

|



|







76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
@synthesize encoding = _encoding;

+ (instancetype)archiveWithStream: (OFStream *)stream mode: (OFString *)mode
{
	return [[[self alloc] initWithStream: stream mode: mode] autorelease];
}

+ (instancetype)archiveWithIRI: (OFIRI *)IRI mode: (OFString *)mode
{
	return [[[self alloc] initWithIRI: IRI mode: mode] autorelease];
}

+ (OFIRI *)IRIForFilePath: (OFString *)path inArchiveWithIRI: (OFIRI *)IRI
{
	return OFArchiveIRIHandlerIRIForFileInArchive(@"tar", path, IRI);
}

- (instancetype)init
{
	OF_INVALID_INIT_METHOD
}

- (instancetype)initWithStream: (OFStream *)stream mode: (OFString *)mode
{
	self = [super init];

	@try {
		_stream = [stream retain];

		if ([mode isEqual: @"r"])
			_mode = modeRead;
		else if ([mode isEqual: @"w"])
			_mode = modeWrite;
		else if ([mode isEqual: @"a"])
			_mode = modeAppend;
		else
			@throw [OFInvalidArgumentException exception];

		if (_mode == modeAppend) {
			uint32_t buffer[1024 / sizeof(uint32_t)];
			bool empty = true;

			if (![_stream isKindOfClass: [OFSeekableStream class]])
				@throw [OFInvalidArgumentException exception];

			[(OFSeekableStream *)_stream seekToOffset: -1024
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
		[self release];
		@throw e;
	}

	return self;
}

- (instancetype)initWithURI: (OFURI *)URI mode: (OFString *)mode
{
	void *pool = objc_autoreleasePoolPush();
	OFStream *stream;

	@try {
		if ([mode isEqual: @"a"])
			stream = [OFURIHandler openItemAtURI: URI mode: @"r+"];
		else
			stream = [OFURIHandler openItemAtURI: URI mode: mode];
	} @catch (id e) {
		[self release];
		@throw e;
	}

	self = [self initWithStream: stream mode: mode];








|






|

|







138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
		[self release];
		@throw e;
	}

	return self;
}

- (instancetype)initWithIRI: (OFIRI *)IRI mode: (OFString *)mode
{
	void *pool = objc_autoreleasePoolPush();
	OFStream *stream;

	@try {
		if ([mode isEqual: @"a"])
			stream = [OFIRIHandler openItemAtIRI: IRI mode: @"r+"];
		else
			stream = [OFIRIHandler openItemAtIRI: IRI mode: mode];
	} @catch (id e) {
		[self release];
		@throw e;
	}

	self = [self initWithStream: stream mode: mode];

168
169
170
171
172
173
174
175
176













177
178
179
180
181
182
183
}

- (OFTarArchiveEntry *)nextEntry
{
	uint32_t buffer[512 / sizeof(uint32_t)];
	bool empty = true;

	if (_mode != OFTarArchiveModeRead)
		@throw [OFInvalidArgumentException exception];














	[_currentEntry release];
	_currentEntry = nil;

	[(OFTarArchiveFileReadStream *)_lastReturnedStream of_skip];
	@try {
		[_lastReturnedStream close];







|

>
>
>
>
>
>
>
>
>
>
>
>
>







174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
}

- (OFTarArchiveEntry *)nextEntry
{
	uint32_t buffer[512 / sizeof(uint32_t)];
	bool empty = true;

	if (_mode != modeRead)
		@throw [OFInvalidArgumentException exception];

	if (_currentEntry != nil && _lastReturnedStream == nil) {
		/*
		 * No read stream was created since the last call to
		 * -[nextEntry]. Create it so that we can properly skip the
		 *  data.
		 */
		void *pool = objc_autoreleasePoolPush();

		[self streamForReadingCurrentEntry];

		objc_autoreleasePoolPop(pool);
	}

	[_currentEntry release];
	_currentEntry = nil;

	[(OFTarArchiveFileReadStream *)_lastReturnedStream of_skip];
	@try {
		[_lastReturnedStream close];
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
		     encoding: _encoding];

	return _currentEntry;
}

- (OFStream *)streamForReadingCurrentEntry
{
	if (_mode != OFTarArchiveModeRead)
		@throw [OFInvalidArgumentException exception];

	if (_currentEntry == nil)
		@throw [OFInvalidArgumentException exception];

	_lastReturnedStream = [[[OFTarArchiveFileReadStream alloc]
	    of_initWithArchive: self
			stream: _stream
			 entry: _currentEntry] autorelease];
	[_currentEntry release];
	_currentEntry = nil;

	return _lastReturnedStream;
}

- (OFStream *)streamForWritingEntry: (OFTarArchiveEntry *)entry
{
	if (_mode != OFTarArchiveModeWrite && _mode != OFTarArchiveModeAppend)
		@throw [OFInvalidArgumentException exception];

	@try {
		[_lastReturnedStream close];
	} @catch (OFNotOpenException *e) {
		/* Might have already been closed by the user - that's fine. */
	}







|

















|







229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
		     encoding: _encoding];

	return _currentEntry;
}

- (OFStream *)streamForReadingCurrentEntry
{
	if (_mode != modeRead)
		@throw [OFInvalidArgumentException exception];

	if (_currentEntry == nil)
		@throw [OFInvalidArgumentException exception];

	_lastReturnedStream = [[[OFTarArchiveFileReadStream alloc]
	    of_initWithArchive: self
			stream: _stream
			 entry: _currentEntry] autorelease];
	[_currentEntry release];
	_currentEntry = nil;

	return _lastReturnedStream;
}

- (OFStream *)streamForWritingEntry: (OFTarArchiveEntry *)entry
{
	if (_mode != modeWrite && _mode != modeAppend)
		@throw [OFInvalidArgumentException exception];

	@try {
		[_lastReturnedStream close];
	} @catch (OFNotOpenException *e) {
		/* Might have already been closed by the user - that's fine. */
	}
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
	@try {
		[_lastReturnedStream close];
	} @catch (OFNotOpenException *e) {
		/* Might have already been closed by the user - that's fine. */
	}
	_lastReturnedStream = nil;

	if (_mode == OFTarArchiveModeWrite || _mode == OFTarArchiveModeAppend) {
		char buffer[1024];
		memset(buffer, '\0', 1024);
		[_stream writeBuffer: buffer length: 1024];
	}

	[_stream release];
	_stream = nil;







|







279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
	@try {
		[_lastReturnedStream close];
	} @catch (OFNotOpenException *e) {
		/* Might have already been closed by the user - that's fine. */
	}
	_lastReturnedStream = nil;

	if (_mode == modeWrite || _mode == modeAppend) {
		char buffer[1024];
		memset(buffer, '\0', 1024);
		[_stream writeBuffer: buffer length: 1024];
	}

	[_stream release];
	_stream = nil;
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
{
	if (_stream == nil)
		@throw [OFNotOpenException exceptionWithObject: self];

	return _atEndOfStream;
}

- (bool)hasDataInReadBuffer
{
	return (super.hasDataInReadBuffer || _stream.hasDataInReadBuffer);
}

- (int)fileDescriptorForReading
{
	return ((id <OFReadyForReadingObserving>)_stream)
	    .fileDescriptorForReading;
}







|

|







358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
{
	if (_stream == nil)
		@throw [OFNotOpenException exceptionWithObject: self];

	return _atEndOfStream;
}

- (bool)lowlevelHasDataInReadBuffer
{
	return _stream.hasDataInReadBuffer;
}

- (int)fileDescriptorForReading
{
	return ((id <OFReadyForReadingObserving>)_stream)
	    .fileDescriptorForReading;
}

Modified src/OFTarArchiveEntry+Private.h from [d7e9114597] to [5be06bc20a].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFTarArchiveEntry.h from [a18b395a59] to [abcddd0481].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFTarArchiveEntry.m from [6add4508d8] to [799d611075].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFThread+Private.h from [b87af72459] to [d8525a6662].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFThread.h from [b1484db738] to [99dddf0f6e].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFThread.m from [3012eaab1d] to [2a7fa371d3].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
28
29
30
31
32
33
34

35
36

37
38
39
40
41
42
43
# include <sched.h>
#endif
#include "unistd_wrapper.h"

#include "platform.h"

#ifdef OF_AMIGAOS

# include <proto/exec.h>
# include <proto/dos.h>

#endif

#ifdef OF_WII
# define nanosleep ogc_nanosleep
# include <ogcsys.h>
# undef nanosleep
#endif







>


>







28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# include <sched.h>
#endif
#include "unistd_wrapper.h"

#include "platform.h"

#ifdef OF_AMIGAOS
# define Class IntuitionClass
# include <proto/exec.h>
# include <proto/dos.h>
# undef Class
#endif

#ifdef OF_WII
# define nanosleep ogc_nanosleep
# include <ogcsys.h>
# undef nanosleep
#endif

Modified src/OFTimer+Private.h from [37a8d06411] to [935ebe136a].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
17
18
19
20
21
22
23

24
25
26

OF_ASSUME_NONNULL_BEGIN

OF_DIRECT_MEMBERS
@interface OFTimer ()
- (void)of_setInRunLoop: (nullable OFRunLoop *)runLoop
		   mode: (nullable OFRunLoopMode)mode;

@end

OF_ASSUME_NONNULL_END







>



17
18
19
20
21
22
23
24
25
26
27

OF_ASSUME_NONNULL_BEGIN

OF_DIRECT_MEMBERS
@interface OFTimer ()
- (void)of_setInRunLoop: (nullable OFRunLoop *)runLoop
		   mode: (nullable OFRunLoopMode)mode;
- (void)of_reschedule;
@end

OF_ASSUME_NONNULL_END

Modified src/OFTimer.h from [bedc280158] to [b61037410d].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
458
459
460
461
462
463
464
465
466


467
468
469
470
471
472
473
 *
 * @param timer The timer to compare the string to
 * @return The result of the comparison
 */
- (OFComparisonResult)compare: (OFTimer *)timer;

/**
 * @brief Fires the timer, meaning it will execute the specified selector on the
 *	  target.


 */
- (void)fire;

/**
 * @brief Invalidates the timer, preventing it from firing.
 */
- (void)invalidate;







|
<
>
>







458
459
460
461
462
463
464
465

466
467
468
469
470
471
472
473
474
 *
 * @param timer The timer to compare the string to
 * @return The result of the comparison
 */
- (OFComparisonResult)compare: (OFTimer *)timer;

/**
 * @brief Fires the timer without changing its regular schedule.

 *
 * A non-repeating timer will be invalidated after firing.
 */
- (void)fire;

/**
 * @brief Invalidates the timer, preventing it from firing.
 */
- (void)invalidate;

Modified src/OFTimer.m from [6b846b58a6] to [51c5bb3274].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#include <stdlib.h>

#include <assert.h>

#import "OFTimer.h"
#import "OFTimer+Private.h"
#import "OFDate.h"
#import "OFRunLoop.h"
#import "OFRunLoop+Private.h"
#ifdef OF_HAVE_THREADS
# import "OFCondition.h"

|

















<
<







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19


20
21
22
23
24
25
26
/*
 * 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 <stdlib.h>



#import "OFTimer.h"
#import "OFTimer+Private.h"
#import "OFDate.h"
#import "OFRunLoop.h"
#import "OFRunLoop+Private.h"
#ifdef OF_HAVE_THREADS
# import "OFCondition.h"
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498

- (void)dealloc
{
	/*
	 * The run loop references the timer, so it should never be deallocated
	 * if it is still in a run loop.
	 */
	assert(_inRunLoop == nil);
	assert(_inRunLoopMode == nil);

	[_fireDate release];
	[_target release];
	[_object1 release];
	[_object2 release];
	[_object3 release];
	[_object4 release];







|
|







481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496

- (void)dealloc
{
	/*
	 * The run loop references the timer, so it should never be deallocated
	 * if it is still in a run loop.
	 */
	OFAssert(_inRunLoop == nil);
	OFAssert(_inRunLoopMode == nil);

	[_fireDate release];
	[_target release];
	[_object1 release];
	[_object2 release];
	[_object3 release];
	[_object4 release];
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

	_inRunLoop = [runLoop retain];
	[oldInRunLoop release];

	_inRunLoopMode = [mode copy];
	[oldInRunLoopMode release];
}

- (void)fire
{
	void *pool = objc_autoreleasePoolPush();
	id target = [[_target retain] autorelease];
	id object1 = [[_object1 retain] autorelease];
	id object2 = [[_object2 retain] autorelease];
	id object3 = [[_object3 retain] autorelease];
	id object4 = [[_object4 retain] autorelease];

	OFEnsure(_arguments <= 4);


	if (_repeats && _valid) {
		int64_t missedIntervals =
		    -_fireDate.timeIntervalSinceNow / _interval;
		OFTimeInterval newFireDate;
		OFRunLoop *runLoop;

		/* In case the clock was changed backwards */
		if (missedIntervals < 0)
			missedIntervals = 0;

		newFireDate = _fireDate.timeIntervalSince1970 +
		    (missedIntervals + 1) * _interval;

		[_fireDate release];

		_fireDate = [[OFDate alloc]
		    initWithTimeIntervalSince1970: newFireDate];

		runLoop = [OFRunLoop currentRunLoop];
		[runLoop addTimer: self forMode: runLoop.currentMode];

	} else



		[self invalidate];



#ifdef OF_HAVE_BLOCKS
	if (_block != NULL)
		_block(self);
	else {
#endif
		switch (_arguments) {
		case 0:
			[target performSelector: _selector];
			break;
		case 1:
			[target performSelector: _selector withObject: object1];

			break;
		case 2:
			[target performSelector: _selector
				     withObject: object1
				     withObject: object2];
			break;
		case 3:
			[target performSelector: _selector
				     withObject: object1
				     withObject: object2
				     withObject: object3];
			break;
		case 4:
			[target performSelector: _selector
				     withObject: object1
				     withObject: object2
				     withObject: object3
				     withObject: object4];
			break;
		}
#ifdef OF_HAVE_BLOCKS
	}
#endif




#ifdef OF_HAVE_THREADS
	[_condition lock];
	@try {
		_done = true;
		[_condition signal];
	} @finally {
		[_condition unlock];
	}
#endif

	objc_autoreleasePoolPop(pool);
}

- (OFDate *)fireDate
{
	return _fireDate;
}









|

|
|
|
<
<
<

|
>

<
<
|
<
<

|
|
|

|
|

|
>
|
|

|
|
>
|
>
>
>
|
>
>








|


|
>


|
|
|


|
|
|
|


|
|
|
|
|






>
>
>









<
<







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

	_inRunLoop = [runLoop retain];
	[oldInRunLoop release];

	_inRunLoopMode = [mode copy];
	[oldInRunLoopMode release];
}

- (void)of_reschedule
{
	long long missedIntervals;
	OFTimeInterval newFireDate;
	OFRunLoop *runLoop;




	if (!_repeats || !_valid)
		return;



	missedIntervals = -_fireDate.timeIntervalSinceNow / _interval;



	/* In case the clock was changed backwards */
	if (missedIntervals < 0)
		missedIntervals = 0;

	newFireDate = _fireDate.timeIntervalSince1970 +
	    (missedIntervals + 1) * _interval;

	[_fireDate release];
	_fireDate = nil;
	_fireDate = [[OFDate alloc]
	    initWithTimeIntervalSince1970: newFireDate];

	runLoop = [OFRunLoop currentRunLoop];
	[runLoop addTimer: self forMode: runLoop.currentMode];
}

- (void)fire
{
	OFEnsure(_arguments <= 4);

	if (!_valid)
		return;

#ifdef OF_HAVE_BLOCKS
	if (_block != NULL)
		_block(self);
	else {
#endif
		switch (_arguments) {
		case 0:
			[_target performSelector: _selector];
			break;
		case 1:
			[_target performSelector: _selector
				      withObject: _object1];
			break;
		case 2:
			[_target performSelector: _selector
				      withObject: _object1
				      withObject: _object2];
			break;
		case 3:
			[_target performSelector: _selector
				      withObject: _object1
				      withObject: _object2
				      withObject: _object3];
			break;
		case 4:
			[_target performSelector: _selector
				      withObject: _object1
				      withObject: _object2
				      withObject: _object3
				      withObject: _object4];
			break;
		}
#ifdef OF_HAVE_BLOCKS
	}
#endif

	if  (!_repeats)
		[self invalidate];

#ifdef OF_HAVE_THREADS
	[_condition lock];
	@try {
		_done = true;
		[_condition signal];
	} @finally {
		[_condition unlock];
	}
#endif


}

- (OFDate *)fireDate
{
	return _fireDate;
}

633
634
635
636
637
638
639



640
641
642
643
644
645
646
	}
}

- (void)invalidate
{
	_valid = false;




	[_target release];
	[_object1 release];
	[_object2 release];
	[_object3 release];
	[_object4 release];

	_target = nil;







>
>
>







634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
	}
}

- (void)invalidate
{
	_valid = false;

#ifdef OF_HAVE_BLOCKS
	[_block release];
#endif
	[_target release];
	[_object1 release];
	[_object2 release];
	[_object3 release];
	[_object4 release];

	_target = nil;

Modified src/OFTriple.h from [190f8c3dbc] to [59a4d46a1e].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFTriple.m from [51ba3c68c4] to [1fbb342275].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFUDPSocket+Private.h from [4a674f5731] to [b98a70815e].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#import "OFUDPSocket.h"

OF_ASSUME_NONNULL_BEGIN

OF_DIRECT_MEMBERS
@interface OFUDPSocket ()
- (uint16_t)of_bindToAddress: (OFSocketAddress *)address
		   extraType: (int)extraType;
@end

OF_ASSUME_NONNULL_END

|



















|
<



1
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 "OFUDPSocket.h"

OF_ASSUME_NONNULL_BEGIN

OF_DIRECT_MEMBERS
@interface OFUDPSocket ()
- (void)of_bindToAddress: (OFSocketAddress *)address extraType: (int)extraType;

@end

OF_ASSUME_NONNULL_END

Modified src/OFUDPSocket.h from [9190ffdfc0] to [3f2d31105b].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
/**
 * @brief Binds the socket to the specified host and port.
 *
 * @param host The host to bind to. Use `@"0.0.0.0"` for IPv4 or `@"::"` for
 *	       IPv6 to bind to all.
 * @param port The port to bind to. If the port is 0, an unused port will be
 *	       chosen, which can be obtained using the return value.
 * @return The port the socket was bound to
 * @throw OFBindIPSocketFailedException Binding failed
 * @throw OFAlreadyConnectedException The socket is already bound
 */
- (uint16_t)bindToHost: (OFString *)host port: (uint16_t)port;
@end

OF_ASSUME_NONNULL_END







|

|

|



67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
/**
 * @brief Binds the socket to the specified host and port.
 *
 * @param host The host to bind to. Use `@"0.0.0.0"` for IPv4 or `@"::"` for
 *	       IPv6 to bind to all.
 * @param port The port to bind to. If the port is 0, an unused port will be
 *	       chosen, which can be obtained using the return value.
 * @return The address the socket was bound to
 * @throw OFBindIPSocketFailedException Binding failed
 * @throw OFAlreadyOpenException The socket is already bound
 */
- (OFSocketAddress)bindToHost: (OFString *)host port: (uint16_t)port;
@end

OF_ASSUME_NONNULL_END

Modified src/OFUDPSocket.m from [67c55bc52f] to [a826172472].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
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
#import "OFUDPSocket+Private.h"
#import "OFDNSResolver.h"
#import "OFData.h"
#import "OFSocket.h"
#import "OFSocket+Private.h"
#import "OFThread.h"

#import "OFAlreadyConnectedException.h"
#import "OFBindIPSocketFailedException.h"

@implementation OFUDPSocket
@dynamic delegate;

- (uint16_t)of_bindToAddress: (OFSocketAddress *)address
		   extraType: (int)extraType OF_DIRECT
{
	void *pool = objc_autoreleasePoolPush();
	uint16_t port;
#if SOCK_CLOEXEC == 0 && defined(HAVE_FCNTL) && defined(FD_CLOEXEC)
	int flags;




#endif

	if ((_socket = socket(
	    ((struct sockaddr *)&address->sockaddr)->sa_family,
	    SOCK_DGRAM | SOCK_CLOEXEC | extraType, 0)) == OFInvalidSocketHandle)
		@throw [OFBindIPSocketFailedException
		    exceptionWithHost: OFSocketAddressString(address)







|





|
|

<
<


>
>
>
>







30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45


46
47
48
49
50
51
52
53
54
55
56
57
58
#import "OFUDPSocket+Private.h"
#import "OFDNSResolver.h"
#import "OFData.h"
#import "OFSocket.h"
#import "OFSocket+Private.h"
#import "OFThread.h"

#import "OFAlreadyOpenException.h"
#import "OFBindIPSocketFailedException.h"

@implementation OFUDPSocket
@dynamic delegate;

- (void)of_bindToAddress: (OFSocketAddress *)address
	       extraType: (int)extraType OF_DIRECT
{


#if SOCK_CLOEXEC == 0 && defined(HAVE_FCNTL) && defined(FD_CLOEXEC)
	int flags;
#endif
#if !defined(OF_HPUX) && !defined(OF_WII) && !defined(OF_NINTENDO_3DS)
	OFString *host;
	uint16_t port;
#endif

	if ((_socket = socket(
	    ((struct sockaddr *)&address->sockaddr)->sa_family,
	    SOCK_DGRAM | SOCK_CLOEXEC | extraType, 0)) == OFInvalidSocketHandle)
		@throw [OFBindIPSocketFailedException
		    exceptionWithHost: OFSocketAddressString(address)
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145

146
147
148

149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
			    (struct sockaddr *)&address->sockaddr,
			    address->length)) == 0)
				break;

			if (OFSocketErrNo() != EADDRINUSE) {
				int errNo = OFSocketErrNo();
				OFString *host = OFSocketAddressString(address);
				port = OFSocketAddressIPPort(address);

				closesocket(_socket);
				_socket = OFInvalidSocketHandle;

				@throw [OFBindIPSocketFailedException
				    exceptionWithHost: host
						 port: port
					       socket: self
						errNo: errNo];
			}
		}
	}
#endif

	objc_autoreleasePoolPop(pool);

	if ((port = OFSocketAddressIPPort(address)) > 0)
		return port;

#if !defined(OF_HPUX) && !defined(OF_WII) && !defined(OF_NINTENDO_3DS)
	memset(address, 0, sizeof(*address));

	address->length = (socklen_t)sizeof(address->sockaddr);
	if (OFGetSockName(_socket, (struct sockaddr *)&address->sockaddr,
	    &address->length) != 0) {
		int errNo = OFSocketErrNo();

		closesocket(_socket);
		_socket = OFInvalidSocketHandle;

		@throw [OFBindIPSocketFailedException
		    exceptionWithHost: OFSocketAddressString(address)
				 port: OFSocketAddressIPPort(address)
			       socket: self
				errNo: errNo];
	}

	switch (((struct sockaddr *)&address->sockaddr)->sa_family) {
	case AF_INET:
		return OFFromBigEndian16(address->sockaddr.in.sin_port);

# ifdef OF_HAVE_IPV6
	case AF_INET6:
		return OFFromBigEndian16(address->sockaddr.in6.sin6_port);

# endif
	default:
		closesocket(_socket);
		_socket = OFInvalidSocketHandle;

		@throw [OFBindIPSocketFailedException
		    exceptionWithHost: OFSocketAddressString(address)
				 port: OFSocketAddressIPPort(address)
			       socket: self
				errNo: EAFNOSUPPORT];
	}
#else
	closesocket(_socket);
	_socket = OFInvalidSocketHandle;

	@throw [OFBindIPSocketFailedException
	    exceptionWithHost: OFSocketAddressString(address)
			 port: OFSocketAddressIPPort(address)
		       socket: self
			errNo: EADDRNOTAVAIL];
#endif
}

- (uint16_t)bindToHost: (OFString *)host port: (uint16_t)port
{
	void *pool = objc_autoreleasePoolPush();
	OFData *socketAddresses;
	OFSocketAddress address;

	if (_socket != OFInvalidSocketHandle)
		@throw [OFAlreadyConnectedException exceptionWithSocket: self];

	socketAddresses = [[OFThread DNSResolver]
	    resolveAddressesForHost: host
		      addressFamily: OFSocketAddressFamilyAny];

	address = *(OFSocketAddress *)[socketAddresses itemAtIndex: 0];
	OFSocketAddressSetIPPort(&address, port);

	port = [self of_bindToAddress: &address extraType: 0];

	objc_autoreleasePoolPop(pool);

	return port;
}
@end







|














|
|
|
<

<










|
<
|
|
|




|
>


|
>






|
|



<
<
<
<
<
<
<
<
<



|






|








|



|


100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124

125

126
127
128
129
130
131
132
133
134
135
136

137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160









161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
			    (struct sockaddr *)&address->sockaddr,
			    address->length)) == 0)
				break;

			if (OFSocketErrNo() != EADDRINUSE) {
				int errNo = OFSocketErrNo();
				OFString *host = OFSocketAddressString(address);
				uint16_t port = OFSocketAddressIPPort(address);

				closesocket(_socket);
				_socket = OFInvalidSocketHandle;

				@throw [OFBindIPSocketFailedException
				    exceptionWithHost: host
						 port: port
					       socket: self
						errNo: errNo];
			}
		}
	}
#endif

#if !defined(OF_HPUX) && !defined(OF_WII) && !defined(OF_NINTENDO_3DS)
	host = OFSocketAddressString(address);
	port = OFSocketAddressIPPort(address);



	memset(address, 0, sizeof(*address));

	address->length = (socklen_t)sizeof(address->sockaddr);
	if (OFGetSockName(_socket, (struct sockaddr *)&address->sockaddr,
	    &address->length) != 0) {
		int errNo = OFSocketErrNo();

		closesocket(_socket);
		_socket = OFInvalidSocketHandle;

		@throw [OFBindIPSocketFailedException exceptionWithHost: host

								   port: port
								 socket: self
								  errNo: errNo];
	}

	switch (((struct sockaddr *)&address->sockaddr)->sa_family) {
	case AF_INET:
		address->family = OFSocketAddressFamilyIPv4;
		break;
# ifdef OF_HAVE_IPV6
	case AF_INET6:
		address->family = OFSocketAddressFamilyIPv6;
		break;
# endif
	default:
		closesocket(_socket);
		_socket = OFInvalidSocketHandle;

		@throw [OFBindIPSocketFailedException
		    exceptionWithHost: host
				 port: port
			       socket: self
				errNo: EAFNOSUPPORT];
	}









#endif
}

- (OFSocketAddress)bindToHost: (OFString *)host port: (uint16_t)port
{
	void *pool = objc_autoreleasePoolPush();
	OFData *socketAddresses;
	OFSocketAddress address;

	if (_socket != OFInvalidSocketHandle)
		@throw [OFAlreadyOpenException exceptionWithObject: self];

	socketAddresses = [[OFThread DNSResolver]
	    resolveAddressesForHost: host
		      addressFamily: OFSocketAddressFamilyAny];

	address = *(OFSocketAddress *)[socketAddresses itemAtIndex: 0];
	OFSocketAddressSetIPPort(&address, port);

	[self of_bindToAddress: &address extraType: 0];

	objc_autoreleasePoolPop(pool);

	return address;
}
@end

Modified src/OFUNIXDatagramSocket.h from [0a3ec7f2ad] to [71b07f1768].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
59
60
61
62
63
64
65
66
67

68
69
70
71
72
73
74
 */
@property OF_NULLABLE_PROPERTY (assign, nonatomic)
    id <OFUNIXDatagramSocketDelegate> delegate;

/**
 * @brief Bind the socket to the specified path.
 *
 * @param path The path to bind to
 * @return The address on which this socket can be reached

 * @throw OFBindUNIXSocketFailedException Binding failed
 * @throw OFAlreadyConnectedException The socket is already bound
 */
- (OFSocketAddress)bindToPath: (OFString *)path;
@end

OF_ASSUME_NONNULL_END







|
|
>

|

|



59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
 */
@property OF_NULLABLE_PROPERTY (assign, nonatomic)
    id <OFUNIXDatagramSocketDelegate> delegate;

/**
 * @brief Bind the socket to the specified path.
 *
 * @param path The path to bind to or `nil` for an anonymous socket
 * @return The address on which this socket can be reached, if a path was
 *	   specified
 * @throw OFBindUNIXSocketFailedException Binding failed
 * @throw OFAlreadyOpenException The socket is already bound
 */
- (OFSocketAddress)bindToPath: (nullable OFString *)path;
@end

OF_ASSUME_NONNULL_END

Modified src/OFUNIXDatagramSocket.m from [7203060d9a] to [7a4a7fa088].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
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
#endif

#import "OFUNIXDatagramSocket.h"
#import "OFSocket.h"
#import "OFSocket+Private.h"
#import "OFString.h"

#import "OFAlreadyConnectedException.h"
#import "OFBindUNIXSocketFailedException.h"

@implementation OFUNIXDatagramSocket
@dynamic delegate;

- (OFSocketAddress)bindToPath: (OFString *)path
{
	OFSocketAddress address;
#if SOCK_CLOEXEC == 0 && defined(HAVE_FCNTL_H) && defined(FD_CLOEXEC)
	int flags;
#endif

	if (_socket != OFInvalidSocketHandle)
		@throw [OFAlreadyConnectedException exceptionWithSocket: self];


	address = OFSocketAddressMakeUNIX(path);





	if ((_socket = socket(address.sockaddr.un.sun_family,
	    SOCK_DGRAM | SOCK_CLOEXEC, 0)) == OFInvalidSocketHandle)
		@throw [OFBindUNIXSocketFailedException
		    exceptionWithPath: path
			       socket: self
				errNo: OFSocketErrNo()];

	_canBlock = true;

#if SOCK_CLOEXEC == 0 && defined(HAVE_FCNTL_H) && defined(FD_CLOEXEC)
	if ((flags = fcntl(_socket, F_GETFD, 0)) != -1)
		fcntl(_socket, F_SETFD, flags | FD_CLOEXEC);
#endif


	if (bind(_socket, (struct sockaddr *)&address.sockaddr,
	    address.length) != 0) {
		int errNo = OFSocketErrNo();

		closesocket(_socket);
		_socket = OFInvalidSocketHandle;

		@throw [OFBindUNIXSocketFailedException
		    exceptionWithPath: path
			       socket: self
				errNo: errNo];

	}

	return address;
}
@end







|













|

>
|
>
>
>
|
>
|
|












>
|
|
|

|
|

|
|
|
|
>





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
#endif

#import "OFUNIXDatagramSocket.h"
#import "OFSocket.h"
#import "OFSocket+Private.h"
#import "OFString.h"

#import "OFAlreadyOpenException.h"
#import "OFBindUNIXSocketFailedException.h"

@implementation OFUNIXDatagramSocket
@dynamic delegate;

- (OFSocketAddress)bindToPath: (OFString *)path
{
	OFSocketAddress address;
#if SOCK_CLOEXEC == 0 && defined(HAVE_FCNTL_H) && defined(FD_CLOEXEC)
	int flags;
#endif

	if (_socket != OFInvalidSocketHandle)
		@throw [OFAlreadyOpenException exceptionWithObject: self];

	if (path != nil)
		address = OFSocketAddressMakeUNIX(path);
	else {
		address.family = OFSocketAddressFamilyUnknown;
		address.length = 0;
	}

	if ((_socket = socket(AF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, 0)) ==
	    OFInvalidSocketHandle)
		@throw [OFBindUNIXSocketFailedException
		    exceptionWithPath: path
			       socket: self
				errNo: OFSocketErrNo()];

	_canBlock = true;

#if SOCK_CLOEXEC == 0 && defined(HAVE_FCNTL_H) && defined(FD_CLOEXEC)
	if ((flags = fcntl(_socket, F_GETFD, 0)) != -1)
		fcntl(_socket, F_SETFD, flags | FD_CLOEXEC);
#endif

	if (path != nil) {
		if (bind(_socket, (struct sockaddr *)&address.sockaddr,
		    address.length) != 0) {
			int errNo = OFSocketErrNo();

			closesocket(_socket);
			_socket = OFInvalidSocketHandle;

			@throw [OFBindUNIXSocketFailedException
			    exceptionWithPath: path
				       socket: self
					errNo: errNo];
		}
	}

	return address;
}
@end

Modified src/OFUNIXStreamSocket.h from [3d105f3c9b] to [00aa582b21].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
    id <OFUNIXStreamSocketDelegate> delegate;

/**
 * @brief Connects the OFUNIXStreamSocket to the specified destination.
 *
 * @param path The path to connect to
 * @throw OFConnectUNIXSocketFailedException Connecting failed
 * @throw OFAlreadyConnectedException The socket is already connected or bound
 */
- (void)connectToPath: (OFString *)path;

/**
 * @brief Binds the socket to the specified host and port.
 *
 * @param path The path to bind to
 * @throw OFBindUNIXSocketFailedException Binding failed
 * @throw OFAlreadyConnectedException The socket is already connected or bound
 */
- (void)bindToPath: (OFString *)path;
@end

OF_ASSUME_NONNULL_END







|








|





51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
    id <OFUNIXStreamSocketDelegate> delegate;

/**
 * @brief Connects the OFUNIXStreamSocket to the specified destination.
 *
 * @param path The path to connect to
 * @throw OFConnectUNIXSocketFailedException Connecting failed
 * @throw OFAlreadyOpenException The socket is already connected or bound
 */
- (void)connectToPath: (OFString *)path;

/**
 * @brief Binds the socket to the specified host and port.
 *
 * @param path The path to bind to
 * @throw OFBindUNIXSocketFailedException Binding failed
 * @throw OFAlreadyOpenException The socket is already connected or bound
 */
- (void)bindToPath: (OFString *)path;
@end

OF_ASSUME_NONNULL_END

Modified src/OFUNIXStreamSocket.m from [ff26304fa1] to [22b6dcf4c0].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#endif

#import "OFUNIXStreamSocket.h"
#import "OFSocket.h"
#import "OFSocket+Private.h"
#import "OFString.h"

#import "OFAlreadyConnectedException.h"
#import "OFBindUNIXSocketFailedException.h"
#import "OFConnectUNIXSocketFailedException.h"

@implementation OFUNIXStreamSocket
@dynamic delegate;

- (void)connectToPath: (OFString *)path
{
	OFSocketAddress address;
#if SOCK_CLOEXEC == 0 && defined(HAVE_FCNTL) && defined(FD_CLOEXEC)
	int flags;
#endif

	if (_socket != OFInvalidSocketHandle)
		@throw [OFAlreadyConnectedException exceptionWithSocket: self];

	address = OFSocketAddressMakeUNIX(path);

	if ((_socket = socket(address.sockaddr.un.sun_family,
	    SOCK_STREAM | SOCK_CLOEXEC, 0)) == OFInvalidSocketHandle)
		@throw [OFConnectUNIXSocketFailedException
		    exceptionWithPath: path







|














|







20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#endif

#import "OFUNIXStreamSocket.h"
#import "OFSocket.h"
#import "OFSocket+Private.h"
#import "OFString.h"

#import "OFAlreadyOpenException.h"
#import "OFBindUNIXSocketFailedException.h"
#import "OFConnectUNIXSocketFailedException.h"

@implementation OFUNIXStreamSocket
@dynamic delegate;

- (void)connectToPath: (OFString *)path
{
	OFSocketAddress address;
#if SOCK_CLOEXEC == 0 && defined(HAVE_FCNTL) && defined(FD_CLOEXEC)
	int flags;
#endif

	if (_socket != OFInvalidSocketHandle)
		@throw [OFAlreadyOpenException exceptionWithObject: self];

	address = OFSocketAddressMakeUNIX(path);

	if ((_socket = socket(address.sockaddr.un.sun_family,
	    SOCK_STREAM | SOCK_CLOEXEC, 0)) == OFInvalidSocketHandle)
		@throw [OFConnectUNIXSocketFailedException
		    exceptionWithPath: path
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
{
	OFSocketAddress address;
#if SOCK_CLOEXEC == 0 && defined(HAVE_FCNTL) && defined(FD_CLOEXEC)
	int flags;
#endif

	if (_socket != OFInvalidSocketHandle)
		@throw [OFAlreadyConnectedException exceptionWithSocket: self];

	address = OFSocketAddressMakeUNIX(path);

	if ((_socket = socket(address.sockaddr.un.sun_family,
	    SOCK_STREAM | SOCK_CLOEXEC, 0)) == OFInvalidSocketHandle)
		@throw [OFBindUNIXSocketFailedException
		    exceptionWithPath: path







|







75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
{
	OFSocketAddress address;
#if SOCK_CLOEXEC == 0 && defined(HAVE_FCNTL) && defined(FD_CLOEXEC)
	int flags;
#endif

	if (_socket != OFInvalidSocketHandle)
		@throw [OFAlreadyOpenException exceptionWithObject: self];

	address = OFSocketAddressMakeUNIX(path);

	if ((_socket = socket(address.sockaddr.un.sun_family,
	    SOCK_STREAM | SOCK_CLOEXEC, 0)) == OFInvalidSocketHandle)
		@throw [OFBindUNIXSocketFailedException
		    exceptionWithPath: path

Modified src/OFUTF8String+Private.h from [a7a276ddae] to [f3aa389365].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFUTF8String.h from [d381d1f2a1] to [a9999803da].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFUTF8String.m from [c76e8c2ef7] to [5604031013].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFUUID.h from [e73d2af113] to [dc4351807f].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#import "OFObject.h"
#import "OFSerialization.h"

OF_ASSUME_NONNULL_BEGIN

@class OFString;

/**
 * @class OFUUID OFUUID.h ObjFW/OFUUID.h
 *
 * @brief A UUID conforming to RFC 4122.
 */
OF_SUBCLASSING_RESTRICTED
@interface OFUUID: OFObject <OFCopying, OFComparing, OFSerialization>
{
	unsigned char _bytes[16];
}

/**
 * @brief The UUID as a string.
 */

|














<











|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
/*
 * Copyright (c) 2008-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 "OFObject.h"


OF_ASSUME_NONNULL_BEGIN

@class OFString;

/**
 * @class OFUUID OFUUID.h ObjFW/OFUUID.h
 *
 * @brief A UUID conforming to RFC 4122.
 */
OF_SUBCLASSING_RESTRICTED
@interface OFUUID: OFObject <OFCopying, OFComparing>
{
	unsigned char _bytes[16];
}

/**
 * @brief The UUID as a string.
 */

Modified src/OFUUID.m from [3edaa624cf] to [27accfec93].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#import "OFUUID.h"
#import "OFArray.h"
#import "OFString.h"
#import "OFXMLElement.h"

#import "OFInvalidArgumentException.h"
#import "OFInvalidFormatException.h"
#import "OFOutOfRangeException.h"

#define bytesSize 16


|


















<







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

21
22
23
24
25
26
27
/*
 * Copyright (c) 2008-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 "OFUUID.h"
#import "OFArray.h"
#import "OFString.h"


#import "OFInvalidArgumentException.h"
#import "OFInvalidFormatException.h"
#import "OFOutOfRangeException.h"

#define bytesSize 16

141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
		[self release];
		@throw e;
	}

	return self;
}

- (instancetype)initWithSerialization: (OFXMLElement *)element
{
	void *pool = objc_autoreleasePoolPush();
	OFString *UUIDString;

	@try {
		if (![element.name isEqual: self.className] ||
		    ![element.namespace isEqual: OFSerializationNS])
			@throw [OFInvalidArgumentException exception];

		UUIDString = element.stringValue;
	} @catch (id e) {
		[self release];
		@throw e;
	}

	self = [self initWithUUIDString: UUIDString];

	objc_autoreleasePoolPop(pool);

	return self;
}

- (bool)isEqual: (id)object
{
	OFUUID *UUID;

	if (![object isKindOfClass: [OFUUID class]])
		return false;








<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







140
141
142
143
144
145
146























147
148
149
150
151
152
153
		[self release];
		@throw e;
	}

	return self;
}
























- (bool)isEqual: (id)object
{
	OFUUID *UUID;

	if (![object isKindOfClass: [OFUUID class]])
		return false;

231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
	    _bytes[12], _bytes[13], _bytes[14], _bytes[15]];
}

- (OFString *)description
{
	return self.UUIDString;
}

- (OFXMLElement *)XMLElementBySerializing
{
	void *pool = objc_autoreleasePoolPush();
	OFXMLElement *element = [OFXMLElement elementWithName: self.className
						    namespace: OFSerializationNS
						  stringValue: self.UUIDString];

	[element retain];

	objc_autoreleasePoolPop(pool);

	return [element autorelease];
}
@end







<
<
<
<
<
<
<
<
<
<
<
<
<
<

207
208
209
210
211
212
213














214
	    _bytes[12], _bytes[13], _bytes[14], _bytes[15]];
}

- (OFString *)description
{
	return self.UUIDString;
}














@end

Modified src/OFValue.h from [94dd083371] to [c0bdc814d4].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36

/**
 * @class OFValue OFValue.h ObjFW/OFValue.h
 *
 * @brief A class for storing arbitrary values in an object.
 */
@interface OFValue: OFObject <OFCopying>
{
	OF_RESERVE_IVARS(OFValue, 4)
}

/**
 * @brief The ObjC type encoding of the value.
 */
@property (readonly, nonatomic) const char *objCType;

/**
 * @brief The value as a pointer to void.







<
<
<
<







19
20
21
22
23
24
25




26
27
28
29
30
31
32

/**
 * @class OFValue OFValue.h ObjFW/OFValue.h
 *
 * @brief A class for storing arbitrary values in an object.
 */
@interface OFValue: OFObject <OFCopying>




/**
 * @brief The ObjC type encoding of the value.
 */
@property (readonly, nonatomic) const char *objCType;

/**
 * @brief The value as a pointer to void.
64
65
66
67
68
69
70
71
72
73
74
75
76














77
78
79
80
81
82
83
 * @brief The value as an OFSize.
 *
 * @throw OFOutOfRangeException The value is not OFSize-sized
 */
@property (readonly, nonatomic) OFSize sizeValue;

/**
 * @brief The value as a OFRect.
 *
 * @throw OFOutOfRangeException The value is not OFRect-sized
 */
@property (readonly, nonatomic) OFRect rectValue;















/**
 * @brief Creates a new, autorelease OFValue with the specified bytes of the
 *	  specified type.
 *
 * @param bytes The bytes containing the value
 * @param objCType The ObjC type encoding for the value
 * @return A new, autoreleased OFValue







|





>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
 * @brief The value as an OFSize.
 *
 * @throw OFOutOfRangeException The value is not OFSize-sized
 */
@property (readonly, nonatomic) OFSize sizeValue;

/**
 * @brief The value as an OFRect.
 *
 * @throw OFOutOfRangeException The value is not OFRect-sized
 */
@property (readonly, nonatomic) OFRect rectValue;

/**
 * @brief The value as an OFVector3D.
 *
 * @throw OFOutOfRangeException The value is not OFVector3D-sized
 */
@property (readonly, nonatomic) OFVector3D vector3DValue;

/**
 * @brief The value as an OFVector4D.
 *
 * @throw OFOutOfRangeException The value is not OFVector4D-sized
 */
@property (readonly, nonatomic) OFVector4D vector4DValue;

/**
 * @brief Creates a new, autorelease OFValue with the specified bytes of the
 *	  specified type.
 *
 * @param bytes The bytes containing the value
 * @param objCType The ObjC type encoding for the value
 * @return A new, autoreleased OFValue
136
137
138
139
140
141
142


















143
144
145
146
147
148
149
150
151
152


153
154
155
156
157
158
159
 *	  rectangle.
 *
 * @param rect The rectangle the OFValue should contain
 * @return A new, autoreleased OFValue
 */
+ (instancetype)valueWithRect: (OFRect)rect;



















/**
 * @brief Initializes an already allocated OFValue with the specified bytes of
 *	  the specified type.
 *
 * @param bytes The bytes containing the value
 * @param objCType The ObjC type encoding for the value
 * @return An initialized OFValue
 */
- (instancetype)initWithBytes: (const void *)bytes
		     objCType: (const char *)objCType;



/**
 * @brief Gets the value.
 *
 * @param value The buffer to copy the value into
 * @param size The size of the value
 * @throw OFOutOfRangeException The specified size does not match the value







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>









|
>
>







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
 *	  rectangle.
 *
 * @param rect The rectangle the OFValue should contain
 * @return A new, autoreleased OFValue
 */
+ (instancetype)valueWithRect: (OFRect)rect;

/**
 * @brief Creates a new, autoreleased OFValue containing the specified
 *	  3D vector.
 *
 * @param vector3D The 3D vector the OFValue should contain
 * @return A new, autoreleased OFValue
 */
+ (instancetype)valueWithVector3D: (OFVector3D)vector3D;

/**
 * @brief Creates a new, autoreleased OFValue containing the specified
 *	  4D vector.
 *
 * @param vector4D The 4D vector the OFValue should contain
 * @return A new, autoreleased OFValue
 */
+ (instancetype)valueWithVector4D: (OFVector4D)vector4D;

/**
 * @brief Initializes an already allocated OFValue with the specified bytes of
 *	  the specified type.
 *
 * @param bytes The bytes containing the value
 * @param objCType The ObjC type encoding for the value
 * @return An initialized OFValue
 */
- (instancetype)initWithBytes: (const void *)bytes
		     objCType: (const char *)objCType OF_DESIGNATED_INITIALIZER;

- (instancetype)init OF_UNAVAILABLE;

/**
 * @brief Gets the value.
 *
 * @param value The buffer to copy the value into
 * @param size The size of the value
 * @throw OFOutOfRangeException The specified size does not match the value

Modified src/OFValue.m from [d37e008646] to [45814a74e5].

1
2
3
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
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#import "OFValue.h"
#import "OFBytesValue.h"
#import "OFMethodSignature.h"
#import "OFNonretainedObjectValue.h"
#import "OFPointValue.h"
#import "OFPointerValue.h"
#import "OFRangeValue.h"
#import "OFRectValue.h"



#import "OFSizeValue.h"


#import "OFString.h"
















#import "OFOutOfMemoryException.h"



@implementation OFValue






+ (instancetype)alloc
{
	if (self == [OFValue class])
		return [OFBytesValue alloc];

	return [super alloc];
}

+ (instancetype)valueWithBytes: (const void *)bytes
		      objCType: (const char *)objCType
{
	return [[[OFBytesValue alloc] initWithBytes: bytes
					   objCType: objCType] autorelease];
}

+ (instancetype)valueWithPointer: (const void *)pointer
{
	return [[[OFPointerValue alloc] initWithPointer: pointer] autorelease];


}

+ (instancetype)valueWithNonretainedObject: (id)object
{
	return [[[OFNonretainedObjectValue alloc]
	    initWithNonretainedObject: object] autorelease];
}

+ (instancetype)valueWithRange: (OFRange)range
{
	return [[[OFRangeValue alloc] initWithRange: range] autorelease];

}

+ (instancetype)valueWithPoint: (OFPoint)point
{
	return [[[OFPointValue alloc] initWithPoint: point] autorelease];

}

+ (instancetype)valueWithSize: (OFSize)size
{
	return [[[OFSizeValue alloc] initWithSize: size] autorelease];

}

+ (instancetype)valueWithRect: (OFRect)rect
{
	return [[[OFRectValue alloc] initWithRect: rect] autorelease];

}















- (instancetype)initWithBytes: (const void *)bytes
		     objCType: (const char *)objCType
















{
	OF_INVALID_INIT_METHOD
}

- (bool)isEqual: (id)object
{
	const char *objCType;

|
















|

<
|
|
|
|
>
>
>
|
>
>
|
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
|
>
>


>
>
>
>
>
>



|







|
|




|
>
>




|
|




|
>




|
>




|
>




|
>


>
>
>
>
>
>
>
>
>
>
>
>
>
>


>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







1
2
3
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
/*
 * 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 "OFValue.h"
#import "OFConcreteValue.h"
#import "OFMethodSignature.h"

#import "OFString.h"

#import "OFOutOfMemoryException.h"

static struct {
	Class isa;
} placeholder;

@interface OFPlaceholderValue: OFValue
@end

@implementation OFPlaceholderValue
#ifdef __clang__
/* We intentionally don't call into super, so silence the warning. */
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wunknown-pragmas"
# pragma clang diagnostic ignored "-Wobjc-designated-initializers"
#endif
- (instancetype)initWithBytes: (const void *)bytes
		     objCType: (const char *)objCType
{
	return (id)[[OFConcreteValue alloc] initWithBytes: bytes
						 objCType: objCType];
}
#ifdef __clang__
# pragma clang diagnostic pop
#endif

OF_SINGLETON_METHODS
@end

@implementation OFValue
+ (void)initialize
{
	if (self == [OFValue class])
		object_setClass((id)&placeholder, [OFPlaceholderValue class]);
}

+ (instancetype)alloc
{
	if (self == [OFValue class])
		return (id)&placeholder;

	return [super alloc];
}

+ (instancetype)valueWithBytes: (const void *)bytes
		      objCType: (const char *)objCType
{
	return [[[OFValue alloc] initWithBytes: bytes
				      objCType: objCType] autorelease];
}

+ (instancetype)valueWithPointer: (const void *)pointer
{
	return [[[OFValue alloc]
	    initWithBytes: &pointer
		 objCType: @encode(const void *)] autorelease];
}

+ (instancetype)valueWithNonretainedObject: (id)object
{
	return [[[OFValue alloc] initWithBytes: &object
				      objCType: @encode(id)] autorelease];
}

+ (instancetype)valueWithRange: (OFRange)range
{
	return [[[OFValue alloc] initWithBytes: &range
				      objCType: @encode(OFRange)] autorelease];
}

+ (instancetype)valueWithPoint: (OFPoint)point
{
	return [[[OFValue alloc] initWithBytes: &point
				      objCType: @encode(OFPoint)] autorelease];
}

+ (instancetype)valueWithSize: (OFSize)size
{
	return [[[OFValue alloc] initWithBytes: &size
				      objCType: @encode(OFSize)] autorelease];
}

+ (instancetype)valueWithRect: (OFRect)rect
{
	return [[[OFValue alloc] initWithBytes: &rect
				      objCType: @encode(OFRect)] autorelease];
}

+ (instancetype)valueWithVector3D: (OFVector3D)vector3D
{
	return [[[OFValue alloc]
	    initWithBytes: &vector3D
		 objCType: @encode(OFVector3D)] autorelease];
}

+ (instancetype)valueWithVector4D: (OFVector4D)vector4D
{
	return [[[OFValue alloc]
	    initWithBytes: &vector4D
		 objCType: @encode(OFVector4D)] autorelease];
}

- (instancetype)initWithBytes: (const void *)bytes
		     objCType: (const char *)objCType
{
	if ([self isMemberOfClass: [OFValue class]]) {
		@try {
			[self doesNotRecognizeSelector: _cmd];
		} @catch (id e) {
			[self release];
			@throw e;
		}

		abort();
	}

	return [super init];
}

- (instancetype)init
{
	OF_INVALID_INIT_METHOD
}

- (bool)isEqual: (id)object
{
	const char *objCType;
196
197
198
199
200
201
202














203
204
205

206
207
208
209
210
















































211
212
213
214
215
216
217

- (OFRect)rectValue
{
	OFRect ret;
	[self getValue: &ret size: sizeof(ret)];
	return ret;
}















- (OFString *)description
{

	OFMutableString *ret =
	    [OFMutableString stringWithString: @"<OFValue: "];
	size_t size = OFSizeOfTypeEncoding(self.objCType);
	unsigned char *value;

















































	value = OFAllocMemory(1, size);
	@try {
		[self getValue: value size: size];

		for (size_t i = 0; i < size; i++) {
			if (i > 0)
				[ret appendString: @" "];







>
>
>
>
>
>
>
>
>
>
>
>
>
>



>
|
<
|


>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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

- (OFRect)rectValue
{
	OFRect ret;
	[self getValue: &ret size: sizeof(ret)];
	return ret;
}

- (OFVector3D)vector3DValue
{
	OFVector3D ret;
	[self getValue: &ret size: sizeof(ret)];
	return ret;
}

- (OFVector4D)vector4DValue
{
	OFVector4D ret;
	[self getValue: &ret size: sizeof(ret)];
	return ret;
}

- (OFString *)description
{
	const char *objCType = self.objCType;
	OFMutableString *ret;

	size_t size;
	unsigned char *value;

	if (strcmp(objCType, @encode(OFRange)) == 0 ||
	    strcmp(objCType, @encode(const OFRange)) == 0) {
		OFRange rangeValue;
		[self getValue: &rangeValue size: sizeof(rangeValue)];
		return [OFString stringWithFormat:
		    @"<OFValue: OFRange { %zd, %zd }>",
		    rangeValue.location, rangeValue.length];
	} else if (strcmp(objCType, @encode(OFPoint)) == 0 ||
	    strcmp(objCType, @encode(const OFPoint)) == 0) {
		OFPoint pointValue;
		[self getValue: &pointValue size: sizeof(pointValue)];
		return [OFString stringWithFormat:
		    @"<OFValue: OFPoint { %g, %g }>",
		    pointValue.x, pointValue.y];
	} else if (strcmp(objCType, @encode(OFSize)) == 0 ||
	    strcmp(objCType, @encode(const OFSize)) == 0) {
		OFSize sizeValue;
		[self getValue: &sizeValue size: sizeof(sizeValue)];
		return [OFString stringWithFormat:
		    @"<OFValue: OFSize { %g, %g }>",
		    sizeValue.width, sizeValue.height];
	} else if (strcmp(objCType, @encode(OFRect)) == 0 ||
	    strcmp(objCType, @encode(const OFRect)) == 0) {
		OFRect rectValue;
		[self getValue: &rectValue size: sizeof(rectValue)];
		return [OFString stringWithFormat:
		    @"<OFValue: OFRect { %g, %g, %g, %g }>",
		    rectValue.origin.x, rectValue.origin.y,
		    rectValue.size.width, rectValue.size.height];
	} else if (strcmp(objCType, @encode(OFVector3D)) == 0 ||
	    strcmp(objCType, @encode(const OFVector3D)) == 0) {
		OFVector3D vector3DValue;
		[self getValue: &vector3DValue size: sizeof(vector3DValue)];
		return [OFString stringWithFormat:
		    @"<OFValue: OFVector3D { %g, %g, %g }>",
		    vector3DValue.x, vector3DValue.y, vector3DValue.z];
	} else if (strcmp(objCType, @encode(OFVector4D)) == 0 ||
	    strcmp(objCType, @encode(const OFVector4D)) == 0) {
		OFVector4D vector4DValue;
		[self getValue: &vector4DValue size: sizeof(vector4DValue)];
		return [OFString stringWithFormat:
		    @"<OFValue: OFVector4D { %g, %g, %g, %g }>",
		    vector4DValue.x, vector4DValue.y, vector4DValue.z,
		    vector4DValue.w];
	}

	ret = [OFMutableString stringWithString: @"<OFValue: "];
	size = OFSizeOfTypeEncoding(objCType);
	value = OFAllocMemory(1, size);
	@try {
		[self getValue: value size: size];

		for (size_t i = 0; i < size; i++) {
			if (i > 0)
				[ret appendString: @" "];

Modified src/OFWin32ConsoleStdIOStream.h from [d9940ccf28] to [490742cd4a].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFWindowsRegistryKey.h from [6b1a582030] to [51e43f2e9c].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFWindowsRegistryKey.m from [bf1674ca4d] to [ed6d846bab].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFXMLAttribute.h from [f37ed8f3fd] to [d32adc207c].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
88
89
90
91
92
93
94
95
96
97
98
99
 * @param nameSpace The namespace of the attribute
 * @param stringValue The string value of the attribute
 * @return An initialized OFXMLAttribute with the specified parameters
 */
- (instancetype)initWithName: (OFString *)name
		   namespace: (nullable OFString *)nameSpace
		 stringValue: (OFString *)stringValue OF_DESIGNATED_INITIALIZER;

- (instancetype)initWithSerialization: (OFXMLElement *)element;
@end

OF_ASSUME_NONNULL_END







<
<



88
89
90
91
92
93
94


95
96
97
 * @param nameSpace The namespace of the attribute
 * @param stringValue The string value of the attribute
 * @return An initialized OFXMLAttribute with the specified parameters
 */
- (instancetype)initWithName: (OFString *)name
		   namespace: (nullable OFString *)nameSpace
		 stringValue: (OFString *)stringValue OF_DESIGNATED_INITIALIZER;


@end

OF_ASSUME_NONNULL_END

Modified src/OFXMLAttribute.m from [fef93ca0aa] to [4bbe01e11d].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#import "OFXMLAttribute.h"
#import "OFXMLNode+Private.h"
#import "OFString.h"
#import "OFDictionary.h"
#import "OFXMLElement.h"

#import "OFInvalidArgumentException.h"

@implementation OFXMLAttribute
@synthesize name = _name, namespace = _namespace;

+ (instancetype)attributeWithName: (OFString *)name

|



















<







1
2
3
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 "OFXMLAttribute.h"
#import "OFXMLNode+Private.h"
#import "OFString.h"
#import "OFDictionary.h"


#import "OFInvalidArgumentException.h"

@implementation OFXMLAttribute
@synthesize name = _name, namespace = _namespace;

+ (instancetype)attributeWithName: (OFString *)name
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
		_namespace = [namespace copy];
		_stringValue = [stringValue copy];
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (instancetype)initWithSerialization: (OFXMLElement *)element
{
	void *pool;
	OFString *name, *namespace, *stringValue;

	@try {
		pool = objc_autoreleasePoolPush();

		if (![element.name isEqual: self.className] ||
		    ![element.namespace isEqual: OFSerializationNS])
			@throw [OFInvalidArgumentException exception];

		name = [element attributeForName: @"name"].stringValue;
		namespace = [element attributeForName: @"namespace"]
		    .stringValue;
		stringValue = [element attributeForName: @"stringValue"]
		    .stringValue;
	} @catch (id e) {
		[self release];
		@throw e;
	}

	self = [self initWithName: name
			namespace: namespace
		      stringValue: stringValue];

	@try {
		objc_autoreleasePoolPop(pool);
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (void)dealloc
{
	[_name release];
	[_namespace release];







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







60
61
62
63
64
65
66




































67
68
69
70
71
72
73
		_namespace = [namespace copy];
		_stringValue = [stringValue copy];
	} @catch (id e) {
		[self release];
		@throw e;
	}





































	return self;
}

- (void)dealloc
{
	[_name release];
	[_namespace release];
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
	OFHashAddHash(&hash, _stringValue.hash);

	OFHashFinalize(&hash);

	return hash;
}

- (OFXMLElement *)XMLElementBySerializing
{
	void *pool = objc_autoreleasePoolPush();
	OFXMLElement *element;

	element = [OFXMLElement elementWithName: self.className
				      namespace: OFSerializationNS];
	[element addAttributeWithName: @"name" stringValue: _name];

	if (_namespace != nil)
		[element addAttributeWithName: @"namespace"
				  stringValue: _namespace];

	[element addAttributeWithName: @"stringValue"
			  stringValue: _stringValue];

	[element retain];

	objc_autoreleasePoolPop(pool);

	return [element autorelease];
}

- (OFString *)description
{
	return [OFString stringWithFormat: @"<%@: name=%@, namespace=%@, "
					   @"stringValue=%@>",
					   self.class, _name, _namespace,
					   _stringValue];
}
@end







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<








122
123
124
125
126
127
128























129
130
131
132
133
134
135
136
	OFHashAddHash(&hash, _stringValue.hash);

	OFHashFinalize(&hash);

	return hash;
}
























- (OFString *)description
{
	return [OFString stringWithFormat: @"<%@: name=%@, namespace=%@, "
					   @"stringValue=%@>",
					   self.class, _name, _namespace,
					   _stringValue];
}
@end

Modified src/OFXMLCDATA.h from [45c442f70d] to [3e696dc76c].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
39
40
41
42
43
44
45
46
47
48
49
50
/**
 * @brief Initializes an already allocated OFXMLCDATA with the specified string.
 *
 * @param string The string value for the CDATA
 * @return An initialized OFXMLCDATA
 */
- (instancetype)initWithString: (OFString *)string;

- (instancetype)initWithSerialization: (OFXMLElement *)element;
@end

OF_ASSUME_NONNULL_END







<
<



39
40
41
42
43
44
45


46
47
48
/**
 * @brief Initializes an already allocated OFXMLCDATA with the specified string.
 *
 * @param string The string value for the CDATA
 * @return An initialized OFXMLCDATA
 */
- (instancetype)initWithString: (OFString *)string;


@end

OF_ASSUME_NONNULL_END

Modified src/OFXMLCDATA.m from [268b8de778] to [c5abefaba4].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#import "OFXMLCDATA.h"
#import "OFXMLNode+Private.h"
#import "OFString.h"
#import "OFXMLElement.h"

#import "OFInvalidArgumentException.h"

@implementation OFXMLCDATA
+ (instancetype)CDATAWithString: (OFString *)string
{
	return [[[self alloc] initWithString: string] autorelease];
}

- (instancetype)initWithString: (OFString *)string
{
	self = [super of_init];

	@try {
		_CDATA = [string copy];
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (instancetype)initWithSerialization: (OFXMLElement *)element
{
	self = [super of_init];

	@try {
		void *pool = objc_autoreleasePoolPush();

		if (![element.name isEqual: self.className] ||
		    ![element.namespace isEqual: OFSerializationNS])
			@throw [OFInvalidArgumentException exception];

		_CDATA = [element.stringValue copy];

		objc_autoreleasePoolPop(pool);
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (void)dealloc
{
	[_CDATA release];


|


















<




















<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40






















41
42
43
44
45
46
47
/*
 * Copyright (c) 2008-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 "OFXMLCDATA.h"
#import "OFXMLNode+Private.h"
#import "OFString.h"


#import "OFInvalidArgumentException.h"

@implementation OFXMLCDATA
+ (instancetype)CDATAWithString: (OFString *)string
{
	return [[[self alloc] initWithString: string] autorelease];
}

- (instancetype)initWithString: (OFString *)string
{
	self = [super of_init];

	@try {
		_CDATA = [string copy];
	} @catch (id e) {
		[self release];
		@throw e;
	}























	return self;
}

- (void)dealloc
{
	[_CDATA release];

116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
	return [ret autorelease];
}

- (OFString *)description
{
	return self.XMLString;
}

- (OFXMLElement *)XMLElementBySerializing
{
	OFXMLElement *element =
	    [OFXMLElement elementWithName: self.className
				namespace: OFSerializationNS];
	[element addChild: self];

	return element;
}
@end







<
<
<
<
<
<
<
<
<
<

93
94
95
96
97
98
99










100
	return [ret autorelease];
}

- (OFString *)description
{
	return self.XMLString;
}










@end

Modified src/OFXMLCharacters.h from [50ac8d5a7f] to [daab18e4f0].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
40
41
42
43
44
45
46
47
48
49
50
51
 * @brief Initializes an already allocated OFXMLCharacters with the specified
 *	  string.
 *
 * @param string The string value for the characters
 * @return An initialized OFXMLCharacters
 */
- (instancetype)initWithString: (OFString *)string;

- (instancetype)initWithSerialization: (OFXMLElement *)element;
@end

OF_ASSUME_NONNULL_END







<
<



40
41
42
43
44
45
46


47
48
49
 * @brief Initializes an already allocated OFXMLCharacters with the specified
 *	  string.
 *
 * @param string The string value for the characters
 * @return An initialized OFXMLCharacters
 */
- (instancetype)initWithString: (OFString *)string;


@end

OF_ASSUME_NONNULL_END

Modified src/OFXMLCharacters.m from [53e16f06bf] to [9e533c6ec8].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#import "OFXMLCharacters.h"
#import "OFXMLNode+Private.h"
#import "OFString.h"
#import "OFXMLElement.h"

#import "OFInvalidArgumentException.h"

@implementation OFXMLCharacters
+ (instancetype)charactersWithString: (OFString *)string
{
	return [[[self alloc] initWithString: string] autorelease];
}

- (instancetype)initWithString: (OFString *)string
{
	self = [super of_init];

	@try {
		_characters = [string copy];
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (instancetype)initWithSerialization: (OFXMLElement *)element
{
	self = [super of_init];

	@try {
		void *pool = objc_autoreleasePoolPush();

		if (![element.name isEqual: self.className] ||
		    ![element.namespace isEqual: OFSerializationNS])
			@throw [OFInvalidArgumentException exception];

		_characters = [element.stringValue copy];

		objc_autoreleasePoolPop(pool);
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (void)dealloc
{
	[_characters release];


|


















<




















<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40






















41
42
43
44
45
46
47
/*
 * Copyright (c) 2008-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 "OFXMLCharacters.h"
#import "OFXMLNode+Private.h"
#import "OFString.h"


#import "OFInvalidArgumentException.h"

@implementation OFXMLCharacters
+ (instancetype)charactersWithString: (OFString *)string
{
	return [[[self alloc] initWithString: string] autorelease];
}

- (instancetype)initWithString: (OFString *)string
{
	self = [super of_init];

	@try {
		_characters = [string copy];
	} @catch (id e) {
		[self release];
		@throw e;
	}























	return self;
}

- (void)dealloc
{
	[_characters release];

108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
	return _characters.stringByXMLEscaping;
}

- (OFString *)description
{
	return self.XMLString;
}

- (OFXMLElement *)XMLElementBySerializing
{
	return [OFXMLElement elementWithName: self.className
				   namespace: OFSerializationNS
				 stringValue: _characters];
}
@end







<
<
<
<
<
<
<

85
86
87
88
89
90
91







92
	return _characters.stringByXMLEscaping;
}

- (OFString *)description
{
	return self.XMLString;
}







@end

Modified src/OFXMLComment.h from [566c15f0b8] to [6613178669].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
45
46
47
48
49
50
51
52
53
54
55
56
 * @brief Initializes an already allocated OFXMLComment with the specified
 *	  text.
 *
 * @param text The text for the comment
 * @return An initialized OFXMLComment
 */
- (instancetype)initWithText: (OFString *)text;

- (instancetype)initWithSerialization: (OFXMLElement *)element;
@end

OF_ASSUME_NONNULL_END







<
<



45
46
47
48
49
50
51


52
53
54
 * @brief Initializes an already allocated OFXMLComment with the specified
 *	  text.
 *
 * @param text The text for the comment
 * @return An initialized OFXMLComment
 */
- (instancetype)initWithText: (OFString *)text;


@end

OF_ASSUME_NONNULL_END

Modified src/OFXMLComment.m from [9e48182a96] to [16e59e9cc9].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#include <string.h>

#import "OFXMLComment.h"
#import "OFXMLNode+Private.h"
#import "OFString.h"
#import "OFXMLElement.h"

#import "OFInvalidArgumentException.h"

@implementation OFXMLComment
@synthesize text = _text;

+ (instancetype)commentWithText: (OFString *)text

|




















<







1
2
3
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.
 */

#include "config.h"

#include <string.h>

#import "OFXMLComment.h"
#import "OFXMLNode+Private.h"
#import "OFString.h"


#import "OFInvalidArgumentException.h"

@implementation OFXMLComment
@synthesize text = _text;

+ (instancetype)commentWithText: (OFString *)text
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
	@try {
		_text = [text copy];
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (instancetype)initWithSerialization: (OFXMLElement *)element
{
	self = [super of_init];

	@try {
		void *pool = objc_autoreleasePoolPush();

		if (![element.name isEqual: self.className] ||
		    ![element.namespace isEqual: OFSerializationNS])
			@throw [OFInvalidArgumentException exception];

		_text = [element.stringValue copy];

		objc_autoreleasePoolPop(pool);
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (void)dealloc
{
	[_text release];








<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







38
39
40
41
42
43
44






















45
46
47
48
49
50
51
	@try {
		_text = [text copy];
	} @catch (id e) {
		[self release];
		@throw e;
	}























	return self;
}

- (void)dealloc
{
	[_text release];

105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
	return [OFString stringWithFormat: @"<!--%@-->", _text];
}

- (OFString *)description
{
	return self.XMLString;
}

- (OFXMLElement *)XMLElementBySerializing
{
	return [OFXMLElement elementWithName: self.className
				   namespace: OFSerializationNS
				 stringValue: _text];
}
@end







<
<
<
<
<
<
<

82
83
84
85
86
87
88







89
	return [OFString stringWithFormat: @"<!--%@-->", _text];
}

- (OFString *)description
{
	return self.XMLString;
}







@end

Deleted src/OFXMLElement+Serialization.h version [fdd03ade73].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#import "OFXMLElement.h"

OF_ASSUME_NONNULL_BEGIN

#ifdef __cplusplus
extern "C" {
#endif
extern int _OFXMLElement_Serialization_reference;
#ifdef __cplusplus
}
#endif

@interface OFXMLElement (OFSerialization)
/**
 * @brief The XML element interpreted as serialization and parsed into an
 *	  object.
 */
@property (readonly, nonatomic) id objectByDeserializing;
@end

OF_ASSUME_NONNULL_END
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<








































































Deleted src/OFXMLElement+Serialization.m version [c71645309e].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#import "OFXMLElement.h"
#import "OFXMLElement+Serialization.h"
#import "OFSerialization.h"
#import "OFString.h"

#import "OFInvalidArgumentException.h"

int _OFXMLElement_Serialization_reference;

@implementation OFXMLElement (Serialization)
- (id)objectByDeserializing
{
	void *pool = objc_autoreleasePoolPush();
	Class class;
	id object;

	if ((class = objc_getClass([_name cStringWithEncoding:
	    OFStringEncodingASCII])) == Nil)
		@throw [OFInvalidArgumentException exception];

	if (![class conformsToProtocol: @protocol(OFSerialization)])
		@throw [OFInvalidArgumentException exception];

	object = [[class alloc] initWithSerialization: self];

	objc_autoreleasePoolPop(pool);

	return [object autorelease];
}
@end
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<






























































































Modified src/OFXMLElement.h from [0fc969c160] to [ce204f44dc].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
430
431
432
433
434
435
436
437
438
 *				      needs a prefix
 */
- (OFString *)XMLStringWithDefaultNamespace: (OFString *)defaultNS
				indentation: (unsigned int)indentation;
@end

OF_ASSUME_NONNULL_END

#import "OFXMLElement+Serialization.h"







<
<
430
431
432
433
434
435
436


 *				      needs a prefix
 */
- (OFString *)XMLStringWithDefaultNamespace: (OFString *)defaultNS
				indentation: (unsigned int)indentation;
@end

OF_ASSUME_NONNULL_END


Modified src/OFXMLElement.m from [ada192cadd] to [a352f57a0b].

1
2
3
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-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#define OF_XML_ELEMENT_M

#include <stdlib.h>
#include <string.h>

#include <assert.h>

#import "OFXMLElement.h"
#import "OFArray.h"
#import "OFData.h"
#import "OFDictionary.h"
#import "OFStream.h"
#import "OFString.h"
#import "OFXMLAttribute.h"
#import "OFXMLCDATA.h"
#import "OFXMLCharacters.h"
#import "OFXMLElementBuilder.h"
#import "OFXMLNode+Private.h"
#import "OFXMLParser.h"

#import "OFInvalidArgumentException.h"
#import "OFInvalidFormatException.h"
#import "OFMalformedXMLException.h"
#import "OFUnboundNamespaceException.h"

/* References for static linking */
void
_references_to_categories_of_OFXMLElement(void)
{
	_OFXMLElement_Serialization_reference = 1;
}

@interface OFXMLElementElementBuilderDelegate: OFObject
    <OFXMLElementBuilderDelegate>
{
@public
	OFXMLElement *_element;
}
@end

|




















<
<


















<
<
<
<
<
<
<







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22


23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40







41
42
43
44
45
46
47
/*
 * Copyright (c) 2008-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"

#define OF_XML_ELEMENT_M

#include <stdlib.h>
#include <string.h>



#import "OFXMLElement.h"
#import "OFArray.h"
#import "OFData.h"
#import "OFDictionary.h"
#import "OFStream.h"
#import "OFString.h"
#import "OFXMLAttribute.h"
#import "OFXMLCDATA.h"
#import "OFXMLCharacters.h"
#import "OFXMLElementBuilder.h"
#import "OFXMLNode+Private.h"
#import "OFXMLParser.h"

#import "OFInvalidArgumentException.h"
#import "OFInvalidFormatException.h"
#import "OFMalformedXMLException.h"
#import "OFUnboundNamespaceException.h"








@interface OFXMLElementElementBuilderDelegate: OFObject
    <OFXMLElementBuilderDelegate>
{
@public
	OFXMLElement *_element;
}
@end
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
		[_attributes release];
		_attributes = [element->_attributes retain];
		[_namespaces release];
		_namespaces = [element->_namespaces retain];
		[_children release];
		_children = [element->_children retain];

		objc_autoreleasePoolPop(pool);
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (instancetype)initWithSerialization: (OFXMLElement *)element
{
	void *pool;
	OFString *name, *namespace;

	@try {
		pool = objc_autoreleasePoolPush();

		if (![element.name isEqual: self.className] ||
		    ![element.namespace isEqual: OFSerializationNS])
			@throw [OFInvalidArgumentException exception];

		name = [element attributeForName: @"name"].stringValue;
		namespace =
		    [element attributeForName: @"namespace"].stringValue;
	} @catch (id e) {
		[self release];
		@throw e;
	}

	self = [self initWithName: name namespace: namespace];

	@try {
		OFXMLElement *attributesElement, *namespacesElement;
		OFXMLElement *childrenElement;
		OFEnumerator *keyEnumerator, *objectEnumerator;
		OFString *key, *object;

		attributesElement = [[element
		    elementForName: @"attributes"
			 namespace: OFSerializationNS]
		    elementsForNamespace: OFSerializationNS].firstObject;
		namespacesElement = [[element
		    elementForName: @"namespaces"
			 namespace: OFSerializationNS]
		    elementsForNamespace: OFSerializationNS].firstObject;
		childrenElement = [[element
		    elementForName: @"children"
			 namespace: OFSerializationNS]
		    elementsForNamespace: OFSerializationNS].firstObject;

		[_attributes release];
		_attributes = nil;
		_attributes = [attributesElement.objectByDeserializing
		    mutableCopy];

		[_namespaces release];
		_namespaces = nil;
		_namespaces = [namespacesElement.objectByDeserializing
		    mutableCopy];

		[_children release];
		_children = nil;
		_children = [childrenElement.objectByDeserializing
		    mutableCopy];

		/* Sanity checks */
		if ((_attributes != nil && ![_attributes isKindOfClass:
		    [OFMutableArray class]]) || (_namespaces != nil &&
		    ![_namespaces isKindOfClass:
		    [OFMutableDictionary class]]) || (_children != nil &&
		    ![_children isKindOfClass: [OFMutableArray class]]))
			@throw [OFInvalidArgumentException exception];

		for (OFXMLAttribute *attribute in _attributes)
			if (![attribute isKindOfClass: [OFXMLAttribute class]])
				@throw [OFInvalidArgumentException exception];

		keyEnumerator = [_namespaces keyEnumerator];
		objectEnumerator = [_namespaces objectEnumerator];
		while ((key = [keyEnumerator nextObject]) != nil &&
		    (object = [objectEnumerator nextObject]) != nil)
			if (![key isKindOfClass: [OFString class]] ||
			    ![object isKindOfClass: [OFString class]])
				@throw [OFInvalidArgumentException exception];

		for (object in _children)
			if (![object isKindOfClass: [OFXMLNode class]])
				@throw [OFInvalidArgumentException exception];

		if (_namespaces == nil)
			_namespaces = [[OFMutableDictionary alloc] init];

		[_namespaces
		    setObject: @"xml"
		       forKey: @"http://www.w3.org/XML/1998/namespace"];
		[_namespaces setObject: @"xmlns"
				forKey: @"http://www.w3.org/2000/xmlns/"];

		objc_autoreleasePoolPop(pool);
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







256
257
258
259
260
261
262


































































































263
264
265
266
267
268
269
		[_attributes release];
		_attributes = [element->_attributes retain];
		[_namespaces release];
		_namespaces = [element->_namespaces retain];
		[_children release];
		_children = [element->_children retain];



































































































		objc_autoreleasePoolPop(pool);
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
			memcpy(cString + i, _name.UTF8String,
			    _name.UTF8StringLength);
			i += _name.UTF8StringLength;
		} else
			cString[i++] = '/';

		cString[i++] = '>';
		assert(i == length);

		objc_autoreleasePoolPop(pool);

		ret = [OFString stringWithUTF8String: cString
					      length: length];
	} @finally {
		OFFreeMemory(cString);







|







522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
			memcpy(cString + i, _name.UTF8String,
			    _name.UTF8StringLength);
			i += _name.UTF8StringLength;
		} else
			cString[i++] = '/';

		cString[i++] = '>';
		OFAssert(i == length);

		objc_autoreleasePoolPop(pool);

		ret = [OFString stringWithUTF8String: cString
					      length: length];
	} @finally {
		OFFreeMemory(cString);
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
{
	return [self of_XMLStringWithDefaultNS: defaultNS
				    namespaces: nil
				   indentation: indentation
					 level: 0];
}

- (OFXMLElement *)XMLElementBySerializing
{
	void *pool = objc_autoreleasePoolPush();
	OFXMLElement *element;

	element = [OFXMLElement elementWithName: self.className
				      namespace: OFSerializationNS];

	if (_name != nil)
		[element addAttributeWithName: @"name" stringValue: _name];

	if (_namespace != nil)
		[element addAttributeWithName: @"namespace"
				  stringValue: _namespace];

	if (_attributes != nil) {
		OFXMLElement *attributesElement;

		attributesElement =
		    [OFXMLElement elementWithName: @"attributes"
					namespace: OFSerializationNS];
		[attributesElement addChild:
		    _attributes.XMLElementBySerializing];
		[element addChild: attributesElement];
	}

	if (_namespaces != nil) {
		OFXMLElement *namespacesElement;
		OFMutableDictionary *namespacesCopy =
		    [[_namespaces mutableCopy] autorelease];

		[namespacesCopy removeObjectForKey:
		    @"http://www.w3.org/XML/1998/namespace"];
		[namespacesCopy removeObjectForKey:
		    @"http://www.w3.org/2000/xmlns/"];

		if (namespacesCopy.count > 0) {
			namespacesElement =
			    [OFXMLElement elementWithName: @"namespaces"
						namespace: OFSerializationNS];
			[namespacesElement addChild:
			    namespacesCopy.XMLElementBySerializing];
			[element addChild: namespacesElement];
		}
	}

	if (_children != nil) {
		OFXMLElement *childrenElement;

		childrenElement =
		    [OFXMLElement elementWithName: @"children"
					namespace: OFSerializationNS];
		[childrenElement addChild: _children.XMLElementBySerializing];
		[element addChild: childrenElement];
	}

	[element retain];

	objc_autoreleasePoolPop(pool);

	return [element autorelease];
}

- (void)addAttribute: (OFXMLAttribute *)attribute
{
	if (![attribute isKindOfClass: [OFXMLAttribute class]])
		@throw [OFInvalidArgumentException exception];

	if (_attributes == nil)
		_attributes = [[OFMutableArray alloc] init];







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







559
560
561
562
563
564
565































































566
567
568
569
570
571
572
{
	return [self of_XMLStringWithDefaultNS: defaultNS
				    namespaces: nil
				   indentation: indentation
					 level: 0];
}
































































- (void)addAttribute: (OFXMLAttribute *)attribute
{
	if (![attribute isKindOfClass: [OFXMLAttribute class]])
		@throw [OFInvalidArgumentException exception];

	if (_attributes == nil)
		_attributes = [[OFMutableArray alloc] init];

Modified src/OFXMLElementBuilder.h from [db177baac1] to [1d54fd3f38].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFXMLElementBuilder.m from [87c5fa2116] to [d48319175e].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFXMLNode+Private.h from [fcadbb17a0] to [d298829c4c].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFXMLNode.h from [5f2e542386] to [923d5f4802].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#import "OFObject.h"
#import "OFSerialization.h"

OF_ASSUME_NONNULL_BEGIN

@class OFXMLElement;

/**
 * @class OFXMLNode OFXMLNode.h ObjFW/OFXMLNode.h
 *
 * @brief A class which stores an XML element.
 */
@interface OFXMLNode: OFObject <OFCopying, OFSerialization>
{
	OF_RESERVE_IVARS(OFXMLNode, 4)
}

/**
 * @brief The contents of the node as a string value.
 *

|














<



<
<





|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

17
18
19


20
21
22
23
24
25
26
27
28
29
30
31
32
/*
 * Copyright (c) 2008-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 "OFObject.h"


OF_ASSUME_NONNULL_BEGIN



/**
 * @class OFXMLNode OFXMLNode.h ObjFW/OFXMLNode.h
 *
 * @brief A class which stores an XML element.
 */
@interface OFXMLNode: OFObject <OFCopying>
{
	OF_RESERVE_IVARS(OFXMLNode, 4)
}

/**
 * @brief The contents of the node as a string value.
 *
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
 * @throw OFUnboundNamespaceException The node uses a namespace that was not
 *				      bound to a prefix in a context where it
 *				      needs a prefix
 */
@property (readonly, nonatomic) OFString *XMLString;

- (instancetype)init OF_UNAVAILABLE;
- (instancetype)initWithSerialization: (OFXMLElement *)element OF_UNAVAILABLE;

/**
 * @brief The contents of the receiver as a `long long` value in the specified
 *	  base.
 *
 * @param base The base to use. If the base is 0, base 16 is assumed if the
 * 	       string starts with 0x (after stripping white spaces). If the







<







70
71
72
73
74
75
76

77
78
79
80
81
82
83
 * @throw OFUnboundNamespaceException The node uses a namespace that was not
 *				      bound to a prefix in a context where it
 *				      needs a prefix
 */
@property (readonly, nonatomic) OFString *XMLString;

- (instancetype)init OF_UNAVAILABLE;


/**
 * @brief The contents of the receiver as a `long long` value in the specified
 *	  base.
 *
 * @param base The base to use. If the base is 0, base 16 is assumed if the
 * 	       string starts with 0x (after stripping white spaces). If the

Modified src/OFXMLNode.m from [ae31a5d0f3] to [187861b96d].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
- (instancetype)of_init
{
	return [super init];
}

- (instancetype)init
{
	OF_INVALID_INIT_METHOD
}

- (instancetype)initWithSerialization: (OFXMLElement *)element
{
	OF_INVALID_INIT_METHOD
}

- (OFString *)stringValue
{
	OF_UNRECOGNIZED_SELECTOR
}







<
<
<
<
<







22
23
24
25
26
27
28





29
30
31
32
33
34
35
- (instancetype)of_init
{
	return [super init];
}

- (instancetype)init
{





	OF_INVALID_INIT_METHOD
}

- (OFString *)stringValue
{
	OF_UNRECOGNIZED_SELECTOR
}
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
}

- (OFString *)description
{
	return self.XMLString;
}

- (OFXMLElement *)XMLElementBySerializing
{
	OF_UNRECOGNIZED_SELECTOR
}

- (id)copy
{
	return [self retain];
}
@end







<
<
<
<
<





75
76
77
78
79
80
81





82
83
84
85
86
}

- (OFString *)description
{
	return self.XMLString;
}






- (id)copy
{
	return [self retain];
}
@end

Modified src/OFXMLParser.h from [89f07c26d5] to [6ec14e4d4c].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
 *
 * @param parser The parser which found a processing instruction
 * @param target The target of the processing instruction
 * @param text The text of the processing instruction
 */
-			  (void)parser: (OFXMLParser *)parser
  foundProcessingInstructionWithTarget: (OFString *)target
				  text: (OFString *)text;

/**
 * @brief This callback is called when the XML parser found the start of a new
 *	  tag.
 *
 * @param parser The parser which found a new tag
 * @param name The name of the tag which just started







|







39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
 *
 * @param parser The parser which found a processing instruction
 * @param target The target of the processing instruction
 * @param text The text of the processing instruction
 */
-			  (void)parser: (OFXMLParser *)parser
  foundProcessingInstructionWithTarget: (OFString *)target
				  text: (nullable OFString *)text;

/**
 * @brief This callback is called when the XML parser found the start of a new
 *	  tag.
 *
 * @param parser The parser which found a new tag
 * @param name The name of the tag which just started

Modified src/OFXMLParser.m from [7be6fc7234] to [70a137d545].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFXMLProcessingInstruction.h from [2e0c868afb] to [c9baffc912].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
56
57
58
59
60
61
62
63
64
65
66
67
 *
 * @param target The target for the processing instruction
 * @param text The text for the processing instruction
 * @return An initialized OFXMLProcessingInstruction
 */
- (instancetype)initWithTarget: (OFString *)target
			  text: (OFString *)text OF_DESIGNATED_INITIALIZER;

- (instancetype)initWithSerialization: (OFXMLElement *)element;
@end

OF_ASSUME_NONNULL_END







<
<



56
57
58
59
60
61
62


63
64
65
 *
 * @param target The target for the processing instruction
 * @param text The text for the processing instruction
 * @return An initialized OFXMLProcessingInstruction
 */
- (instancetype)initWithTarget: (OFString *)target
			  text: (OFString *)text OF_DESIGNATED_INITIALIZER;


@end

OF_ASSUME_NONNULL_END

Modified src/OFXMLProcessingInstruction.m from [98f7922e9f] to [c3be544acd].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#include <string.h>

#import "OFXMLProcessingInstruction.h"
#import "OFString.h"
#import "OFXMLAttribute.h"
#import "OFXMLElement.h"
#import "OFXMLNode+Private.h"

#import "OFInvalidArgumentException.h"

@implementation OFXMLProcessingInstruction
@synthesize target = _target, text = _text;


|




















<







1
2
3
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.
 */

#include "config.h"

#include <string.h>

#import "OFXMLProcessingInstruction.h"
#import "OFString.h"
#import "OFXMLAttribute.h"

#import "OFXMLNode+Private.h"

#import "OFInvalidArgumentException.h"

@implementation OFXMLProcessingInstruction
@synthesize target = _target, text = _text;

44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
		_target = [target copy];
		_text = [text copy];
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (instancetype)initWithSerialization: (OFXMLElement *)element
{
	@try {
		void *pool = objc_autoreleasePoolPush();
		OFXMLAttribute *targetAttr;

		if (![element.name isEqual: self.className] ||
		    ![element.namespace isEqual: OFSerializationNS])
			@throw [OFInvalidArgumentException exception];

		targetAttr = [element attributeForName: @"target"
					     namespace: OFSerializationNS];
		if (targetAttr.stringValue.length == 0)
			@throw [OFInvalidArgumentException exception];

		self = [self initWithTarget: targetAttr.stringValue
				       text: element.stringValue];

		objc_autoreleasePoolPop(pool);
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (void)dealloc
{
	[_target release];
	[_text release];







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







43
44
45
46
47
48
49



























50
51
52
53
54
55
56
		_target = [target copy];
		_text = [text copy];
	} @catch (id e) {
		[self release];
		@throw e;
	}




























	return self;
}

- (void)dealloc
{
	[_target release];
	[_text release];
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
		return [OFString stringWithFormat: @"<?%@?>", _target];
}

- (OFString *)description
{
	return self.XMLString;
}

- (OFXMLElement *)XMLElementBySerializing
{
	OFXMLElement *ret = [OFXMLElement elementWithName: self.className
						namespace: OFSerializationNS
					      stringValue: _text];
	void *pool = objc_autoreleasePoolPush();

	[ret addAttribute: [OFXMLAttribute attributeWithName: @"target"
						 stringValue: _target]];

	objc_autoreleasePoolPop(pool);

	return ret;
}
@end







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

106
107
108
109
110
111
112















113
		return [OFString stringWithFormat: @"<?%@?>", _target];
}

- (OFString *)description
{
	return self.XMLString;
}















@end

Modified src/OFZIPArchive.h from [b8f3f259b0] to [0e8d7ea161].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
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
#import "OFZIPArchiveEntry.h"

OF_ASSUME_NONNULL_BEGIN

@class OFArray OF_GENERIC(ObjectType);
@class OFMutableArray OF_GENERIC(ObjectType);
@class OFMutableDictionary OF_GENERIC(KeyType, ObjectType);

@class OFStream;























/**
 * @class OFZIPArchive OFZIPArchive.h ObjFW/OFZIPArchive.h
 *
 * @brief A class for accessing and manipulating ZIP files.
 */
OF_SUBCLASSING_RESTRICTED
@interface OFZIPArchive: OFObject
{
	OFStream *_stream;
#ifdef OF_ZIP_ARCHIVE_M
@public
#endif


	int64_t _offset;
@protected
	uint_least8_t _mode;
	uint32_t _diskNumber, _centralDirectoryDisk;


	uint64_t _centralDirectoryEntriesInDisk, _centralDirectoryEntries;
	uint64_t _centralDirectorySize;
	int64_t _centralDirectoryOffset;
	OFString *_Nullable _archiveComment;
#ifdef OF_ZIP_ARCHIVE_M
@public
#endif
	OFMutableArray OF_GENERIC(OFZIPArchiveEntry *) *_entries;
	OFMutableDictionary OF_GENERIC(OFString *, OFZIPArchiveEntry *)
	    *_pathToEntryMap;
	OFStream *_Nullable _lastReturnedStream;
}







/**
 * @brief The archive comment.
 */
@property OF_NULLABLE_PROPERTY (copy, nonatomic) OFString *archiveComment;

/**
 * @brief The entries in the central directory of the archive as an array of







>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>









<



>
>

<

|
>
>













>
>
>
>
>
>







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
#import "OFZIPArchiveEntry.h"

OF_ASSUME_NONNULL_BEGIN

@class OFArray OF_GENERIC(ObjectType);
@class OFMutableArray OF_GENERIC(ObjectType);
@class OFMutableDictionary OF_GENERIC(KeyType, ObjectType);
@class OFSeekableStream;
@class OFStream;
@class OFZIPArchive;

/**
 * @protocol OFZIPArchiveDelegate OFZIPArchive.h ObjFW/OFZIPArchive.h
 *
 * @brief A delegate for OFZIPArchive.
 */
@protocol OFZIPArchiveDelegate <OFObject>
@optional
/**
 * @brief A callback that is called when an @ref OFZIPArchive wants to read a
 *	  different archive part.
 *
 * @param archive The archive that wants to read another part
 * @param partNumber The number of the part the archive wants to read
 * @param lastPartNumber The number of the last archive part
 * @return The stream to read the needed part, or `nil` if no such part exists
 */
- (nullable OFSeekableStream *)archive: (OFZIPArchive *)archive
		     wantsPartNumbered: (unsigned int)partNumber
			lastPartNumber: (unsigned int)lastPartNumber;
@end

/**
 * @class OFZIPArchive OFZIPArchive.h ObjFW/OFZIPArchive.h
 *
 * @brief A class for accessing and manipulating ZIP files.
 */
OF_SUBCLASSING_RESTRICTED
@interface OFZIPArchive: OFObject
{

#ifdef OF_ZIP_ARCHIVE_M
@public
#endif
	OFObject <OFZIPArchiveDelegate> *_Nullable _delegate;
	OF_KINDOF(OFStream *) _stream;
	int64_t _offset;

	uint_least8_t _mode;
	uint32_t _diskNumber, _lastDiskNumber;
@protected
	uint32_t _centralDirectoryDisk;
	uint64_t _centralDirectoryEntriesInDisk, _centralDirectoryEntries;
	uint64_t _centralDirectorySize;
	int64_t _centralDirectoryOffset;
	OFString *_Nullable _archiveComment;
#ifdef OF_ZIP_ARCHIVE_M
@public
#endif
	OFMutableArray OF_GENERIC(OFZIPArchiveEntry *) *_entries;
	OFMutableDictionary OF_GENERIC(OFString *, OFZIPArchiveEntry *)
	    *_pathToEntryMap;
	OFStream *_Nullable _lastReturnedStream;
}

/**
 * @brief The delegate of the ZIP archive.
 */
@property OF_NULLABLE_PROPERTY (assign, nonatomic)
    OFObject <OFZIPArchiveDelegate> *delegate;

/**
 * @brief The archive comment.
 */
@property OF_NULLABLE_PROPERTY (copy, nonatomic) OFString *archiveComment;

/**
 * @brief The entries in the central directory of the archive as an array of
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
 * @throw OFInvalidFormatException The format is not that of a valid ZIP archive
 */
+ (instancetype)archiveWithStream: (OFStream *)stream mode: (OFString *)mode;

/**
 * @brief Creates a new OFZIPArchive object with the specified file.
 *
 * @param URI The URI to the ZIP file
 * @param mode The mode for the ZIP file. Valid modes are "r" for reading,
 *	       "w" for creating a new file and "a" for appending to an existing
 *	       archive.
 * @return A new, autoreleased OFZIPArchive
 * @throw OFInvalidFormatException The format is not that of a valid ZIP archive
 */
+ (instancetype)archiveWithURI: (OFURI *)URI mode: (OFString *)mode;

/**
 * @brief Creates a URI for accessing a the specified file within the specified
 *	  ZIP archive.
 *
 * @param path The path of the file within the archive
 * @param URI The URI of the archive
 * @return A URI for accessing the specified file within the specified ZIP
 *	   archive
 */
+ (OFURI *)URIForFilePath: (OFString *)path inArchiveWithURI: (OFURI *)URI;

- (instancetype)init OF_UNAVAILABLE;

/**
 * @brief Initializes an already allocated OFZIPArchive object with the
 *	  specified stream.
 *







|






|


|
|


|
|


|







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
 * @throw OFInvalidFormatException The format is not that of a valid ZIP archive
 */
+ (instancetype)archiveWithStream: (OFStream *)stream mode: (OFString *)mode;

/**
 * @brief Creates a new OFZIPArchive object with the specified file.
 *
 * @param IRI The IRI to the ZIP file
 * @param mode The mode for the ZIP file. Valid modes are "r" for reading,
 *	       "w" for creating a new file and "a" for appending to an existing
 *	       archive.
 * @return A new, autoreleased OFZIPArchive
 * @throw OFInvalidFormatException The format is not that of a valid ZIP archive
 */
+ (instancetype)archiveWithIRI: (OFIRI *)IRI mode: (OFString *)mode;

/**
 * @brief Creates an IRI for accessing a the specified file within the
 *	  specified ZIP archive.
 *
 * @param path The path of the file within the archive
 * @param IRI The IRI of the archive
 * @return An IRI for accessing the specified file within the specified ZIP
 *	   archive
 */
+ (OFIRI *)IRIForFilePath: (OFString *)path inArchiveWithIRI: (OFIRI *)IRI;

- (instancetype)init OF_UNAVAILABLE;

/**
 * @brief Initializes an already allocated OFZIPArchive object with the
 *	  specified stream.
 *
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
- (instancetype)initWithStream: (OFStream *)stream
			  mode: (OFString *)mode OF_DESIGNATED_INITIALIZER;

/**
 * @brief Initializes an already allocated OFZIPArchive object with the
 *	  specified file.
 *
 * @param URI The URI to the ZIP file
 * @param mode The mode for the ZIP file. Valid modes are "r" for reading,
 *	       "w" for creating a new file and "a" for appending to an existing
 *	       archive.
 * @return An initialized OFZIPArchive
 * @throw OFInvalidFormatException The format is not that of a valid ZIP archive
 */
- (instancetype)initWithURI: (OFURI *)URI mode: (OFString *)mode;

/**
 * @brief Returns a stream for reading the specified file from the archive.
 *
 * @note This method is only available in read mode.
 *
 * @note The returned stream conforms to @ref OFReadyForReadingObserving if the







|






|







153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
- (instancetype)initWithStream: (OFStream *)stream
			  mode: (OFString *)mode OF_DESIGNATED_INITIALIZER;

/**
 * @brief Initializes an already allocated OFZIPArchive object with the
 *	  specified file.
 *
 * @param IRI The IRI to the ZIP file
 * @param mode The mode for the ZIP file. Valid modes are "r" for reading,
 *	       "w" for creating a new file and "a" for appending to an existing
 *	       archive.
 * @return An initialized OFZIPArchive
 * @throw OFInvalidFormatException The format is not that of a valid ZIP archive
 */
- (instancetype)initWithIRI: (OFIRI *)IRI mode: (OFString *)mode;

/**
 * @brief Returns a stream for reading the specified file from the archive.
 *
 * @note This method is only available in read mode.
 *
 * @note The returned stream conforms to @ref OFReadyForReadingObserving if the
184
185
186
187
188
189
190
191


192
193
194
195
196
197
198
199
200
 *		  * The uncompressed size.
 *		  * The CRC32.
 *		  * Bit 3 and 11 of the general purpose bit flag.
 * @return A stream for writing the specified entry to the archive
 * @throw OFNotOpenException The archive is not open
 * @throw OFInvalidArgumentException The archive is not in write mode
 * @throw OFOpenItemFailedException Opening the specified file within the
 *				    archive failed. If @ref errNo is `EEXIST`,


 *				    because there is already a file with the
 *				    same name in the archive.
 * @throw OFNotImplementedException The desired compression method is not
 *				    implemented
 */
- (OFStream *)streamForWritingEntry: (OFZIPArchiveEntry *)entry;

/**
 * @brief Closes the OFZIPArchive.







|
>
>
|
|







215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
 *		  * The uncompressed size.
 *		  * The CRC32.
 *		  * Bit 3 and 11 of the general purpose bit flag.
 * @return A stream for writing the specified entry to the archive
 * @throw OFNotOpenException The archive is not open
 * @throw OFInvalidArgumentException The archive is not in write mode
 * @throw OFOpenItemFailedException Opening the specified file within the
 *				    archive failed. If
 *				    @ref OFOpenItemFailedException#errNo is
 *				    `EEXIST`, it failed because there is
 *				    already a file with the same name in the
 *				    archive.
 * @throw OFNotImplementedException The desired compression method is not
 *				    implemented
 */
- (OFStream *)streamForWritingEntry: (OFZIPArchiveEntry *)entry;

/**
 * @brief Closes the OFZIPArchive.

Modified src/OFZIPArchive.m from [3d9576934f] to [1f22a87e08].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
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
#include "config.h"

#include <errno.h>

#import "OFZIPArchive.h"
#import "OFZIPArchiveEntry.h"
#import "OFZIPArchiveEntry+Private.h"
#import "OFArchiveURIHandler.h"
#import "OFArray.h"
#import "OFCRC32.h"
#import "OFData.h"
#import "OFDictionary.h"


#import "OFInflate64Stream.h"
#import "OFInflateStream.h"
#import "OFSeekableStream.h"
#import "OFStream.h"
#import "OFURI.h"
#import "OFURIHandler.h"

#import "OFChecksumMismatchException.h"
#import "OFInvalidArgumentException.h"
#import "OFInvalidFormatException.h"
#import "OFNotImplementedException.h"
#import "OFNotOpenException.h"
#import "OFOpenItemFailedException.h"
#import "OFOutOfRangeException.h"
#import "OFSeekFailedException.h"
#import "OFTruncatedDataException.h"
#import "OFUnsupportedVersionException.h"
#import "OFWriteFailedException.h"

/*
 * FIXME: Current limitations:
 *  - Split archives are not supported.
 *  - Encrypted files cannot be read.
 */

enum {
	modeRead,
	modeWrite,
	modeAppend







|




>
>




<
<














|
<







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
#include "config.h"

#include <errno.h>

#import "OFZIPArchive.h"
#import "OFZIPArchiveEntry.h"
#import "OFZIPArchiveEntry+Private.h"
#import "OFArchiveIRIHandler.h"
#import "OFArray.h"
#import "OFCRC32.h"
#import "OFData.h"
#import "OFDictionary.h"
#import "OFIRI.h"
#import "OFIRIHandler.h"
#import "OFInflate64Stream.h"
#import "OFInflateStream.h"
#import "OFSeekableStream.h"
#import "OFStream.h"



#import "OFChecksumMismatchException.h"
#import "OFInvalidArgumentException.h"
#import "OFInvalidFormatException.h"
#import "OFNotImplementedException.h"
#import "OFNotOpenException.h"
#import "OFOpenItemFailedException.h"
#import "OFOutOfRangeException.h"
#import "OFSeekFailedException.h"
#import "OFTruncatedDataException.h"
#import "OFUnsupportedVersionException.h"
#import "OFWriteFailedException.h"

/*
 * TODO: Current limitations:

 *  - Encrypted files cannot be read.
 */

enum {
	modeRead,
	modeWrite,
	modeAppend
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
- (bool)matchesEntry: (OFZIPArchiveEntry *)entry;
@end

OF_DIRECT_MEMBERS
@interface OFZIPArchiveFileReadStream: OFStream
{
	OFZIPArchive *_archive;

	OFStream *_stream, *_decompressedStream;
	OFZIPArchiveEntry *_entry;
	unsigned long long _toRead;
	uint32_t _CRC32;
	bool _atEndOfStream;
}

- (instancetype)of_initWithArchive: (OFZIPArchive *)archive
			    stream: (OFStream *)stream
			     entry: (OFZIPArchiveEntry *)entry;
@end

OF_DIRECT_MEMBERS
@interface OFZIPArchiveFileWriteStream: OFStream
{
	OFZIPArchive *_archive;
	OFStream *_stream;
	uint32_t _CRC32;

@public
	unsigned long long _bytesWritten;
	OFMutableZIPArchiveEntry *_entry;
}

- (instancetype)of_initWithArchive: (OFZIPArchive *)archive
			    stream: (OFStream *)stream
			     entry: (OFMutableZIPArchiveEntry *)entry;


@end

uint32_t
OFZIPArchiveReadField32(const uint8_t **data, uint16_t *size)
{
	uint32_t field = 0;








>
|















|

>







|
>
>







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
- (bool)matchesEntry: (OFZIPArchiveEntry *)entry;
@end

OF_DIRECT_MEMBERS
@interface OFZIPArchiveFileReadStream: OFStream
{
	OFZIPArchive *_archive;
	OFZIPArchiveEntryCompressionMethod _compressionMethod;
	OF_KINDOF(OFStream *) _decompressedStream;
	OFZIPArchiveEntry *_entry;
	unsigned long long _toRead;
	uint32_t _CRC32;
	bool _atEndOfStream;
}

- (instancetype)of_initWithArchive: (OFZIPArchive *)archive
			    stream: (OFStream *)stream
			     entry: (OFZIPArchiveEntry *)entry;
@end

OF_DIRECT_MEMBERS
@interface OFZIPArchiveFileWriteStream: OFStream
{
	OFZIPArchive *_archive;
	OF_KINDOF(OFStream *) _stream;
	uint32_t _CRC32;
	OFStreamOffset _CRC32Offset, _size64Offset;
@public
	unsigned long long _bytesWritten;
	OFMutableZIPArchiveEntry *_entry;
}

- (instancetype)of_initWithArchive: (OFZIPArchive *)archive
			    stream: (OFStream *)stream
			     entry: (OFMutableZIPArchiveEntry *)entry
		       CRC32Offset: (OFStreamOffset)CRC32Offset
		      size64Offset: (OFStreamOffset)size64Offset;
@end

uint32_t
OFZIPArchiveReadField32(const uint8_t **data, uint16_t *size)
{
	uint32_t field = 0;

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

	*data += 8;
	*size -= 8;

	return field;
}




static void
seekOrThrowInvalidFormat(OFSeekableStream *stream,
    OFStreamOffset offset, OFSeekWhence whence)
{




















	@try {
		[stream seekToOffset: offset whence: whence];
	} @catch (OFSeekFailedException *e) {
		if (e.errNo == EINVAL)
			@throw [OFInvalidFormatException exception];

		@throw e;
	}
}

@implementation OFZIPArchive
@synthesize archiveComment = _archiveComment;

+ (instancetype)archiveWithStream: (OFStream *)stream mode: (OFString *)mode
{
	return [[[self alloc] initWithStream: stream mode: mode] autorelease];
}

+ (instancetype)archiveWithURI: (OFURI *)URI mode: (OFString *)mode
{
	return [[[self alloc] initWithURI: URI mode: mode] autorelease];
}

+ (OFURI *)URIForFilePath: (OFString *)path inArchiveWithURI: (OFURI *)URI
{
	return OFArchiveURIHandlerURIForFileInArchive(@"zip", path, URI);
}

- (instancetype)init
{
	OF_INVALID_INIT_METHOD
}








>
>
>

|


>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

|








<
<
<





|

|


|

|







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

	*data += 8;
	*size -= 8;

	return field;
}

@implementation OFZIPArchive
@synthesize delegate = _delegate, archiveComment = _archiveComment;

static void
seekOrThrowInvalidFormat(OFZIPArchive *archive, const uint32_t *diskNumber,
    OFStreamOffset offset, OFSeekWhence whence)
{
	if (diskNumber != NULL && *diskNumber != archive->_diskNumber) {
		OFStream *oldStream = archive->_stream;
		OFSeekableStream *stream;

		if (archive->_mode != modeRead ||
		    *diskNumber > archive->_lastDiskNumber)
			@throw [OFInvalidFormatException exception];

		stream = [archive->_delegate archive: archive
				   wantsPartNumbered: *diskNumber
				      lastPartNumber: archive->_lastDiskNumber];

		if (stream == nil)
			@throw [OFInvalidFormatException exception];

		archive->_diskNumber = *diskNumber;
		archive->_stream = [stream retain];
		[oldStream release];
	}

	@try {
		[archive->_stream seekToOffset: offset whence: whence];
	} @catch (OFSeekFailedException *e) {
		if (e.errNo == EINVAL)
			@throw [OFInvalidFormatException exception];

		@throw e;
	}
}




+ (instancetype)archiveWithStream: (OFStream *)stream mode: (OFString *)mode
{
	return [[[self alloc] initWithStream: stream mode: mode] autorelease];
}

+ (instancetype)archiveWithIRI: (OFIRI *)IRI mode: (OFString *)mode
{
	return [[[self alloc] initWithIRI: IRI mode: mode] autorelease];
}

+ (OFIRI *)IRIForFilePath: (OFString *)path inArchiveWithIRI: (OFIRI *)IRI
{
	return OFArchiveIRIHandlerIRIForFileInArchive(@"zip", path, IRI);
}

- (instancetype)init
{
	OF_INVALID_INIT_METHOD
}

208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250

			[self of_readZIPInfo];
			[self of_readEntries];
		}

		if (_mode == modeAppend) {
			_offset = _centralDirectoryOffset;
			seekOrThrowInvalidFormat((OFSeekableStream *)_stream,
			    (OFStreamOffset)_offset, OFSeekSet);
		}
	} @catch (id e) {
		/*
		 * If we are in write or append mode, we do not want -[close]
		 * to write anything to it on error - after all, it might not
		 * be a ZIP file which we would destroy otherwise.
		 */
		[_stream release];
		_stream = nil;

		[self release];
		@throw e;
	}

	return self;
}

- (instancetype)initWithURI: (OFURI *)URI mode: (OFString *)mode
{
	void *pool = objc_autoreleasePoolPush();
	OFStream *stream;

	@try {
		if ([mode isEqual: @"a"])
			stream = [OFURIHandler openItemAtURI: URI mode: @"r+"];
		else
			stream = [OFURIHandler openItemAtURI: URI mode: mode];
	} @catch (id e) {
		[self release];
		@throw e;
	}

	self = [self initWithStream: stream mode: mode];








|


















|






|

|







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

			[self of_readZIPInfo];
			[self of_readEntries];
		}

		if (_mode == modeAppend) {
			_offset = _centralDirectoryOffset;
			seekOrThrowInvalidFormat(self, NULL,
			    (OFStreamOffset)_offset, OFSeekSet);
		}
	} @catch (id e) {
		/*
		 * If we are in write or append mode, we do not want -[close]
		 * to write anything to it on error - after all, it might not
		 * be a ZIP file which we would destroy otherwise.
		 */
		[_stream release];
		_stream = nil;

		[self release];
		@throw e;
	}

	return self;
}

- (instancetype)initWithIRI: (OFIRI *)IRI mode: (OFString *)mode
{
	void *pool = objc_autoreleasePoolPush();
	OFStream *stream;

	@try {
		if ([mode isEqual: @"a"])
			stream = [OFIRIHandler openItemAtIRI: IRI mode: @"r+"];
		else
			stream = [OFIRIHandler openItemAtIRI: IRI mode: mode];
	} @catch (id e) {
		[self release];
		@throw e;
	}

	self = [self initWithStream: stream mode: mode];

270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
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
{
	void *pool = objc_autoreleasePoolPush();
	uint16_t commentLength;
	OFStreamOffset offset = -22;
	bool valid = false;

	do {
		seekOrThrowInvalidFormat((OFSeekableStream *)_stream,
		    offset, OFSeekEnd);

		if ([_stream readLittleEndianInt32] == 0x06054B50) {
			valid = true;
			break;
		}
	} while (--offset >= -65557);

	if (!valid)
		@throw [OFInvalidFormatException exception];

	_diskNumber = [_stream readLittleEndianInt16];
	_centralDirectoryDisk = [_stream readLittleEndianInt16];
	_centralDirectoryEntriesInDisk = [_stream readLittleEndianInt16];
	_centralDirectoryEntries = [_stream readLittleEndianInt16];
	_centralDirectorySize = [_stream readLittleEndianInt32];
	_centralDirectoryOffset = [_stream readLittleEndianInt32];

	commentLength = [_stream readLittleEndianInt16];
	_archiveComment = [[_stream
	    readStringWithLength: commentLength
			encoding: OFStringEncodingCodepage437] copy];

	if (_diskNumber == 0xFFFF ||
	    _centralDirectoryDisk == 0xFFFF ||
	    _centralDirectoryEntriesInDisk == 0xFFFF ||
	    _centralDirectoryEntries == 0xFFFF ||
	    _centralDirectorySize == 0xFFFFFFFF ||
	    _centralDirectoryOffset == 0xFFFFFFFF) {

		int64_t offset64;
		uint64_t size;

		seekOrThrowInvalidFormat((OFSeekableStream *)_stream,
		    offset - 20, OFSeekEnd);

		if ([_stream readLittleEndianInt32] != 0x07064B50) {
			objc_autoreleasePoolPop(pool);
			return;
		}

		/*
		 * FIXME: Handle number of the disk containing ZIP64 end of
		 * central directory record.
		 */
		[_stream readLittleEndianInt32];
		offset64 = [_stream readLittleEndianInt64];





		if (offset64 < 0 || (OFStreamOffset)offset64 != offset64)
			@throw [OFOutOfRangeException exception];

		seekOrThrowInvalidFormat((OFSeekableStream *)_stream,
		    (OFStreamOffset)offset64, OFSeekSet);

		if ([_stream readLittleEndianInt32] != 0x06064B50)
			@throw [OFInvalidFormatException exception];

		size = [_stream readLittleEndianInt64];
		if (size < 44)
			@throw [OFInvalidFormatException exception];

		/* version made by */
		[_stream readLittleEndianInt16];
		/* version needed to extract */
		[_stream readLittleEndianInt16];

		_diskNumber = [_stream readLittleEndianInt32];


		_centralDirectoryDisk = [_stream readLittleEndianInt32];
		_centralDirectoryEntriesInDisk =
		    [_stream readLittleEndianInt64];
		_centralDirectoryEntries = [_stream readLittleEndianInt64];
		_centralDirectorySize = [_stream readLittleEndianInt64];
		_centralDirectoryOffset = [_stream readLittleEndianInt64];








<
|










|











|





>



<
|










|

>
>
>
>




|














|
>
>







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
{
	void *pool = objc_autoreleasePoolPush();
	uint16_t commentLength;
	OFStreamOffset offset = -22;
	bool valid = false;

	do {

		seekOrThrowInvalidFormat(self, NULL, offset, OFSeekEnd);

		if ([_stream readLittleEndianInt32] == 0x06054B50) {
			valid = true;
			break;
		}
	} while (--offset >= -65557);

	if (!valid)
		@throw [OFInvalidFormatException exception];

	_diskNumber = _lastDiskNumber = [_stream readLittleEndianInt16];
	_centralDirectoryDisk = [_stream readLittleEndianInt16];
	_centralDirectoryEntriesInDisk = [_stream readLittleEndianInt16];
	_centralDirectoryEntries = [_stream readLittleEndianInt16];
	_centralDirectorySize = [_stream readLittleEndianInt32];
	_centralDirectoryOffset = [_stream readLittleEndianInt32];

	commentLength = [_stream readLittleEndianInt16];
	_archiveComment = [[_stream
	    readStringWithLength: commentLength
			encoding: OFStringEncodingCodepage437] copy];

	if (_lastDiskNumber == 0xFFFF ||
	    _centralDirectoryDisk == 0xFFFF ||
	    _centralDirectoryEntriesInDisk == 0xFFFF ||
	    _centralDirectoryEntries == 0xFFFF ||
	    _centralDirectorySize == 0xFFFFFFFF ||
	    _centralDirectoryOffset == 0xFFFFFFFF) {
		uint32_t diskNumber;
		int64_t offset64;
		uint64_t size;


		seekOrThrowInvalidFormat(self, NULL, offset - 20, OFSeekEnd);

		if ([_stream readLittleEndianInt32] != 0x07064B50) {
			objc_autoreleasePoolPop(pool);
			return;
		}

		/*
		 * FIXME: Handle number of the disk containing ZIP64 end of
		 * central directory record.
		 */
		diskNumber = [_stream readLittleEndianInt32];
		offset64 = [_stream readLittleEndianInt64];
		_lastDiskNumber = [_stream readLittleEndianInt32];
		if (_lastDiskNumber == 0)
			@throw [OFInvalidFormatException exception];
		_lastDiskNumber--;

		if (offset64 < 0 || (OFStreamOffset)offset64 != offset64)
			@throw [OFOutOfRangeException exception];

		seekOrThrowInvalidFormat(self, &diskNumber,
		    (OFStreamOffset)offset64, OFSeekSet);

		if ([_stream readLittleEndianInt32] != 0x06064B50)
			@throw [OFInvalidFormatException exception];

		size = [_stream readLittleEndianInt64];
		if (size < 44)
			@throw [OFInvalidFormatException exception];

		/* version made by */
		[_stream readLittleEndianInt16];
		/* version needed to extract */
		[_stream readLittleEndianInt16];

		if ([_stream readLittleEndianInt32] != _diskNumber)
			@throw [OFInvalidFormatException exception];

		_centralDirectoryDisk = [_stream readLittleEndianInt32];
		_centralDirectoryEntriesInDisk =
		    [_stream readLittleEndianInt64];
		_centralDirectoryEntries = [_stream readLittleEndianInt64];
		_centralDirectorySize = [_stream readLittleEndianInt64];
		_centralDirectoryOffset = [_stream readLittleEndianInt64];

361
362
363
364
365
366
367
368
369
370
371
372

































373
374
375
376
377
378
379
{
	void *pool = objc_autoreleasePoolPush();

	if (_centralDirectoryOffset < 0 ||
	    (OFStreamOffset)_centralDirectoryOffset != _centralDirectoryOffset)
		@throw [OFOutOfRangeException exception];

	seekOrThrowInvalidFormat((OFSeekableStream *)_stream,
	    (OFStreamOffset)_centralDirectoryOffset, OFSeekSet);

	for (size_t i = 0; i < _centralDirectoryEntries; i++) {
		OFZIPArchiveEntry *entry = [[[OFZIPArchiveEntry alloc]

































		    of_initWithStream: _stream] autorelease];

		if ([_pathToEntryMap objectForKey: entry.fileName] != nil)
			@throw [OFInvalidFormatException exception];

		[_entries addObject: entry];
		[_pathToEntryMap setObject: entry forKey: entry.fileName];







|



|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
{
	void *pool = objc_autoreleasePoolPush();

	if (_centralDirectoryOffset < 0 ||
	    (OFStreamOffset)_centralDirectoryOffset != _centralDirectoryOffset)
		@throw [OFOutOfRangeException exception];

	seekOrThrowInvalidFormat(self, &_centralDirectoryDisk,
	    (OFStreamOffset)_centralDirectoryOffset, OFSeekSet);

	for (size_t i = 0; i < _centralDirectoryEntries; i++) {
		OFZIPArchiveEntry *entry;
		char buffer;

		/*
		 * The stream might have 0 bytes left to read, but might not
		 * realize that before a read is attempted, where it will then
		 * return a length of 0. But OFZIPArchiveEntry expects to be
		 * able to read the entire entry and will then throw an
		 * OFTruncatedDataException. Therefore, try to peek one byte to
		 * make sure the stream realizes that it's at the end.
		 */
		if ([_stream readIntoBuffer: &buffer length: 1] == 1)
			[_stream unreadFromBuffer: &buffer length: 1];

		if ([_stream isAtEndOfStream]) {
			OFStream *oldStream = _stream;
			OFSeekableStream *stream;

			if (_diskNumber >= _lastDiskNumber)
				@throw [OFTruncatedDataException exception];

			stream = [_delegate archive: self
				  wantsPartNumbered: _diskNumber + 1
				     lastPartNumber: _lastDiskNumber];

			if (stream == nil)
				@throw [OFInvalidFormatException exception];

			_diskNumber++;
			_stream = [stream retain];
			[oldStream release];
		}

		entry = [[[OFZIPArchiveEntry alloc]
		    of_initWithStream: _stream] autorelease];

		if ([_pathToEntryMap objectForKey: entry.fileName] != nil)
			@throw [OFInvalidFormatException exception];

		[_entries addObject: entry];
		[_pathToEntryMap setObject: entry forKey: entry.fileName];
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
}

- (OFStream *)streamForReadingFile: (OFString *)path
{
	void *pool = objc_autoreleasePoolPush();
	OFZIPArchiveEntry *entry;
	OFZIPArchiveLocalFileHeader *localFileHeader;

	int64_t offset64;

	if (_stream == nil)
		@throw [OFNotOpenException exceptionWithObject: self];

	if (_mode != modeRead)
		@throw [OFInvalidArgumentException exception];

	if ((entry = [_pathToEntryMap objectForKey: path]) == nil)
		@throw [OFOpenItemFailedException exceptionWithPath: path
							       mode: @"r"
							      errNo: ENOENT];

	@try {
		[_lastReturnedStream close];
	} @catch (OFNotOpenException *e) {
		/* Might have already been closed by the user - that's fine. */
	}
	_lastReturnedStream = nil;


	offset64 = entry.of_localFileHeaderOffset;
	if (offset64 < 0 || (OFStreamOffset)offset64 != offset64)
		@throw [OFOutOfRangeException exception];

	seekOrThrowInvalidFormat((OFSeekableStream *)_stream,
	    (OFStreamOffset)offset64, OFSeekSet);
	localFileHeader = [[[OFZIPArchiveLocalFileHeader alloc]
	    initWithStream: _stream] autorelease];

	if (![localFileHeader matchesEntry: entry])
		@throw [OFInvalidFormatException exception];








>




















>




|







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
}

- (OFStream *)streamForReadingFile: (OFString *)path
{
	void *pool = objc_autoreleasePoolPush();
	OFZIPArchiveEntry *entry;
	OFZIPArchiveLocalFileHeader *localFileHeader;
	uint32_t startDiskNumber;
	int64_t offset64;

	if (_stream == nil)
		@throw [OFNotOpenException exceptionWithObject: self];

	if (_mode != modeRead)
		@throw [OFInvalidArgumentException exception];

	if ((entry = [_pathToEntryMap objectForKey: path]) == nil)
		@throw [OFOpenItemFailedException exceptionWithPath: path
							       mode: @"r"
							      errNo: ENOENT];

	@try {
		[_lastReturnedStream close];
	} @catch (OFNotOpenException *e) {
		/* Might have already been closed by the user - that's fine. */
	}
	_lastReturnedStream = nil;

	startDiskNumber = entry.of_startDiskNumber;
	offset64 = entry.of_localFileHeaderOffset;
	if (offset64 < 0 || (OFStreamOffset)offset64 != offset64)
		@throw [OFOutOfRangeException exception];

	seekOrThrowInvalidFormat(self, &startDiskNumber,
	    (OFStreamOffset)offset64, OFSeekSet);
	localFileHeader = [[[OFZIPArchiveLocalFileHeader alloc]
	    initWithStream: _stream] autorelease];

	if (![localFileHeader matchesEntry: entry])
		@throw [OFInvalidFormatException exception];

461
462
463
464
465
466
467
468
469
470
471
472


473
474
475
476
477
478
479
			 entry: entry] autorelease];

	return _lastReturnedStream;
}

- (OFStream *)streamForWritingEntry: (OFZIPArchiveEntry *)entry_
{
	/* TODO: Avoid data descriptor when _stream is an OFSeekableStream */
	int64_t offsetAdd = 0;
	void *pool;
	OFMutableZIPArchiveEntry *entry;
	OFString *fileName;


	OFData *extraField;
	uint16_t fileNameLength, extraFieldLength;

	if (_stream == nil)
		@throw [OFNotOpenException exceptionWithObject: self];

	if (_mode != modeWrite && _mode != modeAppend)







<




>
>







524
525
526
527
528
529
530

531
532
533
534
535
536
537
538
539
540
541
542
543
			 entry: entry] autorelease];

	return _lastReturnedStream;
}

- (OFStream *)streamForWritingEntry: (OFZIPArchiveEntry *)entry_
{

	int64_t offsetAdd = 0;
	void *pool;
	OFMutableZIPArchiveEntry *entry;
	OFString *fileName;
	bool seekable;
	OFStreamOffset CRC32Offset = 0, size64Offset = 0;
	OFData *extraField;
	uint16_t fileNameLength, extraFieldLength;

	if (_stream == nil)
		@throw [OFNotOpenException exceptionWithObject: self];

	if (_mode != modeWrite && _mode != modeAppend)
503
504
505
506
507
508
509


510
511
512
513
514
515
516
517
518
519
520
521
522
523
524


525
526
527
528
529
530
531
532
533
534
535
536
537
538


539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555


556
557
558
559
560
561
562
	fileNameLength = fileName.UTF8StringLength;
	extraField = entry.extraField;
	extraFieldLength = extraField.count;

	if (UINT16_MAX - extraFieldLength < 20)
		@throw [OFOutOfRangeException exception];



	entry.versionMadeBy = (entry.versionMadeBy & 0xFF00) | 45;
	entry.minVersionNeeded = (entry.minVersionNeeded & 0xFF00) | 45;
	entry.compressedSize = 0;
	entry.uncompressedSize = 0;
	entry.CRC32 = 0;
	entry.generalPurposeBitFlag |= (1u << 3) | (1u << 11);
	entry.of_localFileHeaderOffset = _offset;

	[_stream writeLittleEndianInt32: 0x04034B50];
	[_stream writeLittleEndianInt16: entry.minVersionNeeded];
	[_stream writeLittleEndianInt16: entry.generalPurposeBitFlag];
	[_stream writeLittleEndianInt16: entry.compressionMethod];
	[_stream writeLittleEndianInt16: entry.of_lastModifiedFileTime];
	[_stream writeLittleEndianInt16: entry.of_lastModifiedFileDate];
	/* We use the data descriptor */


	[_stream writeLittleEndianInt32: 0];
	/* We use ZIP64 */
	[_stream writeLittleEndianInt32: 0xFFFFFFFF];
	[_stream writeLittleEndianInt32: 0xFFFFFFFF];
	[_stream writeLittleEndianInt16: fileNameLength];
	[_stream writeLittleEndianInt16: extraFieldLength + 20];
	offsetAdd += 4 + (5 * 2) + (3 * 4) + (2 * 2);

	[_stream writeString: fileName];
	offsetAdd += fileNameLength;

	[_stream writeLittleEndianInt16: OFZIPArchiveEntryExtraFieldTagZIP64];
	[_stream writeLittleEndianInt16: 16];
	/* We use the data descriptor */


	[_stream writeLittleEndianInt64: 0];
	[_stream writeLittleEndianInt64: 0];
	offsetAdd += (2 * 2) + (2 * 8);

	if (extraField != nil)
		[_stream writeData: extraField];
	offsetAdd += extraFieldLength;

	if (INT64_MAX - _offset < offsetAdd)
		@throw [OFOutOfRangeException exception];

	_offset += offsetAdd;

	_lastReturnedStream = [[OFZIPArchiveFileWriteStream alloc]
	    of_initWithArchive: self
			stream: _stream
			 entry: entry];



	objc_autoreleasePoolPop(pool);

	return [_lastReturnedStream autorelease];
}

- (void)of_writeCentralDirectory







>
>





|








|
>
>













|
>
>
















|
>
>







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
	fileNameLength = fileName.UTF8StringLength;
	extraField = entry.extraField;
	extraFieldLength = extraField.count;

	if (UINT16_MAX - extraFieldLength < 20)
		@throw [OFOutOfRangeException exception];

	seekable = [_stream isKindOfClass: [OFSeekableStream class]];

	entry.versionMadeBy = (entry.versionMadeBy & 0xFF00) | 45;
	entry.minVersionNeeded = (entry.minVersionNeeded & 0xFF00) | 45;
	entry.compressedSize = 0;
	entry.uncompressedSize = 0;
	entry.CRC32 = 0;
	entry.generalPurposeBitFlag |= (seekable ? 0 : (1u << 3)) | (1u << 11);
	entry.of_localFileHeaderOffset = _offset;

	[_stream writeLittleEndianInt32: 0x04034B50];
	[_stream writeLittleEndianInt16: entry.minVersionNeeded];
	[_stream writeLittleEndianInt16: entry.generalPurposeBitFlag];
	[_stream writeLittleEndianInt16: entry.compressionMethod];
	[_stream writeLittleEndianInt16: entry.of_lastModifiedFileTime];
	[_stream writeLittleEndianInt16: entry.of_lastModifiedFileDate];
	/* Written later or data descriptor used instead */
	if (seekable)
		CRC32Offset = [_stream seekToOffset: 0 whence: OFSeekCurrent];
	[_stream writeLittleEndianInt32: 0];
	/* We use ZIP64 */
	[_stream writeLittleEndianInt32: 0xFFFFFFFF];
	[_stream writeLittleEndianInt32: 0xFFFFFFFF];
	[_stream writeLittleEndianInt16: fileNameLength];
	[_stream writeLittleEndianInt16: extraFieldLength + 20];
	offsetAdd += 4 + (5 * 2) + (3 * 4) + (2 * 2);

	[_stream writeString: fileName];
	offsetAdd += fileNameLength;

	[_stream writeLittleEndianInt16: OFZIPArchiveEntryExtraFieldTagZIP64];
	[_stream writeLittleEndianInt16: 16];
	/* Written later or data descriptor used instead */
	if (seekable)
		size64Offset = [_stream seekToOffset: 0 whence: OFSeekCurrent];
	[_stream writeLittleEndianInt64: 0];
	[_stream writeLittleEndianInt64: 0];
	offsetAdd += (2 * 2) + (2 * 8);

	if (extraField != nil)
		[_stream writeData: extraField];
	offsetAdd += extraFieldLength;

	if (INT64_MAX - _offset < offsetAdd)
		@throw [OFOutOfRangeException exception];

	_offset += offsetAdd;

	_lastReturnedStream = [[OFZIPArchiveFileWriteStream alloc]
	    of_initWithArchive: self
			stream: _stream
			 entry: entry
		   CRC32Offset: CRC32Offset
		  size64Offset: size64Offset];

	objc_autoreleasePoolPop(pool);

	return [_lastReturnedStream autorelease];
}

- (void)of_writeCentralDirectory
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
			    stream: (OFStream *)stream
			     entry: (OFZIPArchiveEntry *)entry
{
	self = [super init];

	@try {
		_archive = [archive retain];
		_stream = [stream retain];

		switch (entry.compressionMethod) {
		case OFZIPArchiveEntryCompressionMethodNone:
			_decompressedStream = [stream retain];
			break;
		case OFZIPArchiveEntryCompressionMethodDeflate:
			_decompressedStream = [[OFInflateStream alloc]
			    initWithStream: stream];
			break;
		case OFZIPArchiveEntryCompressionMethodDeflate64:
			_decompressedStream = [[OFInflate64Stream alloc]
			    initWithStream: stream];
			break;
		default:
			@throw [OFNotImplementedException
			    exceptionWithSelector: _cmd
					   object: nil];
		}

		_entry = [entry copy];
		_toRead = entry.uncompressedSize;
		_CRC32 = ~0;
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (void)dealloc
{
	if (_stream != nil || _decompressedStream != nil)
		[self close];

	[_entry release];

	if (_archive->_lastReturnedStream == self)
		_archive->_lastReturnedStream = nil;

	[_archive release];

	[super dealloc];
}

- (bool)lowlevelIsAtEndOfStream
{
	if (_stream == nil)
		@throw [OFNotOpenException exceptionWithObject: self];

	return _atEndOfStream;
}

- (size_t)lowlevelReadIntoBuffer: (void *)buffer length: (size_t)length
{
	size_t ret;

	if (_stream == nil)
		@throw [OFNotOpenException exceptionWithObject: self];

	if (_atEndOfStream)
		return 0;


	if (_stream.atEndOfStream && !_decompressedStream.hasDataInReadBuffer)




		@throw [OFTruncatedDataException exception];































#if SIZE_MAX >= UINT64_MAX
	if (length > UINT64_MAX)
		@throw [OFOutOfRangeException exception];
#endif

	if (length > _toRead)







|

|

|



|



|




















|














|









|





>
|
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
			    stream: (OFStream *)stream
			     entry: (OFZIPArchiveEntry *)entry
{
	self = [super init];

	@try {
		_archive = [archive retain];
		_compressionMethod = entry.compressionMethod;

		switch (_compressionMethod) {
		case OFZIPArchiveEntryCompressionMethodNone:
			_decompressedStream = [_archive->_stream retain];
			break;
		case OFZIPArchiveEntryCompressionMethodDeflate:
			_decompressedStream = [[OFInflateStream alloc]
			    initWithStream: _archive->_stream];
			break;
		case OFZIPArchiveEntryCompressionMethodDeflate64:
			_decompressedStream = [[OFInflate64Stream alloc]
			    initWithStream: _archive->_stream];
			break;
		default:
			@throw [OFNotImplementedException
			    exceptionWithSelector: _cmd
					   object: nil];
		}

		_entry = [entry copy];
		_toRead = entry.uncompressedSize;
		_CRC32 = ~0;
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (void)dealloc
{
	if (_decompressedStream != nil)
		[self close];

	[_entry release];

	if (_archive->_lastReturnedStream == self)
		_archive->_lastReturnedStream = nil;

	[_archive release];

	[super dealloc];
}

- (bool)lowlevelIsAtEndOfStream
{
	if (_decompressedStream == nil)
		@throw [OFNotOpenException exceptionWithObject: self];

	return _atEndOfStream;
}

- (size_t)lowlevelReadIntoBuffer: (void *)buffer length: (size_t)length
{
	size_t ret;

	if (_decompressedStream == nil)
		@throw [OFNotOpenException exceptionWithObject: self];

	if (_atEndOfStream)
		return 0;

	if ([_archive->_stream isAtEndOfStream] &&
	    ![_decompressedStream hasDataInReadBuffer]) {
		OFStream *oldStream = _archive->_stream, *oldDecompressedStream;
		OFSeekableStream *stream;

		if (_archive->_diskNumber >= _archive->_lastDiskNumber)
			@throw [OFTruncatedDataException exception];

		stream = [_archive->_delegate
			      archive: _archive
		    wantsPartNumbered: _archive->_diskNumber + 1
		       lastPartNumber: _archive->_lastDiskNumber];

		if (stream == nil)
			@throw [OFInvalidFormatException exception];

		_archive->_diskNumber++;
		_archive->_stream = [stream retain];
		[oldStream release];

		switch (_compressionMethod) {
		case OFZIPArchiveEntryCompressionMethodNone:
			oldDecompressedStream = _decompressedStream;
			_decompressedStream = [_archive->_stream retain];
			[oldDecompressedStream release];
			break;
		case OFZIPArchiveEntryCompressionMethodDeflate:
		case OFZIPArchiveEntryCompressionMethodDeflate64:
			[_decompressedStream
			    setUnderlyingStream: _archive->_stream];
			break;
		default:
			@throw [OFNotImplementedException
			    exceptionWithSelector: _cmd
					   object: nil];
		}
	}

#if SIZE_MAX >= UINT64_MAX
	if (length > UINT64_MAX)
		@throw [OFOutOfRangeException exception];
#endif

	if (length > _toRead)
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
				       expectedChecksum: expectedChecksum];
		}
	}

	return ret;
}

- (bool)hasDataInReadBuffer
{
	return (super.hasDataInReadBuffer ||
	    _decompressedStream.hasDataInReadBuffer);
}

- (int)fileDescriptorForReading
{
	return ((id <OFReadyForReadingObserving>)_decompressedStream)
	    .fileDescriptorForReading;
}

- (void)close
{
	if (_stream == nil || _decompressedStream == nil)
		@throw [OFNotOpenException exceptionWithObject: self];

	[_stream release];
	_stream = nil;

	[_decompressedStream release];
	_decompressedStream = nil;

	[super close];
}
@end

@implementation OFZIPArchiveFileWriteStream
- (instancetype)of_initWithArchive: (OFZIPArchive *)archive
			    stream: (OFStream *)stream
			     entry: (OFMutableZIPArchiveEntry *)entry


{
	self = [super init];

	_archive = [archive retain];
	_stream = [stream retain];
	_entry = [entry retain];
	_CRC32 = ~0;



	return self;
}

- (void)dealloc
{
	if (_stream != nil)







|

|
<










|


<
<
<











>
>







>
>







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
				       expectedChecksum: expectedChecksum];
		}
	}

	return ret;
}

- (bool)lowlevelHasDataInReadBuffer
{
	return ((OFStream *)_decompressedStream).hasDataInReadBuffer;

}

- (int)fileDescriptorForReading
{
	return ((id <OFReadyForReadingObserving>)_decompressedStream)
	    .fileDescriptorForReading;
}

- (void)close
{
	if (_decompressedStream == nil)
		@throw [OFNotOpenException exceptionWithObject: self];




	[_decompressedStream release];
	_decompressedStream = nil;

	[super close];
}
@end

@implementation OFZIPArchiveFileWriteStream
- (instancetype)of_initWithArchive: (OFZIPArchive *)archive
			    stream: (OFStream *)stream
			     entry: (OFMutableZIPArchiveEntry *)entry
		       CRC32Offset: (OFStreamOffset)CRC32Offset
		      size64Offset: (OFStreamOffset)size64Offset
{
	self = [super init];

	_archive = [archive retain];
	_stream = [stream retain];
	_entry = [entry retain];
	_CRC32 = ~0;
	_CRC32Offset = CRC32Offset;
	_size64Offset = size64Offset;

	return self;
}

- (void)dealloc
{
	if (_stream != nil)
919
920
921
922
923
924
925


926
927
928
929
930
931














932
933
934
935

936
937
938
939
940
941
942
943
944

945
946
947
948
949
950
951
952
953
954
955
956
957
	_CRC32 = OFCRC32(_CRC32, buffer, length);

	return length;
}

- (void)close
{


	if (_stream == nil)
		@throw [OFNotOpenException exceptionWithObject: self];

	if (_bytesWritten > UINT64_MAX)
		@throw [OFOutOfRangeException exception];















	[_stream writeLittleEndianInt32: 0x08074B50];
	[_stream writeLittleEndianInt32: _CRC32];
	[_stream writeLittleEndianInt64: (uint64_t)_bytesWritten];
	[_stream writeLittleEndianInt64: (uint64_t)_bytesWritten];


	[_stream release];
	_stream = nil;

	_entry.CRC32 = ~_CRC32;
	_entry.compressedSize = _bytesWritten;
	_entry.uncompressedSize = _bytesWritten;
	[_entry makeImmutable];


	_bytesWritten += (2 * 4 + 2 * 8);

	[_archive->_entries addObject: _entry];
	[_archive->_pathToEntryMap setObject: _entry forKey: _entry.fileName];

	if (ULLONG_MAX - _archive->_offset < _bytesWritten)
		@throw [OFOutOfRangeException exception];

	_archive->_offset += _bytesWritten;

	[super close];
}
@end







>
>






>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
|
|
>









>
|












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
	_CRC32 = OFCRC32(_CRC32, buffer, length);

	return length;
}

- (void)close
{
	bool seekable;

	if (_stream == nil)
		@throw [OFNotOpenException exceptionWithObject: self];

	if (_bytesWritten > UINT64_MAX)
		@throw [OFOutOfRangeException exception];

	seekable = [_stream isKindOfClass: [OFSeekableStream class]];

	if (seekable) {
		OFStreamOffset offset = [_stream seekToOffset: 0
						       whence: OFSeekCurrent];

		[_stream seekToOffset: _CRC32Offset whence: OFSeekSet];
		[_stream writeLittleEndianInt32: ~_CRC32];
		[_stream seekToOffset: _size64Offset whence: OFSeekSet];
		[_stream writeLittleEndianInt64: (uint64_t)_bytesWritten];
		[_stream writeLittleEndianInt64: (uint64_t)_bytesWritten];

		[_stream seekToOffset: offset whence: OFSeekSet];
	} else {
		[_stream writeLittleEndianInt32: 0x08074B50];
		[_stream writeLittleEndianInt32: ~_CRC32];
		[_stream writeLittleEndianInt64: (uint64_t)_bytesWritten];
		[_stream writeLittleEndianInt64: (uint64_t)_bytesWritten];
	}

	[_stream release];
	_stream = nil;

	_entry.CRC32 = ~_CRC32;
	_entry.compressedSize = _bytesWritten;
	_entry.uncompressedSize = _bytesWritten;
	[_entry makeImmutable];

	if (!seekable)
		_bytesWritten += (2 * 4 + 2 * 8);

	[_archive->_entries addObject: _entry];
	[_archive->_pathToEntryMap setObject: _entry forKey: _entry.fileName];

	if (ULLONG_MAX - _archive->_offset < _bytesWritten)
		@throw [OFOutOfRangeException exception];

	_archive->_offset += _bytesWritten;

	[super close];
}
@end

Modified src/OFZIPArchiveEntry+Private.h from [1ac3d985fc] to [fb278cf9a9].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

23
24
25
26
27
28
29
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the 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 "OFZIPArchive.h"

OF_ASSUME_NONNULL_BEGIN

@interface OFZIPArchiveEntry ()
@property (readonly, nonatomic)
    uint16_t of_lastModifiedFileTime, of_lastModifiedFileDate;

@property (readonly, nonatomic) int64_t of_localFileHeaderOffset;

- (instancetype)of_init OF_METHOD_FAMILY(init);
- (instancetype)of_initWithStream: (OFStream *)stream
    OF_METHOD_FAMILY(init) OF_DIRECT;
- (uint64_t)of_writeToStream: (OFStream *)stream OF_DIRECT;
@end

|




















>







1
2
3
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.
 */

#import "OFZIPArchive.h"

OF_ASSUME_NONNULL_BEGIN

@interface OFZIPArchiveEntry ()
@property (readonly, nonatomic)
    uint16_t of_lastModifiedFileTime, of_lastModifiedFileDate;
@property (readonly, nonatomic) uint32_t of_startDiskNumber;
@property (readonly, nonatomic) int64_t of_localFileHeaderOffset;

- (instancetype)of_init OF_METHOD_FAMILY(init);
- (instancetype)of_initWithStream: (OFStream *)stream
    OF_METHOD_FAMILY(init) OF_DIRECT;
- (uint64_t)of_writeToStream: (OFStream *)stream OF_DIRECT;
@end

Modified src/OFZIPArchiveEntry.h from [463b0f575c] to [c8000ff1d0].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/OFZIPArchiveEntry.m from [87dd5a9fa3] to [1e5ec904f3].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
403
404
405
406
407
408
409





410
411
412
413
414
415
416
	return _lastModifiedFileTime;
}

- (uint16_t)of_lastModifiedFileDate
{
	return _lastModifiedFileDate;
}






- (int64_t)of_localFileHeaderOffset
{
	return _localFileHeaderOffset;
}

- (OFString *)description







>
>
>
>
>







403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
	return _lastModifiedFileTime;
}

- (uint16_t)of_lastModifiedFileDate
{
	return _lastModifiedFileDate;
}

- (uint32_t)of_startDiskNumber
{
	return _startDiskNumber;
}

- (int64_t)of_localFileHeaderOffset
{
	return _localFileHeaderOffset;
}

- (OFString *)description

Modified src/ObjFW.h from [4f493cfd36] to [010bad87c9].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#import "OFNull.h"

#import "OFMethodSignature.h"
#import "OFInvocation.h"

#import "OFNumber.h"
#import "OFDate.h"
#import "OFUUID.h"
#import "OFURI.h"
#import "OFURIHandler.h"
#import "OFColor.h"

#import "OFNotification.h"
#import "OFNotificationCenter.h"

#import "OFStream.h"
#import "OFSeekableStream.h"







|
|
|







41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#import "OFNull.h"

#import "OFMethodSignature.h"
#import "OFInvocation.h"

#import "OFNumber.h"
#import "OFDate.h"
#import "OFIRI.h"
#import "OFIRIHandler.h"
#import "OFUUID.h"
#import "OFColor.h"

#import "OFNotification.h"
#import "OFNotificationCenter.h"

#import "OFStream.h"
#import "OFSeekableStream.h"
134
135
136
137
138
139
140


141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157

158
159
160
161
162
163
164
#import "OFApplication.h"
#import "OFSystemInfo.h"
#import "OFLocale.h"
#import "OFOptionsParser.h"
#import "OFTimer.h"
#import "OFRunLoop.h"



#ifdef OF_WINDOWS
# import "OFWindowsRegistryKey.h"
#endif

#import "OFASN1BitString.h"
#import "OFASN1Boolean.h"
#import "OFASN1Enumerated.h"
#import "OFASN1IA5String.h"
#import "OFASN1Integer.h"
#import "OFASN1NumericString.h"
#import "OFASN1ObjectIdentifier.h"
#import "OFASN1OctetString.h"
#import "OFASN1PrintableString.h"
#import "OFASN1UTF8String.h"
#import "OFASN1Value.h"

#import "OFAllocFailedException.h"

#import "OFException.h"
#import "OFChangeCurrentDirectoryFailedException.h"
#import "OFChecksumMismatchException.h"
#import "OFCopyItemFailedException.h"
#import "OFCreateDirectoryFailedException.h"
#import "OFCreateSymbolicLinkFailedException.h"
#import "OFEnumerationMutationException.h"







>
>

















>







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
#import "OFApplication.h"
#import "OFSystemInfo.h"
#import "OFLocale.h"
#import "OFOptionsParser.h"
#import "OFTimer.h"
#import "OFRunLoop.h"

#import "OFMatrix4x4.h"

#ifdef OF_WINDOWS
# import "OFWindowsRegistryKey.h"
#endif

#import "OFASN1BitString.h"
#import "OFASN1Boolean.h"
#import "OFASN1Enumerated.h"
#import "OFASN1IA5String.h"
#import "OFASN1Integer.h"
#import "OFASN1NumericString.h"
#import "OFASN1ObjectIdentifier.h"
#import "OFASN1OctetString.h"
#import "OFASN1PrintableString.h"
#import "OFASN1UTF8String.h"
#import "OFASN1Value.h"

#import "OFAllocFailedException.h"
#import "OFAlreadyOpenException.h"
#import "OFException.h"
#import "OFChangeCurrentDirectoryFailedException.h"
#import "OFChecksumMismatchException.h"
#import "OFCopyItemFailedException.h"
#import "OFCreateDirectoryFailedException.h"
#import "OFCreateSymbolicLinkFailedException.h"
#import "OFEnumerationMutationException.h"
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
#import "OFUnknownXMLEntityException.h"
#import "OFUnlockFailedException.h"
#import "OFUnsupportedProtocolException.h"
#import "OFUnsupportedVersionException.h"
#import "OFWriteFailedException.h"
#ifdef OF_HAVE_SOCKETS
# import "OFAcceptSocketFailedException.h"
# import "OFAlreadyConnectedException.h"
# import "OFBindIPSocketFailedException.h"
# import "OFBindSocketFailedException.h"
# import "OFConnectIPSocketFailedException.h"
# import "OFConnectSocketFailedException.h"
# import "OFDNSQueryFailedException.h"
# import "OFHTTPRequestFailedException.h"
# import "OFListenOnSocketFailedException.h"







<







204
205
206
207
208
209
210

211
212
213
214
215
216
217
#import "OFUnknownXMLEntityException.h"
#import "OFUnlockFailedException.h"
#import "OFUnsupportedProtocolException.h"
#import "OFUnsupportedVersionException.h"
#import "OFWriteFailedException.h"
#ifdef OF_HAVE_SOCKETS
# import "OFAcceptSocketFailedException.h"

# import "OFBindIPSocketFailedException.h"
# import "OFBindSocketFailedException.h"
# import "OFConnectIPSocketFailedException.h"
# import "OFConnectSocketFailedException.h"
# import "OFDNSQueryFailedException.h"
# import "OFHTTPRequestFailedException.h"
# import "OFListenOnSocketFailedException.h"

Modified src/bridge/Makefile from [5a2e1acbf4] to [311785c185].

1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
include ../../extra.mk

DISTCLEAN = Info.plist

SHARED_LIB = ${OBJFWBRIDGE_SHARED_LIB}
STATIC_LIB = ${OBJFWBRIDGE_STATIC_LIB}
FRAMEWORK = ${OBJFWBRIDGE_FRAMEWORK}
LIB_MAJOR = ${OBJFW_LIB_MAJOR}
LIB_MINOR = ${OBJFW_LIB_MINOR}


SRCS = OFArray+NSObject.m	\
       OFEnumerator+NSObject.m	\
       OFException+Swift.m	\
       OFDictionary+NSObject.m	\
       OFNumber+NSObject.m	\
       OFSet+NSObject.m		\







|
|
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
include ../../extra.mk

DISTCLEAN = Info.plist

SHARED_LIB = ${OBJFWBRIDGE_SHARED_LIB}
STATIC_LIB = ${OBJFWBRIDGE_STATIC_LIB}
FRAMEWORK = ${OBJFWBRIDGE_FRAMEWORK}
LIB_MAJOR = ${OBJFWBRIDGE_LIB_MAJOR}
LIB_MINOR = ${OBJFWBRIDGE_LIB_MINOR}
LIB_PATCH = ${OBJFWBRIDGE_LIB_PATCH}

SRCS = OFArray+NSObject.m	\
       OFEnumerator+NSObject.m	\
       OFException+Swift.m	\
       OFDictionary+NSObject.m	\
       OFNumber+NSObject.m	\
       OFSet+NSObject.m		\

Modified src/bridge/NSArray+OFObject.h from [4b59b82d97] to [4520acd79c].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/bridge/NSArray+OFObject.m from [a7c2336812] to [f5e6cebd81].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/bridge/NSBridging.h from [1aa6518645] to [bb8b560826].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/bridge/NSDictionary+OFObject.h from [1dcde481c6] to [34576a7d5c].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/bridge/NSDictionary+OFObject.m from [3bee09377c] to [fa5963bb1e].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/bridge/NSEnumerator+OFObject.h from [5e37d187b7] to [a57ddb7a60].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/bridge/NSEnumerator+OFObject.m from [dd0762c949] to [bf912f1b61].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/bridge/NSNumber+OFObject.h from [bd31c0c3cd] to [0c92c13762].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/bridge/NSNumber+OFObject.m from [18f7ec56ae] to [9ff3551b81].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/bridge/NSOFArray.h from [cd8e3e0488] to [240b18914b].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/bridge/NSOFArray.m from [41ea305080] to [d709e7ff15].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/bridge/NSOFDictionary.h from [b628e7e6a3] to [08045610d4].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/bridge/NSOFDictionary.m from [e47773ee01] to [390f7e5c3b].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/bridge/NSOFEnumerator.h from [fcb10c08ed] to [c981cbd744].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/bridge/NSOFEnumerator.m from [ebbed84f33] to [5bab4d5971].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/bridge/NSOFSet.h from [33948f6157] to [b4e566d4ef].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/bridge/NSOFSet.m from [e7387e2762] to [c5a5a3360c].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/bridge/NSSet+OFObject.h from [68cb6c5ccf] to [a8a45f1f21].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/bridge/NSSet+OFObject.m from [5daeb1bac4] to [1a3fff4bac].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/bridge/NSString+OFObject.h from [a30f21642d] to [97cf76b98e].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/bridge/NSString+OFObject.m from [f6fbd9f898] to [34ba1fea05].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/bridge/OFArray+NSObject.h from [f258ecab9a] to [4b8ba8c9e9].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/bridge/OFArray+NSObject.m from [ee4c5a25af] to [ad74ace379].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/bridge/OFBridging.h from [abe87031bc] to [71a8a0383b].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/bridge/OFDictionary+NSObject.h from [27bfd0d589] to [cc93713fad].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/bridge/OFDictionary+NSObject.m from [6df9e22408] to [488e5f8f23].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/bridge/OFEnumerator+NSObject.h from [cb0752d99c] to [a35e608df0].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/bridge/OFEnumerator+NSObject.m from [a3ee1dfe29] to [0798d8dda4].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/bridge/OFException+Swift.h from [da5307c0ad] to [e1daea571c].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/bridge/OFException+Swift.m from [69103747b4] to [8b1b89e3b4].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/bridge/OFNSArray.h from [1c05dea53b] to [bc91fcf25e].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/bridge/OFNSArray.m from [511fcf77df] to [154c1aa369].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/bridge/OFNSDictionary.h from [3699212d07] to [b6fe03ba27].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/bridge/OFNSDictionary.m from [3228b094f1] to [e936810e7c].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/bridge/OFNSEnumerator.h from [f60938ebf6] to [146aaa60ea].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/bridge/OFNSEnumerator.m from [9f5d7028e9] to [b3ceaaf5a7].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/bridge/OFNSSet.h from [7b3370ed57] to [8b3618717b].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/bridge/OFNSSet.m from [151a52ad4b] to [e428a7d927].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/bridge/OFNumber+NSObject.h from [955839af4e] to [fc32bb2b98].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/bridge/OFNumber+NSObject.m from [f73968ae16] to [5349cc0bc2].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/bridge/OFSet+NSObject.h from [9214bbd006] to [c4837c5b7d].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/bridge/OFSet+NSObject.m from [e5bc663707] to [33e1430151].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/bridge/OFString+NSObject.h from [375ab3a6b5] to [9663e731bd].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/bridge/OFString+NSObject.m from [bf4d082579] to [d22f7306ed].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/bridge/ObjFWBridge.h from [1fbb08ae27] to [f1ee24874c].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/encodings/codepage-437.m from [1cc88f79fe] to [e7ff14771d].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/encodings/codepage-850.m from [d9cdb5c58f] to [5a61172f80].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/encodings/codepage-858.m from [402e5b0a14] to [0efff5e77d].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/encodings/common.h from [a9b82f31be] to [34c80fff7a].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/encodings/iso-8859-15.m from [8197488f98] to [35e5917766].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/encodings/iso-8859-2.m from [b10a788d3d] to [20a4dce807].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/encodings/iso-8859-3.m from [57543aa317] to [b9991c0f6c].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/encodings/koi8-r.m from [e29e1b888f] to [f60152b507].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/encodings/koi8-u.m from [10ad0de57d] to [c642a9b6fb].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/encodings/mac-roman.m from [5811cbe352] to [4f5b3e5bc0].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/encodings/windows-1251.m from [b8c4870fa7] to [2987d4facd].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/encodings/windows-1252.m from [f9fc8b9676] to [ac599fe5ce].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/Makefile from [0588e3b54e] to [c441977bfd].

1
2
3
4
5
6

7
8
9
10
11
12
13
include ../../extra.mk

STATIC_PIC_LIB_NOINST = ${EXCEPTIONS_LIB_A}
STATIC_LIB_NOINST = ${EXCEPTIONS_A}

SRCS = OFAllocFailedException.m				\

       OFChecksumMismatchException.m			\
       OFCopyItemFailedException.m			\
       OFCreateDirectoryFailedException.m		\
       OFCreateSymbolicLinkFailedException.m		\
       OFEnumerationMutationException.m			\
       OFException.m					\
       OFGetItemAttributesFailedException.m		\






>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
include ../../extra.mk

STATIC_PIC_LIB_NOINST = ${EXCEPTIONS_LIB_A}
STATIC_LIB_NOINST = ${EXCEPTIONS_A}

SRCS = OFAllocFailedException.m				\
       OFAlreadyOpenException.m				\
       OFChecksumMismatchException.m			\
       OFCopyItemFailedException.m			\
       OFCreateDirectoryFailedException.m		\
       OFCreateSymbolicLinkFailedException.m		\
       OFEnumerationMutationException.m			\
       OFException.m					\
       OFGetItemAttributesFailedException.m		\
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
       ${USE_SRCS_SOCKETS}				\
       ${USE_SRCS_THREADS}				\
       ${USE_SRCS_WINDOWS}
SRCS_FILES = OFChangeCurrentDirectoryFailedException.m	\
	     OFGetCurrentDirectoryFailedException.m
SRCS_PLUGINS = OFLoadPluginFailedException.m
SRCS_SOCKETS = OFAcceptSocketFailedException.m		\
	       OFAlreadyConnectedException.m		\
	       OFBindIPSocketFailedException.m		\
	       OFBindSocketFailedException.m		\
	       OFConnectIPSocketFailedException.m	\
	       OFConnectSocketFailedException.m		\
	       OFDNSQueryFailedException.m		\
	       OFHTTPRequestFailedException.m		\
	       OFListenOnSocketFailedException.m	\







<







51
52
53
54
55
56
57

58
59
60
61
62
63
64
       ${USE_SRCS_SOCKETS}				\
       ${USE_SRCS_THREADS}				\
       ${USE_SRCS_WINDOWS}
SRCS_FILES = OFChangeCurrentDirectoryFailedException.m	\
	     OFGetCurrentDirectoryFailedException.m
SRCS_PLUGINS = OFLoadPluginFailedException.m
SRCS_SOCKETS = OFAcceptSocketFailedException.m		\

	       OFBindIPSocketFailedException.m		\
	       OFBindSocketFailedException.m		\
	       OFConnectIPSocketFailedException.m	\
	       OFConnectSocketFailedException.m		\
	       OFDNSQueryFailedException.m		\
	       OFHTTPRequestFailedException.m		\
	       OFListenOnSocketFailedException.m	\

Modified src/exceptions/OFAcceptSocketFailedException.h from [e062558833] to [4d40689617].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFAcceptSocketFailedException.m from [701680e6d7] to [ef63012ab6].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFActivateSandboxFailedException.h from [97726da76a] to [ad6c7a30e5].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFActivateSandboxFailedException.m from [5dc1486ad8] to [056f3f2b30].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFAllocFailedException.h from [01cde7dcb3] to [b1bbd6b140].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFAllocFailedException.m from [845ed2917e] to [76e4000eaa].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
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
}

- (instancetype)init
{
	OF_INVALID_INIT_METHOD
}

- (instancetype)retain
{
	return self;
}

- (instancetype)autorelease
{
	return self;
}

- (unsigned int)retainCount
{
	return OFMaxRetainCount;
}

- (void)release
{
}

- (void)dealloc
{
	OF_DEALLOC_UNSUPPORTED
}

- (OFString *)description
{
	return @"Allocating an object failed!";
}
@end







<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<






30
31
32
33
34
35
36




37


















38
39
40
41
42
43
}

- (instancetype)init
{
	OF_INVALID_INIT_METHOD
}





OF_SINGLETON_METHODS



















- (OFString *)description
{
	return @"Allocating an object failed!";
}
@end

Renamed and modified src/exceptions/OFAlreadyConnectedException.h [ac208c2ef2] to src/exceptions/OFAlreadyOpenException.h [aea93ead79].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35





36
37
38
39
40
41
42
43
44
45
46
47
48
49


50
51
52
53
54
55


56
57
58
59
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#import "OFException.h"

#ifndef OF_HAVE_SOCKETS
# error No sockets available!
#endif

OF_ASSUME_NONNULL_BEGIN

/**
 * @class OFAlreadyConnectedException \
 *	  OFAlreadyConnectedException.h ObjFW/OFAlreadyConnectedException.h
 *
 * @brief An exception indicating an attempt to connect or bind an already
 *        connected or bound socket.
 */
@interface OFAlreadyConnectedException: OFException
{
	id _socket;
	OF_RESERVE_IVARS(OFAlreadyConnectedException, 4)
}






/**
 * @brief The socket which is already connected.
 */
@property OF_NULLABLE_PROPERTY (readonly, nonatomic) id socket;

/**
 * @brief Creates a new, autoreleased already connected exception.
 *
 * @param socket The socket which is already connected
 * @return A new, autoreleased already connected exception
 */
+ (instancetype)exceptionWithSocket: (nullable id)socket;



/**
 * @brief Initializes an already allocated already connected exception.
 *
 * @param socket The socket which is already connected
 * @return An initialized already connected exception
 */


- (instancetype)initWithSocket: (nullable id)socket OF_DESIGNATED_INITIALIZER;
@end

OF_ASSUME_NONNULL_END

|















<
<
<
<



|
|

|
|

|

|
|

>
>
>
>
>


<
<
<
<
<
|

|
|

|

>
>

|

|
|

>
>
|



1
2
3
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.
 */

#import "OFException.h"





OF_ASSUME_NONNULL_BEGIN

/**
 * @class OFAlreadyOpenException \
 *	  OFAlreadyOpenException.h ObjFW/OFAlreadyOpenException.h
 *
 * @brief An exception indicating that an object is already open and thus
 *	  cannot be opened again.
 */
@interface OFAlreadyOpenException: OFException
{
	id _object;
	OF_RESERVE_IVARS(OFAlreadyOpenException, 4)
}

/**
 * @brief The object which is already open.
 */
@property (readonly, nonatomic) id object;

/**





 * @brief Creates a new, autoreleased already open exception.
 *
 * @param object The object which is already open
 * @return A new, autoreleased already open exception
 */
+ (instancetype)exceptionWithObject: (id)object;

+ (instancetype)exception OF_UNAVAILABLE;

/**
 * @brief Initializes an already allocated already open exception.
 *
 * @param object The object which is already open
 * @return An initialized already open exception
 */
- (instancetype)initWithObject: (id)object OF_DESIGNATED_INITIALIZER;

- (instancetype)init OF_UNAVAILABLE;
@end

OF_ASSUME_NONNULL_END

Renamed and modified src/exceptions/OFAlreadyConnectedException.m [9abd285501] to src/exceptions/OFAlreadyOpenException.m [97afd1314e].

1
2
3
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-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#import "OFAlreadyConnectedException.h"
#import "OFString.h"

@implementation OFAlreadyConnectedException
@synthesize socket = _socket;

+ (instancetype)exceptionWithSocket: (id)sock
{
	return [[[self alloc] initWithSocket: sock] autorelease];
}

- (instancetype)init
{
	return [self initWithSocket: nil];
}

- (instancetype)initWithSocket: (id)sock
{
	self = [super init];

	_socket = [sock retain];

	return self;
}






- (void)dealloc
{
	[_socket release];

	[super dealloc];
}

- (OFString *)description
{
	if (_socket)
		return [OFString stringWithFormat:
		    @"The socket of type %@ is already connected or bound and "
		    @"thus can't be connected or bound again!",
		    [_socket class]];
	else
		return @"A connection has already been established!";
}
@end

|















|


|
|

|

|


|

|


|



|



>
>
>
>
>



|






<
|
|
|
|
<
<


1
2
3
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"

#import "OFAlreadyOpenException.h"
#import "OFString.h"

@implementation OFAlreadyOpenException
@synthesize object = _object;

+ (instancetype)exceptionWithObject: (id)object
{
	return [[[self alloc] initWithObject: object] autorelease];
}

+ (instancetype)exception
{
	OF_UNRECOGNIZED_SELECTOR
}

- (instancetype)initWithObject: (id)object
{
	self = [super init];

	_object = [object retain];

	return self;
}

- (instancetype)init
{
	OF_INVALID_INIT_METHOD
}

- (void)dealloc
{
	[_object release];

	[super dealloc];
}

- (OFString *)description
{

	return [OFString stringWithFormat:
	    @"An object of type %@ is already open and thus cannot be opened "
	    @"again!",
	    [_object class]];


}
@end

Modified src/exceptions/OFBindDDPSocketFailedException.h from [5a5edecbc3] to [212c39ffcd].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFBindDDPSocketFailedException.m from [10cafd22cd] to [3628420ad1].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
70
71
72
73
74
75
76
77
78
79
80
81
82
	return self;
}

- (OFString *)description
{
	return [OFString stringWithFormat:
	    @"Binding to port %" @PRIx8 @" of node %" @PRIx8 @" on network "
	    @"%" PRIx16 @" with protocol type %" @PRIx8 @" failed in socket of "
	    @"type %@: %@",
	    _port, _node, _network, _protocolType, [_socket class],
	    OFStrError(_errNo)];
}
@end







|
|




70
71
72
73
74
75
76
77
78
79
80
81
82
	return self;
}

- (OFString *)description
{
	return [OFString stringWithFormat:
	    @"Binding to port %" @PRIx8 @" of node %" @PRIx8 @" on network "
	    @"%" PRIx16 @" with protocol type 0x%" @PRIX8 @" failed in socket "
	    @"of type %@: %@",
	    _port, _node, _network, _protocolType, [_socket class],
	    OFStrError(_errNo)];
}
@end

Modified src/exceptions/OFBindIPSocketFailedException.h from [5e1e83771b] to [dc408fe74d].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFBindIPSocketFailedException.m from [f9eddfdc09] to [df48bf8838].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFBindIPXSocketFailedException.h from [348112e28c] to [87db14b383].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFBindIPXSocketFailedException.m from [ae7cdae06b] to [43765520cc].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
76
77
78
79
80
81
82
83
84
85
86

87
88
89
90
91
- (void)getNode: (unsigned char [IPX_NODE_LEN])node
{
	memcpy(node, _node, sizeof(_node));
}

- (OFString *)description
{
	OFData *node = [OFData dataWithItems: _node count: sizeof(_node)];

	return [OFString stringWithFormat:
	    @"Binding to network %" @PRIx16 " on node %@ with port %" @PRIx16

	    @" failed for packet type %" @PRIx8 " in socket of type %@: %@",
	    _network, node, _port, _packetType, [_socket class],
	    OFStrError(_errNo)];
}
@end







<
<

|
>
|
|
|


76
77
78
79
80
81
82


83
84
85
86
87
88
89
90
- (void)getNode: (unsigned char [IPX_NODE_LEN])node
{
	memcpy(node, _node, sizeof(_node));
}

- (OFString *)description
{


	return [OFString stringWithFormat:
	    @"Binding to network %" @PRIx16 " on node "
	    @"%02X:%02X:%02X:%02X:%02X:%02X with port %" @PRIx16 @" failed for "
	    @"packet type %" @PRIx8 " in socket of type %@: %@",
	    _network, _node[0], _node[1], _node[2], _node[3], _node[4],
	    _node[5], _port, _packetType, [_socket class], OFStrError(_errNo)];
}
@end

Modified src/exceptions/OFBindSocketFailedException.h from [36c8977d2e] to [a55906ae63].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFBindSocketFailedException.m from [6491b695d4] to [016bb92ca1].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFBindUNIXSocketFailedException.h from [8dc7fd786c] to [a807b13958].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
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
 * @brief Creates a new, autoreleased bind UNIX socket failed exception.
 *
 * @param path The path on which binding failed
 * @param socket The socket which could not be bound
 * @param errNo The errno of the error that occurred
 * @return A new, autoreleased bind UNIX socket failed exception
 */
+ (instancetype)exceptionWithPath: (OFString *)path
			   socket: (id)socket
			    errNo: (int)errNo;

+ (instancetype)exceptionWithSocket: (id)socket
			      errNo: (int)errNo OF_UNAVAILABLE;

/**
 * @brief Initializes an already allocated bind UNIX socket failed exception.
 *
 * @param path The path on which binding failed
 * @param socket The socket which could not be bound
 * @param errNo The errno of the error that occurred
 * @return An initialized bind UNIX socket failed exception
 */
- (instancetype)initWithPath: (OFString *)path
		      socket: (id)socket
		       errNo: (int)errNo OF_DESIGNATED_INITIALIZER;

- (instancetype)initWithSocket: (id)socket errNo: (int)errNo OF_UNAVAILABLE;
@end

OF_ASSUME_NONNULL_END







|














|







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
 * @brief Creates a new, autoreleased bind UNIX socket failed exception.
 *
 * @param path The path on which binding failed
 * @param socket The socket which could not be bound
 * @param errNo The errno of the error that occurred
 * @return A new, autoreleased bind UNIX socket failed exception
 */
+ (instancetype)exceptionWithPath: (nullable OFString *)path
			   socket: (id)socket
			    errNo: (int)errNo;

+ (instancetype)exceptionWithSocket: (id)socket
			      errNo: (int)errNo OF_UNAVAILABLE;

/**
 * @brief Initializes an already allocated bind UNIX socket failed exception.
 *
 * @param path The path on which binding failed
 * @param socket The socket which could not be bound
 * @param errNo The errno of the error that occurred
 * @return An initialized bind UNIX socket failed exception
 */
- (instancetype)initWithPath: (nullable OFString *)path
		      socket: (id)socket
		       errNo: (int)errNo OF_DESIGNATED_INITIALIZER;

- (instancetype)initWithSocket: (id)socket errNo: (int)errNo OF_UNAVAILABLE;
@end

OF_ASSUME_NONNULL_END

Modified src/exceptions/OFBindUNIXSocketFailedException.m from [e85a3193a3] to [b5eeaa4d9e].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFBroadcastConditionFailedException.h from [b5c55a5caf] to [102c52be8a].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFBroadcastConditionFailedException.m from [aeec33aa4e] to [9070b08e82].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFChangeCurrentDirectoryFailedException.h from [c93252d4da] to [c000cc3c78].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFChangeCurrentDirectoryFailedException.m from [7267a7e220] to [90839be848].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFChecksumMismatchException.h from [5d6d269610] to [3821135424].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFChecksumMismatchException.m from [194677cc27] to [e3790612f4].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFConditionStillWaitingException.h from [6424437193] to [4d92614945].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFConditionStillWaitingException.m from [28d38d170f] to [eba5eb38d2].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFConnectIPSocketFailedException.h from [f85ab38f4c] to [8b62d55339].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFConnectIPSocketFailedException.m from [b9f4e412ce] to [5273540bbe].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFConnectSPXSocketFailedException.h from [acdfa9213b] to [90b4a78595].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFConnectSPXSocketFailedException.m from [35220eec8e] to [52d6ca0c92].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
70
71
72
73
74
75
76
77
78
79
80
81


82
83
84
- (void)getNode: (unsigned char [IPX_NODE_LEN])node
{
	memcpy(node, _node, sizeof(_node));
}

- (OFString *)description
{
	OFData *node = [OFData dataWithItems: _node count: sizeof(_node)];

	return [OFString stringWithFormat:
	    @"A connection to %@ port %" @PRIu16 @" on network %" @PRIX32
	    " could not be established in socket of type %@: %@",


	    node, _port, _network, [_socket class], OFStrError(_errNo)];
}
@end







<
<

|
|
>
>
|


70
71
72
73
74
75
76


77
78
79
80
81
82
83
84
- (void)getNode: (unsigned char [IPX_NODE_LEN])node
{
	memcpy(node, _node, sizeof(_node));
}

- (OFString *)description
{


	return [OFString stringWithFormat:
	    @"A connection to %02X:%02X:%02X:%02X:%02X:%02X port %" @PRIu16
	    @" on network %" @PRIX32 " could not be established in socket of "
	    @"type %@: %@",
	    _node[0], _node[1], _node[2], _node[3], _node[4], _node[5], _port,
	    _network, [_socket class], OFStrError(_errNo)];
}
@end

Modified src/exceptions/OFConnectSocketFailedException.h from [8f2d911f53] to [f7d237c480].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFConnectSocketFailedException.m from [cadbcb9d65] to [bdc7811eef].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFConnectUNIXSocketFailedException.h from [9ffd06e788] to [2982ed499b].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFConnectUNIXSocketFailedException.m from [f1376977d4] to [87e8760126].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFCopyItemFailedException.h from [123bfde77a] to [377bf410f8].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#import "OFException.h"

OF_ASSUME_NONNULL_BEGIN

@class OFURI;

/**
 * @class OFCopyItemFailedException \
 *	  OFCopyItemFailedException.h ObjFW/OFCopyItemFailedException.h
 *
 * @brief An exception indicating that copying a item failed.
 */
@interface OFCopyItemFailedException: OFException
{
	OFURI *_sourceURI, *_destinationURI;
	int _errNo;
	OF_RESERVE_IVARS(OFCopyItemFailedException, 4)
}

/**
 * @brief The URI of the source item.
 */
@property (readonly, nonatomic) OFURI *sourceURI;

/**
 * @brief The destination URI.
 */
@property (readonly, nonatomic) OFURI *destinationURI;

/**
 * @brief The errno of the error that occurred.
 */
@property (readonly, nonatomic) int errNo;

/**
 * @brief Creates a new, autoreleased copy item failed exception.
 *
 * @param sourceURI The URI of the source item
 * @param destinationURI The destination URI
 * @param errNo The errno of the error that occurred
 * @return A new, autoreleased copy item failed exception
 */
+ (instancetype)exceptionWithSourceURI: (OFURI *)sourceURI
			destinationURI: (OFURI *)destinationURI
				 errNo: (int)errNo;

+ (instancetype)exception OF_UNAVAILABLE;

/**
 * @brief Initializes an already allocated copy item failed exception.
 *
 * @param sourceURI The URI of the source item
 * @param destinationURI The destination URI
 * @param errNo The errno of the error that occurred
 * @return An initialized copy item failed exception
 */
- (instancetype)initWithSourceURI: (OFURI *)sourceURI
		   destinationURI: (OFURI *)destinationURI
			    errNo: (int)errNo OF_DESIGNATED_INITIALIZER;

- (instancetype)init OF_UNAVAILABLE;
@end

OF_ASSUME_NONNULL_END

|

















|









|





|

|


|

|









|
|



|
|







|
|



|
|






1
2
3
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 "OFException.h"

OF_ASSUME_NONNULL_BEGIN

@class OFIRI;

/**
 * @class OFCopyItemFailedException \
 *	  OFCopyItemFailedException.h ObjFW/OFCopyItemFailedException.h
 *
 * @brief An exception indicating that copying a item failed.
 */
@interface OFCopyItemFailedException: OFException
{
	OFIRI *_sourceIRI, *_destinationIRI;
	int _errNo;
	OF_RESERVE_IVARS(OFCopyItemFailedException, 4)
}

/**
 * @brief The IRI of the source item.
 */
@property (readonly, nonatomic) OFIRI *sourceIRI;

/**
 * @brief The destination IRI.
 */
@property (readonly, nonatomic) OFIRI *destinationIRI;

/**
 * @brief The errno of the error that occurred.
 */
@property (readonly, nonatomic) int errNo;

/**
 * @brief Creates a new, autoreleased copy item failed exception.
 *
 * @param sourceIRI The IRI of the source item
 * @param destinationIRI The destination IRI
 * @param errNo The errno of the error that occurred
 * @return A new, autoreleased copy item failed exception
 */
+ (instancetype)exceptionWithSourceIRI: (OFIRI *)sourceIRI
			destinationIRI: (OFIRI *)destinationIRI
				 errNo: (int)errNo;

+ (instancetype)exception OF_UNAVAILABLE;

/**
 * @brief Initializes an already allocated copy item failed exception.
 *
 * @param sourceIRI The IRI of the source item
 * @param destinationIRI The destination IRI
 * @param errNo The errno of the error that occurred
 * @return An initialized copy item failed exception
 */
- (instancetype)initWithSourceIRI: (OFIRI *)sourceIRI
		   destinationIRI: (OFIRI *)destinationIRI
			    errNo: (int)errNo OF_DESIGNATED_INITIALIZER;

- (instancetype)init OF_UNAVAILABLE;
@end

OF_ASSUME_NONNULL_END

Modified src/exceptions/OFCopyItemFailedException.m from [86e24afee9] to [dd6abeea44].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#import "OFCopyItemFailedException.h"
#import "OFString.h"
#import "OFURI.h"

@implementation OFCopyItemFailedException
@synthesize sourceURI = _sourceURI, destinationURI = _destinationURI;
@synthesize errNo = _errNo;

+ (instancetype)exception
{
	OF_UNRECOGNIZED_SELECTOR
}

+ (instancetype)exceptionWithSourceURI: (OFURI *)sourceURI
			destinationURI: (OFURI *)destinationURI
				 errNo: (int)errNo
{
	return [[[self alloc] initWithSourceURI: sourceURI
				 destinationURI: destinationURI
					  errNo: errNo] autorelease];
}

- (instancetype)init
{
	OF_INVALID_INIT_METHOD
}

- (instancetype)initWithSourceURI: (OFURI *)sourceURI
		   destinationURI: (OFURI *)destinationURI
			    errNo: (int)errNo
{
	self = [super init];

	@try {
		_sourceURI = [sourceURI copy];
		_destinationURI = [destinationURI copy];
		_errNo = errNo;
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (void)dealloc
{
	[_sourceURI release];
	[_destinationURI release];

	[super dealloc];
}

- (OFString *)description
{
	return [OFString stringWithFormat: @"Failed to copy item %@ to %@: %@",
	    _sourceURI, _destinationURI, OFStrError(_errNo)];
}
@end

|
















|
|


|







|
|


|
|








|
|





|
|











|
|







|


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
/*
 * Copyright (c) 2008-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 "OFCopyItemFailedException.h"
#import "OFIRI.h"
#import "OFString.h"

@implementation OFCopyItemFailedException
@synthesize sourceIRI = _sourceIRI, destinationIRI = _destinationIRI;
@synthesize errNo = _errNo;

+ (instancetype)exception
{
	OF_UNRECOGNIZED_SELECTOR
}

+ (instancetype)exceptionWithSourceIRI: (OFIRI *)sourceIRI
			destinationIRI: (OFIRI *)destinationIRI
				 errNo: (int)errNo
{
	return [[[self alloc] initWithSourceIRI: sourceIRI
				 destinationIRI: destinationIRI
					  errNo: errNo] autorelease];
}

- (instancetype)init
{
	OF_INVALID_INIT_METHOD
}

- (instancetype)initWithSourceIRI: (OFIRI *)sourceIRI
		   destinationIRI: (OFIRI *)destinationIRI
			    errNo: (int)errNo
{
	self = [super init];

	@try {
		_sourceIRI = [sourceIRI copy];
		_destinationIRI = [destinationIRI copy];
		_errNo = errNo;
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (void)dealloc
{
	[_sourceIRI release];
	[_destinationIRI release];

	[super dealloc];
}

- (OFString *)description
{
	return [OFString stringWithFormat: @"Failed to copy item %@ to %@: %@",
	    _sourceIRI, _destinationIRI, OFStrError(_errNo)];
}
@end

Modified src/exceptions/OFCreateDirectoryFailedException.h from [e16c672401] to [119cf51816].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#import "OFException.h"

OF_ASSUME_NONNULL_BEGIN

@class OFURI;

/**
 * @class OFCreateDirectoryFailedException \
 *	  OFCreateDirectoryFailedException.h \
 *	  ObjFW/OFCreateDirectoryFailedException.h
 *
 * @brief An exception indicating a directory couldn't be created.
 */
@interface OFCreateDirectoryFailedException: OFException
{
	OFURI *_URI;
	int _errNo;
	OF_RESERVE_IVARS(OFCreateDirectoryFailedException, 4)
}

/**
 * @brief The URI of the directory which couldn't be created.
 */
@property (readonly, nonatomic) OFURI *URI;

/**
 * @brief The errno of the error that occurred.
 */
@property (readonly, nonatomic) int errNo;

/**
 * @brief Creates a new, autoreleased create directory failed exception.
 *
 * @param URI The URI of the directory which could not be created
 * @param errNo The errno of the error that occurred
 * @return A new, autoreleased create directory failed exception
 */
+ (instancetype)exceptionWithURI: (OFURI *)URI errNo: (int)errNo;

+ (instancetype)exception OF_UNAVAILABLE;

/**
 * @brief Initializes an already allocated create directory failed exception.
 *
 * @param URI The URI of the directory which could not be created
 * @param errNo The errno of the error that occurred
 * @return An initialized create directory failed exception
 */
- (instancetype)initWithURI: (OFURI *)URI
		      errNo: (int)errNo OF_DESIGNATED_INITIALIZER;

- (instancetype)init OF_UNAVAILABLE;
@end

OF_ASSUME_NONNULL_END

|

















|










|





|

|









|



|






|



|






1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
/*
 * Copyright (c) 2008-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"

OF_ASSUME_NONNULL_BEGIN

@class OFIRI;

/**
 * @class OFCreateDirectoryFailedException \
 *	  OFCreateDirectoryFailedException.h \
 *	  ObjFW/OFCreateDirectoryFailedException.h
 *
 * @brief An exception indicating a directory couldn't be created.
 */
@interface OFCreateDirectoryFailedException: OFException
{
	OFIRI *_IRI;
	int _errNo;
	OF_RESERVE_IVARS(OFCreateDirectoryFailedException, 4)
}

/**
 * @brief The IRI of the directory which couldn't be created.
 */
@property (readonly, nonatomic) OFIRI *IRI;

/**
 * @brief The errno of the error that occurred.
 */
@property (readonly, nonatomic) int errNo;

/**
 * @brief Creates a new, autoreleased create directory failed exception.
 *
 * @param IRI The IRI of the directory which could not be created
 * @param errNo The errno of the error that occurred
 * @return A new, autoreleased create directory failed exception
 */
+ (instancetype)exceptionWithIRI: (OFIRI *)IRI errNo: (int)errNo;

+ (instancetype)exception OF_UNAVAILABLE;

/**
 * @brief Initializes an already allocated create directory failed exception.
 *
 * @param IRI The IRI of the directory which could not be created
 * @param errNo The errno of the error that occurred
 * @return An initialized create directory failed exception
 */
- (instancetype)initWithIRI: (OFIRI *)IRI
		      errNo: (int)errNo OF_DESIGNATED_INITIALIZER;

- (instancetype)init OF_UNAVAILABLE;
@end

OF_ASSUME_NONNULL_END

Modified src/exceptions/OFCreateDirectoryFailedException.m from [cd0b53b912] to [59f155c9b0].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#import "OFCreateDirectoryFailedException.h"
#import "OFString.h"
#import "OFURI.h"

@implementation OFCreateDirectoryFailedException
@synthesize URI = _URI, errNo = _errNo;

+ (instancetype)exception
{
	OF_UNRECOGNIZED_SELECTOR
}

+ (instancetype)exceptionWithURI: (OFURI *)URI errNo: (int)errNo
{
	return [[[self alloc] initWithURI: URI errNo: errNo] autorelease];
}

- (instancetype)init
{
	OF_INVALID_INIT_METHOD
}

- (instancetype)initWithURI: (OFURI *)URI errNo: (int)errNo
{
	self = [super init];

	@try {
		_URI = [URI copy];
		_errNo = errNo;
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (void)dealloc
{
	[_URI release];

	[super dealloc];
}

- (OFString *)description
{
	return [OFString stringWithFormat:
	    @"Failed to create directory %@: %@", _URI, OFStrError(_errNo)];
}
@end

|
















|
|


|






|

|







|




|











|







|


1
2
3
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.
 */

#include "config.h"

#import "OFCreateDirectoryFailedException.h"
#import "OFIRI.h"
#import "OFString.h"

@implementation OFCreateDirectoryFailedException
@synthesize IRI = _IRI, errNo = _errNo;

+ (instancetype)exception
{
	OF_UNRECOGNIZED_SELECTOR
}

+ (instancetype)exceptionWithIRI: (OFIRI *)IRI errNo: (int)errNo
{
	return [[[self alloc] initWithIRI: IRI errNo: errNo] autorelease];
}

- (instancetype)init
{
	OF_INVALID_INIT_METHOD
}

- (instancetype)initWithIRI: (OFIRI *)IRI errNo: (int)errNo
{
	self = [super init];

	@try {
		_IRI = [IRI copy];
		_errNo = errNo;
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (void)dealloc
{
	[_IRI release];

	[super dealloc];
}

- (OFString *)description
{
	return [OFString stringWithFormat:
	    @"Failed to create directory %@: %@", _IRI, OFStrError(_errNo)];
}
@end

Modified src/exceptions/OFCreateSymbolicLinkFailedException.h from [79c2f6b7ee] to [bd616cbde6].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#import "OFException.h"

OF_ASSUME_NONNULL_BEGIN

@class OFURI;

/**
 * @class OFCreateSymbolicLinkFailedException \
 *	  OFCreateSymbolicLinkFailedException.h \
 *	  ObjFW/OFCreateSymbolicLinkFailedException.h
 *
 * @brief An exception indicating that creating a symbolic link failed.
 */
@interface OFCreateSymbolicLinkFailedException: OFException
{
	OFURI *_URI;
	OFString *_target;
	int _errNo;
	OF_RESERVE_IVARS(OFCreateSymbolicLinkFailedException, 4)
}

/**
 * @brief The URI at which the symlink should have been created.
 */
@property (readonly, nonatomic) OFURI *URI;

/**
 * @brief The target for the symlink.
 */
@property (readonly, nonatomic) OFString *target;

/**
 * @brief The errno of the error that occurred.
 */
@property (readonly, nonatomic) int errNo;

/**
 * @brief Creates a new, autoreleased create symbolic link failed exception.
 *
 * @param URI The URI where the symlink should have been created
 * @param target The target for the symbolic link
 * @param errNo The errno of the error that occurred
 * @return A new, autoreleased create symbolic link failed exception
 */
+ (instancetype)exceptionWithURI: (OFURI *)URI
			  target: (OFString *)target
			   errNo: (int)errNo;

+ (instancetype)exception OF_UNAVAILABLE;

/**
 * @brief Initializes an already allocated create symbolic link failed
 *	  exception.
 *
 * @param URI The URI where the symlink should have been created
 * @param target The target for the symbolic link
 * @param errNo The errno of the error that occurred
 * @return An initialized create symbolic link failed exception
 */
- (instancetype)initWithURI: (OFURI *)URI
		     target: (OFString *)target
		      errNo: (int)errNo OF_DESIGNATED_INITIALIZER;

- (instancetype)init OF_UNAVAILABLE;
@end

OF_ASSUME_NONNULL_END

|

















|










|






|

|














|




|









|




|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
/*
 * Copyright (c) 2008-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"

OF_ASSUME_NONNULL_BEGIN

@class OFIRI;

/**
 * @class OFCreateSymbolicLinkFailedException \
 *	  OFCreateSymbolicLinkFailedException.h \
 *	  ObjFW/OFCreateSymbolicLinkFailedException.h
 *
 * @brief An exception indicating that creating a symbolic link failed.
 */
@interface OFCreateSymbolicLinkFailedException: OFException
{
	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

Modified src/exceptions/OFCreateSymbolicLinkFailedException.m from [c5e085b246] to [0a0c895913].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#import "OFCreateSymbolicLinkFailedException.h"
#import "OFString.h"
#import "OFURI.h"

@implementation OFCreateSymbolicLinkFailedException
@synthesize URI = _URI, target = _target, errNo = _errNo;

+ (instancetype)exception
{
	OF_UNRECOGNIZED_SELECTOR
}

+ (instancetype)exceptionWithURI: (OFURI *)URI
			  target: (OFString *)target
			   errNo: (int)errNo
{
	return [[[self alloc] initWithURI: URI
				   target: target
				    errNo: errNo] autorelease];
}

- (instancetype)init
{
	OF_INVALID_INIT_METHOD
}

- (instancetype)initWithURI: (OFURI *)URI
		     target: (OFString *)target
		      errNo: (int)errNo
{
	self = [super init];

	@try {
		_URI = [URI copy];
		_target = [target copy];
		_errNo = errNo;
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (void)dealloc
{
	[_URI release];
	[_target release];

	[super dealloc];
}

- (OFString *)description
{
	return [OFString stringWithFormat:
	    @"Failed to create symbolic link %@ with target %@: %@",
	    _URI, _target, OFStrError(_errNo)];
}
@end

|
















|
|


|






|



|









|






|












|









|


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
/*
 * Copyright (c) 2008-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 "OFCreateSymbolicLinkFailedException.h"
#import "OFIRI.h"
#import "OFString.h"

@implementation OFCreateSymbolicLinkFailedException
@synthesize IRI = _IRI, target = _target, errNo = _errNo;

+ (instancetype)exception
{
	OF_UNRECOGNIZED_SELECTOR
}

+ (instancetype)exceptionWithIRI: (OFIRI *)IRI
			  target: (OFString *)target
			   errNo: (int)errNo
{
	return [[[self alloc] initWithIRI: IRI
				   target: target
				    errNo: errNo] autorelease];
}

- (instancetype)init
{
	OF_INVALID_INIT_METHOD
}

- (instancetype)initWithIRI: (OFIRI *)IRI
		     target: (OFString *)target
		      errNo: (int)errNo
{
	self = [super init];

	@try {
		_IRI = [IRI copy];
		_target = [target copy];
		_errNo = errNo;
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (void)dealloc
{
	[_IRI release];
	[_target release];

	[super dealloc];
}

- (OFString *)description
{
	return [OFString stringWithFormat:
	    @"Failed to create symbolic link %@ with target %@: %@",
	    _IRI, _target, OFStrError(_errNo)];
}
@end

Modified src/exceptions/OFCreateWindowsRegistryKeyFailedException.h from [3739e39dc2] to [50fe38db48].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFCreateWindowsRegistryKeyFailedException.m from [3f8a5e58b7] to [6e7d2b3d40].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFDNSQueryFailedException.h from [e0cf12b730] to [e0bfabb924].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFDNSQueryFailedException.m from [d34eb3c9de] to [05adcdd60e].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFDeleteWindowsRegistryKeyFailedException.h from [7a006ec7b5] to [48d9cd8762].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFDeleteWindowsRegistryKeyFailedException.m from [123f06f5d8] to [afb297b235].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFDeleteWindowsRegistryValueFailedException.h from [0a7f480a16] to [bd06338798].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFDeleteWindowsRegistryValueFailedException.m from [efa255c388] to [e51a2078ac].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFEnumerationMutationException.h from [1a130e7399] to [26657aa11a].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFEnumerationMutationException.m from [f408c0df64] to [7ff22fe2ad].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFException.h from [e7c0836484] to [97c5efe66a].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFException.m from [700714ee53] to [aa2fc710c4].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFGetCurrentDirectoryFailedException.h from [60ae2d8910] to [2cdfac4af1].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFGetCurrentDirectoryFailedException.m from [b29d0ac295] to [032fd435d7].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFGetItemAttributesFailedException.h from [354af07fb2] to [6b18fe3b15].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#import "OFException.h"

OF_ASSUME_NONNULL_BEGIN

@class OFURI;

/**
 * @class OFGetItemAttributesFailedException \
 *	  OFGetItemAttributesFailedException.h \
 *	  ObjFW/OFGetItemAttributesFailedException.h
 *
 * @brief An exception indicating an item's attributes could not be retrieved.
 */
@interface OFGetItemAttributesFailedException: OFException
{
	OFURI *_URI;
	int _errNo;
	OF_RESERVE_IVARS(OFGetItemAttributesFailedException, 4)
}

/**
 * @brief The URI of the item whose attributes could not be retrieved.
 */
@property (readonly, nonatomic) OFURI *URI;

/**
 * @brief The errno of the error that occurred.
 */
@property (readonly, nonatomic) int errNo;

/**
 * @brief Creates a new, autoreleased retrieve item attributes failed exception.
 *
 * @param URI The URI of the item whose attributes could not be retrieved
 * @param errNo The errno of the error that occurred
 * @return A new, autoreleased retrieve item attributes failed exception
 */
+ (instancetype)exceptionWithURI: (OFURI *)URI errNo: (int)errNo;

+ (instancetype)exception OF_UNAVAILABLE;

/**
 * @brief Initializes an already allocated retrieve item attributes failed
 *	  exception.
 *
 * @param URI The URI of the item whose attributes could not be retrieved
 * @param errNo The errno of the error that occurred
 * @return An initialized retrieve item attributes failed exception
 */
- (instancetype)initWithURI: (OFURI *)URI
		      errNo: (int)errNo OF_DESIGNATED_INITIALIZER;

- (instancetype)init OF_UNAVAILABLE;
@end

OF_ASSUME_NONNULL_END

|

















|










|





|

|









|



|







|



|






1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
/*
 * Copyright (c) 2008-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"

OF_ASSUME_NONNULL_BEGIN

@class OFIRI;

/**
 * @class OFGetItemAttributesFailedException \
 *	  OFGetItemAttributesFailedException.h \
 *	  ObjFW/OFGetItemAttributesFailedException.h
 *
 * @brief An exception indicating an item's attributes could not be retrieved.
 */
@interface OFGetItemAttributesFailedException: OFException
{
	OFIRI *_IRI;
	int _errNo;
	OF_RESERVE_IVARS(OFGetItemAttributesFailedException, 4)
}

/**
 * @brief The IRI of the item whose attributes could not be retrieved.
 */
@property (readonly, nonatomic) OFIRI *IRI;

/**
 * @brief The errno of the error that occurred.
 */
@property (readonly, nonatomic) int errNo;

/**
 * @brief Creates a new, autoreleased retrieve item attributes failed exception.
 *
 * @param IRI The IRI of the item whose attributes could not be retrieved
 * @param errNo The errno of the error that occurred
 * @return A new, autoreleased retrieve item attributes failed exception
 */
+ (instancetype)exceptionWithIRI: (OFIRI *)IRI errNo: (int)errNo;

+ (instancetype)exception OF_UNAVAILABLE;

/**
 * @brief Initializes an already allocated retrieve item attributes failed
 *	  exception.
 *
 * @param IRI The IRI of the item whose attributes could not be retrieved
 * @param errNo The errno of the error that occurred
 * @return An initialized retrieve item attributes failed exception
 */
- (instancetype)initWithIRI: (OFIRI *)IRI
		      errNo: (int)errNo OF_DESIGNATED_INITIALIZER;

- (instancetype)init OF_UNAVAILABLE;
@end

OF_ASSUME_NONNULL_END

Modified src/exceptions/OFGetItemAttributesFailedException.m from [db212ce8f9] to [879972dfb1].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#import "OFGetItemAttributesFailedException.h"
#import "OFString.h"
#import "OFURI.h"

@implementation OFGetItemAttributesFailedException
@synthesize URI = _URI, errNo = _errNo;

+ (instancetype)exception
{
	OF_UNRECOGNIZED_SELECTOR
}

+ (instancetype)exceptionWithURI: (OFURI *)URI errNo: (int)errNo
{
	return [[[self alloc] initWithURI: URI errNo: errNo] autorelease];
}

- (instancetype)init
{
	OF_INVALID_INIT_METHOD
}

- (instancetype)initWithURI: (OFURI *)URI errNo: (int)errNo
{
	self = [super init];

	@try {
		_URI = [URI copy];
		_errNo = errNo;
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (void)dealloc
{
	[_URI release];

	[super dealloc];
}

- (OFString *)description
{
	return [OFString stringWithFormat:
	    @"Failed to get attributes for item %@: %@",
	    _URI, OFStrError(_errNo)];
}
@end

|
















|
|


|






|

|







|




|











|








|


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
/*
 * Copyright (c) 2008-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 "OFGetItemAttributesFailedException.h"
#import "OFIRI.h"
#import "OFString.h"

@implementation OFGetItemAttributesFailedException
@synthesize IRI = _IRI, errNo = _errNo;

+ (instancetype)exception
{
	OF_UNRECOGNIZED_SELECTOR
}

+ (instancetype)exceptionWithIRI: (OFIRI *)IRI errNo: (int)errNo
{
	return [[[self alloc] initWithIRI: IRI errNo: errNo] autorelease];
}

- (instancetype)init
{
	OF_INVALID_INIT_METHOD
}

- (instancetype)initWithIRI: (OFIRI *)IRI errNo: (int)errNo
{
	self = [super init];

	@try {
		_IRI = [IRI copy];
		_errNo = errNo;
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (void)dealloc
{
	[_IRI release];

	[super dealloc];
}

- (OFString *)description
{
	return [OFString stringWithFormat:
	    @"Failed to get attributes for item %@: %@",
	    _IRI, OFStrError(_errNo)];
}
@end

Modified src/exceptions/OFGetOptionFailedException.h from [a8c8d533b3] to [aae90c71d3].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
 * @class OFGetOptionFailedException \
 *	  OFGetOptionFailedException.h ObjFW/OFGetOptionFailedException.h
 *
 * @brief An exception indicating that getting an option for an object failed.
 */
@interface OFGetOptionFailedException: OFException
{
	id _object;
	int _errNo;
	OF_RESERVE_IVARS(OFGetOptionFailedException, 4)
}

/**
 * @brief The object for which the option could not be retrieved.
 */
@property (readonly, nonatomic) id object;

/**
 * @brief The errno of the error that occurred.
 */
@property (readonly, nonatomic) int errNo;

/**
 * @brief Creates a new, autoreleased get option failed exception.
 *
 * @param object The object for which the option could not be retrieved
 * @param errNo The errno of the error that occurred
 * @return A new, autoreleased get option failed exception
 */
+ (instancetype)exceptionWithObject: (id)object errNo: (int)errNo;

+ (instancetype)exception OF_UNAVAILABLE;

/**
 * @brief Initializes an already allocated get option failed exception.
 *
 * @param object The object for which the option could not be retrieved
 * @param errNo The errno of the error that occurred
 * @return An initialized get option failed exception
 */
- (instancetype)initWithObject: (id)object
			 errNo: (int)errNo OF_DESIGNATED_INITIALIZER;

- (instancetype)init OF_UNAVAILABLE;
@end

OF_ASSUME_NONNULL_END







|







|













|










|






21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
 * @class OFGetOptionFailedException \
 *	  OFGetOptionFailedException.h ObjFW/OFGetOptionFailedException.h
 *
 * @brief An exception indicating that getting an option for an object failed.
 */
@interface OFGetOptionFailedException: OFException
{
	id _Nullable _object;
	int _errNo;
	OF_RESERVE_IVARS(OFGetOptionFailedException, 4)
}

/**
 * @brief The object for which the option could not be retrieved.
 */
@property OF_NULLABLE_PROPERTY (readonly, nonatomic) id object;

/**
 * @brief The errno of the error that occurred.
 */
@property (readonly, nonatomic) int errNo;

/**
 * @brief Creates a new, autoreleased get option failed exception.
 *
 * @param object The object for which the option could not be retrieved
 * @param errNo The errno of the error that occurred
 * @return A new, autoreleased get option failed exception
 */
+ (instancetype)exceptionWithObject: (nullable id)object errNo: (int)errNo;

+ (instancetype)exception OF_UNAVAILABLE;

/**
 * @brief Initializes an already allocated get option failed exception.
 *
 * @param object The object for which the option could not be retrieved
 * @param errNo The errno of the error that occurred
 * @return An initialized get option failed exception
 */
- (instancetype)initWithObject: (nullable id)object
			 errNo: (int)errNo OF_DESIGNATED_INITIALIZER;

- (instancetype)init OF_UNAVAILABLE;
@end

OF_ASSUME_NONNULL_END

Modified src/exceptions/OFGetOptionFailedException.m from [aeeadc602d] to [bcad1d6dec].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
51
52
53
54
55
56
57

58
59
60



61
62
	[_object release];

	[super dealloc];
}

- (OFString *)description
{

	return [OFString stringWithFormat:
	    @"Getting an option in an object of type %@ failed: %@",
	    [_object class], OFStrError(_errNo)];



}
@end







>
|
|
|
>
>
>


51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
	[_object release];

	[super dealloc];
}

- (OFString *)description
{
	if (_object != nil)
		return [OFString stringWithFormat:
		    @"Getting an option in an object of type %@ failed: %@",
		    [_object class], OFStrError(_errNo)];
	else
		return [OFString stringWithFormat:
		    @"Getting an option failed: %@", OFStrError(_errNo)];
}
@end

Modified src/exceptions/OFGetWindowsRegistryValueFailedException.h from [1bae299028] to [2442379612].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFGetWindowsRegistryValueFailedException.m from [57087b05b3] to [92bc5d3ce4].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFHTTPRequestFailedException.h from [d5947528d2] to [2a60d01cb7].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFHTTPRequestFailedException.m from [f93ff97e23] to [873118e171].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
57
58
59
60
61
62
63
64
65
66
67
68
69
70
	[_response release];

	[super dealloc];
}

- (OFString *)description
{
	const char *method = OFHTTPRequestMethodName(_request.method);

	return [OFString stringWithFormat:
	    @"An HTTP %s request with URI %@ failed with code %hd!", method,
	    _request.URI, _response.statusCode];
}
@end







|


|
|


57
58
59
60
61
62
63
64
65
66
67
68
69
70
	[_response release];

	[super dealloc];
}

- (OFString *)description
{
	OFString *method = OFHTTPRequestMethodString(_request.method);

	return [OFString stringWithFormat:
	    @"An HTTP %@ request with IRI %@ failed with code %hd!", method,
	    _request.IRI, _response.statusCode];
}
@end

Modified src/exceptions/OFHashAlreadyCalculatedException.h from [0455e7b89e] to [65495fc28e].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFHashAlreadyCalculatedException.m from [cf2d8e44b5] to [4951347084].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFHashNotCalculatedException.h from [e76b9886eb] to [ffeb0b69ee].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFHashNotCalculatedException.m from [3e84cb3642] to [2494da87d2].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFInitializationFailedException.h from [280997dfe1] to [54d7f4adaf].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFInitializationFailedException.m from [cfa23bb7fe] to [1695829c14].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFInvalidArgumentException.h from [835c000126] to [25d23dc103].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFInvalidArgumentException.m from [70957802ed] to [5dc138e811].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFInvalidEncodingException.h from [36e737e07d] to [efca50d8c1].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFInvalidEncodingException.m from [7e85cac169] to [5a8e7a496a].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFInvalidFormatException.h from [7bd0078c9f] to [2320dd7c5c].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFInvalidFormatException.m from [f3d13d03ab] to [c0e5a29bab].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFInvalidJSONException.h from [a9bef800fe] to [9cb620be01].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFInvalidJSONException.m from [973f5127bd] to [f3162443ab].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFInvalidServerResponseException.h from [8680d9915b] to [8c9dc17ff5].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFInvalidServerResponseException.m from [8436f85f3d] to [4ff650e316].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFJoinThreadFailedException.h from [b841fb7f6d] to [23ac9ec161].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFJoinThreadFailedException.m from [7e2f0f00c7] to [2175d07408].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFLinkItemFailedException.h from [bc4e6321e5] to [a8e91f4a64].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#import "OFException.h"

OF_ASSUME_NONNULL_BEGIN

@class OFURI;

/**
 * @class OFLinkItemFailedException \
 *	  OFLinkItemFailedException.h ObjFW/OFLinkItemFailedException.h
 *
 * @brief An exception indicating that creating a link failed.
 */
@interface OFLinkItemFailedException: OFException
{
	OFURI *_sourceURI, *_destinationURI;
	int _errNo;
	OF_RESERVE_IVARS(OFLinkItemFailedException, 4)
}

/**
 * @brief A URI with the source for the link.
 */
@property (readonly, nonatomic) OFURI *sourceURI;

/**
 * @brief A URI with the destination for the link.
 */
@property (readonly, nonatomic) OFURI *destinationURI;

/**
 * @brief The errno of the error that occurred.
 */
@property (readonly, nonatomic) int errNo;

/**
 * @brief Creates a new, autoreleased link failed exception.
 *
 * @param sourceURI The source for the link
 * @param destinationURI The destination for the link
 * @param errNo The errno of the error that occurred
 * @return A new, autoreleased link failed exception
 */
+ (instancetype)exceptionWithSourceURI: (OFURI *)sourceURI
			destinationURI: (OFURI *)destinationURI
				 errNo: (int)errNo;

+ (instancetype)exception OF_UNAVAILABLE;

/**
 * @brief Initializes an already allocated link failed exception.
 *
 * @param sourceURI The source for the link
 * @param destinationURI The destination for the link
 * @param errNo The errno of the error that occurred
 * @return An initialized link failed exception
 */
- (instancetype)initWithSourceURI: (OFURI*)sourceURI
		   destinationURI: (OFURI *)destinationURI
			    errNo: (int)errNo OF_DESIGNATED_INITIALIZER;

- (instancetype)init OF_UNAVAILABLE;
@end

OF_ASSUME_NONNULL_END

|

















|









|





|

|


|

|









|
|



|
|







|
|



|
|






1
2
3
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 "OFException.h"

OF_ASSUME_NONNULL_BEGIN

@class OFIRI;

/**
 * @class OFLinkItemFailedException \
 *	  OFLinkItemFailedException.h ObjFW/OFLinkItemFailedException.h
 *
 * @brief An exception indicating that creating a link failed.
 */
@interface OFLinkItemFailedException: OFException
{
	OFIRI *_sourceIRI, *_destinationIRI;
	int _errNo;
	OF_RESERVE_IVARS(OFLinkItemFailedException, 4)
}

/**
 * @brief An IRI with the source for the link.
 */
@property (readonly, nonatomic) OFIRI *sourceIRI;

/**
 * @brief An IRI with the destination for the link.
 */
@property (readonly, nonatomic) OFIRI *destinationIRI;

/**
 * @brief The errno of the error that occurred.
 */
@property (readonly, nonatomic) int errNo;

/**
 * @brief Creates a new, autoreleased link failed exception.
 *
 * @param sourceIRI The source for the link
 * @param destinationIRI The destination for the link
 * @param errNo The errno of the error that occurred
 * @return A new, autoreleased link failed exception
 */
+ (instancetype)exceptionWithSourceIRI: (OFIRI *)sourceIRI
			destinationIRI: (OFIRI *)destinationIRI
				 errNo: (int)errNo;

+ (instancetype)exception OF_UNAVAILABLE;

/**
 * @brief Initializes an already allocated link failed exception.
 *
 * @param sourceIRI The source for the link
 * @param destinationIRI The destination for the link
 * @param errNo The errno of the error that occurred
 * @return An initialized link failed exception
 */
- (instancetype)initWithSourceIRI: (OFIRI*)sourceIRI
		   destinationIRI: (OFIRI *)destinationIRI
			    errNo: (int)errNo OF_DESIGNATED_INITIALIZER;

- (instancetype)init OF_UNAVAILABLE;
@end

OF_ASSUME_NONNULL_END

Modified src/exceptions/OFLinkItemFailedException.m from [3033895110] to [39970032b6].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#import "OFLinkItemFailedException.h"
#import "OFString.h"
#import "OFURI.h"

@implementation OFLinkItemFailedException
@synthesize sourceURI = _sourceURI, destinationURI = _destinationURI;
@synthesize errNo = _errNo;

+ (instancetype)exception
{
	OF_UNRECOGNIZED_SELECTOR
}

+ (instancetype)exceptionWithSourceURI: (OFURI *)sourceURI
			destinationURI: (OFURI *)destinationURI
				 errNo: (int)errNo
{
	return [[[self alloc] initWithSourceURI: sourceURI
				 destinationURI: destinationURI
					  errNo: errNo] autorelease];
}

- (instancetype)init
{
	OF_INVALID_INIT_METHOD
}

- (instancetype)initWithSourceURI: (OFURI *)sourceURI
		   destinationURI: (OFURI *)destinationURI
			    errNo: (int)errNo
{
	self = [super init];

	@try {
		_sourceURI = [sourceURI copy];
		_destinationURI = [destinationURI copy];
		_errNo = errNo;
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (void)dealloc
{
	[_sourceURI release];
	[_destinationURI release];

	[super dealloc];
}

- (OFString *)description
{
	return [OFString stringWithFormat: @"Failed to link file %@ to %@: %@",
	    _sourceURI, _destinationURI, OFStrError(_errNo)];
}
@end

|
















|
|


|







|
|


|
|








|
|





|
|











|
|







|


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
/*
 * Copyright (c) 2008-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 "OFLinkItemFailedException.h"
#import "OFIRI.h"
#import "OFString.h"

@implementation OFLinkItemFailedException
@synthesize sourceIRI = _sourceIRI, destinationIRI = _destinationIRI;
@synthesize errNo = _errNo;

+ (instancetype)exception
{
	OF_UNRECOGNIZED_SELECTOR
}

+ (instancetype)exceptionWithSourceIRI: (OFIRI *)sourceIRI
			destinationIRI: (OFIRI *)destinationIRI
				 errNo: (int)errNo
{
	return [[[self alloc] initWithSourceIRI: sourceIRI
				 destinationIRI: destinationIRI
					  errNo: errNo] autorelease];
}

- (instancetype)init
{
	OF_INVALID_INIT_METHOD
}

- (instancetype)initWithSourceIRI: (OFIRI *)sourceIRI
		   destinationIRI: (OFIRI *)destinationIRI
			    errNo: (int)errNo
{
	self = [super init];

	@try {
		_sourceIRI = [sourceIRI copy];
		_destinationIRI = [destinationIRI copy];
		_errNo = errNo;
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (void)dealloc
{
	[_sourceIRI release];
	[_destinationIRI release];

	[super dealloc];
}

- (OFString *)description
{
	return [OFString stringWithFormat: @"Failed to link file %@ to %@: %@",
	    _sourceIRI, _destinationIRI, OFStrError(_errNo)];
}
@end

Modified src/exceptions/OFListenOnSocketFailedException.h from [98d11c8685] to [947935e4c8].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFListenOnSocketFailedException.m from [5b45bde80b] to [119ebe79b1].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFLoadPluginFailedException.h from [bb70233a5c] to [1532e45ab2].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFLoadPluginFailedException.m from [73caeab9c3] to [64cc4bb1d3].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFLockFailedException.h from [58545dfa42] to [2d729ada0b].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFLockFailedException.m from [77b32492ca] to [6921dd8baf].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFMalformedXMLException.h from [d319798b44] to [fdf8d2fd37].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFMalformedXMLException.m from [f5ceb7c800] to [365a9d8f2f].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFMoveItemFailedException.h from [f2cc0cdf02] to [5748869676].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#import "OFException.h"

OF_ASSUME_NONNULL_BEGIN

@class OFURI;

/**
 * @class OFMoveItemFailedException \
 *	  OFMoveItemFailedException.h ObjFW/OFMoveItemFailedException.h
 *
 * @brief An exception indicating that moving an item failed.
 */
@interface OFMoveItemFailedException: OFException
{
	OFURI *_sourceURI, *_destinationURI;
	int _errNo;
	OF_RESERVE_IVARS(OFMoveItemFailedException, 4)
}

/**
 * @brief The original URI.
 */
@property (readonly, nonatomic) OFURI *sourceURI;

/**
 * @brief The new URI.
 */
@property (readonly, nonatomic) OFURI *destinationURI;

/**
 * @brief The errno of the error that occurred.
 */
@property (readonly, nonatomic) int errNo;

/**
 * @brief Creates a new, autoreleased move item failed exception.
 *
 * @param sourceURI The original URI
 * @param destinationURI The new URI
 * @param errNo The errno of the error that occurred
 * @return A new, autoreleased move item failed exception
 */
+ (instancetype)exceptionWithSourceURI: (OFURI *)sourceURI
			destinationURI: (OFURI *)destinationURI
				 errNo: (int)errNo;

+ (instancetype)exception OF_UNAVAILABLE;

/**
 * @brief Initializes an already allocated move item failed exception.
 *
 * @param sourceURI The original URI
 * @param destinationURI The new URI
 * @param errNo The errno of the error that occurred
 * @return An initialized move item failed exception
 */
- (instancetype)initWithSourceURI: (OFURI *)sourceURI
		   destinationURI: (OFURI *)destinationURI
			    errNo: (int)errNo OF_DESIGNATED_INITIALIZER;

- (instancetype)init OF_UNAVAILABLE;
@end

OF_ASSUME_NONNULL_END

|

















|









|





|

|


|

|









|
|



|
|







|
|



|
|






1
2
3
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 "OFException.h"

OF_ASSUME_NONNULL_BEGIN

@class OFIRI;

/**
 * @class OFMoveItemFailedException \
 *	  OFMoveItemFailedException.h ObjFW/OFMoveItemFailedException.h
 *
 * @brief An exception indicating that moving an item failed.
 */
@interface OFMoveItemFailedException: OFException
{
	OFIRI *_sourceIRI, *_destinationIRI;
	int _errNo;
	OF_RESERVE_IVARS(OFMoveItemFailedException, 4)
}

/**
 * @brief The original IRI.
 */
@property (readonly, nonatomic) OFIRI *sourceIRI;

/**
 * @brief The new IRI.
 */
@property (readonly, nonatomic) OFIRI *destinationIRI;

/**
 * @brief The errno of the error that occurred.
 */
@property (readonly, nonatomic) int errNo;

/**
 * @brief Creates a new, autoreleased move item failed exception.
 *
 * @param sourceIRI The original IRI
 * @param destinationIRI The new IRI
 * @param errNo The errno of the error that occurred
 * @return A new, autoreleased move item failed exception
 */
+ (instancetype)exceptionWithSourceIRI: (OFIRI *)sourceIRI
			destinationIRI: (OFIRI *)destinationIRI
				 errNo: (int)errNo;

+ (instancetype)exception OF_UNAVAILABLE;

/**
 * @brief Initializes an already allocated move item failed exception.
 *
 * @param sourceIRI The original IRI
 * @param destinationIRI The new IRI
 * @param errNo The errno of the error that occurred
 * @return An initialized move item failed exception
 */
- (instancetype)initWithSourceIRI: (OFIRI *)sourceIRI
		   destinationIRI: (OFIRI *)destinationIRI
			    errNo: (int)errNo OF_DESIGNATED_INITIALIZER;

- (instancetype)init OF_UNAVAILABLE;
@end

OF_ASSUME_NONNULL_END

Modified src/exceptions/OFMoveItemFailedException.m from [7df7241c06] to [c0be4f4231].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#import "OFMoveItemFailedException.h"
#import "OFString.h"
#import "OFURI.h"

@implementation OFMoveItemFailedException
@synthesize sourceURI = _sourceURI, destinationURI = _destinationURI;
@synthesize errNo = _errNo;

+ (instancetype)exception
{
	OF_UNRECOGNIZED_SELECTOR
}

+ (instancetype)exceptionWithSourceURI: (OFURI *)sourceURI
			destinationURI: (OFURI *)destinationURI
				 errNo: (int)errNo
{
	return [[[self alloc] initWithSourceURI: sourceURI
				 destinationURI: destinationURI
					  errNo: errNo] autorelease];
}

- (instancetype)init
{
	OF_INVALID_INIT_METHOD
}

- (instancetype)initWithSourceURI: (OFURI *)sourceURI
		   destinationURI: (OFURI *)destinationURI
			    errNo: (int)errNo
{
	self = [super init];

	@try {
		_sourceURI = [sourceURI copy];
		_destinationURI = [destinationURI copy];
		_errNo = errNo;
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (void)dealloc
{
	[_sourceURI release];
	[_destinationURI release];

	[super dealloc];
}

- (OFString *)description
{
	return [OFString stringWithFormat:
	    @"Failed to move item at %@ to %@: %@",
	    _sourceURI, _destinationURI, OFStrError(_errNo)];
}
@end

|
















|
|


|







|
|


|
|








|
|





|
|











|
|








|


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
/*
 * Copyright (c) 2008-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 "OFMoveItemFailedException.h"
#import "OFIRI.h"
#import "OFString.h"

@implementation OFMoveItemFailedException
@synthesize sourceIRI = _sourceIRI, destinationIRI = _destinationIRI;
@synthesize errNo = _errNo;

+ (instancetype)exception
{
	OF_UNRECOGNIZED_SELECTOR
}

+ (instancetype)exceptionWithSourceIRI: (OFIRI *)sourceIRI
			destinationIRI: (OFIRI *)destinationIRI
				 errNo: (int)errNo
{
	return [[[self alloc] initWithSourceIRI: sourceIRI
				 destinationIRI: destinationIRI
					  errNo: errNo] autorelease];
}

- (instancetype)init
{
	OF_INVALID_INIT_METHOD
}

- (instancetype)initWithSourceIRI: (OFIRI *)sourceIRI
		   destinationIRI: (OFIRI *)destinationIRI
			    errNo: (int)errNo
{
	self = [super init];

	@try {
		_sourceIRI = [sourceIRI copy];
		_destinationIRI = [destinationIRI copy];
		_errNo = errNo;
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (void)dealloc
{
	[_sourceIRI release];
	[_destinationIRI release];

	[super dealloc];
}

- (OFString *)description
{
	return [OFString stringWithFormat:
	    @"Failed to move item at %@ to %@: %@",
	    _sourceIRI, _destinationIRI, OFStrError(_errNo)];
}
@end

Modified src/exceptions/OFNotImplementedException.h from [f0426204c4] to [00fd29b658].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFNotImplementedException.m from [c04e46d7c8] to [f46b1e8fba].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFNotOpenException.h from [5a826ad61e] to [16cd531d6c].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFNotOpenException.m from [b0a200e662] to [6cbb571f79].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFObserveKernelEventsFailedException.h from [a11562c534] to [7f06bdef92].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFObserveKernelEventsFailedException.m from [1f89b66175] to [82ead321f6].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFOpenItemFailedException.h from [fe988003bf] to [fe58b96b56].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#import "OFException.h"

OF_ASSUME_NONNULL_BEGIN

@class OFURI;

/**
 * @class OFOpenItemFailedException \
 *	  OFOpenItemFailedException.h ObjFW/OFOpenItemFailedException.h
 *
 * @brief An exception indicating an item could not be opened.
 */
@interface OFOpenItemFailedException: OFException
{
	OFURI *_Nullable _URI;
	OFString *_Nullable _path;
	OFString *_mode;
	int _errNo;
	OF_RESERVE_IVARS(OFOpenItemFailedException, 4)
}

/**
 * @brief The URI of the item which could not be opened.
 */
@property OF_NULLABLE_PROPERTY (readonly, nonatomic) OFURI *URI;

/**
 * @brief The path of the item which could not be opened.
 */
@property OF_NULLABLE_PROPERTY (readonly, nonatomic) OFString *path;

/**
 * @brief The mode in which the item should have been opened.
 */
@property OF_NULLABLE_PROPERTY (readonly, nonatomic) OFString *mode;

/**
 * @brief The errno of the error that occurred.
 */
@property (readonly, nonatomic) int errNo;

/**
 * @brief Creates a new, autoreleased open item failed exception.
 *
 * @param URI The URI of the item which could not be opened
 * @param mode A string with the mode in which the item should have been opened
 * @param errNo The errno of the error that occurred
 * @return A new, autoreleased open item failed exception
 */
+ (instancetype)exceptionWithURI: (OFURI *)URI
			    mode: (nullable OFString *)mode
			   errNo: (int)errNo;

/**
 * @brief Creates a new, autoreleased open item failed exception.
 *
 * @param path The path of the item which could not be opened
 * @param mode A string with the mode in which the item should have been opened
 * @param errNo The errno of the error that occurred
 * @return A new, autoreleased open item failed exception
 */
+ (instancetype)exceptionWithPath: (OFString *)path
			     mode: (nullable OFString *)mode
			    errNo: (int)errNo;

+ (instancetype)exception OF_UNAVAILABLE;

/**
 * @brief Initializes an already allocated open item failed exception.
 *
 * @param URI The URI of the item which could not be opened
 * @param mode A string with the mode in which the item should have been opened
 * @param errNo The errno of the error that occurred
 * @return An initialized open item failed exception
 */
- (instancetype)initWithURI: (OFURI *)URI
		       mode: (nullable OFString *)mode
		      errNo: (int)errNo;

/**
 * @brief Initializes an already allocated open item failed exception.
 *
 * @param path The path of the item which could not be opened

|

















|









|







|

|



















|




|




















|




|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
/*
 * Copyright (c) 2008-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"

OF_ASSUME_NONNULL_BEGIN

@class OFIRI;

/**
 * @class OFOpenItemFailedException \
 *	  OFOpenItemFailedException.h ObjFW/OFOpenItemFailedException.h
 *
 * @brief An exception indicating an item could not be opened.
 */
@interface OFOpenItemFailedException: OFException
{
	OFIRI *_Nullable _IRI;
	OFString *_Nullable _path;
	OFString *_mode;
	int _errNo;
	OF_RESERVE_IVARS(OFOpenItemFailedException, 4)
}

/**
 * @brief The IRI of the item which could not be opened.
 */
@property OF_NULLABLE_PROPERTY (readonly, nonatomic) OFIRI *IRI;

/**
 * @brief The path of the item which could not be opened.
 */
@property OF_NULLABLE_PROPERTY (readonly, nonatomic) OFString *path;

/**
 * @brief The mode in which the item should have been opened.
 */
@property OF_NULLABLE_PROPERTY (readonly, nonatomic) OFString *mode;

/**
 * @brief The errno of the error that occurred.
 */
@property (readonly, nonatomic) int errNo;

/**
 * @brief Creates a new, autoreleased open item failed exception.
 *
 * @param IRI The IRI of the item which could not be opened
 * @param mode A string with the mode in which the item should have been opened
 * @param errNo The errno of the error that occurred
 * @return A new, autoreleased open item failed exception
 */
+ (instancetype)exceptionWithIRI: (OFIRI *)IRI
			    mode: (nullable OFString *)mode
			   errNo: (int)errNo;

/**
 * @brief Creates a new, autoreleased open item failed exception.
 *
 * @param path The path of the item which could not be opened
 * @param mode A string with the mode in which the item should have been opened
 * @param errNo The errno of the error that occurred
 * @return A new, autoreleased open item failed exception
 */
+ (instancetype)exceptionWithPath: (OFString *)path
			     mode: (nullable OFString *)mode
			    errNo: (int)errNo;

+ (instancetype)exception OF_UNAVAILABLE;

/**
 * @brief Initializes an already allocated open item failed exception.
 *
 * @param IRI The IRI of the item which could not be opened
 * @param mode A string with the mode in which the item should have been opened
 * @param errNo The errno of the error that occurred
 * @return An initialized open item failed exception
 */
- (instancetype)initWithIRI: (OFIRI *)IRI
		       mode: (nullable OFString *)mode
		      errNo: (int)errNo;

/**
 * @brief Initializes an already allocated open item failed exception.
 *
 * @param path The path of the item which could not be opened

Modified src/exceptions/OFOpenItemFailedException.m from [7129cdf836] to [983180045f].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#import "OFOpenItemFailedException.h"
#import "OFString.h"
#import "OFURI.h"

@implementation OFOpenItemFailedException
@synthesize URI = _URI, path = _path, mode = _mode, errNo = _errNo;

+ (instancetype)exceptionWithURI: (OFURI *)URI
			    mode: (OFString *)mode
			   errNo: (int)errNo
{
	return [[[self alloc] initWithURI: URI
				     mode: mode
				    errNo: errNo] autorelease];
}

+ (instancetype)exceptionWithPath: (OFString *)path
			     mode: (OFString *)mode
			    errNo: (int)errNo
{
	return [[[self alloc] initWithPath: path
				      mode: mode
				     errNo: errNo] autorelease];
}

+ (instancetype)exception
{
	OF_UNRECOGNIZED_SELECTOR
}

- (instancetype)initWithURI: (OFURI *)URI
		       mode: (OFString *)mode
		      errNo: (int)errNo
{
	self = [super init];

	@try {
		_URI = [URI copy];
		_mode = [mode copy];
		_errNo = errNo;
	} @catch (id e) {
		[self release];
		@throw e;
	}


|
















|
|


|

|



|


















|






|







1
2
3
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"

#import "OFOpenItemFailedException.h"
#import "OFIRI.h"
#import "OFString.h"

@implementation OFOpenItemFailedException
@synthesize IRI = _IRI, path = _path, mode = _mode, errNo = _errNo;

+ (instancetype)exceptionWithIRI: (OFIRI *)IRI
			    mode: (OFString *)mode
			   errNo: (int)errNo
{
	return [[[self alloc] initWithIRI: IRI
				     mode: mode
				    errNo: errNo] autorelease];
}

+ (instancetype)exceptionWithPath: (OFString *)path
			     mode: (OFString *)mode
			    errNo: (int)errNo
{
	return [[[self alloc] initWithPath: path
				      mode: mode
				     errNo: errNo] autorelease];
}

+ (instancetype)exception
{
	OF_UNRECOGNIZED_SELECTOR
}

- (instancetype)initWithIRI: (OFIRI *)IRI
		       mode: (OFString *)mode
		      errNo: (int)errNo
{
	self = [super init];

	@try {
		_IRI = [IRI copy];
		_mode = [mode copy];
		_errNo = errNo;
	} @catch (id e) {
		[self release];
		@throw e;
	}

84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
- (instancetype)init
{
	OF_INVALID_INIT_METHOD
}

- (void)dealloc
{
	[_URI release];
	[_path release];
	[_mode release];

	[super dealloc];
}

- (OFString *)description
{
	id item = nil;

	if (_URI != nil)
		item = _URI;
	else if (_path != nil)
		item = _path;

	if (_mode != nil)
		return [OFString stringWithFormat:
		    @"Failed to open file %@ with mode %@: %@",
		    item, _mode, OFStrError(_errNo)];
	else
		return [OFString stringWithFormat:
		    @"Failed to open item %@: %@", item, OFStrError(_errNo)];
}
@end







|










|
|












84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
- (instancetype)init
{
	OF_INVALID_INIT_METHOD
}

- (void)dealloc
{
	[_IRI release];
	[_path release];
	[_mode release];

	[super dealloc];
}

- (OFString *)description
{
	id item = nil;

	if (_IRI != nil)
		item = _IRI;
	else if (_path != nil)
		item = _path;

	if (_mode != nil)
		return [OFString stringWithFormat:
		    @"Failed to open file %@ with mode %@: %@",
		    item, _mode, OFStrError(_errNo)];
	else
		return [OFString stringWithFormat:
		    @"Failed to open item %@: %@", item, OFStrError(_errNo)];
}
@end

Modified src/exceptions/OFOpenWindowsRegistryKeyFailedException.h from [36fb64cf1a] to [f20c94c64f].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFOpenWindowsRegistryKeyFailedException.m from [64b24e1261] to [e357a7d0d4].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFOutOfMemoryException.h from [f5654732f6] to [b1516ee71e].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFOutOfMemoryException.m from [f0195e5a54] to [85dee5f624].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFOutOfRangeException.h from [f8a5e124cb] to [f8b70220da].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFOutOfRangeException.m from [42dae12fbe] to [52c97f7827].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFReadFailedException.h from [1ab276c5fd] to [aef4e1650a].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFReadFailedException.m from [0a38835e23] to [d866e06309].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFReadOrWriteFailedException.h from [2c37db7aa0] to [dc1528c8fc].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFReadOrWriteFailedException.m from [02ef4afd0b] to [fed08201b6].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFRemoveItemFailedException.h from [18b7b9ee6b] to [70c54ee3fb].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#import "OFException.h"

OF_ASSUME_NONNULL_BEGIN

@class OFURI;

/**
 * @class OFRemoveItemFailedException \
 *	  OFRemoveItemFailedException.h ObjFW/OFRemoveItemFailedException.h
 *
 * @brief An exception indicating that removing an item failed.
 */
@interface OFRemoveItemFailedException: OFException
{
	OFURI *_URI;
	int _errNo;
	OF_RESERVE_IVARS(OFRemoveItemFailedException, 4)
}

/**
 * @brief The URI of the item which could not be removed.
 */
@property (readonly, nonatomic) OFURI *URI;

/**
 * @brief The errno of the error that occurred.
 */
@property (readonly, nonatomic) int errNo;

/**
 * @brief Creates a new, autoreleased remove failed exception.
 *
 * @param URI The URI of the item which could not be removed
 * @param errNo The errno of the error that occurred
 * @return A new, autoreleased remove item failed exception
 */
+ (instancetype)exceptionWithURI: (OFURI *)URI errNo: (int)errNo;

+ (instancetype)exception OF_UNAVAILABLE;

/**
 * @brief Initializes an already allocated remove failed exception.
 *
 * @param URI The URI of the item which could not be removed
 * @param errNo The errno of the error that occurred
 * @return An initialized remove item failed exception
 */
- (instancetype)initWithURI: (OFURI *)URI
		      errNo: (int)errNo OF_DESIGNATED_INITIALIZER;

- (instancetype)init OF_UNAVAILABLE;
@end

OF_ASSUME_NONNULL_END

|

















|









|





|

|









|



|






|



|






1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
/*
 * Copyright (c) 2008-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"

OF_ASSUME_NONNULL_BEGIN

@class OFIRI;

/**
 * @class OFRemoveItemFailedException \
 *	  OFRemoveItemFailedException.h ObjFW/OFRemoveItemFailedException.h
 *
 * @brief An exception indicating that removing an item failed.
 */
@interface OFRemoveItemFailedException: OFException
{
	OFIRI *_IRI;
	int _errNo;
	OF_RESERVE_IVARS(OFRemoveItemFailedException, 4)
}

/**
 * @brief The IRI of the item which could not be removed.
 */
@property (readonly, nonatomic) OFIRI *IRI;

/**
 * @brief The errno of the error that occurred.
 */
@property (readonly, nonatomic) int errNo;

/**
 * @brief Creates a new, autoreleased remove failed exception.
 *
 * @param IRI The IRI of the item which could not be removed
 * @param errNo The errno of the error that occurred
 * @return A new, autoreleased remove item failed exception
 */
+ (instancetype)exceptionWithIRI: (OFIRI *)IRI errNo: (int)errNo;

+ (instancetype)exception OF_UNAVAILABLE;

/**
 * @brief Initializes an already allocated remove failed exception.
 *
 * @param IRI The IRI of the item which could not be removed
 * @param errNo The errno of the error that occurred
 * @return An initialized remove item failed exception
 */
- (instancetype)initWithIRI: (OFIRI *)IRI
		      errNo: (int)errNo OF_DESIGNATED_INITIALIZER;

- (instancetype)init OF_UNAVAILABLE;
@end

OF_ASSUME_NONNULL_END

Modified src/exceptions/OFRemoveItemFailedException.m from [790fd92540] to [cfd5d0de3c].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#import "OFRemoveItemFailedException.h"
#import "OFString.h"
#import "OFURI.h"

@implementation OFRemoveItemFailedException
@synthesize URI = _URI, errNo = _errNo;

+ (instancetype)exception
{
	OF_UNRECOGNIZED_SELECTOR
}

+ (instancetype)exceptionWithURI: (OFURI *)URI errNo: (int)errNo
{
	return [[[self alloc] initWithURI: URI errNo: errNo] autorelease];
}

- (instancetype)init
{
	OF_INVALID_INIT_METHOD
}

- (instancetype)initWithURI: (OFURI *)URI errNo: (int)errNo
{
	self = [super init];

	@try {
		_URI = [URI copy];
		_errNo = errNo;
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (void)dealloc
{
	[_URI release];

	[super dealloc];
}

- (OFString *)description
{
	return [OFString stringWithFormat:
	    @"Failed to remove item at URI %@: %@", _URI, OFStrError(_errNo)];
}
@end

|
















|
|


|






|

|







|




|











|







|


1
2
3
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.
 */

#include "config.h"

#import "OFRemoveItemFailedException.h"
#import "OFIRI.h"
#import "OFString.h"

@implementation OFRemoveItemFailedException
@synthesize IRI = _IRI, errNo = _errNo;

+ (instancetype)exception
{
	OF_UNRECOGNIZED_SELECTOR
}

+ (instancetype)exceptionWithIRI: (OFIRI *)IRI errNo: (int)errNo
{
	return [[[self alloc] initWithIRI: IRI errNo: errNo] autorelease];
}

- (instancetype)init
{
	OF_INVALID_INIT_METHOD
}

- (instancetype)initWithIRI: (OFIRI *)IRI errNo: (int)errNo
{
	self = [super init];

	@try {
		_IRI = [IRI copy];
		_errNo = errNo;
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (void)dealloc
{
	[_IRI release];

	[super dealloc];
}

- (OFString *)description
{
	return [OFString stringWithFormat:
	    @"Failed to remove item at IRI %@: %@", _IRI, OFStrError(_errNo)];
}
@end

Modified src/exceptions/OFResolveHostFailedException.h from [983add21d8] to [bd472458b0].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFResolveHostFailedException.m from [a81a110c2f] to [fa5e213949].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFSeekFailedException.h from [2132111c3a] to [ecb2c75473].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFSeekFailedException.m from [20812553c7] to [5cba0234e3].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFSetItemAttributesFailedException.h from [4b245f8a54] to [35356237a0].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#import "OFException.h"
#import "OFURIHandler.h"

OF_ASSUME_NONNULL_BEGIN

@class OFURI;

/**
 * @class OFSetItemAttributesFailedException \
 *	  OFSetItemAttributesFailedException.h \
 *	  ObjFW/OFSetItemAttributesFailedException.h
 *
 * @brief An exception indicating an item's attributes could not be set.
 */
@interface OFSetItemAttributesFailedException: OFException
{
	OFURI *_URI;
	OFFileAttributes _attributes;
	OFFileAttributeKey _failedAttribute;
	int _errNo;
	OF_RESERVE_IVARS(OFSetItemAttributesFailedException, 4)
}

/**
 * @brief The URI of the item whose attributes could not be set.
 */
@property (readonly, nonatomic) OFURI *URI;

/**
 * @brief The errno of the error that occurred.
 */
@property (readonly, nonatomic) int errNo;

/**
 * @brief The attributes that should have been set.
 */
@property (readonly, nonatomic) OFFileAttributes attributes;

/**
 * @brief The first attribute that could not be set.
 */
@property (readonly, nonatomic) OFFileAttributeKey failedAttribute;

/**
 * @brief Creates a new, autoreleased set item attributes failed exception.
 *
 * @param URI The URI of the item whose attributes could not be set
 * @param attributes The attributes that should have been set for the specified
 *		     item.
 * @param failedAttribute The first attribute that could not be set
 * @param errNo The errno of the error that occurred
 * @return A new, autoreleased set item attributes failed exception
 */
+ (instancetype)exceptionWithURI: (OFURI *)URI
		      attributes: (OFFileAttributes)attributes
		 failedAttribute: (OFFileAttributeKey)failedAttribute
			   errNo: (int)errNo;

+ (instancetype)exception OF_UNAVAILABLE;

/**
 * @brief Initializes an already allocated set item attributes failed exception.
 *
 * @param URI The URI of the item whose attributes could not be set
 * @param attributes The attributes that should have been set for the specified
 *		     item.
 * @param failedAttribute The first attribute that could not be set
 * @param errNo The errno of the error that occurred
 * @return An initialized set item attributes failed exception
 */
- (instancetype)initWithURI: (OFURI *)URI
		 attributes: (OFFileAttributes)attributes
	    failedAttribute: (OFFileAttributeKey)failedAttribute
		      errNo: (int)errNo OF_DESIGNATED_INITIALIZER;

- (instancetype)init OF_UNAVAILABLE;
@end

OF_ASSUME_NONNULL_END

|














|



|










|







|

|



















|






|









|






|








1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
/*
 * Copyright (c) 2008-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 "OFIRIHandler.h"

OF_ASSUME_NONNULL_BEGIN

@class OFIRI;

/**
 * @class OFSetItemAttributesFailedException \
 *	  OFSetItemAttributesFailedException.h \
 *	  ObjFW/OFSetItemAttributesFailedException.h
 *
 * @brief An exception indicating an item's attributes could not be set.
 */
@interface OFSetItemAttributesFailedException: OFException
{
	OFIRI *_IRI;
	OFFileAttributes _attributes;
	OFFileAttributeKey _failedAttribute;
	int _errNo;
	OF_RESERVE_IVARS(OFSetItemAttributesFailedException, 4)
}

/**
 * @brief The IRI of the item whose attributes could not be set.
 */
@property (readonly, nonatomic) OFIRI *IRI;

/**
 * @brief The errno of the error that occurred.
 */
@property (readonly, nonatomic) int errNo;

/**
 * @brief The attributes that should have been set.
 */
@property (readonly, nonatomic) OFFileAttributes attributes;

/**
 * @brief The first attribute that could not be set.
 */
@property (readonly, nonatomic) OFFileAttributeKey failedAttribute;

/**
 * @brief Creates a new, autoreleased set item attributes failed exception.
 *
 * @param IRI The IRI of the item whose attributes could not be set
 * @param attributes The attributes that should have been set for the specified
 *		     item.
 * @param failedAttribute The first attribute that could not be set
 * @param errNo The errno of the error that occurred
 * @return A new, autoreleased set item attributes failed exception
 */
+ (instancetype)exceptionWithIRI: (OFIRI *)IRI
		      attributes: (OFFileAttributes)attributes
		 failedAttribute: (OFFileAttributeKey)failedAttribute
			   errNo: (int)errNo;

+ (instancetype)exception OF_UNAVAILABLE;

/**
 * @brief Initializes an already allocated set item attributes failed exception.
 *
 * @param IRI The IRI of the item whose attributes could not be set
 * @param attributes The attributes that should have been set for the specified
 *		     item.
 * @param failedAttribute The first attribute that could not be set
 * @param errNo The errno of the error that occurred
 * @return An initialized set item attributes failed exception
 */
- (instancetype)initWithIRI: (OFIRI *)IRI
		 attributes: (OFFileAttributes)attributes
	    failedAttribute: (OFFileAttributeKey)failedAttribute
		      errNo: (int)errNo OF_DESIGNATED_INITIALIZER;

- (instancetype)init OF_UNAVAILABLE;
@end

OF_ASSUME_NONNULL_END

Modified src/exceptions/OFSetItemAttributesFailedException.m from [419b3c1aff] to [52049697e7].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#import "OFSetItemAttributesFailedException.h"
#import "OFString.h"
#import "OFURI.h"

@implementation OFSetItemAttributesFailedException
@synthesize URI = _URI, attributes = _attributes;
@synthesize failedAttribute = _failedAttribute, errNo = _errNo;

+ (instancetype)exception
{
	OF_UNRECOGNIZED_SELECTOR
}

+ (instancetype)exceptionWithURI: (OFURI *)URI
		      attributes: (OFFileAttributes)attributes
		 failedAttribute: (OFFileAttributeKey)failedAttribute
			   errNo: (int)errNo
{
	return [[[self alloc] initWithURI: URI
			       attributes: attributes
			  failedAttribute: failedAttribute
				    errNo: errNo] autorelease];
}

- (instancetype)init
{
	OF_INVALID_INIT_METHOD
}

- (instancetype)initWithURI: (OFURI *)URI
		 attributes: (OFFileAttributes)attributes
	    failedAttribute: (OFFileAttributeKey)failedAttribute
		      errNo: (int)errNo
{
	self = [super init];

	@try {
		_URI = [URI copy];
		_attributes = [attributes copy];
		_failedAttribute = [failedAttribute copy];
		_errNo = errNo;
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (void)dealloc
{
	[_URI release];
	[_attributes release];
	[_failedAttribute release];

	[super dealloc];
}

- (OFString *)description
{
	return [OFString stringWithFormat:
	    @"Failed to set attribute %@ for item %@: %@",
	    _failedAttribute, _URI, OFStrError(_errNo)];
}
@end

|
















|
|


|







|




|










|







|













|










|


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
/*
 * Copyright (c) 2008-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 "OFSetItemAttributesFailedException.h"
#import "OFIRI.h"
#import "OFString.h"

@implementation OFSetItemAttributesFailedException
@synthesize IRI = _IRI, attributes = _attributes;
@synthesize failedAttribute = _failedAttribute, errNo = _errNo;

+ (instancetype)exception
{
	OF_UNRECOGNIZED_SELECTOR
}

+ (instancetype)exceptionWithIRI: (OFIRI *)IRI
		      attributes: (OFFileAttributes)attributes
		 failedAttribute: (OFFileAttributeKey)failedAttribute
			   errNo: (int)errNo
{
	return [[[self alloc] initWithIRI: IRI
			       attributes: attributes
			  failedAttribute: failedAttribute
				    errNo: errNo] autorelease];
}

- (instancetype)init
{
	OF_INVALID_INIT_METHOD
}

- (instancetype)initWithIRI: (OFIRI *)IRI
		 attributes: (OFFileAttributes)attributes
	    failedAttribute: (OFFileAttributeKey)failedAttribute
		      errNo: (int)errNo
{
	self = [super init];

	@try {
		_IRI = [IRI copy];
		_attributes = [attributes copy];
		_failedAttribute = [failedAttribute copy];
		_errNo = errNo;
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (void)dealloc
{
	[_IRI release];
	[_attributes release];
	[_failedAttribute release];

	[super dealloc];
}

- (OFString *)description
{
	return [OFString stringWithFormat:
	    @"Failed to set attribute %@ for item %@: %@",
	    _failedAttribute, _IRI, OFStrError(_errNo)];
}
@end

Modified src/exceptions/OFSetOptionFailedException.h from [2fa10041b9] to [f9ef2566c9].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
 * @class OFSetOptionFailedException \
 *	  OFSetOptionFailedException.h ObjFW/OFSetOptionFailedException.h
 *
 * @brief An exception indicating that setting an option for an object failed.
 */
@interface OFSetOptionFailedException: OFException
{
	id _object;
	int _errNo;
	OF_RESERVE_IVARS(OFSetOptionFailedException, 4)
}

/**
 * @brief The object for which the option could not be set.
 */
@property (readonly, nonatomic) id object;

/**
 * @brief The errno of the error that occurred.
 */
@property (readonly, nonatomic) int errNo;

/**
 * @brief Creates a new, autoreleased set option failed exception.
 *
 * @param object The object for which the option could not be set
 * @param errNo The errno of the error that occurred
 * @return A new, autoreleased set option failed exception
 */
+ (instancetype)exceptionWithObject: (id)object errNo: (int)errNo;

+ (instancetype)exception OF_UNAVAILABLE;

/**
 * @brief Initializes an already allocated set option failed exception.
 *
 * @param object The object for which the option could not be set
 * @param errNo The errno of the error that occurred
 * @return An initialized set option failed exception
 */
- (instancetype)initWithObject: (id)object
			 errNo: (int)errNo OF_DESIGNATED_INITIALIZER;

- (instancetype)init OF_UNAVAILABLE;
@end

OF_ASSUME_NONNULL_END







|







|













|










|






21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
 * @class OFSetOptionFailedException \
 *	  OFSetOptionFailedException.h ObjFW/OFSetOptionFailedException.h
 *
 * @brief An exception indicating that setting an option for an object failed.
 */
@interface OFSetOptionFailedException: OFException
{
	id _Nullable _object;
	int _errNo;
	OF_RESERVE_IVARS(OFSetOptionFailedException, 4)
}

/**
 * @brief The object for which the option could not be set.
 */
@property OF_NULLABLE_PROPERTY (readonly, nonatomic) id object;

/**
 * @brief The errno of the error that occurred.
 */
@property (readonly, nonatomic) int errNo;

/**
 * @brief Creates a new, autoreleased set option failed exception.
 *
 * @param object The object for which the option could not be set
 * @param errNo The errno of the error that occurred
 * @return A new, autoreleased set option failed exception
 */
+ (instancetype)exceptionWithObject: (nullable id)object errNo: (int)errNo;

+ (instancetype)exception OF_UNAVAILABLE;

/**
 * @brief Initializes an already allocated set option failed exception.
 *
 * @param object The object for which the option could not be set
 * @param errNo The errno of the error that occurred
 * @return An initialized set option failed exception
 */
- (instancetype)initWithObject: (nullable id)object
			 errNo: (int)errNo OF_DESIGNATED_INITIALIZER;

- (instancetype)init OF_UNAVAILABLE;
@end

OF_ASSUME_NONNULL_END

Modified src/exceptions/OFSetOptionFailedException.m from [8f19f7dfbc] to [22a35c4efd].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
51
52
53
54
55
56
57

58
59
60



61
62
	[_object release];

	[super dealloc];
}

- (OFString *)description
{

	return [OFString stringWithFormat:
	    @"Setting an option in an object of type %@ failed: %@",
	    [_object class], OFStrError(_errNo)];



}
@end







>
|
|
|
>
>
>


51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
	[_object release];

	[super dealloc];
}

- (OFString *)description
{
	if (_object != nil)
		return [OFString stringWithFormat:
		    @"Setting an option in an object of type %@ failed: %@",
		    [_object class], OFStrError(_errNo)];
	else
		return [OFString stringWithFormat:
		    @"Setting an option failed: %@", OFStrError(_errNo)];
}
@end

Modified src/exceptions/OFSetWindowsRegistryValueFailedException.h from [88eed12b7b] to [853b067d9b].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFSetWindowsRegistryValueFailedException.m from [e6d28eef78] to [c8d0084ea9].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFSignalConditionFailedException.h from [abb9bfa0ca] to [0b370b3353].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFSignalConditionFailedException.m from [f5f3ff967a] to [bbd161e9a3].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFStartThreadFailedException.h from [e0e650ae0d] to [5c270959f4].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFStartThreadFailedException.m from [9dcf5912d6] to [943b596499].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFStillLockedException.h from [da104224a4] to [c3680b7c60].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFStillLockedException.m from [3bdcf688e2] to [3bdbdf86c6].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFTLSHandshakeFailedException.h from [f9e2ae9630] to [ff229bf16d].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFTLSHandshakeFailedException.m from [9f825e73f8] to [c4de254140].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFThreadStillRunningException.h from [8cadaadd37] to [d9b9473361].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFThreadStillRunningException.m from [08b6a2fa91] to [600b683c63].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFTruncatedDataException.h from [c355984cb5] to [350be15a70].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFTruncatedDataException.m from [d3465afc55] to [a7e70437ac].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFUnboundNamespaceException.h from [782770074b] to [236662c3e6].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFUnboundNamespaceException.m from [8d26c2cfa6] to [be5ddfb62a].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFUnboundPrefixException.h from [c1eaadb13e] to [d2503eb0f8].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFUnboundPrefixException.m from [09d3302162] to [ab3405479b].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFUndefinedKeyException.h from [1b1bc72e6f] to [23829743a6].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFUndefinedKeyException.m from [fa0cc877cd] to [dea1de5a47].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFUnknownXMLEntityException.h from [effb41465b] to [da97251a7a].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFUnknownXMLEntityException.m from [87056195a2] to [9cc64ed58a].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFUnlockFailedException.h from [2273de4dc6] to [83bdb8a3ea].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFUnlockFailedException.m from [68e65cd613] to [cf24a67a33].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFUnsupportedProtocolException.h from [229fefef5c] to [f2d3f6b7fd].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#import "OFException.h"

OF_ASSUME_NONNULL_BEGIN

@class OFURI;

/**
 * @class OFUnsupportedProtocolException \
 *	  OFUnsupportedProtocolException.h \
 *	  ObjFW/OFUnsupportedProtocolException.h
 *
 * @brief An exception indicating that the protocol specified by the URI is not
 *	  supported.
 */
@interface OFUnsupportedProtocolException: OFException
{
	OFURI *_Nullable _URI;
	OF_RESERVE_IVARS(OFUnsupportedProtocolException, 4)
}

/**
 * @brief The URI whose protocol is unsupported.
 */
@property OF_NULLABLE_PROPERTY (readonly, nonatomic) OFURI *URI;

/**
 * @brief Creates a new, autoreleased unsupported protocol exception.
 *
 * @param URI The URI whose protocol is unsupported
 * @return A new, autoreleased unsupported protocol exception
 */
+ (instancetype)exceptionWithURI: (nullable OFURI*)URI;

/**
 * @brief Initializes an already allocated unsupported protocol exception
 *
 * @param URI The URI whose protocol is unsupported
 * @return An initialized unsupported protocol exception
 */
- (instancetype)initWithURI: (nullable OFURI*)URI OF_DESIGNATED_INITIALIZER;
@end

OF_ASSUME_NONNULL_END

|

















|






|




|




|

|




|


|




|


|



1
2
3
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 "OFException.h"

OF_ASSUME_NONNULL_BEGIN

@class OFIRI;

/**
 * @class OFUnsupportedProtocolException \
 *	  OFUnsupportedProtocolException.h \
 *	  ObjFW/OFUnsupportedProtocolException.h
 *
 * @brief An exception indicating that the protocol specified by the IRI is not
 *	  supported.
 */
@interface OFUnsupportedProtocolException: OFException
{
	OFIRI *_Nullable _IRI;
	OF_RESERVE_IVARS(OFUnsupportedProtocolException, 4)
}

/**
 * @brief The IRI whose protocol is unsupported.
 */
@property OF_NULLABLE_PROPERTY (readonly, nonatomic) OFIRI *IRI;

/**
 * @brief Creates a new, autoreleased unsupported protocol exception.
 *
 * @param IRI The IRI whose protocol is unsupported
 * @return A new, autoreleased unsupported protocol exception
 */
+ (instancetype)exceptionWithIRI: (nullable OFIRI*)IRI;

/**
 * @brief Initializes an already allocated unsupported protocol exception
 *
 * @param IRI The IRI whose protocol is unsupported
 * @return An initialized unsupported protocol exception
 */
- (instancetype)initWithIRI: (nullable OFIRI*)IRI OF_DESIGNATED_INITIALIZER;
@end

OF_ASSUME_NONNULL_END

Modified src/exceptions/OFUnsupportedProtocolException.m from [a391485837] to [f2a0212c03].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#import "OFUnsupportedProtocolException.h"
#import "OFString.h"
#import "OFURI.h"

@implementation OFUnsupportedProtocolException
@synthesize URI = _URI;

+ (instancetype)exceptionWithURI: (OFURI *)URI
{
	return [[[self alloc] initWithURI: URI] autorelease];
}

- (instancetype)initWithURI: (OFURI *)URI
{
	self = [super init];

	_URI = [URI retain];

	return self;
}

- (void)dealloc
{
	[_URI release];

	[super dealloc];
}

- (OFString *)description
{
	if (_URI != nil)
		return [OFString stringWithFormat:
		    @"The protocol of URI %@ is not supported!", _URI];
	else
		return @"The requested protocol is unsupported!";
}
@end

|
















|
|


|

|

|


|



|






|






|

|




1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
/*
 * Copyright (c) 2008-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 "OFUnsupportedProtocolException.h"
#import "OFIRI.h"
#import "OFString.h"

@implementation OFUnsupportedProtocolException
@synthesize IRI = _IRI;

+ (instancetype)exceptionWithIRI: (OFIRI *)IRI
{
	return [[[self alloc] initWithIRI: IRI] autorelease];
}

- (instancetype)initWithIRI: (OFIRI *)IRI
{
	self = [super init];

	_IRI = [IRI retain];

	return self;
}

- (void)dealloc
{
	[_IRI release];

	[super dealloc];
}

- (OFString *)description
{
	if (_IRI != nil)
		return [OFString stringWithFormat:
		    @"The protocol of IRI %@ is not supported!", _IRI];
	else
		return @"The requested protocol is unsupported!";
}
@end

Modified src/exceptions/OFUnsupportedVersionException.h from [2da3b1eaf2] to [9f1f6cf6b9].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFUnsupportedVersionException.m from [ae8969b353] to [d15e4d9944].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFWaitForConditionFailedException.h from [a1e587c621] to [3a836802e3].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFWaitForConditionFailedException.m from [e419f3f9dc] to [527c08b36e].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFWriteFailedException.h from [6dee61073a] to [e28b2af903].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/exceptions/OFWriteFailedException.m from [1eca55cb4e] to [f282ecd58a].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Renamed and modified src/forwarding/apple-forwarding-x86_64.S [1324ab08b0] to src/forwarding/apple-forwarding-amd64.S [59b2226de5].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the 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"

.globl _OFForward
.globl _OFForward_stret

.section __TEXT, __objc_methname, cstring_literals
str_forwardingTargetForSelector_:
	.asciz "forwardingTargetForSelector:"

.section __DATA, __objc_selrefs, literal_pointers, no_dead_strip
sel_forwardingTargetForSelector_:
	.quad str_forwardingTargetForSelector_

.section __DATA, __objc_imageinfo, regular, no_dead_strip
	.long 0, 0

.section __TEXT, __text, regular, pure_instructions
_OFForward:
	pushq	%rbp

|



















|



|
|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
/*
 * Copyright (c) 2008-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"

.globl _OFForward
.globl _OFForward_stret

.section __TEXT, __objc_methname, cstring_literals
Lstr_forwardingTargetForSelector_:
	.asciz "forwardingTargetForSelector:"

.section __DATA, __objc_selrefs, literal_pointers, no_dead_strip
Lsel_forwardingTargetForSelector_:
	.quad Lstr_forwardingTargetForSelector_

.section __DATA, __objc_imageinfo, regular, no_dead_strip
	.long 0, 0

.section __TEXT, __text, regular, pure_instructions
_OFForward:
	pushq	%rbp
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
	movaps	%xmm5, -0xA0(%rbp)
	movaps	%xmm6, -0xB0(%rbp)
	movaps	%xmm7, -0xC0(%rbp)

	call	_object_getClass

	movq	%rax, %rdi
	movq	sel_forwardingTargetForSelector_(%rip), %rsi
	call	_class_respondsToSelector

	testq	%rax, %rax
	jz	0f

	movq	-0x10(%rbp), %rdi
	movq	sel_forwardingTargetForSelector_(%rip), %rsi
	movq	-0x18(%rbp), %rdx
	call	_objc_msgSend

	testq	%rax, %rax
	jz	0f
	cmpq	-0x10(%rbp), %rax
	je	0f







|






|







51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
	movaps	%xmm5, -0xA0(%rbp)
	movaps	%xmm6, -0xB0(%rbp)
	movaps	%xmm7, -0xC0(%rbp)

	call	_object_getClass

	movq	%rax, %rdi
	movq	Lsel_forwardingTargetForSelector_(%rip), %rsi
	call	_class_respondsToSelector

	testq	%rax, %rax
	jz	0f

	movq	-0x10(%rbp), %rdi
	movq	Lsel_forwardingTargetForSelector_(%rip), %rsi
	movq	-0x18(%rbp), %rdx
	call	_objc_msgSend

	testq	%rax, %rax
	jz	0f
	cmpq	-0x10(%rbp), %rax
	je	0f
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
	movaps	%xmm6, -0xB0(%rbp)
	movaps	%xmm7, -0xC0(%rbp)

	movq	%rsi, %rdi
	call	_object_getClass

	movq	%rax, %rdi
	movq	sel_forwardingTargetForSelector_(%rip), %rsi
	call	_class_respondsToSelector
	testq	%rax, %rax
	jz	0f

	movq	-0x18(%rbp), %rdi
	movq	sel_forwardingTargetForSelector_(%rip), %rsi
	movq	-0x20(%rbp), %rdx
	call	_objc_msgSend

	testq	%rax, %rax
	jz	0f
	cmpq	-0x18(%rbp), %rax
	je	0f







|





|







125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
	movaps	%xmm6, -0xB0(%rbp)
	movaps	%xmm7, -0xC0(%rbp)

	movq	%rsi, %rdi
	call	_object_getClass

	movq	%rax, %rdi
	movq	Lsel_forwardingTargetForSelector_(%rip), %rsi
	call	_class_respondsToSelector
	testq	%rax, %rax
	jz	0f

	movq	-0x18(%rbp), %rdi
	movq	Lsel_forwardingTargetForSelector_(%rip), %rsi
	movq	-0x20(%rbp), %rdx
	call	_objc_msgSend

	testq	%rax, %rax
	jz	0f
	cmpq	-0x18(%rbp), %rax
	je	0f

Modified src/forwarding/apple-forwarding-arm.S from [638359a9cd] to [48419797eb].

1
2
3
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
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

.globl _OFForward
.globl _OFForward_stret

.section __TEXT, __objc_methname, cstring_literals
str_forwardingTargetForSelector_:
	.asciz "forwardingTargetForSelector:"

.section __DATA, __objc_selrefs, literal_pointers, no_dead_strip
sel_forwardingTargetForSelector_:
	.long str_forwardingTargetForSelector_

.section __DATA, __objc_imageinfo, regular, no_dead_strip
	.long 0, 0

.section __TEXT, __text, regular, pure_instructions
.arm
.align 2
_OFForward:
	stmfd	sp!, {r0-r4, lr}
	vstmdb	sp!, {d0-d7}

	ldr	r4, sel_forwardingTargetForSelector_$indirect_L0
L0:
	ldr	r4, [pc, r4]

	blx	_object_getClass

	mov	r1, r4
	blx	_class_respondsToSelector

|



















|



|












|







1
2
3
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
/*
 * 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"

.globl _OFForward
.globl _OFForward_stret

.section __TEXT, __objc_methname, cstring_literals
Lstr_forwardingTargetForSelector_:
	.asciz "forwardingTargetForSelector:"

.section __DATA, __objc_selrefs, literal_pointers, no_dead_strip
Lsel_forwardingTargetForSelector_:
	.long str_forwardingTargetForSelector_

.section __DATA, __objc_imageinfo, regular, no_dead_strip
	.long 0, 0

.section __TEXT, __text, regular, pure_instructions
.arm
.align 2
_OFForward:
	stmfd	sp!, {r0-r4, lr}
	vstmdb	sp!, {d0-d7}

	ldr	r4, Lsel_forwardingTargetForSelector_$indirect_L0
L0:
	ldr	r4, [pc, r4]

	blx	_object_getClass

	mov	r1, r4
	blx	_class_respondsToSelector
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90

0:
	vldmia	sp!, {d0-d7}
	ldmfd	sp!, {r0-r4, lr}
	b	_OFMethodNotFound

.data_region
sel_forwardingTargetForSelector_$indirect_L0:
	.long sel_forwardingTargetForSelector_-(L0+8)
.end_data_region

.align 2
_OFForward_stret:
	stmfd	sp!, {r0-r4, lr}
	vstmdb	sp!, {d0-d7}

	ldr	r4, sel_forwardingTargetForSelector_$indirect_L1
L1:
	ldr	r4, [pc, r4]

	mov	r0, r1
	blx	_object_getClass

	mov	r1, r4







|
|







|







67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90

0:
	vldmia	sp!, {d0-d7}
	ldmfd	sp!, {r0-r4, lr}
	b	_OFMethodNotFound

.data_region
Lsel_forwardingTargetForSelector_$indirect_L0:
	.long Lsel_forwardingTargetForSelector_-(L0+8)
.end_data_region

.align 2
_OFForward_stret:
	stmfd	sp!, {r0-r4, lr}
	vstmdb	sp!, {d0-d7}

	ldr	r4, Lsel_forwardingTargetForSelector_$indirect_L1
L1:
	ldr	r4, [pc, r4]

	mov	r0, r1
	blx	_object_getClass

	mov	r1, r4
115
116
117
118
119
120
121
122
123
124

0:
	vldmia	sp!, {d0-d7}
	ldmfd	sp!, {r0-r4, lr}
	b	_OFMethodNotFound_stret

.data_region
sel_forwardingTargetForSelector_$indirect_L1:
	.long sel_forwardingTargetForSelector_-(L1+8)
.end_data_region







|
|

115
116
117
118
119
120
121
122
123
124

0:
	vldmia	sp!, {d0-d7}
	ldmfd	sp!, {r0-r4, lr}
	b	_OFMethodNotFound_stret

.data_region
Lsel_forwardingTargetForSelector_$indirect_L1:
	.long Lsel_forwardingTargetForSelector_-(L1+8)
.end_data_region

Modified src/forwarding/apple-forwarding-arm64.S from [d2adf305f5] to [a595def47d].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the 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"

.globl _OFForward
.globl _OFForward_stret

.section __TEXT, __objc_methname, cstring_literals
str_forwardingTargetForSelector_:
	.asciz "forwardingTargetForSelector:"

.section __DATA, __objc_selrefs, literal_pointers, no_dead_strip
sel_forwardingTargetForSelector_:
	.quad str_forwardingTargetForSelector_

.section __DATA, __objc_imageinfo, regular, no_dead_strip
	.long 0, 0

.section __TEXT, __text, regular, pure_instructions
.align 2
_OFForward:

|



















|



|
|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
/*
 * Copyright (c) 2008-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"

.globl _OFForward
.globl _OFForward_stret

.section __TEXT, __objc_methname, cstring_literals
Lstr_forwardingTargetForSelector_:
	.asciz "forwardingTargetForSelector:"

.section __DATA, __objc_selrefs, literal_pointers, no_dead_strip
Lsel_forwardingTargetForSelector_:
	.quad Lstr_forwardingTargetForSelector_

.section __DATA, __objc_imageinfo, regular, no_dead_strip
	.long 0, 0

.section __TEXT, __text, regular, pure_instructions
.align 2
_OFForward:
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
	stp	q0, q1, [sp, #80]
	stp	q2, q3, [sp, #112]
	stp	q4, q5, [sp, #144]
	stp	q6, q7, [sp, #176]

	bl	_object_getClass

	adrp	x19, sel_forwardingTargetForSelector_@PAGE
	add	x19, x19, sel_forwardingTargetForSelector_@PAGEOFF
	ldr	x19, [x19]

	mov	x1, x19
	bl	_class_respondsToSelector

	cbz	x0, 0f








|
|







48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
	stp	q0, q1, [sp, #80]
	stp	q2, q3, [sp, #112]
	stp	q4, q5, [sp, #144]
	stp	q6, q7, [sp, #176]

	bl	_object_getClass

	adrp	x19, Lsel_forwardingTargetForSelector_@PAGE
	add	x19, x19, Lsel_forwardingTargetForSelector_@PAGEOFF
	ldr	x19, [x19]

	mov	x1, x19
	bl	_class_respondsToSelector

	cbz	x0, 0f

Modified src/forwarding/apple-forwarding-powerpc.S from [8f7b914664] to [c0a6de7a63].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the 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"

.globl _OFForward
.globl _OFForward_stret

.section __TEXT, __cstring, cstring_literals
str_forwardingTargetForSelector_:
	.asciz "forwardingTargetForSelector:"

.section __OBJC, __message_refs
sel_forwardingTargetForSelector_:
	.long str_forwardingTargetForSelector_

.section __OBJC, __image_info
	.long 0, 0

.section __TEXT, __text, regular, pure_instructions
_OFForward:
	mflr	r0

|



















|



|
|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
/*
 * Copyright (c) 2008-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"

.globl _OFForward
.globl _OFForward_stret

.section __TEXT, __cstring, cstring_literals
Lstr_forwardingTargetForSelector_:
	.asciz "forwardingTargetForSelector:"

.section __OBJC, __message_refs
Lsel_forwardingTargetForSelector_:
	.long Lstr_forwardingTargetForSelector_

.section __OBJC, __image_info
	.long 0, 0

.section __TEXT, __text, regular, pure_instructions
_OFForward:
	mflr	r0
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
	stfd	f13, 184(r1)

	bl	_object_getClass

	bl	0f
0:
	mflr	r13
	addis	r13, r13, ha16(sel_forwardingTargetForSelector_-0b)
	lwz	r13, lo16(sel_forwardingTargetForSelector_-0b)(r13)

	mr	r4, r13
	bl	_class_respondsToSelector

	cmpwi	r3, 0
	beq-	0f








|
|







67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
	stfd	f13, 184(r1)

	bl	_object_getClass

	bl	0f
0:
	mflr	r13
	addis	r13, r13, ha16(Lsel_forwardingTargetForSelector_-0b)
	lwz	r13, lo16(Lsel_forwardingTargetForSelector_-0b)(r13)

	mr	r4, r13
	bl	_class_respondsToSelector

	cmpwi	r3, 0
	beq-	0f

170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185

	mr	r3, r4
	bl	_object_getClass

	bl	0f
0:
	mflr	r13
	addis	r13, r13, ha16(sel_forwardingTargetForSelector_-0b)
	lwz	r13, lo16(sel_forwardingTargetForSelector_-0b)(r13)

	mr	r4, r13
	bl	_class_respondsToSelector

	cmpwi	r3, 0
	beq-	0f








|
|







170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185

	mr	r3, r4
	bl	_object_getClass

	bl	0f
0:
	mflr	r13
	addis	r13, r13, ha16(Lsel_forwardingTargetForSelector_-0b)
	lwz	r13, lo16(Lsel_forwardingTargetForSelector_-0b)(r13)

	mr	r4, r13
	bl	_class_respondsToSelector

	cmpwi	r3, 0
	beq-	0f

Renamed and modified src/forwarding/apple-forwarding-i386.S [11f716a457] to src/forwarding/apple-forwarding-x86.S [5b3e10592e].

1
2
3
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
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

.globl _OFForward
.globl _OFForward_stret

.section __TEXT, __cstring, cstring_literals
str_forwardingTargetForSelector_:
	.asciz "forwardingTargetForSelector:"

.section __OBJC, __message_refs, literal_pointers, no_dead_strip
sel_forwardingTargetForSelector_:
	.long str_forwardingTargetForSelector_

.section __OBJC, __image_info
	.long 0, 0

.section __TEXT, __text, regular, pure_instructions
_OFForward:
	pushl	%ebp
	movl	%esp, %ebp

	pushl	%ebx
	subl	$20, %esp

	call	get_eip
0:

	movl	8(%ebp), %eax
	movl	%eax, (%esp)
	call	_object_getClass

	movl	%eax, (%esp)
	movl	sel_forwardingTargetForSelector_-0b(%ebx), %eax
	movl	%eax, 4(%esp)
	call	_class_respondsToSelector

	testl	%eax, %eax
	jz	0f

	movl	8(%ebp), %eax
	movl	%eax, (%esp)
	movl	sel_forwardingTargetForSelector_-0b(%ebx), %eax
	movl	%eax, 4(%esp)
	movl	12(%ebp), %eax
	movl	%eax, 8(%esp)
	call	_objc_msgSend

	testl	%eax, %eax
	jz	0f

|



















|



|
|












|







|








|







1
2
3
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
/*
 * 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"

.globl _OFForward
.globl _OFForward_stret

.section __TEXT, __cstring, cstring_literals
Lstr_forwardingTargetForSelector_:
	.asciz "forwardingTargetForSelector:"

.section __OBJC, __message_refs, literal_pointers, no_dead_strip
Lsel_forwardingTargetForSelector_:
	.long Lstr_forwardingTargetForSelector_

.section __OBJC, __image_info
	.long 0, 0

.section __TEXT, __text, regular, pure_instructions
_OFForward:
	pushl	%ebp
	movl	%esp, %ebp

	pushl	%ebx
	subl	$20, %esp

	call	LgetEIP
0:

	movl	8(%ebp), %eax
	movl	%eax, (%esp)
	call	_object_getClass

	movl	%eax, (%esp)
	movl	Lsel_forwardingTargetForSelector_-0b(%ebx), %eax
	movl	%eax, 4(%esp)
	call	_class_respondsToSelector

	testl	%eax, %eax
	jz	0f

	movl	8(%ebp), %eax
	movl	%eax, (%esp)
	movl	Lsel_forwardingTargetForSelector_-0b(%ebx), %eax
	movl	%eax, 4(%esp)
	movl	12(%ebp), %eax
	movl	%eax, 8(%esp)
	call	_objc_msgSend

	testl	%eax, %eax
	jz	0f
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
_OFForward_stret:
	pushl	%ebp
	movl	%esp, %ebp

	pushl	%ebx
	subl	$20, %esp

	call	get_eip
0:

	movl	12(%ebp), %eax
	movl	%eax, (%esp)
	call	_object_getClass

	movl	%eax, (%esp)
	movl	sel_forwardingTargetForSelector_-0b(%ebx), %eax
	movl	%eax, 4(%esp)
	call	_class_respondsToSelector

	testl	%eax, %eax
	jz	0f

	movl	12(%ebp), %eax
	movl	%eax, (%esp)
	movl	sel_forwardingTargetForSelector_-0b(%ebx), %eax
	movl	%eax, 4(%esp)
	movl	16(%ebp), %eax
	movl	%eax, 8(%esp)
	call	_objc_msgSend

	testl	%eax, %eax
	jz	0f







|







|








|







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
_OFForward_stret:
	pushl	%ebp
	movl	%esp, %ebp

	pushl	%ebx
	subl	$20, %esp

	call	LgetEIP
0:

	movl	12(%ebp), %eax
	movl	%eax, (%esp)
	call	_object_getClass

	movl	%eax, (%esp)
	movl	Lsel_forwardingTargetForSelector_-0b(%ebx), %eax
	movl	%eax, 4(%esp)
	call	_class_respondsToSelector

	testl	%eax, %eax
	jz	0f

	movl	12(%ebp), %eax
	movl	%eax, (%esp)
	movl	Lsel_forwardingTargetForSelector_-0b(%ebx), %eax
	movl	%eax, 4(%esp)
	movl	16(%ebp), %eax
	movl	%eax, 8(%esp)
	call	_objc_msgSend

	testl	%eax, %eax
	jz	0f
126
127
128
129
130
131
132
133
134
135
0:
	addl	$20, %esp
	popl	%ebx
	popl	%ebp

	jmp	_OFMethodNotFound_stret

get_eip:
	movl	(%esp), %ebx
	ret







|


126
127
128
129
130
131
132
133
134
135
0:
	addl	$20, %esp
	popl	%ebx
	popl	%ebp

	jmp	_OFMethodNotFound_stret

LgetEIP:
	movl	(%esp), %ebx
	ret

Renamed and modified src/forwarding/forwarding-x86_64-elf.S [9ea0cb41b3] to src/forwarding/forwarding-amd64-elf.S [f508a1c5c1].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
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
	movaps	%xmm5, -0xA0(%rbp)
	movaps	%xmm6, -0xB0(%rbp)
	movaps	%xmm7, -0xC0(%rbp)

	call	object_getClass@PLT

	movq	%rax, %rdi
	leaq	sel_forwardingTargetForSelector_(%rip), %rsi
	call	class_respondsToSelector@PLT

	testq	%rax, %rax
	jz	0f

	movq	-0x10(%rbp), %rdi
	leaq	sel_forwardingTargetForSelector_(%rip), %rsi
	call	objc_msg_lookup@PLT

	movq	-0x10(%rbp), %rdi
	leaq	sel_forwardingTargetForSelector_(%rip), %rsi
	movq	-0x18(%rbp), %rdx
	call	*%rax

	testq	%rax, %rax
	jz	0f
	cmpq	-0x10(%rbp), %rax
	je	0f







|






|



|







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
	movaps	%xmm5, -0xA0(%rbp)
	movaps	%xmm6, -0xB0(%rbp)
	movaps	%xmm7, -0xC0(%rbp)

	call	object_getClass@PLT

	movq	%rax, %rdi
	leaq	.Lsel_forwardingTargetForSelector_(%rip), %rsi
	call	class_respondsToSelector@PLT

	testq	%rax, %rax
	jz	0f

	movq	-0x10(%rbp), %rdi
	leaq	.Lsel_forwardingTargetForSelector_(%rip), %rsi
	call	objc_msg_lookup@PLT

	movq	-0x10(%rbp), %rdi
	leaq	.Lsel_forwardingTargetForSelector_(%rip), %rsi
	movq	-0x18(%rbp), %rdx
	call	*%rax

	testq	%rax, %rax
	jz	0f
	cmpq	-0x10(%rbp), %rax
	je	0f
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
	movaps	%xmm6, -0xB0(%rbp)
	movaps	%xmm7, -0xC0(%rbp)

	movq	%rsi, %rdi
	call	object_getClass@PLT

	movq	%rax, %rdi
	leaq	sel_forwardingTargetForSelector_(%rip), %rsi
	call	class_respondsToSelector@PLT

	testq	%rax, %rax
	jz	0f

	movq	-0x18(%rbp), %rdi
	leaq	sel_forwardingTargetForSelector_(%rip), %rsi
	call	objc_msg_lookup@PLT

	movq	-0x18(%rbp), %rdi
	leaq	sel_forwardingTargetForSelector_(%rip), %rsi
	movq	-0x20(%rbp), %rdx
	call	*%rax

	testq	%rax, %rax
	jz	0f
	cmpq	-0x18(%rbp), %rax
	je	0f







|






|



|







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
	movaps	%xmm6, -0xB0(%rbp)
	movaps	%xmm7, -0xC0(%rbp)

	movq	%rsi, %rdi
	call	object_getClass@PLT

	movq	%rax, %rdi
	leaq	.Lsel_forwardingTargetForSelector_(%rip), %rsi
	call	class_respondsToSelector@PLT

	testq	%rax, %rax
	jz	0f

	movq	-0x18(%rbp), %rdi
	leaq	.Lsel_forwardingTargetForSelector_(%rip), %rsi
	call	objc_msg_lookup@PLT

	movq	-0x18(%rbp), %rdi
	leaq	.Lsel_forwardingTargetForSelector_(%rip), %rsi
	movq	-0x20(%rbp), %rdx
	call	*%rax

	testq	%rax, %rax
	jz	0f
	cmpq	-0x18(%rbp), %rax
	je	0f
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
	movq	%rbp, %rsp
	popq	%rbp

	jmp	OFMethodNotFound_stret@PLT
.type OFForward_stret, %function
.size OFForward_stret, .-OFForward_stret

init:
	leaq	module(%rip), %rdi
	jmp	__objc_exec_class@PLT

#ifdef OF_SOLARIS
.section .init_array, "aw"
#else
.section .ctors, "aw", %progbits
#endif
	.quad init

.section .rodata
str_forwardingTargetForSelector_:
	.asciz "forwardingTargetForSelector:"

.section .data
sel_forwardingTargetForSelector_:
	.quad str_forwardingTargetForSelector_, 0
	.quad 0, 0
symtab:
	.quad 0, sel_forwardingTargetForSelector_
	.short 0, 0
	.long 0
	.quad 0
module:
	.quad 8, 32, 0, symtab

#ifdef OF_LINUX
.section .note.GNU-stack, "", %progbits
#endif







|
|







|


|



|
|

|
|



|
|

|


189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
	movq	%rbp, %rsp
	popq	%rbp

	jmp	OFMethodNotFound_stret@PLT
.type OFForward_stret, %function
.size OFForward_stret, .-OFForward_stret

.Linit:
	leaq	.Lmodule(%rip), %rdi
	jmp	__objc_exec_class@PLT

#ifdef OF_SOLARIS
.section .init_array, "aw"
#else
.section .ctors, "aw", %progbits
#endif
	.quad .Linit

.section .rodata
.Lstr_forwardingTargetForSelector_:
	.asciz "forwardingTargetForSelector:"

.section .data
.Lsel_forwardingTargetForSelector_:
	.quad .Lstr_forwardingTargetForSelector_, 0
	.quad 0, 0
.Lsymtab:
	.quad 0, .Lsel_forwardingTargetForSelector_
	.short 0, 0
	.long 0
	.quad 0
.Lmodule:
	.quad 8, 32, 0, .Lsymtab

#if defined(OF_LINUX) || defined(OF_HAIKU) || defined(OF_HURD)
.section .note.GNU-stack, "", %progbits
#endif

Renamed and modified src/forwarding/forwarding-x86_64-macho.S [0e975fcfd2] to src/forwarding/forwarding-amd64-macho.S [fb857e93f9].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
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
	movaps	%xmm5, -0xA0(%rbp)
	movaps	%xmm6, -0xB0(%rbp)
	movaps	%xmm7, -0xC0(%rbp)

	call	_object_getClass

	movq	%rax, %rdi
	leaq	sel_forwardingTargetForSelector_(%rip), %rsi
	call	_class_respondsToSelector

	testq	%rax, %rax
	jz	0f

	movq	-0x10(%rbp), %rdi
	leaq	sel_forwardingTargetForSelector_(%rip), %rsi
	call	_objc_msg_lookup

	movq	-0x10(%rbp), %rdi
	leaq	sel_forwardingTargetForSelector_(%rip), %rsi
	movq	-0x18(%rbp), %rdx
	call	*%rax

	testq	%rax, %rax
	jz	0f
	cmpq	-0x10(%rbp), %rax
	je	0f







|






|



|







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
	movaps	%xmm5, -0xA0(%rbp)
	movaps	%xmm6, -0xB0(%rbp)
	movaps	%xmm7, -0xC0(%rbp)

	call	_object_getClass

	movq	%rax, %rdi
	leaq	Lsel_forwardingTargetForSelector_(%rip), %rsi
	call	_class_respondsToSelector

	testq	%rax, %rax
	jz	0f

	movq	-0x10(%rbp), %rdi
	leaq	Lsel_forwardingTargetForSelector_(%rip), %rsi
	call	_objc_msg_lookup

	movq	-0x10(%rbp), %rdi
	leaq	Lsel_forwardingTargetForSelector_(%rip), %rsi
	movq	-0x18(%rbp), %rdx
	call	*%rax

	testq	%rax, %rax
	jz	0f
	cmpq	-0x10(%rbp), %rax
	je	0f
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
	movaps	%xmm6, -0xB0(%rbp)
	movaps	%xmm7, -0xC0(%rbp)

	movq	%rsi, %rdi
	call	_object_getClass

	movq	%rax, %rdi
	leaq	sel_forwardingTargetForSelector_(%rip), %rsi
	call	_class_respondsToSelector

	testq	%rax, %rax
	jz	0f

	movq	-0x18(%rbp), %rdi
	leaq	sel_forwardingTargetForSelector_(%rip), %rsi
	call	_objc_msg_lookup

	movq	-0x18(%rbp), %rdi
	leaq	sel_forwardingTargetForSelector_(%rip), %rsi
	movq	-0x20(%rbp), %rdx
	call	*%rax

	testq	%rax, %rax
	jz	0f
	cmpq	-0x18(%rbp), %rax
	je	0f







|






|



|







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
	movaps	%xmm6, -0xB0(%rbp)
	movaps	%xmm7, -0xC0(%rbp)

	movq	%rsi, %rdi
	call	_object_getClass

	movq	%rax, %rdi
	leaq	Lsel_forwardingTargetForSelector_(%rip), %rsi
	call	_class_respondsToSelector

	testq	%rax, %rax
	jz	0f

	movq	-0x18(%rbp), %rdi
	leaq	Lsel_forwardingTargetForSelector_(%rip), %rsi
	call	_objc_msg_lookup

	movq	-0x18(%rbp), %rdi
	leaq	Lsel_forwardingTargetForSelector_(%rip), %rsi
	movq	-0x20(%rbp), %rdx
	call	*%rax

	testq	%rax, %rax
	jz	0f
	cmpq	-0x18(%rbp), %rax
	je	0f
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
	movq	-0x20(%rbp), %rdx

	movq	%rbp, %rsp
	popq	%rbp

	jmp	_OFMethodNotFound_stret

init:
	leaq	module(%rip), %rdi
	jmp	___objc_exec_class

.section __DATA, __mod_init_func, mod_init_funcs
	.quad init

.section __TEXT, __cstring, cstring_literals
str_forwardingTargetForSelector_:
	.asciz "forwardingTargetForSelector:"

.section __DATA, __data
sel_forwardingTargetForSelector_:
	.quad str_forwardingTargetForSelector_, 0
	.quad 0, 0
symtab:
	.quad 0, sel_forwardingTargetForSelector_
	.short 0, 0
	.long 0
	.quad 0
module:
	.quad 8, 32, 0, symtab







|
|



|


|



|
|

|
|



|
|
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
	movq	-0x20(%rbp), %rdx

	movq	%rbp, %rsp
	popq	%rbp

	jmp	_OFMethodNotFound_stret

Linit:
	leaq	Lmodule(%rip), %rdi
	jmp	___objc_exec_class

.section __DATA, __mod_init_func, mod_init_funcs
	.quad Linit

.section __TEXT, __cstring, cstring_literals
Lstr_forwardingTargetForSelector_:
	.asciz "forwardingTargetForSelector:"

.section __DATA, __data
Lsel_forwardingTargetForSelector_:
	.quad Lstr_forwardingTargetForSelector_, 0
	.quad 0, 0
Lsymtab:
	.quad 0, Lsel_forwardingTargetForSelector_
	.short 0, 0
	.long 0
	.quad 0
Lmodule:
	.quad 8, 32, 0, Lsymtab

Renamed and modified src/forwarding/forwarding-x86_64-win64.S [74c1db404c] to src/forwarding/forwarding-amd64-win64.S [fedf0b1bb7].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
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
	movaps	%xmm1, -0x70(%rbp)
	movaps	%xmm2, -0x80(%rbp)
	movaps	%xmm3, -0x90(%rbp)

	call	object_getClass

	movq	%rax, %rcx
	leaq	sel_forwardingTargetForSelector_(%rip), %rdx
	call	class_respondsToSelector

	testq	%rax, %rax
	jz	0f

	movq	-0x30(%rbp), %rcx
	leaq	sel_forwardingTargetForSelector_(%rip), %rdx
	call	objc_msg_lookup

	movq	-0x30(%rbp), %rcx
	leaq	sel_forwardingTargetForSelector_(%rip), %rdx
	movq	-0x38(%rbp), %r8
	call	*%rax

	testq	%rax, %rax
	jz	0f
	cmpq	-0x30(%rbp), %rax
	je	0f







|






|



|







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
	movaps	%xmm1, -0x70(%rbp)
	movaps	%xmm2, -0x80(%rbp)
	movaps	%xmm3, -0x90(%rbp)

	call	object_getClass

	movq	%rax, %rcx
	leaq	.Lsel_forwardingTargetForSelector_(%rip), %rdx
	call	class_respondsToSelector

	testq	%rax, %rax
	jz	0f

	movq	-0x30(%rbp), %rcx
	leaq	.Lsel_forwardingTargetForSelector_(%rip), %rdx
	call	objc_msg_lookup

	movq	-0x30(%rbp), %rcx
	leaq	.Lsel_forwardingTargetForSelector_(%rip), %rdx
	movq	-0x38(%rbp), %r8
	call	*%rax

	testq	%rax, %rax
	jz	0f
	cmpq	-0x30(%rbp), %rax
	je	0f
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
	movaps	%xmm2, -0x80(%rbp)
	movaps	%xmm3, -0x90(%rbp)

	movq	%rdx, %rcx
	call	object_getClass

	movq	%rax, %rcx
	leaq	sel_forwardingTargetForSelector_(%rip), %rdx
	call	class_respondsToSelector

	testq	%rax, %rax
	jz	0f

	movq	-0x38(%rbp), %rcx
	leaq	sel_forwardingTargetForSelector_(%rip), %rdx
	call	objc_msg_lookup

	movq	-0x38(%rbp), %rcx
	leaq	sel_forwardingTargetForSelector_(%rip), %rdx
	movq	-0x40(%rbp), %r8
	call	*%rax

	testq	%rax, %rax
	jz	0f
	cmpq	-0x38(%rbp), %rax
	je	0f







|






|



|







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
	movaps	%xmm2, -0x80(%rbp)
	movaps	%xmm3, -0x90(%rbp)

	movq	%rdx, %rcx
	call	object_getClass

	movq	%rax, %rcx
	leaq	.Lsel_forwardingTargetForSelector_(%rip), %rdx
	call	class_respondsToSelector

	testq	%rax, %rax
	jz	0f

	movq	-0x38(%rbp), %rcx
	leaq	.Lsel_forwardingTargetForSelector_(%rip), %rdx
	call	objc_msg_lookup

	movq	-0x38(%rbp), %rcx
	leaq	.Lsel_forwardingTargetForSelector_(%rip), %rdx
	movq	-0x40(%rbp), %r8
	call	*%rax

	testq	%rax, %rax
	jz	0f
	cmpq	-0x38(%rbp), %rax
	je	0f
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

	jmp	OFMethodNotFound_stret
.def OFForward_stret
.scl 2
.type 32
.endef

init:
	leaq	module(%rip), %rcx
	jmp	__objc_exec_class

.section .ctors, "aw"
	.quad init

.section .rodata
str_forwardingTargetForSelector_:
	.asciz "forwardingTargetForSelector:"

.section .data
sel_forwardingTargetForSelector_:
	.quad str_forwardingTargetForSelector_, 0
	.quad 0, 0
symtab:
	.long 0, 0
	.quad sel_forwardingTargetForSelector_
	.short 0, 0
	.long 0
	.quad 0
module:
	.long 8, 32
	.quad 0, symtab







|
|



|


|



|
|

|

|



|

|
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

	jmp	OFMethodNotFound_stret
.def OFForward_stret
.scl 2
.type 32
.endef

.Linit:
	leaq	.Lmodule(%rip), %rcx
	jmp	__objc_exec_class

.section .ctors, "aw"
	.quad .Linit

.section .rodata
.Lstr_forwardingTargetForSelector_:
	.asciz "forwardingTargetForSelector:"

.section .data
.Lsel_forwardingTargetForSelector_:
	.quad .Lstr_forwardingTargetForSelector_, 0
	.quad 0, 0
.Lsymtab:
	.long 0, 0
	.quad .Lsel_forwardingTargetForSelector_
	.short 0, 0
	.long 0
	.quad 0
.Lmodule:
	.long 8, 32
	.quad 0, .Lsymtab

Modified src/forwarding/forwarding-arm-elf.S from [ebb3f926fa] to [1d972d62a5].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
.section .text
OFForward:
#ifdef HAVE_VFP2
	vstmdb	sp!, {d0-d7}
#endif
	stmfd	sp!, {r0-r4, lr}

	ldr	r4, sel_forwardingTargetForSelector_$indirect_.L0
.L0:
	add	r4, pc

	bl	object_getClass(PLT)

	mov	r1, r4
	bl	class_respondsToSelector(PLT)







|







27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
.section .text
OFForward:
#ifdef HAVE_VFP2
	vstmdb	sp!, {d0-d7}
#endif
	stmfd	sp!, {r0-r4, lr}

	ldr	r4, .Lsel_forwardingTargetForSelector_$indirect_.L0
.L0:
	add	r4, pc

	bl	object_getClass(PLT)

	mov	r1, r4
	bl	class_respondsToSelector(PLT)
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96

OFForward_stret:
#ifdef HAVE_VFP2
	vstmdb	sp!, {d0-d7}
#endif
	stmfd	sp!, {r0-r4, lr}

	ldr	r4, sel_forwardingTargetForSelector_$indirect_.L1
.L1:
	add	r4, pc

	mov	r0, r1
	bl	object_getClass(PLT)

	mov	r1, r4







|







82
83
84
85
86
87
88
89
90
91
92
93
94
95
96

OFForward_stret:
#ifdef HAVE_VFP2
	vstmdb	sp!, {d0-d7}
#endif
	stmfd	sp!, {r0-r4, lr}

	ldr	r4, .Lsel_forwardingTargetForSelector_$indirect_.L1
.L1:
	add	r4, pc

	mov	r0, r1
	bl	object_getClass(PLT)

	mov	r1, r4
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
#ifdef HAVE_VFP2
	vldmia	sp!, {d0-d7}
#endif
	b	OFMethodNotFound_stret(PLT)
.type OFForward_stret, %function
.size OFForward_stret, .-OFForward_stret

init:
	ldr	r0, module$indirect_.L2
.L2:
	add	r0, pc
	b	__objc_exec_class(PLT)

sel_forwardingTargetForSelector_$indirect_.L0:
	.long sel_forwardingTargetForSelector_-(.L0+8)
sel_forwardingTargetForSelector_$indirect_.L1:
	.long sel_forwardingTargetForSelector_-(.L1+8)
module$indirect_.L2:
	.long module-(.L2+8)

.section .init_array, "aw", %init_array
	.long init

.section .rodata
str_forwardingTargetForSelector_:
	.asciz "forwardingTargetForSelector:"

.section .data
sel_forwardingTargetForSelector_:
	.long str_forwardingTargetForSelector_, 0
	.long 0, 0
symtab:
	.long 0, sel_forwardingTargetForSelector_
	.short 0, 0
	.long 0
	.long 0
module:
	.long 8, 16, 0, symtab

#ifdef OF_LINUX
.section .note.GNU-stack, "", %progbits
#endif







|
|




|
|
|
|
|
|


|


|



|
|

|
|



|
|

|


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
#ifdef HAVE_VFP2
	vldmia	sp!, {d0-d7}
#endif
	b	OFMethodNotFound_stret(PLT)
.type OFForward_stret, %function
.size OFForward_stret, .-OFForward_stret

.Linit:
	ldr	r0, .Lmodule$indirect_.L2
.L2:
	add	r0, pc
	b	__objc_exec_class(PLT)

.Lsel_forwardingTargetForSelector_$indirect_.L0:
	.long .Lsel_forwardingTargetForSelector_-(.L0+8)
.Lsel_forwardingTargetForSelector_$indirect_.L1:
	.long .Lsel_forwardingTargetForSelector_-(.L1+8)
.Lmodule$indirect_.L2:
	.long .Lmodule-(.L2+8)

.section .init_array, "aw", %init_array
	.long .Linit

.section .rodata
.Lstr_forwardingTargetForSelector_:
	.asciz "forwardingTargetForSelector:"

.section .data
.Lsel_forwardingTargetForSelector_:
	.long .Lstr_forwardingTargetForSelector_, 0
	.long 0, 0
.Lsymtab:
	.long 0, .Lsel_forwardingTargetForSelector_
	.short 0, 0
	.long 0
	.long 0
.Lmodule:
	.long 8, 16, 0, .Lsymtab

#if defined(OF_LINUX) || defined(OF_HAIKU) || defined(OF_HURD)
.section .note.GNU-stack, "", %progbits
#endif

Modified src/forwarding/forwarding-arm64-elf.S from [81775de57c] to [ae93185aa7].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
	stp	q0, q1, [sp, #80]
	stp	q2, q3, [sp, #112]
	stp	q4, q5, [sp, #144]
	stp	q6, q7, [sp, #176]

	bl	object_getClass

	adrp	x19, sel_forwardingTargetForSelector_
	add	x19, x19, :lo12:sel_forwardingTargetForSelector_

	mov	x1, x19
	bl	class_respondsToSelector

	cbz	x0, 0f

	ldr	x0, [sp]







|
|







38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
	stp	q0, q1, [sp, #80]
	stp	q2, q3, [sp, #112]
	stp	q4, q5, [sp, #144]
	stp	q6, q7, [sp, #176]

	bl	object_getClass

	adrp	x19, .Lsel_forwardingTargetForSelector_
	add	x19, x19, :lo12:.Lsel_forwardingTargetForSelector_

	mov	x1, x19
	bl	class_respondsToSelector

	cbz	x0, 0f

	ldr	x0, [sp]
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

	b	OFMethodNotFound
.type OFForward, %function
.size OFForward, .-OFForward
.type OFForward_stret, %function
.size OFForward_stret, .-OFForward_stret

init:
	adrp	x0, module
	add	x0, x0, :lo12:module
	b	__objc_exec_class

.section .init_array, "aw", %init_array
	.xword init

.section .rodata
str_forwardingTargetForSelector_:
	.asciz "forwardingTargetForSelector:"

.section .data
sel_forwardingTargetForSelector_:
	.xword str_forwardingTargetForSelector_, 0
	.xword 0, 0
symtab:
	.xword 0, sel_forwardingTargetForSelector_
	.short 0, 0
	.long 4
	.xword 0
module:
	.xword 8, 32, 0, symtab

#ifdef OF_LINUX
.section .note.GNU-stack, "", %progbits
#endif







|
|
|



|


|



|
|

|
|



|
|

|


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

	b	OFMethodNotFound
.type OFForward, %function
.size OFForward, .-OFForward
.type OFForward_stret, %function
.size OFForward_stret, .-OFForward_stret

.Linit:
	adrp	x0, .Lmodule
	add	x0, x0, :lo12:.Lmodule
	b	__objc_exec_class

.section .init_array, "aw", %init_array
	.xword .Linit

.section .rodata
.Lstr_forwardingTargetForSelector_:
	.asciz "forwardingTargetForSelector:"

.section .data
.Lsel_forwardingTargetForSelector_:
	.xword .Lstr_forwardingTargetForSelector_, 0
	.xword 0, 0
.Lsymtab:
	.xword 0, .Lsel_forwardingTargetForSelector_
	.short 0, 0
	.long 4
	.xword 0
.Lmodule:
	.xword 8, 32, 0, .Lsymtab

#if defined(OF_LINUX) || defined(OF_HAIKU) || defined(OF_HURD)
.section .note.GNU-stack, "", %progbits
#endif

Modified src/forwarding/forwarding-mips-elf.S from [e03d5d5039] to [f27e195ed0].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
	swc1	$f17, 80($sp)
	swc1	$f18, 84($sp)
	swc1	$f19, 88($sp)
#endif

	move	$s0, $gp
#ifdef OF_PIC
	lw	$s1, %got(sel_forwardingTargetForSelector_)($gp)
#else
	lui	$s1, %hi(sel_forwardingTargetForSelector_)
#endif
	addiu	$s1, $s1, %lo(sel_forwardingTargetForSelector_)

	jal_pic	object_getClass

	move	$gp, $s0
	move	$a0, $v0
	move	$a1, $s1
	jal_pic	class_respondsToSelector







|

|

|







78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
	swc1	$f17, 80($sp)
	swc1	$f18, 84($sp)
	swc1	$f19, 88($sp)
#endif

	move	$s0, $gp
#ifdef OF_PIC
	lw	$s1, %got(.Lsel_forwardingTargetForSelector_)($gp)
#else
	lui	$s1, %hi(.Lsel_forwardingTargetForSelector_)
#endif
	addiu	$s1, $s1, %lo(.Lsel_forwardingTargetForSelector_)

	jal_pic	object_getClass

	move	$gp, $s0
	move	$a0, $v0
	move	$a1, $s1
	jal_pic	class_respondsToSelector
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
	swc1	$f17, 80($sp)
	swc1	$f18, 84($sp)
	swc1	$f19, 88($sp)
#endif

	move	$s0, $gp
#ifdef OF_PIC
	lw	$s1, %got(sel_forwardingTargetForSelector_)($gp)
#else
	lui	$s1, %hi(sel_forwardingTargetForSelector_)
#endif
	addiu	$s1, $s1, %lo(sel_forwardingTargetForSelector_)

	move	$a0, $a1
	jal_pic	object_getClass

	move	$gp, $s0
	move	$a0, $v0
	move	$a1, $s1







|

|

|







202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
	swc1	$f17, 80($sp)
	swc1	$f18, 84($sp)
	swc1	$f19, 88($sp)
#endif

	move	$s0, $gp
#ifdef OF_PIC
	lw	$s1, %got(.Lsel_forwardingTargetForSelector_)($gp)
#else
	lui	$s1, %hi(.Lsel_forwardingTargetForSelector_)
#endif
	addiu	$s1, $s1, %lo(.Lsel_forwardingTargetForSelector_)

	move	$a0, $a1
	jal_pic	object_getClass

	move	$gp, $s0
	move	$a0, $v0
	move	$a1, $s1
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

	addiu	$sp, $sp, 96

	j_pic	of_method_not_found_stret
.type OFForward_stret, %function
.size OFForward_stret, .-OFForward_stret

init:
#ifdef OF_PIC
	lui	$gp, %hi(_gp_disp)
	addiu	$gp, $gp, %lo(_gp_disp)
	addu	$gp, $gp, $t9

	lw	$a0, %got(module)($gp)
	addiu	$a0, $a0, %lo(module)
	lw	$t9, %call16(__objc_exec_class)($gp)
	jr	$t9
#else
	lui	$a0, %hi(module)
	addiu	$a0, $a0, %lo(module)
	j	__objc_exec_class
#endif

.section .ctors, "aw", %progbits
	.long init

.section .rodata
str_forwardingTargetForSelector_:
	.asciz "forwardingTargetForSelector:"

.section .data
sel_forwardingTargetForSelector_:
	.long str_forwardingTargetForSelector_, 0
	.long 0, 0
symtab:
	.long 0, sel_forwardingTargetForSelector_
	.short 0, 0
	.long 0
	.long 0
module:
	.long 8, 16, 0, symtab

#ifdef OF_LINUX
.section .note.GNU-stack, "", %progbits
#endif







|





|
|



|
|




|


|



|
|

|
|



|
|

|


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

	addiu	$sp, $sp, 96

	j_pic	of_method_not_found_stret
.type OFForward_stret, %function
.size OFForward_stret, .-OFForward_stret

.Linit:
#ifdef OF_PIC
	lui	$gp, %hi(_gp_disp)
	addiu	$gp, $gp, %lo(_gp_disp)
	addu	$gp, $gp, $t9

	lw	$a0, %got(.Lmodule)($gp)
	addiu	$a0, $a0, %lo(.Lmodule)
	lw	$t9, %call16(__objc_exec_class)($gp)
	jr	$t9
#else
	lui	$a0, %hi(.Lmodule)
	addiu	$a0, $a0, %lo(.Lmodule)
	j	__objc_exec_class
#endif

.section .ctors, "aw", %progbits
	.long .Linit

.section .rodata
.Lstr_forwardingTargetForSelector_:
	.asciz "forwardingTargetForSelector:"

.section .data
.Lsel_forwardingTargetForSelector_:
	.long .Lstr_forwardingTargetForSelector_, 0
	.long 0, 0
.Lsymtab:
	.long 0, .Lsel_forwardingTargetForSelector_
	.short 0, 0
	.long 0
	.long 0
.Lmodule:
	.long 8, 16, 0, .Lsymtab

#if defined(OF_LINUX) || defined(OF_HAIKU) || defined(OF_HURD)
.section .note.GNU-stack, "", %progbits
#endif

Modified src/forwarding/forwarding-powerpc-elf.S from [65258e67de] to [eb87a47ed7].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
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
	bl	object_getClass+0x8000@plt

	lwz	%r4, .Lgot_sel_forwardingTargetForSelector_-.Lbiased_got2(%r30)
	bl	class_respondsToSelector+0x8000@plt
#else
	bl	object_getClass

	lis	%r4, sel_forwardingTargetForSelector_@ha
	la	%r4, sel_forwardingTargetForSelector_@l(%r4)
	bl	class_respondsToSelector
#endif

	cmpwi	%r3, 0
	beq-	0f

	lwz	%r3, 8(%r1)
#ifdef OF_PIC
	lwz	%r4, .Lgot_sel_forwardingTargetForSelector_-.Lbiased_got2(%r30)
	bl	objc_msg_lookup+0x8000@plt
#else
	lis	%r4, sel_forwardingTargetForSelector_@ha
	la	%r4, sel_forwardingTargetForSelector_@l(%r4)
	bl	objc_msg_lookup
#endif
	mtctr	%r3

	lwz	%r3, 8(%r1)
#ifdef OF_PIC
	lwz	%r4, .Lgot_sel_forwardingTargetForSelector_-.Lbiased_got2(%r30)
#else
	lis	%r4, sel_forwardingTargetForSelector_@ha
	la	%r4, sel_forwardingTargetForSelector_@l(%r4)
#endif
	lwz	%r5, 12(%r1)
	bctrl

	cmpwi	%r3, 0
	beq-	0f
	lwz	%r4, 8(%r1)







|
|











|
|








|
|







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
	bl	object_getClass+0x8000@plt

	lwz	%r4, .Lgot_sel_forwardingTargetForSelector_-.Lbiased_got2(%r30)
	bl	class_respondsToSelector+0x8000@plt
#else
	bl	object_getClass

	lis	%r4, .Lsel_forwardingTargetForSelector_@ha
	la	%r4, .Lsel_forwardingTargetForSelector_@l(%r4)
	bl	class_respondsToSelector
#endif

	cmpwi	%r3, 0
	beq-	0f

	lwz	%r3, 8(%r1)
#ifdef OF_PIC
	lwz	%r4, .Lgot_sel_forwardingTargetForSelector_-.Lbiased_got2(%r30)
	bl	objc_msg_lookup+0x8000@plt
#else
	lis	%r4, .Lsel_forwardingTargetForSelector_@ha
	la	%r4, .Lsel_forwardingTargetForSelector_@l(%r4)
	bl	objc_msg_lookup
#endif
	mtctr	%r3

	lwz	%r3, 8(%r1)
#ifdef OF_PIC
	lwz	%r4, .Lgot_sel_forwardingTargetForSelector_-.Lbiased_got2(%r30)
#else
	lis	%r4, .Lsel_forwardingTargetForSelector_@ha
	la	%r4, .Lsel_forwardingTargetForSelector_@l(%r4)
#endif
	lwz	%r5, 12(%r1)
	bctrl

	cmpwi	%r3, 0
	beq-	0f
	lwz	%r4, 8(%r1)
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
	bl	object_getClass+0x8000@plt

	lwz	%r4, .Lgot_sel_forwardingTargetForSelector_-.Lbiased_got2(%r30)
	bl	class_respondsToSelector+0x8000@plt
#else
	bl	object_getClass

	lis	%r4, sel_forwardingTargetForSelector_@ha
	la	%r4, sel_forwardingTargetForSelector_@l(%r4)
	bl	class_respondsToSelector
#endif

	cmpwi	%r3, 0
	beq-	0f

	lwz	%r3, 12(%r1)
#ifdef OF_PIC
	lwz	%r4, .Lgot_sel_forwardingTargetForSelector_-.Lbiased_got2(%r30)
	bl	objc_msg_lookup+0x8000@plt
#else
	lis	%r4, sel_forwardingTargetForSelector_@ha
	la	%r4, sel_forwardingTargetForSelector_@l(%r4)
	bl	objc_msg_lookup
#endif
	mtctr	%r3

	lwz	%r3, 12(%r1)
#ifdef OF_PIC
	lwz	%r4, .Lgot_sel_forwardingTargetForSelector_-.Lbiased_got2(%r30)
#else
	lis	%r4, sel_forwardingTargetForSelector_@ha
	la	%r4, sel_forwardingTargetForSelector_@l(%r4)
#endif
	lwz	%r5, 16(%r1)
	bctrl

	cmpwi	%r3, 0
	beq-	0f
	lwz	%r4, 12(%r1)







|
|











|
|








|
|







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
	bl	object_getClass+0x8000@plt

	lwz	%r4, .Lgot_sel_forwardingTargetForSelector_-.Lbiased_got2(%r30)
	bl	class_respondsToSelector+0x8000@plt
#else
	bl	object_getClass

	lis	%r4, .Lsel_forwardingTargetForSelector_@ha
	la	%r4, .Lsel_forwardingTargetForSelector_@l(%r4)
	bl	class_respondsToSelector
#endif

	cmpwi	%r3, 0
	beq-	0f

	lwz	%r3, 12(%r1)
#ifdef OF_PIC
	lwz	%r4, .Lgot_sel_forwardingTargetForSelector_-.Lbiased_got2(%r30)
	bl	objc_msg_lookup+0x8000@plt
#else
	lis	%r4, .Lsel_forwardingTargetForSelector_@ha
	la	%r4, .Lsel_forwardingTargetForSelector_@l(%r4)
	bl	objc_msg_lookup
#endif
	mtctr	%r3

	lwz	%r3, 12(%r1)
#ifdef OF_PIC
	lwz	%r4, .Lgot_sel_forwardingTargetForSelector_-.Lbiased_got2(%r30)
#else
	lis	%r4, .Lsel_forwardingTargetForSelector_@ha
	la	%r4, .Lsel_forwardingTargetForSelector_@l(%r4)
#endif
	lwz	%r5, 16(%r1)
	bctrl

	cmpwi	%r3, 0
	beq-	0f
	lwz	%r4, 12(%r1)
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
	bctr
#else
	b	OFMethodNotFound_stret
#endif
.type OFForward_stret, @function
.size OFForward_stret, .-OFForward_stret

init:
	stwu	%r1, -16(%r1)
	mflr	%r0
	stw	%r0, 20(%r1)
#ifdef OF_PIC
	stw	%r30, 8(%r1)

	bl	0f
0:
	mflr	%r30
	addis	%r30, %r30, .Lbiased_got2-0b@ha
	addi	%r30, %r30, .Lbiased_got2-0b@l

	lwz	%r3, .Lgot_module-.Lbiased_got2(%r30)
	bl	__objc_exec_class+0x8000@plt

	lwz	%r30, 8(%r1)
#else
	lis	%r3, module@ha
	la	%r3, module@l(%r3)
	bl	__objc_exec_class
#endif

	lwz	%r0, 20(%r1)
	addi	%r1, %r1, 16
	mtlr	%r0
	blr

.section .ctors, "aw", @progbits
	.long init

.section .rodata
str_forwardingTargetForSelector_:
	.asciz "forwardingTargetForSelector:"

.section .data
sel_forwardingTargetForSelector_:
	.long str_forwardingTargetForSelector_, 0
	.long 0, 0
symtab:
	.long 0, sel_forwardingTargetForSelector_
	.short 0, 0
	.long 0
	.long 0
module:
	.long 8, 16, 0, symtab

#ifdef OF_PIC
.section .got2, "aw"
.Lbiased_got2 = .+0x8000
.Lgot_module:
	.long module
.Lgot_sel_forwardingTargetForSelector_:
	.long sel_forwardingTargetForSelector_
.Lgot_OFMethodNotFound:
	.long OFMethodNotFound
.Lgot_OFMethodNotFound_stret:
	.long OFMethodNotFound_stret
#endif

#ifdef OF_LINUX
.section .note.GNU-stack, "", @progbits
#endif







|

















|
|









|


|



|
|

|
|



|
|





|

|






|


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
	bctr
#else
	b	OFMethodNotFound_stret
#endif
.type OFForward_stret, @function
.size OFForward_stret, .-OFForward_stret

.Linit:
	stwu	%r1, -16(%r1)
	mflr	%r0
	stw	%r0, 20(%r1)
#ifdef OF_PIC
	stw	%r30, 8(%r1)

	bl	0f
0:
	mflr	%r30
	addis	%r30, %r30, .Lbiased_got2-0b@ha
	addi	%r30, %r30, .Lbiased_got2-0b@l

	lwz	%r3, .Lgot_module-.Lbiased_got2(%r30)
	bl	__objc_exec_class+0x8000@plt

	lwz	%r30, 8(%r1)
#else
	lis	%r3, .Lmodule@ha
	la	%r3, .Lmodule@l(%r3)
	bl	__objc_exec_class
#endif

	lwz	%r0, 20(%r1)
	addi	%r1, %r1, 16
	mtlr	%r0
	blr

.section .ctors, "aw", @progbits
	.long .Linit

.section .rodata
.Lstr_forwardingTargetForSelector_:
	.asciz "forwardingTargetForSelector:"

.section .data
.Lsel_forwardingTargetForSelector_:
	.long .Lstr_forwardingTargetForSelector_, 0
	.long 0, 0
.Lsymtab:
	.long 0, .Lsel_forwardingTargetForSelector_
	.short 0, 0
	.long 0
	.long 0
.Lmodule:
	.long 8, 16, 0, .Lsymtab

#ifdef OF_PIC
.section .got2, "aw"
.Lbiased_got2 = .+0x8000
.Lgot_module:
	.long .Lmodule
.Lgot_sel_forwardingTargetForSelector_:
	.long .Lsel_forwardingTargetForSelector_
.Lgot_OFMethodNotFound:
	.long OFMethodNotFound
.Lgot_OFMethodNotFound_stret:
	.long OFMethodNotFound_stret
#endif

#if defined(OF_LINUX) || defined(OF_HAIKU) || defined(OF_HURD)
.section .note.GNU-stack, "", @progbits
#endif

Modified src/forwarding/forwarding-sparc-elf.S from [8ec3e64b89] to [51069593c4].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
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
	 add	%l7, %lo(_GLOBAL_OFFSET_TABLE_ + 4), %l7
#endif

	mov	%i0, %o0
	call	object_getClass
	 nop

	sethi	%hi(sel_forwardingTargetForSelector_), %o1
	or	%o1, %lo(sel_forwardingTargetForSelector_), %o1
#ifdef OF_PIC
	ld	[%l7 + %o1], %o1
#endif
	call	class_respondsToSelector
	 nop

	cmp	%o0, 0
	be	0f

	 mov	%i0, %o0
	sethi	%hi(sel_forwardingTargetForSelector_), %o1
	or	%o1, %lo(sel_forwardingTargetForSelector_), %o1
#ifdef OF_PIC
	ld	[%l7 + %o1], %o1
#endif
	call	objc_msg_lookup
	 nop
	mov	%o0, %l0

	mov	%i0, %o0
	sethi	%hi(sel_forwardingTargetForSelector_), %o1
	or	%o1, %lo(sel_forwardingTargetForSelector_), %o1
#ifdef OF_PIC
	ld	[%l7 + %o1], %o1
#endif
	jmpl	%l0, %o7
	 mov	%i1, %o2

	cmp	%o0, 0







|
|










|
|








|
|







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
	 add	%l7, %lo(_GLOBAL_OFFSET_TABLE_ + 4), %l7
#endif

	mov	%i0, %o0
	call	object_getClass
	 nop

	sethi	%hi(.Lsel_forwardingTargetForSelector_), %o1
	or	%o1, %lo(.Lsel_forwardingTargetForSelector_), %o1
#ifdef OF_PIC
	ld	[%l7 + %o1], %o1
#endif
	call	class_respondsToSelector
	 nop

	cmp	%o0, 0
	be	0f

	 mov	%i0, %o0
	sethi	%hi(.Lsel_forwardingTargetForSelector_), %o1
	or	%o1, %lo(.Lsel_forwardingTargetForSelector_), %o1
#ifdef OF_PIC
	ld	[%l7 + %o1], %o1
#endif
	call	objc_msg_lookup
	 nop
	mov	%o0, %l0

	mov	%i0, %o0
	sethi	%hi(.Lsel_forwardingTargetForSelector_), %o1
	or	%o1, %lo(.Lsel_forwardingTargetForSelector_), %o1
#ifdef OF_PIC
	ld	[%l7 + %o1], %o1
#endif
	jmpl	%l0, %o7
	 mov	%i1, %o2

	cmp	%o0, 0
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
	 add	%l7, %lo(_GLOBAL_OFFSET_TABLE_ + 4), %l7
#endif

	mov	%i1, %o0
	call	object_getClass
	 nop

	sethi	%hi(sel_forwardingTargetForSelector_), %o1
	or	%o1, %lo(sel_forwardingTargetForSelector_), %o1
#ifdef OF_PIC
	ld	[%l7 + %o1], %o1
#endif
	call	class_respondsToSelector
	 nop

	cmp	%o0, 0
	be	0f

	 mov	%i1, %o0
	sethi	%hi(sel_forwardingTargetForSelector_), %o1
	or	%o1, %lo(sel_forwardingTargetForSelector_), %o1
#ifdef OF_PIC
	ld	[%l7 + %o1], %o1
#endif
	call	objc_msg_lookup
	 nop
	mov	%o0, %l0

	mov	%i1, %o0
	sethi	%hi(sel_forwardingTargetForSelector_), %o1
	or	%o1, %lo(sel_forwardingTargetForSelector_), %o1
#ifdef OF_PIC
	ld	[%l7 + %o1], %o1
#endif
	jmpl	%l0, %o7
	 mov	%i2, %o2

	cmp	%o0, 0







|
|










|
|








|
|







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
	 add	%l7, %lo(_GLOBAL_OFFSET_TABLE_ + 4), %l7
#endif

	mov	%i1, %o0
	call	object_getClass
	 nop

	sethi	%hi(.Lsel_forwardingTargetForSelector_), %o1
	or	%o1, %lo(.Lsel_forwardingTargetForSelector_), %o1
#ifdef OF_PIC
	ld	[%l7 + %o1], %o1
#endif
	call	class_respondsToSelector
	 nop

	cmp	%o0, 0
	be	0f

	 mov	%i1, %o0
	sethi	%hi(.Lsel_forwardingTargetForSelector_), %o1
	or	%o1, %lo(.Lsel_forwardingTargetForSelector_), %o1
#ifdef OF_PIC
	ld	[%l7 + %o1], %o1
#endif
	call	objc_msg_lookup
	 nop
	mov	%o0, %l0

	mov	%i1, %o0
	sethi	%hi(.Lsel_forwardingTargetForSelector_), %o1
	or	%o1, %lo(.Lsel_forwardingTargetForSelector_), %o1
#ifdef OF_PIC
	ld	[%l7 + %o1], %o1
#endif
	jmpl	%l0, %o7
	 mov	%i2, %o2

	cmp	%o0, 0
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

0:
	call	OFMethodNotFound_stret
	 restore
.type OFForward_stret, %function
.size OFForward_stret, .-OFForward_stret

init:
	save	%sp, -96, %sp

#ifdef OF_PIC
	sethi	%hi(_GLOBAL_OFFSET_TABLE_ - 4), %l7
	call	add_pc
	 add	%l7, %lo(_GLOBAL_OFFSET_TABLE_ + 4), %l7
#endif

	sethi	%hi(module), %i0
	or	%i0, %lo(module), %i0
#ifdef OF_PIC
	ld	[%l7 + %i0], %i0
#endif

	call	__objc_exec_class
	 restore

#ifdef OF_PIC
add_pc:
	jmp	%o7 + 8
	 add	%l7, %o7, %l7
#endif

#ifdef OF_SOLARIS
.section .init_array, "aw"
#else
.section .ctors, "aw", %progbits
#endif
	.word init

.section .rodata
str_forwardingTargetForSelector_:
	.asciz "forwardingTargetForSelector:"

.section .data
sel_forwardingTargetForSelector_:
	.word str_forwardingTargetForSelector_, 0
	.word 0, 0
symtab:
	.word 0, sel_forwardingTargetForSelector_
	.half 0, 0
	.word 0
	.word 0
module:
	.word 8, 16, 0, symtab

#ifdef OF_LINUX
.section .note.GNU-stack, "", %progbits
#endif







|








|
|


















|


|



|
|

|
|



|
|

|


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

0:
	call	OFMethodNotFound_stret
	 restore
.type OFForward_stret, %function
.size OFForward_stret, .-OFForward_stret

.Linit:
	save	%sp, -96, %sp

#ifdef OF_PIC
	sethi	%hi(_GLOBAL_OFFSET_TABLE_ - 4), %l7
	call	add_pc
	 add	%l7, %lo(_GLOBAL_OFFSET_TABLE_ + 4), %l7
#endif

	sethi	%hi(.Lmodule), %i0
	or	%i0, %lo(.Lmodule), %i0
#ifdef OF_PIC
	ld	[%l7 + %i0], %i0
#endif

	call	__objc_exec_class
	 restore

#ifdef OF_PIC
add_pc:
	jmp	%o7 + 8
	 add	%l7, %o7, %l7
#endif

#ifdef OF_SOLARIS
.section .init_array, "aw"
#else
.section .ctors, "aw", %progbits
#endif
	.word .Linit

.section .rodata
.Lstr_forwardingTargetForSelector_:
	.asciz "forwardingTargetForSelector:"

.section .data
.Lsel_forwardingTargetForSelector_:
	.word .Lstr_forwardingTargetForSelector_, 0
	.word 0, 0
.Lsymtab:
	.word 0, .Lsel_forwardingTargetForSelector_
	.half 0, 0
	.word 0
	.word 0
.Lmodule:
	.word 8, 16, 0, .Lsymtab

#if defined(OF_LINUX) || defined(OF_HAIKU) || defined(OF_HURD)
.section .note.GNU-stack, "", %progbits
#endif

Modified src/forwarding/forwarding-sparc64-elf.S from [5ae72e6aac] to [4e4b856e4e].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
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
	std	%f22, [%sp + BIAS + 264]
	std	%f24, [%sp + BIAS + 272]
	std	%f26, [%sp + BIAS + 280]
	std	%f28, [%sp + BIAS + 288]
	std	%f30, [%sp + BIAS + 296]

	sethi	%hi(_GLOBAL_OFFSET_TABLE_ - 4), %l7
	call	add_pc
	 add	%l7, %lo(_GLOBAL_OFFSET_TABLE_ + 4), %l7

	mov	%i0, %o0
	call	object_getClass
	 nop

	sethi	%hi(sel_forwardingTargetForSelector_), %o1
	or	%o1, %lo(sel_forwardingTargetForSelector_), %o1
	ldx	[%l7 + %o1], %o1
	call	class_respondsToSelector
	 nop

	brz,pn	%o0, 0f

	 mov	%i0, %o0
	sethi	%hi(sel_forwardingTargetForSelector_), %o1
	or	%o1, %lo(sel_forwardingTargetForSelector_), %o1
	ldx	[%l7 + %o1], %o1
	call	objc_msg_lookup
	 nop
	mov	%o0, %l0

	mov	%i0, %o0
	sethi	%hi(sel_forwardingTargetForSelector_), %o1
	or	%o1, %lo(sel_forwardingTargetForSelector_), %o1
	ldx	[%l7 + %o1], %o1
	jmpl	%l0, %o7
	 mov	%i1, %o2

	brz,pn	%o0, 0f
	 cmp	%o0, %i0
	be,pn	%xcc, 0f







|






|
|







|
|






|
|







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
	std	%f22, [%sp + BIAS + 264]
	std	%f24, [%sp + BIAS + 272]
	std	%f26, [%sp + BIAS + 280]
	std	%f28, [%sp + BIAS + 288]
	std	%f30, [%sp + BIAS + 296]

	sethi	%hi(_GLOBAL_OFFSET_TABLE_ - 4), %l7
	call	.LaddPC
	 add	%l7, %lo(_GLOBAL_OFFSET_TABLE_ + 4), %l7

	mov	%i0, %o0
	call	object_getClass
	 nop

	sethi	%hi(.Lsel_forwardingTargetForSelector_), %o1
	or	%o1, %lo(.Lsel_forwardingTargetForSelector_), %o1
	ldx	[%l7 + %o1], %o1
	call	class_respondsToSelector
	 nop

	brz,pn	%o0, 0f

	 mov	%i0, %o0
	sethi	%hi(.Lsel_forwardingTargetForSelector_), %o1
	or	%o1, %lo(.Lsel_forwardingTargetForSelector_), %o1
	ldx	[%l7 + %o1], %o1
	call	objc_msg_lookup
	 nop
	mov	%o0, %l0

	mov	%i0, %o0
	sethi	%hi(.Lsel_forwardingTargetForSelector_), %o1
	or	%o1, %lo(.Lsel_forwardingTargetForSelector_), %o1
	ldx	[%l7 + %o1], %o1
	jmpl	%l0, %o7
	 mov	%i1, %o2

	brz,pn	%o0, 0f
	 cmp	%o0, %i0
	be,pn	%xcc, 0f
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
	std	%f22, [%sp + BIAS + 264]
	std	%f24, [%sp + BIAS + 272]
	std	%f26, [%sp + BIAS + 280]
	std	%f28, [%sp + BIAS + 288]
	std	%f30, [%sp + BIAS + 296]

	sethi	%hi(_GLOBAL_OFFSET_TABLE_ - 4), %l7
	call	add_pc
	 add	%l7, %lo(_GLOBAL_OFFSET_TABLE_ + 4), %l7

	mov	%i1, %o0
	call	object_getClass
	 nop

	sethi	%hi(sel_forwardingTargetForSelector_), %o1
	or	%o1, %lo(sel_forwardingTargetForSelector_), %o1
	ldx	[%l7 + %o1], %o1
	call	class_respondsToSelector
	 nop

	brz,pn	%o0, 0f

	 mov	%i1, %o0
	sethi	%hi(sel_forwardingTargetForSelector_), %o1
	or	%o1, %lo(sel_forwardingTargetForSelector_), %o1
	ldx	[%l7 + %o1], %o1
	call	objc_msg_lookup
	 nop
	mov	%o0, %l0

	mov	%i1, %o0
	sethi	%hi(sel_forwardingTargetForSelector_), %o1
	or	%o1, %lo(sel_forwardingTargetForSelector_), %o1
	ldx	[%l7 + %o1], %o1
	jmpl	%l0, %o7
	 mov	%i2, %o2

	brz,pn	%o0, 0f
	 cmp	%o0, %i1
	be,pn	%xcc, 0f







|






|
|







|
|






|
|







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
	std	%f22, [%sp + BIAS + 264]
	std	%f24, [%sp + BIAS + 272]
	std	%f26, [%sp + BIAS + 280]
	std	%f28, [%sp + BIAS + 288]
	std	%f30, [%sp + BIAS + 296]

	sethi	%hi(_GLOBAL_OFFSET_TABLE_ - 4), %l7
	call	.LaddPC
	 add	%l7, %lo(_GLOBAL_OFFSET_TABLE_ + 4), %l7

	mov	%i1, %o0
	call	object_getClass
	 nop

	sethi	%hi(.Lsel_forwardingTargetForSelector_), %o1
	or	%o1, %lo(.Lsel_forwardingTargetForSelector_), %o1
	ldx	[%l7 + %o1], %o1
	call	class_respondsToSelector
	 nop

	brz,pn	%o0, 0f

	 mov	%i1, %o0
	sethi	%hi(.Lsel_forwardingTargetForSelector_), %o1
	or	%o1, %lo(.Lsel_forwardingTargetForSelector_), %o1
	ldx	[%l7 + %o1], %o1
	call	objc_msg_lookup
	 nop
	mov	%o0, %l0

	mov	%i1, %o0
	sethi	%hi(.Lsel_forwardingTargetForSelector_), %o1
	or	%o1, %lo(.Lsel_forwardingTargetForSelector_), %o1
	ldx	[%l7 + %o1], %o1
	jmpl	%l0, %o7
	 mov	%i2, %o2

	brz,pn	%o0, 0f
	 cmp	%o0, %i1
	be,pn	%xcc, 0f
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

0:
	call	OFMethodNotFound_stret
	 restore
.type OFForward_stret, %function
.size OFForward_stret, .-OFForward_stret

init:
	save	%sp, -176, %sp

	sethi	%hi(_GLOBAL_OFFSET_TABLE_ - 4), %l7
	call	add_pc
	 add	%l7, %lo(_GLOBAL_OFFSET_TABLE_ + 4), %l7

	sethi	%hi(module), %i0
	or	%i0, %lo(module), %i0
	ldx	[%l7 + %i0], %i0

	call	__objc_exec_class
	 restore

add_pc:
	jmp	%o7 + 8
	 add	%l7, %o7, %l7

#ifdef OF_SOLARIS
.section .init_array, "aw"
#else
.section .ctors, "aw", %progbits
#endif
	.xword init

.section .rodata
str_forwardingTargetForSelector_:
	.asciz "forwardingTargetForSelector:"

.section .data
sel_forwardingTargetForSelector_:
	.xword str_forwardingTargetForSelector_, 0
	.xword 0, 0
symtab:
	.xword 0, sel_forwardingTargetForSelector_
	.half 0, 0
	.word 0
	.xword 0
module:
	.xword 8, 32, 0, symtab

#ifdef OF_LINUX
.section .note.GNU-stack, "", %progbits
#endif







|



|


|
|





|








|


|



|
|

|
|



|
|

|


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

0:
	call	OFMethodNotFound_stret
	 restore
.type OFForward_stret, %function
.size OFForward_stret, .-OFForward_stret

.Linit:
	save	%sp, -176, %sp

	sethi	%hi(_GLOBAL_OFFSET_TABLE_ - 4), %l7
	call	.LaddPC
	 add	%l7, %lo(_GLOBAL_OFFSET_TABLE_ + 4), %l7

	sethi	%hi(.Lmodule), %i0
	or	%i0, %lo(.Lmodule), %i0
	ldx	[%l7 + %i0], %i0

	call	__objc_exec_class
	 restore

.LaddPC:
	jmp	%o7 + 8
	 add	%l7, %o7, %l7

#ifdef OF_SOLARIS
.section .init_array, "aw"
#else
.section .ctors, "aw", %progbits
#endif
	.xword .Linit

.section .rodata
.Lstr_forwardingTargetForSelector_:
	.asciz "forwardingTargetForSelector:"

.section .data
.Lsel_forwardingTargetForSelector_:
	.xword .Lstr_forwardingTargetForSelector_, 0
	.xword 0, 0
.Lsymtab:
	.xword 0, .Lsel_forwardingTargetForSelector_
	.half 0, 0
	.word 0
	.xword 0
.Lmodule:
	.xword 8, 32, 0, .Lsymtab

#if defined(OF_LINUX) || defined(OF_HAIKU) || defined(OF_HURD)
.section .note.GNU-stack, "", %progbits
#endif

Modified src/forwarding/forwarding-x86-elf.S from [a55d3f40d7] to [8672a85794].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
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
OFForward:
	pushl	%ebp
	movl	%esp, %ebp

	pushl	%ebx
	subl	$20, %esp

	call	get_eip
	addl	$_GLOBAL_OFFSET_TABLE_, %ebx

	movl	8(%ebp), %eax
	movl	%eax, (%esp)
	call	object_getClass@PLT

	movl	%eax, (%esp)
	leal	sel_forwardingTargetForSelector_@GOTOFF(%ebx), %eax
	movl	%eax, 4(%esp)
	call	class_respondsToSelector@PLT

	testl	%eax, %eax
	jz	0f

	movl	8(%ebp), %eax
	movl	%eax, (%esp)
	leal	sel_forwardingTargetForSelector_@GOTOFF(%ebx), %eax
	movl	%eax, 4(%esp)
	call	objc_msg_lookup@PLT

	movl	8(%ebp), %edx
	movl	%edx, (%esp)
	leal	sel_forwardingTargetForSelector_@GOTOFF(%ebx), %edx
	movl	%edx, 4(%esp)
	movl	12(%ebp), %edx
	movl	%edx, 8(%esp)
	call	*%eax

	testl	%eax, %eax
	jz	0f







|







|








|





|







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
OFForward:
	pushl	%ebp
	movl	%esp, %ebp

	pushl	%ebx
	subl	$20, %esp

	call	.LgetEIP
	addl	$_GLOBAL_OFFSET_TABLE_, %ebx

	movl	8(%ebp), %eax
	movl	%eax, (%esp)
	call	object_getClass@PLT

	movl	%eax, (%esp)
	leal	.Lsel_forwardingTargetForSelector_@GOTOFF(%ebx), %eax
	movl	%eax, 4(%esp)
	call	class_respondsToSelector@PLT

	testl	%eax, %eax
	jz	0f

	movl	8(%ebp), %eax
	movl	%eax, (%esp)
	leal	.Lsel_forwardingTargetForSelector_@GOTOFF(%ebx), %eax
	movl	%eax, 4(%esp)
	call	objc_msg_lookup@PLT

	movl	8(%ebp), %edx
	movl	%edx, (%esp)
	leal	.Lsel_forwardingTargetForSelector_@GOTOFF(%ebx), %edx
	movl	%edx, 4(%esp)
	movl	12(%ebp), %edx
	movl	%edx, 8(%esp)
	call	*%eax

	testl	%eax, %eax
	jz	0f
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
	addl	$20, %esp
	popl	%ebx
	popl	%ebp

	jmp	*%eax

0:
	leal	OFMethodNotFound@GOTOFF(%ebx), %eax

	addl	$20, %esp
	popl	%ebx
	popl	%ebp

	jmp	*%eax
.type OFForward, %function
.size OFForward, .-OFForward

OFForward_stret:
	pushl	%ebp
	movl	%esp, %ebp

	pushl	%ebx
	subl	$20, %esp

	call	get_eip
	addl	$_GLOBAL_OFFSET_TABLE_, %ebx

	movl	12(%ebp), %eax
	movl	%eax, (%esp)
	call	object_getClass@PLT

	movl	%eax, (%esp)
	leal	sel_forwardingTargetForSelector_@GOTOFF(%ebx), %eax
	movl	%eax, 4(%esp)
	call	class_respondsToSelector@PLT

	testl	%eax, %eax
	jz	0f

	movl	12(%ebp), %eax
	movl	%eax, (%esp)
	leal	sel_forwardingTargetForSelector_@GOTOFF(%ebx), %eax
	movl	%eax, 4(%esp)
	call	objc_msg_lookup@PLT

	movl	12(%ebp), %edx
	movl	%edx, (%esp)
	leal	sel_forwardingTargetForSelector_@GOTOFF(%ebx), %edx
	movl	%edx, 4(%esp)
	movl	16(%ebp), %edx
	movl	%edx, 8(%esp)
	call	*%eax

	testl	%eax, %eax
	jz	0f







|
















|







|








|





|







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
	addl	$20, %esp
	popl	%ebx
	popl	%ebp

	jmp	*%eax

0:
	movl	OFMethodNotFound@GOT(%ebx), %eax

	addl	$20, %esp
	popl	%ebx
	popl	%ebp

	jmp	*%eax
.type OFForward, %function
.size OFForward, .-OFForward

OFForward_stret:
	pushl	%ebp
	movl	%esp, %ebp

	pushl	%ebx
	subl	$20, %esp

	call	.LgetEIP
	addl	$_GLOBAL_OFFSET_TABLE_, %ebx

	movl	12(%ebp), %eax
	movl	%eax, (%esp)
	call	object_getClass@PLT

	movl	%eax, (%esp)
	leal	.Lsel_forwardingTargetForSelector_@GOTOFF(%ebx), %eax
	movl	%eax, 4(%esp)
	call	class_respondsToSelector@PLT

	testl	%eax, %eax
	jz	0f

	movl	12(%ebp), %eax
	movl	%eax, (%esp)
	leal	.Lsel_forwardingTargetForSelector_@GOTOFF(%ebx), %eax
	movl	%eax, 4(%esp)
	call	objc_msg_lookup@PLT

	movl	12(%ebp), %edx
	movl	%edx, (%esp)
	leal	.Lsel_forwardingTargetForSelector_@GOTOFF(%ebx), %edx
	movl	%edx, 4(%esp)
	movl	16(%ebp), %edx
	movl	%edx, 8(%esp)
	call	*%eax

	testl	%eax, %eax
	jz	0f
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
	addl	$20, %esp
	popl	%ebx
	popl	%ebp

	jmp	*%eax

0:
	leal	OFMethodNotFound_stret@GOTOFF(%ebx), %eax

	addl	$20, %esp
	popl	%ebx
	popl	%ebp

	jmp	*%eax
.type OFForward_stret, %function
.size OFForward_stret, .-OFForward_stret

init:
	pushl	%ebp
	movl	%esp, %ebp

	pushl	%ebx
	subl	$4, %esp

	call	get_eip
	addl	$_GLOBAL_OFFSET_TABLE_, %ebx

	leal	module@GOTOFF(%ebx), %eax
	movl	%eax, (%esp)
	call	__objc_exec_class@PLT

	addl	$4, %esp
	popl	%ebx
	popl	%ebp
	ret

get_eip:
	movl	(%esp), %ebx
	ret

#ifdef OF_SOLARIS
.section .init_array, "aw"
#else
.section .ctors, "aw", %progbits
#endif
	.long init

.section .rodata
str_forwardingTargetForSelector_:
	.asciz "forwardingTargetForSelector:"

.section .data
sel_forwardingTargetForSelector_:
	.long str_forwardingTargetForSelector_, 0
	.long 0, 0
symtab:
	.long 0, sel_forwardingTargetForSelector_
	.short 0, 0
	.long 0
	.long 0
module:
	.long 8, 16, 0, symtab

#ifdef OF_LINUX
.section .note.GNU-stack, "", %progbits
#endif







|









|






|


|








|








|


|



|
|

|
|



|
|

|


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
	addl	$20, %esp
	popl	%ebx
	popl	%ebp

	jmp	*%eax

0:
	movl	OFMethodNotFound_stret@GOT(%ebx), %eax

	addl	$20, %esp
	popl	%ebx
	popl	%ebp

	jmp	*%eax
.type OFForward_stret, %function
.size OFForward_stret, .-OFForward_stret

.Linit:
	pushl	%ebp
	movl	%esp, %ebp

	pushl	%ebx
	subl	$4, %esp

	call	.LgetEIP
	addl	$_GLOBAL_OFFSET_TABLE_, %ebx

	leal	.Lmodule@GOTOFF(%ebx), %eax
	movl	%eax, (%esp)
	call	__objc_exec_class@PLT

	addl	$4, %esp
	popl	%ebx
	popl	%ebp
	ret

.LgetEIP:
	movl	(%esp), %ebx
	ret

#ifdef OF_SOLARIS
.section .init_array, "aw"
#else
.section .ctors, "aw", %progbits
#endif
	.long .Linit

.section .rodata
.Lstr_forwardingTargetForSelector_:
	.asciz "forwardingTargetForSelector:"

.section .data
.Lsel_forwardingTargetForSelector_:
	.long .Lstr_forwardingTargetForSelector_, 0
	.long 0, 0
.Lsymtab:
	.long 0, .Lsel_forwardingTargetForSelector_
	.short 0, 0
	.long 0
	.long 0
.Lmodule:
	.long 8, 16, 0, .Lsymtab

#if defined(OF_LINUX) || defined(OF_HAIKU) || defined(OF_HURD)
.section .note.GNU-stack, "", %progbits
#endif

Modified src/forwarding/forwarding-x86-win32.S from [7c90db9737] to [5d1651a3b2].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
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
	subl	$20, %esp

	movl	8(%ebp), %eax
	movl	%eax, (%esp)
	call	_object_getClass

	movl	%eax, (%esp)
	movl	$sel_forwardingTargetForSelector_, %eax
	movl	%eax, 4(%esp)
	call	_class_respondsToSelector

	testl	%eax, %eax
	jz	0f

	movl	8(%ebp), %eax
	movl	%eax, (%esp)
	movl	$sel_forwardingTargetForSelector_, %eax
	movl	%eax, 4(%esp)
	call	_objc_msg_lookup

	movl	8(%ebp), %edx
	movl	%edx, (%esp)
	movl	$sel_forwardingTargetForSelector_, %edx
	movl	%edx, 4(%esp)
	movl	12(%ebp), %edx
	movl	%edx, 8(%esp)
	call	*%eax

	testl	%eax, %eax
	jz	0f







|








|





|







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
	subl	$20, %esp

	movl	8(%ebp), %eax
	movl	%eax, (%esp)
	call	_object_getClass

	movl	%eax, (%esp)
	movl	$.Lsel_forwardingTargetForSelector_, %eax
	movl	%eax, 4(%esp)
	call	_class_respondsToSelector

	testl	%eax, %eax
	jz	0f

	movl	8(%ebp), %eax
	movl	%eax, (%esp)
	movl	$.Lsel_forwardingTargetForSelector_, %eax
	movl	%eax, 4(%esp)
	call	_objc_msg_lookup

	movl	8(%ebp), %edx
	movl	%edx, (%esp)
	movl	$.Lsel_forwardingTargetForSelector_, %edx
	movl	%edx, 4(%esp)
	movl	12(%ebp), %edx
	movl	%edx, 8(%esp)
	call	*%eax

	testl	%eax, %eax
	jz	0f
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
	subl	$20, %esp

	movl	12(%ebp), %eax
	movl	%eax, (%esp)
	call	_object_getClass

	movl	%eax, (%esp)
	movl	$sel_forwardingTargetForSelector_, %eax
	movl	%eax, 4(%esp)
	call	_class_respondsToSelector

	testl	%eax, %eax
	jz	0f

	movl	12(%ebp), %eax
	movl	%eax, (%esp)
	movl	$sel_forwardingTargetForSelector_, %eax
	movl	%eax, 4(%esp)
	call	_objc_msg_lookup

	movl	12(%ebp), %edx
	movl	%edx, (%esp)
	movl	$sel_forwardingTargetForSelector_, %edx
	movl	%edx, 4(%esp)
	movl	16(%ebp), %edx
	movl	%edx, 8(%esp)
	call	*%eax

	testl	%eax, %eax
	jz	0f







|








|





|







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
	subl	$20, %esp

	movl	12(%ebp), %eax
	movl	%eax, (%esp)
	call	_object_getClass

	movl	%eax, (%esp)
	movl	$.Lsel_forwardingTargetForSelector_, %eax
	movl	%eax, 4(%esp)
	call	_class_respondsToSelector

	testl	%eax, %eax
	jz	0f

	movl	12(%ebp), %eax
	movl	%eax, (%esp)
	movl	$.Lsel_forwardingTargetForSelector_, %eax
	movl	%eax, 4(%esp)
	call	_objc_msg_lookup

	movl	12(%ebp), %edx
	movl	%edx, (%esp)
	movl	$.Lsel_forwardingTargetForSelector_, %edx
	movl	%edx, 4(%esp)
	movl	16(%ebp), %edx
	movl	%edx, 8(%esp)
	call	*%eax

	testl	%eax, %eax
	jz	0f
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

	jmp	_OFMethodNotFound_stret
.def _OFForward_stret
.scl 2
.type 32
.endef

init:
	pushl	%ebp
	movl	%esp, %ebp

	pushl	%ebx
	subl	$4, %esp

	movl	$module, %eax
	movl	%eax, (%esp)
	call	___objc_exec_class

	addl	$4, %esp
	popl	%ebx
	popl	%ebp
	ret

.section .ctors, "aw"
	.long init

.section .rodata
str_forwardingTargetForSelector_:
	.asciz "forwardingTargetForSelector:"

.section .data
sel_forwardingTargetForSelector_:
	.long str_forwardingTargetForSelector_, 0
	.long 0, 0
symtab:
	.long 0, sel_forwardingTargetForSelector_
	.short 0, 0
	.long 0
	.long 0
module:
	.long 8, 16, 0, symtab







|






|









|


|



|
|

|
|



|
|
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

	jmp	_OFMethodNotFound_stret
.def _OFForward_stret
.scl 2
.type 32
.endef

.Linit:
	pushl	%ebp
	movl	%esp, %ebp

	pushl	%ebx
	subl	$4, %esp

	movl	$.Lmodule, %eax
	movl	%eax, (%esp)
	call	___objc_exec_class

	addl	$4, %esp
	popl	%ebx
	popl	%ebp
	ret

.section .ctors, "aw"
	.long .Linit

.section .rodata
.Lstr_forwardingTargetForSelector_:
	.asciz "forwardingTargetForSelector:"

.section .data
.Lsel_forwardingTargetForSelector_:
	.long .Lstr_forwardingTargetForSelector_, 0
	.long 0, 0
.Lsymtab:
	.long 0, .Lsel_forwardingTargetForSelector_
	.short 0, 0
	.long 0
	.long 0
.Lmodule:
	.long 8, 16, 0, .Lsymtab

Modified src/forwarding/forwarding.S from [0a5e45dea8] to [1668d8694a].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#include "platform.h"

#ifdef OF_APPLE_RUNTIME
# if defined(OF_X86_64)
#  include "apple-forwarding-x86_64.S"
# elif defined(OF_X86)
#  include "apple-forwarding-i386.S"
# elif defined(OF_ARM64)
#  include "apple-forwarding-arm64.S"
# elif defined(OF_ARM)
#  include "apple-forwarding-arm.S"
# elif defined(OF_POWERPC)
#  include "apple-forwarding-powerpc.S"
# endif
#else
# if defined(OF_ELF)
#  if defined(OF_X86_64)
#   include "forwarding-x86_64-elf.S"
#  elif defined(OF_X86)
#   include "forwarding-x86-elf.S"
#  elif defined(OF_ARM64)
#   include "forwarding-arm64-elf.S"
#  elif defined(OF_ARM)
#   include "forwarding-arm-elf.S"
#  elif defined(OF_POWERPC)
#   include "forwarding-powerpc-elf.S"
#  elif defined(OF_MIPS)
#   include "forwarding-mips-elf.S"
#  elif defined(OF_SPARC64)
#   include "forwarding-sparc64-elf.S"
#  elif defined(OF_SPARC)
#   include "forwarding-sparc-elf.S"
#  endif
# elif defined(OF_MACH_O)
#  if defined(OF_X86_64)
#   include "forwarding-x86_64-macho.S"
#  endif
# elif defined(OF_WINDOWS)
#  if defined(OF_X86_64)
#   include "forwarding-x86_64-win64.S"
#  elif defined(OF_X86)
#   include "forwarding-x86-win32.S"
#  endif
# endif
#endif

|


















|
|

|









|
|
















|
|


|
|





1
2
3
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 "platform.h"

#ifdef OF_APPLE_RUNTIME
# if defined(OF_AMD64)
#  include "apple-forwarding-amd64.S"
# elif defined(OF_X86)
#  include "apple-forwarding-x86.S"
# elif defined(OF_ARM64)
#  include "apple-forwarding-arm64.S"
# elif defined(OF_ARM)
#  include "apple-forwarding-arm.S"
# elif defined(OF_POWERPC)
#  include "apple-forwarding-powerpc.S"
# endif
#else
# if defined(OF_ELF)
#  if defined(OF_AMD64)
#   include "forwarding-amd64-elf.S"
#  elif defined(OF_X86)
#   include "forwarding-x86-elf.S"
#  elif defined(OF_ARM64)
#   include "forwarding-arm64-elf.S"
#  elif defined(OF_ARM)
#   include "forwarding-arm-elf.S"
#  elif defined(OF_POWERPC)
#   include "forwarding-powerpc-elf.S"
#  elif defined(OF_MIPS)
#   include "forwarding-mips-elf.S"
#  elif defined(OF_SPARC64)
#   include "forwarding-sparc64-elf.S"
#  elif defined(OF_SPARC)
#   include "forwarding-sparc-elf.S"
#  endif
# elif defined(OF_MACH_O)
#  if defined(OF_AMD64)
#   include "forwarding-amd64-macho.S"
#  endif
# elif defined(OF_WINDOWS)
#  if defined(OF_AMD64)
#   include "forwarding-amd64-win64.S"
#  elif defined(OF_X86)
#   include "forwarding-x86-win32.S"
#  endif
# endif
#endif

Modified src/libbases.m from [952ca43ba1] to [478b2709cc].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

18

19
20
21
22
23
24
25
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the 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 <proto/exec.h>


#import "OFInitializationFailedException.h"

#import "macros.h"

#ifdef OF_AMIGAOS4
extern struct Library *DOSBase;

|















>

>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/*
 * Copyright (c) 2008-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"

#define Class IntuitionClass
#include <proto/exec.h>
#undef Class

#import "OFInitializationFailedException.h"

#import "macros.h"

#ifdef OF_AMIGAOS4
extern struct Library *DOSBase;

Modified src/macros.h from [4ca2ebbb7b] to [f9c11c2712].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
97
98
99
100
101
102
103




104
105
106
107
108
109
110
111
112
113
114
115
116
117
# define OF_INLINE inline
# define OF_LIKELY(cond) (cond)
# define OF_UNLIKELY(cond) (cond)
# define OF_CONST_FUNC
# define OF_NO_RETURN_FUNC
# define OF_WEAK_REF(sym)
#endif





#if __STDC_VERSION__ >= 201112L
# define OF_ALIGNOF(type) _Alignof(type)
# define OF_ALIGNAS(type) _Alignas(type)
#else
# define OF_ALIGNOF(type) __alignof__(type)
# define OF_ALIGNAS(type) __attribute__((__aligned__(__alignof__(type))))
#endif

#if __STDC_VERSION__ >= 201112L && defined(OF_HAVE_MAX_ALIGN_T)
# define OF_BIGGEST_ALIGNMENT _Alignof(max_align_t)
#else
# ifdef __BIGGEST_ALIGNMENT__
#  define OF_BIGGEST_ALIGNMENT __BIGGEST_ALIGNMENT__







>
>
>
>






|







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
# define OF_INLINE inline
# define OF_LIKELY(cond) (cond)
# define OF_UNLIKELY(cond) (cond)
# define OF_CONST_FUNC
# define OF_NO_RETURN_FUNC
# define OF_WEAK_REF(sym)
#endif

#ifdef __GNUC__
# define OF_ALIGN(alignment) __attribute__((__aligned__(alignment)))
#endif

#if __STDC_VERSION__ >= 201112L
# define OF_ALIGNOF(type) _Alignof(type)
# define OF_ALIGNAS(type) _Alignas(type)
#else
# define OF_ALIGNOF(type) __alignof__(type)
# define OF_ALIGNAS(type) OF_ALIGN(OF_ALIGNOF(type))
#endif

#if __STDC_VERSION__ >= 201112L && defined(OF_HAVE_MAX_ALIGN_T)
# define OF_BIGGEST_ALIGNMENT _Alignof(max_align_t)
#else
# ifdef __BIGGEST_ALIGNMENT__
#  define OF_BIGGEST_ALIGNMENT __BIGGEST_ALIGNMENT__
287
288
289
290
291
292
293











294
295
296
297
298
299
300

#if __has_attribute(__objc_designated_initializer__)
# define OF_DESIGNATED_INITIALIZER \
    __attribute__((__objc_designated_initializer__))
#else
# define OF_DESIGNATED_INITIALIZER
#endif












#if __has_attribute(__objc_boxable__)
# define OF_BOXABLE __attribute__((__objc_boxable__))
#else
# define OF_BOXABLE
#endif








>
>
>
>
>
>
>
>
>
>
>







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

#if __has_attribute(__objc_designated_initializer__)
# define OF_DESIGNATED_INITIALIZER \
    __attribute__((__objc_designated_initializer__))
#else
# define OF_DESIGNATED_INITIALIZER
#endif

#if defined(__clang__) || OF_GCC_VERSION >= 405
# define OF_DEPRECATED(project, major, minor, msg)		\
    __attribute__((__deprecated__("Deprecated in " #project " "	\
    #major "." #minor ": " msg)))
#elif defined(__GNUC__)
# define OF_DEPRECATED(project, major, minor, msg) \
    __attribute__((__deprecated__))
#else
# define OF_DEPRECATED(project, major, minor, msg)
#endif

#if __has_attribute(__objc_boxable__)
# define OF_BOXABLE __attribute__((__objc_boxable__))
#else
# define OF_BOXABLE
#endif

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
#if __has_attribute(__objc_direct_members__) && defined(OF_APPLE_RUNTIME)
# define OF_DIRECT_MEMBERS __attribute__((__objc_direct_members__))
#else
# define OF_DIRECT_MEMBERS
#endif

#ifdef OF_APPLE_RUNTIME
# if defined(OF_X86_64) || defined(OF_X86) || defined(OF_ARM64) || \
    defined(OF_ARM) || defined(OF_POWERPC)
#  define OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR
#  define OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR_STRET
# endif
#else
# if defined(OF_ELF)
#  if defined(OF_X86_64) || defined(OF_X86) || \
    defined(OF_ARM64) || defined(OF_ARM) || defined(OF_POWERPC) || \
    defined(OF_MIPS) || defined(OF_SPARC64) || defined(OF_SPARC)
#   define OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR
#   if __OBJFW_RUNTIME_ABI__ >= 800
#    define OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR_STRET
#   endif
#  endif
# elif defined(OF_MACH_O)
#  if defined(OF_X86_64)
#   define OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR
#   if __OBJFW_RUNTIME_ABI__ >= 800
#    define OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR_STRET
#   endif
#  endif
# elif defined(OF_WINDOWS)
#  if defined(OF_X86_64) || defined(OF_X86)
#   define OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR
#   if __OBJFW_RUNTIME_ABI__ >= 800
#    define OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR_STRET
#   endif
#  endif
# endif
#endif

#define OFMaxRetainCount UINT_MAX

#ifdef OBJC_COMPILING_RUNTIME
# define OFEnsure(cond)							\
	do {								\
		if OF_UNLIKELY (!(cond))				\
			objc_error("ObjFWRT @ " __FILE__ ":"		\
			    OF_STRINGIFY(__LINE__),			\
			    "Failed to ensure condition:\n" #cond);	\
	} while(0)
#else








# define OFEnsure(cond)							\
	do {								\
		if OF_UNLIKELY (!(cond)) {				\
			fprintf(stderr, "Failed to ensure condition "	\
			    "in " __FILE__ ":%d:\n" #cond "\n",		\
			    __LINE__);					\
			abort();					\
		}							\
	} while (0)
#endif







#define OF_UNRECOGNIZED_SELECTOR OFMethodNotFound(self, _cmd);
#if __has_feature(objc_arc)
# define OF_INVALID_INIT_METHOD OFMethodNotFound(self, _cmd);
#else
# define OF_INVALID_INIT_METHOD				\
	@try {						\







|






|








|






|



















>
>
>
>
>
>
>
>



|
|
<




>
>
>
>
>
>







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
#if __has_attribute(__objc_direct_members__) && defined(OF_APPLE_RUNTIME)
# define OF_DIRECT_MEMBERS __attribute__((__objc_direct_members__))
#else
# define OF_DIRECT_MEMBERS
#endif

#ifdef OF_APPLE_RUNTIME
# if defined(OF_AMD64) || defined(OF_X86) || defined(OF_ARM64) || \
    defined(OF_ARM) || defined(OF_POWERPC)
#  define OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR
#  define OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR_STRET
# endif
#else
# if defined(OF_ELF)
#  if defined(OF_AMD64) || defined(OF_X86) || \
    defined(OF_ARM64) || defined(OF_ARM) || defined(OF_POWERPC) || \
    defined(OF_MIPS) || defined(OF_SPARC64) || defined(OF_SPARC)
#   define OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR
#   if __OBJFW_RUNTIME_ABI__ >= 800
#    define OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR_STRET
#   endif
#  endif
# elif defined(OF_MACH_O)
#  if defined(OF_AMD64)
#   define OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR
#   if __OBJFW_RUNTIME_ABI__ >= 800
#    define OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR_STRET
#   endif
#  endif
# elif defined(OF_WINDOWS)
#  if defined(OF_AMD64) || defined(OF_X86)
#   define OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR
#   if __OBJFW_RUNTIME_ABI__ >= 800
#    define OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR_STRET
#   endif
#  endif
# endif
#endif

#define OFMaxRetainCount UINT_MAX

#ifdef OBJC_COMPILING_RUNTIME
# define OFEnsure(cond)							\
	do {								\
		if OF_UNLIKELY (!(cond))				\
			objc_error("ObjFWRT @ " __FILE__ ":"		\
			    OF_STRINGIFY(__LINE__),			\
			    "Failed to ensure condition:\n" #cond);	\
	} while(0)
#else
@class OFConstantString;
# ifdef __cplusplus
extern "C" {
# endif
extern void OFLog(OFConstantString *_Nonnull, ...);
# ifdef __cplusplus
}
# endif
# define OFEnsure(cond)							\
	do {								\
		if OF_UNLIKELY (!(cond)) {				\
			OFLog(@"Failed to ensure condition in "		\
			    @__FILE__ ":%d: " @#cond, __LINE__);	\

			abort();					\
		}							\
	} while (0)
#endif

#ifndef NDEBUG
# define OFAssert(...) OFEnsure(__VA_ARGS__)
#else
# define OFAssert(...)
#endif

#define OF_UNRECOGNIZED_SELECTOR OFMethodNotFound(self, _cmd);
#if __has_feature(objc_arc)
# define OF_INVALID_INIT_METHOD OFMethodNotFound(self, _cmd);
#else
# define OF_INVALID_INIT_METHOD				\
	@try {						\
398
399
400
401
402
403
404
























405
406
407
408
409
410
411
# define OF_DEALLOC_UNSUPPORTED						\
	[self doesNotRecognizeSelector: _cmd];				\
									\
	abort();							\
									\
	[super dealloc];	/* Get rid of a stupid warning */
#endif

























#define OF_CONSTRUCTOR(prio)					\
	static void __attribute__((__constructor__(prio)))	\
	OF_PREPROCESSOR_CONCAT(constructor, __LINE__)(void)
#define OF_DESTRUCTOR(prio)					\
	static void __attribute__((__destructor__(prio)))	\
	OF_PREPROCESSOR_CONCAT(destructor, __LINE__)(void)







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
# define OF_DEALLOC_UNSUPPORTED						\
	[self doesNotRecognizeSelector: _cmd];				\
									\
	abort();							\
									\
	[super dealloc];	/* Get rid of a stupid warning */
#endif
#define OF_SINGLETON_METHODS			\
	- (instancetype)autorelease		\
	{					\
		return self;			\
	}					\
						\
	- (instancetype)retain			\
	{					\
		return self;			\
	}					\
						\
	- (void)release				\
	{					\
	}					\
						\
	- (unsigned int)retainCount		\
	{					\
		return OFMaxRetainCount;	\
	}					\
						\
	- (void)dealloc				\
	{					\
		OF_DEALLOC_UNSUPPORTED		\
	}

#define OF_CONSTRUCTOR(prio)					\
	static void __attribute__((__constructor__(prio)))	\
	OF_PREPROCESSOR_CONCAT(constructor, __LINE__)(void)
#define OF_DESTRUCTOR(prio)					\
	static void __attribute__((__destructor__(prio)))	\
	OF_PREPROCESSOR_CONCAT(destructor, __LINE__)(void)
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
}

static OF_INLINE uint16_t OF_CONST_FUNC
OFByteSwap16NonConst(uint16_t i)
{
#if defined(OF_HAVE_BUILTIN_BSWAP16)
	return __builtin_bswap16(i);
#elif (defined(OF_X86_64) || defined(OF_X86)) && defined(__GNUC__)
	__asm__ (
	    "xchgb	%h0, %b0"
	    : "=Q"(i)
	    : "0"(i)
	);
#elif defined(OF_POWERPC) && defined(__GNUC__)
	__asm__ (
	    "lhbrx	%0, 0, %1"
	    : "=r"(i)
	    : "r"(&i), "m"(i)

	);
#elif defined(OF_ARMV6) && defined(__GNUC__)
	__asm__ (
	    "rev16	%0, %0"
	    : "=r"(i)
	    : "0"(i)
	);
#else
	i = (i & UINT16_C(0xFF00)) >> 8 |
	    (i & UINT16_C(0x00FF)) << 8;
#endif
	return i;
}

static OF_INLINE uint32_t OF_CONST_FUNC
OFByteSwap32NonConst(uint32_t i)
{
#if defined(OF_HAVE_BUILTIN_BSWAP32)
	return __builtin_bswap32(i);
#elif (defined(OF_X86_64) || defined(OF_X86)) && defined(__GNUC__)
	__asm__ (
	    "bswap	%0"
	    : "=q"(i)
	    : "0"(i)
	);
#elif defined(OF_POWERPC) && defined(__GNUC__)
	__asm__ (
	    "lwbrx	%0, 0, %1"
	    : "=r"(i)
	    : "r"(&i), "m"(i)

	);
#elif defined(OF_ARMV6) && defined(__GNUC__)
	__asm__ (
	    "rev	%0, %0"
	    : "=r"(i)
	    : "0"(i)
	);
#else
	i = (i & UINT32_C(0xFF000000)) >> 24 |
	    (i & UINT32_C(0x00FF0000)) >>  8 |
	    (i & UINT32_C(0x0000FF00)) <<  8 |
	    (i & UINT32_C(0x000000FF)) << 24;
#endif
	return i;
}

static OF_INLINE uint64_t OF_CONST_FUNC
OFByteSwap64NonConst(uint64_t i)
{
#if defined(OF_HAVE_BUILTIN_BSWAP64)
	return __builtin_bswap64(i);
#elif defined(OF_X86_64) && defined(__GNUC__)
	__asm__ (
	    "bswap	%0"
	    : "=r"(i)
	    : "0"(i)
	);
#elif defined(OF_X86) && defined(__GNUC__)
	__asm__ (
	    "bswap	%%eax\n\t"
	    "bswap	%%edx\n\t"
	    "xchgl	%%eax, %%edx"
	    : "=A"(i)
	    : "0"(i)
	);
#else
	i = (uint64_t)OFByteSwap32NonConst(
	    (uint32_t)(i & UINT32_C(0xFFFFFFFF))) << 32 |
	    OFByteSwap32NonConst((uint32_t)(i >> 32));
#endif
	return i;







|

|
|
|




|
|
>




|
|













|


|
|




|
|
>




|
|















|


|
|



|
|
|
|
|







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
}

static OF_INLINE uint16_t OF_CONST_FUNC
OFByteSwap16NonConst(uint16_t i)
{
#if defined(OF_HAVE_BUILTIN_BSWAP16)
	return __builtin_bswap16(i);
#elif (defined(OF_AMD64) || defined(OF_X86)) && defined(__GNUC__)
	__asm__ (
	    "xchg{b}	{ %h0, %b0 | %b0, %h0 }"
	    : "=Q" (i)
	    : "0" (i)
	);
#elif defined(OF_POWERPC) && defined(__GNUC__)
	__asm__ (
	    "lhbrx	%0, 0, %1"
	    : "=r" (i)
	    : "r" (&i),
	      "m" (i)
	);
#elif defined(OF_ARMV6) && defined(__GNUC__)
	__asm__ (
	    "rev16	%0, %0"
	    : "=r" (i)
	    : "0" (i)
	);
#else
	i = (i & UINT16_C(0xFF00)) >> 8 |
	    (i & UINT16_C(0x00FF)) << 8;
#endif
	return i;
}

static OF_INLINE uint32_t OF_CONST_FUNC
OFByteSwap32NonConst(uint32_t i)
{
#if defined(OF_HAVE_BUILTIN_BSWAP32)
	return __builtin_bswap32(i);
#elif (defined(OF_AMD64) || defined(OF_X86)) && defined(__GNUC__)
	__asm__ (
	    "bswap	%0"
	    : "=q" (i)
	    : "0" (i)
	);
#elif defined(OF_POWERPC) && defined(__GNUC__)
	__asm__ (
	    "lwbrx	%0, 0, %1"
	    : "=r" (i)
	    : "r" (&i),
	      "m" (i)
	);
#elif defined(OF_ARMV6) && defined(__GNUC__)
	__asm__ (
	    "rev	%0, %0"
	    : "=r" (i)
	    : "0" (i)
	);
#else
	i = (i & UINT32_C(0xFF000000)) >> 24 |
	    (i & UINT32_C(0x00FF0000)) >>  8 |
	    (i & UINT32_C(0x0000FF00)) <<  8 |
	    (i & UINT32_C(0x000000FF)) << 24;
#endif
	return i;
}

static OF_INLINE uint64_t OF_CONST_FUNC
OFByteSwap64NonConst(uint64_t i)
{
#if defined(OF_HAVE_BUILTIN_BSWAP64)
	return __builtin_bswap64(i);
#elif defined(OF_AMD64) && defined(__GNUC__)
	__asm__ (
	    "bswap	%0"
	    : "=r" (i)
	    : "0" (i)
	);
#elif defined(OF_X86) && defined(__GNUC__)
	__asm__ (
	    "bswap	{%%}eax\n\t"
	    "bswap	{%%}edx\n\t"
	    "xchg{l}	{ %%eax, %%edx | edx, eax }"
	    : "=A" (i)
	    : "0" (i)
	);
#else
	i = (uint64_t)OFByteSwap32NonConst(
	    (uint32_t)(i & UINT32_C(0xFFFFFFFF))) << 32 |
	    OFByteSwap32NonConst((uint32_t)(i >> 32));
#endif
	return i;

Modified src/objfw-defs.h.in from [281bf4782f] to [5a8629e6a6].

1
2

3
4
5
6
7
8
9
#undef OF_APPLE_RUNTIME
#undef OF_BIG_ENDIAN

#undef OF_FLOAT_BIG_ENDIAN
#undef OF_HAVE_AFUNIX_H
#undef OF_HAVE_APPLETALK
#undef OF_HAVE_ATOMIC_BUILTINS
#undef OF_HAVE_ATOMIC_OPS
#undef OF_HAVE_BUILTIN_BSWAP16
#undef OF_HAVE_BUILTIN_BSWAP32


>







1
2
3
4
5
6
7
8
9
10
#undef OF_APPLE_RUNTIME
#undef OF_BIG_ENDIAN
#undef OF_CLASSIC_MACOS
#undef OF_FLOAT_BIG_ENDIAN
#undef OF_HAVE_AFUNIX_H
#undef OF_HAVE_APPLETALK
#undef OF_HAVE_ATOMIC_BUILTINS
#undef OF_HAVE_ATOMIC_OPS
#undef OF_HAVE_BUILTIN_BSWAP16
#undef OF_HAVE_BUILTIN_BSWAP32
27
28
29
30
31
32
33

34
35
36
37
38
39
40
#undef OF_HAVE_PIPE
#undef OF_HAVE_PLEDGE
#undef OF_HAVE_PLUGINS
#undef OF_HAVE_PTHREADS
#undef OF_HAVE_PTHREAD_SPINLOCKS
#undef OF_HAVE_RECURSIVE_PTHREAD_MUTEXES
#undef OF_HAVE_SCHED_YIELD

#undef OF_HAVE_SOCKETS
#undef OF_HAVE_STDNORETURN
#undef OF_HAVE_SUBPROCESSES
#undef OF_HAVE_SYMLINK
#undef OF_HAVE_SYNC_BUILTINS
#undef OF_HAVE_SYS_SOCKET_H
#undef OF_HAVE_SYS_TYPES_H







>







28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#undef OF_HAVE_PIPE
#undef OF_HAVE_PLEDGE
#undef OF_HAVE_PLUGINS
#undef OF_HAVE_PTHREADS
#undef OF_HAVE_PTHREAD_SPINLOCKS
#undef OF_HAVE_RECURSIVE_PTHREAD_MUTEXES
#undef OF_HAVE_SCHED_YIELD
#undef OF_HAVE_SOCKADDR_STORAGE
#undef OF_HAVE_SOCKETS
#undef OF_HAVE_STDNORETURN
#undef OF_HAVE_SUBPROCESSES
#undef OF_HAVE_SYMLINK
#undef OF_HAVE_SYNC_BUILTINS
#undef OF_HAVE_SYS_SOCKET_H
#undef OF_HAVE_SYS_TYPES_H

Modified src/platform.h from [927be68827] to [9ff30a4101].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#  define OF_FLOAT_BIG_ENDIAN
# elif !__LITTLE_ENDIAN__
#  error OF_UNIVERSAL defined, but neither __BIG_ENDIAN__ nor __LITTLE_ENDIAN__!
# endif
#endif

#if defined(__x86_64__) || defined(__amd64__)
# define OF_X86_64
#elif defined(__i386__)
# define OF_X86
#elif defined(__powerpc64__) || defined(__ppc64__) || defined(__PPC64__)
# define OF_POWERPC64
#elif defined(__powerpc__) || defined(__ppc__) || defined(__PPC__)
# define OF_POWERPC
#elif defined(__arm64__) || defined(__aarch64__) || defined(__ARM64_ARCH_8__)







|







22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#  define OF_FLOAT_BIG_ENDIAN
# elif !__LITTLE_ENDIAN__
#  error OF_UNIVERSAL defined, but neither __BIG_ENDIAN__ nor __LITTLE_ENDIAN__!
# endif
#endif

#if defined(__x86_64__) || defined(__amd64__)
# define OF_AMD64
#elif defined(__i386__)
# define OF_X86
#elif defined(__powerpc64__) || defined(__ppc64__) || defined(__PPC64__)
# define OF_POWERPC64
#elif defined(__powerpc__) || defined(__ppc__) || defined(__PPC__)
# define OF_POWERPC
#elif defined(__arm64__) || defined(__aarch64__) || defined(__ARM64_ARCH_8__)
147
148
149
150
151
152
153






154
155
156
157
158
159
160
161
162
163
164
#elif defined(__DJGPP__)
# define OF_DJGPP
# define OF_MSDOS
#elif defined(__riscos__)
# define OF_ACORN_RISC_OS
#elif defined(__MINT__)
# define OF_MINT






#endif

#if defined(__ELF__)
# define OF_ELF
#elif defined(__MACH__)
# define OF_MACH_O
#endif

#if defined(__PIC__) || defined(__pic__)
# define OF_PIC
#endif







>
>
>
>
>
>











147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
#elif defined(__DJGPP__)
# define OF_DJGPP
# define OF_MSDOS
#elif defined(__riscos__)
# define OF_ACORN_RISC_OS
#elif defined(__MINT__)
# define OF_MINT
#elif defined(__gnu_hurd__)
# define OF_HURD
#endif

#ifdef __GLIBC__
# define OF_GLIBC
#endif

#if defined(__ELF__)
# define OF_ELF
#elif defined(__MACH__)
# define OF_MACH_O
#endif

#if defined(__PIC__) || defined(__pic__)
# define OF_PIC
#endif

Modified src/platform/AmigaOS/OFPlainCondition.m from [b17297ed32] to [c6e8a3e13b].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

22
23
24
25
26

27
28
29
30
31
32
33
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#include <errno.h>

#import "OFPlainCondition.h"


#include <proto/exec.h>
#include <devices/timer.h>
#ifndef OF_AMIGAOS4
# include <clib/alib_protos.h>
#endif


int
OFPlainConditionNew(OFPlainCondition *condition)
{
	condition->waitingTasks = NULL;

	return 0;

|



















>





>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
/*
 * Copyright (c) 2008-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 <errno.h>

#import "OFPlainCondition.h"

#define Class IntuitionClass
#include <proto/exec.h>
#include <devices/timer.h>
#ifndef OF_AMIGAOS4
# include <clib/alib_protos.h>
#endif
#undef Class

int
OFPlainConditionNew(OFPlainCondition *condition)
{
	condition->waitingTasks = NULL;

	return 0;

Modified src/platform/AmigaOS/OFPlainMutex.m from [635aa59c59] to [d999310993].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

22

23
24
25
26
27
28
29
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#include <errno.h>

#import "OFPlainMutex.h"


#include <proto/exec.h>


int
OFPlainMutexNew(OFPlainMutex *mutex)
{
	InitSemaphore(mutex);

	return 0;

|



















>

>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/*
 * Copyright (c) 2008-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 <errno.h>

#import "OFPlainMutex.h"

#define Class IntuitionClass
#include <proto/exec.h>
#undef Class

int
OFPlainMutexNew(OFPlainMutex *mutex)
{
	InitSemaphore(mutex);

	return 0;

Modified src/platform/AmigaOS/OFPlainThread.m from [70ea6c25e9] to [de8dd371a0].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

23
24

25
26
27

28
29
30
31
32
33
34
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the 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 <assert.h>
#include <errno.h>

#import "OFPlainThread.h"
#import "OFData.h"

#import "OFTLSKey.h"


#include <dos/dostags.h>
#include <proto/dos.h>
#include <proto/exec.h>


#ifndef OF_MORPHOS
extern void OFTLSKeyThreadExited(void);
#endif
static OFTLSKey threadKey;

OF_CONSTRUCTOR()

|















<




>


>



>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
/*
 * Copyright (c) 2008-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 <errno.h>

#import "OFPlainThread.h"
#import "OFData.h"
#import "OFString.h"
#import "OFTLSKey.h"

#define Class IntuitionClass
#include <dos/dostags.h>
#include <proto/dos.h>
#include <proto/exec.h>
#undef Class

#ifndef OF_MORPHOS
extern void OFTLSKeyThreadExited(void);
#endif
static OFTLSKey threadKey;

OF_CONSTRUCTOR()
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
	} @finally {
		ReleaseSemaphore(&thread->semaphore);
	}

	Wait(1ul << thread->joinSigBit);
	FreeSignal(thread->joinSigBit);

	assert(thread->done);
	free(thread);

	return 0;
}

int
OFPlainThreadDetach(OFPlainThread thread)







|







191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
	} @finally {
		ReleaseSemaphore(&thread->semaphore);
	}

	Wait(1ul << thread->joinSigBit);
	FreeSignal(thread->joinSigBit);

	OFAssert(thread->done);
	free(thread);

	return 0;
}

int
OFPlainThreadDetach(OFPlainThread thread)

Modified src/platform/AmigaOS/OFString+PathAdditions.m from [60752aa5d1] to [9727b31d5c].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#import "OFString+PathAdditions.h"
#import "OFArray.h"
#import "OFFileURIHandler.h"

#import "OFOutOfRangeException.h"

int _OFString_PathAdditions_reference;

@implementation OFString (PathAdditions)
+ (OFString *)pathWithComponents: (OFArray *)components

|

















|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/*
 * Copyright (c) 2008-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+PathAdditions.h"
#import "OFArray.h"
#import "OFFileIRIHandler.h"

#import "OFOutOfRangeException.h"

int _OFString_PathAdditions_reference;

@implementation OFString (PathAdditions)
+ (OFString *)pathWithComponents: (OFArray *)components
251
252
253
254
255
256
257



258
259
260
261
262
263
264
	[ret retain];
	objc_autoreleasePoolPop(pool);
	return [ret autorelease];
}

- (OFString *)stringByAppendingPathComponent: (OFString *)component
{



	if ([self hasSuffix: @"/"] || [self hasSuffix: @":"])
		return [self stringByAppendingString: component];
	else {
		OFMutableString *ret = [[self mutableCopy] autorelease];

		[ret appendString: @"/"];
		[ret appendString: component];







>
>
>







251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
	[ret retain];
	objc_autoreleasePoolPop(pool);
	return [ret autorelease];
}

- (OFString *)stringByAppendingPathComponent: (OFString *)component
{
	if (self.length == 0)
		return component;

	if ([self hasSuffix: @"/"] || [self hasSuffix: @":"])
		return [self stringByAppendingString: component];
	else {
		OFMutableString *ret = [[self mutableCopy] autorelease];

		[ret appendString: @"/"];
		[ret appendString: component];
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
	} else
		return [self stringByAppendingFormat: @".%@", extension];
}

- (bool)of_isDirectoryPath
{
	return ([self hasSuffix: @"/"] || [self hasSuffix: @":"] ||
	    [OFFileURIHandler of_directoryExistsAtPath: self]);
}

- (OFString *)of_pathToURIPathWithPercentEncodedHost:
    (OFString **)percentEncodedHost
{
	OFArray OF_GENERIC(OFString *) *components = self.pathComponents;
	OFMutableString *ret = [OFMutableString string];

	for (OFString *component in components) {
		if (component.length == 0)







|


|







292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
	} else
		return [self stringByAppendingFormat: @".%@", extension];
}

- (bool)of_isDirectoryPath
{
	return ([self hasSuffix: @"/"] || [self hasSuffix: @":"] ||
	    [OFFileIRIHandler of_directoryExistsAtPath: self]);
}

- (OFString *)of_pathToIRIPathWithPercentEncodedHost:
    (OFString **)percentEncodedHost
{
	OFArray OF_GENERIC(OFString *) *components = self.pathComponents;
	OFMutableString *ret = [OFMutableString string];

	for (OFString *component in components) {
		if (component.length == 0)
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
	}

	[ret makeImmutable];

	return ret;
}

- (OFString *)of_URIPathToPathWithPercentEncodedHost:
    (OFString *)percentEncodedHost
{
	OFString *path = self;

	if (path.length > 1 && [path hasSuffix: @"/"])
		path = [path substringToIndex: path.length - 1];








|







318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
	}

	[ret makeImmutable];

	return ret;
}

- (OFString *)of_IRIPathToPathWithPercentEncodedHost:
    (OFString *)percentEncodedHost
{
	OFString *path = self;

	if (path.length > 1 && [path hasSuffix: @"/"])
		path = [path substringToIndex: path.length - 1];

349
350
351
352
353
354
355
356
357
358
359
360
		if ([component isEqual: @".."])
			[components replaceObjectAtIndex: i withObject: @"/"];
	}

	return [OFString pathWithComponents: components];
}

- (OFString *)of_pathComponentToURIPathComponent
{
	return self;
}
@end







|




352
353
354
355
356
357
358
359
360
361
362
363
		if ([component isEqual: @".."])
			[components replaceObjectAtIndex: i withObject: @"/"];
	}

	return [OFString pathWithComponents: components];
}

- (OFString *)of_pathComponentToIRIPathComponent
{
	return self;
}
@end

Modified src/platform/AmigaOS/OFTLSKey.m from [7115be10da] to [fed5ca925d].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

20
21

22
23
24
25
26
27
28
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#import "OFTLSKey.h"


#include <exec/semaphores.h>
#include <proto/exec.h>


/*
 * As we use this file in both the runtime and ObjFW, and since AmigaOS always
 * has the runtime, use the hashtable from the runtime.
 */
#import "runtime/private.h"


|

















>


>







1
2
3
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 "OFTLSKey.h"

#define Class IntuitionClass
#include <exec/semaphores.h>
#include <proto/exec.h>
#undef Class

/*
 * As we use this file in both the runtime and ObjFW, and since AmigaOS always
 * has the runtime, use the hashtable from the runtime.
 */
#import "runtime/private.h"

Modified src/platform/GCC4.7/OFAtomic.h from [3a2198950d] to [f232a592aa].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/platform/GCC4/OFAtomic.h from [46ae36c82b] to [acade4fce3].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/platform/MorphOS/OFTLSKey.m from [f46c8d88c6] to [0fcdfef1b3].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/platform/POSIX/OFPlainCondition.m from [d0abcf1839] to [13ac107ee1].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/platform/POSIX/OFPlainMutex.m from [bcf658e6be] to [4f30a4c59a].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/platform/POSIX/OFPlainThread.m from [7bbb313eb6] to [e57b745be2].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/platform/POSIX/OFString+PathAdditions.m from [d1f51523cf] to [ee99a206d6].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#import "OFString+PathAdditions.h"
#import "OFArray.h"
#import "OFFileURIHandler.h"

#import "OFOutOfRangeException.h"

int _OFString_PathAdditions_reference;

@implementation OFString (PathAdditions)
+ (OFString *)pathWithComponents: (OFArray *)components

|

















|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/*
 * Copyright (c) 2008-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+PathAdditions.h"
#import "OFArray.h"
#import "OFFileIRIHandler.h"

#import "OFOutOfRangeException.h"

int _OFString_PathAdditions_reference;

@implementation OFString (PathAdditions)
+ (OFString *)pathWithComponents: (OFArray *)components
296
297
298
299
300
301
302



303
304
305
306
307
308
309
	objc_autoreleasePoolPop(pool);

	return [ret autorelease];
}

- (OFString *)stringByAppendingPathComponent: (OFString *)component
{



	if ([self hasSuffix: @"/"])
		return [self stringByAppendingString: component];
	else {
		OFMutableString *ret = [[self mutableCopy] autorelease];

		[ret appendString: @"/"];
		[ret appendString: component];







>
>
>







296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
	objc_autoreleasePoolPop(pool);

	return [ret autorelease];
}

- (OFString *)stringByAppendingPathComponent: (OFString *)component
{
	if (self.length == 0)
		return component;

	if ([self hasSuffix: @"/"])
		return [self stringByAppendingString: component];
	else {
		OFMutableString *ret = [[self mutableCopy] autorelease];

		[ret appendString: @"/"];
		[ret appendString: component];
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
	} else
		return [self stringByAppendingFormat: @".%@", extension];
}

- (bool)of_isDirectoryPath
{
	return ([self hasSuffix: @"/"] ||
	    [OFFileURIHandler of_directoryExistsAtPath: self]);
}

- (OFString *)of_pathToURIPathWithPercentEncodedHost:
    (OFString **)percentEncodedHost
{
	return self;
}

- (OFString *)of_URIPathToPathWithPercentEncodedHost:
    (OFString *)percentEncodedHost
{
	OFString *path = self;

	if (path.length > 1 && [path hasSuffix: @"/"])
		path = [path substringToIndex: path.length - 1];

	return path;
}

- (OFString *)of_pathComponentToURIPathComponent
{
	return self;
}
@end







|


|





|










|




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
	} else
		return [self stringByAppendingFormat: @".%@", extension];
}

- (bool)of_isDirectoryPath
{
	return ([self hasSuffix: @"/"] ||
	    [OFFileIRIHandler of_directoryExistsAtPath: self]);
}

- (OFString *)of_pathToIRIPathWithPercentEncodedHost:
    (OFString **)percentEncodedHost
{
	return self;
}

- (OFString *)of_IRIPathToPathWithPercentEncodedHost:
    (OFString *)percentEncodedHost
{
	OFString *path = self;

	if (path.length > 1 && [path hasSuffix: @"/"])
		path = [path substringToIndex: path.length - 1];

	return path;
}

- (OFString *)of_pathComponentToIRIPathComponent
{
	return self;
}
@end

Modified src/platform/POSIX/OFSubprocess.m from [9ff417c581] to [6b69aef5c9].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51

#import "OFInitializationFailedException.h"
#import "OFNotOpenException.h"
#import "OFOutOfRangeException.h"
#import "OFReadFailedException.h"
#import "OFWriteFailedException.h"

#ifndef HAVE_POSIX_SPAWNP
extern char **environ;
#endif

@interface OFSubprocess ()
- (void)of_getArgv: (char ***)argv
    forProgramName: (OFString *)programName
      andArguments: (OFArray *)arguments;







|







37
38
39
40
41
42
43
44
45
46
47
48
49
50
51

#import "OFInitializationFailedException.h"
#import "OFNotOpenException.h"
#import "OFOutOfRangeException.h"
#import "OFReadFailedException.h"
#import "OFWriteFailedException.h"

#if !defined(HAVE_POSIX_SPAWNP) || !defined(HAVE_SPAWN_H)
extern char **environ;
#endif

@interface OFSubprocess ()
- (void)of_getArgv: (char ***)argv
    forProgramName: (OFString *)programName
      andArguments: (OFArray *)arguments;
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
		path = [program cStringWithEncoding: [OFLocale encoding]];
		[self of_getArgv: &argv
		  forProgramName: programName
		    andArguments: arguments];

		@try {
			env = [self of_environmentForDictionary: environment];
#ifdef HAVE_POSIX_SPAWNP
			posix_spawn_file_actions_t actions;
			posix_spawnattr_t attr;

			if (posix_spawn_file_actions_init(&actions) != 0)
				@throw [OFInitializationFailedException
				    exceptionWithClass: self.class];








|







139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
		path = [program cStringWithEncoding: [OFLocale encoding]];
		[self of_getArgv: &argv
		  forProgramName: programName
		    andArguments: arguments];

		@try {
			env = [self of_environmentForDictionary: environment];
#if defined(HAVE_POSIX_SPAWNP) && defined(HAVE_SPAWN_H)
			posix_spawn_file_actions_t actions;
			posix_spawnattr_t attr;

			if (posix_spawn_file_actions_init(&actions) != 0)
				@throw [OFInitializationFailedException
				    exceptionWithClass: self.class];

Added src/platform/POSIX/OFSystemInfo+NetworkInterfaces.m version [39156521a7].













































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
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
/*
 * 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"

#ifdef HAVE_SYS_IOCTL_H
# include <sys/ioctl.h>
#endif
#ifdef OF_HAVE_SYS_SOCKET_H
# include <sys/socket.h>
#endif
#ifdef HAVE_SYS_SOCKIO_H
# include <sys/sockio.h>
#endif
#ifdef HAVE_NET_IF_H
# include <net/if.h>
#endif
#ifdef HAVE_NET_IF_ARP_H
# include <net/if_arp.h>
#endif
#ifdef HAVE_NET_IF_DL_H
# include <net/if_dl.h>
#endif
#ifdef HAVE_NET_IF_TYPES_H
# include <net/if_types.h>
#endif

#import "OFSystemInfo.h"
#import "OFSystemInfo+NetworkInterfaces.h"
#import "OFArray.h"
#import "OFData.h"
#import "OFDictionary.h"
#ifdef OF_HAVE_FILES
 #import "OFFile.h"
#endif
#import "OFLocale.h"
#import "OFNumber.h"
#import "OFSocket.h"
#import "OFSocket+Private.h"
#import "OFString.h"

#import "OFInvalidFormatException.h"
#import "OFOpenItemFailedException.h"

@implementation OFSystemInfo (NetworkInterfaces)
static bool
queryNetworkInterfaceIndices(OFMutableDictionary *ret)
{
#ifdef HAVE_IF_NAMEINDEX
	OFStringEncoding encoding = [OFLocale encoding];
	struct if_nameindex *nameindex = if_nameindex();

	if (nameindex == NULL)
		return false;

	@try {
		for (size_t i = 0; nameindex[i].if_index != 0; i++) {
			OFString *name = [OFString
			    stringWithCString: nameindex[i].if_name
				     encoding: encoding];
			OFNumber *idx = [OFNumber
			    numberWithUnsignedInt: nameindex[i].if_index];
			OFMutableDictionary *interface =
			    [ret objectForKey: name];

			if (interface == nil) {
				interface = [OFMutableDictionary dictionary];
				[ret setObject: interface forKey: name];
			}

			[interface setObject: idx
				      forKey: OFNetworkInterfaceIndex];
		}
	} @finally {
		if_freenameindex(nameindex);
	}

	return true;
#else
	return false;
#endif
}

#if defined(HAVE_IOCTL) && defined(HAVE_NET_IF_H)
static bool
queryNetworkInterfaceAddresses(OFMutableDictionary *ret,
    OFNetworkInterfaceKey key, OFSocketAddressFamily addressFamily, int family,
    size_t sockaddrSize)
{
	OFStringEncoding encoding = [OFLocale encoding];
	int sock = socket(family, SOCK_DGRAM, 0);
	OFMutableDictionary *interface;
	OFEnumerator *enumerator;

	if (sock < 0)
		return false;

# if defined(HAVE_STRUCT_LIFCONF) && defined(SIOCGLIFCONF)
	struct lifconf lifc;
	struct lifreq *lifrs;

	if ((lifrs = malloc(128 * sizeof(struct lifreq))) == NULL) {
		closesocket(sock);
		return false;
	}

	@try {
		char *buffer;

		memset(&lifc, 0, sizeof(lifc));
		lifc.lifc_buf = (void *)lifrs;
		lifc.lifc_len = 128 * sizeof(struct lifreq);
		if (ioctl(sock, SIOCGLIFCONF, &lifc) < 0)
			return false;

		for (buffer = lifc.lifc_buf;
		    buffer < (char *)lifc.lifc_buf + lifc.lifc_len;
		    buffer += sizeof(struct lifreq)) {
			struct lifreq *current =
			    (struct lifreq *)(void *)buffer;
			OFString *name;
			OFMutableData *addresses;
			OFSocketAddress address;

			if (current->lifr_addr.ss_family != family)
				continue;

			name = [OFString stringWithCString: current->lifr_name
						  encoding: encoding];
			if ((interface = [ret objectForKey: name]) == nil) {
				interface = [OFMutableDictionary dictionary];
				[ret setObject: interface forKey: name];
			}

			addresses = [interface objectForKey: key];
			if (addresses == nil) {
				addresses = [OFMutableData
				    dataWithItemSize: sizeof(OFSocketAddress)];
				[interface setObject: addresses forKey: key];
			}

			memset(&address, 0, sizeof(address));
			address.family = addressFamily;
			memcpy(&address.sockaddr.in, &current->lifr_addr,
			    sockaddrSize);

#  if defined(OF_HAVE_IPV6) && defined(HAVE_IF_NAMETOINDEX)
			if (address.sockaddr.in6.sin6_family == AF_INET6 &&
			    address.sockaddr.in6.sin6_addr.s6_addr[0] == 0xFE &&
			    (address.sockaddr.in6.sin6_addr.s6_addr[1] & 0xC0)
			    == 0x80)
				address.sockaddr.in6.sin6_scope_id =
				    if_nametoindex(
				    [name cStringWithEncoding: encoding]);
#  endif

			[addresses addItem: &address];
		}
	} @finally {
		free(lifrs);
		closesocket(sock);
	}
# else
	struct ifconf ifc;
	struct ifreq *ifrs;

	if (sock < 0)
		return false;

	if ((ifrs = malloc(128 * sizeof(struct ifreq))) == NULL) {
		closesocket(sock);
		return false;
	}

	@try {
		char *buffer;

		memset(&ifc, 0, sizeof(ifc));
		ifc.ifc_buf = (void *)ifrs;
		ifc.ifc_len = 128 * sizeof(struct ifreq);
		if (ioctl(sock, SIOCGIFCONF, &ifc) < 0)
			return false;

		buffer = ifc.ifc_buf;
		while (buffer < (char *)ifc.ifc_buf + ifc.ifc_len) {
			struct ifreq *current = (struct ifreq *)(void *)buffer;
			OFString *name;
			OFMutableData *addresses;
			OFSocketAddress address;

			if (current->ifr_addr.sa_family != family)
				goto next;

			name = [OFString stringWithCString: current->ifr_name
						  encoding: encoding];
			if ((interface = [ret objectForKey: name]) == nil) {
				interface = [OFMutableDictionary dictionary];
				[ret setObject: interface forKey: name];
			}

			addresses = [interface objectForKey: key];
			if (addresses == nil) {
				addresses = [OFMutableData
				    dataWithItemSize: sizeof(OFSocketAddress)];
				[interface setObject: addresses forKey: key];
			}

			memset(&address, 0, sizeof(address));
			address.family = addressFamily;
			memcpy(&address.sockaddr.in, &current->ifr_addr,
			    sockaddrSize);

#  if defined(OF_HAVE_IPV6) && defined(HAVE_IF_NAMETOINDEX)
			if (address.sockaddr.in6.sin6_family == AF_INET6 &&
			    address.sockaddr.in6.sin6_addr.s6_addr[0] == 0xFE &&
			    (address.sockaddr.in6.sin6_addr.s6_addr[1] & 0xC0)
			    == 0x80) {
#   if defined(__KAME__)
#    define addr6 address.sockaddr.in6.sin6_addr.s6_addr
				address.sockaddr.in6.sin6_scope_id =
				    (addr6[2] << 8) | addr6[3];
				addr6[2] = addr6[3] = 0;
#    undef addr6
#   elif defined(HAVE_IF_NAMETOINDEX)
				address.sockaddr.in6.sin6_scope_id =
				    if_nametoindex(
				    [name cStringWithEncoding: encoding]);
#   endif
			}
#  endif

			[addresses addItem: &address];

next:
#  ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
			if (current->ifr_addr.sa_len > sizeof(struct sockaddr))
				buffer += sizeof(struct ifreq) -
				    sizeof(struct sockaddr) +
				    current->ifr_addr.sa_len;
			else
#  endif
				buffer += sizeof(struct ifreq);
		}
	} @finally {
		free(ifrs);
		closesocket(sock);
	}
# endif

	enumerator = [ret objectEnumerator];
	while ((interface = [enumerator nextObject]) != nil)
		[[interface objectForKey: key] makeImmutable];

	return true;
}
#endif

static bool
queryNetworkInterfaceIPv4Addresses(OFMutableDictionary *ret)
{
#if defined(HAVE_IOCTL) && defined(HAVE_NET_IF_H)
	return queryNetworkInterfaceAddresses(ret,
	    OFNetworkInterfaceIPv4Addresses, OFSocketAddressFamilyIPv4,
	    AF_INET, sizeof(struct sockaddr_in));
#else
	return false;
#endif
}

#ifdef OF_HAVE_IPV6
static bool
queryNetworkInterfaceIPv6Addresses(OFMutableDictionary *ret)
{
# if defined(OF_LINUX) && defined(OF_HAVE_FILES)
#  ifdef HAVE_IF_NAMETOINDEX
	OFStringEncoding encoding = [OFLocale encoding];
#  endif
	OFFile *file;
	OFString *line;
	OFMutableDictionary *interface;
	OFEnumerator *enumerator;

	@try {
		file = [OFFile fileWithPath: @"/proc/net/if_inet6" mode: @"r"];
	} @catch (OFOpenItemFailedException *e) {
		return false;
	}

	while ((line = [file readLine]) != nil) {
		OFArray *components = [line
		    componentsSeparatedByString: @" "
					options: OFStringSkipEmptyComponents];
		OFString *addressString, *name;
		OFSocketAddress address;
		OFMutableData *addresses;

		if (components.count < 6)
			continue;

		addressString = [components objectAtIndex: 0];
		name = [components objectAtIndex: 5];

		if (addressString.length != 32)
			continue;

		if ((interface = [ret objectForKey: name]) == nil) {
			interface = [OFMutableDictionary dictionary];
			[ret setObject: interface forKey: name];
		}

		memset(&address, 0, sizeof(address));
		address.family = OFSocketAddressFamilyIPv6;
		address.sockaddr.in6.sin6_family = AF_INET6;

		for (size_t i = 0; i < 32; i += 2) {
			unsigned long long byte;

			@try {
				byte = [[addressString
				    substringWithRange: OFMakeRange(i, 2)]
				    unsignedLongLongValueWithBase: 16];
			} @catch (OFInvalidFormatException *e) {
				goto next_line;
			}

			if (byte > 0xFF)
				goto next_line;

			address.sockaddr.in6.sin6_addr.s6_addr[i / 2] =
			    (unsigned char)byte;
		}

#  ifdef HAVE_IF_NAMETOINDEX
		if (address.sockaddr.in6.sin6_addr.s6_addr[0] == 0xFE &&
		    (address.sockaddr.in6.sin6_addr.s6_addr[1] & 0xC0) == 0x80)
			address.sockaddr.in6.sin6_scope_id = if_nametoindex(
			    [name cStringWithEncoding: encoding]);
#  endif

		if ((addresses = [interface
		    objectForKey: OFNetworkInterfaceIPv6Addresses]) == nil) {
			addresses = [OFMutableData
			    dataWithItemSize: sizeof(OFSocketAddress)];
			[interface setObject: addresses
				      forKey: OFNetworkInterfaceIPv6Addresses];
		}

		[addresses addItem: &address];

next_line:
		continue;
	}

	enumerator = [ret objectEnumerator];
	while ((interface = [enumerator nextObject]) != nil)
		[[interface objectForKey: OFNetworkInterfaceIPv6Addresses]
		    makeImmutable];

	return false;
# elif defined(HAVE_IOCTL) && defined(HAVE_NET_IF_H)
	return queryNetworkInterfaceAddresses(ret,
	    OFNetworkInterfaceIPv6Addresses, OFSocketAddressFamilyIPv6,
	    AF_INET6, sizeof(struct sockaddr_in6));
# else
	return false;
# endif
}
#endif

#ifdef OF_HAVE_IPX
static bool
queryNetworkInterfaceIPXAddresses(OFMutableDictionary *ret)
{
# if defined(OF_LINUX) && defined(OF_HAVE_FILES)
	OFFile *file;
	OFString *line;
	OFMutableDictionary *interface;
	OFEnumerator *enumerator;

	@try {
		file = [OFFile fileWithPath: @"/proc/net/ipx/interface"
				       mode: @"r"];
	} @catch (OFOpenItemFailedException *e) {
		return false;
	}

	/* First line is "Network Node_Address Primary Device Frame_Type" */
	if (![[file readLine] hasPrefix: @"Network "])
		return false;

	while ((line = [file readLine]) != nil) {
		OFArray *components = [line
		    componentsSeparatedByString: @" "
					options: OFStringSkipEmptyComponents];
		OFString *name;
		unsigned long long network, nodeLong;
		unsigned char node[IPX_NODE_LEN];
		OFSocketAddress address;
		OFMutableData *addresses;

		if (components.count < 5)
			continue;

		name = [components objectAtIndex: 3];

		if ((interface = [ret objectForKey: name]) == nil) {
			interface = [OFMutableDictionary dictionary];
			[ret setObject: interface forKey: name];
		}

		@try {
			network = [[components objectAtIndex: 0]
			    unsignedLongLongValueWithBase: 16];
			nodeLong = [[components objectAtIndex: 1]
			    unsignedLongLongValueWithBase: 16];
		} @catch (OFInvalidFormatException *e) {
			continue;
		}

		if (network > 0xFFFFFFFF || nodeLong > 0xFFFFFFFFFFFF)
			continue;

		node[0] = (nodeLong >> 40) & 0xFF;
		node[1] = (nodeLong >> 32) & 0xFF;
		node[2] = (nodeLong >> 24) & 0xFF;
		node[3] = (nodeLong >> 16) & 0xFF;
		node[4] = (nodeLong >> 8) & 0xFF;
		node[5] = nodeLong & 0xFF;

		address = OFSocketAddressMakeIPX((uint32_t)network, node, 0);

		if ((addresses = [interface objectForKey:
		    OFNetworkInterfaceIPXAddresses]) == nil) {
			addresses = [OFMutableData
			    dataWithItemSize: sizeof(OFSocketAddress)];
			[interface setObject: addresses
				      forKey: OFNetworkInterfaceIPXAddresses];
		}

		[addresses addItem: &address];
	}

	enumerator = [ret objectEnumerator];
	while ((interface = [enumerator nextObject]) != nil)
		[[interface objectForKey: OFNetworkInterfaceIPXAddresses]
		    makeImmutable];

	return false;
# elif defined(HAVE_IOCTL) && defined(HAVE_NET_IF_H)
	return queryNetworkInterfaceAddresses(ret,
	    OFNetworkInterfaceIPXAddresses, OFSocketAddressFamilyIPX,
	    AF_IPX, sizeof(struct sockaddr_ipx));
# else
	return false;
# endif
}
#endif

#ifdef OF_HAVE_APPLETALK
static bool
queryNetworkInterfaceAppleTalkAddresses(OFMutableDictionary *ret)
{
# if defined(OF_LINUX) && defined(OF_HAVE_FILES)
	OFFile *file;
	OFString *line;
	OFMutableDictionary *interface;
	OFEnumerator *enumerator;

	@try {
		file = [OFFile fileWithPath: @"/proc/net/atalk/interface"
				       mode: @"r"];
	} @catch (OFOpenItemFailedException *e) {
		return false;
	}

	/* First line is "Interface Address Networks Status" */
	if (![[file readLine] hasPrefix: @"Interface "])
		return false;

	while ((line = [file readLine]) != nil) {
		OFArray *components = [line
		    componentsSeparatedByString: @" "
					options: OFStringSkipEmptyComponents];
		OFString *addressString, *name;
		unsigned long long network, node;
		OFSocketAddress address;
		OFMutableData *addresses;

		if (components.count < 4)
			continue;

		name = [components objectAtIndex: 0];
		addressString = [components objectAtIndex: 1];

		if (addressString.length != 7 ||
		    [addressString characterAtIndex: 4] != ':')
			continue;

		if ((interface = [ret objectForKey: name]) == nil) {
			interface = [OFMutableDictionary dictionary];
			[ret setObject: interface forKey: name];
		}

		@try {
			network = [[addressString
			    substringWithRange: OFMakeRange(0, 4)]
			    unsignedLongLongValueWithBase: 16];
			node = [[addressString
			    substringWithRange: OFMakeRange(5, 2)]
			    unsignedLongLongValueWithBase: 16];
		} @catch (OFInvalidFormatException *e) {
			continue;
		}

		if (network > 0xFFFF || node > 0xFF)
			continue;

		address = OFSocketAddressMakeAppleTalk(
		    (uint16_t)network, (uint8_t)node, 0);

		if ((addresses = [interface objectForKey:
		    OFNetworkInterfaceAppleTalkAddresses]) == nil) {
			addresses = [OFMutableData
			    dataWithItemSize: sizeof(OFSocketAddress)];
			[interface
			    setObject: addresses
			       forKey: OFNetworkInterfaceAppleTalkAddresses];
		}

		[addresses addItem: &address];
	}

	enumerator = [ret objectEnumerator];
	while ((interface = [enumerator nextObject]) != nil)
		[[interface objectForKey: OFNetworkInterfaceAppleTalkAddresses]
		    makeImmutable];

	return false;
# elif defined(HAVE_IOCTL) && defined(HAVE_NET_IF_H)
	return queryNetworkInterfaceAddresses(ret,
	    OFNetworkInterfaceAppleTalkAddresses,
	    OFSocketAddressFamilyAppleTalk, AF_APPLETALK,
	    sizeof(struct sockaddr_at));
# else
	return false;
# endif
}
#endif

static bool
queryNetworkInterfaceHardwareAddress(OFMutableDictionary *ret)
{
#if defined(HAVE_IOCTL) && defined(HAVE_NET_IF_H) && defined(SIOCGLIFHWADDR)
	OFStringEncoding encoding = [OFLocale encoding];
	int sock = socket(AF_INET, SOCK_DGRAM, 0);

	if (sock < 0)
		return false;

	for (OFString *name in ret) {
		size_t nameLength = [name cStringLengthWithEncoding: encoding];
		struct lifreq lifr;
		struct sockaddr_dl *sdl;
		OFData *hardwareAddress;

		if (nameLength > IFNAMSIZ)
			continue;

		memset(&lifr, 0, sizeof(lifr));
		memcpy(&lifr.lifr_name, [name cStringWithEncoding: encoding],
		    nameLength);

		if (ioctl(sock, SIOCGLIFHWADDR, &lifr) < 0)
			continue;

		if (lifr.lifr_addr.ss_family != AF_LINK)
			continue;

		sdl = (struct sockaddr_dl *)(void *)&lifr.lifr_addr;
		hardwareAddress = [OFData dataWithItems: LLADDR(sdl)
						  count: sdl->sdl_alen];
		[[ret objectForKey: name]
		    setObject: hardwareAddress
		       forKey: OFNetworkInterfaceHardwareAddress];
	}

	return true;
#elif defined(HAVE_IOCTL) && defined(HAVE_NET_IF_H) && \
    defined(SIOCGIFHWADDR) && defined(HAVE_STRUCT_IFREQ_IFR_HWADDR)
	OFStringEncoding encoding = [OFLocale encoding];
	int sock = socket(AF_INET, SOCK_DGRAM, 0);

	if (sock < 0)
		return false;

	for (OFString *name in ret) {
		size_t nameLength = [name cStringLengthWithEncoding: encoding];
		struct ifreq ifr;
		OFData *hardwareAddress;

		if (nameLength > IFNAMSIZ)
			continue;

		memset(&ifr, 0, sizeof(ifr));
		memcpy(&ifr.ifr_name, [name cStringWithEncoding: encoding],
		    nameLength);

		if (ioctl(sock, SIOCGIFHWADDR, &ifr) < 0)
			continue;

		if (ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER)
			continue;

		hardwareAddress = [OFData dataWithItems: ifr.ifr_hwaddr.sa_data
						  count: 6];
		[[ret objectForKey: name]
		    setObject: hardwareAddress
		       forKey: OFNetworkInterfaceHardwareAddress];
	}

	return true;
#elif defined(HAVE_IOCTL) && defined(HAVE_NET_IF_H) && \
    defined(HAVE_STRUCT_SOCKADDR_DL)
	OFStringEncoding encoding = [OFLocale encoding];
	int sock = socket(AF_INET, SOCK_DGRAM, 0);
	struct ifconf ifc;
	struct ifreq *ifrs;

	if (sock < 0)
		return false;

	ifrs = malloc(128 * sizeof(struct ifreq));
	if (ifrs == NULL) {
		closesocket(sock);
		return false;
	}

	@try {
		char *buffer;

		memset(&ifc, 0, sizeof(ifc));
		ifc.ifc_buf = (void *)ifrs;
		ifc.ifc_len = 128 * sizeof(struct ifreq);
		if (ioctl(sock, SIOCGIFCONF, &ifc) < 0)
			return false;

		buffer = ifc.ifc_buf;
		while (buffer < (char *)ifc.ifc_buf + ifc.ifc_len) {
			struct ifreq *current = (struct ifreq *)(void *)buffer;
			struct sockaddr_dl *sdl;
			OFString *name;
			OFMutableDictionary *interface;
			OFData *hardwareAddress;

			if (current->ifr_addr.sa_family != AF_LINK)
				goto next;

			sdl = (struct sockaddr_dl *)(void *)&current->ifr_addr;
			if (sdl->sdl_type != IFT_ETHER)
				goto next;

			name = [OFString stringWithCString: current->ifr_name
						  encoding: encoding];
			if ((interface = [ret objectForKey: name]) == nil) {
				interface = [OFMutableDictionary dictionary];
				[ret setObject: interface forKey: name];
			}

			hardwareAddress = [OFData dataWithItems: LLADDR(sdl)
							  count: sdl->sdl_alen];
			[interface
			    setObject: hardwareAddress
			       forKey: OFNetworkInterfaceHardwareAddress];

next:
# ifdef _SIZEOF_ADDR_IFREQ
			buffer += _SIZEOF_ADDR_IFREQ(*current);
# else
			buffer += sizeof(struct ifreq);
# endif
		}
	} @finally {
		free(ifrs);
		closesocket(sock);
	}

	return true;
#else
	return false;
#endif
}

+ (OFDictionary OF_GENERIC(OFString *, OFNetworkInterface) *)networkInterfaces
{
	void *pool = objc_autoreleasePoolPush();
	OFMutableDictionary *ret = [OFMutableDictionary dictionary];
	bool success = false;
	OFEnumerator *enumerator;
	OFMutableDictionary *interface;

	success |= queryNetworkInterfaceIndices(ret);
	success |= queryNetworkInterfaceIPv4Addresses(ret);
#ifdef OF_HAVE_IPV6
	success |= queryNetworkInterfaceIPv6Addresses(ret);
#endif
#ifdef OF_HAVE_IPX
	success |= queryNetworkInterfaceIPXAddresses(ret);
#endif
#ifdef OF_HAVE_APPLETALK
	success |= queryNetworkInterfaceAppleTalkAddresses(ret);
#endif
	success |= queryNetworkInterfaceHardwareAddress(ret);

	if (!success) {
		objc_autoreleasePoolPop(pool);
		return nil;
	}

	enumerator = [ret objectEnumerator];
	while ((interface = [enumerator nextObject]) != nil)
		[interface makeImmutable];

	[ret makeImmutable];
	[ret retain];

	objc_autoreleasePoolPop(pool);

	return [ret autorelease];
}
@end

Modified src/platform/POSIX/OFTLSKey.m from [e854931fa2] to [481fca63a3].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/platform/PowerPC/OFAtomic.h from [d8964b5a28] to [6fce0c346d].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
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
{
	__asm__ __volatile__ (
	    "0:\n\t"
	    "lwarx	%0, 0, %2\n\t"
	    "add	%0, %0, %1\n\t"
	    "stwcx.	%0, 0, %2\n\t"
	    "bne-	0b"
	    : "=&r"(i)
	    : "r"(i), "r"(p)

	    : "cc", "memory"
	);

	return i;
}

static OF_INLINE int32_t
OFAtomicInt32Add(volatile int32_t *_Nonnull p, int32_t i)
{
	__asm__ __volatile__ (
	    "0:\n\t"
	    "lwarx	%0, 0, %2\n\t"
	    "add	%0, %0, %1\n\t"
	    "stwcx.	%0, 0, %2\n\t"
	    "bne-	0b"
	    : "=&r"(i)
	    : "r"(i), "r"(p)

	    : "cc", "memory"
	);

	return i;
}

static OF_INLINE void *_Nullable
OFAtomicPointerAdd(void *volatile _Nullable *_Nonnull p, intptr_t i)
{
	__asm__ __volatile__ (
	    "0:\n\t"
	    "lwarx	%0, 0, %2\n\t"
	    "add	%0, %0, %1\n\t"
	    "stwcx.	%0, 0, %2\n\t"
	    "bne-	0b"
	    : "=&r"(i)
	    : "r"(i), "r"(p)

	    : "cc", "memory"
	);

	return (void *)i;
}

static OF_INLINE int
OFAtomicIntSubtract(volatile int *_Nonnull p, int i)
{
	__asm__ __volatile__ (
	    "0:\n\t"
	    "lwarx	%0, 0, %2\n\t"
	    "sub	%0, %0, %1\n\t"
	    "stwcx.	%0, 0, %2\n\t"
	    "bne-	0b"
	    : "=&r"(i)
	    : "r"(i), "r"(p)

	    : "cc", "memory"
	);

	return i;
}

static OF_INLINE int32_t
OFAtomicInt32Subtract(volatile int32_t *_Nonnull p, int32_t i)
{
	__asm__ __volatile__ (
	    "0:\n\t"
	    "lwarx	%0, 0, %2\n\t"
	    "sub	%0, %0, %1\n\t"
	    "stwcx.	%0, 0, %2\n\t"
	    "bne-	0b"
	    : "=&r"(i)
	    : "r"(i), "r"(p)

	    : "cc", "memory"
	);

	return i;
}

static OF_INLINE void *_Nullable
OFAtomicPointerSubtract(void *volatile _Nullable *_Nonnull p, intptr_t i)
{
	__asm__ __volatile__ (
	    "0:\n\t"
	    "lwarx	%0, 0, %2\n\t"
	    "sub	%0, %0, %1\n\t"
	    "stwcx.	%0, 0, %2\n\t"
	    "bne-	0b"
	    : "=&r"(i)
	    : "r"(i), "r"(p)

	    : "cc", "memory"
	);

	return (void *)i;
}

static OF_INLINE int
OFAtomicIntIncrease(volatile int *_Nonnull p)
{
	int i;

	__asm__ __volatile__ (
	    "0:\n\t"
	    "lwarx	%0, 0, %1\n\t"
	    "addi	%0, %0, 1\n\t"
	    "stwcx.	%0, 0, %1\n\t"
	    "bne-	0b"
	    : "=&r"(i)
	    : "r"(p)
	    : "cc", "memory"
	);

	return i;
}

static OF_INLINE int32_t
OFAtomicInt32Increase(volatile int32_t *_Nonnull p)
{
	int32_t i;

	__asm__ __volatile__ (
	    "0:\n\t"
	    "lwarx	%0, 0, %1\n\t"
	    "addi	%0, %0, 1\n\t"
	    "stwcx.	%0, 0, %1\n\t"
	    "bne-	0b"
	    : "=&r"(i)
	    : "r"(p)
	    : "cc", "memory"
	);

	return i;
}

static OF_INLINE int
OFAtomicIntDecrease(volatile int *_Nonnull p)
{
	int i;

	__asm__ __volatile__ (
	    "0:\n\t"
	    "lwarx	%0, 0, %1\n\t"
	    "subi	%0, %0, 1\n\t"
	    "stwcx.	%0, 0, %1\n\t"
	    "bne-	0b"
	    : "=&r"(i)
	    : "r"(p)
	    : "cc", "memory"
	);

	return i;
}

static OF_INLINE int32_t
OFAtomicInt32Decrease(volatile int32_t *_Nonnull p)
{
	int32_t i;

	__asm__ __volatile__ (
	    "0:\n\t"
	    "lwarx	%0, 0, %1\n\t"
	    "subi	%0, %0, 1\n\t"
	    "stwcx.	%0, 0, %1\n\t"
	    "bne-	0b"
	    : "=&r"(i)
	    : "r"(p)
	    : "cc", "memory"
	);

	return i;
}

static OF_INLINE unsigned int
OFAtomicIntOr(volatile unsigned int *_Nonnull p, unsigned int i)
{
	__asm__ __volatile__ (
	    "0:\n\t"
	    "lwarx	%0, 0, %2\n\t"
	    "or		%0, %0, %1\n\t"
	    "stwcx.	%0, 0, %2\n\t"
	    "bne-	0b"
	    : "=&r"(i)
	    : "r"(i), "r"(p)

	    : "cc", "memory"
	);

	return i;
}

static OF_INLINE uint32_t
OFAtomicInt32Or(volatile uint32_t *_Nonnull p, uint32_t i)
{
	__asm__ __volatile__ (
	    "0:\n\t"
	    "lwarx	%0, 0, %2\n\t"
	    "or		%0, %0, %1\n\t"
	    "stwcx.	%0, 0, %2\n\t"
	    "bne-	0b"
	    : "=&r"(i)
	    : "r"(i), "r"(p)

	    : "cc", "memory"
	);

	return i;
}

static OF_INLINE unsigned int
OFAtomicIntAnd(volatile unsigned int *_Nonnull p, unsigned int i)
{
	__asm__ __volatile__ (
	    "0:\n\t"
	    "lwarx	%0, 0, %2\n\t"
	    "and	%0, %0, %1\n\t"
	    "stwcx.	%0, 0, %2\n\t"
	    "bne-	0b"
	    : "=&r"(i)
	    : "r"(i), "r"(p)

	    : "cc", "memory"
	);

	return i;
}

static OF_INLINE uint32_t
OFAtomicInt32And(volatile uint32_t *_Nonnull p, uint32_t i)
{
	__asm__ __volatile__ (
	    "0:\n\t"
	    "lwarx	%0, 0, %2\n\t"
	    "and	%0, %0, %1\n\t"
	    "stwcx.	%0, 0, %2\n\t"
	    "bne-	0b"
	    : "=&r"(i)
	    : "r"(i), "r"(p)

	    : "cc", "memory"
	);

	return i;
}

static OF_INLINE unsigned int
OFAtomicIntXor(volatile unsigned int *_Nonnull p, unsigned int i)
{
	__asm__ __volatile__ (
	    "0:\n\t"
	    "lwarx	%0, 0, %2\n\t"
	    "xor	%0, %0, %1\n\t"
	    "stwcx.	%0, 0, %2\n\t"
	    "bne-	0b"
	    : "=&r"(i)
	    : "r"(i), "r"(p)

	    : "cc", "memory"
	);

	return i;
}

static OF_INLINE uint32_t
OFAtomicInt32Xor(volatile uint32_t *_Nonnull p, uint32_t i)
{
	__asm__ __volatile__ (
	    "0:\n\t"
	    "lwarx	%0, 0, %2\n\t"
	    "xor	%0, %0, %1\n\t"
	    "stwcx.	%0, 0, %2\n\t"
	    "bne-	0b"
	    : "=&r"(i)
	    : "r"(i), "r"(p)

	    : "cc", "memory"
	);

	return i;
}

static OF_INLINE bool







|
|
>















|
|
>















|
|
>















|
|
>















|
|
>















|
|
>

















|
|

















|
|

















|
|

















|
|















|
|
>















|
|
>















|
|
>















|
|
>















|
|
>















|
|
>







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
{
	__asm__ __volatile__ (
	    "0:\n\t"
	    "lwarx	%0, 0, %2\n\t"
	    "add	%0, %0, %1\n\t"
	    "stwcx.	%0, 0, %2\n\t"
	    "bne-	0b"
	    : "=&r" (i)
	    : "r" (i),
	      "r" (p)
	    : "cc", "memory"
	);

	return i;
}

static OF_INLINE int32_t
OFAtomicInt32Add(volatile int32_t *_Nonnull p, int32_t i)
{
	__asm__ __volatile__ (
	    "0:\n\t"
	    "lwarx	%0, 0, %2\n\t"
	    "add	%0, %0, %1\n\t"
	    "stwcx.	%0, 0, %2\n\t"
	    "bne-	0b"
	    : "=&r" (i)
	    : "r" (i),
	      "r" (p)
	    : "cc", "memory"
	);

	return i;
}

static OF_INLINE void *_Nullable
OFAtomicPointerAdd(void *volatile _Nullable *_Nonnull p, intptr_t i)
{
	__asm__ __volatile__ (
	    "0:\n\t"
	    "lwarx	%0, 0, %2\n\t"
	    "add	%0, %0, %1\n\t"
	    "stwcx.	%0, 0, %2\n\t"
	    "bne-	0b"
	    : "=&r" (i)
	    : "r" (i),
	      "r" (p)
	    : "cc", "memory"
	);

	return (void *)i;
}

static OF_INLINE int
OFAtomicIntSubtract(volatile int *_Nonnull p, int i)
{
	__asm__ __volatile__ (
	    "0:\n\t"
	    "lwarx	%0, 0, %2\n\t"
	    "sub	%0, %0, %1\n\t"
	    "stwcx.	%0, 0, %2\n\t"
	    "bne-	0b"
	    : "=&r" (i)
	    : "r" (i),
	      "r" (p)
	    : "cc", "memory"
	);

	return i;
}

static OF_INLINE int32_t
OFAtomicInt32Subtract(volatile int32_t *_Nonnull p, int32_t i)
{
	__asm__ __volatile__ (
	    "0:\n\t"
	    "lwarx	%0, 0, %2\n\t"
	    "sub	%0, %0, %1\n\t"
	    "stwcx.	%0, 0, %2\n\t"
	    "bne-	0b"
	    : "=&r" (i)
	    : "r" (i),
	      "r" (p)
	    : "cc", "memory"
	);

	return i;
}

static OF_INLINE void *_Nullable
OFAtomicPointerSubtract(void *volatile _Nullable *_Nonnull p, intptr_t i)
{
	__asm__ __volatile__ (
	    "0:\n\t"
	    "lwarx	%0, 0, %2\n\t"
	    "sub	%0, %0, %1\n\t"
	    "stwcx.	%0, 0, %2\n\t"
	    "bne-	0b"
	    : "=&r" (i)
	    : "r" (i),
	      "r" (p)
	    : "cc", "memory"
	);

	return (void *)i;
}

static OF_INLINE int
OFAtomicIntIncrease(volatile int *_Nonnull p)
{
	int i;

	__asm__ __volatile__ (
	    "0:\n\t"
	    "lwarx	%0, 0, %1\n\t"
	    "addi	%0, %0, 1\n\t"
	    "stwcx.	%0, 0, %1\n\t"
	    "bne-	0b"
	    : "=&r" (i)
	    : "r" (p)
	    : "cc", "memory"
	);

	return i;
}

static OF_INLINE int32_t
OFAtomicInt32Increase(volatile int32_t *_Nonnull p)
{
	int32_t i;

	__asm__ __volatile__ (
	    "0:\n\t"
	    "lwarx	%0, 0, %1\n\t"
	    "addi	%0, %0, 1\n\t"
	    "stwcx.	%0, 0, %1\n\t"
	    "bne-	0b"
	    : "=&r" (i)
	    : "r" (p)
	    : "cc", "memory"
	);

	return i;
}

static OF_INLINE int
OFAtomicIntDecrease(volatile int *_Nonnull p)
{
	int i;

	__asm__ __volatile__ (
	    "0:\n\t"
	    "lwarx	%0, 0, %1\n\t"
	    "subi	%0, %0, 1\n\t"
	    "stwcx.	%0, 0, %1\n\t"
	    "bne-	0b"
	    : "=&r" (i)
	    : "r" (p)
	    : "cc", "memory"
	);

	return i;
}

static OF_INLINE int32_t
OFAtomicInt32Decrease(volatile int32_t *_Nonnull p)
{
	int32_t i;

	__asm__ __volatile__ (
	    "0:\n\t"
	    "lwarx	%0, 0, %1\n\t"
	    "subi	%0, %0, 1\n\t"
	    "stwcx.	%0, 0, %1\n\t"
	    "bne-	0b"
	    : "=&r" (i)
	    : "r" (p)
	    : "cc", "memory"
	);

	return i;
}

static OF_INLINE unsigned int
OFAtomicIntOr(volatile unsigned int *_Nonnull p, unsigned int i)
{
	__asm__ __volatile__ (
	    "0:\n\t"
	    "lwarx	%0, 0, %2\n\t"
	    "or		%0, %0, %1\n\t"
	    "stwcx.	%0, 0, %2\n\t"
	    "bne-	0b"
	    : "=&r" (i)
	    : "r" (i),
	      "r" (p)
	    : "cc", "memory"
	);

	return i;
}

static OF_INLINE uint32_t
OFAtomicInt32Or(volatile uint32_t *_Nonnull p, uint32_t i)
{
	__asm__ __volatile__ (
	    "0:\n\t"
	    "lwarx	%0, 0, %2\n\t"
	    "or		%0, %0, %1\n\t"
	    "stwcx.	%0, 0, %2\n\t"
	    "bne-	0b"
	    : "=&r" (i)
	    : "r" (i),
	      "r" (p)
	    : "cc", "memory"
	);

	return i;
}

static OF_INLINE unsigned int
OFAtomicIntAnd(volatile unsigned int *_Nonnull p, unsigned int i)
{
	__asm__ __volatile__ (
	    "0:\n\t"
	    "lwarx	%0, 0, %2\n\t"
	    "and	%0, %0, %1\n\t"
	    "stwcx.	%0, 0, %2\n\t"
	    "bne-	0b"
	    : "=&r" (i)
	    : "r" (i),
	      "r" (p)
	    : "cc", "memory"
	);

	return i;
}

static OF_INLINE uint32_t
OFAtomicInt32And(volatile uint32_t *_Nonnull p, uint32_t i)
{
	__asm__ __volatile__ (
	    "0:\n\t"
	    "lwarx	%0, 0, %2\n\t"
	    "and	%0, %0, %1\n\t"
	    "stwcx.	%0, 0, %2\n\t"
	    "bne-	0b"
	    : "=&r" (i)
	    : "r" (i),
	      "r" (p)
	    : "cc", "memory"
	);

	return i;
}

static OF_INLINE unsigned int
OFAtomicIntXor(volatile unsigned int *_Nonnull p, unsigned int i)
{
	__asm__ __volatile__ (
	    "0:\n\t"
	    "lwarx	%0, 0, %2\n\t"
	    "xor	%0, %0, %1\n\t"
	    "stwcx.	%0, 0, %2\n\t"
	    "bne-	0b"
	    : "=&r" (i)
	    : "r" (i),
	      "r" (p)
	    : "cc", "memory"
	);

	return i;
}

static OF_INLINE uint32_t
OFAtomicInt32Xor(volatile uint32_t *_Nonnull p, uint32_t i)
{
	__asm__ __volatile__ (
	    "0:\n\t"
	    "lwarx	%0, 0, %2\n\t"
	    "xor	%0, %0, %1\n\t"
	    "stwcx.	%0, 0, %2\n\t"
	    "bne-	0b"
	    : "=&r" (i)
	    : "r" (i),
	      "r" (p)
	    : "cc", "memory"
	);

	return i;
}

static OF_INLINE bool
307
308
309
310
311
312
313
314
315


316
317
318
319
320
321
322
	    "bne-	0b\n\t"
	    "li		%0, 1\n\t"
	    "b		2f\n\t"
	    "1:\n\t"
	    "stwcx.	%0, 0, %3\n\t"
	    "li		%0, 0\n\t"
	    "2:"
	    : "=&r"(r)
	    : "r"(o), "r"(n), "r"(p)


	    : "cc", "memory"
	);

	return r;
}

static OF_INLINE bool







|
|
>
>







319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
	    "bne-	0b\n\t"
	    "li		%0, 1\n\t"
	    "b		2f\n\t"
	    "1:\n\t"
	    "stwcx.	%0, 0, %3\n\t"
	    "li		%0, 0\n\t"
	    "2:"
	    : "=&r" (r)
	    : "r" (o),
	      "r" (n),
	      "r" (p)
	    : "cc", "memory"
	);

	return r;
}

static OF_INLINE bool
333
334
335
336
337
338
339
340
341


342
343
344
345
346
347
348
	    "bne-	0b\n\t"
	    "li		%0, 1\n\t"
	    "b		2f\n\t"
	    "1:\n\t"
	    "stwcx.	%0, 0, %3\n\t"
	    "li		%0, 0\n\t"
	    "2:"
	    : "=&r"(r)
	    : "r"(o), "r"(n), "r"(p)


	    : "cc", "memory"
	);

	return r;
}

static OF_INLINE bool







|
|
>
>







347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
	    "bne-	0b\n\t"
	    "li		%0, 1\n\t"
	    "b		2f\n\t"
	    "1:\n\t"
	    "stwcx.	%0, 0, %3\n\t"
	    "li		%0, 0\n\t"
	    "2:"
	    : "=&r" (r)
	    : "r" (o),
	      "r" (n),
	      "r" (p)
	    : "cc", "memory"
	);

	return r;
}

static OF_INLINE bool
360
361
362
363
364
365
366
367
368


369
370
371
372
373
374
375
	    "bne-	0b\n\t"
	    "li		%0, 1\n\t"
	    "b		2f\n\t"
	    "1:\n\t"
	    "stwcx.	%0, 0, %3\n\t"
	    "li		%0, 0\n\t"
	    "2:"
	    : "=&r"(r)
	    : "r"(o), "r"(n), "r"(p)


	    : "cc", "memory"
	);

	return r;
}

static OF_INLINE void







|
|
>
>







376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
	    "bne-	0b\n\t"
	    "li		%0, 1\n\t"
	    "b		2f\n\t"
	    "1:\n\t"
	    "stwcx.	%0, 0, %3\n\t"
	    "li		%0, 0\n\t"
	    "2:"
	    : "=&r" (r)
	    : "r" (o),
	      "r" (n),
	      "r" (p)
	    : "cc", "memory"
	);

	return r;
}

static OF_INLINE void

Modified src/platform/Windows/OFPlainCondition.m from [cd952f15d7] to [30016e033f].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

21
22
23
24
25
26
27
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#include <errno.h>

#import "OFPlainCondition.h"


#include <windows.h>

int
OFPlainConditionNew(OFPlainCondition *condition)
{
	condition->count = 0;

|


















>







1
2
3
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"

#include <errno.h>

#import "OFPlainCondition.h"
#import "OFConstantString.h"

#include <windows.h>

int
OFPlainConditionNew(OFPlainCondition *condition)
{
	condition->count = 0;

Modified src/platform/Windows/OFPlainMutex.m from [f924adddc3] to [dec5e41705].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/platform/Windows/OFPlainThread.m from [d2bc6a9806] to [8447cf3b9e].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#include <errno.h>

#import "OFPlainThread.h"

#import "macros.h"

#include <windows.h>

struct ThreadContext {
	void (*function)(id);
	id object;
};

|


















<
|







1
2
3
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"

#include <errno.h>

#import "OFPlainThread.h"

#import "OFConstantString.h"

#include <windows.h>

struct ThreadContext {
	void (*function)(id);
	id object;
};

Modified src/platform/Windows/OFString+PathAdditions.m from [ec08b34f89] to [a3daa7c8cf].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
 * Windows-specific parts!
 */

#include "config.h"

#import "OFString+PathAdditions.h"
#import "OFArray.h"
#import "OFFileURIHandler.h"
#import "OFURI.h"

#import "OFInvalidFormatException.h"
#import "OFOutOfRangeException.h"

int _OFString_PathAdditions_reference;

@implementation OFString (PathAdditions)







|
|







18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
 * Windows-specific parts!
 */

#include "config.h"

#import "OFString+PathAdditions.h"
#import "OFArray.h"
#import "OFFileIRIHandler.h"
#import "OFIRI.h"

#import "OFInvalidFormatException.h"
#import "OFOutOfRangeException.h"

int _OFString_PathAdditions_reference;

@implementation OFString (PathAdditions)
301
302
303
304
305
306
307



308
309
310
311
312
313
314
	objc_autoreleasePoolPop(pool);

	return [ret autorelease];
}

- (OFString *)stringByAppendingPathComponent: (OFString *)component
{



	if ([self hasSuffix: @"\\"] || [self hasSuffix: @"/"])
		return [self stringByAppendingString: component];
	else {
		OFMutableString *ret = [[self mutableCopy] autorelease];

		[ret appendString: @"\\"];
		[ret appendString: component];







>
>
>







301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
	objc_autoreleasePoolPop(pool);

	return [ret autorelease];
}

- (OFString *)stringByAppendingPathComponent: (OFString *)component
{
	if (self.length == 0)
		return component;

	if ([self hasSuffix: @"\\"] || [self hasSuffix: @"/"])
		return [self stringByAppendingString: component];
	else {
		OFMutableString *ret = [[self mutableCopy] autorelease];

		[ret appendString: @"\\"];
		[ret appendString: component];
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
	} else
		return [self stringByAppendingFormat: @".%@", extension];
}

- (bool)of_isDirectoryPath
{
	return ([self hasSuffix: @"\\"] || [self hasSuffix: @"/"] ||
	    [OFFileURIHandler of_directoryExistsAtPath: self]);
}

- (OFString *)of_pathToURIPathWithPercentEncodedHost:
    (OFString **)percentEncodedHost
{
	OFString *path = self;

	if ([path hasPrefix: @"\\\\"]) {
		OFArray *components = path.pathComponents;

		if (components.count < 2)
			@throw [OFInvalidFormatException exception];

		*percentEncodedHost = [[components objectAtIndex: 1]
		     stringByAddingPercentEncodingWithAllowedCharacters:
		     [OFCharacterSet URIHostAllowedCharacterSet]];
		path = [OFString pathWithComponents: [components
		    objectsInRange: OFMakeRange(2, components.count - 2)]];
	}

	path = [path stringByReplacingOccurrencesOfString: @"\\"
					       withString: @"/"];
	path = [@"/" stringByAppendingString: path];

	return path;
}

- (OFString *)of_URIPathToPathWithPercentEncodedHost:
    (OFString *)percentEncodedHost
{
	OFString *path = self;

	if (path.length > 1 && [path hasSuffix: @"/"] &&
	    ![path hasSuffix: @":/"])
		path = [path substringToIndex: path.length - 1];







|


|












|











|







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
	} else
		return [self stringByAppendingFormat: @".%@", extension];
}

- (bool)of_isDirectoryPath
{
	return ([self hasSuffix: @"\\"] || [self hasSuffix: @"/"] ||
	    [OFFileIRIHandler of_directoryExistsAtPath: self]);
}

- (OFString *)of_pathToIRIPathWithPercentEncodedHost:
    (OFString **)percentEncodedHost
{
	OFString *path = self;

	if ([path hasPrefix: @"\\\\"]) {
		OFArray *components = path.pathComponents;

		if (components.count < 2)
			@throw [OFInvalidFormatException exception];

		*percentEncodedHost = [[components objectAtIndex: 1]
		     stringByAddingPercentEncodingWithAllowedCharacters:
		     [OFCharacterSet IRIHostAllowedCharacterSet]];
		path = [OFString pathWithComponents: [components
		    objectsInRange: OFMakeRange(2, components.count - 2)]];
	}

	path = [path stringByReplacingOccurrencesOfString: @"\\"
					       withString: @"/"];
	path = [@"/" stringByAppendingString: path];

	return path;
}

- (OFString *)of_IRIPathToPathWithPercentEncodedHost:
    (OFString *)percentEncodedHost
{
	OFString *path = self;

	if (path.length > 1 && [path hasSuffix: @"/"] &&
	    ![path hasSuffix: @":/"])
		path = [path substringToIndex: path.length - 1];
394
395
396
397
398
399
400
401
402
403
404
405
406
			path = [OFString stringWithFormat: @"\\\\%@\\%@",
							   host, path];
	}

	return path;
}

- (OFString *)of_pathComponentToURIPathComponent
{
	return [self stringByReplacingOccurrencesOfString: @"\\"
					       withString: @"/"];
}
@end







|





397
398
399
400
401
402
403
404
405
406
407
408
409
			path = [OFString stringWithFormat: @"\\\\%@\\%@",
							   host, path];
	}

	return path;
}

- (OFString *)of_pathComponentToIRIPathComponent
{
	return [self stringByReplacingOccurrencesOfString: @"\\"
					       withString: @"/"];
}
@end

Modified src/platform/Windows/OFSubprocess.m from [bef5ba2521] to [3257d0230c].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Added src/platform/Windows/OFSystemInfo+NetworkInterfaces.m version [a714877a2e].





















































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
/*
 * 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 "OFSystemInfo.h"
#import "OFSystemInfo+NetworkInterfaces.h"
#import "OFData.h"
#import "OFDictionary.h"
#import "OFLocale.h"
#import "OFNumber.h"
#import "OFOnce.h"
#import "OFSocket.h"
#import "OFString.h"

#include <windows.h>
#define interface struct
#include <iphlpapi.h>
#undef interface

static WINAPI ULONG (*GetAdaptersAddressesFuncPtr)(ULONG, ULONG, PVOID,
    PIP_ADAPTER_ADDRESSES, PULONG);

static void
init(void)
{
	HMODULE module;

	if ((module = 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);

			if (newAdapterAddresses == NULL)
				return nil;

			adapterAddresses = newAdapterAddresses;
			error = GetAdaptersAddressesFuncPtr(AF_UNSPEC, 0, NULL,
			    adapterAddresses, &adapterAddressesSize);
		}

		if (error != ERROR_SUCCESS)
			return nil;

		for (PIP_ADAPTER_ADDRESSES iter = adapterAddresses;
		    iter != NULL; iter = iter->Next) {
			OFString *name;
			OFMutableDictionary *interface;
			OFNumber *index;

			name = [OFString 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;

				length = (int)sizeof(address.sockaddr);
				if (length > addrIter->Address.iSockaddrLength)
					length =
					    addrIter->Address.iSockaddrLength;

				memset(&address, 0, sizeof(OFSocketAddress));
				memcpy(&address.sockaddr,
				    addrIter->Address.lpSockaddr,
				    (size_t)length);

				switch (address.sockaddr.in.sin_family) {
				case AF_INET:
					address.family =
					    OFSocketAddressFamilyIPv4;
					key = OFNetworkInterfaceIPv4Addresses;
					break;
				case AF_INET6:
					address.family =
					    OFSocketAddressFamilyIPv6;
					key = OFNetworkInterfaceIPv6Addresses;
					break;
				default:
					continue;
				}

				addresses = [interface objectForKey: key];
				if (addresses == nil) {
					addresses = [OFMutableData
					    dataWithItemSize:
					    sizeof(OFSocketAddress)];
					[interface setObject: addresses
						      forKey: key];
				}

				[addresses addItem: &address];
			}

			[[interface objectForKey:
			    OFNetworkInterfaceIPv4Addresses] makeImmutable];
			[[interface objectForKey:
			    OFNetworkInterfaceIPv6Addresses] makeImmutable];
		}
	} @finally {
		free(adapterAddresses);
	}

	return ret;
}

static OFMutableDictionary OF_GENERIC(OFString *, OFNetworkInterface) *
networkInterfacesFromGetAdaptersInfo(void)
{
	OFMutableDictionary *ret = [OFMutableDictionary dictionary];
	OFStringEncoding encoding = [OFLocale encoding];
	ULONG adapterInfoSize = sizeof(IP_ADAPTER_INFO);
	PIP_ADAPTER_INFO adapterInfo;

	if ((adapterInfo = malloc(adapterInfoSize)) == NULL)
		return nil;

	@try {
		ULONG error = GetAdaptersInfo(adapterInfo, &adapterInfoSize);

		if (error == ERROR_BUFFER_OVERFLOW) {
			PIP_ADAPTER_INFO newAdapterInfo =
			    realloc(adapterInfo, adapterInfoSize);

			if (newAdapterInfo == NULL)
				return nil;

			adapterInfo = newAdapterInfo;
			error = GetAdaptersInfo(adapterInfo, &adapterInfoSize);
		}

		if (error != ERROR_SUCCESS)
			return nil;

		for (PIP_ADAPTER_INFO iter = adapterInfo; iter != NULL;
		    iter = iter->Next) {
			OFMutableDictionary *interface;
			OFString *name, *IPString;
			OFNumber *index;
			OFSocketAddress IPv4Address;
			OFData *addresses;

			name = [OFString stringWithFormat: @"%u", iter->Index];

			if ((interface = [ret objectForKey: name]) == nil) {
				interface = [OFMutableDictionary dictionary];
				[ret setObject: interface forKey: name];
			}

			index = [OFNumber numberWithUnsignedInt: iter->Index];
			[interface setObject: index
				      forKey: OFNetworkInterfaceIndex];

			if (iter->AddressLength > 0) {
				const OFNetworkInterfaceKey key =
				    OFNetworkInterfaceHardwareAddress;
				OFData *address = [OFData
				    dataWithItems: iter->Address
					    count: iter->AddressLength];
				[interface setObject: address forKey: key];
			}

			IPString = [OFString
			    stringWithCString: iter->IpAddressList.IpAddress
						   .String
				     encoding: encoding];

			if ([IPString isEqual: @"0.0.0.0"])
				continue;

			IPv4Address = OFSocketAddressParseIPv4(IPString, 0);
			addresses = [OFData dataWithItems: &IPv4Address
						    count: 1
						 itemSize: sizeof(IPv4Address)];
			[interface setObject: addresses
				      forKey: OFNetworkInterfaceIPv4Addresses];
		}
	} @finally {
		free(adapterInfo);
	}

	return ret;
}

@implementation OFSystemInfo (NetworkInterfaces)
+ (OFDictionary OF_GENERIC(OFString *, OFNetworkInterface) *)networkInterfaces
{
	static OFOnceControl onceControl = OFOnceControlInitValue;
	void *pool = objc_autoreleasePoolPush();
	OFMutableDictionary *ret;
	OFEnumerator *enumerator;
	OFMutableDictionary *interface;

	OFOnce(&onceControl, init);

	if (GetAdaptersAddressesFuncPtr != NULL)
		ret = networkInterfacesFromGetAdaptersAddresses();
	else
		ret = networkInterfacesFromGetAdaptersInfo();

	enumerator = [ret objectEnumerator];
	while ((interface = [enumerator nextObject]) != nil)
		[interface makeImmutable];

	[ret makeImmutable];
	[ret retain];

	objc_autoreleasePoolPop(pool);

	return [ret autorelease];
}
@end

Modified src/platform/Windows/OFTLSKey.m from [819b78979d] to [9fbfa5279a].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/platform/Windows/OFWin32ConsoleStdIOStream.m from [8c3f9ce8af] to [75e78c9802].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
 * In order to not do this when redirecting input / output to a file (as the
 * file would then be read / written in the wrong encoding and break reading /
 * writing binary), it checks that the handle is indeed a console.
 */

#include "config.h"

#include <assert.h>
#include <errno.h>
#include <io.h>

#import "OFWin32ConsoleStdIOStream.h"
#import "OFColor.h"
#import "OFData.h"
#import "OFStdIOStream+Private.h"







<







35
36
37
38
39
40
41

42
43
44
45
46
47
48
 * In order to not do this when redirecting input / output to a file (as the
 * file would then be read / written in the wrong encoding and break reading /
 * writing binary), it checks that the handle is indeed a console.
 */

#include "config.h"


#include <errno.h>
#include <io.h>

#import "OFWin32ConsoleStdIOStream.h"
#import "OFColor.h"
#import "OFData.h"
#import "OFStdIOStream+Private.h"
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
		if (_incompleteUTF8SurrogateLen < (size_t)UTF8Len)
			return 0;

		UTF8Len = OFUTF8StringDecode(
		    _incompleteUTF8Surrogate, _incompleteUTF8SurrogateLen, &c);

		if (UTF8Len <= 0 || c > 0x10FFFF) {
			assert(UTF8Len == 0 || UTF8Len < -4);

			UTF16[0] = 0xFFFD;
			UTF16Len = 1;
		} else {
			if (c > 0xFFFF) {
				c -= 0x10000;
				UTF16[0] = 0xD800 | (c >> 10);







|







290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
		if (_incompleteUTF8SurrogateLen < (size_t)UTF8Len)
			return 0;

		UTF8Len = OFUTF8StringDecode(
		    _incompleteUTF8Surrogate, _incompleteUTF8SurrogateLen, &c);

		if (UTF8Len <= 0 || c > 0x10FFFF) {
			OFAssert(UTF8Len == 0 || UTF8Len < -4);

			UTF16[0] = 0xFFFD;
			UTF16Len = 1;
		} else {
			if (c > 0xFFFF) {
				c -= 0x10000;
				UTF16[0] = 0xD800 | (c >> 10);

Modified src/platform/libfat/OFString+PathAdditions.m from [6647377f7a] to [ebac2411d6].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#import "OFString+PathAdditions.h"
#import "OFArray.h"
#import "OFFileURIHandler.h"

#import "OFOutOfRangeException.h"

int _OFString_PathAdditions_reference;

@implementation OFString (PathAdditions)
+ (OFString *)pathWithComponents: (OFArray *)components

|

















|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/*
 * Copyright (c) 2008-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+PathAdditions.h"
#import "OFArray.h"
#import "OFFileIRIHandler.h"

#import "OFOutOfRangeException.h"

int _OFString_PathAdditions_reference;

@implementation OFString (PathAdditions)
+ (OFString *)pathWithComponents: (OFArray *)components
297
298
299
300
301
302
303



304
305
306
307
308
309
310
	objc_autoreleasePoolPop(pool);

	return [ret autorelease];
}

- (OFString *)stringByAppendingPathComponent: (OFString *)component
{



	if ([self hasSuffix: @"/"])
		return [self stringByAppendingString: component];
	else {
		OFMutableString *ret = [[self mutableCopy] autorelease];

		[ret appendString: @"/"];
		[ret appendString: component];







>
>
>







297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
	objc_autoreleasePoolPop(pool);

	return [ret autorelease];
}

- (OFString *)stringByAppendingPathComponent: (OFString *)component
{
	if (self.length == 0)
		return component;

	if ([self hasSuffix: @"/"])
		return [self stringByAppendingString: component];
	else {
		OFMutableString *ret = [[self mutableCopy] autorelease];

		[ret appendString: @"/"];
		[ret appendString: component];
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
	} else
		return [self stringByAppendingFormat: @".%@", extension];
}

- (bool)of_isDirectoryPath
{
	return ([self hasSuffix: @"/"] ||
	    [OFFileURIHandler of_directoryExistsAtPath: self]);
}

- (OFString *)of_pathToURIPathWithPercentEncodedHost:
    (OFString **)percentEncodedHost
{
	return [@"/" stringByAppendingString: self];
}

- (OFString *)of_URIPathToPathWithPercentEncodedHost:
    (OFString *)percentEncodedHost
{
	OFString *path = self;

	if (path.length > 1 && [path hasSuffix: @"/"])
		path = [path substringToIndex: path.length - 1];

	return [path substringFromIndex: 1];
}

- (OFString *)of_pathComponentToURIPathComponent
{
	return self;
}
@end







|


|





|










|




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
	} else
		return [self stringByAppendingFormat: @".%@", extension];
}

- (bool)of_isDirectoryPath
{
	return ([self hasSuffix: @"/"] ||
	    [OFFileIRIHandler of_directoryExistsAtPath: self]);
}

- (OFString *)of_pathToIRIPathWithPercentEncodedHost:
    (OFString **)percentEncodedHost
{
	return [@"/" stringByAppendingString: self];
}

- (OFString *)of_IRIPathToPathWithPercentEncodedHost:
    (OFString *)percentEncodedHost
{
	OFString *path = self;

	if (path.length > 1 && [path hasSuffix: @"/"])
		path = [path substringToIndex: path.length - 1];

	return [path substringFromIndex: 1];
}

- (OFString *)of_pathComponentToIRIPathComponent
{
	return self;
}
@end

Modified src/platform/macOS/OFAtomic.h from [af25398c26] to [ea4bea9a33].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/platform/x86/OFAtomic.h from [db489edc3a] to [96b363e98b].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49






50


51











52
53

54



55
56
57
58
59
60
61
62
63
64
65
66
67
68

69
70
71
72
73
74
75
76
77
78

79
80
81
82
83
















84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105

106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139

140
141
142
143
144
145
146
147
148
149
150

151
152
153
154
155


















156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261


262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308

309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342

343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364

365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398

399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420

421
422
423
424
425
426
427
428
429
430
431


432




433
434
435
436
437
438

439
440



441
442
443
444
445
446
447
448
449
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
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

OF_ASSUME_NONNULL_BEGIN

static OF_INLINE int
OFAtomicIntAdd(volatile int *_Nonnull p, int i)
{
	if (sizeof(int) == 4)
		__asm__ __volatile__ (
		    "lock\n\t"
		    "xaddl	%0, %2\n\t"
		    "addl	%1, %0"
		    : "+&r"(i)
		    : "r"(i), "m"(*p)
		);
#ifdef OF_X86_64
	else if (sizeof(int) == 8)
		__asm__ __volatile__ (
		    "lock\n\t"
		    "xaddq	%0, %2\n\t"
		    "addq	%1, %0"
		    : "+&r"(i)
		    : "r"(i), "m"(*p)
		);
#endif
	else
		abort();

	return i;
}

static OF_INLINE int32_t
OFAtomicInt32Add(volatile int32_t *_Nonnull p, int32_t i)
{
	__asm__ __volatile__ (
	    "lock\n\t"






	    "xaddl	%0, %2\n\t"


	    "addl	%1, %0"











	    : "+&r"(i)
	    : "r"(i), "m"(*p)

	);




	return i;
}

static OF_INLINE void *_Nullable
OFAtomicPointerAdd(void *volatile _Nullable *_Nonnull p, intptr_t i)
{
#if defined(OF_X86_64)
	__asm__ __volatile__ (
	    "lock\n\t"
	    "xaddq	%0, %2\n\t"
	    "addq	%1, %0"
	    : "+&r"(i)
	    : "r"(i), "m"(*p)

	);

	return (void *)i;
#elif defined(OF_X86)
	__asm__ __volatile__ (
	    "lock\n\t"
	    "xaddl	%0, %2\n\t"
	    "addl	%1, %0"
	    : "+&r"(i)
	    : "r"(i), "m"(*p)

	);

	return (void *)i;
#endif
}

















static OF_INLINE int
OFAtomicIntSubtract(volatile int *_Nonnull p, int i)
{
	if (sizeof(int) == 4)
		__asm__ __volatile__ (
		    "negl	%0\n\t"
		    "lock\n\t"
		    "xaddl	%0, %2\n\t"
		    "subl	%1, %0"
		    : "+&r"(i)
		    : "r"(i), "m"(*p)
		);
#ifdef OF_X86_64
	else if (sizeof(int) == 8)
		__asm__ __volatile__ (
		    "negq	%0\n\t"
		    "lock\n\t"
		    "xaddq	%0, %2\n\t"
		    "subq	%1, %0"
		    : "+&r"(i)
		    : "r"(i), "m"(*p)

		);
#endif
	else
		abort();

	return i;
}

static OF_INLINE int32_t
OFAtomicInt32Subtract(volatile int32_t *_Nonnull p, int32_t i)
{
	__asm__ __volatile__ (
	    "negl	%0\n\t"
	    "lock\n\t"
	    "xaddl	%0, %2\n\t"
	    "subl	%1, %0"
	    : "+&r"(i)
	    : "r"(i), "m"(*p)
	);

	return i;
}

static OF_INLINE void *_Nullable
OFAtomicPointerSubtract(void *volatile _Nullable *_Nonnull p, intptr_t i)
{
#if defined(OF_X86_64)
	__asm__ __volatile__ (
	    "negq	%0\n\t"
	    "lock\n\t"
	    "xaddq	%0, %2\n\t"
	    "subq	%1, %0"
	    : "+&r"(i)
	    : "r"(i), "m"(*p)

	);

	return (void *)i;
#elif defined(OF_X86)
	__asm__ __volatile__ (
	    "negl	%0\n\t"
	    "lock\n\t"
	    "xaddl	%0, %2\n\t"
	    "subl	%1, %0"
	    : "+&r"(i)
	    : "r"(i), "m"(*p)

	);

	return (void *)i;
#endif
}



















static OF_INLINE int
OFAtomicIntIncrease(volatile int *_Nonnull p)
{
	int i;

	if (sizeof(int) == 4)
		__asm__ __volatile__ (
		    "xorl	%0, %0\n\t"
		    "incl	%0\n\t"
		    "lock\n\t"
		    "xaddl	%0, %1\n\t"
		    "incl	%0"
		    : "=&r"(i)
		    : "m"(*p)
		);
#ifdef OF_X86_64
	else if (sizeof(int) == 8)
		__asm__ __volatile__ (
		    "xorq	%0, %0\n\t"
		    "incq	%0\n\t"
		    "lock\n\t"
		    "xaddq	%0, %1\n\t"
		    "incq	%0"
		    : "=&r"(i)
		    : "m"(*p)
		);
#endif
	else
		abort();

	return i;
}

static OF_INLINE int32_t
OFAtomicInt32Increase(volatile int32_t *_Nonnull p)
{
	int32_t i;

	__asm__ __volatile__ (
	    "xorl	%0, %0\n\t"
	    "incl	%0\n\t"
	    "lock\n\t"
	    "xaddl	%0, %1\n\t"
	    "incl	%0"
	    : "=&r"(i)
	    : "m"(*p)
	);

	return i;
}

static OF_INLINE int
OFAtomicIntDecrease(volatile int *_Nonnull p)
{
	int i;

	if (sizeof(int) == 4)
		__asm__ __volatile__ (
		    "xorl	%0, %0\n\t"
		    "decl	%0\n\t"
		    "lock\n\t"
		    "xaddl	%0, %1\n\t"
		    "decl	%0"
		    : "=&r"(i)
		    : "m"(*p)
		);
#ifdef OF_X86_64
	else if (sizeof(int) == 8)
		__asm__ __volatile__ (
		    "xorq	%0, %0\n\t"
		    "decq	%0\n\t"
		    "lock\n\t"
		    "xaddq	%0, %1\n\t"
		    "decq	%0"
		    : "=&r"(i)
		    : "m"(*p)
		);
#endif
	else
		abort();

	return i;
}

static OF_INLINE int32_t
OFAtomicInt32Decrease(volatile int32_t *_Nonnull p)
{
	int32_t i;

	__asm__ __volatile__ (
	    "xorl	%0, %0\n\t"
	    "decl	%0\n\t"
	    "lock\n\t"
	    "xaddl	%0, %1\n\t"
	    "decl	%0"
	    : "=&r"(i)
	    : "m"(*p)
	);

	return i;
}

static OF_INLINE unsigned int
OFAtomicIntOr(volatile unsigned int *_Nonnull p, unsigned int i)
{


	if (sizeof(int) == 4)
		__asm__ __volatile__ (
		    "0:\n\t"
		    "movl	%2, %0\n\t"
		    "movl	%0, %%eax\n\t"
		    "orl	%1, %0\n\t"
		    "lock\n\t"
		    "cmpxchg	%0, %2\n\t"
		    "jne	0b"
		    : "=&r"(i)
		    : "r"(i), "m"(*p)
		    : "eax", "cc"
		);
#ifdef OF_X86_64
	else if (sizeof(int) == 8)
		__asm__ __volatile__ (
		    "0:\n\t"
		    "movq	%2, %0\n\t"
		    "movq	%0, %%rax\n\t"
		    "orq	%1, %0\n\t"
		    "lock\n\t"
		    "cmpxchg	%0, %2\n\t"
		    "jne	0b"
		    : "=&r"(i)
		    : "r"(i), "m"(*p)
		    : "rax", "cc"
		);
#endif
	else
		abort();

	return i;
}

static OF_INLINE uint32_t
OFAtomicInt32Or(volatile uint32_t *_Nonnull p, uint32_t i)
{
	__asm__ __volatile__ (
	    "0:\n\t"
	    "movl	%2, %0\n\t"
	    "movl	%0, %%eax\n\t"
	    "orl	%1, %0\n\t"
	    "lock\n\t"
	    "cmpxchg	%0, %2\n\t"
	    "jne	0b"
	    : "=&r"(i)
	    : "r"(i), "m"(*p)

	    : "eax", "cc"
	);

	return i;
}

static OF_INLINE unsigned int
OFAtomicIntAnd(volatile unsigned int *_Nonnull p, unsigned int i)
{
	if (sizeof(int) == 4)
		__asm__ __volatile__ (
		    "0:\n\t"
		    "movl	%2, %0\n\t"
		    "movl	%0, %%eax\n\t"
		    "andl	%1, %0\n\t"
		    "lock\n\t"
		    "cmpxchg	%0, %2\n\t"
		    "jne	0b"
		    : "=&r"(i)
		    : "r"(i), "m"(*p)
		    : "eax", "cc"
		);
#ifdef OF_X86_64
	else if (sizeof(int) == 8)
		__asm__ __volatile__ (
		    "0:\n\t"
		    "movq	%2, %0\n\t"
		    "movq	%0, %%rax\n\t"
		    "andq	%1, %0\n\t"
		    "lock\n\t"
		    "cmpxchg	%0, %2\n\t"
		    "jne	0b"
		    : "=&r"(i)
		    : "r"(i), "m"(*p)

		    : "rax", "cc"
		);
#endif
	else
		abort();

	return i;
}

static OF_INLINE uint32_t
OFAtomicInt32And(volatile uint32_t *_Nonnull p, uint32_t i)
{
	__asm__ __volatile__ (
	    "0:\n\t"
	    "movl	%2, %0\n\t"
	    "movl	%0, %%eax\n\t"
	    "andl	%1, %0\n\t"
	    "lock\n\t"
	    "cmpxchg	%0, %2\n\t"
	    "jne	0b"
	    : "=&r"(i)
	    : "r"(i), "m"(*p)

	    : "eax", "cc"
	);

	return i;
}

static OF_INLINE unsigned int
OFAtomicIntXor(volatile unsigned int *_Nonnull p, unsigned int i)
{
	if (sizeof(int) == 4)
		__asm__ __volatile__ (
		    "0:\n\t"
		    "movl	%2, %0\n\t"
		    "movl	%0, %%eax\n\t"
		    "xorl	%1, %0\n\t"
		    "lock\n\t"
		    "cmpxchg	%0, %2\n\t"
		    "jne	0b"
		    : "=&r"(i)
		    : "r"(i), "m"(*p)
		    : "eax", "cc"
		);
#ifdef OF_X86_64
	else if (sizeof(int) == 8)
		__asm__ __volatile__ (
		    "0:\n\t"
		    "movq	%2, %0\n\t"
		    "movq	%0, %%rax\n\t"
		    "xorq	%1, %0\n\t"
		    "lock\n\t"
		    "cmpxchg	%0, %2\n\t"
		    "jne	0b"
		    : "=&r"(i)
		    : "r"(i), "m"(*p)

		    : "rax", "cc"
		);
#endif
	else
		abort();

	return i;
}

static OF_INLINE uint32_t
OFAtomicInt32Xor(volatile uint32_t *_Nonnull p, uint32_t i)
{
	__asm__ __volatile__ (
	    "0:\n\t"
	    "movl	%2, %0\n\t"
	    "movl	%0, %%eax\n\t"
	    "xorl	%1, %0\n\t"
	    "lock\n\t"
	    "cmpxchgl	%0, %2\n\t"
	    "jne	0b"
	    : "=&r"(i)
	    : "r"(i), "m"(*p)

	    : "eax", "cc"
	);

	return i;
}

static OF_INLINE bool
OFAtomicIntCompareAndSwap(volatile int *_Nonnull p, int o, int n)
{
	int r;



	__asm__ __volatile__ (




	    "lock\n\t"
	    "cmpxchg	%2, %3\n\t"
	    "sete	%b0\n\t"
	    "movzbl	%b0, %0"
	    : "=&d"(r), "+a"(o)	/* use d instead of r to avoid a gcc bug */
	    : "r"(n), "m"(*p)

	    : "cc"
	);




	return r;
}

static OF_INLINE bool
OFAtomicInt32CompareAndSwap(volatile int32_t *_Nonnull p, int32_t o, int32_t n)
{
	int r;

	__asm__ __volatile__ (
	    "lock\n\t"
	    "cmpxchg	%2, %3\n\t"
	    "sete	%b0\n\t"







	    "movzbl	%b0, %0"













	    : "=&d"(r), "+a"(o)	/* use d instead of r to avoid a gcc bug */

	    : "r"(n), "m"(*p)

	    : "cc"
	);

	return r;
}

static OF_INLINE bool
OFAtomicPointerCompareAndSwap(void *volatile _Nullable *_Nonnull p,
    void *_Nullable o, void *_Nullable n)
{
	int r;

	__asm__ __volatile__ (
	    "lock\n\t"
	    "cmpxchg	%2, %3\n\t"
	    "sete	%b0\n\t"
	    "movzbl	%b0, %0"
	    : "=&d"(r), "+a"(o)	/* use d instead of r to avoid a gcc bug */

	    : "r"(n), "m"(*p)

	    : "cc"
	);

	return r;
}

static OF_INLINE void
OFMemoryBarrier(void)
{

	__asm__ __volatile__ (
	    "mfence" ::: "memory"
	);





}

static OF_INLINE void
OFAcquireMemoryBarrier(void)
{
	__asm__ __volatile__ ("" ::: "memory");
}

|















<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<





>
>
>
>
>
>
|
>
>
|
>
>
>
>
>
>
>
>
>
>
>
|
|
>
|
>
>
>







|


|
|
|
|
>






|
|
|
|
>





>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>





<
<
<
<
<
<
<
|
|


|

|
|
|
|
>








<
<
<
<
<
<
<
<
<
<
<
<
<
<
<



|

|

|
|
|
|
>





|

|
|
|
|
>





>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|


|
|

|
|
|
|














|
|

|
|
|
|





|
|

>
>

<
<
<
<
<
<
<
<
<
<
<
|
|


<
|
<
|

|
|
|
|
<













|
|
|

|

|
|
>







|


<
<
<
<
<
<
<
<
<
<
<
|
|



|
|
|

|

|
|
>














|
|
|

|

|
|
>







|


<
<
<
<
<
<
<
<
<
<
<
|
|



|
|
|

|

|
|
>














|
|
|

|

|
|
>






|
|

|
|
>
>
|
>
>
>
>
|
|
|
<
|
|
>
|
|
>
>
>

|









|

>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
|
>














|

|
|
>
|
>









>

|

>
>
>
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17



























18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102







103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121















122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175




























176































177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218











219
220
221
222

223

224
225
226
227
228
229

230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261











262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308











309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366

367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
/*
 * 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.
 */

OF_ASSUME_NONNULL_BEGIN




























static OF_INLINE int32_t
OFAtomicInt32Add(volatile int32_t *_Nonnull p, int32_t i)
{
	__asm__ __volatile__ (
	    "lock\n\t"
	    "xadd{l}	{ %0, %2 | %2, %0 }\n\t"
	    "add{l}	{ %1, %0 | %0, %1 }"
	    : "+&r" (i)
	    : "r" (i),
	      "m" (*p)
	);

	return i;
}

static OF_INLINE int
OFAtomicIntAdd(volatile int *_Nonnull p, int i)
{
	if (sizeof(int) == 4)
		return OFAtomicInt32Add(p, i);
#ifdef OF_AMD64
	else if (sizeof(int) == 8)
		__asm__ __volatile__ (
		    "lock\n\t"
		    "xadd{q}	{ %0, %2 | %2, %0 }\n\t"
		    "add{q}	{ %1, %0 | %0, %1 }"
		    : "+&r" (i)
		    : "r" (i),
		      "m" (*p)
		);
#endif
	else
		abort();

	return i;
}

static OF_INLINE void *_Nullable
OFAtomicPointerAdd(void *volatile _Nullable *_Nonnull p, intptr_t i)
{
#if defined(OF_AMD64)
	__asm__ __volatile__ (
	    "lock\n\t"
	    "xadd{q}	{ %0, %2 | %2, %0 }\n\t"
	    "add{q}	{ %1, %0 | %0, %1 }"
	    : "+&r" (i)
	    : "r" (i),
	      "m" (*p)
	);

	return (void *)i;
#elif defined(OF_X86)
	__asm__ __volatile__ (
	    "lock\n\t"
	    "xadd{l}	{ %0, %2 | %2, %0 }\n\t"
	    "add{l}	{ %1, %0 | %0, %1 }"
	    : "+&r" (i)
	    : "r" (i),
	      "m" (*p)
	);

	return (void *)i;
#endif
}

static OF_INLINE int32_t
OFAtomicInt32Subtract(volatile int32_t *_Nonnull p, int32_t i)
{
	__asm__ __volatile__ (
	    "neg{l}	%0\n\t"
	    "lock\n\t"
	    "xadd{l}	{ %0, %2 | %2, %0 }\n\t"
	    "sub{l}	{ %1, %0 | %0, %1 }"
	    : "+&r" (i)
	    : "r" (i),
	      "m" (*p)
	);

	return i;
}

static OF_INLINE int
OFAtomicIntSubtract(volatile int *_Nonnull p, int i)
{
	if (sizeof(int) == 4)







		return OFAtomicInt32Subtract(p, i);
#ifdef OF_AMD64
	else if (sizeof(int) == 8)
		__asm__ __volatile__ (
		    "neg{q}	%0\n\t"
		    "lock\n\t"
		    "xadd{q}	{ %0, %2 | %2, %0 }\n\t"
		    "sub{q}	{ %1, %0 | %0, %1 }"
		    : "+&r" (i)
		    : "r" (i),
		      "m" (*p)
		);
#endif
	else
		abort();

	return i;
}
















static OF_INLINE void *_Nullable
OFAtomicPointerSubtract(void *volatile _Nullable *_Nonnull p, intptr_t i)
{
#if defined(OF_AMD64)
	__asm__ __volatile__ (
	    "neg{q}	%0\n\t"
	    "lock\n\t"
	    "xadd{q}	{ %0, %2 | %2, %0 }\n\t"
	    "sub{q}	{ %1, %0 | %0, %1 }"
	    : "+&r" (i)
	    : "r" (i),
	      "m" (*p)
	);

	return (void *)i;
#elif defined(OF_X86)
	__asm__ __volatile__ (
	    "neg{l}	%0\n\t"
	    "lock\n\t"
	    "xadd{l}	{ %0, %2 | %2, %0 }\n\t"
	    "sub{l}	{ %1, %0 | %0, %1 }"
	    : "+&r" (i)
	    : "r" (i),
	      "m" (*p)
	);

	return (void *)i;
#endif
}

static OF_INLINE int32_t
OFAtomicInt32Increase(volatile int32_t *_Nonnull p)
{
	int32_t i;

	__asm__ __volatile__ (
	    "xor{l}	%0, %0\n\t"
	    "inc{l}	%0\n\t"
	    "lock\n\t"
	    "xadd{l}	{ %0, %1 | %1, %0 }\n\t"
	    "inc{l}	%0"
	    : "=&r" (i)
	    : "m" (*p)
	);

	return i;
}

static OF_INLINE int
OFAtomicIntIncrease(volatile int *_Nonnull p)
{
	int i;

	if (sizeof(int) == 4)




























		return OFAtomicInt32Increase(p);































#ifdef OF_AMD64
	else if (sizeof(int) == 8)
		__asm__ __volatile__ (
		    "xor{q}	%0, %0\n\t"
		    "inc{q}	%0\n\t"
		    "lock\n\t"
		    "xadd{q}	{ %0, %1 | %1, %0 }\n\t"
		    "inc{q}	%0"
		    : "=&r" (i)
		    : "m" (*p)
		);
#endif
	else
		abort();

	return i;
}

static OF_INLINE int32_t
OFAtomicInt32Decrease(volatile int32_t *_Nonnull p)
{
	int32_t i;

	__asm__ __volatile__ (
	    "xor{l}	%0, %0\n\t"
	    "dec{l}	%0\n\t"
	    "lock\n\t"
	    "xadd{l}	{ %0, %1 | %1, %0 }\n\t"
	    "dec{l}	%0"
	    : "=&r" (i)
	    : "m" (*p)
	);

	return i;
}

static OF_INLINE int
OFAtomicIntDecrease(volatile int *_Nonnull p)
{
	int i;

	if (sizeof(int) == 4)











		return OFAtomicInt32Decrease(p);
#ifdef OF_AMD64
	else if (sizeof(int) == 8)
		__asm__ __volatile__ (

		    "xor{q}	%0, %0\n\t"

		    "dec{q}	%0\n\t"
		    "lock\n\t"
		    "xadd{q}	{ %0, %1 | %1, %0 }\n\t"
		    "dec{q}	%0"
		    : "=&r" (i)
		    : "m" (*p)

		);
#endif
	else
		abort();

	return i;
}

static OF_INLINE uint32_t
OFAtomicInt32Or(volatile uint32_t *_Nonnull p, uint32_t i)
{
	__asm__ __volatile__ (
	    "0:\n\t"
	    "mov{l}	{ %2, %0 | %0, %2 }\n\t"
	    "mov{l}	{ %0, %%eax | eax, %0 }\n\t"
	    "or{l}	{ %1, %0 | %0, %1 }\n\t"
	    "lock\n\t"
	    "cmpxchg{l}	{ %0, %2 | %2, %0 }\n\t"
	    "jne	0b"
	    : "=&r" (i)
	    : "r" (i),
	      "m" (*p)
	    : "eax", "cc"
	);

	return i;
}

static OF_INLINE unsigned int
OFAtomicIntOr(volatile unsigned int *_Nonnull p, unsigned int i)
{
	if (sizeof(int) == 4)











		return OFAtomicInt32Or(p, i);
#ifdef OF_AMD64
	else if (sizeof(int) == 8)
		__asm__ __volatile__ (
		    "0:\n\t"
		    "mov{q}	{ %2, %0 | %0, %2 }\n\t"
		    "mov{q}	{ %0, %%rax | rax, %0 }\n\t"
		    "or{q}	{ %1, %0 | %0, %1 }\n\t"
		    "lock\n\t"
		    "cmpxchg{q}	{ %0, %2 | %2, %0 }\n\t"
		    "jne	0b"
		    : "=&r" (i)
		    : "r" (i),
		      "m" (*p)
		    : "rax", "cc"
		);
#endif
	else
		abort();

	return i;
}

static OF_INLINE uint32_t
OFAtomicInt32And(volatile uint32_t *_Nonnull p, uint32_t i)
{
	__asm__ __volatile__ (
	    "0:\n\t"
	    "mov{l}	{ %2, %0 | %0, %2 }\n\t"
	    "mov{l}	{ %0, %%eax | eax, %0 }\n\t"
	    "and{l}	{ %1, %0 | %0, %1 }\n\t"
	    "lock\n\t"
	    "cmpxchg{l}	{ %0, %2 | %2, %0 }\n\t"
	    "jne	0b"
	    : "=&r" (i)
	    : "r" (i),
	      "m" (*p)
	    : "eax", "cc"
	);

	return i;
}

static OF_INLINE unsigned int
OFAtomicIntAnd(volatile unsigned int *_Nonnull p, unsigned int i)
{
	if (sizeof(int) == 4)











		return OFAtomicInt32And(p, i);
#ifdef OF_AMD64
	else if (sizeof(int) == 8)
		__asm__ __volatile__ (
		    "0:\n\t"
		    "mov{q}	{ %2, %0 | %0, %2 }\n\t"
		    "mov{q}	{ %0, %%rax | rax, %0 }\n\t"
		    "and{q}	{ %1, %0 | %0, %1 }\n\t"
		    "lock\n\t"
		    "cmpxchg{q}	{ %0, %2 | %2, %0 }\n\t"
		    "jne	0b"
		    : "=&r" (i)
		    : "r" (i),
		      "m" (*p)
		    : "rax", "cc"
		);
#endif
	else
		abort();

	return i;
}

static OF_INLINE uint32_t
OFAtomicInt32Xor(volatile uint32_t *_Nonnull p, uint32_t i)
{
	__asm__ __volatile__ (
	    "0:\n\t"
	    "mov{l}	{ %2, %0 | %0, %2 }\n\t"
	    "mov{l}	{ %0, %%eax | eax, %0 }\n\t"
	    "xor{l}	{ %1, %0 | %0, %1 }\n\t"
	    "lock\n\t"
	    "cmpxchg{l}	{ %0, %2 | %2, %0 }\n\t"
	    "jne	0b"
	    : "=&r" (i)
	    : "r" (i),
	      "m" (*p)
	    : "eax", "cc"
	);

	return i;
}

static OF_INLINE unsigned int
OFAtomicIntXor(volatile unsigned int *_Nonnull p, unsigned int i)
{
	if (sizeof(int) == 4)
		return OFAtomicInt32Xor(p, i);
#ifdef OF_AMD64
	else if (sizeof(int) == 8)
		__asm__ __volatile__ (
		    "0:\n\t"
		    "mov{q}	{ %2, %0 | %0, %2 }\n\t"
		    "mov{q}	{ %0, %%rax | rax, %0 }\n\t"
		    "xor{q}	{ %1, %0 | %0, %1 }\n\t"
		    "lock\n\t"
		    "cmpxchg{q}	{ %0, %2 | %2, %0 }\n\t"
		    "jne	0b"

		    : "=&r" (i)
		    : "r" (i),
		      "m" (*p)
		    : "rax", "cc"
		);
#endif
	else
		abort();

	return i;
}

static OF_INLINE bool
OFAtomicInt32CompareAndSwap(volatile int32_t *_Nonnull p, int32_t o, int32_t n)
{
	int r;

	__asm__ __volatile__ (
	    "lock\n\t"
	    "cmpxchg{l}	{ %2, %3 | %3, %2 }\n\t"
	    "sete	%b0\n\t"
	    "movz{bl|x}	{ %b0, %0 | %0, %b0 }"
	    : "=&d" (r),	/* use d instead of r to avoid a gcc bug */
	      "+a" (o)
	    : "r" (n),
	      "m" (*p)
	    : "cc"
	);

	return r;
}

static OF_INLINE bool
OFAtomicIntCompareAndSwap(volatile int *_Nonnull p, int o, int n)
{
	int r;

	__asm__ __volatile__ (
	    "lock\n\t"
	    "cmpxchg	{ %2, %3 | %3, %2 }\n\t"
	    "sete	%b0\n\t"
	    "movz{bl|x}	{ %b0, %0 | %0, %b0 }"
	    : "=&d" (r),	/* use d instead of r to avoid a gcc bug */
	      "+a" (o)
	    : "r" (n),
	      "m" (*p)
	    : "cc"
	);

	return r;
}

static OF_INLINE bool
OFAtomicPointerCompareAndSwap(void *volatile _Nullable *_Nonnull p,
    void *_Nullable o, void *_Nullable n)
{
	int r;

	__asm__ __volatile__ (
	    "lock\n\t"
	    "cmpxchg	{ %2, %3 | %3, %2 }\n\t"
	    "sete	%b0\n\t"
	    "movz{bl|x}	{ %b0, %0 | %0, %b0 }"
	    : "=&d" (r),	/* use d instead of r to avoid a gcc bug */
	      "+a" (o)
	    : "r" (n),
	      "m" (*p)
	    : "cc"
	);

	return r;
}

static OF_INLINE void
OFMemoryBarrier(void)
{
#ifdef OF_AMD64
	__asm__ __volatile__ (
	    "lock or{q}	{ $0, (%%rsp) | [rsp], 0 }" ::: "memory", "cc"
	);
#else
	__asm__ __volatile__ (
	    "lock or{l}	{ $0, (%%esp) | [esp], 0 }" ::: "memory", "cc"
	);
#endif
}

static OF_INLINE void
OFAcquireMemoryBarrier(void)
{
	__asm__ __volatile__ ("" ::: "memory");
}

Modified src/runtime/Makefile from [23dfac9b53] to [af674fab60].

1
2
3
4
5
6
7
8
9
10
11
12

13
14
15
16
17
18
19
include ../../extra.mk

SUBDIRS = lookup-asm
SUBDIRS_AFTER = ${LINKLIB}
DISTCLEAN = Info.plist

SHARED_LIB = ${OBJFWRT_SHARED_LIB}
STATIC_LIB = ${OBJFWRT_STATIC_LIB}
FRAMEWORK = ${OBJFWRT_FRAMEWORK}
AMIGA_LIB = ${OBJFWRT_AMIGA_LIB}
LIB_MAJOR = ${OBJFWRT_LIB_MAJOR}
LIB_MINOR = ${OBJFWRT_LIB_MINOR}


SRCS = arc.m			\
       autorelease.m		\
       category.m		\
       class.m			\
       dtable.m			\
       exception.m		\



<





<


>







1
2
3

4
5
6
7
8

9
10
11
12
13
14
15
16
17
18
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		\
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
	       threading.m
SRCS_WINDOWS = versioninfo.rc
INCLUDES = ObjFWRT.h
includesubdir = ObjFWRT

OBJS_EXTRA = lookup-asm/lookup-asm.a
LIB_OBJS_EXTRA = lookup-asm/lookup-asm.lib.a
AMIGA_LIB_OBJS_START = amiga-library.amigalib.o
AMIGA_LIB_OBJS_EXTRA = amiga-glue.amigalib.o		\
		       lookup-asm/lookup-asm.amigalib.a	\
		       amiga-end.amigalib.o

include ../../buildsys.mk

CPPFLAGS += -I. -I.. -I../..					\
	    -DOBJC_COMPILING_RUNTIME				\
	    -DOBJFWRT_AMIGA_LIB=\"${OBJFWRT_AMIGA_LIB}\"	\
	    -DOBJFWRT_LIB_MAJOR=${OBJFWRT_LIB_MAJOR}		\
	    -DOBJFWRT_LIB_MINOR=${OBJFWRT_LIB_MINOR}
AMIGA_LIB_CFLAGS += -DOBJC_COMPILING_AMIGA_LIBRARY
LD = ${OBJC}
FRAMEWORK_LIBS = ${LIBS}
RCFLAGS = --use-temp-file						      \
	  -DOBJFWRT_LIB_MAJOR=${OBJFWRT_LIB_MAJOR}			      \
	  -DOBJFWRT_LIB_MINOR=${OBJFWRT_LIB_MINOR}			      \
	  -DOBJFWRT_LIB_VERSION=\"${OBJFWRT_LIB_MAJOR}.${OBJFWRT_LIB_MINOR}\" \
	  -DOBJFWRT_SHARED_LIB=\"${OBJFWRT_SHARED_LIB}\"







<
<
<
<





<


<







38
39
40
41
42
43
44




45
46
47
48
49

50
51

52
53
54
55
56
57
58
	       threading.m
SRCS_WINDOWS = versioninfo.rc
INCLUDES = ObjFWRT.h
includesubdir = ObjFWRT

OBJS_EXTRA = lookup-asm/lookup-asm.a
LIB_OBJS_EXTRA = lookup-asm/lookup-asm.lib.a





include ../../buildsys.mk

CPPFLAGS += -I. -I.. -I../..					\
	    -DOBJC_COMPILING_RUNTIME				\

	    -DOBJFWRT_LIB_MAJOR=${OBJFWRT_LIB_MAJOR}		\
	    -DOBJFWRT_LIB_MINOR=${OBJFWRT_LIB_MINOR}

LD = ${OBJC}
FRAMEWORK_LIBS = ${LIBS}
RCFLAGS = --use-temp-file						      \
	  -DOBJFWRT_LIB_MAJOR=${OBJFWRT_LIB_MAJOR}			      \
	  -DOBJFWRT_LIB_MINOR=${OBJFWRT_LIB_MINOR}			      \
	  -DOBJFWRT_LIB_VERSION=\"${OBJFWRT_LIB_MAJOR}.${OBJFWRT_LIB_MINOR}\" \
	  -DOBJFWRT_SHARED_LIB=\"${OBJFWRT_SHARED_LIB}\"

Modified src/runtime/OFOnce.m from [9cc54fa246] to [991be429bb].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/runtime/OFPlainMutex.m from [1b4abcc3c8] to [081a712ad6].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/runtime/OFTLSKey.m from [c512b1fdd8] to [80db68cc96].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/runtime/ObjFWRT.h from [87156bda73] to [a1ab03cb5a].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
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
 *		 pointers with
 */
extern void objc_setTaggedPointerSecret(uintptr_t secret);

/**
 * @brief Registers a class for tagged pointers.
 *
 * @param class The class to register for tagged pointers
 * @return The tagged pointer ID for the registered class
 */
extern int objc_registerTaggedPointerClass(Class _Nonnull class);

/**
 * @brief Returns whether the specified object is a tagged pointer.
 *
 * @param object The object to inspect
 * @return Whether the specified object is a tagged pointer
 */
extern bool object_isTaggedPointer(id _Nullable object);

/**
 * @brief Returns the value of the specified tagged pointer.
 *
 * @param object The object whose tagged pointer value should be returned
 * @return The tagged pointer value of the object
 */
extern uintptr_t object_getTaggedPointerValue(id _Nonnull object);

/**
 * @brief Creates a new tagged pointer.
 *
 * @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.
 */







|


|




















|



|







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
 *		 pointers with
 */
extern void objc_setTaggedPointerSecret(uintptr_t secret);

/**
 * @brief Registers a class for tagged pointers.
 *
 * @param class_ The class to register for tagged pointers
 * @return The tagged pointer ID for the registered class
 */
extern int objc_registerTaggedPointerClass(Class _Nonnull class_);

/**
 * @brief Returns whether the specified object is a tagged pointer.
 *
 * @param object The object to inspect
 * @return Whether the specified object is a tagged pointer
 */
extern bool object_isTaggedPointer(id _Nullable object);

/**
 * @brief Returns the value of the specified tagged pointer.
 *
 * @param object The object whose tagged pointer value should be returned
 * @return The tagged pointer value of the object
 */
extern uintptr_t object_getTaggedPointerValue(id _Nonnull object);

/**
 * @brief Creates a new tagged pointer.
 *
 * @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.
 */

Deleted src/runtime/amiga-end.m version [0cdcd50b7f].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#include "platform.h"

#ifdef OF_MORPHOS
__asm__ (
    ".section .eh_frame, \"aw\"\n"
    "	.long 0\n"
    ".section .ctors, \"aw\"\n"
    "	.long 0"
);
#else
__asm__ (
    ""
);
#endif
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<






























































Deleted src/runtime/amiga-funcarray.inc version [820bef97bb].

1
2
3
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
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

/* This file is automatically generated from amiga-library.xml */

(CONST_APTR)glue_objc_init,
(CONST_APTR)glue___objc_exec_class,
(CONST_APTR)glue_objc_msg_lookup,
(CONST_APTR)glue_objc_msg_lookup_stret,
(CONST_APTR)glue_objc_msg_lookup_super,
(CONST_APTR)glue_objc_msg_lookup_super_stret,
(CONST_APTR)glue_objc_lookUpClass,
(CONST_APTR)glue_objc_getClass,
(CONST_APTR)glue_objc_getRequiredClass,
(CONST_APTR)glue_objc_lookup_class,
(CONST_APTR)glue_objc_get_class,
(CONST_APTR)glue_objc_exception_throw,
(CONST_APTR)glue_objc_sync_enter,
(CONST_APTR)glue_objc_sync_exit,
(CONST_APTR)glue_objc_getProperty,
(CONST_APTR)glue_objc_setProperty,
(CONST_APTR)glue_objc_getPropertyStruct,
(CONST_APTR)glue_objc_setPropertyStruct,
(CONST_APTR)glue_objc_enumerationMutation,
(CONST_APTR)glue___gnu_objc_personality,
(CONST_APTR)glue_objc_retain,
(CONST_APTR)glue_objc_retainBlock,
(CONST_APTR)glue_objc_retainAutorelease,
(CONST_APTR)glue_objc_release,
(CONST_APTR)glue_objc_autorelease,
(CONST_APTR)glue_objc_autoreleaseReturnValue,
(CONST_APTR)glue_objc_retainAutoreleaseReturnValue,
(CONST_APTR)glue_objc_retainAutoreleasedReturnValue,
(CONST_APTR)glue_objc_storeStrong,
(CONST_APTR)glue_objc_storeWeak,
(CONST_APTR)glue_objc_loadWeakRetained,
(CONST_APTR)glue_objc_initWeak,
(CONST_APTR)glue_objc_destroyWeak,
(CONST_APTR)glue_objc_loadWeak,
(CONST_APTR)glue_objc_copyWeak,
(CONST_APTR)glue_objc_moveWeak,
(CONST_APTR)glue_sel_registerName,
(CONST_APTR)glue_sel_getName,
(CONST_APTR)glue_sel_isEqual,
(CONST_APTR)glue_objc_allocateClassPair,
(CONST_APTR)glue_objc_registerClassPair,
(CONST_APTR)glue_objc_getClassList,
(CONST_APTR)glue_objc_copyClassList,
(CONST_APTR)glue_class_isMetaClass,
(CONST_APTR)glue_class_getName,
(CONST_APTR)glue_class_getSuperclass,
(CONST_APTR)glue_class_getInstanceSize,
(CONST_APTR)glue_class_respondsToSelector,
(CONST_APTR)glue_class_conformsToProtocol,
(CONST_APTR)glue_class_getMethodImplementation,
(CONST_APTR)glue_class_getMethodImplementation_stret,
(CONST_APTR)glue_class_getInstanceMethod,
(CONST_APTR)glue_class_addMethod,
(CONST_APTR)glue_class_replaceMethod,
(CONST_APTR)glue_object_getClass,
(CONST_APTR)glue_object_setClass,
(CONST_APTR)glue_object_getClassName,
(CONST_APTR)glue_protocol_getName,
(CONST_APTR)glue_protocol_isEqual,
(CONST_APTR)glue_protocol_conformsToProtocol,
(CONST_APTR)glue_objc_setUncaughtExceptionHandler,
(CONST_APTR)glue_objc_setForwardHandler,
(CONST_APTR)glue_objc_setEnumerationMutationHandler,
(CONST_APTR)glue_objc_constructInstance,
(CONST_APTR)glue_objc_deinit,
(CONST_APTR)glue_class_copyIvarList,
(CONST_APTR)glue_ivar_getName,
(CONST_APTR)glue_ivar_getTypeEncoding,
(CONST_APTR)glue_ivar_getOffset,
(CONST_APTR)glue_class_copyMethodList,
(CONST_APTR)glue_method_getName,
(CONST_APTR)glue_method_getTypeEncoding,
(CONST_APTR)glue_class_copyPropertyList,
(CONST_APTR)glue_property_getName,
(CONST_APTR)glue_property_copyAttributeValue,
(CONST_APTR)glue_objc_destructInstance,
(CONST_APTR)glue_objc_autoreleasePoolPush,
(CONST_APTR)glue_objc_autoreleasePoolPop,
(CONST_APTR)glue__objc_rootAutorelease,
(CONST_APTR)glue_objc_hashtable_new,
(CONST_APTR)glue_objc_hashtable_set,
(CONST_APTR)glue_objc_hashtable_get,
(CONST_APTR)glue_objc_hashtable_delete,
(CONST_APTR)glue_objc_hashtable_free,
(CONST_APTR)glue_objc_setTaggedPointerSecret,
(CONST_APTR)glue_objc_registerTaggedPointerClass,
(CONST_APTR)glue_object_isTaggedPointer,
(CONST_APTR)glue_object_getTaggedPointerValue,
(CONST_APTR)glue_objc_createTaggedPointer,
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<




















































































































































































































Deleted src/runtime/amiga-glue.h version [dc66f09f8a].

1
2
3
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
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

/* This file is automatically generated from amiga-library.xml */

#import "ObjFWRT.h"
#import "private.h"

#ifdef OF_AMIGAOS_M68K
# define PPC_PARAMS(...) (void)
# define M68K_ARG(type, name, reg)		\
	register type reg##name __asm__(#reg);	\
	type name = reg##name;
#else
# define PPC_PARAMS(...) (__VA_ARGS__)
# define M68K_ARG(...)
#endif

extern bool glue_objc_init PPC_PARAMS(unsigned int version, struct objc_libc *libc);
extern void glue___objc_exec_class PPC_PARAMS(struct objc_module *_Nonnull module);
extern IMP _Nonnull glue_objc_msg_lookup PPC_PARAMS(id _Nullable object, SEL _Nonnull selector);
extern IMP _Nonnull glue_objc_msg_lookup_stret PPC_PARAMS(id _Nullable object, SEL _Nonnull selector);
extern IMP _Nonnull glue_objc_msg_lookup_super PPC_PARAMS(struct objc_super *_Nonnull super, SEL _Nonnull selector);
extern IMP _Nonnull glue_objc_msg_lookup_super_stret PPC_PARAMS(struct objc_super *_Nonnull super, SEL _Nonnull selector);
extern Class _Nullable glue_objc_lookUpClass PPC_PARAMS(const char *_Nonnull name);
extern Class _Nullable glue_objc_getClass PPC_PARAMS(const char *_Nonnull name);
extern Class _Nonnull glue_objc_getRequiredClass PPC_PARAMS(const char *_Nonnull name);
extern Class _Nullable glue_objc_lookup_class PPC_PARAMS(const char *_Nonnull name);
extern Class _Nonnull glue_objc_get_class PPC_PARAMS(const char *_Nonnull name);
extern void glue_objc_exception_throw PPC_PARAMS(id _Nonnull object);
extern int glue_objc_sync_enter PPC_PARAMS(id _Nullable object);
extern int glue_objc_sync_exit PPC_PARAMS(id _Nullable object);
extern id _Nullable glue_objc_getProperty PPC_PARAMS(id _Nonnull self, SEL _Nonnull _cmd, ptrdiff_t offset, bool atomic);
extern void glue_objc_setProperty PPC_PARAMS(id _Nonnull self, SEL _Nonnull _cmd, ptrdiff_t offset, id _Nullable value, bool atomic, signed char copy);
extern void glue_objc_getPropertyStruct PPC_PARAMS(void *_Nonnull dest, const void *_Nonnull src, ptrdiff_t size, bool atomic, bool strong);
extern void glue_objc_setPropertyStruct PPC_PARAMS(void *_Nonnull dest, const void *_Nonnull src, ptrdiff_t size, bool atomic, bool strong);
extern void glue_objc_enumerationMutation PPC_PARAMS(id _Nonnull object);
extern int glue___gnu_objc_personality PPC_PARAMS(int version, int actions, uint64_t *_Nonnull exClass, void *_Nonnull ex, void *_Nonnull ctx);
extern id _Nullable glue_objc_retain PPC_PARAMS(id _Nullable object);
extern id _Nullable glue_objc_retainBlock PPC_PARAMS(id _Nullable block);
extern id _Nullable glue_objc_retainAutorelease PPC_PARAMS(id _Nullable object);
extern void glue_objc_release PPC_PARAMS(id _Nullable object);
extern id _Nullable glue_objc_autorelease PPC_PARAMS(id _Nullable object);
extern id _Nullable glue_objc_autoreleaseReturnValue PPC_PARAMS(id _Nullable object);
extern id _Nullable glue_objc_retainAutoreleaseReturnValue PPC_PARAMS(id _Nullable object);
extern id _Nullable glue_objc_retainAutoreleasedReturnValue PPC_PARAMS(id _Nullable object);
extern id _Nullable glue_objc_storeStrong PPC_PARAMS(id _Nullable *_Nonnull object, id _Nullable value);
extern id _Nullable glue_objc_storeWeak PPC_PARAMS(id _Nullable *_Nonnull object, id _Nullable value);
extern id _Nullable glue_objc_loadWeakRetained PPC_PARAMS(id _Nullable *_Nonnull object);
extern id _Nullable glue_objc_initWeak PPC_PARAMS(id _Nullable *_Nonnull object, id _Nullable value);
extern void glue_objc_destroyWeak PPC_PARAMS(id _Nullable *_Nonnull object);
extern id _Nullable glue_objc_loadWeak PPC_PARAMS(id _Nullable *_Nonnull object);
extern void glue_objc_copyWeak PPC_PARAMS(id _Nullable *_Nonnull dest, id _Nullable *_Nonnull src);
extern void glue_objc_moveWeak PPC_PARAMS(id _Nullable *_Nonnull dest, id _Nullable *_Nonnull src);
extern SEL _Nonnull glue_sel_registerName PPC_PARAMS(const char *_Nonnull name);
extern const char *_Nonnull glue_sel_getName PPC_PARAMS(SEL _Nonnull selector);
extern bool glue_sel_isEqual PPC_PARAMS(SEL _Nonnull selector1, SEL _Nonnull selector2);
extern Class _Nonnull glue_objc_allocateClassPair PPC_PARAMS(Class _Nullable superclass, const char *_Nonnull name, size_t extraBytes);
extern void glue_objc_registerClassPair PPC_PARAMS(Class _Nonnull class);
extern unsigned int glue_objc_getClassList PPC_PARAMS(Class _Nonnull *_Nullable buffer, unsigned int count);
extern Class _Nonnull *_Nonnull glue_objc_copyClassList PPC_PARAMS(unsigned int *_Nullable length);
extern bool glue_class_isMetaClass PPC_PARAMS(Class _Nullable class);
extern const char *_Nullable glue_class_getName PPC_PARAMS(Class _Nullable class);
extern Class _Nullable glue_class_getSuperclass PPC_PARAMS(Class _Nullable class);
extern unsigned long glue_class_getInstanceSize PPC_PARAMS(Class _Nullable class);
extern bool glue_class_respondsToSelector PPC_PARAMS(Class _Nullable class, SEL _Nonnull selector);
extern bool glue_class_conformsToProtocol PPC_PARAMS(Class _Nullable class, Protocol *_Nonnull p);
extern IMP _Nullable glue_class_getMethodImplementation PPC_PARAMS(Class _Nullable class, SEL _Nonnull selector);
extern IMP _Nullable glue_class_getMethodImplementation_stret PPC_PARAMS(Class _Nullable class, SEL _Nonnull selector);
extern Method _Nullable glue_class_getInstanceMethod PPC_PARAMS(Class _Nullable class, SEL _Nonnull selector);
extern bool glue_class_addMethod PPC_PARAMS(Class _Nonnull class, SEL _Nonnull selector, IMP _Nonnull implementation, const char *_Nullable typeEncoding);
extern IMP _Nullable glue_class_replaceMethod PPC_PARAMS(Class _Nonnull class, SEL _Nonnull selector, IMP _Nonnull implementation, const char *_Nullable typeEncoding);
extern Class _Nullable glue_object_getClass PPC_PARAMS(id _Nullable object);
extern Class _Nullable glue_object_setClass PPC_PARAMS(id _Nullable object, Class _Nonnull class);
extern const char *_Nullable glue_object_getClassName PPC_PARAMS(id _Nullable object);
extern const char *_Nonnull glue_protocol_getName PPC_PARAMS(Protocol *_Nonnull protocol);
extern bool glue_protocol_isEqual PPC_PARAMS(Protocol *_Nonnull protocol1, Protocol *_Nonnull protocol2);
extern bool glue_protocol_conformsToProtocol PPC_PARAMS(Protocol *_Nonnull protocol1, Protocol *_Nonnull protocol2);
extern _Nullable objc_uncaught_exception_handler glue_objc_setUncaughtExceptionHandler PPC_PARAMS(objc_uncaught_exception_handler _Nullable handler);
extern void glue_objc_setForwardHandler PPC_PARAMS(IMP _Nullable forward, IMP _Nullable stretForward);
extern void glue_objc_setEnumerationMutationHandler PPC_PARAMS(objc_enumeration_mutation_handler _Nullable hadler);
extern id _Nullable glue_objc_constructInstance PPC_PARAMS(Class _Nullable class, void *_Nullable bytes);
extern void glue_objc_deinit(void);
extern Ivar _Nullable *_Nullable glue_class_copyIvarList PPC_PARAMS(Class _Nullable class, unsigned int *_Nullable outCount);
extern const char *_Nonnull glue_ivar_getName PPC_PARAMS(Ivar _Nonnull ivar);
extern const char *_Nonnull glue_ivar_getTypeEncoding PPC_PARAMS(Ivar _Nonnull ivar);
extern ptrdiff_t glue_ivar_getOffset PPC_PARAMS(Ivar _Nonnull ivar);
extern Method _Nullable *_Nullable glue_class_copyMethodList PPC_PARAMS(Class _Nullable class, unsigned int *_Nullable outCount);
extern SEL _Nonnull glue_method_getName PPC_PARAMS(Method _Nonnull method);
extern const char *_Nullable glue_method_getTypeEncoding PPC_PARAMS(Method _Nonnull method);
extern objc_property_t _Nullable *_Nullable glue_class_copyPropertyList PPC_PARAMS(Class _Nullable class, unsigned int *_Nullable outCount);
extern const char *_Nonnull glue_property_getName PPC_PARAMS(objc_property_t _Nonnull property);
extern char *_Nullable glue_property_copyAttributeValue PPC_PARAMS(objc_property_t _Nonnull property, const char *_Nonnull name);
extern void *_Nullable glue_objc_destructInstance PPC_PARAMS(id _Nullable object);
extern void *_Null_unspecified glue_objc_autoreleasePoolPush(void);
extern void glue_objc_autoreleasePoolPop PPC_PARAMS(void *_Null_unspecified pool);
extern id _Nullable glue__objc_rootAutorelease PPC_PARAMS(id _Nullable object);
extern struct objc_hashtable *_Nonnull glue_objc_hashtable_new PPC_PARAMS(objc_hashtable_hash_func hash, objc_hashtable_equal_func equal, uint32_t size);
extern void glue_objc_hashtable_set PPC_PARAMS(struct objc_hashtable *_Nonnull table, const void *_Nonnull key, const void *_Nonnull object);
extern void *_Nullable glue_objc_hashtable_get PPC_PARAMS(struct objc_hashtable *_Nonnull table, const void *_Nonnull key);
extern void glue_objc_hashtable_delete PPC_PARAMS(struct objc_hashtable *_Nonnull table, const void *_Nonnull key);
extern void glue_objc_hashtable_free PPC_PARAMS(struct objc_hashtable *_Nonnull table);
extern void glue_objc_setTaggedPointerSecret PPC_PARAMS(uintptr_t secret);
extern int glue_objc_registerTaggedPointerClass PPC_PARAMS(Class _Nonnull class);
extern bool glue_object_isTaggedPointer PPC_PARAMS(id _Nullable object);
extern uintptr_t glue_object_getTaggedPointerValue PPC_PARAMS(id _Nonnull object);
extern id _Nullable glue_objc_createTaggedPointer PPC_PARAMS(int class, uintptr_t value);
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<














































































































































































































































Deleted src/runtime/amiga-glue.m version [8e4bfceffc].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
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
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

/* This file is automatically generated from amiga-library.xml */

#include "config.h"

#import "amiga-glue.h"

#ifdef OF_MORPHOS
/* All __saveds functions in this file need to use the SysV ABI */
__asm__ (
    ".section .text\n"
    ".align 2\n"
    "__restore_r13:\n"
    "	lwz	%r13, 44(%r12)\n"
    "	blr\n"
);
#endif

bool __saveds
glue_objc_init PPC_PARAMS(unsigned int version, struct objc_libc *libc)
{
	M68K_ARG(unsigned int, version, d0)
	M68K_ARG(struct objc_libc *, libc, a0)

	return objc_init(version, libc);
}

void __saveds
glue___objc_exec_class PPC_PARAMS(struct objc_module *_Nonnull module)
{
	M68K_ARG(struct objc_module *_Nonnull, module, a0)

	__objc_exec_class(module);
}

IMP _Nonnull __saveds
glue_objc_msg_lookup PPC_PARAMS(id _Nullable object, SEL _Nonnull selector)
{
	M68K_ARG(id _Nullable, object, a0)
	M68K_ARG(SEL _Nonnull, selector, a1)

	return objc_msg_lookup(object, selector);
}

IMP _Nonnull __saveds
glue_objc_msg_lookup_stret PPC_PARAMS(id _Nullable object, SEL _Nonnull selector)
{
	M68K_ARG(id _Nullable, object, a0)
	M68K_ARG(SEL _Nonnull, selector, a1)

	return objc_msg_lookup_stret(object, selector);
}

IMP _Nonnull __saveds
glue_objc_msg_lookup_super PPC_PARAMS(struct objc_super *_Nonnull super, SEL _Nonnull selector)
{
	M68K_ARG(struct objc_super *_Nonnull, super, a0)
	M68K_ARG(SEL _Nonnull, selector, a1)

	return objc_msg_lookup_super(super, selector);
}

IMP _Nonnull __saveds
glue_objc_msg_lookup_super_stret PPC_PARAMS(struct objc_super *_Nonnull super, SEL _Nonnull selector)
{
	M68K_ARG(struct objc_super *_Nonnull, super, a0)
	M68K_ARG(SEL _Nonnull, selector, a1)

	return objc_msg_lookup_super_stret(super, selector);
}

Class _Nullable __saveds
glue_objc_lookUpClass PPC_PARAMS(const char *_Nonnull name)
{
	M68K_ARG(const char *_Nonnull, name, a0)

	return objc_lookUpClass(name);
}

Class _Nullable __saveds
glue_objc_getClass PPC_PARAMS(const char *_Nonnull name)
{
	M68K_ARG(const char *_Nonnull, name, a0)

	return objc_getClass(name);
}

Class _Nonnull __saveds
glue_objc_getRequiredClass PPC_PARAMS(const char *_Nonnull name)
{
	M68K_ARG(const char *_Nonnull, name, a0)

	return objc_getRequiredClass(name);
}

Class _Nullable __saveds
glue_objc_lookup_class PPC_PARAMS(const char *_Nonnull name)
{
	M68K_ARG(const char *_Nonnull, name, a0)

	return objc_lookup_class(name);
}

Class _Nonnull __saveds
glue_objc_get_class PPC_PARAMS(const char *_Nonnull name)
{
	M68K_ARG(const char *_Nonnull, name, a0)

	return objc_get_class(name);
}

void __saveds
glue_objc_exception_throw PPC_PARAMS(id _Nonnull object)
{
	M68K_ARG(id _Nonnull, object, a0)

	objc_exception_throw(object);
}

int __saveds
glue_objc_sync_enter PPC_PARAMS(id _Nullable object)
{
	M68K_ARG(id _Nullable, object, a0)

	return objc_sync_enter(object);
}

int __saveds
glue_objc_sync_exit PPC_PARAMS(id _Nullable object)
{
	M68K_ARG(id _Nullable, object, a0)

	return objc_sync_exit(object);
}

id _Nullable __saveds
glue_objc_getProperty PPC_PARAMS(id _Nonnull self, SEL _Nonnull _cmd, ptrdiff_t offset, bool atomic)
{
	M68K_ARG(id _Nonnull, self, a0)
	M68K_ARG(SEL _Nonnull, _cmd, a1)
	M68K_ARG(ptrdiff_t, offset, d0)
	M68K_ARG(bool, atomic, d1)

	return objc_getProperty(self, _cmd, offset, atomic);
}

void __saveds
glue_objc_setProperty PPC_PARAMS(id _Nonnull self, SEL _Nonnull _cmd, ptrdiff_t offset, id _Nullable value, bool atomic, signed char copy)
{
	M68K_ARG(id _Nonnull, self, a0)
	M68K_ARG(SEL _Nonnull, _cmd, a1)
	M68K_ARG(ptrdiff_t, offset, d0)
	M68K_ARG(id _Nullable, value, a2)
	M68K_ARG(bool, atomic, d1)
	M68K_ARG(signed char, copy, d2)

	objc_setProperty(self, _cmd, offset, value, atomic, copy);
}

void __saveds
glue_objc_getPropertyStruct PPC_PARAMS(void *_Nonnull dest, const void *_Nonnull src, ptrdiff_t size, bool atomic, bool strong)
{
	M68K_ARG(void *_Nonnull, dest, a0)
	M68K_ARG(const void *_Nonnull, src, a1)
	M68K_ARG(ptrdiff_t, size, d0)
	M68K_ARG(bool, atomic, d1)
	M68K_ARG(bool, strong, d2)

	objc_getPropertyStruct(dest, src, size, atomic, strong);
}

void __saveds
glue_objc_setPropertyStruct PPC_PARAMS(void *_Nonnull dest, const void *_Nonnull src, ptrdiff_t size, bool atomic, bool strong)
{
	M68K_ARG(void *_Nonnull, dest, a0)
	M68K_ARG(const void *_Nonnull, src, a1)
	M68K_ARG(ptrdiff_t, size, d0)
	M68K_ARG(bool, atomic, d1)
	M68K_ARG(bool, strong, d2)

	objc_setPropertyStruct(dest, src, size, atomic, strong);
}

void __saveds
glue_objc_enumerationMutation PPC_PARAMS(id _Nonnull object)
{
	M68K_ARG(id _Nonnull, object, a0)

	objc_enumerationMutation(object);
}

int __saveds
glue___gnu_objc_personality PPC_PARAMS(int version, int actions, uint64_t *_Nonnull exClass, void *_Nonnull ex, void *_Nonnull ctx)
{
	M68K_ARG(int, version, d0)
	M68K_ARG(int, actions, d1)
	M68K_ARG(uint64_t *_Nonnull, exClass, d2)
	M68K_ARG(void *_Nonnull, ex, a0)
	M68K_ARG(void *_Nonnull, ctx, a1)

	return __gnu_objc_personality(version, actions, exClass, ex, ctx);
}

id _Nullable __saveds
glue_objc_retain PPC_PARAMS(id _Nullable object)
{
	M68K_ARG(id _Nullable, object, a0)

	return objc_retain(object);
}

id _Nullable __saveds
glue_objc_retainBlock PPC_PARAMS(id _Nullable block)
{
	M68K_ARG(id _Nullable, block, a0)

	return objc_retainBlock(block);
}

id _Nullable __saveds
glue_objc_retainAutorelease PPC_PARAMS(id _Nullable object)
{
	M68K_ARG(id _Nullable, object, a0)

	return objc_retainAutorelease(object);
}

void __saveds
glue_objc_release PPC_PARAMS(id _Nullable object)
{
	M68K_ARG(id _Nullable, object, a0)

	objc_release(object);
}

id _Nullable __saveds
glue_objc_autorelease PPC_PARAMS(id _Nullable object)
{
	M68K_ARG(id _Nullable, object, a0)

	return objc_autorelease(object);
}

id _Nullable __saveds
glue_objc_autoreleaseReturnValue PPC_PARAMS(id _Nullable object)
{
	M68K_ARG(id _Nullable, object, a0)

	return objc_autoreleaseReturnValue(object);
}

id _Nullable __saveds
glue_objc_retainAutoreleaseReturnValue PPC_PARAMS(id _Nullable object)
{
	M68K_ARG(id _Nullable, object, a0)

	return objc_retainAutoreleaseReturnValue(object);
}

id _Nullable __saveds
glue_objc_retainAutoreleasedReturnValue PPC_PARAMS(id _Nullable object)
{
	M68K_ARG(id _Nullable, object, a0)

	return objc_retainAutoreleasedReturnValue(object);
}

id _Nullable __saveds
glue_objc_storeStrong PPC_PARAMS(id _Nullable *_Nonnull object, id _Nullable value)
{
	M68K_ARG(id _Nullable *_Nonnull, object, a0)
	M68K_ARG(id _Nullable, value, a1)

	return objc_storeStrong(object, value);
}

id _Nullable __saveds
glue_objc_storeWeak PPC_PARAMS(id _Nullable *_Nonnull object, id _Nullable value)
{
	M68K_ARG(id _Nullable *_Nonnull, object, a0)
	M68K_ARG(id _Nullable, value, a1)

	return objc_storeWeak(object, value);
}

id _Nullable __saveds
glue_objc_loadWeakRetained PPC_PARAMS(id _Nullable *_Nonnull object)
{
	M68K_ARG(id _Nullable *_Nonnull, object, a0)

	return objc_loadWeakRetained(object);
}

id _Nullable __saveds
glue_objc_initWeak PPC_PARAMS(id _Nullable *_Nonnull object, id _Nullable value)
{
	M68K_ARG(id _Nullable *_Nonnull, object, a0)
	M68K_ARG(id _Nullable, value, a1)

	return objc_initWeak(object, value);
}

void __saveds
glue_objc_destroyWeak PPC_PARAMS(id _Nullable *_Nonnull object)
{
	M68K_ARG(id _Nullable *_Nonnull, object, a0)

	objc_destroyWeak(object);
}

id _Nullable __saveds
glue_objc_loadWeak PPC_PARAMS(id _Nullable *_Nonnull object)
{
	M68K_ARG(id _Nullable *_Nonnull, object, a0)

	return objc_loadWeak(object);
}

void __saveds
glue_objc_copyWeak PPC_PARAMS(id _Nullable *_Nonnull dest, id _Nullable *_Nonnull src)
{
	M68K_ARG(id _Nullable *_Nonnull, dest, a0)
	M68K_ARG(id _Nullable *_Nonnull, src, a1)

	objc_copyWeak(dest, src);
}

void __saveds
glue_objc_moveWeak PPC_PARAMS(id _Nullable *_Nonnull dest, id _Nullable *_Nonnull src)
{
	M68K_ARG(id _Nullable *_Nonnull, dest, a0)
	M68K_ARG(id _Nullable *_Nonnull, src, a1)

	objc_moveWeak(dest, src);
}

SEL _Nonnull __saveds
glue_sel_registerName PPC_PARAMS(const char *_Nonnull name)
{
	M68K_ARG(const char *_Nonnull, name, a0)

	return sel_registerName(name);
}

const char *_Nonnull __saveds
glue_sel_getName PPC_PARAMS(SEL _Nonnull selector)
{
	M68K_ARG(SEL _Nonnull, selector, a0)

	return sel_getName(selector);
}

bool __saveds
glue_sel_isEqual PPC_PARAMS(SEL _Nonnull selector1, SEL _Nonnull selector2)
{
	M68K_ARG(SEL _Nonnull, selector1, a0)
	M68K_ARG(SEL _Nonnull, selector2, a1)

	return sel_isEqual(selector1, selector2);
}

Class _Nonnull __saveds
glue_objc_allocateClassPair PPC_PARAMS(Class _Nullable superclass, const char *_Nonnull name, size_t extraBytes)
{
	M68K_ARG(Class _Nullable, superclass, a0)
	M68K_ARG(const char *_Nonnull, name, a1)
	M68K_ARG(size_t, extraBytes, d0)

	return objc_allocateClassPair(superclass, name, extraBytes);
}

void __saveds
glue_objc_registerClassPair PPC_PARAMS(Class _Nonnull class)
{
	M68K_ARG(Class _Nonnull, class, a0)

	objc_registerClassPair(class);
}

unsigned int __saveds
glue_objc_getClassList PPC_PARAMS(Class _Nonnull *_Nullable buffer, unsigned int count)
{
	M68K_ARG(Class _Nonnull *_Nullable, buffer, a0)
	M68K_ARG(unsigned int, count, d0)

	return objc_getClassList(buffer, count);
}

Class _Nonnull *_Nonnull __saveds
glue_objc_copyClassList PPC_PARAMS(unsigned int *_Nullable length)
{
	M68K_ARG(unsigned int *_Nullable, length, a0)

	return objc_copyClassList(length);
}

bool __saveds
glue_class_isMetaClass PPC_PARAMS(Class _Nullable class)
{
	M68K_ARG(Class _Nullable, class, a0)

	return class_isMetaClass(class);
}

const char *_Nullable __saveds
glue_class_getName PPC_PARAMS(Class _Nullable class)
{
	M68K_ARG(Class _Nullable, class, a0)

	return class_getName(class);
}

Class _Nullable __saveds
glue_class_getSuperclass PPC_PARAMS(Class _Nullable class)
{
	M68K_ARG(Class _Nullable, class, a0)

	return class_getSuperclass(class);
}

unsigned long __saveds
glue_class_getInstanceSize PPC_PARAMS(Class _Nullable class)
{
	M68K_ARG(Class _Nullable, class, a0)

	return class_getInstanceSize(class);
}

bool __saveds
glue_class_respondsToSelector PPC_PARAMS(Class _Nullable class, SEL _Nonnull selector)
{
	M68K_ARG(Class _Nullable, class, a0)
	M68K_ARG(SEL _Nonnull, selector, a1)

	return class_respondsToSelector(class, selector);
}

bool __saveds
glue_class_conformsToProtocol PPC_PARAMS(Class _Nullable class, Protocol *_Nonnull p)
{
	M68K_ARG(Class _Nullable, class, a0)
	M68K_ARG(Protocol *_Nonnull, p, a1)

	return class_conformsToProtocol(class, p);
}

IMP _Nullable __saveds
glue_class_getMethodImplementation PPC_PARAMS(Class _Nullable class, SEL _Nonnull selector)
{
	M68K_ARG(Class _Nullable, class, a0)
	M68K_ARG(SEL _Nonnull, selector, a1)

	return class_getMethodImplementation(class, selector);
}

IMP _Nullable __saveds
glue_class_getMethodImplementation_stret PPC_PARAMS(Class _Nullable class, SEL _Nonnull selector)
{
	M68K_ARG(Class _Nullable, class, a0)
	M68K_ARG(SEL _Nonnull, selector, a1)

	return class_getMethodImplementation_stret(class, selector);
}

Method _Nullable __saveds
glue_class_getInstanceMethod PPC_PARAMS(Class _Nullable class, SEL _Nonnull selector)
{
	M68K_ARG(Class _Nullable, class, a0)
	M68K_ARG(SEL _Nonnull, selector, a1)

	return class_getInstanceMethod(class, selector);
}

bool __saveds
glue_class_addMethod PPC_PARAMS(Class _Nonnull class, SEL _Nonnull selector, IMP _Nonnull implementation, const char *_Nullable typeEncoding)
{
	M68K_ARG(Class _Nonnull, class, a0)
	M68K_ARG(SEL _Nonnull, selector, a1)
	M68K_ARG(IMP _Nonnull, implementation, a2)
	M68K_ARG(const char *_Nullable, typeEncoding, a3)

	return class_addMethod(class, selector, implementation, typeEncoding);
}

IMP _Nullable __saveds
glue_class_replaceMethod PPC_PARAMS(Class _Nonnull class, SEL _Nonnull selector, IMP _Nonnull implementation, const char *_Nullable typeEncoding)
{
	M68K_ARG(Class _Nonnull, class, a0)
	M68K_ARG(SEL _Nonnull, selector, a1)
	M68K_ARG(IMP _Nonnull, implementation, a2)
	M68K_ARG(const char *_Nullable, typeEncoding, a3)

	return class_replaceMethod(class, selector, implementation, typeEncoding);
}

Class _Nullable __saveds
glue_object_getClass PPC_PARAMS(id _Nullable object)
{
	M68K_ARG(id _Nullable, object, a0)

	return object_getClass(object);
}

Class _Nullable __saveds
glue_object_setClass PPC_PARAMS(id _Nullable object, Class _Nonnull class)
{
	M68K_ARG(id _Nullable, object, a0)
	M68K_ARG(Class _Nonnull, class, a1)

	return object_setClass(object, class);
}

const char *_Nullable __saveds
glue_object_getClassName PPC_PARAMS(id _Nullable object)
{
	M68K_ARG(id _Nullable, object, a0)

	return object_getClassName(object);
}

const char *_Nonnull __saveds
glue_protocol_getName PPC_PARAMS(Protocol *_Nonnull protocol)
{
	M68K_ARG(Protocol *_Nonnull, protocol, a0)

	return protocol_getName(protocol);
}

bool __saveds
glue_protocol_isEqual PPC_PARAMS(Protocol *_Nonnull protocol1, Protocol *_Nonnull protocol2)
{
	M68K_ARG(Protocol *_Nonnull, protocol1, a0)
	M68K_ARG(Protocol *_Nonnull, protocol2, a1)

	return protocol_isEqual(protocol1, protocol2);
}

bool __saveds
glue_protocol_conformsToProtocol PPC_PARAMS(Protocol *_Nonnull protocol1, Protocol *_Nonnull protocol2)
{
	M68K_ARG(Protocol *_Nonnull, protocol1, a0)
	M68K_ARG(Protocol *_Nonnull, protocol2, a1)

	return protocol_conformsToProtocol(protocol1, protocol2);
}

_Nullable objc_uncaught_exception_handler __saveds
glue_objc_setUncaughtExceptionHandler PPC_PARAMS(objc_uncaught_exception_handler _Nullable handler)
{
	M68K_ARG(objc_uncaught_exception_handler _Nullable, handler, a0)

	return objc_setUncaughtExceptionHandler(handler);
}

void __saveds
glue_objc_setForwardHandler PPC_PARAMS(IMP _Nullable forward, IMP _Nullable stretForward)
{
	M68K_ARG(IMP _Nullable, forward, a0)
	M68K_ARG(IMP _Nullable, stretForward, a1)

	objc_setForwardHandler(forward, stretForward);
}

void __saveds
glue_objc_setEnumerationMutationHandler PPC_PARAMS(objc_enumeration_mutation_handler _Nullable hadler)
{
	M68K_ARG(objc_enumeration_mutation_handler _Nullable, hadler, a0)

	objc_setEnumerationMutationHandler(hadler);
}

id _Nullable __saveds
glue_objc_constructInstance PPC_PARAMS(Class _Nullable class, void *_Nullable bytes)
{
	M68K_ARG(Class _Nullable, class, a0)
	M68K_ARG(void *_Nullable, bytes, a1)

	return objc_constructInstance(class, bytes);
}

void __saveds
glue_objc_deinit(void)
{
	objc_deinit();
}

Ivar _Nullable *_Nullable __saveds
glue_class_copyIvarList PPC_PARAMS(Class _Nullable class, unsigned int *_Nullable outCount)
{
	M68K_ARG(Class _Nullable, class, a0)
	M68K_ARG(unsigned int *_Nullable, outCount, a1)

	return class_copyIvarList(class, outCount);
}

const char *_Nonnull __saveds
glue_ivar_getName PPC_PARAMS(Ivar _Nonnull ivar)
{
	M68K_ARG(Ivar _Nonnull, ivar, a0)

	return ivar_getName(ivar);
}

const char *_Nonnull __saveds
glue_ivar_getTypeEncoding PPC_PARAMS(Ivar _Nonnull ivar)
{
	M68K_ARG(Ivar _Nonnull, ivar, a0)

	return ivar_getTypeEncoding(ivar);
}

ptrdiff_t __saveds
glue_ivar_getOffset PPC_PARAMS(Ivar _Nonnull ivar)
{
	M68K_ARG(Ivar _Nonnull, ivar, a0)

	return ivar_getOffset(ivar);
}

Method _Nullable *_Nullable __saveds
glue_class_copyMethodList PPC_PARAMS(Class _Nullable class, unsigned int *_Nullable outCount)
{
	M68K_ARG(Class _Nullable, class, a0)
	M68K_ARG(unsigned int *_Nullable, outCount, a1)

	return class_copyMethodList(class, outCount);
}

SEL _Nonnull __saveds
glue_method_getName PPC_PARAMS(Method _Nonnull method)
{
	M68K_ARG(Method _Nonnull, method, a0)

	return method_getName(method);
}

const char *_Nullable __saveds
glue_method_getTypeEncoding PPC_PARAMS(Method _Nonnull method)
{
	M68K_ARG(Method _Nonnull, method, a0)

	return method_getTypeEncoding(method);
}

objc_property_t _Nullable *_Nullable __saveds
glue_class_copyPropertyList PPC_PARAMS(Class _Nullable class, unsigned int *_Nullable outCount)
{
	M68K_ARG(Class _Nullable, class, a0)
	M68K_ARG(unsigned int *_Nullable, outCount, a1)

	return class_copyPropertyList(class, outCount);
}

const char *_Nonnull __saveds
glue_property_getName PPC_PARAMS(objc_property_t _Nonnull property)
{
	M68K_ARG(objc_property_t _Nonnull, property, a0)

	return property_getName(property);
}

char *_Nullable __saveds
glue_property_copyAttributeValue PPC_PARAMS(objc_property_t _Nonnull property, const char *_Nonnull name)
{
	M68K_ARG(objc_property_t _Nonnull, property, a0)
	M68K_ARG(const char *_Nonnull, name, a1)

	return property_copyAttributeValue(property, name);
}

void *_Nullable __saveds
glue_objc_destructInstance PPC_PARAMS(id _Nullable object)
{
	M68K_ARG(id _Nullable, object, a0)

	return objc_destructInstance(object);
}

void *_Null_unspecified __saveds
glue_objc_autoreleasePoolPush(void)
{
	return objc_autoreleasePoolPush();
}

void __saveds
glue_objc_autoreleasePoolPop PPC_PARAMS(void *_Null_unspecified pool)
{
	M68K_ARG(void *_Null_unspecified, pool, a0)

	objc_autoreleasePoolPop(pool);
}

id _Nullable __saveds
glue__objc_rootAutorelease PPC_PARAMS(id _Nullable object)
{
	M68K_ARG(id _Nullable, object, a0)

	return _objc_rootAutorelease(object);
}

struct objc_hashtable *_Nonnull __saveds
glue_objc_hashtable_new PPC_PARAMS(objc_hashtable_hash_func hash, objc_hashtable_equal_func equal, uint32_t size)
{
	M68K_ARG(objc_hashtable_hash_func, hash, a0)
	M68K_ARG(objc_hashtable_equal_func, equal, a1)
	M68K_ARG(uint32_t, size, d0)

	return objc_hashtable_new(hash, equal, size);
}

void __saveds
glue_objc_hashtable_set PPC_PARAMS(struct objc_hashtable *_Nonnull table, const void *_Nonnull key, const void *_Nonnull object)
{
	M68K_ARG(struct objc_hashtable *_Nonnull, table, a0)
	M68K_ARG(const void *_Nonnull, key, a1)
	M68K_ARG(const void *_Nonnull, object, a2)

	objc_hashtable_set(table, key, object);
}

void *_Nullable __saveds
glue_objc_hashtable_get PPC_PARAMS(struct objc_hashtable *_Nonnull table, const void *_Nonnull key)
{
	M68K_ARG(struct objc_hashtable *_Nonnull, table, a0)
	M68K_ARG(const void *_Nonnull, key, a1)

	return objc_hashtable_get(table, key);
}

void __saveds
glue_objc_hashtable_delete PPC_PARAMS(struct objc_hashtable *_Nonnull table, const void *_Nonnull key)
{
	M68K_ARG(struct objc_hashtable *_Nonnull, table, a0)
	M68K_ARG(const void *_Nonnull, key, a1)

	objc_hashtable_delete(table, key);
}

void __saveds
glue_objc_hashtable_free PPC_PARAMS(struct objc_hashtable *_Nonnull table)
{
	M68K_ARG(struct objc_hashtable *_Nonnull, table, a0)

	objc_hashtable_free(table);
}

void __saveds
glue_objc_setTaggedPointerSecret PPC_PARAMS(uintptr_t secret)
{
	M68K_ARG(uintptr_t, secret, d0)

	objc_setTaggedPointerSecret(secret);
}

int __saveds
glue_objc_registerTaggedPointerClass PPC_PARAMS(Class _Nonnull class)
{
	M68K_ARG(Class _Nonnull, class, a0)

	return objc_registerTaggedPointerClass(class);
}

bool __saveds
glue_object_isTaggedPointer PPC_PARAMS(id _Nullable object)
{
	M68K_ARG(id _Nullable, object, a0)

	return object_isTaggedPointer(object);
}

uintptr_t __saveds
glue_object_getTaggedPointerValue PPC_PARAMS(id _Nonnull object)
{
	M68K_ARG(id _Nonnull, object, a0)

	return object_getTaggedPointerValue(object);
}

id _Nullable __saveds
glue_objc_createTaggedPointer PPC_PARAMS(int class, uintptr_t value)
{
	M68K_ARG(int, class, d0)
	M68K_ARG(uintptr_t, value, d1)

	return objc_createTaggedPointer(class, value);
}
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































Deleted src/runtime/amiga-library.m version [db6b5f4a82].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
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
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#import "ObjFWRT.h"
#import "private.h"

#import "amiga-glue.h"

#include <exec/libraries.h>
#include <exec/nodes.h>
#include <exec/resident.h>
#include <proto/exec.h>

#define CONCAT_VERSION2(major, minor) #major "." #minor
#define CONCAT_VERSION(major, minor) CONCAT_VERSION2(major, minor)
#define VERSION_STRING CONCAT_VERSION(OBJFWRT_LIB_MAJOR, OBJFWRT_LIB_MINOR)

#if defined(OF_AMIGAOS_M68K)
# define DATA_OFFSET 0x7FFE
#elif defined(OF_MORPHOS)
# define DATA_OFFSET 0x8000
#endif

#ifdef OF_AMIGAOS_M68K
# define OBJC_M68K_REG(reg) __asm__(#reg)
#else
# define OBJC_M68K_REG(reg)
#endif

/* This always needs to be the first thing in the file. */
int
_start(void)
{
	return -1;
}

#ifdef OF_AMIGAOS_M68K
void
__init_eh(void)
{
}
#endif

struct ObjFWRTBase {
	struct Library library;
	void *segList;
	struct ObjFWRTBase *parent;
	char *dataSeg;
	bool initialized;
};

#ifdef OF_AMIGAOS_M68K
extern uintptr_t __CTOR_LIST__[];
extern const void *_EH_FRAME_BEGINS__;
extern void *_EH_FRAME_OBJECTS__;
#endif

#ifdef OF_MORPHOS
const ULONG __abox__ = 1;
#endif
struct ExecBase *SysBase;
struct objc_libc libc;

#if defined(OF_AMIGAOS_M68K)
__asm__ (
    ".text\n"
    ".globl ___restore_a4\n"
    ".align 1\n"
    "___restore_a4:\n"
    "	movea.l	42(a6), a4\n"
    "	rts"
);
#elif defined(OF_MORPHOS)
/* All __saveds functions in this file need to use the M68K ABI */
__asm__ (
    ".section .text\n"
    ".align 2\n"
    "__restore_r13:\n"
    "	lwz	%r13, 56(%r2)\n"
    "	lwz	%r13, 44(%r13)\n"
    "	blr\n"
);
#endif

static OF_INLINE char *
getDataSeg(void)
{
	char *dataSeg;

#if defined(OF_AMIGAOS_M68K)
	__asm__ (
	    "move.l	#___a4_init, %0"
	    : "=r"(dataSeg)
	);
#elif defined(OF_MORPHOS)
	__asm__ (
	    "lis	%0, __r13_init@ha\n\t"
	    "la		%0, __r13_init@l(%0)"
	    : "=r"(dataSeg)
	);
#endif

	return dataSeg;
}

static OF_INLINE size_t
getDataSize(void)
{
	size_t dataSize;

#if defined(OF_AMIGAOS_M68K)
	__asm__ (
	    "move.l	#___data_size, %0\n\t"
	    "add.l	#___bss_size, %0"
	    : "=r"(dataSize)
	);
#elif defined(OF_MORPHOS)
	__asm__ (
	    "lis	%0, __sdata_size@ha\n\t"
	    "la		%0, __sdata_size@l(%0)\n\t"
	    "lis	%%r9, __sbss_size@ha\n\t"
	    "la		%%r9, __sbss_size@l(%%r9)\n\t"
	    "add	%0, %0, %%r9"
	    : "=r"(dataSize)
	    :: "r9"
	);
#endif

	return dataSize;
}

static OF_INLINE size_t *
getDataDataRelocs(void)
{
	size_t *dataDataRelocs;

#if defined(OF_AMIGAOS_M68K)
	__asm__ (
	    "move.l	#___datadata_relocs, %0"
	    : "=r"(dataDataRelocs)
	);
#elif defined(OF_MORPHOS)
	__asm__ (
	    "lis	%0, __datadata_relocs@ha\n\t"
	    "la		%0, __datadata_relocs@l(%0)\n\t"
	    : "=r"(dataDataRelocs)
	);
#endif

	return dataDataRelocs;
}

static struct Library *
lib_init(struct ObjFWRTBase *base OBJC_M68K_REG(d0),
    void *segList OBJC_M68K_REG(a0), struct ExecBase *sysBase OBJC_M68K_REG(a6))
{
#if defined(OF_AMIGAOS_M68K)
	__asm__ __volatile__ (
	    "move.l	a6, _SysBase"
	    :: "a"(sysBase)
	);
#elif defined(OF_MORPHOS)
	__asm__ __volatile__ (
	    "lis	%%r9, SysBase@ha\n\t"
	    "stw	%0, SysBase@l(%%r9)"
	    :: "r"(sysBase) : "r9"
	);
#endif

	base->segList = segList;
	base->parent = NULL;
	base->dataSeg = getDataSeg();

	return &base->library;
}

struct Library *__saveds
lib_open(void)
{
	OBJC_M68K_ARG(struct ObjFWRTBase *, base, a6)

	struct ObjFWRTBase *child;
	size_t dataSize, *dataDataRelocs;
	ptrdiff_t displacement;

	if (base->parent != NULL)
		return NULL;

	base->library.lib_OpenCnt++;
	base->library.lib_Flags &= ~LIBF_DELEXP;

	/*
	 * We cannot use malloc here, as that depends on the libc passed from
	 * the application.
	 */
	if ((child = AllocMem(base->library.lib_NegSize +
	    base->library.lib_PosSize, MEMF_ANY)) == NULL) {
		base->library.lib_OpenCnt--;
		return NULL;
	}

	memcpy(child, (char *)base - base->library.lib_NegSize,
	    base->library.lib_NegSize + base->library.lib_PosSize);

	child = (struct ObjFWRTBase *)
	    ((char *)child + base->library.lib_NegSize);
	child->library.lib_OpenCnt = 1;
	child->parent = base;

	dataSize = getDataSize();

	if ((child->dataSeg = AllocMem(dataSize, MEMF_ANY)) == NULL) {
		FreeMem((char *)child - child->library.lib_NegSize,
		    child->library.lib_NegSize + child->library.lib_PosSize);
		base->library.lib_OpenCnt--;
		return NULL;
	}

	memcpy(child->dataSeg, base->dataSeg - DATA_OFFSET, dataSize);

	dataDataRelocs = getDataDataRelocs();
	displacement = child->dataSeg - (base->dataSeg - DATA_OFFSET);

	for (size_t i = 1; i <= dataDataRelocs[0]; i++)
		*(long *)(child->dataSeg + dataDataRelocs[i]) += displacement;

	child->dataSeg += DATA_OFFSET;

	return &child->library;
}

static void *
expunge(struct ObjFWRTBase *base, struct ExecBase *sysBase)
{
#define SysBase sysBase
	void *segList;

	if (base->parent != NULL) {
		base->parent->library.lib_Flags |= LIBF_DELEXP;
		return 0;
	}

	if (base->library.lib_OpenCnt > 0) {
		base->library.lib_Flags |= LIBF_DELEXP;
		return 0;
	}

	segList = base->segList;

	Remove(&base->library.lib_Node);
	FreeMem((char *)base - base->library.lib_NegSize,
	    base->library.lib_NegSize + base->library.lib_PosSize);

	return segList;
#undef SysBase
}

static void *__saveds
lib_expunge(void)
{
	OBJC_M68K_ARG(struct ObjFWRTBase *, base, a6)

	return expunge(base, SysBase);
}

static void *__saveds
lib_close(void)
{
	/*
	 * SysBase becomes invalid during this function, so we store it in
	 * sysBase and add a define to make the inlines use the right one.
	 */
	struct ExecBase *sysBase = SysBase;
#define SysBase sysBase

	OBJC_M68K_ARG(struct ObjFWRTBase *, base, a6)

	if (base->parent != NULL) {
		struct ObjFWRTBase *parent;

#ifdef OF_AMIGAOS_M68K
		if (base->initialized)
			for (void *const *frame = _EH_FRAME_BEGINS__;
			    *frame != NULL;)
				libc.__deregister_frame_info(*frame++);
#endif

		parent = base->parent;

		FreeMem(base->dataSeg - DATA_OFFSET, getDataSize());
		FreeMem((char *)base - base->library.lib_NegSize,
		    base->library.lib_NegSize + base->library.lib_PosSize);

		base = parent;
	}

	if (--base->library.lib_OpenCnt == 0 &&
	    (base->library.lib_Flags & LIBF_DELEXP))
		return expunge(base, sysBase);

	return NULL;
#undef SysBase
}

static void *
lib_null(void)
{
	return NULL;
}

bool
objc_init(unsigned int version, struct objc_libc *libc_)
{
#ifdef OF_AMIGAOS_M68K
	OBJC_M68K_ARG(struct ObjFWRTBase *, base, a6)
#else
	register struct ObjFWRTBase *r12 __asm__("r12");
	struct ObjFWRTBase *base = r12;
#endif
#ifdef OF_MORPHOS
	void *frame;
#endif
	uintptr_t *iter, *iter0;

	if (version > 1)
		return false;

	memcpy(&libc, libc_, sizeof(libc));

#ifdef OF_AMIGAOS_M68K
	for (void *const *frame = _EH_FRAME_OBJECTS__,
	    **object = _EH_FRAME_OBJECTS__; *frame != NULL;)
		libc.__register_frame_info(*frame++, *object++);

	iter0 = &__CTOR_LIST__[1];
#elif defined(OF_MORPHOS)
	__asm__ (
	    "lis	%0, __EH_FRAME_BEGIN__@ha\n\t"
	    "la		%0, __EH_FRAME_BEGIN__@l(%0)\n\t"
	    "lis	%1, __CTOR_LIST__@ha\n\t"
	    "la		%1, __CTOR_LIST__@l(%1)\n\t"
	    : "=r"(frame), "=r"(iter0)
	);

	libc.__register_frame(frame);
#endif

	for (iter = iter0; *iter != 0; iter++);

	while (iter > iter0) {
		void (*ctor)(void) = (void (*)(void))*--iter;
		ctor();
	}

	base->initialized = true;

	return true;
}

void *
malloc(size_t size)
{
	return libc.malloc(size);
}

void *
calloc(size_t count, size_t size)
{
	return libc.calloc(count, size);
}

void *
realloc(void *ptr, size_t size)
{
	return libc.realloc(ptr, size);
}

void
free(void *ptr)
{
	libc.free(ptr);
}

#ifdef HAVE_SJLJ_EXCEPTIONS
int
_Unwind_SjLj_RaiseException(void *ex)
{
	return libc._Unwind_SjLj_RaiseException(ex);
}
#else
int
_Unwind_RaiseException(void *ex)
{
	return libc._Unwind_RaiseException(ex);
}
#endif

void
_Unwind_DeleteException(void *ex)
{
	libc._Unwind_DeleteException(ex);
}

void *
_Unwind_GetLanguageSpecificData(void *ctx)
{
	return libc._Unwind_GetLanguageSpecificData(ctx);
}

uintptr_t
_Unwind_GetRegionStart(void *ctx)
{
	return libc._Unwind_GetRegionStart(ctx);
}

uintptr_t
_Unwind_GetDataRelBase(void *ctx)
{
	return libc._Unwind_GetDataRelBase(ctx);
}

uintptr_t
_Unwind_GetTextRelBase(void *ctx)
{
	return libc._Unwind_GetTextRelBase(ctx);
}

uintptr_t
_Unwind_GetIP(void *ctx)
{
	return libc._Unwind_GetIP(ctx);
}

uintptr_t
_Unwind_GetGR(void *ctx, int gr)
{
	return libc._Unwind_GetGR(ctx, gr);
}

void
_Unwind_SetIP(void *ctx, uintptr_t ip)
{
	libc._Unwind_SetIP(ctx, ip);
}

void
_Unwind_SetGR(void *ctx, int gr, uintptr_t value)
{
	libc._Unwind_SetGR(ctx, gr, value);
}

#ifdef HAVE_SJLJ_EXCEPTIONS
void
_Unwind_SjLj_Resume(void *ex)
{
	libc._Unwind_SjLj_Resume(ex);
}
#else
void
_Unwind_Resume(void *ex)
{
	libc._Unwind_Resume(ex);
}
#endif

#ifdef OF_AMIGAOS_M68K
int
snprintf(char *restrict str, size_t size, const char *restrict fmt, ...)
{
	va_list args;
	int ret;

	va_start(args, fmt);
	ret = vsnprintf(str, size, fmt, args);
	va_end(args);

	return ret;
}

int
vsnprintf(char *restrict str, size_t size, const char *restrict fmt,
    va_list args)
{
	return libc.vsnprintf(str, size, fmt, args);
}
#endif

int
atexit(void (*function)(void))
{
	return libc.atexit(function);
}

void
exit(int status)
{
	libc.exit(status);

	OF_UNREACHABLE
}

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpedantic"
static CONST_APTR functionTable[] = {
#ifdef OF_MORPHOS
	(CONST_APTR)FUNCARRAY_BEGIN,
	(CONST_APTR)FUNCARRAY_32BIT_NATIVE,
#endif
	(CONST_APTR)lib_open,
	(CONST_APTR)lib_close,
	(CONST_APTR)lib_expunge,
	(CONST_APTR)lib_null,
#ifdef OF_MORPHOS
	(CONST_APTR)-1,
	(CONST_APTR)FUNCARRAY_32BIT_SYSTEMV,
#endif
#include "amiga-funcarray.inc"
	(CONST_APTR)-1,
#ifdef OF_MORPHOS
	(CONST_APTR)FUNCARRAY_END
#endif
};
#pragma GCC diagnostic pop

static struct {
	ULONG dataSize;
	CONST_APTR *functionTable;
	ULONG *dataTable;
	struct Library *(*initFunc)(
	    struct ObjFWRTBase *base OBJC_M68K_REG(d0),
	    void *segList OBJC_M68K_REG(a0),
	    struct ExecBase *execBase OBJC_M68K_REG(a6));
} init_table = {
	sizeof(struct ObjFWRTBase),
	functionTable,
	NULL,
	lib_init
};

struct Resident resident = {
	.rt_MatchWord = RTC_MATCHWORD,
	.rt_MatchTag = &resident,
	.rt_EndSkip = &resident + 1,
	.rt_Flags = RTF_AUTOINIT
#ifdef OF_MORPHOS
	    | RTF_PPC | RTF_EXTENDED
#endif
	    ,
	.rt_Version = OBJFWRT_LIB_MAJOR,
	.rt_Type = NT_LIBRARY,
	.rt_Pri = 0,
	.rt_Name = (char *)OBJFWRT_AMIGA_LIB,
	.rt_IdString = (char *)"ObjFWRT " VERSION_STRING
	    " \xA9 2008-2022 Jonathan Schleifer",
	.rt_Init = &init_table,
#ifdef OF_MORPHOS
	.rt_Revision = OBJFWRT_LIB_MINOR,
	.rt_Tags = NULL,
#endif
};

#ifdef OF_MORPHOS
__asm__ (
    ".section .eh_frame, \"aw\"\n"
    ".globl __EH_FRAME_BEGIN__\n"
    ".type __EH_FRAME_BEGIN__, @object\n"
    "__EH_FRAME_BEGIN__:\n"
    ".section .ctors, \"aw\"\n"
    ".globl __CTOR_LIST__\n"
    ".type __CTOR_LIST__, @object\n"
    "__CTOR_LIST__:\n"
    ".section .text"
);
#endif
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































Deleted src/runtime/amiga-library.xml version [f6565586a9].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
<amiga-library version='1.0' base='ObjFWRTBase'>
  <include>ObjFWRT.h</include>
  <include>private.h</include>
  <!-- The following function is only for the linklib. -->
  <function name='objc_init' return-type='bool'>
    <argument name='version' type='unsigned int' m68k-reg='d0'/>
    <argument name='libc' type='struct objc_libc *' m68k-reg='a0'/>
  </function>
  <function name='__objc_exec_class'>
    <argument name='module' type='struct objc_module *_Nonnull' m68k-reg='a0'/>
  </function>
  <function name='objc_msg_lookup' return-type='IMP _Nonnull'>
    <argument name='object' type='id _Nullable' m68k-reg='a0'/>
    <argument name='selector' type='SEL _Nonnull' m68k-reg='a1'/>
  </function>
  <function name='objc_msg_lookup_stret' return-type='IMP _Nonnull'>
    <argument name='object' type='id _Nullable' m68k-reg='a0'/>
    <argument name='selector' type='SEL _Nonnull' m68k-reg='a1'/>
  </function>
  <function name='objc_msg_lookup_super' return-type='IMP _Nonnull'>
    <argument name='super' type='struct objc_super *_Nonnull' m68k-reg='a0'/>
    <argument name='selector' type='SEL _Nonnull' m68k-reg='a1'/>
  </function>
  <function name='objc_msg_lookup_super_stret' return-type='IMP _Nonnull'>
    <argument name='super' type='struct objc_super *_Nonnull' m68k-reg='a0'/>
    <argument name='selector' type='SEL _Nonnull' m68k-reg='a1'/>
  </function>
  <function name='objc_lookUpClass' return-type='Class _Nullable'>
    <argument name='name' type='const char *_Nonnull' m68k-reg='a0'/>
  </function>
  <function name='objc_getClass' return-type='Class _Nullable'>
    <argument name='name' type='const char *_Nonnull' m68k-reg='a0'/>
  </function>
  <function name='objc_getRequiredClass' return-type='Class _Nonnull'>
    <argument name='name' type='const char *_Nonnull' m68k-reg='a0'/>
  </function>
  <function name='objc_lookup_class' return-type='Class _Nullable'>
    <argument name='name' type='const char *_Nonnull' m68k-reg='a0'/>
  </function>
  <function name='objc_get_class' return-type='Class _Nonnull'>
    <argument name='name' type='const char *_Nonnull' m68k-reg='a0'/>
  </function>
  <function name='objc_exception_throw' noreturn='1'>
    <argument name='object' type='id _Nonnull' m68k-reg='a0'/>
  </function>
  <function name='objc_sync_enter' return-type='int'>
    <argument name='object' type='id _Nullable' m68k-reg='a0'/>
  </function>
  <function name='objc_sync_exit' return-type='int'>
    <argument name='object' type='id _Nullable' m68k-reg='a0'/>
  </function>
  <function name='objc_getProperty' return-type='id _Nullable'>
    <argument name='self' type='id _Nonnull' m68k-reg='a0'/>
    <argument name='_cmd' type='SEL _Nonnull' m68k-reg='a1'/>
    <argument name='offset' type='ptrdiff_t' m68k-reg='d0'/>
    <argument name='atomic' type='bool' m68k-reg='d1'/>
  </function>
  <function name='objc_setProperty'>
    <argument name='self' type='id _Nonnull' m68k-reg='a0'/>
    <argument name='_cmd' type='SEL _Nonnull' m68k-reg='a1'/>
    <argument name='offset' type='ptrdiff_t' m68k-reg='d0'/>
    <argument name='value' type='id _Nullable' m68k-reg='a2'/>
    <argument name='atomic' type='bool' m68k-reg='d1'/>
    <argument name='copy' type='signed char' m68k-reg='d2'/>
  </function>
  <function name='objc_getPropertyStruct'>
    <argument name='dest' type='void *_Nonnull' m68k-reg='a0'/>
    <argument name='src' type='const void *_Nonnull' m68k-reg='a1'/>
    <argument name='size' type='ptrdiff_t' m68k-reg='d0'/>
    <argument name='atomic' type='bool' m68k-reg='d1'/>
    <argument name='strong' type='bool' m68k-reg='d2'/>
  </function>
  <function name='objc_setPropertyStruct'>
    <argument name='dest' type='void *_Nonnull' m68k-reg='a0'/>
    <argument name='src' type='const void *_Nonnull' m68k-reg='a1'/>
    <argument name='size' type='ptrdiff_t' m68k-reg='d0'/>
    <argument name='atomic' type='bool' m68k-reg='d1'/>
    <argument name='strong' type='bool' m68k-reg='d2'/>
  </function>
  <function name='objc_enumerationMutation'>
    <argument name='object' type='id _Nonnull' m68k-reg='a0'/>
  </function>
  <function name='__gnu_objc_personality' return-type='int'>
    <argument name='version' type='int' m68k-reg='d0'/>
    <argument name='actions' type='int' m68k-reg='d1'/>
    <argument name='exClass' type='uint64_t *_Nonnull' m68k-reg='d2'/>
    <argument name='ex' type='void *_Nonnull' m68k-reg='a0'/>
    <argument name='ctx' type='void *_Nonnull' m68k-reg='a1'/>
  </function>
  <function name='objc_retain' return-type='id _Nullable'>
    <argument name='object' type='id _Nullable' m68k-reg='a0'/>
  </function>
  <function name='objc_retainBlock' return-type='id _Nullable'>
    <argument name='block' type='id _Nullable' m68k-reg='a0'/>
  </function>
  <function name='objc_retainAutorelease' return-type='id _Nullable'>
    <argument name='object' type='id _Nullable' m68k-reg='a0'/>
  </function>
  <function name='objc_release'>
    <argument name='object' type='id _Nullable' m68k-reg='a0'/>
  </function>
  <function name='objc_autorelease' return-type='id _Nullable'>
    <argument name='object' type='id _Nullable' m68k-reg='a0'/>
  </function>
  <function name='objc_autoreleaseReturnValue' return-type='id _Nullable'>
    <argument name='object' type='id _Nullable' m68k-reg='a0'/>
  </function>
  <function name='objc_retainAutoreleaseReturnValue' return-type='id _Nullable'>
    <argument name='object' type='id _Nullable' m68k-reg='a0'/>
  </function>
  <function name='objc_retainAutoreleasedReturnValue'
            return-type='id _Nullable'>
    <argument name='object' type='id _Nullable' m68k-reg='a0'/>
  </function>
  <function name='objc_storeStrong' return-type='id _Nullable'>
    <argument name='object' type='id _Nullable *_Nonnull' m68k-reg='a0'/>
    <argument name='value' type='id _Nullable' m68k-reg='a1'/>
  </function>
  <function name='objc_storeWeak' return-type='id _Nullable'>
    <argument name='object' type='id _Nullable *_Nonnull' m68k-reg='a0'/>
    <argument name='value' type='id _Nullable' m68k-reg='a1'/>
  </function>
  <function name='objc_loadWeakRetained' return-type='id _Nullable'>
    <argument name='object' type='id _Nullable *_Nonnull' m68k-reg='a0'/>
  </function>
  <function name='objc_initWeak' return-type='id _Nullable'>
    <argument name='object' type='id _Nullable *_Nonnull' m68k-reg='a0'/>
    <argument name='value' type='id _Nullable' m68k-reg='a1'/>
  </function>
  <function name='objc_destroyWeak'>
    <argument name='object' type='id _Nullable *_Nonnull' m68k-reg='a0'/>
  </function>
  <function name='objc_loadWeak' return-type='id _Nullable'>
    <argument name='object' type='id _Nullable *_Nonnull' m68k-reg='a0'/>
  </function>
  <function name='objc_copyWeak'>
    <argument name='dest' type='id _Nullable *_Nonnull' m68k-reg='a0'/>
    <argument name='src' type='id _Nullable *_Nonnull' m68k-reg='a1'/>
  </function>
  <function name='objc_moveWeak'>
    <argument name='dest' type='id _Nullable *_Nonnull' m68k-reg='a0'/>
    <argument name='src' type='id _Nullable *_Nonnull' m68k-reg='a1'/>
  </function>
  <function name='sel_registerName' return-type='SEL _Nonnull'>
    <argument name='name' type='const char *_Nonnull' m68k-reg='a0'/>
  </function>
  <function name='sel_getName' return-type='const char *_Nonnull'>
    <argument name='selector' type='SEL _Nonnull' m68k-reg='a0'/>
  </function>
  <function name='sel_isEqual' return-type='bool'>
    <argument name='selector1' type='SEL _Nonnull' m68k-reg='a0'/>
    <argument name='selector2' type='SEL _Nonnull' m68k-reg='a1'/>
  </function>
  <function name='objc_allocateClassPair' return-type='Class _Nonnull'>
    <argument name='superclass' type='Class _Nullable' m68k-reg='a0'/>
    <argument name='name' type='const char *_Nonnull' m68k-reg='a1'/>
    <argument name='extraBytes' type='size_t' m68k-reg='d0'/>
  </function>
  <function name='objc_registerClassPair'>
    <argument name='class' type='Class _Nonnull' m68k-reg='a0'/>
  </function>
  <function name='objc_getClassList' return-type='unsigned int'>
    <argument name='buffer' type='Class _Nonnull *_Nullable' m68k-reg='a0'/>
    <argument name='count' type='unsigned int' m68k-reg='d0'/>
  </function>
  <function name='objc_copyClassList' return-type='Class _Nonnull *_Nonnull'>
    <argument name='length' type='unsigned int *_Nullable' m68k-reg='a0'/>
  </function>
  <function name='class_isMetaClass' return-type='bool'>
    <argument name='class' type='Class _Nullable' m68k-reg='a0'/>
  </function>
  <function name='class_getName' return-type='const char *_Nullable'>
    <argument name='class' type='Class _Nullable' m68k-reg='a0'/>
  </function>
  <function name='class_getSuperclass' return-type='Class _Nullable'>
    <argument name='class' type='Class _Nullable' m68k-reg='a0'/>
  </function>
  <function name='class_getInstanceSize' return-type='unsigned long'>
    <argument name='class' type='Class _Nullable' m68k-reg='a0'/>
  </function>
  <function name='class_respondsToSelector' return-type='bool'>
    <argument name='class' type='Class _Nullable' m68k-reg='a0'/>
    <argument name='selector' type='SEL _Nonnull' m68k-reg='a1'/>
  </function>
  <function name='class_conformsToProtocol' return-type='bool'>
    <argument name='class' type='Class _Nullable' m68k-reg='a0'/>
    <argument name='p' type='Protocol *_Nonnull' m68k-reg='a1'/>
  </function>
  <function name='class_getMethodImplementation' return-type='IMP _Nullable'>
    <argument name='class' type='Class _Nullable' m68k-reg='a0'/>
    <argument name='selector' type='SEL _Nonnull' m68k-reg='a1'/>
  </function>
  <function name='class_getMethodImplementation_stret'
            return-type='IMP _Nullable'>
    <argument name='class' type='Class _Nullable' m68k-reg='a0'/>
    <argument name='selector' type='SEL _Nonnull' m68k-reg='a1'/>
  </function>
  <function name='class_getInstanceMethod' return-type='Method _Nullable'>
    <argument name='class' type='Class _Nullable' m68k-reg='a0'/>
    <argument name='selector' type='SEL _Nonnull' m68k-reg='a1'/>
  </function>
  <function name='class_addMethod' return-type='bool'>
    <argument name='class' type='Class _Nonnull' m68k-reg='a0'/>
    <argument name='selector' type='SEL _Nonnull' m68k-reg='a1'/>
    <argument name='implementation' type='IMP _Nonnull' m68k-reg='a2'/>
    <argument name='typeEncoding' type='const char *_Nullable' m68k-reg='a3'/>
  </function>
  <function name='class_replaceMethod' return-type='IMP _Nullable'>
    <argument name='class' type='Class _Nonnull' m68k-reg='a0'/>
    <argument name='selector' type='SEL _Nonnull' m68k-reg='a1'/>
    <argument name='implementation' type='IMP _Nonnull' m68k-reg='a2'/>
    <argument name='typeEncoding' type='const char *_Nullable' m68k-reg='a3'/>
  </function>
  <function name='object_getClass' return-type='Class _Nullable'>
    <argument name='object' type='id _Nullable' m68k-reg='a0'/>
  </function>
  <function name='object_setClass' return-type='Class _Nullable'>
    <argument name='object' type='id _Nullable' m68k-reg='a0'/>
    <argument name='class' type='Class _Nonnull' m68k-reg='a1'/>
  </function>
  <function name='object_getClassName' return-type='const char *_Nullable'>
    <argument name='object' type='id _Nullable' m68k-reg='a0'/>
  </function>
  <function name='protocol_getName' return-type='const char *_Nonnull'>
    <argument name='protocol' type='Protocol *_Nonnull' m68k-reg='a0'/>
  </function>
  <function name='protocol_isEqual' return-type='bool'>
    <argument name='protocol1' type='Protocol *_Nonnull' m68k-reg='a0'/>
    <argument name='protocol2' type='Protocol *_Nonnull' m68k-reg='a1'/>
  </function>
  <function name='protocol_conformsToProtocol' return-type='bool'>
    <argument name='protocol1' type='Protocol *_Nonnull' m68k-reg='a0'/>
    <argument name='protocol2' type='Protocol *_Nonnull' m68k-reg='a1'/>
  </function>
  <function name='objc_setUncaughtExceptionHandler'
            return-type='_Nullable objc_uncaught_exception_handler'>
    <argument name='handler' type='objc_uncaught_exception_handler _Nullable'
              m68k-reg='a0'/>
  </function>
  <function name='objc_setForwardHandler'>
    <argument name='forward' type='IMP _Nullable' m68k-reg='a0'/>
    <argument name='stretForward' type='IMP _Nullable' m68k-reg='a1'/>
  </function>
  <function name='objc_setEnumerationMutationHandler'>
    <argument name='hadler' type='objc_enumeration_mutation_handler _Nullable'
              m68k-reg='a0'/>
  </function>
  <function name='objc_constructInstance' return-type='id _Nullable'>
    <argument name='class' type='Class _Nullable' m68k-reg='a0'/>
    <argument name='bytes' type='void *_Nullable' m68k-reg='a1'/>
  </function>
  <function name='objc_deinit'/>
  <function name='class_copyIvarList' return-type='Ivar _Nullable *_Nullable'>
    <argument name='class' type='Class _Nullable' m68k-reg='a0'/>
    <argument name='outCount' type='unsigned int *_Nullable' m68k-reg='a1'/>
  </function>
  <function name='ivar_getName' return-type='const char *_Nonnull'>
    <argument name='ivar' type='Ivar _Nonnull' m68k-reg='a0'/>
  </function>
  <function name='ivar_getTypeEncoding' return-type='const char *_Nonnull'>
    <argument name='ivar' type='Ivar _Nonnull' m68k-reg='a0'/>
  </function>
  <function name='ivar_getOffset' return-type='ptrdiff_t'>
    <argument name='ivar' type='Ivar _Nonnull' m68k-reg='a0'/>
  </function>
  <function name='class_copyMethodList'
            return-type='Method _Nullable *_Nullable'>
    <argument name='class' type='Class _Nullable' m68k-reg='a0'/>
    <argument name='outCount' type='unsigned int *_Nullable' m68k-reg='a1'/>
  </function>
  <function name='method_getName' return-type='SEL _Nonnull'>
    <argument name='method' type='Method _Nonnull' m68k-reg='a0'/>
  </function>
  <function name='method_getTypeEncoding' return-type='const char *_Nullable'>
    <argument name='method' type='Method _Nonnull' m68k-reg='a0'/>
  </function>
  <function name='class_copyPropertyList'
            return-type='objc_property_t _Nullable *_Nullable'>
    <argument name='class' type='Class _Nullable' m68k-reg='a0'/>
    <argument name='outCount' type='unsigned int *_Nullable' m68k-reg='a1'/>
  </function>
  <function name='property_getName' return-type='const char *_Nonnull'>
    <argument name='property' type='objc_property_t _Nonnull' m68k-reg='a0'/>
  </function>
  <function name='property_copyAttributeValue' return-type='char *_Nullable'>
    <argument name='property' type='objc_property_t _Nonnull' m68k-reg='a0'/>
    <argument name='name' type='const char *_Nonnull' m68k-reg='a1'/>
  </function>
  <function name='objc_destructInstance' return-type='void *_Nullable'>
    <argument name='object' type='id _Nullable' m68k-reg='a0'/>
  </function>
  <function name='objc_autoreleasePoolPush'
            return-type='void *_Null_unspecified'>
  </function>
  <function name='objc_autoreleasePoolPop'>
    <argument name='pool' type='void *_Null_unspecified' m68k-reg='a0'/>
  </function>
  <function name='_objc_rootAutorelease' return-type='id _Nullable'>
    <argument name='object' type='id _Nullable' m68k-reg='a0'/>
  </function>
  <!-- The following functions are private! Don't use! -->
  <function name='objc_hashtable_new'
            return-type='struct objc_hashtable *_Nonnull'>
    <argument name='hash' type='objc_hashtable_hash_func' m68k-reg='a0'/>
    <argument name='equal' type='objc_hashtable_equal_func' m68k-reg='a1'/>
    <argument name='size' type='uint32_t' m68k-reg='d0'/>
  </function>
  <function name='objc_hashtable_set'>
    <argument name='table' type='struct objc_hashtable *_Nonnull'
              m68k-reg='a0'/>
    <argument name='key' type='const void *_Nonnull' m68k-reg='a1'/>
    <argument name='object' type='const void *_Nonnull' m68k-reg='a2'/>
  </function>
  <function name='objc_hashtable_get' return-type='void *_Nullable'>
    <argument name='table' type='struct objc_hashtable *_Nonnull'
              m68k-reg='a0'/>
    <argument name='key' type='const void *_Nonnull' m68k-reg='a1'/>
  </function>
  <function name='objc_hashtable_delete'>
    <argument name='table' type='struct objc_hashtable *_Nonnull'
              m68k-reg='a0'/>
    <argument name='key' type='const void *_Nonnull' m68k-reg='a1'/>
  </function>
  <function name='objc_hashtable_free'>
    <argument name='table' type='struct objc_hashtable *_Nonnull'
              m68k-reg='a0'/>
  </function>
  <!-- Public functions again -->
  <function name='objc_setTaggedPointerSecret'>
    <argument name='secret' type='uintptr_t' m68k-reg='d0'/>
  </function>
  <function name='objc_registerTaggedPointerClass' return-type='int'>
    <argument name='class' type='Class _Nonnull' m68k-reg='a0'/>
  </function>
  <function name='object_isTaggedPointer' return-type='bool'>
    <argument name='object' type='id _Nullable' m68k-reg='a0'/>
  </function>
  <function name='object_getTaggedPointerValue' return-type='uintptr_t'>
    <argument name='object' type='id _Nonnull' m68k-reg='a0'/>
  </function>
  <function name='objc_createTaggedPointer' return-type='id _Nullable'>
    <argument name='class' type='int' m68k-reg='d0'/>
    <argument name='value' type='uintptr_t' m68k-reg='d1'/>
  </function>
</amiga-library>
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<


















































































































































































































































































































































































































































































































































































































































































































Modified src/runtime/arc.m from [262fd1b7bb] to [33a15bfda2].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
	return value;
}

id
objc_loadWeakRetained(id *object)
{
	id value = nil;
	struct WeakRef *ref;

#ifdef OF_HAVE_THREADS
	if (OFSpinlockLock(&spinlock) != 0)
		OBJC_ERROR("Failed to lock spinlock!");
#endif

	if (*object != nil &&
	    (ref = objc_hashtable_get(hashtable, *object)) != NULL)
		value = *object;

#ifdef OF_HAVE_THREADS
	if (OFSpinlockUnlock(&spinlock) != 0)
		OBJC_ERROR("Failed to unlock spinlock!");
#endif








<






|
<







184
185
186
187
188
189
190

191
192
193
194
195
196
197

198
199
200
201
202
203
204
	return value;
}

id
objc_loadWeakRetained(id *object)
{
	id value = nil;


#ifdef OF_HAVE_THREADS
	if (OFSpinlockLock(&spinlock) != 0)
		OBJC_ERROR("Failed to lock spinlock!");
#endif

	if (*object != nil && objc_hashtable_get(hashtable, *object) != NULL)

		value = *object;

#ifdef OF_HAVE_THREADS
	if (OFSpinlockUnlock(&spinlock) != 0)
		OBJC_ERROR("Failed to unlock spinlock!");
#endif

Modified src/runtime/autorelease.m from [a652114a4e] to [bcf56c003e].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/runtime/category.m from [7faaa519d3] to [0ac9e67ceb].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/runtime/class.m from [4cb79aa414] to [99bd522eda].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
class_registerAlias_np(Class class, const char *name)
{
	objc_globalMutex_lock();

	if (classes == NULL) {
		objc_globalMutex_unlock();

		return NO;
	}

	objc_hashtable_set(classes, name, (Class)((uintptr_t)class | 1));

	objc_globalMutex_unlock();

	return YES;
}

static void
registerSelectors(Class class)
{
	struct objc_method_list *iter;
	unsigned int i;







|






|







54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
class_registerAlias_np(Class class, const char *name)
{
	objc_globalMutex_lock();

	if (classes == NULL) {
		objc_globalMutex_unlock();

		return false;
	}

	objc_hashtable_set(classes, name, (Class)((uintptr_t)class | 1));

	objc_globalMutex_unlock();

	return true;
}

static void
registerSelectors(Class class)
{
	struct objc_method_list *iter;
	unsigned int i;
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
		return Nil;

	/*
	 * Fast path
	 *
	 * Instead of looking up the string in a dictionary, which needs
	 * locking, we use a sparse array to look up the pointer. If
	 * objc_classname_to_class() gets called a lot, it is most likely that
	 * the GCC ABI is used, which always calls into objc_lookup_class(), or
	 * that it is used in a loop by the user. In both cases, it is very
	 * likely that the same string pointer is passed again and again.
	 *
	 * This is not used before objc_classname_to_class() has been called a
	 * certain amount of times, so that no memory is wasted if it is only
	 * used rarely, for example if the ObjFW ABI is used and the user does
	 * not call it in a loop.
	 *
	 * Runtime internal usage does not use the fast path and does not count
	 * as a call into objc_classname_to_class(). The reason for this is
	 * that if the runtime calls into objc_classname_to_class(), it already
	 * has the lock and thus the performance gain would be small, but it
	 * would waste memory.
	 */
	if (cache && fastPath != NULL) {
		class = objc_sparsearray_get(fastPath, (uintptr_t)name);

		if (class != Nil)
			return class;
	}







|




|





|
|
|
|







88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
		return Nil;

	/*
	 * Fast path
	 *
	 * Instead of looking up the string in a dictionary, which needs
	 * locking, we use a sparse array to look up the pointer. If
	 * objc_classnameToClass() gets called a lot, it is most likely that
	 * the GCC ABI is used, which always calls into objc_lookup_class(), or
	 * that it is used in a loop by the user. In both cases, it is very
	 * likely that the same string pointer is passed again and again.
	 *
	 * This is not used before objc_classnameToClass() has been called a
	 * certain amount of times, so that no memory is wasted if it is only
	 * used rarely, for example if the ObjFW ABI is used and the user does
	 * not call it in a loop.
	 *
	 * Runtime internal usage does not use the fast path and does not count
	 * as a call into objc_classnameToClass(). The reason for this is that
	 * if the runtime calls into objc_classnameToClass(), it already has
	 * the lock and thus the performance gain would be small, but it would
	 * waste memory.
	 */
	if (cache && fastPath != NULL) {
		class = objc_sparsearray_get(fastPath, (uintptr_t)name);

		if (class != Nil)
			return class;
	}
776
777
778
779
780
781
782

783
784
785
786
787
788
789
790

	class->methodList = methodList;

	objc_updateDTable(class);
}

Method

#if defined(__clang__) && __clang_major__ == 3 && __clang_minor__ <= 7
/* Work around an ICE in Clang 3.7.0 on Windows/x86 */
__attribute__((__optnone__))
#endif
class_getInstanceMethod(Class class, SEL selector)
{
	Method method;
	Class superclass;







>
|







776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791

	class->methodList = methodList;

	objc_updateDTable(class);
}

Method
#if defined(__clang__) && __has_attribute(__optnone__) && \
    __clang_major__ == 3 && __clang_minor__ <= 7
/* Work around an ICE in Clang 3.7.0 on Windows/x86 */
__attribute__((__optnone__))
#endif
class_getInstanceMethod(Class class, SEL selector)
{
	Method method;
	Class superclass;

Modified src/runtime/dtable.m from [f0602aa5e2] to [559b2cd300].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/runtime/exception.m from [ba2a43d17f] to [1ae703b363].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include <string.h>

#import "ObjFWRT.h"
#import "private.h"

#import "macros.h"
#ifdef OF_HAVE_THREADS
# include "OFPlainMutex.h"
#endif

#ifdef HAVE_SEH_EXCEPTIONS
# include <windows.h>
#endif

#if defined(HAVE_DWARF_EXCEPTIONS)







|







22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include <string.h>

#import "ObjFWRT.h"
#import "private.h"

#import "macros.h"
#ifdef OF_HAVE_THREADS
# import "OFPlainMutex.h"
#endif

#ifdef HAVE_SEH_EXCEPTIONS
# include <windows.h>
#endif

#if defined(HAVE_DWARF_EXCEPTIONS)

Modified src/runtime/hashtable.m from [4617c1e6d6] to [ad24f61645].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/runtime/init.m from [bad26900aa] to [60d4f8763e].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/runtime/instance.m from [bb4ce37e30] to [356d4e5ea1].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/runtime/ivar.m from [9c027bf0b1] to [2b22e6b336].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Deleted src/runtime/linklib/Makefile version [dc27346920].

1
2
3
4
5
6
7
8
9
10
11
12
13
include ../../../extra.mk

STATIC_LIB = libobjfwrt.library.a
SRCS = init.m		\
       linklib.m

include ../../../buildsys.mk

CPPFLAGS += -I..  -I../..  -I../../..				\
	    -DOBJC_COMPILING_AMIGA_LINKLIB			\
	    -DOBJFWRT_AMIGA_LIB=\"${OBJFWRT_AMIGA_LIB}\"	\
	    -DOBJFWRT_LIB_MINOR=${OBJFWRT_LIB_MINOR}
LD = ${OBJC}
<
<
<
<
<
<
<
<
<
<
<
<
<


























Deleted src/runtime/linklib/init.m version [6ddafedf04].

1
2
3
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
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#import "ObjFWRT.h"
#import "private.h"
#import "macros.h"

#include <proto/exec.h>
#include <proto/intuition.h>

struct ObjFWRTBase;

#include <stdio.h>
#include <stdlib.h>

#if defined(OF_AMIGAOS_M68K)
# include <stabs.h>
#elif defined(OF_MORPHOS)
# include <constructor.h>
#endif

#ifdef HAVE_SJLJ_EXCEPTIONS
extern int _Unwind_SjLj_RaiseException(void *);
#else
extern int _Unwind_RaiseException(void *);
#endif
extern void _Unwind_DeleteException(void *);
extern void *_Unwind_GetLanguageSpecificData(void *);
extern uintptr_t _Unwind_GetRegionStart(void *);
extern uintptr_t _Unwind_GetDataRelBase(void *);
extern uintptr_t _Unwind_GetTextRelBase(void *);
extern uintptr_t _Unwind_GetIP(void *);
extern uintptr_t _Unwind_GetGR(void *, int);
extern void _Unwind_SetIP(void *, uintptr_t);
extern void _Unwind_SetGR(void *, int, uintptr_t);
#ifdef HAVE_SJLJ_EXCEPTIONS
extern void _Unwind_SjLj_Resume(void *);
#else
extern void _Unwind_Resume(void *);
#endif
#ifdef OF_AMIGAOS_M68K
extern void __register_frame_info(const void *, void *);
extern void *__deregister_frame_info(const void *);
#endif
#ifdef OF_MORPHOS
extern void __register_frame(void *);
extern void __deregister_frame(void *);
#endif

struct Library *ObjFWRTBase;
void *__objc_class_name_Protocol;

extern bool objc_init(unsigned int version, struct objc_libc *libc);

static void
error(const char *string, ULONG arg)
{
	struct Library *IntuitionBase = OpenLibrary("intuition.library", 0);

	if (IntuitionBase != NULL) {
		struct EasyStruct easy = {
			.es_StructSize = sizeof(easy),
			.es_Flags = 0,
			.es_Title = (void *)NULL,
			.es_TextFormat = (void *)string,
			(void *)"OK"
		};

		EasyRequest(NULL, &easy, NULL, arg);

		CloseLibrary(IntuitionBase);
	}

	exit(EXIT_FAILURE);
}

static void __attribute__((__used__))
ctor(void)
{
	static bool initialized = false;
	struct objc_libc libc = {
		.malloc = malloc,
		.calloc = calloc,
		.realloc = realloc,
		.free = free,
#ifdef HAVE_SJLJ_EXCEPTIONS
		._Unwind_SjLj_RaiseException = _Unwind_SjLj_RaiseException,
#else
		._Unwind_RaiseException = _Unwind_RaiseException,
#endif
		._Unwind_DeleteException = _Unwind_DeleteException,
		._Unwind_GetLanguageSpecificData =
		    _Unwind_GetLanguageSpecificData,
		._Unwind_GetRegionStart = _Unwind_GetRegionStart,
		._Unwind_GetDataRelBase = _Unwind_GetDataRelBase,
		._Unwind_GetTextRelBase = _Unwind_GetTextRelBase,
		._Unwind_GetIP = _Unwind_GetIP,
		._Unwind_GetGR = _Unwind_GetGR,
		._Unwind_SetIP = _Unwind_SetIP,
		._Unwind_SetGR = _Unwind_SetGR,
#ifdef HAVE_SJLJ_EXCEPTIONS
		._Unwind_SjLj_Resume = _Unwind_SjLj_Resume,
#else
		._Unwind_Resume = _Unwind_Resume,
#endif
#ifdef OF_AMIGAOS_M68K
		.__register_frame_info = __register_frame_info,
		.__deregister_frame_info = __deregister_frame_info,
#endif
#ifdef OF_MORPHOS
		.__register_frame = __register_frame,
		.__deregister_frame = __deregister_frame,
#endif
#ifdef OF_AMIGAOS_M68K
		.vsnprintf = vsnprintf,
#endif
		.atexit = atexit,
		.exit = exit,
	};

	if (initialized)
		return;

	if ((ObjFWRTBase = OpenLibrary(OBJFWRT_AMIGA_LIB,
	    OBJFWRT_LIB_MINOR)) == NULL)
		error("Failed to open " OBJFWRT_AMIGA_LIB " version %lu!",
		    OBJFWRT_LIB_MINOR);

	if (!objc_init(1, &libc))
		error("Failed to initialize " OBJFWRT_AMIGA_LIB "!", 0);

	initialized = true;
}

static void __attribute__((__used__))
dtor(void)
{
	CloseLibrary(ObjFWRTBase);
}

#if defined(OF_AMIGAOS_M68K)
ADD2INIT(ctor, -5)
ADD2EXIT(dtor, -5)
#elif defined(OF_MORPHOS)
CONSTRUCTOR_P(ObjFWRT, 4000)
{
	ctor();

	return 0;
}

DESTRUCTOR_P(ObjFWRT, 0)
{
	dtor();
}
#endif

extern int __gnu_objc_personality(int version, int actions, uint64_t *exClass,
    void *ex, void *ctx);

int
#ifdef HAVE_SJLJ_EXCEPTIONS
__gnu_objc_personality_sj0(
#else
__gnu_objc_personality_v0(
#endif
    int version, int actions, uint64_t exClass, void *ex, void *ctx)
{
#ifdef OF_AMIGAOS_M68K
	return __gnu_objc_personality(version, actions, &exClass, ex, ctx);
#else
	return __gnu_objc_personality(version, actions, &exClass, ex, ctx);
#endif
}
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
























































































































































































































































































































































































Deleted src/runtime/linklib/linklib.m version [0c00bc31d2].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
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
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

/* This file is automatically generated from amiga-library.xml */

#include "config.h"

#import "ObjFWRT.h"
#import "private.h"

extern struct Library *ObjFWRTBase;

bool
objc_init(unsigned int version, struct objc_libc *libc)
{
#if defined(OF_AMIGAOS_M68K)
	register struct Library *a6 __asm__("a6") = ObjFWRTBase;
	(void)a6;
	return ((bool (*)(unsigned int __asm__("d0"), struct objc_libc *__asm__("a0")))(((uintptr_t)ObjFWRTBase) - 30))(version, libc);
#elif defined(OF_MORPHOS)
	__asm__ __volatile__ (
	    "mr		%%r12, %0"
	    :: "r"(ObjFWRTBase) : "r12"
	);

	return __extension__ ((bool (*)(unsigned int, struct objc_libc *))*(void **)(((uintptr_t)ObjFWRTBase) - 28))(version, libc);
#endif
}

void
__objc_exec_class(struct objc_module *_Nonnull module)
{
#if defined(OF_AMIGAOS_M68K)
	register struct Library *a6 __asm__("a6") = ObjFWRTBase;
	(void)a6;
	((void (*)(struct objc_module *_Nonnull __asm__("a0")))(((uintptr_t)ObjFWRTBase) - 36))(module);
#elif defined(OF_MORPHOS)
	__asm__ __volatile__ (
	    "mr		%%r12, %0"
	    :: "r"(ObjFWRTBase) : "r12"
	);

	__extension__ ((void (*)(struct objc_module *_Nonnull))*(void **)(((uintptr_t)ObjFWRTBase) - 34))(module);
#endif
}

IMP _Nonnull
objc_msg_lookup(id _Nullable object, SEL _Nonnull selector)
{
#if defined(OF_AMIGAOS_M68K)
	register struct Library *a6 __asm__("a6") = ObjFWRTBase;
	(void)a6;
	return ((IMP _Nonnull (*)(id _Nullable __asm__("a0"), SEL _Nonnull __asm__("a1")))(((uintptr_t)ObjFWRTBase) - 42))(object, selector);
#elif defined(OF_MORPHOS)
	__asm__ __volatile__ (
	    "mr		%%r12, %0"
	    :: "r"(ObjFWRTBase) : "r12"
	);

	return __extension__ ((IMP _Nonnull (*)(id _Nullable, SEL _Nonnull))*(void **)(((uintptr_t)ObjFWRTBase) - 40))(object, selector);
#endif
}

IMP _Nonnull
objc_msg_lookup_stret(id _Nullable object, SEL _Nonnull selector)
{
#if defined(OF_AMIGAOS_M68K)
	register struct Library *a6 __asm__("a6") = ObjFWRTBase;
	(void)a6;
	return ((IMP _Nonnull (*)(id _Nullable __asm__("a0"), SEL _Nonnull __asm__("a1")))(((uintptr_t)ObjFWRTBase) - 48))(object, selector);
#elif defined(OF_MORPHOS)
	__asm__ __volatile__ (
	    "mr		%%r12, %0"
	    :: "r"(ObjFWRTBase) : "r12"
	);

	return __extension__ ((IMP _Nonnull (*)(id _Nullable, SEL _Nonnull))*(void **)(((uintptr_t)ObjFWRTBase) - 46))(object, selector);
#endif
}

IMP _Nonnull
objc_msg_lookup_super(struct objc_super *_Nonnull super, SEL _Nonnull selector)
{
#if defined(OF_AMIGAOS_M68K)
	register struct Library *a6 __asm__("a6") = ObjFWRTBase;
	(void)a6;
	return ((IMP _Nonnull (*)(struct objc_super *_Nonnull __asm__("a0"), SEL _Nonnull __asm__("a1")))(((uintptr_t)ObjFWRTBase) - 54))(super, selector);
#elif defined(OF_MORPHOS)
	__asm__ __volatile__ (
	    "mr		%%r12, %0"
	    :: "r"(ObjFWRTBase) : "r12"
	);

	return __extension__ ((IMP _Nonnull (*)(struct objc_super *_Nonnull, SEL _Nonnull))*(void **)(((uintptr_t)ObjFWRTBase) - 52))(super, selector);
#endif
}

IMP _Nonnull
objc_msg_lookup_super_stret(struct objc_super *_Nonnull super, SEL _Nonnull selector)
{
#if defined(OF_AMIGAOS_M68K)
	register struct Library *a6 __asm__("a6") = ObjFWRTBase;
	(void)a6;
	return ((IMP _Nonnull (*)(struct objc_super *_Nonnull __asm__("a0"), SEL _Nonnull __asm__("a1")))(((uintptr_t)ObjFWRTBase) - 60))(super, selector);
#elif defined(OF_MORPHOS)
	__asm__ __volatile__ (
	    "mr		%%r12, %0"
	    :: "r"(ObjFWRTBase) : "r12"
	);

	return __extension__ ((IMP _Nonnull (*)(struct objc_super *_Nonnull, SEL _Nonnull))*(void **)(((uintptr_t)ObjFWRTBase) - 58))(super, selector);
#endif
}

Class _Nullable
objc_lookUpClass(const char *_Nonnull name)
{
#if defined(OF_AMIGAOS_M68K)
	register struct Library *a6 __asm__("a6") = ObjFWRTBase;
	(void)a6;
	return ((Class _Nullable (*)(const char *_Nonnull __asm__("a0")))(((uintptr_t)ObjFWRTBase) - 66))(name);
#elif defined(OF_MORPHOS)
	__asm__ __volatile__ (
	    "mr		%%r12, %0"
	    :: "r"(ObjFWRTBase) : "r12"
	);

	return __extension__ ((Class _Nullable (*)(const char *_Nonnull))*(void **)(((uintptr_t)ObjFWRTBase) - 64))(name);
#endif
}

Class _Nullable
objc_getClass(const char *_Nonnull name)
{
#if defined(OF_AMIGAOS_M68K)
	register struct Library *a6 __asm__("a6") = ObjFWRTBase;
	(void)a6;
	return ((Class _Nullable (*)(const char *_Nonnull __asm__("a0")))(((uintptr_t)ObjFWRTBase) - 72))(name);
#elif defined(OF_MORPHOS)
	__asm__ __volatile__ (
	    "mr		%%r12, %0"
	    :: "r"(ObjFWRTBase) : "r12"
	);

	return __extension__ ((Class _Nullable (*)(const char *_Nonnull))*(void **)(((uintptr_t)ObjFWRTBase) - 70))(name);
#endif
}

Class _Nonnull
objc_getRequiredClass(const char *_Nonnull name)
{
#if defined(OF_AMIGAOS_M68K)
	register struct Library *a6 __asm__("a6") = ObjFWRTBase;
	(void)a6;
	return ((Class _Nonnull (*)(const char *_Nonnull __asm__("a0")))(((uintptr_t)ObjFWRTBase) - 78))(name);
#elif defined(OF_MORPHOS)
	__asm__ __volatile__ (
	    "mr		%%r12, %0"
	    :: "r"(ObjFWRTBase) : "r12"
	);

	return __extension__ ((Class _Nonnull (*)(const char *_Nonnull))*(void **)(((uintptr_t)ObjFWRTBase) - 76))(name);
#endif
}

Class _Nullable
objc_lookup_class(const char *_Nonnull name)
{
#if defined(OF_AMIGAOS_M68K)
	register struct Library *a6 __asm__("a6") = ObjFWRTBase;
	(void)a6;
	return ((Class _Nullable (*)(const char *_Nonnull __asm__("a0")))(((uintptr_t)ObjFWRTBase) - 84))(name);
#elif defined(OF_MORPHOS)
	__asm__ __volatile__ (
	    "mr		%%r12, %0"
	    :: "r"(ObjFWRTBase) : "r12"
	);

	return __extension__ ((Class _Nullable (*)(const char *_Nonnull))*(void **)(((uintptr_t)ObjFWRTBase) - 82))(name);
#endif
}

Class _Nonnull
objc_get_class(const char *_Nonnull name)
{
#if defined(OF_AMIGAOS_M68K)
	register struct Library *a6 __asm__("a6") = ObjFWRTBase;
	(void)a6;
	return ((Class _Nonnull (*)(const char *_Nonnull __asm__("a0")))(((uintptr_t)ObjFWRTBase) - 90))(name);
#elif defined(OF_MORPHOS)
	__asm__ __volatile__ (
	    "mr		%%r12, %0"
	    :: "r"(ObjFWRTBase) : "r12"
	);

	return __extension__ ((Class _Nonnull (*)(const char *_Nonnull))*(void **)(((uintptr_t)ObjFWRTBase) - 88))(name);
#endif
}

void
objc_exception_throw(id _Nonnull object)
{
#if defined(OF_AMIGAOS_M68K)
	register struct Library *a6 __asm__("a6") = ObjFWRTBase;
	(void)a6;
	((void (*)(id _Nonnull __asm__("a0")))(((uintptr_t)ObjFWRTBase) - 96))(object);
#elif defined(OF_MORPHOS)
	__asm__ __volatile__ (
	    "mr		%%r12, %0"
	    :: "r"(ObjFWRTBase) : "r12"
	);

	__extension__ ((void (*)(id _Nonnull))*(void **)(((uintptr_t)ObjFWRTBase) - 94))(object);
#endif

	OF_UNREACHABLE
}

int
objc_sync_enter(id _Nullable object)
{
#if defined(OF_AMIGAOS_M68K)
	register struct Library *a6 __asm__("a6") = ObjFWRTBase;
	(void)a6;
	return ((int (*)(id _Nullable __asm__("a0")))(((uintptr_t)ObjFWRTBase) - 102))(object);
#elif defined(OF_MORPHOS)
	__asm__ __volatile__ (
	    "mr		%%r12, %0"
	    :: "r"(ObjFWRTBase) : "r12"
	);

	return __extension__ ((int (*)(id _Nullable))*(void **)(((uintptr_t)ObjFWRTBase) - 100))(object);
#endif
}

int
objc_sync_exit(id _Nullable object)
{
#if defined(OF_AMIGAOS_M68K)
	register struct Library *a6 __asm__("a6") = ObjFWRTBase;
	(void)a6;
	return ((int (*)(id _Nullable __asm__("a0")))(((uintptr_t)ObjFWRTBase) - 108))(object);
#elif defined(OF_MORPHOS)
	__asm__ __volatile__ (
	    "mr		%%r12, %0"
	    :: "r"(ObjFWRTBase) : "r12"
	);

	return __extension__ ((int (*)(id _Nullable))*(void **)(((uintptr_t)ObjFWRTBase) - 106))(object);
#endif
}

id _Nullable
objc_getProperty(id _Nonnull self, SEL _Nonnull _cmd, ptrdiff_t offset, bool atomic)
{
#if defined(OF_AMIGAOS_M68K)
	register struct Library *a6 __asm__("a6") = ObjFWRTBase;
	(void)a6;
	return ((id _Nullable (*)(id _Nonnull __asm__("a0"), SEL _Nonnull __asm__("a1"), ptrdiff_t __asm__("d0"), bool __asm__("d1")))(((uintptr_t)ObjFWRTBase) - 114))(self, _cmd, offset, atomic);
#elif defined(OF_MORPHOS)
	__asm__ __volatile__ (
	    "mr		%%r12, %0"
	    :: "r"(ObjFWRTBase) : "r12"
	);

	return __extension__ ((id _Nullable (*)(id _Nonnull, SEL _Nonnull, ptrdiff_t, bool))*(void **)(((uintptr_t)ObjFWRTBase) - 112))(self, _cmd, offset, atomic);
#endif
}

void
objc_setProperty(id _Nonnull self, SEL _Nonnull _cmd, ptrdiff_t offset, id _Nullable value, bool atomic, signed char copy)
{
#if defined(OF_AMIGAOS_M68K)
	register struct Library *a6 __asm__("a6") = ObjFWRTBase;
	(void)a6;
	((void (*)(id _Nonnull __asm__("a0"), SEL _Nonnull __asm__("a1"), ptrdiff_t __asm__("d0"), id _Nullable __asm__("a2"), bool __asm__("d1"), signed char __asm__("d2")))(((uintptr_t)ObjFWRTBase) - 120))(self, _cmd, offset, value, atomic, copy);
#elif defined(OF_MORPHOS)
	__asm__ __volatile__ (
	    "mr		%%r12, %0"
	    :: "r"(ObjFWRTBase) : "r12"
	);

	__extension__ ((void (*)(id _Nonnull, SEL _Nonnull, ptrdiff_t, id _Nullable, bool, signed char))*(void **)(((uintptr_t)ObjFWRTBase) - 118))(self, _cmd, offset, value, atomic, copy);
#endif
}

void
objc_getPropertyStruct(void *_Nonnull dest, const void *_Nonnull src, ptrdiff_t size, bool atomic, bool strong)
{
#if defined(OF_AMIGAOS_M68K)
	register struct Library *a6 __asm__("a6") = ObjFWRTBase;
	(void)a6;
	((void (*)(void *_Nonnull __asm__("a0"), const void *_Nonnull __asm__("a1"), ptrdiff_t __asm__("d0"), bool __asm__("d1"), bool __asm__("d2")))(((uintptr_t)ObjFWRTBase) - 126))(dest, src, size, atomic, strong);
#elif defined(OF_MORPHOS)
	__asm__ __volatile__ (
	    "mr		%%r12, %0"
	    :: "r"(ObjFWRTBase) : "r12"
	);

	__extension__ ((void (*)(void *_Nonnull, const void *_Nonnull, ptrdiff_t, bool, bool))*(void **)(((uintptr_t)ObjFWRTBase) - 124))(dest, src, size, atomic, strong);
#endif
}

void
objc_setPropertyStruct(void *_Nonnull dest, const void *_Nonnull src, ptrdiff_t size, bool atomic, bool strong)
{
#if defined(OF_AMIGAOS_M68K)
	register struct Library *a6 __asm__("a6") = ObjFWRTBase;
	(void)a6;
	((void (*)(void *_Nonnull __asm__("a0"), const void *_Nonnull __asm__("a1"), ptrdiff_t __asm__("d0"), bool __asm__("d1"), bool __asm__("d2")))(((uintptr_t)ObjFWRTBase) - 132))(dest, src, size, atomic, strong);
#elif defined(OF_MORPHOS)
	__asm__ __volatile__ (
	    "mr		%%r12, %0"
	    :: "r"(ObjFWRTBase) : "r12"
	);

	__extension__ ((void (*)(void *_Nonnull, const void *_Nonnull, ptrdiff_t, bool, bool))*(void **)(((uintptr_t)ObjFWRTBase) - 130))(dest, src, size, atomic, strong);
#endif
}

void
objc_enumerationMutation(id _Nonnull object)
{
#if defined(OF_AMIGAOS_M68K)
	register struct Library *a6 __asm__("a6") = ObjFWRTBase;
	(void)a6;
	((void (*)(id _Nonnull __asm__("a0")))(((uintptr_t)ObjFWRTBase) - 138))(object);
#elif defined(OF_MORPHOS)
	__asm__ __volatile__ (
	    "mr		%%r12, %0"
	    :: "r"(ObjFWRTBase) : "r12"
	);

	__extension__ ((void (*)(id _Nonnull))*(void **)(((uintptr_t)ObjFWRTBase) - 136))(object);
#endif
}

int
__gnu_objc_personality(int version, int actions, uint64_t *_Nonnull exClass, void *_Nonnull ex, void *_Nonnull ctx)
{
#if defined(OF_AMIGAOS_M68K)
	register struct Library *a6 __asm__("a6") = ObjFWRTBase;
	(void)a6;
	return ((int (*)(int __asm__("d0"), int __asm__("d1"), uint64_t *_Nonnull __asm__("d2"), void *_Nonnull __asm__("a0"), void *_Nonnull __asm__("a1")))(((uintptr_t)ObjFWRTBase) - 144))(version, actions, exClass, ex, ctx);
#elif defined(OF_MORPHOS)
	__asm__ __volatile__ (
	    "mr		%%r12, %0"
	    :: "r"(ObjFWRTBase) : "r12"
	);

	return __extension__ ((int (*)(int, int, uint64_t *_Nonnull, void *_Nonnull, void *_Nonnull))*(void **)(((uintptr_t)ObjFWRTBase) - 142))(version, actions, exClass, ex, ctx);
#endif
}

id _Nullable
objc_retain(id _Nullable object)
{
#if defined(OF_AMIGAOS_M68K)
	register struct Library *a6 __asm__("a6") = ObjFWRTBase;
	(void)a6;
	return ((id _Nullable (*)(id _Nullable __asm__("a0")))(((uintptr_t)ObjFWRTBase) - 150))(object);
#elif defined(OF_MORPHOS)
	__asm__ __volatile__ (
	    "mr		%%r12, %0"
	    :: "r"(ObjFWRTBase) : "r12"
	);

	return __extension__ ((id _Nullable (*)(id _Nullable))*(void **)(((uintptr_t)ObjFWRTBase) - 148))(object);
#endif
}

id _Nullable
objc_retainBlock(id _Nullable block)
{
#if defined(OF_AMIGAOS_M68K)
	register struct Library *a6 __asm__("a6") = ObjFWRTBase;
	(void)a6;
	return ((id _Nullable (*)(id _Nullable __asm__("a0")))(((uintptr_t)ObjFWRTBase) - 156))(block);
#elif defined(OF_MORPHOS)
	__asm__ __volatile__ (
	    "mr		%%r12, %0"
	    :: "r"(ObjFWRTBase) : "r12"
	);

	return __extension__ ((id _Nullable (*)(id _Nullable))*(void **)(((uintptr_t)ObjFWRTBase) - 154))(block);
#endif
}

id _Nullable
objc_retainAutorelease(id _Nullable object)
{
#if defined(OF_AMIGAOS_M68K)
	register struct Library *a6 __asm__("a6") = ObjFWRTBase;
	(void)a6;
	return ((id _Nullable (*)(id _Nullable __asm__("a0")))(((uintptr_t)ObjFWRTBase) - 162))(object);
#elif defined(OF_MORPHOS)
	__asm__ __volatile__ (
	    "mr		%%r12, %0"
	    :: "r"(ObjFWRTBase) : "r12"
	);

	return __extension__ ((id _Nullable (*)(id _Nullable))*(void **)(((uintptr_t)ObjFWRTBase) - 160))(object);
#endif
}

void
objc_release(id _Nullable object)
{
#if defined(OF_AMIGAOS_M68K)
	register struct Library *a6 __asm__("a6") = ObjFWRTBase;
	(void)a6;
	((void (*)(id _Nullable __asm__("a0")))(((uintptr_t)ObjFWRTBase) - 168))(object);
#elif defined(OF_MORPHOS)
	__asm__ __volatile__ (
	    "mr		%%r12, %0"
	    :: "r"(ObjFWRTBase) : "r12"
	);

	__extension__ ((void (*)(id _Nullable))*(void **)(((uintptr_t)ObjFWRTBase) - 166))(object);
#endif
}

id _Nullable
objc_autorelease(id _Nullable object)
{
#if defined(OF_AMIGAOS_M68K)
	register struct Library *a6 __asm__("a6") = ObjFWRTBase;
	(void)a6;
	return ((id _Nullable (*)(id _Nullable __asm__("a0")))(((uintptr_t)ObjFWRTBase) - 174))(object);
#elif defined(OF_MORPHOS)
	__asm__ __volatile__ (
	    "mr		%%r12, %0"
	    :: "r"(ObjFWRTBase) : "r12"
	);

	return __extension__ ((id _Nullable (*)(id _Nullable))*(void **)(((uintptr_t)ObjFWRTBase) - 172))(object);
#endif
}

id _Nullable
objc_autoreleaseReturnValue(id _Nullable object)
{
#if defined(OF_AMIGAOS_M68K)
	register struct Library *a6 __asm__("a6") = ObjFWRTBase;
	(void)a6;
	return ((id _Nullable (*)(id _Nullable __asm__("a0")))(((uintptr_t)ObjFWRTBase) - 180))(object);
#elif defined(OF_MORPHOS)
	__asm__ __volatile__ (
	    "mr		%%r12, %0"
	    :: "r"(ObjFWRTBase) : "r12"
	);

	return __extension__ ((id _Nullable (*)(id _Nullable))*(void **)(((uintptr_t)ObjFWRTBase) - 178))(object);
#endif
}

id _Nullable
objc_retainAutoreleaseReturnValue(id _Nullable object)
{
#if defined(OF_AMIGAOS_M68K)
	register struct Library *a6 __asm__("a6") = ObjFWRTBase;
	(void)a6;
	return ((id _Nullable (*)(id _Nullable __asm__("a0")))(((uintptr_t)ObjFWRTBase) - 186))(object);
#elif defined(OF_MORPHOS)
	__asm__ __volatile__ (
	    "mr		%%r12, %0"
	    :: "r"(ObjFWRTBase) : "r12"
	);

	return __extension__ ((id _Nullable (*)(id _Nullable))*(void **)(((uintptr_t)ObjFWRTBase) - 184))(object);
#endif
}

id _Nullable
objc_retainAutoreleasedReturnValue(id _Nullable object)
{
#if defined(OF_AMIGAOS_M68K)
	register struct Library *a6 __asm__("a6") = ObjFWRTBase;
	(void)a6;
	return ((id _Nullable (*)(id _Nullable __asm__("a0")))(((uintptr_t)ObjFWRTBase) - 192))(object);
#elif defined(OF_MORPHOS)
	__asm__ __volatile__ (
	    "mr		%%r12, %0"
	    :: "r"(ObjFWRTBase) : "r12"
	);

	return __extension__ ((id _Nullable (*)(id _Nullable))*(void **)(((uintptr_t)ObjFWRTBase) - 190))(object);
#endif
}

id _Nullable
objc_storeStrong(id _Nullable *_Nonnull object, id _Nullable value)
{
#if defined(OF_AMIGAOS_M68K)
	register struct Library *a6 __asm__("a6") = ObjFWRTBase;
	(void)a6;
	return ((id _Nullable (*)(id _Nullable *_Nonnull __asm__("a0"), id _Nullable __asm__("a1")))(((uintptr_t)ObjFWRTBase) - 198))(object, value);
#elif defined(OF_MORPHOS)
	__asm__ __volatile__ (
	    "mr		%%r12, %0"
	    :: "r"(ObjFWRTBase) : "r12"
	);

	return __extension__ ((id _Nullable (*)(id _Nullable *_Nonnull, id _Nullable))*(void **)(((uintptr_t)ObjFWRTBase) - 196))(object, value);
#endif
}

id _Nullable
objc_storeWeak(id _Nullable *_Nonnull object, id _Nullable value)
{
#if defined(OF_AMIGAOS_M68K)
	register struct Library *a6 __asm__("a6") = ObjFWRTBase;
	(void)a6;
	return ((id _Nullable (*)(id _Nullable *_Nonnull __asm__("a0"), id _Nullable __asm__("a1")))(((uintptr_t)ObjFWRTBase) - 204))(object, value);
#elif defined(OF_MORPHOS)
	__asm__ __volatile__ (
	    "mr		%%r12, %0"
	    :: "r"(ObjFWRTBase) : "r12"
	);

	return __extension__ ((id _Nullable (*)(id _Nullable *_Nonnull, id _Nullable))*(void **)(((uintptr_t)ObjFWRTBase) - 202))(object, value);
#endif
}

id _Nullable
objc_loadWeakRetained(id _Nullable *_Nonnull object)
{
#if defined(OF_AMIGAOS_M68K)
	register struct Library *a6 __asm__("a6") = ObjFWRTBase;
	(void)a6;
	return ((id _Nullable (*)(id _Nullable *_Nonnull __asm__("a0")))(((uintptr_t)ObjFWRTBase) - 210))(object);
#elif defined(OF_MORPHOS)
	__asm__ __volatile__ (
	    "mr		%%r12, %0"
	    :: "r"(ObjFWRTBase) : "r12"
	);

	return __extension__ ((id _Nullable (*)(id _Nullable *_Nonnull))*(void **)(((uintptr_t)ObjFWRTBase) - 208))(object);
#endif
}

id _Nullable
objc_initWeak(id _Nullable *_Nonnull object, id _Nullable value)
{
#if defined(OF_AMIGAOS_M68K)
	register struct Library *a6 __asm__("a6") = ObjFWRTBase;
	(void)a6;
	return ((id _Nullable (*)(id _Nullable *_Nonnull __asm__("a0"), id _Nullable __asm__("a1")))(((uintptr_t)ObjFWRTBase) - 216))(object, value);
#elif defined(OF_MORPHOS)
	__asm__ __volatile__ (
	    "mr		%%r12, %0"
	    :: "r"(ObjFWRTBase) : "r12"
	);

	return __extension__ ((id _Nullable (*)(id _Nullable *_Nonnull, id _Nullable))*(void **)(((uintptr_t)ObjFWRTBase) - 214))(object, value);
#endif
}

void
objc_destroyWeak(id _Nullable *_Nonnull object)
{
#if defined(OF_AMIGAOS_M68K)
	register struct Library *a6 __asm__("a6") = ObjFWRTBase;
	(void)a6;
	((void (*)(id _Nullable *_Nonnull __asm__("a0")))(((uintptr_t)ObjFWRTBase) - 222))(object);
#elif defined(OF_MORPHOS)
	__asm__ __volatile__ (
	    "mr		%%r12, %0"
	    :: "r"(ObjFWRTBase) : "r12"
	);

	__extension__ ((void (*)(id _Nullable *_Nonnull))*(void **)(((uintptr_t)ObjFWRTBase) - 220))(object);
#endif
}

id _Nullable
objc_loadWeak(id _Nullable *_Nonnull object)
{
#if defined(OF_AMIGAOS_M68K)
	register struct Library *a6 __asm__("a6") = ObjFWRTBase;
	(void)a6;
	return ((id _Nullable (*)(id _Nullable *_Nonnull __asm__("a0")))(((uintptr_t)ObjFWRTBase) - 228))(object);
#elif defined(OF_MORPHOS)
	__asm__ __volatile__ (
	    "mr		%%r12, %0"
	    :: "r"(ObjFWRTBase) : "r12"
	);

	return __extension__ ((id _Nullable (*)(id _Nullable *_Nonnull))*(void **)(((uintptr_t)ObjFWRTBase) - 226))(object);
#endif
}

void
objc_copyWeak(id _Nullable *_Nonnull dest, id _Nullable *_Nonnull src)
{
#if defined(OF_AMIGAOS_M68K)
	register struct Library *a6 __asm__("a6") = ObjFWRTBase;
	(void)a6;
	((void (*)(id _Nullable *_Nonnull __asm__("a0"), id _Nullable *_Nonnull __asm__("a1")))(((uintptr_t)ObjFWRTBase) - 234))(dest, src);
#elif defined(OF_MORPHOS)
	__asm__ __volatile__ (
	    "mr		%%r12, %0"
	    :: "r"(ObjFWRTBase) : "r12"
	);

	__extension__ ((void (*)(id _Nullable *_Nonnull, id _Nullable *_Nonnull))*(void **)(((uintptr_t)ObjFWRTBase) - 232))(dest, src);
#endif
}

void
objc_moveWeak(id _Nullable *_Nonnull dest, id _Nullable *_Nonnull src)
{
#if defined(OF_AMIGAOS_M68K)
	register struct Library *a6 __asm__("a6") = ObjFWRTBase;
	(void)a6;
	((void (*)(id _Nullable *_Nonnull __asm__("a0"), id _Nullable *_Nonnull __asm__("a1")))(((uintptr_t)ObjFWRTBase) - 240))(dest, src);
#elif defined(OF_MORPHOS)
	__asm__ __volatile__ (
	    "mr		%%r12, %0"
	    :: "r"(ObjFWRTBase) : "r12"
	);

	__extension__ ((void (*)(id _Nullable *_Nonnull, id _Nullable *_Nonnull))*(void **)(((uintptr_t)ObjFWRTBase) - 238))(dest, src);
#endif
}

SEL _Nonnull
sel_registerName(const char *_Nonnull name)
{
#if defined(OF_AMIGAOS_M68K)
	register struct Library *a6 __asm__("a6") = ObjFWRTBase;
	(void)a6;
	return ((SEL _Nonnull (*)(const char *_Nonnull __asm__("a0")))(((uintptr_t)ObjFWRTBase) - 246))(name);
#elif defined(OF_MORPHOS)
	__asm__ __volatile__ (
	    "mr		%%r12, %0"
	    :: "r"(ObjFWRTBase) : "r12"
	);

	return __extension__ ((SEL _Nonnull (*)(const char *_Nonnull))*(void **)(((uintptr_t)ObjFWRTBase) - 244))(name);
#endif
}

const char *_Nonnull
sel_getName(SEL _Nonnull selector)
{
#if defined(OF_AMIGAOS_M68K)
	register struct Library *a6 __asm__("a6") = ObjFWRTBase;
	(void)a6;
	return ((const char *_Nonnull (*)(SEL _Nonnull __asm__("a0")))(((uintptr_t)ObjFWRTBase) - 252))(selector);
#elif defined(OF_MORPHOS)
	__asm__ __volatile__ (
	    "mr		%%r12, %0"
	    :: "r"(ObjFWRTBase) : "r12"
	);

	return __extension__ ((const char *_Nonnull (*)(SEL _Nonnull))*(void **)(((uintptr_t)ObjFWRTBase) - 250))(selector);
#endif
}

bool
sel_isEqual(SEL _Nonnull selector1, SEL _Nonnull selector2)
{
#if defined(OF_AMIGAOS_M68K)
	register struct Library *a6 __asm__("a6") = ObjFWRTBase;
	(void)a6;
	return ((bool (*)(SEL _Nonnull __asm__("a0"), SEL _Nonnull __asm__("a1")))(((uintptr_t)ObjFWRTBase) - 258))(selector1, selector2);
#elif defined(OF_MORPHOS)
	__asm__ __volatile__ (
	    "mr		%%r12, %0"
	    :: "r"(ObjFWRTBase) : "r12"
	);

	return __extension__ ((bool (*)(SEL _Nonnull, SEL _Nonnull))*(void **)(((uintptr_t)ObjFWRTBase) - 256))(selector1, selector2);
#endif
}

Class _Nonnull
objc_allocateClassPair(Class _Nullable superclass, const char *_Nonnull name, size_t extraBytes)
{
#if defined(OF_AMIGAOS_M68K)
	register struct Library *a6 __asm__("a6") = ObjFWRTBase;
	(void)a6;
	return ((Class _Nonnull (*)(Class _Nullable __asm__("a0"), const char *_Nonnull __asm__("a1"), size_t __asm__("d0")))(((uintptr_t)ObjFWRTBase) - 264))(superclass, name, extraBytes);
#elif defined(OF_MORPHOS)
	__asm__ __volatile__ (
	    "mr		%%r12, %0"
	    :: "r"(ObjFWRTBase) : "r12"
	);

	return __extension__ ((Class _Nonnull (*)(Class _Nullable, const char *_Nonnull, size_t))*(void **)(((uintptr_t)ObjFWRTBase) - 262))(superclass, name, extraBytes);
#endif
}

void
objc_registerClassPair(Class _Nonnull class)
{
#if defined(OF_AMIGAOS_M68K)
	register struct Library *a6 __asm__("a6") = ObjFWRTBase;
	(void)a6;
	((void (*)(Class _Nonnull __asm__("a0")))(((uintptr_t)ObjFWRTBase) - 270))(class);
#elif defined(OF_MORPHOS)
	__asm__ __volatile__ (
	    "mr		%%r12, %0"
	    :: "r"(ObjFWRTBase) : "r12"
	);

	__extension__ ((void (*)(Class _Nonnull))*(void **)(((uintptr_t)ObjFWRTBase) - 268))(class);
#endif
}

unsigned int
objc_getClassList(Class _Nonnull *_Nullable buffer, unsigned int count)
{
#if defined(OF_AMIGAOS_M68K)
	register struct Library *a6 __asm__("a6") = ObjFWRTBase;
	(void)a6;
	return ((unsigned int (*)(Class _Nonnull *_Nullable __asm__("a0"), unsigned int __asm__("d0")))(((uintptr_t)ObjFWRTBase) - 276))(buffer, count);
#elif defined(OF_MORPHOS)
	__asm__ __volatile__ (
	    "mr		%%r12, %0"
	    :: "r"(ObjFWRTBase) : "r12"
	);

	return __extension__ ((unsigned int (*)(Class _Nonnull *_Nullable, unsigned int))*(void **)(((uintptr_t)ObjFWRTBase) - 274))(buffer, count);
#endif
}

Class _Nonnull *_Nonnull
objc_copyClassList(unsigned int *_Nullable length)
{
#if defined(OF_AMIGAOS_M68K)
	register struct Library *a6 __asm__("a6") = ObjFWRTBase;
	(void)a6;
	return ((Class _Nonnull *_Nonnull (*)(unsigned int *_Nullable __asm__("a0")))(((uintptr_t)ObjFWRTBase) - 282))(length);
#elif defined(OF_MORPHOS)
	__asm__ __volatile__ (
	    "mr		%%r12, %0"
	    :: "r"(ObjFWRTBase) : "r12"
	);

	return __extension__ ((Class _Nonnull *_Nonnull (*)(unsigned int *_Nullable))*(void **)(((uintptr_t)ObjFWRTBase) - 280))(length);
#endif
}

bool
class_isMetaClass(Class _Nullable class)
{
#if defined(OF_AMIGAOS_M68K)
	register struct Library *a6 __asm__("a6") = ObjFWRTBase;
	(void)a6;
	return ((bool (*)(Class _Nullable __asm__("a0")))(((uintptr_t)ObjFWRTBase) - 288))(class);
#elif defined(OF_MORPHOS)
	__asm__ __volatile__ (
	    "mr		%%r12, %0"
	    :: "r"(ObjFWRTBase) : "r12"
	);

	return __extension__ ((bool (*)(Class _Nullable))*(void **)(((uintptr_t)ObjFWRTBase) - 286))(class);
#endif
}

const char *_Nullable
class_getName(Class _Nullable class)
{
#if defined(OF_AMIGAOS_M68K)
	register struct Library *a6 __asm__("a6") = ObjFWRTBase;
	(void)a6;
	return ((const char *_Nullable (*)(Class _Nullable __asm__("a0")))(((uintptr_t)ObjFWRTBase) - 294))(class);
#elif defined(OF_MORPHOS)
	__asm__ __volatile__ (
	    "mr		%%r12, %0"
	    :: "r"(ObjFWRTBase) : "r12"
	);

	return __extension__ ((const char *_Nullable (*)(Class _Nullable))*(void **)(((uintptr_t)ObjFWRTBase) - 292))(class);
#endif
}

Class _Nullable
class_getSuperclass(Class _Nullable class)
{
#if defined(OF_AMIGAOS_M68K)
	register struct Library *a6 __asm__("a6") = ObjFWRTBase;
	(void)a6;
	return ((Class _Nullable (*)(Class _Nullable __asm__("a0")))(((uintptr_t)ObjFWRTBase) - 300))(class);
#elif defined(OF_MORPHOS)
	__asm__ __volatile__ (
	    "mr		%%r12, %0"
	    :: "r"(ObjFWRTBase) : "r12"
	);

	return __extension__ ((Class _Nullable (*)(Class _Nullable))*(void **)(((uintptr_t)ObjFWRTBase) - 298))(class);
#endif
}

unsigned long
class_getInstanceSize(Class _Nullable class)
{
#if defined(OF_AMIGAOS_M68K)
	register struct Library *a6 __asm__("a6") = ObjFWRTBase;
	(void)a6;
	return ((unsigned long (*)(Class _Nullable __asm__("a0")))(((uintptr_t)ObjFWRTBase) - 306))(class);
#elif defined(OF_MORPHOS)
	__asm__ __volatile__ (
	    "mr		%%r12, %0"
	    :: "r"(ObjFWRTBase) : "r12"
	);

	return __extension__ ((unsigned long (*)(Class _Nullable))*(void **)(((uintptr_t)ObjFWRTBase) - 304))(class);
#endif
}

bool
class_respondsToSelector(Class _Nullable class, SEL _Nonnull selector)
{
#if defined(OF_AMIGAOS_M68K)
	register struct Library *a6 __asm__("a6") = ObjFWRTBase;
	(void)a6;
	return ((bool (*)(Class _Nullable __asm__("a0"), SEL _Nonnull __asm__("a1")))(((uintptr_t)ObjFWRTBase) - 312))(class, selector);
#elif defined(OF_MORPHOS)
	__asm__ __volatile__ (
	    "mr		%%r12, %0"
	    :: "r"(ObjFWRTBase) : "r12"
	);

	return __extension__ ((bool (*)(Class _Nullable, SEL _Nonnull))*(void **)(((uintptr_t)ObjFWRTBase) - 310))(class, selector);
#endif
}

bool
class_conformsToProtocol(Class _Nullable class, Protocol *_Nonnull p)
{
#if defined(OF_AMIGAOS_M68K)
	register struct Library *a6 __asm__("a6") = ObjFWRTBase;
	(void)a6;
	return ((bool (*)(Class _Nullable __asm__("a0"), Protocol *_Nonnull __asm__("a1")))(((uintptr_t)ObjFWRTBase) - 318))(class, p);
#elif defined(OF_MORPHOS)
	__asm__ __volatile__ (
	    "mr		%%r12, %0"
	    :: "r"(ObjFWRTBase) : "r12"
	);

	return __extension__ ((bool (*)(Class _Nullable, Protocol *_Nonnull))*(void **)(((uintptr_t)ObjFWRTBase) - 316))(class, p);
#endif
}

IMP _Nullable
class_getMethodImplementation(Class _Nullable class, SEL _Nonnull selector)
{
#if defined(OF_AMIGAOS_M68K)
	register struct Library *a6 __asm__("a6") = ObjFWRTBase;
	(void)a6;
	return ((IMP _Nullable (*)(Class _Nullable __asm__("a0"), SEL _Nonnull __asm__("a1")))(((uintptr_t)ObjFWRTBase) - 324))(class, selector);
#elif defined(OF_MORPHOS)
	__asm__ __volatile__ (
	    "mr		%%r12, %0"
	    :: "r"(ObjFWRTBase) : "r12"
	);

	return __extension__ ((IMP _Nullable (*)(Class _Nullable, SEL _Nonnull))*(void **)(((uintptr_t)ObjFWRTBase) - 322))(class, selector);
#endif
}

IMP _Nullable
class_getMethodImplementation_stret(Class _Nullable class, SEL _Nonnull selector)
{
#if defined(OF_AMIGAOS_M68K)
	register struct Library *a6 __asm__("a6") = ObjFWRTBase;
	(void)a6;
	return ((IMP _Nullable (*)(Class _Nullable __asm__("a0"), SEL _Nonnull __asm__("a1")))(((uintptr_t)ObjFWRTBase) - 330))(class, selector);
#elif defined(OF_MORPHOS)
	__asm__ __volatile__ (
	    "mr		%%r12, %0"
	    :: "r"(ObjFWRTBase) : "r12"
	);

	return __extension__ ((IMP _Nullable (*)(Class _Nullable, SEL _Nonnull))*(void **)(((uintptr_t)ObjFWRTBase) - 328))(class, selector);
#endif
}

Method _Nullable
class_getInstanceMethod(Class _Nullable class, SEL _Nonnull selector)
{
#if defined(OF_AMIGAOS_M68K)
	register struct Library *a6 __asm__("a6") = ObjFWRTBase;
	(void)a6;
	return ((Method _Nullable (*)(Class _Nullable __asm__("a0"), SEL _Nonnull __asm__("a1")))(((uintptr_t)ObjFWRTBase) - 336))(class, selector);
#elif defined(OF_MORPHOS)
	__asm__ __volatile__ (
	    "mr		%%r12, %0"
	    :: "r"(ObjFWRTBase) : "r12"
	);

	return __extension__ ((Method _Nullable (*)(Class _Nullable, SEL _Nonnull))*(void **)(((uintptr_t)ObjFWRTBase) - 334))(class, selector);
#endif
}

bool
class_addMethod(Class _Nonnull class, SEL _Nonnull selector, IMP _Nonnull implementation, const char *_Nullable typeEncoding)
{
#if defined(OF_AMIGAOS_M68K)
	register struct Library *a6 __asm__("a6") = ObjFWRTBase;
	(void)a6;
	return ((bool (*)(Class _Nonnull __asm__("a0"), SEL _Nonnull __asm__("a1"), IMP _Nonnull __asm__("a2"), const char *_Nullable __asm__("a3")))(((uintptr_t)ObjFWRTBase) - 342))(class, selector, implementation, typeEncoding);
#elif defined(OF_MORPHOS)
	__asm__ __volatile__ (
	    "mr		%%r12, %0"
	    :: "r"(ObjFWRTBase) : "r12"
	);

	return __extension__ ((bool (*)(Class _Nonnull, SEL _Nonnull, IMP _Nonnull, const char *_Nullable))*(void **)(((uintptr_t)ObjFWRTBase) - 340))(class, selector, implementation, typeEncoding);
#endif
}

IMP _Nullable
class_replaceMethod(Class _Nonnull class, SEL _Nonnull selector, IMP _Nonnull implementation, const char *_Nullable typeEncoding)
{
#if defined(OF_AMIGAOS_M68K)
	register struct Library *a6 __asm__("a6") = ObjFWRTBase;
	(void)a6;
	return ((IMP _Nullable (*)(Class _Nonnull __asm__("a0"), SEL _Nonnull __asm__("a1"), IMP _Nonnull __asm__("a2"), const char *_Nullable __asm__("a3")))(((uintptr_t)ObjFWRTBase) - 348))(class, selector, implementation, typeEncoding);
#elif defined(OF_MORPHOS)
	__asm__ __volatile__ (
	    "mr		%%r12, %0"
	    :: "r"(ObjFWRTBase) : "r12"
	);

	return __extension__ ((IMP _Nullable (*)(Class _Nonnull, SEL _Nonnull, IMP _Nonnull, const char *_Nullable))*(void **)(((uintptr_t)ObjFWRTBase) - 346))(class, selector, implementation, typeEncoding);
#endif
}

Class _Nullable
object_getClass(id _Nullable object)
{
#if defined(OF_AMIGAOS_M68K)
	register struct Library *a6 __asm__("a6") = ObjFWRTBase;
	(void)a6;
	return ((Class _Nullable (*)(id _Nullable __asm__("a0")))(((uintptr_t)ObjFWRTBase) - 354))(object);
#elif defined(OF_MORPHOS)
	__asm__ __volatile__ (
	    "mr		%%r12, %0"
	    :: "r"(ObjFWRTBase) : "r12"
	);

	return __extension__ ((Class _Nullable (*)(id _Nullable))*(void **)(((uintptr_t)ObjFWRTBase) - 352))(object);
#endif
}

Class _Nullable
object_setClass(id _Nullable object, Class _Nonnull class)
{
#if defined(OF_AMIGAOS_M68K)
	register struct Library *a6 __asm__("a6") = ObjFWRTBase;
	(void)a6;
	return ((Class _Nullable (*)(id _Nullable __asm__("a0"), Class _Nonnull __asm__("a1")))(((uintptr_t)ObjFWRTBase) - 360))(object, class);
#elif defined(OF_MORPHOS)
	__asm__ __volatile__ (
	    "mr		%%r12, %0"
	    :: "r"(ObjFWRTBase) : "r12"
	);

	return __extension__ ((Class _Nullable (*)(id _Nullable, Class _Nonnull))*(void **)(((uintptr_t)ObjFWRTBase) - 358))(object, class);
#endif
}

const char *_Nullable
object_getClassName(id _Nullable object)
{
#if defined(OF_AMIGAOS_M68K)
	register struct Library *a6 __asm__("a6") = ObjFWRTBase;
	(void)a6;
	return ((const char *_Nullable (*)(id _Nullable __asm__("a0")))(((uintptr_t)ObjFWRTBase) - 366))(object);
#elif defined(OF_MORPHOS)
	__asm__ __volatile__ (
	    "mr		%%r12, %0"
	    :: "r"(ObjFWRTBase) : "r12"
	);

	return __extension__ ((const char *_Nullable (*)(id _Nullable))*(void **)(((uintptr_t)ObjFWRTBase) - 364))(object);
#endif
}

const char *_Nonnull
protocol_getName(Protocol *_Nonnull protocol)
{
#if defined(OF_AMIGAOS_M68K)
	register struct Library *a6 __asm__("a6") = ObjFWRTBase;
	(void)a6;
	return ((const char *_Nonnull (*)(Protocol *_Nonnull __asm__("a0")))(((uintptr_t)ObjFWRTBase) - 372))(protocol);
#elif defined(OF_MORPHOS)
	__asm__ __volatile__ (
	    "mr		%%r12, %0"
	    :: "r"(ObjFWRTBase) : "r12"
	);

	return __extension__ ((const char *_Nonnull (*)(Protocol *_Nonnull))*(void **)(((uintptr_t)ObjFWRTBase) - 370))(protocol);
#endif
}

bool
protocol_isEqual(Protocol *_Nonnull protocol1, Protocol *_Nonnull protocol2)
{
#if defined(OF_AMIGAOS_M68K)
	register struct Library *a6 __asm__("a6") = ObjFWRTBase;
	(void)a6;
	return ((bool (*)(Protocol *_Nonnull __asm__("a0"), Protocol *_Nonnull __asm__("a1")))(((uintptr_t)ObjFWRTBase) - 378))(protocol1, protocol2);
#elif defined(OF_MORPHOS)
	__asm__ __volatile__ (
	    "mr		%%r12, %0"
	    :: "r"(ObjFWRTBase) : "r12"
	);

	return __extension__ ((bool (*)(Protocol *_Nonnull, Protocol *_Nonnull))*(void **)(((uintptr_t)ObjFWRTBase) - 376))(protocol1, protocol2);
#endif
}

bool
protocol_conformsToProtocol(Protocol *_Nonnull protocol1, Protocol *_Nonnull protocol2)
{
#if defined(OF_AMIGAOS_M68K)
	register struct Library *a6 __asm__("a6") = ObjFWRTBase;
	(void)a6;
	return ((bool (*)(Protocol *_Nonnull __asm__("a0"), Protocol *_Nonnull __asm__("a1")))(((uintptr_t)ObjFWRTBase) - 384))(protocol1, protocol2);
#elif defined(OF_MORPHOS)
	__asm__ __volatile__ (
	    "mr		%%r12, %0"
	    :: "r"(ObjFWRTBase) : "r12"
	);

	return __extension__ ((bool (*)(Protocol *_Nonnull, Protocol *_Nonnull))*(void **)(((uintptr_t)ObjFWRTBase) - 382))(protocol1, protocol2);
#endif
}

_Nullable objc_uncaught_exception_handler
objc_setUncaughtExceptionHandler(objc_uncaught_exception_handler _Nullable handler)
{
#if defined(OF_AMIGAOS_M68K)
	register struct Library *a6 __asm__("a6") = ObjFWRTBase;
	(void)a6;
	return ((_Nullable objc_uncaught_exception_handler (*)(objc_uncaught_exception_handler _Nullable __asm__("a0")))(((uintptr_t)ObjFWRTBase) - 390))(handler);
#elif defined(OF_MORPHOS)
	__asm__ __volatile__ (
	    "mr		%%r12, %0"
	    :: "r"(ObjFWRTBase) : "r12"
	);

	return __extension__ ((_Nullable objc_uncaught_exception_handler (*)(objc_uncaught_exception_handler _Nullable))*(void **)(((uintptr_t)ObjFWRTBase) - 388))(handler);
#endif
}

void
objc_setForwardHandler(IMP _Nullable forward, IMP _Nullable stretForward)
{
#if defined(OF_AMIGAOS_M68K)
	register struct Library *a6 __asm__("a6") = ObjFWRTBase;
	(void)a6;
	((void (*)(IMP _Nullable __asm__("a0"), IMP _Nullable __asm__("a1")))(((uintptr_t)ObjFWRTBase) - 396))(forward, stretForward);
#elif defined(OF_MORPHOS)
	__asm__ __volatile__ (
	    "mr		%%r12, %0"
	    :: "r"(ObjFWRTBase) : "r12"
	);

	__extension__ ((void (*)(IMP _Nullable, IMP _Nullable))*(void **)(((uintptr_t)ObjFWRTBase) - 394))(forward, stretForward);
#endif
}

void
objc_setEnumerationMutationHandler(objc_enumeration_mutation_handler _Nullable hadler)
{
#if defined(OF_AMIGAOS_M68K)
	register struct Library *a6 __asm__("a6") = ObjFWRTBase;
	(void)a6;
	((void (*)(objc_enumeration_mutation_handler _Nullable __asm__("a0")))(((uintptr_t)ObjFWRTBase) - 402))(hadler);
#elif defined(OF_MORPHOS)
	__asm__ __volatile__ (
	    "mr		%%r12, %0"
	    :: "r"(ObjFWRTBase) : "r12"
	);

	__extension__ ((void (*)(objc_enumeration_mutation_handler _Nullable))*(void **)(((uintptr_t)ObjFWRTBase) - 400))(hadler);
#endif
}

id _Nullable
objc_constructInstance(Class _Nullable class, void *_Nullable bytes)
{
#if defined(OF_AMIGAOS_M68K)
	register struct Library *a6 __asm__("a6") = ObjFWRTBase;
	(void)a6;
	return ((id _Nullable (*)(Class _Nullable __asm__("a0"), void *_Nullable __asm__("a1")))(((uintptr_t)ObjFWRTBase) - 408))(class, bytes);
#elif defined(OF_MORPHOS)
	__asm__ __volatile__ (
	    "mr		%%r12, %0"
	    :: "r"(ObjFWRTBase) : "r12"
	);

	return __extension__ ((id _Nullable (*)(Class _Nullable, void *_Nullable))*(void **)(((uintptr_t)ObjFWRTBase) - 406))(class, bytes);
#endif
}

void
objc_deinit()
{
#if defined(OF_AMIGAOS_M68K)
	register struct Library *a6 __asm__("a6") = ObjFWRTBase;
	(void)a6;
	((void (*)())(((uintptr_t)ObjFWRTBase) - 414))();
#elif defined(OF_MORPHOS)
	__asm__ __volatile__ (
	    "mr		%%r12, %0"
	    :: "r"(ObjFWRTBase) : "r12"
	);

	__extension__ ((void (*)())*(void **)(((uintptr_t)ObjFWRTBase) - 412))();
#endif
}

Ivar _Nullable *_Nullable
class_copyIvarList(Class _Nullable class, unsigned int *_Nullable outCount)
{
#if defined(OF_AMIGAOS_M68K)
	register struct Library *a6 __asm__("a6") = ObjFWRTBase;
	(void)a6;
	return ((Ivar _Nullable *_Nullable (*)(Class _Nullable __asm__("a0"), unsigned int *_Nullable __asm__("a1")))(((uintptr_t)ObjFWRTBase) - 420))(class, outCount);
#elif defined(OF_MORPHOS)
	__asm__ __volatile__ (
	    "mr		%%r12, %0"
	    :: "r"(ObjFWRTBase) : "r12"
	);

	return __extension__ ((Ivar _Nullable *_Nullable (*)(Class _Nullable, unsigned int *_Nullable))*(void **)(((uintptr_t)ObjFWRTBase) - 418))(class, outCount);
#endif
}

const char *_Nonnull
ivar_getName(Ivar _Nonnull ivar)
{
#if defined(OF_AMIGAOS_M68K)
	register struct Library *a6 __asm__("a6") = ObjFWRTBase;
	(void)a6;
	return ((const char *_Nonnull (*)(Ivar _Nonnull __asm__("a0")))(((uintptr_t)ObjFWRTBase) - 426))(ivar);
#elif defined(OF_MORPHOS)
	__asm__ __volatile__ (
	    "mr		%%r12, %0"
	    :: "r"(ObjFWRTBase) : "r12"
	);

	return __extension__ ((const char *_Nonnull (*)(Ivar _Nonnull))*(void **)(((uintptr_t)ObjFWRTBase) - 424))(ivar);
#endif
}

const char *_Nonnull
ivar_getTypeEncoding(Ivar _Nonnull ivar)
{
#if defined(OF_AMIGAOS_M68K)
	register struct Library *a6 __asm__("a6") = ObjFWRTBase;
	(void)a6;
	return ((const char *_Nonnull (*)(Ivar _Nonnull __asm__("a0")))(((uintptr_t)ObjFWRTBase) - 432))(ivar);
#elif defined(OF_MORPHOS)
	__asm__ __volatile__ (
	    "mr		%%r12, %0"
	    :: "r"(ObjFWRTBase) : "r12"
	);

	return __extension__ ((const char *_Nonnull (*)(Ivar _Nonnull))*(void **)(((uintptr_t)ObjFWRTBase) - 430))(ivar);
#endif
}

ptrdiff_t
ivar_getOffset(Ivar _Nonnull ivar)
{
#if defined(OF_AMIGAOS_M68K)
	register struct Library *a6 __asm__("a6") = ObjFWRTBase;
	(void)a6;
	return ((ptrdiff_t (*)(Ivar _Nonnull __asm__("a0")))(((uintptr_t)ObjFWRTBase) - 438))(ivar);
#elif defined(OF_MORPHOS)
	__asm__ __volatile__ (
	    "mr		%%r12, %0"
	    :: "r"(ObjFWRTBase) : "r12"
	);

	return __extension__ ((ptrdiff_t (*)(Ivar _Nonnull))*(void **)(((uintptr_t)ObjFWRTBase) - 436))(ivar);
#endif
}

Method _Nullable *_Nullable
class_copyMethodList(Class _Nullable class, unsigned int *_Nullable outCount)
{
#if defined(OF_AMIGAOS_M68K)
	register struct Library *a6 __asm__("a6") = ObjFWRTBase;
	(void)a6;
	return ((Method _Nullable *_Nullable (*)(Class _Nullable __asm__("a0"), unsigned int *_Nullable __asm__("a1")))(((uintptr_t)ObjFWRTBase) - 444))(class, outCount);
#elif defined(OF_MORPHOS)
	__asm__ __volatile__ (
	    "mr		%%r12, %0"
	    :: "r"(ObjFWRTBase) : "r12"
	);

	return __extension__ ((Method _Nullable *_Nullable (*)(Class _Nullable, unsigned int *_Nullable))*(void **)(((uintptr_t)ObjFWRTBase) - 442))(class, outCount);
#endif
}

SEL _Nonnull
method_getName(Method _Nonnull method)
{
#if defined(OF_AMIGAOS_M68K)
	register struct Library *a6 __asm__("a6") = ObjFWRTBase;
	(void)a6;
	return ((SEL _Nonnull (*)(Method _Nonnull __asm__("a0")))(((uintptr_t)ObjFWRTBase) - 450))(method);
#elif defined(OF_MORPHOS)
	__asm__ __volatile__ (
	    "mr		%%r12, %0"
	    :: "r"(ObjFWRTBase) : "r12"
	);

	return __extension__ ((SEL _Nonnull (*)(Method _Nonnull))*(void **)(((uintptr_t)ObjFWRTBase) - 448))(method);
#endif
}

const char *_Nullable
method_getTypeEncoding(Method _Nonnull method)
{
#if defined(OF_AMIGAOS_M68K)
	register struct Library *a6 __asm__("a6") = ObjFWRTBase;
	(void)a6;
	return ((const char *_Nullable (*)(Method _Nonnull __asm__("a0")))(((uintptr_t)ObjFWRTBase) - 456))(method);
#elif defined(OF_MORPHOS)
	__asm__ __volatile__ (
	    "mr		%%r12, %0"
	    :: "r"(ObjFWRTBase) : "r12"
	);

	return __extension__ ((const char *_Nullable (*)(Method _Nonnull))*(void **)(((uintptr_t)ObjFWRTBase) - 454))(method);
#endif
}

objc_property_t _Nullable *_Nullable
class_copyPropertyList(Class _Nullable class, unsigned int *_Nullable outCount)
{
#if defined(OF_AMIGAOS_M68K)
	register struct Library *a6 __asm__("a6") = ObjFWRTBase;
	(void)a6;
	return ((objc_property_t _Nullable *_Nullable (*)(Class _Nullable __asm__("a0"), unsigned int *_Nullable __asm__("a1")))(((uintptr_t)ObjFWRTBase) - 462))(class, outCount);
#elif defined(OF_MORPHOS)
	__asm__ __volatile__ (
	    "mr		%%r12, %0"
	    :: "r"(ObjFWRTBase) : "r12"
	);

	return __extension__ ((objc_property_t _Nullable *_Nullable (*)(Class _Nullable, unsigned int *_Nullable))*(void **)(((uintptr_t)ObjFWRTBase) - 460))(class, outCount);
#endif
}

const char *_Nonnull
property_getName(objc_property_t _Nonnull property)
{
#if defined(OF_AMIGAOS_M68K)
	register struct Library *a6 __asm__("a6") = ObjFWRTBase;
	(void)a6;
	return ((const char *_Nonnull (*)(objc_property_t _Nonnull __asm__("a0")))(((uintptr_t)ObjFWRTBase) - 468))(property);
#elif defined(OF_MORPHOS)
	__asm__ __volatile__ (
	    "mr		%%r12, %0"
	    :: "r"(ObjFWRTBase) : "r12"
	);

	return __extension__ ((const char *_Nonnull (*)(objc_property_t _Nonnull))*(void **)(((uintptr_t)ObjFWRTBase) - 466))(property);
#endif
}

char *_Nullable
property_copyAttributeValue(objc_property_t _Nonnull property, const char *_Nonnull name)
{
#if defined(OF_AMIGAOS_M68K)
	register struct Library *a6 __asm__("a6") = ObjFWRTBase;
	(void)a6;
	return ((char *_Nullable (*)(objc_property_t _Nonnull __asm__("a0"), const char *_Nonnull __asm__("a1")))(((uintptr_t)ObjFWRTBase) - 474))(property, name);
#elif defined(OF_MORPHOS)
	__asm__ __volatile__ (
	    "mr		%%r12, %0"
	    :: "r"(ObjFWRTBase) : "r12"
	);

	return __extension__ ((char *_Nullable (*)(objc_property_t _Nonnull, const char *_Nonnull))*(void **)(((uintptr_t)ObjFWRTBase) - 472))(property, name);
#endif
}

void *_Nullable
objc_destructInstance(id _Nullable object)
{
#if defined(OF_AMIGAOS_M68K)
	register struct Library *a6 __asm__("a6") = ObjFWRTBase;
	(void)a6;
	return ((void *_Nullable (*)(id _Nullable __asm__("a0")))(((uintptr_t)ObjFWRTBase) - 480))(object);
#elif defined(OF_MORPHOS)
	__asm__ __volatile__ (
	    "mr		%%r12, %0"
	    :: "r"(ObjFWRTBase) : "r12"
	);

	return __extension__ ((void *_Nullable (*)(id _Nullable))*(void **)(((uintptr_t)ObjFWRTBase) - 478))(object);
#endif
}

void *_Null_unspecified
objc_autoreleasePoolPush()
{
#if defined(OF_AMIGAOS_M68K)
	register struct Library *a6 __asm__("a6") = ObjFWRTBase;
	(void)a6;
	return ((void *_Null_unspecified (*)())(((uintptr_t)ObjFWRTBase) - 486))();
#elif defined(OF_MORPHOS)
	__asm__ __volatile__ (
	    "mr		%%r12, %0"
	    :: "r"(ObjFWRTBase) : "r12"
	);

	return __extension__ ((void *_Null_unspecified (*)())*(void **)(((uintptr_t)ObjFWRTBase) - 484))();
#endif
}

void
objc_autoreleasePoolPop(void *_Null_unspecified pool)
{
#if defined(OF_AMIGAOS_M68K)
	register struct Library *a6 __asm__("a6") = ObjFWRTBase;
	(void)a6;
	((void (*)(void *_Null_unspecified __asm__("a0")))(((uintptr_t)ObjFWRTBase) - 492))(pool);
#elif defined(OF_MORPHOS)
	__asm__ __volatile__ (
	    "mr		%%r12, %0"
	    :: "r"(ObjFWRTBase) : "r12"
	);

	__extension__ ((void (*)(void *_Null_unspecified))*(void **)(((uintptr_t)ObjFWRTBase) - 490))(pool);
#endif
}

id _Nullable
_objc_rootAutorelease(id _Nullable object)
{
#if defined(OF_AMIGAOS_M68K)
	register struct Library *a6 __asm__("a6") = ObjFWRTBase;
	(void)a6;
	return ((id _Nullable (*)(id _Nullable __asm__("a0")))(((uintptr_t)ObjFWRTBase) - 498))(object);
#elif defined(OF_MORPHOS)
	__asm__ __volatile__ (
	    "mr		%%r12, %0"
	    :: "r"(ObjFWRTBase) : "r12"
	);

	return __extension__ ((id _Nullable (*)(id _Nullable))*(void **)(((uintptr_t)ObjFWRTBase) - 496))(object);
#endif
}

struct objc_hashtable *_Nonnull
objc_hashtable_new(objc_hashtable_hash_func hash, objc_hashtable_equal_func equal, uint32_t size)
{
#if defined(OF_AMIGAOS_M68K)
	register struct Library *a6 __asm__("a6") = ObjFWRTBase;
	(void)a6;
	return ((struct objc_hashtable *_Nonnull (*)(objc_hashtable_hash_func __asm__("a0"), objc_hashtable_equal_func __asm__("a1"), uint32_t __asm__("d0")))(((uintptr_t)ObjFWRTBase) - 504))(hash, equal, size);
#elif defined(OF_MORPHOS)
	__asm__ __volatile__ (
	    "mr		%%r12, %0"
	    :: "r"(ObjFWRTBase) : "r12"
	);

	return __extension__ ((struct objc_hashtable *_Nonnull (*)(objc_hashtable_hash_func, objc_hashtable_equal_func, uint32_t))*(void **)(((uintptr_t)ObjFWRTBase) - 502))(hash, equal, size);
#endif
}

void
objc_hashtable_set(struct objc_hashtable *_Nonnull table, const void *_Nonnull key, const void *_Nonnull object)
{
#if defined(OF_AMIGAOS_M68K)
	register struct Library *a6 __asm__("a6") = ObjFWRTBase;
	(void)a6;
	((void (*)(struct objc_hashtable *_Nonnull __asm__("a0"), const void *_Nonnull __asm__("a1"), const void *_Nonnull __asm__("a2")))(((uintptr_t)ObjFWRTBase) - 510))(table, key, object);
#elif defined(OF_MORPHOS)
	__asm__ __volatile__ (
	    "mr		%%r12, %0"
	    :: "r"(ObjFWRTBase) : "r12"
	);

	__extension__ ((void (*)(struct objc_hashtable *_Nonnull, const void *_Nonnull, const void *_Nonnull))*(void **)(((uintptr_t)ObjFWRTBase) - 508))(table, key, object);
#endif
}

void *_Nullable
objc_hashtable_get(struct objc_hashtable *_Nonnull table, const void *_Nonnull key)
{
#if defined(OF_AMIGAOS_M68K)
	register struct Library *a6 __asm__("a6") = ObjFWRTBase;
	(void)a6;
	return ((void *_Nullable (*)(struct objc_hashtable *_Nonnull __asm__("a0"), const void *_Nonnull __asm__("a1")))(((uintptr_t)ObjFWRTBase) - 516))(table, key);
#elif defined(OF_MORPHOS)
	__asm__ __volatile__ (
	    "mr		%%r12, %0"
	    :: "r"(ObjFWRTBase) : "r12"
	);

	return __extension__ ((void *_Nullable (*)(struct objc_hashtable *_Nonnull, const void *_Nonnull))*(void **)(((uintptr_t)ObjFWRTBase) - 514))(table, key);
#endif
}

void
objc_hashtable_delete(struct objc_hashtable *_Nonnull table, const void *_Nonnull key)
{
#if defined(OF_AMIGAOS_M68K)
	register struct Library *a6 __asm__("a6") = ObjFWRTBase;
	(void)a6;
	((void (*)(struct objc_hashtable *_Nonnull __asm__("a0"), const void *_Nonnull __asm__("a1")))(((uintptr_t)ObjFWRTBase) - 522))(table, key);
#elif defined(OF_MORPHOS)
	__asm__ __volatile__ (
	    "mr		%%r12, %0"
	    :: "r"(ObjFWRTBase) : "r12"
	);

	__extension__ ((void (*)(struct objc_hashtable *_Nonnull, const void *_Nonnull))*(void **)(((uintptr_t)ObjFWRTBase) - 520))(table, key);
#endif
}

void
objc_hashtable_free(struct objc_hashtable *_Nonnull table)
{
#if defined(OF_AMIGAOS_M68K)
	register struct Library *a6 __asm__("a6") = ObjFWRTBase;
	(void)a6;
	((void (*)(struct objc_hashtable *_Nonnull __asm__("a0")))(((uintptr_t)ObjFWRTBase) - 528))(table);
#elif defined(OF_MORPHOS)
	__asm__ __volatile__ (
	    "mr		%%r12, %0"
	    :: "r"(ObjFWRTBase) : "r12"
	);

	__extension__ ((void (*)(struct objc_hashtable *_Nonnull))*(void **)(((uintptr_t)ObjFWRTBase) - 526))(table);
#endif
}

void
objc_setTaggedPointerSecret(uintptr_t secret)
{
#if defined(OF_AMIGAOS_M68K)
	register struct Library *a6 __asm__("a6") = ObjFWRTBase;
	(void)a6;
	((void (*)(uintptr_t __asm__("d0")))(((uintptr_t)ObjFWRTBase) - 534))(secret);
#elif defined(OF_MORPHOS)
	__asm__ __volatile__ (
	    "mr		%%r12, %0"
	    :: "r"(ObjFWRTBase) : "r12"
	);

	__extension__ ((void (*)(uintptr_t))*(void **)(((uintptr_t)ObjFWRTBase) - 532))(secret);
#endif
}

int
objc_registerTaggedPointerClass(Class _Nonnull class)
{
#if defined(OF_AMIGAOS_M68K)
	register struct Library *a6 __asm__("a6") = ObjFWRTBase;
	(void)a6;
	return ((int (*)(Class _Nonnull __asm__("a0")))(((uintptr_t)ObjFWRTBase) - 540))(class);
#elif defined(OF_MORPHOS)
	__asm__ __volatile__ (
	    "mr		%%r12, %0"
	    :: "r"(ObjFWRTBase) : "r12"
	);

	return __extension__ ((int (*)(Class _Nonnull))*(void **)(((uintptr_t)ObjFWRTBase) - 538))(class);
#endif
}

bool
object_isTaggedPointer(id _Nullable object)
{
#if defined(OF_AMIGAOS_M68K)
	register struct Library *a6 __asm__("a6") = ObjFWRTBase;
	(void)a6;
	return ((bool (*)(id _Nullable __asm__("a0")))(((uintptr_t)ObjFWRTBase) - 546))(object);
#elif defined(OF_MORPHOS)
	__asm__ __volatile__ (
	    "mr		%%r12, %0"
	    :: "r"(ObjFWRTBase) : "r12"
	);

	return __extension__ ((bool (*)(id _Nullable))*(void **)(((uintptr_t)ObjFWRTBase) - 544))(object);
#endif
}

uintptr_t
object_getTaggedPointerValue(id _Nonnull object)
{
#if defined(OF_AMIGAOS_M68K)
	register struct Library *a6 __asm__("a6") = ObjFWRTBase;
	(void)a6;
	return ((uintptr_t (*)(id _Nonnull __asm__("a0")))(((uintptr_t)ObjFWRTBase) - 552))(object);
#elif defined(OF_MORPHOS)
	__asm__ __volatile__ (
	    "mr		%%r12, %0"
	    :: "r"(ObjFWRTBase) : "r12"
	);

	return __extension__ ((uintptr_t (*)(id _Nonnull))*(void **)(((uintptr_t)ObjFWRTBase) - 550))(object);
#endif
}

id _Nullable
objc_createTaggedPointer(int class, uintptr_t value)
{
#if defined(OF_AMIGAOS_M68K)
	register struct Library *a6 __asm__("a6") = ObjFWRTBase;
	(void)a6;
	return ((id _Nullable (*)(int __asm__("d0"), uintptr_t __asm__("d1")))(((uintptr_t)ObjFWRTBase) - 558))(class, value);
#elif defined(OF_MORPHOS)
	__asm__ __volatile__ (
	    "mr		%%r12, %0"
	    :: "r"(ObjFWRTBase) : "r12"
	);

	return __extension__ ((id _Nullable (*)(int, uintptr_t))*(void **)(((uintptr_t)ObjFWRTBase) - 556))(class, value);
#endif
}
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<




































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































Modified src/runtime/lookup-asm/Makefile from [3c7b7f7fc1] to [a8b7579307].

1
2
3
4
5
6
7
8
9
10
11
12
include ../../../extra.mk

STATIC_PIC_LIB_NOINST = ${LOOKUP_ASM_LIB_A}
STATIC_AMIGA_LIB_NOINST = ${LOOKUP_ASM_AMIGALIB_A}
STATIC_LIB_NOINST = ${LOOKUP_ASM_A}

SRCS = lookup-asm.S

include ../../../buildsys.mk

ASFLAGS += -I../../.. -I../..
ASFLAGS_lookup-asm.amigalib.o += -DOF_BASEREL



<







<
1
2
3

4
5
6
7
8
9
10

include ../../../extra.mk

STATIC_PIC_LIB_NOINST = ${LOOKUP_ASM_LIB_A}

STATIC_LIB_NOINST = ${LOOKUP_ASM_A}

SRCS = lookup-asm.S

include ../../../buildsys.mk

ASFLAGS += -I../../.. -I../..

Renamed and modified src/runtime/lookup-asm/lookup-asm-x86_64-elf.S [63daf9ee68] to src/runtime/lookup-asm/lookup-asm-amd64-elf.S [d99537b0fa].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
.globl objc_msg_lookup_super
.globl objc_msg_lookup_super_stret

.section .text
.macro GENERATE_LOOKUP name notFound
\name:
	testq	%rdi, %rdi
	jz	returnNilMethod

	testb	$1, %dil
	jnz	.LtaggedPointer_\name

	movq	(%rdi), %r8
	movq	64(%r8), %r8








|







22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
.globl objc_msg_lookup_super
.globl objc_msg_lookup_super_stret

.section .text
.macro GENERATE_LOOKUP name notFound
\name:
	testq	%rdi, %rdi
	jz	.LreturnNilMethod

	testb	$1, %dil
	jnz	.LtaggedPointer_\name

	movq	(%rdi), %r8
	movq	64(%r8), %r8

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
.endm

.macro GENERATE_LOOKUP_SUPER name lookup
\name:
	movq	%rdi, %r8
	movq	(%rdi), %rdi
	testq	%rdi, %rdi
	jz	returnNilMethod

	movq	8(%r8), %r8
	movq	64(%r8), %r8
	jmp	.Lmain_\lookup
.type \name, %function
.size \name, .-\name
.endm

GENERATE_LOOKUP objc_msg_lookup objc_methodNotFound
GENERATE_LOOKUP objc_msg_lookup_stret objc_methodNotFound_stret
GENERATE_LOOKUP_SUPER objc_msg_lookup_super objc_msg_lookup
GENERATE_LOOKUP_SUPER objc_msg_lookup_super_stret objc_msg_lookup_stret

returnNilMethod:
	leaq	nilMethod(%rip), %rax
	ret

nilMethod:
	xorq	%rax, %rax
	ret

#ifdef OF_LINUX
.section .note.GNU-stack, "", %progbits
#endif







|













|
|


|



|


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
.endm

.macro GENERATE_LOOKUP_SUPER name lookup
\name:
	movq	%rdi, %r8
	movq	(%rdi), %rdi
	testq	%rdi, %rdi
	jz	.LreturnNilMethod

	movq	8(%r8), %r8
	movq	64(%r8), %r8
	jmp	.Lmain_\lookup
.type \name, %function
.size \name, .-\name
.endm

GENERATE_LOOKUP objc_msg_lookup objc_methodNotFound
GENERATE_LOOKUP objc_msg_lookup_stret objc_methodNotFound_stret
GENERATE_LOOKUP_SUPER objc_msg_lookup_super objc_msg_lookup
GENERATE_LOOKUP_SUPER objc_msg_lookup_super_stret objc_msg_lookup_stret

.LreturnNilMethod:
	leaq	.LnilMethod(%rip), %rax
	ret

.LnilMethod:
	xorq	%rax, %rax
	ret

#if defined(OF_LINUX) || defined(OF_HAIKU) || defined(OF_HURD)
.section .note.GNU-stack, "", %progbits
#endif

Renamed and modified src/runtime/lookup-asm/lookup-asm-x86_64-macho.S [1e72bfb083] to src/runtime/lookup-asm/lookup-asm-amd64-macho.S [77b3efe9ac].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
.globl _objc_msg_lookup_super
.globl _objc_msg_lookup_super_stret

.section __TEXT, __text, regular, pure_instructions
.macro GENERATE_LOOKUP
$0:
	testq	%rdi, %rdi
	jz	returnNilMethod

	testb	$$1, %dil
	jnz	LtaggedPointer_$0

	movq	(%rdi), %r8
	movq	64(%r8), %r8








|







20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
.globl _objc_msg_lookup_super
.globl _objc_msg_lookup_super_stret

.section __TEXT, __text, regular, pure_instructions
.macro GENERATE_LOOKUP
$0:
	testq	%rdi, %rdi
	jz	LreturnNilMethod

	testb	$$1, %dil
	jnz	LtaggedPointer_$0

	movq	(%rdi), %r8
	movq	64(%r8), %r8

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
.endmacro

.macro GENERATE_LOOKUP_SUPER
$0:
	movq	%rdi, %r8
	movq	(%rdi), %rdi
	testq	%rdi, %rdi
	jz	returnNilMethod

	movq	8(%r8), %r8
	movq	64(%r8), %r8
	jmp	Lmain_$1
.endmacro

GENERATE_LOOKUP _objc_msg_lookup, _objc_methodNotFound
GENERATE_LOOKUP _objc_msg_lookup_stret, _objc_methodNotFound_stret
GENERATE_LOOKUP_SUPER _objc_msg_lookup_super, _objc_msg_lookup
GENERATE_LOOKUP_SUPER _objc_msg_lookup_super_stret, _objc_msg_lookup_stret

returnNilMethod:
	leaq	nilMethod(%rip), %rax
	ret

nilMethod:
	xorq	%rax, %rax
	ret







|











|
|


|


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
.endmacro

.macro GENERATE_LOOKUP_SUPER
$0:
	movq	%rdi, %r8
	movq	(%rdi), %rdi
	testq	%rdi, %rdi
	jz	LreturnNilMethod

	movq	8(%r8), %r8
	movq	64(%r8), %r8
	jmp	Lmain_$1
.endmacro

GENERATE_LOOKUP _objc_msg_lookup, _objc_methodNotFound
GENERATE_LOOKUP _objc_msg_lookup_stret, _objc_methodNotFound_stret
GENERATE_LOOKUP_SUPER _objc_msg_lookup_super, _objc_msg_lookup
GENERATE_LOOKUP_SUPER _objc_msg_lookup_super_stret, _objc_msg_lookup_stret

LreturnNilMethod:
	leaq	LnilMethod(%rip), %rax
	ret

LnilMethod:
	xorq	%rax, %rax
	ret

Renamed and modified src/runtime/lookup-asm/lookup-asm-x86_64-win64.S [bb874856c9] to src/runtime/lookup-asm/lookup-asm-amd64-win64.S [c432b0ebda].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
.globl objc_msg_lookup_super
.globl objc_msg_lookup_super_stret

.section .text
.macro GENERATE_LOOKUP name notFound
\name:
	testq	%rcx, %rcx
	jz	returnNilMethod

	testb	$1, %cl
	jnz	.LtaggedPointer_\name

	movq	(%rcx), %r8
	movq	56(%r8), %r8








|







20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
.globl objc_msg_lookup_super
.globl objc_msg_lookup_super_stret

.section .text
.macro GENERATE_LOOKUP name notFound
\name:
	testq	%rcx, %rcx
	jz	.LreturnNilMethod

	testb	$1, %cl
	jnz	.LtaggedPointer_\name

	movq	(%rcx), %r8
	movq	56(%r8), %r8

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
.endm

.macro GENERATE_LOOKUP_SUPER name lookup
\name:
	movq	%rcx, %r8
	movq	(%rcx), %rcx
	testq	%rcx, %rcx
	jz	returnNilMethod

	movq	8(%r8), %r8
	movq	56(%r8), %r8
	jmp	.Lmain_\lookup
.def \name
.scl 2
.type 32
.endef
.endm

GENERATE_LOOKUP objc_msg_lookup objc_methodNotFound
GENERATE_LOOKUP objc_msg_lookup_stret objc_methodNotFound_stret
GENERATE_LOOKUP_SUPER objc_msg_lookup_super objc_msg_lookup
GENERATE_LOOKUP_SUPER objc_msg_lookup_super_stret objc_msg_lookup_stret

returnNilMethod:
	leaq	nilMethod(%rip), %rax
	ret

nilMethod:
	xorq	%rax, %rax
	ret







|















|
|


|


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
.endm

.macro GENERATE_LOOKUP_SUPER name lookup
\name:
	movq	%rcx, %r8
	movq	(%rcx), %rcx
	testq	%rcx, %rcx
	jz	.LreturnNilMethod

	movq	8(%r8), %r8
	movq	56(%r8), %r8
	jmp	.Lmain_\lookup
.def \name
.scl 2
.type 32
.endef
.endm

GENERATE_LOOKUP objc_msg_lookup objc_methodNotFound
GENERATE_LOOKUP objc_msg_lookup_stret objc_methodNotFound_stret
GENERATE_LOOKUP_SUPER objc_msg_lookup_super objc_msg_lookup
GENERATE_LOOKUP_SUPER objc_msg_lookup_super_stret objc_msg_lookup_stret

.LreturnNilMethod:
	leaq	.LnilMethod(%rip), %rax
	ret

.LnilMethod:
	xorq	%rax, %rax
	ret

Modified src/runtime/lookup-asm/lookup-asm-arm-elf.S from [f0e5b05f4e] to [d09f6fcb9f].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
.globl objc_msg_lookup_super
.globl objc_msg_lookup_super_stret

.section .text
.macro GENERATE_LOOKUP name notFound
\name:
	cmp	r0, #0
	beq	returnNilMethod

	tst	r0, #1
	bne	.LtaggedPointer_\name

	ldr	r2, [r0, #0]
	ldr	r2, [r2, #32]








|







22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
.globl objc_msg_lookup_super
.globl objc_msg_lookup_super_stret

.section .text
.macro GENERATE_LOOKUP name notFound
\name:
	cmp	r0, #0
	beq	.LreturnNilMethod

	tst	r0, #1
	bne	.LtaggedPointer_\name

	ldr	r2, [r0, #0]
	ldr	r2, [r2, #32]

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
.endm

.macro GENERATE_LOOKUP_SUPER name lookup
\name:
	mov	r2, r0
	ldr	r0, [r0, #0]
	cmp	r0, #0
	beq	returnNilMethod

	ldr	r2, [r2, #4]
	ldr	r2, [r2, #32]

	b	.Lmain_\lookup
.type \name, %function
.size \name, .-\name
.endm

GENERATE_LOOKUP objc_msg_lookup objc_methodNotFound
GENERATE_LOOKUP objc_msg_lookup_stret objc_methodNotFound_stret
GENERATE_LOOKUP_SUPER objc_msg_lookup_super objc_msg_lookup
GENERATE_LOOKUP_SUPER objc_msg_lookup_super_stret objc_msg_lookup_stret

returnNilMethod:
	adr	r0, nilMethod
	bx	lr

nilMethod:
	mov	r0, #0
	bx	lr

#ifdef OF_LINUX
.section .note.GNU-stack, "", %progbits
#endif







|














|
|


|



|


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
.endm

.macro GENERATE_LOOKUP_SUPER name lookup
\name:
	mov	r2, r0
	ldr	r0, [r0, #0]
	cmp	r0, #0
	beq	.LreturnNilMethod

	ldr	r2, [r2, #4]
	ldr	r2, [r2, #32]

	b	.Lmain_\lookup
.type \name, %function
.size \name, .-\name
.endm

GENERATE_LOOKUP objc_msg_lookup objc_methodNotFound
GENERATE_LOOKUP objc_msg_lookup_stret objc_methodNotFound_stret
GENERATE_LOOKUP_SUPER objc_msg_lookup_super objc_msg_lookup
GENERATE_LOOKUP_SUPER objc_msg_lookup_super_stret objc_msg_lookup_stret

.LreturnNilMethod:
	adr	r0, .LnilMethod
	bx	lr

.LnilMethod:
	mov	r0, #0
	bx	lr

#if defined(OF_LINUX) || defined(OF_HAIKU) || defined(OF_HURD)
.section .note.GNU-stack, "", %progbits
#endif

Modified src/runtime/lookup-asm/lookup-asm-arm64-elf.S from [ad3c36fa42] to [3f3a340787].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
.globl objc_msg_lookup_stret
.globl objc_msg_lookup_super
.globl objc_msg_lookup_super_stret

.section .text
.macro GENERATE_LOOKUP name notFound
\name:
	cbz	x0, returnNilMethod

	tst	x0, #1
	b.ne	.LtaggedPointer_\name

	ldr	x2, [x0]
	ldr	x2, [x2, #64]








|







21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
.globl objc_msg_lookup_stret
.globl objc_msg_lookup_super
.globl objc_msg_lookup_super_stret

.section .text
.macro GENERATE_LOOKUP name notFound
\name:
	cbz	x0, .LreturnNilMethod

	tst	x0, #1
	b.ne	.LtaggedPointer_\name

	ldr	x2, [x0]
	ldr	x2, [x2, #64]

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
.size \name, .-\name
.endm

.macro GENERATE_LOOKUP_SUPER name lookup
\name:
	mov	x2, x0
	ldr	x0, [x0]
	cbz	x0, returnNilMethod

	ldr	x2, [x2, #8]
	ldr	x2, [x2, #64]

	b	.Lmain_\lookup
.type \name, %function
.size \name, .-\name
.endm

GENERATE_LOOKUP objc_msg_lookup objc_methodNotFound
GENERATE_LOOKUP objc_msg_lookup_stret objc_methodNotFound_stret
GENERATE_LOOKUP_SUPER objc_msg_lookup_super objc_msg_lookup
GENERATE_LOOKUP_SUPER objc_msg_lookup_super_stret objc_msg_lookup_stret

returnNilMethod:
	adr	x0, nilMethod
	ret

nilMethod:
	mov	x0, #0
	ret

#ifdef OF_LINUX
.section .note.GNU-stack, "", %progbits
#endif







|














|
|


|



|


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
.size \name, .-\name
.endm

.macro GENERATE_LOOKUP_SUPER name lookup
\name:
	mov	x2, x0
	ldr	x0, [x0]
	cbz	x0, .LreturnNilMethod

	ldr	x2, [x2, #8]
	ldr	x2, [x2, #64]

	b	.Lmain_\lookup
.type \name, %function
.size \name, .-\name
.endm

GENERATE_LOOKUP objc_msg_lookup objc_methodNotFound
GENERATE_LOOKUP objc_msg_lookup_stret objc_methodNotFound_stret
GENERATE_LOOKUP_SUPER objc_msg_lookup_super objc_msg_lookup
GENERATE_LOOKUP_SUPER objc_msg_lookup_super_stret objc_msg_lookup_stret

.LreturnNilMethod:
	adr	x0, .LnilMethod
	ret

.LnilMethod:
	mov	x0, #0
	ret

#if defined(OF_LINUX) || defined(OF_HAIKU) || defined(OF_HURD)
.section .note.GNU-stack, "", %progbits
#endif

Modified src/runtime/lookup-asm/lookup-asm-mips-elf.S from [c727ce9d5a] to [3af172b4a7].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
#endif

	move	$v0, $t0
	jr	$ra

0:
#ifdef OF_PIC
	addiu	$v0, $t9, nilMethod-\name
#else
	la	$v0, nilMethod
#endif
	jr	$ra

#ifdef OF_PIC
1:
	lui	$gp, %hi(_gp_disp)
	addiu	$gp, $gp, %lo(_gp_disp)







|

|







70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
#endif

	move	$v0, $t0
	jr	$ra

0:
#ifdef OF_PIC
	addiu	$v0, $t9, .LnilMethod-\name
#else
	la	$v0, .LnilMethod
#endif
	jr	$ra

#ifdef OF_PIC
1:
	lui	$gp, %hi(_gp_disp)
	addiu	$gp, $gp, %lo(_gp_disp)
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
	lw	$t0, 32($t0)

	addiu	$t9, $t9, \lookup-\name
	b	.Lmain_\lookup

0:
#ifdef OF_PIC
	addiu	$v0, $t9, nilMethod-\name
#else
	la	$v0, nilMethod
#endif
	jr	$ra
.type \name, %function
.size \name, .-\name
.endm

GENERATE_LOOKUP objc_msg_lookup objc_methodNotFound
GENERATE_LOOKUP objc_msg_lookup_stret objc_methodNotFound_stret
GENERATE_LOOKUP_SUPER objc_msg_lookup_super objc_msg_lookup
GENERATE_LOOKUP_SUPER objc_msg_lookup_super_stret objc_msg_lookup_stret

nilMethod:
	move	$v0, $zero
	jr	$ra

#ifdef OF_LINUX
.section .note.GNU-stack, "", %progbits
#endif







|

|











|



|


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
	lw	$t0, 32($t0)

	addiu	$t9, $t9, \lookup-\name
	b	.Lmain_\lookup

0:
#ifdef OF_PIC
	addiu	$v0, $t9, .LnilMethod-\name
#else
	la	$v0, .LnilMethod
#endif
	jr	$ra
.type \name, %function
.size \name, .-\name
.endm

GENERATE_LOOKUP objc_msg_lookup objc_methodNotFound
GENERATE_LOOKUP objc_msg_lookup_stret objc_methodNotFound_stret
GENERATE_LOOKUP_SUPER objc_msg_lookup_super objc_msg_lookup
GENERATE_LOOKUP_SUPER objc_msg_lookup_super_stret objc_msg_lookup_stret

.LnilMethod:
	move	$v0, $zero
	jr	$ra

#if defined(OF_LINUX) || defined(OF_HAIKU) || defined(OF_HURD)
.section .note.GNU-stack, "", %progbits
#endif

Modified src/runtime/lookup-asm/lookup-asm-mips64-n64-elf.S from [53637868a6] to [f8bea93ee9].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
	move	$v0, $t0
	jr	$ra

0:
	lui	$v0, %hi(%neg(%gp_rel(\name)))
	daddiu	$v0, $v0, %lo(%neg(%gp_rel(\name)))
	daddu	$v0, $v0, $t9
	ld	$v0, %got_disp(nilMethod)($v0)
	jr	$ra

1:
	lui	$t0, %hi(%neg(%gp_rel(\name)))
	daddiu	$t0, $t0, %lo(%neg(%gp_rel(\name)))
	daddu	$t0, $t0, $t9
	ld	$t9, %got_disp(\notFound)($t0)







|







68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
	move	$v0, $t0
	jr	$ra

0:
	lui	$v0, %hi(%neg(%gp_rel(\name)))
	daddiu	$v0, $v0, %lo(%neg(%gp_rel(\name)))
	daddu	$v0, $v0, $t9
	ld	$v0, %got_disp(.LnilMethod)($v0)
	jr	$ra

1:
	lui	$t0, %hi(%neg(%gp_rel(\name)))
	daddiu	$t0, $t0, %lo(%neg(%gp_rel(\name)))
	daddu	$t0, $t0, $t9
	ld	$t9, %got_disp(\notFound)($t0)
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
	daddiu	$t9, $t9, \lookup-\name
	b	.Lmain_\lookup

0:
	lui	$v0, %hi(%neg(%gp_rel(\name)))
	daddiu	$v0, $v0, %lo(%neg(%gp_rel(\name)))
	daddu	$v0, $v0, $t9
	ld	$v0, %got_disp(nilMethod)($v0)
	jr	$ra
.type \name, %function
.size \name, .-\name
.endm

GENERATE_LOOKUP objc_msg_lookup objc_methodNotFound
GENERATE_LOOKUP objc_msg_lookup_stret objc_methodNotFound_stret
GENERATE_LOOKUP_SUPER objc_msg_lookup_super objc_msg_lookup
GENERATE_LOOKUP_SUPER objc_msg_lookup_super_stret objc_msg_lookup_stret

nilMethod:
	move	$v0, $zero
	jr	$ra

#ifdef OF_LINUX
.section .note.GNU-stack, "", %progbits
#endif







|










|



|


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
	daddiu	$t9, $t9, \lookup-\name
	b	.Lmain_\lookup

0:
	lui	$v0, %hi(%neg(%gp_rel(\name)))
	daddiu	$v0, $v0, %lo(%neg(%gp_rel(\name)))
	daddu	$v0, $v0, $t9
	ld	$v0, %got_disp(.LnilMethod)($v0)
	jr	$ra
.type \name, %function
.size \name, .-\name
.endm

GENERATE_LOOKUP objc_msg_lookup objc_methodNotFound
GENERATE_LOOKUP objc_msg_lookup_stret objc_methodNotFound_stret
GENERATE_LOOKUP_SUPER objc_msg_lookup_super objc_msg_lookup
GENERATE_LOOKUP_SUPER objc_msg_lookup_super_stret objc_msg_lookup_stret

.LnilMethod:
	move	$v0, $zero
	jr	$ra

#if defined(OF_LINUX) || defined(OF_HAIKU) || defined(OF_HURD)
.section .note.GNU-stack, "", %progbits
#endif

Modified src/runtime/lookup-asm/lookup-asm-powerpc-elf.S from [134bfef460] to [2c45573f75].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
.globl objc_msg_lookup_super
.globl objc_msg_lookup_super_stret

.section .text
.macro GENERATE_LOOKUP name notFound
\name:
	cmpwi	%r3, 0
	beq-	returnNilMethod

	andi.	%r0, %r3, 1
	bne-	.LtaggedPointer_\name

	lwz	%r5, 0(%r3)
	lwz	%r5, 32(%r5)








|







22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
.globl objc_msg_lookup_super
.globl objc_msg_lookup_super_stret

.section .text
.macro GENERATE_LOOKUP name notFound
\name:
	cmpwi	%r3, 0
	beq-	.LreturnNilMethod

	andi.	%r0, %r3, 1
	bne-	.LtaggedPointer_\name

	lwz	%r5, 0(%r3)
	lwz	%r5, 32(%r5)

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
.endm

.macro GENERATE_LOOKUP_SUPER name lookup
\name:
	mr	%r5, %r3
	lwz	%r3, 0(%r3)
	cmpwi	%r3, 0
	beq-	returnNilMethod

	lwz	%r5, 4(%r5)
	lwz	%r5, 32(%r5)

	b	.Lmain_\lookup
.type \name, @function
.size \name, .-\name
.endm

GENERATE_LOOKUP objc_msg_lookup objc_methodNotFound
GENERATE_LOOKUP objc_msg_lookup_stret objc_methodNotFound_stret
GENERATE_LOOKUP_SUPER objc_msg_lookup_super objc_msg_lookup
GENERATE_LOOKUP_SUPER objc_msg_lookup_super_stret objc_msg_lookup_stret

returnNilMethod:
	mflr	%r0
	bl	getPC
	mtlr	%r0
0:
	addi	%r3, %r3, nilMethod-0b
	blr

nilMethod:
	li	%r3, 0
	blr

getPC:
	mflr	%r3
	blr

#ifdef OF_PIC
.section .got2, "aw"
.Lbiased_got2 = .+0x8000
.Lgot_objc_methodNotFound:
	.long objc_methodNotFound
.Lgot_objc_methodNotFound_stret:
	.long objc_methodNotFound_stret
.Lgot_objc_taggedPointerSecret:
	.long objc_taggedPointerSecret
.Lgot_objc_taggedPointerClasses:
	.long objc_taggedPointerClasses
#endif

#ifdef OF_LINUX
.section .note.GNU-stack, "", @progbits
#endif







|














|

|


|


|



|
















|


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
.endm

.macro GENERATE_LOOKUP_SUPER name lookup
\name:
	mr	%r5, %r3
	lwz	%r3, 0(%r3)
	cmpwi	%r3, 0
	beq-	.LreturnNilMethod

	lwz	%r5, 4(%r5)
	lwz	%r5, 32(%r5)

	b	.Lmain_\lookup
.type \name, @function
.size \name, .-\name
.endm

GENERATE_LOOKUP objc_msg_lookup objc_methodNotFound
GENERATE_LOOKUP objc_msg_lookup_stret objc_methodNotFound_stret
GENERATE_LOOKUP_SUPER objc_msg_lookup_super objc_msg_lookup
GENERATE_LOOKUP_SUPER objc_msg_lookup_super_stret objc_msg_lookup_stret

.LreturnNilMethod:
	mflr	%r0
	bl	.LgetPC
	mtlr	%r0
0:
	addi	%r3, %r3, .LnilMethod-0b
	blr

.LnilMethod:
	li	%r3, 0
	blr

.LgetPC:
	mflr	%r3
	blr

#ifdef OF_PIC
.section .got2, "aw"
.Lbiased_got2 = .+0x8000
.Lgot_objc_methodNotFound:
	.long objc_methodNotFound
.Lgot_objc_methodNotFound_stret:
	.long objc_methodNotFound_stret
.Lgot_objc_taggedPointerSecret:
	.long objc_taggedPointerSecret
.Lgot_objc_taggedPointerClasses:
	.long objc_taggedPointerClasses
#endif

#if defined(OF_LINUX) || defined(OF_HAIKU) || defined(OF_HURD)
.section .note.GNU-stack, "", @progbits
#endif

Modified src/runtime/lookup-asm/lookup-asm-powerpc64-elf.S from [8516ac090f] to [3f0a2be9c2].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
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

GENERATE_LOOKUP objc_msg_lookup objc_methodNotFound
GENERATE_LOOKUP objc_msg_lookup_stret objc_methodNotFound_stret
GENERATE_LOOKUP_SUPER objc_msg_lookup_super objc_msg_lookup
GENERATE_LOOKUP_SUPER objc_msg_lookup_super_stret objc_msg_lookup_stret

.LreturnNilMethod:
	addis	%r3, %r2, nilMethod@toc@ha
	addi	%r3, %r3, nilMethod@toc@l
	blr

#if defined(_CALL_ELF) && _CALL_ELF == 2
nilMethod:
	addis	%r2, %r12, .TOC.-nilMethod@ha
	addi	%r2, %r2, .TOC.-nilMethod@l
.localentry nilMethod, .-nilMethod
#else
.section .opd, "aw", @progbits
nilMethod:
	.p2align 3
	.quad .Lbegin_nilMethod
	.quad .TOC.@tocbase
	.quad 0
.section .text
#endif
.Lbegin_nilMethod:
	li	%r3, 0
	blr
.type nilMethod, @function
.size nilMethod, .-.Lbegin_nilMethod

#ifdef OF_LINUX
.section .note.GNU-stack, "", @progbits
#endif







|
|



|
|
|
|


|









|
|

|


130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163

GENERATE_LOOKUP objc_msg_lookup objc_methodNotFound
GENERATE_LOOKUP objc_msg_lookup_stret objc_methodNotFound_stret
GENERATE_LOOKUP_SUPER objc_msg_lookup_super objc_msg_lookup
GENERATE_LOOKUP_SUPER objc_msg_lookup_super_stret objc_msg_lookup_stret

.LreturnNilMethod:
	addis	%r3, %r2, .LnilMethod@toc@ha
	addi	%r3, %r3, .LnilMethod@toc@l
	blr

#if defined(_CALL_ELF) && _CALL_ELF == 2
.LnilMethod:
	addis	%r2, %r12, .TOC.-.LnilMethod@ha
	addi	%r2, %r2, .TOC.-.LnilMethod@l
.localentry .LnilMethod, .-.LnilMethod
#else
.section .opd, "aw", @progbits
.LnilMethod:
	.p2align 3
	.quad .Lbegin_nilMethod
	.quad .TOC.@tocbase
	.quad 0
.section .text
#endif
.Lbegin_nilMethod:
	li	%r3, 0
	blr
.type .LnilMethod, @function
.size .LnilMethod, .-.Lbegin_nilMethod

#if defined(OF_LINUX) || defined(OF_HAIKU) || defined(OF_HURD)
.section .note.GNU-stack, "", @progbits
#endif

Modified src/runtime/lookup-asm/lookup-asm-sparc-elf.S from [52b9093b5b] to [9287a66648].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
.globl objc_msg_lookup_super
.globl objc_msg_lookup_super_stret

.section .text
.macro GENERATE_LOOKUP name notFound
\name:
	tst	%o0
	bz	returnNilMethod
	 btst	1, %o0
	bnz	.LtaggedPointer_\name	
	 nop

	ld	[%o0], %o2
	ld	[%o2 + 32], %o2








|







22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
.globl objc_msg_lookup_super
.globl objc_msg_lookup_super_stret

.section .text
.macro GENERATE_LOOKUP name notFound
\name:
	tst	%o0
	bz	.LreturnNilMethod
	 btst	1, %o0
	bnz	.LtaggedPointer_\name	
	 nop

	ld	[%o0], %o2
	ld	[%o2 + 32], %o2

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
.endm

.macro GENERATE_LOOKUP_SUPER name lookup
\name:
	mov	%o0, %o2
	ld	[%o0], %o0
	cmp	%o0, 0
	be	returnNilMethod
	 nop

	ld	[%o2 + 4], %o2
	ba	.Lmain_\lookup
	 ld	[%o2 + 32], %o2
.type \name, %function
.size \name, .-\name
.endm

GENERATE_LOOKUP objc_msg_lookup objc_methodNotFound
GENERATE_LOOKUP objc_msg_lookup_stret objc_methodNotFound_stret
GENERATE_LOOKUP_SUPER objc_msg_lookup_super objc_msg_lookup
GENERATE_LOOKUP_SUPER objc_msg_lookup_super_stret objc_msg_lookup_stret

returnNilMethod:
#ifdef OF_PIC
	mov	%o7, %g1

	sethi	%hi(_GLOBAL_OFFSET_TABLE_ - 4), %o1
	call	0f
	 add	%o1, %lo(_GLOBAL_OFFSET_TABLE_ + 4), %o1
0:
	add	%o7, %o1, %o1

	sethi	%hi(nilMethod), %o0
	or	%o0, %lo(nilMethod), %o0

	jmpl	%g1 + 8, %g0
	 ld	[%o1 + %o0], %o0
#else
	sethi	%hi(nilMethod), %o0
	retl
	 or	%o0, %lo(nilMethod), %o0
#endif

nilMethod:
	retl
	 clr	%o0

#ifdef OF_LINUX
.section .note.GNU-stack, "", %progbits
#endif







|














|









|
|




|

|


|



|


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
.endm

.macro GENERATE_LOOKUP_SUPER name lookup
\name:
	mov	%o0, %o2
	ld	[%o0], %o0
	cmp	%o0, 0
	be	.LreturnNilMethod
	 nop

	ld	[%o2 + 4], %o2
	ba	.Lmain_\lookup
	 ld	[%o2 + 32], %o2
.type \name, %function
.size \name, .-\name
.endm

GENERATE_LOOKUP objc_msg_lookup objc_methodNotFound
GENERATE_LOOKUP objc_msg_lookup_stret objc_methodNotFound_stret
GENERATE_LOOKUP_SUPER objc_msg_lookup_super objc_msg_lookup
GENERATE_LOOKUP_SUPER objc_msg_lookup_super_stret objc_msg_lookup_stret

.LreturnNilMethod:
#ifdef OF_PIC
	mov	%o7, %g1

	sethi	%hi(_GLOBAL_OFFSET_TABLE_ - 4), %o1
	call	0f
	 add	%o1, %lo(_GLOBAL_OFFSET_TABLE_ + 4), %o1
0:
	add	%o7, %o1, %o1

	sethi	%hi(.LnilMethod), %o0
	or	%o0, %lo(.LnilMethod), %o0

	jmpl	%g1 + 8, %g0
	 ld	[%o1 + %o0], %o0
#else
	sethi	%hi(.LnilMethod), %o0
	retl
	 or	%o0, %lo(.LnilMethod), %o0
#endif

.LnilMethod:
	retl
	 clr	%o0

#if defined(OF_LINUX) || defined(OF_HAIKU) || defined(OF_HURD)
.section .note.GNU-stack, "", %progbits
#endif

Modified src/runtime/lookup-asm/lookup-asm-sparc64-elf.S from [1e61b50ef6] to [bd4ad17dba].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
.globl objc_msg_lookup_stret
.globl objc_msg_lookup_super
.globl objc_msg_lookup_super_stret

.section .text
.macro GENERATE_LOOKUP name notFound
\name:
	brz,pn	%o0, returnNilMethod
	 and	%o0, 1, %o2
	brnz,pn	%o2, .LtaggedPointer_\name
	 nop

	ldx	[%o0], %o2
	ldx	[%o2 + 64], %o2








|







21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
.globl objc_msg_lookup_stret
.globl objc_msg_lookup_super
.globl objc_msg_lookup_super_stret

.section .text
.macro GENERATE_LOOKUP name notFound
\name:
	brz,pn	%o0, .LreturnNilMethod
	 and	%o0, 1, %o2
	brnz,pn	%o2, .LtaggedPointer_\name
	 nop

	ldx	[%o0], %o2
	ldx	[%o2 + 64], %o2

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
.size \name, .-\name
.endm

.macro GENERATE_LOOKUP_SUPER name lookup
\name:
	mov	%o0, %o2
	ldx	[%o0], %o0
	brz,pn	%o0, returnNilMethod
	 nop

	ldx	[%o2 + 8], %o2
	ba	.Lmain_\lookup
	 ldx	[%o2 + 64], %o2
.type \name, %function
.size \name, .-\name
.endm

GENERATE_LOOKUP objc_msg_lookup objc_methodNotFound
GENERATE_LOOKUP objc_msg_lookup_stret objc_methodNotFound_stret
GENERATE_LOOKUP_SUPER objc_msg_lookup_super objc_msg_lookup
GENERATE_LOOKUP_SUPER objc_msg_lookup_super_stret objc_msg_lookup_stret

returnNilMethod:
#ifdef OF_PIC
	mov	%o7, %g1

	sethi	%hi(_GLOBAL_OFFSET_TABLE_ - 4), %o1
	call	0f
	 or	%o1, %lo(_GLOBAL_OFFSET_TABLE_ + 4), %o1
0:
	add	%o7, %o1, %o1

	sethi	%hi(nilMethod), %o0
	or	%o0, %lo(nilMethod), %o0

	jmpl	%g1 + 8, %g0
	 ldx	[%o1 + %o0], %o0
#else
	sethi	%hi(nilMethod), %o0
	retl
	 or	%o0, %lo(nilMethod), %o0
#endif

nilMethod:
	retl
	 clr	%o0

#ifdef OF_LINUX
.section .note.GNU-stack, "", %progbits
#endif







|














|









|
|




|

|


|



|


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
.size \name, .-\name
.endm

.macro GENERATE_LOOKUP_SUPER name lookup
\name:
	mov	%o0, %o2
	ldx	[%o0], %o0
	brz,pn	%o0, .LreturnNilMethod
	 nop

	ldx	[%o2 + 8], %o2
	ba	.Lmain_\lookup
	 ldx	[%o2 + 64], %o2
.type \name, %function
.size \name, .-\name
.endm

GENERATE_LOOKUP objc_msg_lookup objc_methodNotFound
GENERATE_LOOKUP objc_msg_lookup_stret objc_methodNotFound_stret
GENERATE_LOOKUP_SUPER objc_msg_lookup_super objc_msg_lookup
GENERATE_LOOKUP_SUPER objc_msg_lookup_super_stret objc_msg_lookup_stret

.LreturnNilMethod:
#ifdef OF_PIC
	mov	%o7, %g1

	sethi	%hi(_GLOBAL_OFFSET_TABLE_ - 4), %o1
	call	0f
	 or	%o1, %lo(_GLOBAL_OFFSET_TABLE_ + 4), %o1
0:
	add	%o7, %o1, %o1

	sethi	%hi(.LnilMethod), %o0
	or	%o0, %lo(.LnilMethod), %o0

	jmpl	%g1 + 8, %g0
	 ldx	[%o1 + %o0], %o0
#else
	sethi	%hi(.LnilMethod), %o0
	retl
	 or	%o0, %lo(.LnilMethod), %o0
#endif

.LnilMethod:
	retl
	 clr	%o0

#if defined(OF_LINUX) || defined(OF_HAIKU) || defined(OF_HURD)
.section .note.GNU-stack, "", %progbits
#endif

Modified src/runtime/lookup-asm/lookup-asm-x86-elf.S from [fe04c47c7f] to [875e7a8b79].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
.globl objc_msg_lookup_super_stret

.section .text
.macro GENERATE_LOOKUP name notFound
\name:
	movl	4(%esp), %edx
	testl	%edx, %edx
	jz	returnNilMethod

	testb	$1, %dl
	jnz	.LtaggedPointer_\name

	movl	(%edx), %edx
	movl	32(%edx), %edx








|







23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
.globl objc_msg_lookup_super_stret

.section .text
.macro GENERATE_LOOKUP name notFound
\name:
	movl	4(%esp), %edx
	testl	%edx, %edx
	jz	.LreturnNilMethod

	testb	$1, %dl
	jnz	.LtaggedPointer_\name

	movl	(%edx), %edx
	movl	32(%edx), %edx

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

	testl	%eax, %eax
	jz	0f

	ret

0:
	call	getEIP
	addl	$_GLOBAL_OFFSET_TABLE_, %eax
	lea	\notFound@GOTOFF(%eax), %eax
	jmp	*%eax

.LtaggedPointer_\name:
	call	getEIP
	addl	$_GLOBAL_OFFSET_TABLE_, %eax

	leal	objc_taggedPointerSecret@GOTOFF(%eax), %ecx
	xorl	(%ecx), %edx
	andb	$0xE, %dl
	movzbl	%dl, %edx

	leal	objc_taggedPointerClasses@GOTOFF(%eax), %eax
	movl	(%eax,%edx,2), %edx
	movl	32(%edx), %edx

	jmp	.Lmain_\name
.type \name, %function
.size \name, .-\name
.endm

.macro GENERATE_LOOKUP_SUPER name lookup
\name:
	movl	4(%esp), %edx
	movl	(%edx), %eax
	testl	%eax, %eax
	jz	returnNilMethod

	movl	%eax, 4(%esp)
	mov	4(%edx), %edx
	mov	32(%edx), %edx
	jmp	.Lmain_\lookup
.type \name, %function
.size \name, .-\name
.endm

GENERATE_LOOKUP objc_msg_lookup objc_methodNotFound
GENERATE_LOOKUP objc_msg_lookup_stret objc_methodNotFound_stret
GENERATE_LOOKUP_SUPER objc_msg_lookup_super objc_msg_lookup
GENERATE_LOOKUP_SUPER objc_msg_lookup_super_stret objc_msg_lookup_stret

returnNilMethod:
	call	getEIP
	addl	$_GLOBAL_OFFSET_TABLE_, %eax
	leal	nilMethod@GOTOFF(%eax), %eax
	ret

nilMethod:
	xorl	%eax, %eax
	ret

getEIP:
	movl	(%esp), %eax
	ret

#ifdef OF_LINUX
.section .note.GNU-stack, "", %progbits
#endif







|

|



|


|




|













|














|
|

|


|



|



|


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

	testl	%eax, %eax
	jz	0f

	ret

0:
	call	.LgetEIP
	addl	$_GLOBAL_OFFSET_TABLE_, %eax
	movl	\notFound@GOT(%eax), %eax
	jmp	*%eax

.LtaggedPointer_\name:
	call	.LgetEIP
	addl	$_GLOBAL_OFFSET_TABLE_, %eax

	movl	objc_taggedPointerSecret@GOT(%eax), %ecx
	xorl	(%ecx), %edx
	andb	$0xE, %dl
	movzbl	%dl, %edx

	movl	objc_taggedPointerClasses@GOT(%eax), %eax
	movl	(%eax,%edx,2), %edx
	movl	32(%edx), %edx

	jmp	.Lmain_\name
.type \name, %function
.size \name, .-\name
.endm

.macro GENERATE_LOOKUP_SUPER name lookup
\name:
	movl	4(%esp), %edx
	movl	(%edx), %eax
	testl	%eax, %eax
	jz	.LreturnNilMethod

	movl	%eax, 4(%esp)
	mov	4(%edx), %edx
	mov	32(%edx), %edx
	jmp	.Lmain_\lookup
.type \name, %function
.size \name, .-\name
.endm

GENERATE_LOOKUP objc_msg_lookup objc_methodNotFound
GENERATE_LOOKUP objc_msg_lookup_stret objc_methodNotFound_stret
GENERATE_LOOKUP_SUPER objc_msg_lookup_super objc_msg_lookup
GENERATE_LOOKUP_SUPER objc_msg_lookup_super_stret objc_msg_lookup_stret

.LreturnNilMethod:
	call	.LgetEIP
	addl	$_GLOBAL_OFFSET_TABLE_, %eax
	leal	.LnilMethod@GOTOFF(%eax), %eax
	ret

.LnilMethod:
	xorl	%eax, %eax
	ret

.LgetEIP:
	movl	(%esp), %eax
	ret

#if defined(OF_LINUX) || defined(OF_HAIKU) || defined(OF_HURD)
.section .note.GNU-stack, "", %progbits
#endif

Modified src/runtime/lookup-asm/lookup-asm-x86-win32.S from [0d663a9140] to [f5268f2582].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
.globl _objc_msg_lookup_super_stret

.section .text
.macro GENERATE_LOOKUP name notFound
\name:
	movl	4(%esp), %edx
	testl	%edx, %edx
	jz	returnNilMethod

	testb	$1, %dl
	jnz	.LtaggedPointer_\name

	movl	(%edx), %edx
	movl	32(%edx), %edx








|







21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
.globl _objc_msg_lookup_super_stret

.section .text
.macro GENERATE_LOOKUP name notFound
\name:
	movl	4(%esp), %edx
	testl	%edx, %edx
	jz	.LreturnNilMethod

	testb	$1, %dl
	jnz	.LtaggedPointer_\name

	movl	(%edx), %edx
	movl	32(%edx), %edx

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
.endm

.macro GENERATE_LOOKUP_SUPER name lookup
\name:
	movl	4(%esp), %edx
	movl	(%edx), %eax
	test	%eax, %eax
	jz	returnNilMethod

	movl	%eax, 4(%esp)
	movl	4(%edx), %edx
	movl	32(%edx), %edx
	jmp	.Lmain_\lookup
.def \name
.scl 2
.type 32
.endef
.endm

GENERATE_LOOKUP _objc_msg_lookup _objc_methodNotFound
GENERATE_LOOKUP _objc_msg_lookup_stret _objc_methodNotFound_stret
GENERATE_LOOKUP_SUPER _objc_msg_lookup_super _objc_msg_lookup
GENERATE_LOOKUP_SUPER _objc_msg_lookup_super_stret _objc_msg_lookup_stret

returnNilMethod:
	movl	$nilMethod, %eax
	ret

nilMethod:
	xorl	%eax, %eax
	ret







|
















|
|


|


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
.endm

.macro GENERATE_LOOKUP_SUPER name lookup
\name:
	movl	4(%esp), %edx
	movl	(%edx), %eax
	test	%eax, %eax
	jz	.LreturnNilMethod

	movl	%eax, 4(%esp)
	movl	4(%edx), %edx
	movl	32(%edx), %edx
	jmp	.Lmain_\lookup
.def \name
.scl 2
.type 32
.endef
.endm

GENERATE_LOOKUP _objc_msg_lookup _objc_methodNotFound
GENERATE_LOOKUP _objc_msg_lookup_stret _objc_methodNotFound_stret
GENERATE_LOOKUP_SUPER _objc_msg_lookup_super _objc_msg_lookup
GENERATE_LOOKUP_SUPER _objc_msg_lookup_super_stret _objc_msg_lookup_stret

.LreturnNilMethod:
	movl	$.LnilMethod, %eax
	ret

.LnilMethod:
	xorl	%eax, %eax
	ret

Modified src/runtime/lookup-asm/lookup-asm.S from [31f647ad96] to [b5312a96ee].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#include "platform.h"

#if defined(OF_ELF)
# if defined(OF_X86_64)
#  include "lookup-asm-x86_64-elf.S"
# elif defined(OF_X86)
#  include "lookup-asm-x86-elf.S"
# elif defined(OF_ARM64)
#  include "lookup-asm-arm64-elf.S"
# elif defined(OF_ARM)
#  include "lookup-asm-arm-elf.S"
# elif defined(OF_POWERPC64)
#  include "lookup-asm-powerpc64-elf.S"
# elif defined(OF_POWERPC)
#  include "lookup-asm-powerpc-elf.S"
# elif defined(OF_MIPS64_N64)
#  include "lookup-asm-mips64-n64-elf.S"
# elif defined(OF_MIPS)
#  include "lookup-asm-mips-elf.S"
# elif defined(OF_SPARC64)
#  include "lookup-asm-sparc64-elf.S"
# elif defined(OF_SPARC)
#  include "lookup-asm-sparc-elf.S"
# endif
#elif defined(OF_MACH_O)
# if defined(OF_X86_64)
#  include "lookup-asm-x86_64-macho.S"
# endif
#elif defined(OF_WINDOWS)
# if defined(OF_X86_64)
#  include "lookup-asm-x86_64-win64.S"
# elif defined(OF_X86)
#  include "lookup-asm-x86-win32.S"
# endif
#endif

|


















|
|




















|
|


|
|




1
2
3
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"

#include "platform.h"

#if defined(OF_ELF)
# if defined(OF_AMD64)
#  include "lookup-asm-amd64-elf.S"
# elif defined(OF_X86)
#  include "lookup-asm-x86-elf.S"
# elif defined(OF_ARM64)
#  include "lookup-asm-arm64-elf.S"
# elif defined(OF_ARM)
#  include "lookup-asm-arm-elf.S"
# elif defined(OF_POWERPC64)
#  include "lookup-asm-powerpc64-elf.S"
# elif defined(OF_POWERPC)
#  include "lookup-asm-powerpc-elf.S"
# elif defined(OF_MIPS64_N64)
#  include "lookup-asm-mips64-n64-elf.S"
# elif defined(OF_MIPS)
#  include "lookup-asm-mips-elf.S"
# elif defined(OF_SPARC64)
#  include "lookup-asm-sparc64-elf.S"
# elif defined(OF_SPARC)
#  include "lookup-asm-sparc-elf.S"
# endif
#elif defined(OF_MACH_O)
# if defined(OF_AMD64)
#  include "lookup-asm-amd64-macho.S"
# endif
#elif defined(OF_WINDOWS)
# if defined(OF_AMD64)
#  include "lookup-asm-amd64-win64.S"
# elif defined(OF_X86)
#  include "lookup-asm-x86-win32.S"
# endif
#endif

Modified src/runtime/lookup.m from [620b9cc132] to [46930723ef].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/runtime/method.m from [82646e77ef] to [d2dde64b35].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/runtime/misc.m from [6b0956b061] to [33aa585c19].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
23
24
25
26
27
28
29

30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include "private.h"

#ifdef OF_WINDOWS
# include <windows.h>
#endif

#ifdef OF_AMIGAOS

# define USE_INLINE_STDARG
# include <proto/exec.h>
# include <clib/debug_protos.h>
# define __NOLIBBASE__
# define Class IntuitionClass
# include <proto/intuition.h>
# undef Class
# undef __NOLIBBASE__
#endif

static objc_enumeration_mutation_handler enumerationMutationHandler = NULL;

void
objc_enumerationMutation(id object)
{







>




<

|
|







23
24
25
26
27
28
29
30
31
32
33
34

35
36
37
38
39
40
41
42
43
44
#include "private.h"

#ifdef OF_WINDOWS
# include <windows.h>
#endif

#ifdef OF_AMIGAOS
# define Class IntuitionClass
# define USE_INLINE_STDARG
# include <proto/exec.h>
# include <clib/debug_protos.h>
# define __NOLIBBASE__

# include <proto/intuition.h>
# undef __NOLIBBASE__
# undef Class
#endif

static objc_enumeration_mutation_handler enumerationMutationHandler = NULL;

void
objc_enumerationMutation(id object)
{

Modified src/runtime/private.h from [aebd8619bf] to [e0e05e3c60].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
	Class _Nullable superclass;
	const char *_Nonnull name;
	unsigned long version;
	unsigned long info;
	long instanceSize;
	struct objc_ivar_list *_Nullable ivars;
	struct objc_method_list *_Nullable methodList;
	struct objc_dtable *_Nonnull dTable;
	Class _Nullable *_Nullable subclassList;
	void *_Nullable siblingClass;
	struct objc_protocol_list *_Nullable protocols;
	void *_Nullable GCObjectType;
	unsigned long ABIVersion;
	int32_t *_Nonnull *_Nullable ivarOffsets;
	struct objc_property_list *_Nullable propertyList;







|







35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
	Class _Nullable superclass;
	const char *_Nonnull name;
	unsigned long version;
	unsigned long info;
	long instanceSize;
	struct objc_ivar_list *_Nullable ivars;
	struct objc_method_list *_Nullable methodList;
	struct objc_dtable *_Nullable dTable;
	Class _Nullable *_Nullable subclassList;
	void *_Nullable siblingClass;
	struct objc_protocol_list *_Nullable protocols;
	void *_Nullable GCObjectType;
	unsigned long ABIVersion;
	int32_t *_Nonnull *_Nullable ivarOffsets;
	struct objc_property_list *_Nullable propertyList;
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
		} *_Nonnull buckets[256];
#else
		IMP _Nullable buckets[256];
#endif
	} *_Nonnull buckets[256];
};

#if defined(OBJC_COMPILING_AMIGA_LIBRARY) || \
    defined(OBJC_COMPILING_AMIGA_LINKLIB)
struct objc_libc {
	void *_Nullable (*_Nonnull malloc)(size_t);
	void *_Nullable (*_Nonnull calloc)(size_t, size_t);
	void *_Nullable (*_Nonnull realloc)(void *_Nullable, size_t);
	void (*_Nonnull free)(void *_Nullable);
# ifdef HAVE_SJLJ_EXCEPTIONS
	int (*_Nonnull _Unwind_SjLj_RaiseException)(void *_Nonnull);
# else
	int (*_Nonnull _Unwind_RaiseException)(void *_Nonnull);
# endif
	void (*_Nonnull _Unwind_DeleteException)(void *_Nonnull);
	void *_Nullable (*_Nonnull _Unwind_GetLanguageSpecificData)(
	    void *_Nonnull);
	uintptr_t (*_Nonnull _Unwind_GetRegionStart)(void *_Nonnull);
	uintptr_t (*_Nonnull _Unwind_GetDataRelBase)(void *_Nonnull);
	uintptr_t (*_Nonnull _Unwind_GetTextRelBase)(void *_Nonnull);
	uintptr_t (*_Nonnull _Unwind_GetIP)(void *_Nonnull);
	uintptr_t (*_Nonnull _Unwind_GetGR)(void *_Nonnull, int);
	void (*_Nonnull _Unwind_SetIP)(void *_Nonnull, uintptr_t);
	void (*_Nonnull _Unwind_SetGR)(void *_Nonnull, int, uintptr_t);
# ifdef HAVE_SJLJ_EXCEPTIONS
	void (*_Nonnull _Unwind_SjLj_Resume)(void *_Nonnull);
# else
	void (*_Nonnull _Unwind_Resume)(void *_Nonnull);
# endif
# ifdef OF_AMIGAOS_M68K
	void (*_Nonnull __register_frame_info)(const void *_Nonnull,
	    void *_Nonnull);
	void *(*_Nonnull __deregister_frame_info)(const void *_Nonnull);
# endif
# ifdef OF_MORPHOS
	void (*_Nonnull __register_frame)(void *_Nonnull);
	void (*_Nonnull __deregister_frame)(void *_Nonnull);
# endif
# ifdef OF_AMIGAOS_M68K
	int (*_Nonnull vsnprintf)(char *restrict _Nonnull str, size_t size,
	    const char *_Nonnull restrict fmt, va_list args);
# endif
	int (*_Nonnull atexit)(void (*_Nonnull)(void));
	void (*_Nonnull exit)(int);
};
#endif

#ifdef OBJC_COMPILING_AMIGA_LIBRARY
# if defined(__MORPHOS__)
#  include <ppcinline/macros.h>
#  define OBJC_M68K_ARG(type, name, reg) type name = (type)REG_##reg;
# else
#  define OBJC_M68K_ARG(type, name, reg)	\
	register type reg_##name __asm__(#reg);	\
	type name = reg_##name;
# endif

extern bool objc_init(unsigned int, struct objc_libc *);
# ifdef HAVE_SJLJ_EXCEPTIONS
#  define __gnu_objc_personality(version, actions, exClass, ex, ctx)	\
	__gnu_objc_personality_sj0(version, actions, *exClass, ex, ctx)
# else
#  define __gnu_objc_personality(version, actions, exClass, ex, ctx)	\
	__gnu_objc_personality_v0(version, actions, *exClass, ex, ctx)
# endif
#endif

extern void objc_registerAllCategories(struct objc_symtab *_Nonnull);
extern struct objc_category *_Nullable *_Nullable
    objc_categoriesForClass(Class _Nonnull);
extern void objc_unregisterAllCategories(void);
extern void objc_initializeClass(Class _Nonnull);
extern void objc_updateDTable(Class _Nonnull);
extern void objc_registerAllClasses(struct objc_symtab *_Nonnull);







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







211
212
213
214
215
216
217

































































218
219
220
221
222
223
224
		} *_Nonnull buckets[256];
#else
		IMP _Nullable buckets[256];
#endif
	} *_Nonnull buckets[256];
};


































































extern void objc_registerAllCategories(struct objc_symtab *_Nonnull);
extern struct objc_category *_Nullable *_Nullable
    objc_categoriesForClass(Class _Nonnull);
extern void objc_unregisterAllCategories(void);
extern void objc_initializeClass(Class _Nonnull);
extern void objc_updateDTable(Class _Nonnull);
extern void objc_registerAllClasses(struct objc_symtab *_Nonnull);
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
extern void OF_NO_RETURN_FUNC objc_error(const char *_Nonnull title,
    const char *_Nonnull format, ...);
#define OBJC_ERROR(...)							\
	objc_error("ObjFWRT @ " __FILE__ ":" OF_STRINGIFY(__LINE__),	\
	    __VA_ARGS__)

#if defined(OF_ELF)
# if defined(OF_X86_64) || defined(OF_X86) || \
    defined(OF_POWERPC64) || defined(OF_POWERPC) || \
    defined(OF_ARM64) || defined(OF_ARM) || \
    defined(OF_MIPS64_N64) || defined(OF_MIPS) || \
    defined(OF_SPARC64) || defined(OF_SPARC)
#  define OF_ASM_LOOKUP
# endif
#elif defined(OF_MACH_O)
# if defined(OF_X86_64)
#  define OF_ASM_LOOKUP
# endif
#elif defined(OF_WINDOWS)
# if defined(OF_X86_64) || defined(OF_X86)
#  define OF_ASM_LOOKUP
# endif
#endif

@interface DummyObject
{
	Class _Nonnull isa;







|







|



|







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
extern void OF_NO_RETURN_FUNC objc_error(const char *_Nonnull title,
    const char *_Nonnull format, ...);
#define OBJC_ERROR(...)							\
	objc_error("ObjFWRT @ " __FILE__ ":" OF_STRINGIFY(__LINE__),	\
	    __VA_ARGS__)

#if defined(OF_ELF)
# if defined(OF_AMD64) || defined(OF_X86) || \
    defined(OF_POWERPC64) || defined(OF_POWERPC) || \
    defined(OF_ARM64) || defined(OF_ARM) || \
    defined(OF_MIPS64_N64) || defined(OF_MIPS) || \
    defined(OF_SPARC64) || defined(OF_SPARC)
#  define OF_ASM_LOOKUP
# endif
#elif defined(OF_MACH_O)
# if defined(OF_AMD64)
#  define OF_ASM_LOOKUP
# endif
#elif defined(OF_WINDOWS)
# if defined(OF_AMD64) || defined(OF_X86)
#  define OF_ASM_LOOKUP
# endif
#endif

@interface DummyObject
{
	Class _Nonnull isa;

Modified src/runtime/property.m from [822a1641e1] to [eac1d5ea2f].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/runtime/protocol.m from [30a1ffceef] to [ec36b73c60].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/runtime/selector.m from [9a44ebdc88] to [ad46e99f3d].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/runtime/sparsearray.m from [5acb08c6c8] to [44ad4592e2].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/runtime/static-instances.m from [7d72566e27] to [785f22c36a].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/runtime/synchronized.m from [2eb69df2c4] to [7848379ca1].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/runtime/tagged-pointer.m from [747427397b] to [b300ffd521].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/runtime/threading.m from [f4000ae0f7] to [0aef164090].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/runtime/versioninfo.rc from [6986fc8cab] to [6ae207e79a].

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
	BLOCK "StringFileInfo" {
		BLOCK "040904E4" {
			VALUE "ProductName", "ObjFW Runtime"
			VALUE "ProductVersion", PACKAGE_VERSION
			VALUE "FileVersion", OBJFWRT_LIB_VERSION
			VALUE "FileDescription", "Objective-C runtime"
			VALUE "LegalCopyright",
			    "(c) 2008-2022 Jonathan Schleifer"
			VALUE "InternalName", "ObjFWRT"
			VALUE "OriginalFilename", OBJFWRT_SHARED_LIB
		}

	}

	BLOCK "VarFileInfo" {
		VALUE "Translation", 0x409, 1252
	}
}







|










10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
	BLOCK "StringFileInfo" {
		BLOCK "040904E4" {
			VALUE "ProductName", "ObjFW Runtime"
			VALUE "ProductVersion", PACKAGE_VERSION
			VALUE "FileVersion", OBJFWRT_LIB_VERSION
			VALUE "FileDescription", "Objective-C runtime"
			VALUE "LegalCopyright",
			    "(c) 2008-2024 Jonathan Schleifer"
			VALUE "InternalName", "ObjFWRT"
			VALUE "OriginalFilename", OBJFWRT_SHARED_LIB
		}

	}

	BLOCK "VarFileInfo" {
		VALUE "Translation", 0x409, 1252
	}
}

Modified src/tls/Makefile from [a6c2c67827] to [9769a7e248].

1
2
3
4
5
6
7
8
9

10
11
12

13
14
15
16
17
18
19
20
21
22
23
include ../../extra.mk

DISTCLEAN = Info.plist

SHARED_LIB = ${OBJFWTLS_SHARED_LIB}
STATIC_LIB = ${OBJFWTLS_STATIC_LIB}
FRAMEWORK = ${OBJFWTLS_FRAMEWORK}
LIB_MAJOR = ${OBJFW_LIB_MAJOR}
LIB_MINOR = ${OBJFW_LIB_MINOR}


INCLUDES := ObjFWTLS.h
SRCS = ${OF_GNUTLS_TLS_STREAM_M}		\

       ${OF_OPENSSL_TLS_STREAM_M}		\
       ${OF_SECURE_TRANSPORT_TLS_STREAM_M}

includesubdir = ObjFWTLS

include ../../buildsys.mk

CPPFLAGS += -I. -I.. -I../.. -I../exceptions -I../runtime ${TLS_CPPFLAGS}
LD = ${OBJC}
FRAMEWORK_LIBS := ${TLS_LIBS} -F.. -framework ObjFW ${LIBS}
LIBS := ${TLS_LIBS} -L.. -lobjfw -L../runtime ${RUNTIME_LIBS} ${LIBS}







|
|
>



>











1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
include ../../extra.mk

DISTCLEAN = Info.plist

SHARED_LIB = ${OBJFWTLS_SHARED_LIB}
STATIC_LIB = ${OBJFWTLS_STATIC_LIB}
FRAMEWORK = ${OBJFWTLS_FRAMEWORK}
LIB_MAJOR = ${OBJFWTLS_LIB_MAJOR}
LIB_MINOR = ${OBJFWTLS_LIB_MINOR}
LIB_PATCH = ${OBJFWTLS_LIB_PATCH}

INCLUDES := ObjFWTLS.h
SRCS = ${OF_GNUTLS_TLS_STREAM_M}		\
       ${OF_MBEDTLS_TLS_STREAM_M}		\
       ${OF_OPENSSL_TLS_STREAM_M}		\
       ${OF_SECURE_TRANSPORT_TLS_STREAM_M}

includesubdir = ObjFWTLS

include ../../buildsys.mk

CPPFLAGS += -I. -I.. -I../.. -I../exceptions -I../runtime ${TLS_CPPFLAGS}
LD = ${OBJC}
FRAMEWORK_LIBS := ${TLS_LIBS} -F.. -framework ObjFW ${LIBS}
LIBS := ${TLS_LIBS} -L.. -lobjfw -L../runtime ${RUNTIME_LIBS} ${LIBS}

Modified src/tls/OFGnuTLSTLSStream.h from [d33b11b9cb] to [a770d3d852].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/tls/OFGnuTLSTLSStream.m from [fad8797bf6] to [570186048d].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#include <errno.h>

#import "OFGnuTLSTLSStream.h"
#import "OFData.h"

#import "OFAlreadyConnectedException.h"
#import "OFInitializationFailedException.h"
#import "OFNotOpenException.h"
#import "OFReadFailedException.h"
#import "OFTLSHandshakeFailedException.h"
#import "OFWriteFailedException.h"

int _ObjFWTLS_reference;

|




















|







1
2
3
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"

#include <errno.h>

#import "OFGnuTLSTLSStream.h"
#import "OFData.h"

#import "OFAlreadyOpenException.h"
#import "OFInitializationFailedException.h"
#import "OFNotOpenException.h"
#import "OFReadFailedException.h"
#import "OFTLSHandshakeFailedException.h"
#import "OFWriteFailedException.h"

int _ObjFWTLS_reference;
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
	if (!_initialized)
		@throw [OFNotOpenException exceptionWithObject: self];

	if (_handshakeDone)
		gnutls_bye(_session, GNUTLS_SHUT_WR);

	gnutls_deinit(_session);
	_initialized = false;

	[_host release];
	_host = nil;

	[super close];
}








|







123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
	if (!_initialized)
		@throw [OFNotOpenException exceptionWithObject: self];

	if (_handshakeDone)
		gnutls_bye(_session, GNUTLS_SHUT_WR);

	gnutls_deinit(_session);
	_initialized = _handshakeDone = false;

	[_host release];
	_host = nil;

	[super close];
}

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
						      bytesWritten: ret
							     errNo: 0];
	}

	return ret;
}

- (bool)hasDataInReadBuffer
{

	if (gnutls_record_check_pending(_session) > 0)
		return true;

	return super.hasDataInReadBuffer;
}

- (void)asyncPerformClientHandshakeWithHost: (OFString *)host
				runLoopMode: (OFRunLoopMode)runLoopMode
{
	static const OFTLSStreamErrorCode initFailedErrorCode =
	    OFTLSStreamErrorCodeInitializationFailed;
	id exception = nil;
	int status;

	if (_initialized)
		@throw [OFAlreadyConnectedException exceptionWithSocket: self];

	if (gnutls_init(&_session, GNUTLS_CLIENT | GNUTLS_NONBLOCK |
	    GNUTLS_SAFE_PADDING_CHECK) != GNUTLS_E_SUCCESS)
		@throw [OFTLSHandshakeFailedException
		    exceptionWithStream: self
				   host: host
			      errorCode: initFailedErrorCode];







|

>
|
<
<
<











|







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
						      bytesWritten: ret
							     errNo: 0];
	}

	return ret;
}

- (bool)lowlevelHasDataInReadBuffer
{
	return (_underlyingStream.hasDataInReadBuffer ||
	    gnutls_record_check_pending(_session) > 0);



}

- (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 |
	    GNUTLS_SAFE_PADDING_CHECK) != GNUTLS_E_SUCCESS)
		@throw [OFTLSHandshakeFailedException
		    exceptionWithStream: self
				   host: host
			      errorCode: initFailedErrorCode];
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
	if (_verifiesCertificates)
		gnutls_session_set_verify_cert(_session, _host.UTF8String, 0);

	status = gnutls_handshake(_session);

	if (status == GNUTLS_E_INTERRUPTED || status == GNUTLS_E_AGAIN) {
		if (gnutls_record_get_direction(_session) == 1)
			[_underlyingStream
			    asyncWriteData: [OFData dataWithItems: "" count: 0]
			       runLoopMode: runLoopMode];
		else
			[_underlyingStream asyncReadIntoBuffer: (void *)""
							length: 0
						   runLoopMode: runLoopMode];

		[_delegate retain];
		return;







|
<
|







235
236
237
238
239
240
241
242

243
244
245
246
247
248
249
250
	if (_verifiesCertificates)
		gnutls_session_set_verify_cert(_session, _host.UTF8String, 0);

	status = gnutls_handshake(_session);

	if (status == GNUTLS_E_INTERRUPTED || status == GNUTLS_E_AGAIN) {
		if (gnutls_record_get_direction(_session) == 1)
			[_underlyingStream asyncWriteData: [OFData data]

					      runLoopMode: runLoopMode];
		else
			[_underlyingStream asyncReadIntoBuffer: (void *)""
							length: 0
						   runLoopMode: runLoopMode];

		[_delegate retain];
		return;
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
		    didPerformClientHandshakeWithHost: host
					    exception: exception];
}

-      (bool)stream: (OFStream *)stream
  didReadIntoBuffer: (void *)buffer
	     length: (size_t)length
	  exception: (nullable id)exception
{
	if (exception == nil) {
		int status = gnutls_handshake(_session);

		if (status == GNUTLS_E_INTERRUPTED ||
		    status == GNUTLS_E_AGAIN) {
			if (gnutls_record_get_direction(_session) == 1) {
				OFData *data = [OFData dataWithItems: ""
							       count: 0];
				OFRunLoopMode runLoopMode =
				    [OFRunLoop currentRunLoop].currentMode;
				[_underlyingStream asyncWriteData: data
						      runLoopMode: runLoopMode];
				return false;
			} else
				return true;
		}

		if (status == GNUTLS_E_SUCCESS)







|







<
<


|







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
		    didPerformClientHandshakeWithHost: host
					    exception: exception];
}

-      (bool)stream: (OFStream *)stream
  didReadIntoBuffer: (void *)buffer
	     length: (size_t)length
	  exception: (id)exception
{
	if (exception == nil) {
		int status = gnutls_handshake(_session);

		if (status == GNUTLS_E_INTERRUPTED ||
		    status == GNUTLS_E_AGAIN) {
			if (gnutls_record_get_direction(_session) == 1) {


				OFRunLoopMode runLoopMode =
				    [OFRunLoop currentRunLoop].currentMode;
				[_underlyingStream asyncWriteData: [OFData data]
						      runLoopMode: runLoopMode];
				return false;
			} else
				return true;
		}

		if (status == GNUTLS_E_SUCCESS)

Added src/tls/OFMbedTLSTLSStream.h version [b21f7f1267].































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/*
 * Copyright (c) 2008-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 "OFTLSStream.h"

#include <mbedtls/ssl.h>

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

Added src/tls/OFMbedTLSTLSStream.m version [14845fbfc0].















































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
/*
 * 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 <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;

	@try {
		length = [stream.underlyingStream readIntoBuffer: buffer
							  length: length];
	} @catch (OFReadFailedException *e) {
		return -1;
	}

	if (length == 0 && !stream.underlyingStream.atEndOfStream)
		return MBEDTLS_ERR_SSL_WANT_READ;

	if (length > INT_MAX)
		@throw [OFOutOfRangeException exception];

	return (int)length;
}

static int
writeFunc(void *ctx, const unsigned char *buffer, size_t length)
{
	OFMbedTLSTLSStream *stream = (OFMbedTLSTLSStream *)ctx;

	@try {
		[stream.underlyingStream writeBuffer: buffer length: length];
	} @catch (OFWriteFailedException *e) {
		if (e.errNo == EWOULDBLOCK || e.errNo == EAGAIN) {
			size_t bytesWritten = e.bytesWritten;

			if (bytesWritten > INT_MAX)
				@throw [OFOutOfRangeException exception];

			return (bytesWritten > 0
			    ? (int)bytesWritten : MBEDTLS_ERR_SSL_WANT_WRITE);
		}

		return -1;
	}

	if (length > INT_MAX)
		@throw [OFOutOfRangeException exception];

	return (int)length;
}

+ (void)load
{
	if (OFTLSStreamImplementation == Nil)
		OFTLSStreamImplementation = self;
}

+ (void)initialize
{
	if (self != [OFMbedTLSTLSStream class])
		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)
		@throw [OFNotOpenException exceptionWithObject: self];

	if (_handshakeDone)
		mbedtls_ssl_close_notify(&_SSL);

	mbedtls_ssl_free(&_SSL);
	mbedtls_ssl_config_free(&_config);
	_initialized = _handshakeDone = false;

	[_host release];
	_host = nil;

	[super close];
}

- (size_t)lowlevelReadIntoBuffer: (void *)buffer length: (size_t)length
{
	int ret;

	if (!_handshakeDone)
		@throw [OFNotOpenException exceptionWithObject: self];

	if ((ret = mbedtls_ssl_read(&_SSL, buffer, length)) < 0) {
		/*
		 * The underlying stream might have had data ready, but not
		 * enough for MbedTLS to return decrypted data. This means the
		 * caller might have observed the TLS stream for reading, got a
		 * ready signal and read - and expects the read to succeed, not
		 * to fail with EWOULDBLOCK/EAGAIN, as it was signaled ready.
		 * Therefore, return 0, as we could read 0 decrypted bytes, but
		 * cleared the ready signal of the underlying stream.
		 */
		if (ret == MBEDTLS_ERR_SSL_WANT_READ ||
		    ret == MBEDTLS_ERR_SSL_WANT_WRITE)
			return 0;

		/* FIXME: Translate error to errNo */
		@throw [OFReadFailedException exceptionWithObject: self
						  requestedLength: length
							    errNo: 0];
	}

	return ret;
}

- (size_t)lowlevelWriteBuffer: (const void *)buffer length: (size_t)length
{
	int ret;

	if (!_handshakeDone)
		@throw [OFNotOpenException exceptionWithObject: self];

	if ((ret = mbedtls_ssl_write(&_SSL, buffer, length)) < 0) {
		if (ret == MBEDTLS_ERR_SSL_WANT_READ ||
		    ret == MBEDTLS_ERR_SSL_WANT_WRITE)
			return 0;

		/* FIXME: Translate error to errNo */
		@throw [OFWriteFailedException exceptionWithObject: self
						   requestedLength: length
						      bytesWritten: ret
							     errNo: 0];
	}

	return ret;
}

- (bool)lowlevelHasDataInReadBuffer
{
	return (_underlyingStream.hasDataInReadBuffer ||
	    mbedtls_ssl_get_bytes_avail(&_SSL));
}

- (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];

	mbedtls_ssl_set_bio(&_SSL, self, writeFunc, readFunc, NULL);

	_host = [host copy];

	if (mbedtls_ssl_set_hostname(&_SSL, _host.UTF8String) != 0)
		@throw [OFTLSHandshakeFailedException
		    exceptionWithStream: self
				   host: host
			      errorCode: initFailedErrorCode];

	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
{
	if (exception == nil) {
		int status = mbedtls_ssl_handshake_step(&_SSL);

		if (status == MBEDTLS_ERR_SSL_WANT_READ)
			return true;
		else if (status == MBEDTLS_ERR_SSL_WANT_WRITE) {
			OFRunLoopMode runLoopMode =
			    [OFRunLoop currentRunLoop].currentMode;
			[_underlyingStream asyncWriteData: [OFData data]
					      runLoopMode: runLoopMode];
			return false;
		}

		if (status == 0)
			_handshakeDone = true;
		else
			exception = [OFTLSHandshakeFailedException
			    exceptionWithStream: self
					   host: _host
				      errorCode: OFTLSStreamErrorCodeUnknown];
	}

	if ([_delegate respondsToSelector:
	    @selector(stream:didPerformClientHandshakeWithHost:exception:)])
		[_delegate		       stream: self
		    didPerformClientHandshakeWithHost: _host
					    exception: exception];

	[_delegate release];

	return false;
}

- (OFData *)stream: (OFStream *)stream
      didWriteData: (OFData *)data
      bytesWritten: (size_t)bytesWritten
	 exception: (id)exception
{
	if (exception == nil) {
		int status = mbedtls_ssl_handshake_step(&_SSL);

		if (status == MBEDTLS_ERR_SSL_WANT_WRITE)
			return data;
		else if (status == MBEDTLS_ERR_SSL_WANT_READ) {
			OFRunLoopMode runLoopMode =
			    [OFRunLoop currentRunLoop].currentMode;
			[_underlyingStream asyncReadIntoBuffer: (void *)""
							length: 0
						   runLoopMode: runLoopMode];
			return nil;
		}

		if (status == 0)
			_handshakeDone = true;
		else
			exception = [OFTLSHandshakeFailedException
			    exceptionWithStream: self
					   host: _host
				      errorCode: OFTLSStreamErrorCodeUnknown];
	}

	if ([_delegate respondsToSelector:
	    @selector(stream:didPerformClientHandshakeWithHost:exception:)])
		[_delegate		       stream: self
		    didPerformClientHandshakeWithHost: _host
					    exception: exception];

	[_delegate release];

	return nil;
}
@end

Modified src/tls/OFOpenSSLTLSStream.h from [5bdb0a26b6] to [46e1bb5fe2].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/tls/OFOpenSSLTLSStream.m from [faf6205c5a] to [acd160399f].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#include <errno.h>

#import "OFOpenSSLTLSStream.h"
#import "OFData.h"

#import "OFAlreadyConnectedException.h"
#import "OFInitializationFailedException.h"
#import "OFNotOpenException.h"
#import "OFReadFailedException.h"
#import "OFTLSHandshakeFailedException.h"
#import "OFWriteFailedException.h"

#define bufferSize OFOpenSSLTLSStreamBufferSize

|




















|







1
2
3
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"

#include <errno.h>

#import "OFOpenSSLTLSStream.h"
#import "OFData.h"

#import "OFAlreadyOpenException.h"
#import "OFInitializationFailedException.h"
#import "OFNotOpenException.h"
#import "OFReadFailedException.h"
#import "OFTLSHandshakeFailedException.h"
#import "OFWriteFailedException.h"

#define bufferSize OFOpenSSLTLSStreamBufferSize
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

	if (_handshakeDone)
		SSL_shutdown(_SSL);

	SSL_free(_SSL);
	_SSL = NULL;



	[_host release];
	_host = nil;

	[super close];
}

- (size_t)lowlevelReadIntoBuffer: (void *)buffer length: (size_t)length
{
	int ret;
	size_t bytesRead;

	if (!_handshakeDone)
		@throw [OFNotOpenException exceptionWithObject: self];

	if (BIO_ctrl_pending(_readBIO) < 1) {
		@try {
			size_t tmp = [_underlyingStream
			    readIntoBuffer: _buffer
				    length: bufferSize];

			OFEnsure(tmp <= INT_MAX);
			/* Writing to a memory BIO must never fail. */
			OFEnsure(BIO_write(_readBIO, _buffer, (int)tmp) ==
			    (int)tmp);
		} @catch (OFReadFailedException *e) {
			if (e.errNo != EWOULDBLOCK && e.errNo != EAGAIN)
				@throw e;
		}
	}

	ret = SSL_read_ex(_SSL, buffer, length, &bytesRead);

	while (BIO_ctrl_pending(_writeBIO) > 0) {
		int tmp = BIO_read(_writeBIO, _buffer, bufferSize);

		OFEnsure(tmp >= 0);

		[_underlyingStream writeBuffer: _buffer length: tmp];
		[_underlyingStream flushWriteBuffer];
	}

	if (ret != 1) {

		/*



		 * The underlying stream might have had data ready, but not


		 * enough for OpenSSL to return decrypted data. This means the









		 * caller might have observed the TLS stream for reading, got a

		 * ready signal and read - and expects the read to succeed, not


		 * to fail with EWOULDBLOCK, as it was signaled ready.

		 * Therefore, return 0, as we could read 0 decrypted bytes, but



		 * cleared the ready signal of the underlying stream.


		 */
		if (SSL_get_error(_SSL, ret) == SSL_ERROR_WANT_READ)
			return 0;


		/* FIXME: Translate error to errNo */
		@throw [OFReadFailedException exceptionWithObject: self
						  requestedLength: length
							    errNo: 0];
	}

	return bytesRead;
}

- (size_t)lowlevelWriteBuffer: (const void *)buffer length: (size_t)length
{
	int ret;
	size_t bytesWritten;








>
>














<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<











|
>
|
>
>
>
|
>
>
|
>
>
>
>
>
>
>
>
>
|
>
|
>
>
|
>
|
>
>
>
|
>
>
|


|
>
|
|
|
|
<
<
<







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

	if (_handshakeDone)
		SSL_shutdown(_SSL);

	SSL_free(_SSL);
	_SSL = NULL;

	_handshakeDone = false;

	[_host release];
	_host = nil;

	[super close];
}

- (size_t)lowlevelReadIntoBuffer: (void *)buffer length: (size_t)length
{
	int ret;
	size_t bytesRead;

	if (!_handshakeDone)
		@throw [OFNotOpenException exceptionWithObject: self];

















	ret = SSL_read_ex(_SSL, buffer, length, &bytesRead);

	while (BIO_ctrl_pending(_writeBIO) > 0) {
		int tmp = BIO_read(_writeBIO, _buffer, bufferSize);

		OFEnsure(tmp >= 0);

		[_underlyingStream writeBuffer: _buffer length: tmp];
		[_underlyingStream flushWriteBuffer];
	}

	if (ret == 1)
		return bytesRead;

	if (SSL_get_error(_SSL, ret) == SSL_ERROR_WANT_READ) {
		if (BIO_ctrl_pending(_readBIO) < 1) {
			@try {
				size_t tmp = [_underlyingStream
				    readIntoBuffer: _buffer
					    length: bufferSize];

				OFEnsure(tmp <= INT_MAX);
				/* Writing to a memory BIO must never fail. */
				OFEnsure(BIO_write(_readBIO, _buffer,
				    (int)tmp) == (int)tmp);
			} @catch (OFReadFailedException *e) {
				if (e.errNo == EWOULDBLOCK || e.errNo != EAGAIN)
					return 0;
			}
		}

		ret = SSL_read_ex(_SSL, buffer, length, &bytesRead);

		while (BIO_ctrl_pending(_writeBIO) > 0) {
			int tmp = BIO_read(_writeBIO, _buffer, bufferSize);

			OFEnsure(tmp >= 0);

			[_underlyingStream writeBuffer: _buffer length: tmp];
			[_underlyingStream flushWriteBuffer];
		}

		if (ret == 1)
			return bytesRead;

		if (SSL_get_error(_SSL, ret) == SSL_ERROR_WANT_READ)
			return 0;
	}

	/* FIXME: Translate error to errNo */
	@throw [OFReadFailedException exceptionWithObject: self
					  requestedLength: length
						    errNo: 0];



}

- (size_t)lowlevelWriteBuffer: (const void *)buffer length: (size_t)length
{
	int ret;
	size_t bytesWritten;

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
		[_underlyingStream writeBuffer: _buffer length: tmp];
		[_underlyingStream flushWriteBuffer];
	}

	return bytesWritten;
}

- (bool)hasDataInReadBuffer
{


	if (SSL_pending(_SSL) > 0 || BIO_ctrl_pending(_readBIO) > 0)
		return true;

	return super.hasDataInReadBuffer;


}

- (void)asyncPerformClientHandshakeWithHost: (OFString *)host
				runLoopMode: (OFRunLoopMode)runLoopMode
{
	static const OFTLSStreamErrorCode initFailedErrorCode =
	    OFTLSStreamErrorCodeInitializationFailed;
	id exception = nil;
	int status;

	if (_SSL != NULL)
		@throw [OFAlreadyConnectedException exceptionWithSocket: self];

	if ((_readBIO = BIO_new(BIO_s_mem())) == NULL)
		@throw [OFTLSHandshakeFailedException
		    exceptionWithStream: self
				   host: host
			      errorCode: initFailedErrorCode];








|

>
>
|
<
|
|
>
>











|







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
		[_underlyingStream writeBuffer: _buffer length: tmp];
		[_underlyingStream flushWriteBuffer];
	}

	return bytesWritten;
}

- (bool)lowlevelHasDataInReadBuffer
{
#ifdef HAVE_SSL_HAS_PENDING
	return (_underlyingStream.hasDataInReadBuffer ||
	    SSL_has_pending(_SSL) || BIO_ctrl_pending(_readBIO) > 0);

#else
	return (_underlyingStream.hasDataInReadBuffer ||
	    SSL_pending(_SSL) > 0 || BIO_ctrl_pending(_readBIO) > 0);
#endif
}

- (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)
		@throw [OFTLSHandshakeFailedException
		    exceptionWithStream: self
				   host: host
			      errorCode: initFailedErrorCode];

274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
		case SSL_ERROR_WANT_READ:
			[_underlyingStream asyncReadIntoBuffer: _buffer
							length: bufferSize
						   runLoopMode: runLoopMode];
			[_delegate retain];
			return;
		case SSL_ERROR_WANT_WRITE:
			[_underlyingStream
			    asyncWriteData: [OFData dataWithItems: "" count: 0]
			       runLoopMode: runLoopMode];
			[_delegate retain];
			return;
		default:
			/* FIXME: Map to better errors */
			exception = [OFTLSHandshakeFailedException
			    exceptionWithStream: self
					   host: host







|
<
|







285
286
287
288
289
290
291
292

293
294
295
296
297
298
299
300
		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
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
	     length: (size_t)length
	  exception: (nullable id)exception
{
	if (exception == nil) {
		static const OFTLSStreamErrorCode unknownErrorCode =
		    OFTLSStreamErrorCodeUnknown;
		int status;
		OFData *data;

		OFEnsure(length <= INT_MAX);
		OFEnsure(BIO_write(_readBIO, buffer, (int)length) ==
		    (int)length);

		status = SSL_do_handshake(_SSL);








<







315
316
317
318
319
320
321

322
323
324
325
326
327
328
	     length: (size_t)length
	  exception: (nullable id)exception
{
	if (exception == nil) {
		static const OFTLSStreamErrorCode unknownErrorCode =
		    OFTLSStreamErrorCodeUnknown;
		int status;


		OFEnsure(length <= INT_MAX);
		OFEnsure(BIO_write(_readBIO, buffer, (int)length) ==
		    (int)length);

		status = SSL_do_handshake(_SSL);

328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346

		if (status == 1)
			_handshakeDone = true;
		else {
			switch (SSL_get_error(_SSL, status)) {
			case SSL_ERROR_WANT_READ:
				return true;
			case SSL_ERROR_WANT_WRITE:
				data = [OFData dataWithItems: "" count: 0];
				OFRunLoopMode runLoopMode =
				    [OFRunLoop currentRunLoop].currentMode;
				[_underlyingStream asyncWriteData: data
						      runLoopMode: runLoopMode];
				return false;
			default:
				exception = [OFTLSHandshakeFailedException
				    exceptionWithStream: self
						   host: _host
					      errorCode: unknownErrorCode];







|
<


|







337
338
339
340
341
342
343
344

345
346
347
348
349
350
351
352
353
354

		if (status == 1)
			_handshakeDone = true;
		else {
			switch (SSL_get_error(_SSL, status)) {
			case SSL_ERROR_WANT_READ:
				return true;
			case SSL_ERROR_WANT_WRITE:;

				OFRunLoopMode runLoopMode =
				    [OFRunLoop currentRunLoop].currentMode;
				[_underlyingStream asyncWriteData: [OFData data]
						      runLoopMode: runLoopMode];
				return false;
			default:
				exception = [OFTLSHandshakeFailedException
				    exceptionWithStream: self
						   host: _host
					      errorCode: unknownErrorCode];

Modified src/tls/OFSecureTransportTLSStream.h from [6f1a3f10c3] to [798981535c].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/tls/OFSecureTransportTLSStream.m from [d93ffbbd51] to [b218de48f5].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#include <errno.h>

#import "OFSecureTransportTLSStream.h"

#import "OFAlreadyConnectedException.h"
#import "OFNotOpenException.h"
#import "OFReadFailedException.h"
#import "OFTLSHandshakeFailedException.h"
#import "OFWriteFailedException.h"

int _ObjFWTLS_reference;


|



















|







1
2
3
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.
 */

#include "config.h"

#include <errno.h>

#import "OFSecureTransportTLSStream.h"

#import "OFAlreadyOpenException.h"
#import "OFNotOpenException.h"
#import "OFReadFailedException.h"
#import "OFTLSHandshakeFailedException.h"
#import "OFWriteFailedException.h"

int _ObjFWTLS_reference;

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
						   requestedLength: length
						      bytesWritten: bytesWritten
							     errNo: 0];

	return bytesWritten;
}

- (bool)hasDataInReadBuffer
{
	size_t bufferSize;


	if (SSLGetBufferedReadSize(_context, &bufferSize) == noErr &&
	    bufferSize > 0)
		return true;

	return super.hasDataInReadBuffer;
}

- (void)asyncPerformClientHandshakeWithHost: (OFString *)host
				runLoopMode: (OFRunLoopMode)runLoopMode
{
	static const OFTLSStreamErrorCode initFailedErrorCode =
	    OFTLSStreamErrorCodeInitializationFailed;
	id exception = nil;
	OSStatus status;

	if (_context != NULL)
		@throw [OFAlreadyConnectedException exceptionWithSocket: self];

#ifdef HAVE_SSLCREATECONTEXT
	if ((_context = SSLCreateContext(kCFAllocatorDefault, kSSLClientSide,
	    kSSLStreamType)) == NULL)
#else
	if (SSLNewContext(false, &_context) != noErr)
#endif







|



>
|
|
<
<
<











|







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
						   requestedLength: length
						      bytesWritten: bytesWritten
							     errNo: 0];

	return bytesWritten;
}

- (bool)lowlevelHasDataInReadBuffer
{
	size_t bufferSize;

	return (_underlyingStream.hasDataInReadBuffer ||
	    (SSLGetBufferedReadSize(_context, &bufferSize) == noErr &&
	    bufferSize > 0));



}

- (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
	if ((_context = SSLCreateContext(kCFAllocatorDefault, kSSLClientSide,
	    kSSLStreamType)) == NULL)
#else
	if (SSLNewContext(false, &_context) != noErr)
#endif

Modified src/tls/ObjFWTLS.h from [498108c5a2] to [e5a5a6ee9b].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/unicode.h from [2eea427f38] to [87ac0a7fef].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#import "OFString.h"

#define OFUnicodeUppercaseTableSize 0x1EA
#define OFUnicodeLowercaseTableSize 0x1EA
#define OFUnicodeTitlecaseTableSize 0x1EA
#define OFUnicodeCaseFoldingTableSize 0x1EA
#define OFUnicodeDecompositionTableSize 0x2FB
#define OFUnicodeDecompositionCompatTableSize 0x2FB

#ifdef __cplusplus
extern "C" {
#endif
extern const OFUnichar *const _Nonnull
    OFUnicodeUppercaseTable[OFUnicodeUppercaseTableSize];
extern const OFUnichar *const _Nonnull
    OFUnicodeLowercaseTable[OFUnicodeLowercaseTableSize];
extern const OFUnichar *const _Nonnull
    OFUnicodeTitlecaseTable[OFUnicodeTitlecaseTableSize];
extern const OFUnichar *const _Nonnull
    OFUnicodeCaseFoldingTable[OFUnicodeCaseFoldingTableSize];
extern const char *const _Nullable *const _Nonnull
    OFUnicodeDecompositionTable[OFUnicodeDecompositionTableSize];
extern const char *const _Nullable *const _Nonnull
    OFUnicodeDecompositionCompatTable[OFUnicodeDecompositionCompatTableSize];
#ifdef __cplusplus
}
#endif

|



















<
<












<
<
<
<



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21


22
23
24
25
26
27
28
29
30
31
32
33




34
35
36
/*
 * Copyright (c) 2008-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 "OFString.h"

#define OFUnicodeUppercaseTableSize 0x1EA
#define OFUnicodeLowercaseTableSize 0x1EA
#define OFUnicodeTitlecaseTableSize 0x1EA
#define OFUnicodeCaseFoldingTableSize 0x1EA



#ifdef __cplusplus
extern "C" {
#endif
extern const OFUnichar *const _Nonnull
    OFUnicodeUppercaseTable[OFUnicodeUppercaseTableSize];
extern const OFUnichar *const _Nonnull
    OFUnicodeLowercaseTable[OFUnicodeLowercaseTableSize];
extern const OFUnichar *const _Nonnull
    OFUnicodeTitlecaseTable[OFUnicodeTitlecaseTableSize];
extern const OFUnichar *const _Nonnull
    OFUnicodeCaseFoldingTable[OFUnicodeCaseFoldingTableSize];




#ifdef __cplusplus
}
#endif

Modified src/unicode.m from [1934fadafb] to [c7e0387bf9].

more than 10,000 changes

Modified src/unistd_wrapper.h from [10576ea4f7] to [5d0b16d0f5].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified src/versioninfo.rc from [ec5c3868fe] to [b00925a4c5].

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
	BLOCK "StringFileInfo" {
		BLOCK "040904E4" {
			VALUE "ProductName", "ObjFW"
			VALUE "ProductVersion", PACKAGE_VERSION
			VALUE "FileVersion", OBJFW_LIB_VERSION
			VALUE "FileDescription", "Objective-C framework"
			VALUE "LegalCopyright",
			    "(c) 2008-2022 Jonathan Schleifer"
			VALUE "InternalName", "ObjFW"
			VALUE "OriginalFilename", OBJFW_SHARED_LIB
		}

	}

	BLOCK "VarFileInfo" {
		VALUE "Translation", 0x409, 1252
	}
}







|










10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
	BLOCK "StringFileInfo" {
		BLOCK "040904E4" {
			VALUE "ProductName", "ObjFW"
			VALUE "ProductVersion", PACKAGE_VERSION
			VALUE "FileVersion", OBJFW_LIB_VERSION
			VALUE "FileDescription", "Objective-C framework"
			VALUE "LegalCopyright",
			    "(c) 2008-2024 Jonathan Schleifer"
			VALUE "InternalName", "ObjFW"
			VALUE "OriginalFilename", OBJFW_SHARED_LIB
		}

	}

	BLOCK "VarFileInfo" {
		VALUE "Translation", 0x409, 1252
	}
}

Modified tests/ForwardingTests.m from [de62832427] to [1d203d1fb8].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
	TEST(@"-[forwardingTargetForSelector:] variable arguments",
	    [[testObject forwardingTargetVarArgTest: FORMAT, ARGS]
	    isEqual: RESULT])
	/*
	 * Don't try fpret on Win64 if we don't have stret forwarding, as
	 * long double is handled as a struct there.
	 */
# if !defined(OF_WINDOWS) || !defined(OF_X86_64) || \
	defined(OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR_STRET)
	TEST(@"-[forwardingTargetForSelector:] fp return",
	    [testObject forwardingTargetFPRetTest] == 12345678.00006103515625)
# endif
# ifdef OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR_STRET
	TEST(@"-[forwardingTargetForSelector:] struct return",
	    !memcmp([testObject forwardingTargetStRetTest].buffer,
	    "abcdefghijklmnopqrstuvwxyz", 27))







|
|







204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
	TEST(@"-[forwardingTargetForSelector:] variable arguments",
	    [[testObject forwardingTargetVarArgTest: FORMAT, ARGS]
	    isEqual: RESULT])
	/*
	 * Don't try fpret on Win64 if we don't have stret forwarding, as
	 * long double is handled as a struct there.
	 */
# if !defined(OF_WINDOWS) || !defined(OF_AMD64) || \
    defined(OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR_STRET)
	TEST(@"-[forwardingTargetForSelector:] fp return",
	    [testObject forwardingTargetFPRetTest] == 12345678.00006103515625)
# endif
# ifdef OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR_STRET
	TEST(@"-[forwardingTargetForSelector:] struct return",
	    !memcmp([testObject forwardingTargetStRetTest].buffer,
	    "abcdefghijklmnopqrstuvwxyz", 27))

Modified tests/ImportTest.m from [50763ee365] to [cdf2caeff4].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#import <ObjFW/ObjFW.h>

|













|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/*
 * 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;

Modified tests/Makefile from [1571a065f0] to [b7f0a6995a].

1
2
3
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
include ../extra.mk

SUBDIRS = ${TESTPLUGIN}	\
	  ${OBJC_SYNC}	\
	  terminal

CLEAN = EBOOT.PBP		\
	boot.dol		\
	${PROG_NOINST}.arm9	\
	${PROG_NOINST}.nds	\
	${PROG_NOINST}.nro	\
	${PROG_NOINST}.rpx	\
	serialization_xml.m	\
	testfile_bin.m		\
	testfile_ini.m
DISTCLEAN = Info.plist

PROG_NOINST = tests${PROG_SUFFIX}
STATIC_LIB_NOINST = ${TESTS_STATIC_LIB}
SRCS = ForwardingTests.m		\
       OFASN1DERParsingTests.m		\
       OFASN1DERRepresentationTests.m	\
       OFArrayTests.m			\
       ${OF_BLOCK_TESTS_M}		\
       OFCharacterSetTests.m		\

       OFDataTests.m			\
       OFDateTests.m			\
       OFDictionaryTests.m		\
       OFHMACTests.m			\
       OFINIFileTests.m			\

       OFInvocationTests.m		\
       OFJSONTests.m			\
       OFListTests.m			\
       OFLocaleTests.m			\
       OFMD5HashTests.m			\

       OFMemoryStreamTests.m		\
       OFMethodSignatureTests.m		\
       OFNotificationCenterTests.m	\
       OFNumberTests.m			\
       OFObjectTests.m			\
       OFPBKDF2Tests.m			\
       OFPropertyListTests.m		\
       OFRIPEMD160HashTests.m		\
       OFSHA1HashTests.m		\
       OFSHA224HashTests.m		\
       OFSHA256HashTests.m		\
       OFSHA384HashTests.m		\
       OFSHA512HashTests.m		\
       OFScryptTests.m			\
       OFSerializationTests.m		\
       OFSetTests.m			\
       OFStreamTests.m			\
       OFStringTests.m			\
       OFSystemInfoTests.m		\
       OFURITests.m			\
       OFValueTests.m			\
       OFXMLElementBuilderTests.m	\
       OFXMLNodeTests.m			\
       OFXMLParserTests.m		\
       RuntimeTests.m			\
       ${RUNTIME_ARC_TESTS_M}		\
       TestsAppDelegate.m		\
       ${USE_SRCS_FILES}		\
       ${USE_SRCS_PLUGINS}		\
       ${USE_SRCS_SOCKETS}		\
       ${USE_SRCS_THREADS}		\
       ${USE_SRCS_WINDOWS}		\
       serialization_xml.m		\
       testfile_bin.m			\
       testfile_ini.m
SRCS_PLUGINS = OFPluginTests.m
SRCS_SOCKETS = OFDNSResolverTests.m		\
	       ${OF_HTTP_CLIENT_TESTS_M}	\
	       OFHTTPCookieTests.m		\
	       OFHTTPCookieManagerTests.m	\












<












>





>





>














<




<












<







1
2
3
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
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	\
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
SRCS_WINDOWS = OFWindowsRegistryKeyTests.m

IOS_USER ?= mobile
IOS_TMP ?= /tmp/objfw-test

include ../buildsys.mk

serialization_xml.m: serialization.xml
	${SHELL} ../utils/objfw-embed serialization.xml serialization.xml $@
testfile_bin.m: testfile.bin
	${SHELL} ../utils/objfw-embed testfile.bin testfile.bin $@
testfile_ini.m: testfile.ini
	${SHELL} ../utils/objfw-embed testfile.ini testfile.ini $@

.PHONY: run run-on-ios run-on-android
run:
	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
	rm -f ${OBJFWRT_AMIGA_LIB}
	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}; \







<
<














<







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
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}
	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}; \
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
		${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
	if test -f ../src/runtime/${OBJFWRT_AMIGA_LIB}; then \
		${LN_S} ../src/runtime/${OBJFWRT_AMIGA_LIB} \
		    ${OBJFWRT_AMIGA_LIB}; \
	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}; \







<
<
<
<







135
136
137
138
139
140
141




142
143
144
145
146
147
148
		${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}; \

Modified tests/OFASN1DERParsingTests.m from [6d6dab178a] to [c8309707b3].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2021 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified tests/OFASN1DERRepresentationTests.m from [c3751ee953] to [08cf18d206].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2021 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified tests/OFArrayTests.m from [cc2ce2f7d0] to [1024ac5260].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
	    valueForKey: @"length"] isEqual:
	    [arrayClass arrayWithObjects: [OFNumber numberWithInt: 3],
	    [OFNumber numberWithInt: 3], [OFNumber numberWithInt: 6], nil]] &&
	    [[[arrayClass arrayWithObjects: @"1", @"2", nil]
	    valueForKey: @"@count"] isEqual: [OFNumber numberWithInt: 2]])

	mutableArray1 = [mutableArrayClass arrayWithObjects:
	    [OFMutableURI URIWithString: @"http://foo.bar/"],
	    [OFMutableURI URIWithString: @"http://bar.qux/"],
	    [OFMutableURI URIWithString: @"http://qux.quxqux/"], nil];
	TEST(@"-[setValue:forKey:]",
	    R([mutableArray1 setValue: [OFNumber numberWithShort: 1234]
			       forKey: @"port"]) &&
	    [mutableArray1 isEqual: [arrayClass arrayWithObjects:
	    [OFURI URIWithString: @"http://foo.bar:1234/"],
	    [OFURI URIWithString: @"http://bar.qux:1234/"],
	    [OFURI URIWithString: @"http://qux.quxqux:1234/"], nil]])

	objc_autoreleasePoolPop(pool);
}

- (void)arrayTests
{
	module = @"OFArray";







|
|
|




|
|
|







427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
	    valueForKey: @"length"] isEqual:
	    [arrayClass arrayWithObjects: [OFNumber numberWithInt: 3],
	    [OFNumber numberWithInt: 3], [OFNumber numberWithInt: 6], nil]] &&
	    [[[arrayClass arrayWithObjects: @"1", @"2", nil]
	    valueForKey: @"@count"] isEqual: [OFNumber numberWithInt: 2]])

	mutableArray1 = [mutableArrayClass arrayWithObjects:
	    [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";

Modified tests/OFBlockTests.m from [d2cc5b8a58] to [41100ed0e1].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
25
26
27
28
29
30
31


32

33
34
35
36
37
38
39
extern struct objc_class _NSConcreteMallocBlock;
#elif defined(OF_APPLE_RUNTIME)
extern void *_NSConcreteStackBlock;
extern void *_NSConcreteGlobalBlock;
extern void *_NSConcreteMallocBlock;
#endif



static void (^globalBlock)(void) = ^ {};


static int
(^returnStackBlock(void))(void)
{
	__block int i = 42;

	return [Block_copy(^ int { return ++i; }) autorelease];







>
>

>







25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
extern struct objc_class _NSConcreteMallocBlock;
#elif defined(OF_APPLE_RUNTIME)
extern void *_NSConcreteStackBlock;
extern void *_NSConcreteGlobalBlock;
extern void *_NSConcreteMallocBlock;
#endif

/* Clang on Win32 generates broken code that crashes for global blocks. */
#if !defined(OF_WINDOWS) || !defined(__clang__)
static void (^globalBlock)(void) = ^ {};
#endif

static int
(^returnStackBlock(void))(void)
{
	__block int i = 42;

	return [Block_copy(^ int { return ++i; }) autorelease];
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96

97
98

99
100
101
102
103
104
105
106
107

108

109
110
111
112
113
114
115
116
	void (^mallocBlock)(void);
	int (^voidBlock)(void);

	TEST(@"Class of stack block",
	    (Class)&_NSConcreteStackBlock == objc_getClass("OFStackBlock") &&
	    [stackBlock isKindOfClass: [OFBlock class]])

#if !defined(OF_WINDOWS) || !defined(__clang__) || !defined(OF_NO_SHARED)
	/*
	 * Causes a linker error on Windows with Clang when compiling as a
	 * static library. This is a bug in Clang.
	 */
	TEST(@"Class of global block",
	    (Class)&_NSConcreteGlobalBlock == objc_getClass("OFGlobalBlock") &&
	    [globalBlock isKindOfClass: [OFBlock class]])
#endif

	TEST(@"Class of a malloc block",
	    (Class)&_NSConcreteMallocBlock == objc_getClass("OFMallocBlock"))

	TEST(@"Copying a stack block",
	    (mallocBlock = [[stackBlock copy] autorelease]) &&
	    [mallocBlock class] == objc_getClass("OFMallocBlock") &&
	    [mallocBlock isKindOfClass: [OFBlock class]])

	TEST(@"Copying a stack block and referencing its variable",
	    forwardTest() == 5)

	TEST(@"Copying a stack block and using its copied variable",
	    (voidBlock = returnStackBlock()) && voidBlock() == 43 &&
	    voidBlock() == 44 && voidBlock() == 45)


	TEST(@"Copying a global block",
	    (id)globalBlock == [[globalBlock copy] autorelease])


#ifndef __clang_analyzer__
	TEST(@"Copying a malloc block",
	    (id)mallocBlock == [mallocBlock copy] &&
	    [mallocBlock retainCount] == 2)
#endif

	TEST(@"Autorelease a stack block", R([stackBlock autorelease]))


	TEST(@"Autorelease a global block", R([globalBlock autorelease]))


#ifndef __clang_analyzer__
	TEST(@"Autorelease a malloc block", R([mallocBlock autorelease]))
#endif

	objc_autoreleasePoolPop(pool);
}
@end







|
<
<
<
<




















>


>









>

>








68
69
70
71
72
73
74
75




76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
	void (^mallocBlock)(void);
	int (^voidBlock)(void);

	TEST(@"Class of stack block",
	    (Class)&_NSConcreteStackBlock == objc_getClass("OFStackBlock") &&
	    [stackBlock isKindOfClass: [OFBlock class]])

#if !defined(OF_WINDOWS) || !defined(__clang__)




	TEST(@"Class of global block",
	    (Class)&_NSConcreteGlobalBlock == objc_getClass("OFGlobalBlock") &&
	    [globalBlock isKindOfClass: [OFBlock class]])
#endif

	TEST(@"Class of a malloc block",
	    (Class)&_NSConcreteMallocBlock == objc_getClass("OFMallocBlock"))

	TEST(@"Copying a stack block",
	    (mallocBlock = [[stackBlock copy] autorelease]) &&
	    [mallocBlock class] == objc_getClass("OFMallocBlock") &&
	    [mallocBlock isKindOfClass: [OFBlock class]])

	TEST(@"Copying a stack block and referencing its variable",
	    forwardTest() == 5)

	TEST(@"Copying a stack block and using its copied variable",
	    (voidBlock = returnStackBlock()) && voidBlock() == 43 &&
	    voidBlock() == 44 && voidBlock() == 45)

#if !defined(OF_WINDOWS) || !defined(__clang__)
	TEST(@"Copying a global block",
	    (id)globalBlock == [[globalBlock copy] autorelease])
#endif

#ifndef __clang_analyzer__
	TEST(@"Copying a malloc block",
	    (id)mallocBlock == [mallocBlock copy] &&
	    [mallocBlock retainCount] == 2)
#endif

	TEST(@"Autorelease a stack block", R([stackBlock autorelease]))

#if !defined(OF_WINDOWS) || !defined(__clang__)
	TEST(@"Autorelease a global block", R([globalBlock autorelease]))
#endif

#ifndef __clang_analyzer__
	TEST(@"Autorelease a malloc block", R([mallocBlock autorelease]))
#endif

	objc_autoreleasePoolPop(pool);
}
@end

Modified tests/OFCharacterSetTests.m from [9bcb0257c8] to [cbaf41131b].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Added tests/OFColorTests.m version [43c0fcb4d4].































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
/*
 * Copyright (c) 2008-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 "TestsAppDelegate.h"

static OFString *const module = @"OFColor";

@implementation TestsAppDelegate (OFColorTests)
- (void)colorTests
{
	void *pool = objc_autoreleasePoolPush();
	OFColor *color;
	float red, green, blue, alpha;

	TEST(@"+[colorWithRed:green:blue:alpha:]",
	    (color = [OFColor colorWithRed: 63.f / 255
				     green: 127.f / 255
				      blue: 1
				     alpha: 1]))

#ifdef OF_OBJFW_RUNTIME
	TEST(@"+[colorWithRed:green:blue:alpha:] returns tagged pointer",
	    object_isTaggedPointer(color))
#endif

	TEST(@"-[getRed:green:blue:alpha:]",
	    R([color getRed: &red green: &green blue: &blue alpha: &alpha]) &&
	    red == 63.f / 255 && green == 127.f / 255 && blue == 1 &&
	    alpha == 1)

	objc_autoreleasePoolPop(pool);
}
@end

Modified tests/OFDDPSocketTests.m from [7798ad31e7] to [5433dc7a16].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
36
37
38
39
40
41
42

43
44
45
46
47
48
49
		    R(address1 = [sock bindToNetwork: 0
						node: 0
						port: 0
					protocolType: 11]))
	} @catch (OFBindSocketFailedException *e) {
		switch (e.errNo) {
		case EAFNOSUPPORT:

			[OFStdOut setForegroundColor: [OFColor lime]];
			[OFStdOut writeLine:
			    @"\r[OFDDPSocket] -[bindToNetwork:node:port:"
			    @"protocolType:] AppleTalk unsupported, skipping "
			    @"tests"];
			break;
		case EADDRNOTAVAIL:







>







36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
		    R(address1 = [sock bindToNetwork: 0
						node: 0
						port: 0
					protocolType: 11]))
	} @catch (OFBindSocketFailedException *e) {
		switch (e.errNo) {
		case EAFNOSUPPORT:
		case EPROTONOSUPPORT:
			[OFStdOut setForegroundColor: [OFColor lime]];
			[OFStdOut writeLine:
			    @"\r[OFDDPSocket] -[bindToNetwork:node:port:"
			    @"protocolType:] AppleTalk unsupported, skipping "
			    @"tests"];
			break;
		case EADDRNOTAVAIL:

Modified tests/OFDNSResolverTests.m from [b7997ffc05] to [979544c90c].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
	[OFStdOut writeFormat: @"[OFDNSResolver] Max attempts: %u\n",
	    resolver.maxAttempts];

	[OFStdOut writeFormat:
	    @"[OFDNSResolver] Min number of dots in absolute name: %u\n",
	    resolver.minNumberOfDotsInAbsoluteName];

	[OFStdOut writeFormat: @"[OFDNSResolver] Uses TCP: %u\n",
	    resolver.usesTCP];

	[OFStdOut writeFormat:
	    @"[OFDNSResolver] Config reload interval: %lf\n",
	    resolver.configReloadInterval];

	objc_autoreleasePoolPop(pool);
}
@end







|
|








55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
	[OFStdOut writeFormat: @"[OFDNSResolver] Max attempts: %u\n",
	    resolver.maxAttempts];

	[OFStdOut writeFormat:
	    @"[OFDNSResolver] Min number of dots in absolute name: %u\n",
	    resolver.minNumberOfDotsInAbsoluteName];

	[OFStdOut writeFormat: @"[OFDNSResolver] Forces TCP: %u\n",
	    resolver.forcesTCP];

	[OFStdOut writeFormat:
	    @"[OFDNSResolver] Config reload interval: %lf\n",
	    resolver.configReloadInterval];

	objc_autoreleasePoolPop(pool);
}
@end

Modified tests/OFDataTests.m from [ffac8c7aa2] to [a8658a6bbf].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified tests/OFDateTests.m from [f110295df2] to [a09d2c22e2].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified tests/OFDictionaryTests.m from [856ca278b2] to [322f36dbf5].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified tests/OFHMACTests.m from [dc8ace4048] to [b03d7ee96c].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
    "\x61\xB3\xF9\x1A\xE3\x09\x43\xA6\x5B\x85\xB1\x50\x5B\xCB\x1A\x2E"
    "\xB7\xE8\x87\xC1\x73\x19\x63\xF6\xA2\x91\x8D\x7E\x2E\xCC\xEC\x99";

@implementation TestsAppDelegate (OFHMACTests)
- (void)HMACTests
{
	void *pool = objc_autoreleasePoolPush();
	OFURI *URI = [OFURI URIWithString: @"embedded:testfile.bin"];
	OFStream *file = [OFURIHandler openItemAtURI: URI mode: @"r"];
	OFHMAC *HMACMD5, *HMACSHA1, *HMACRMD160;
	OFHMAC *HMACSHA256, *HMACSHA384, *HMACSHA512;

	TEST(@"+[HMACWithHashClass:] with MD5",
	    (HMACMD5 = [OFHMAC HMACWithHashClass: [OFMD5Hash class]
			   allowsSwappableMemory: true]))
	TEST(@"+[HMACWithHashClass:] with SHA-1",







|
|







47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
    "\x61\xB3\xF9\x1A\xE3\x09\x43\xA6\x5B\x85\xB1\x50\x5B\xCB\x1A\x2E"
    "\xB7\xE8\x87\xC1\x73\x19\x63\xF6\xA2\x91\x8D\x7E\x2E\xCC\xEC\x99";

@implementation TestsAppDelegate (OFHMACTests)
- (void)HMACTests
{
	void *pool = objc_autoreleasePoolPush();
	OFIRI *IRI = [OFIRI IRIWithString: @"embedded:testfile.bin"];
	OFStream *file = [OFIRIHandler openItemAtIRI: IRI mode: @"r"];
	OFHMAC *HMACMD5, *HMACSHA1, *HMACRMD160;
	OFHMAC *HMACSHA256, *HMACSHA384, *HMACSHA512;

	TEST(@"+[HMACWithHashClass:] with MD5",
	    (HMACMD5 = [OFHMAC HMACWithHashClass: [OFMD5Hash class]
			   allowsSwappableMemory: true]))
	TEST(@"+[HMACWithHashClass:] with SHA-1",

Modified tests/OFHTTPClientTests.m from [64ad652a21] to [8ae0f89264].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
34
35
36
37
38
39
40

41
42
43
44
45
46

47
48
49
50
51
52
53
}
@end

@implementation HTTPClientTestsServer
- (id)main
{
	OFTCPSocket *listener, *client;

	char buffer[5];

	[condition lock];

	listener = [OFTCPSocket socket];
	_port = [listener bindToHost: @"127.0.0.1" port: 0];

	[listener listen];

	[condition signal];
	[condition unlock];

	client = [listener accept];








>





|
>







34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
}
@end

@implementation HTTPClientTestsServer
- (id)main
{
	OFTCPSocket *listener, *client;
	OFSocketAddress address;
	char buffer[5];

	[condition lock];

	listener = [OFTCPSocket socket];
	address = [listener bindToHost: @"127.0.0.1" port: 0];
	_port = OFSocketAddressIPPort(&address);
	[listener listen];

	[condition signal];
	[condition unlock];

	client = [listener accept];

97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
	[[OFRunLoop mainRunLoop] stop];
}

- (void)HTTPClientTests
{
	void *pool = objc_autoreleasePoolPush();
	HTTPClientTestsServer *server;
	OFURI *URI;
	OFHTTPClient *client;
	OFHTTPRequest *request;
	OFData *data;

	condition = [OFCondition condition];
	[condition lock];

	server = [[[HTTPClientTestsServer alloc] init] autorelease];
	server.supportsSockets = true;
	[server start];

	[condition wait];
	[condition unlock];

	URI = [OFURI URIWithString:
	    [OFString stringWithFormat: @"http://127.0.0.1:%" @PRIu16 "/foo",
					server->_port]];

	TEST(@"-[asyncPerformRequest:]",
	    (client = [OFHTTPClient client]) && (client.delegate = self) &&
	    (request = [OFHTTPRequest requestWithURI: URI]) &&
	    (request.headers =
	    [OFDictionary dictionaryWithObject: @"5"
					forKey: @"Content-Length"]) &&
	    R([client asyncPerformRequest: request]))

	[[OFRunLoop mainRunLoop] runUntilDate:
	    [OFDate dateWithTimeIntervalSinceNow: 2]];







|














|





|







99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
	[[OFRunLoop mainRunLoop] stop];
}

- (void)HTTPClientTests
{
	void *pool = objc_autoreleasePoolPush();
	HTTPClientTestsServer *server;
	OFIRI *IRI;
	OFHTTPClient *client;
	OFHTTPRequest *request;
	OFData *data;

	condition = [OFCondition condition];
	[condition lock];

	server = [[[HTTPClientTestsServer alloc] init] autorelease];
	server.supportsSockets = true;
	[server start];

	[condition wait];
	[condition unlock];

	IRI = [OFIRI IRIWithString:
	    [OFString stringWithFormat: @"http://127.0.0.1:%" @PRIu16 "/foo",
					server->_port]];

	TEST(@"-[asyncPerformRequest:]",
	    (client = [OFHTTPClient client]) && (client.delegate = self) &&
	    (request = [OFHTTPRequest requestWithIRI: IRI]) &&
	    (request.headers =
	    [OFDictionary dictionaryWithObject: @"5"
					forKey: @"Content-Length"]) &&
	    R([client asyncPerformRequest: request]))

	[[OFRunLoop mainRunLoop] runUntilDate:
	    [OFDate dateWithTimeIntervalSinceNow: 2]];

Modified tests/OFHTTPCookieManagerTests.m from [fc980e6e00] to [fdaaae41cf].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
static OFString *const module = @"OFHTTPCookieManager";

@implementation TestsAppDelegate (OFHTTPCookieManagerTests)
- (void)HTTPCookieManagerTests
{
	void *pool = objc_autoreleasePoolPush();
	OFHTTPCookieManager *manager = [OFHTTPCookieManager manager];
	OFURI *URI1, *URI2, *URI3, *URI4;
	OFHTTPCookie *cookie1, *cookie2, *cookie3, *cookie4, *cookie5;

	URI1 = [OFURI URIWithString: @"http://nil.im/foo"];
	URI2 = [OFURI URIWithString: @"https://nil.im/foo/bar"];
	URI3 = [OFURI URIWithString: @"https://test.nil.im/foo/bar"];
	URI4 = [OFURI URIWithString: @"http://webkeks.org/foo/bar"];

	cookie1 = [OFHTTPCookie cookieWithName: @"test"
					 value: @"1"
					domain: @"nil.im"];
	TEST(@"-[addCookie:forURI:] #1",
	    R([manager addCookie: cookie1 forURI: URI1]))

	TEST(@"-[cookiesForURI:] #1",
	    [[manager cookiesForURI: URI1] isEqual:
	    [OFArray arrayWithObject: cookie1]])

	cookie2 = [OFHTTPCookie cookieWithName: @"test"
					 value: @"2"
					domain: @"webkeks.org"];
	TEST(@"-[addCookie:forURI:] #2",
	    R([manager addCookie: cookie2 forURI: URI1]))

	TEST(@"-[cookiesForURI:] #2",
	    [[manager cookiesForURI: URI1] isEqual:
	    [OFArray arrayWithObject: cookie1]] &&
	    [[manager cookiesForURI: URI4] isEqual: [OFArray array]])

	cookie3 = [OFHTTPCookie cookieWithName: @"test"
					 value: @"3"
					domain: @"nil.im"];
	cookie3.secure = true;
	TEST(@"-[addCookie:forURI:] #3",
	    R([manager addCookie: cookie3 forURI: URI2]))

	TEST(@"-[cookiesForURI:] #3",
	    [[manager cookiesForURI: URI2] isEqual:
	    [OFArray arrayWithObject: cookie3]] &&
	    [[manager cookiesForURI: URI1] isEqual: [OFArray array]])

	cookie3.expires = [OFDate dateWithTimeIntervalSinceNow: -1];
	cookie4 = [OFHTTPCookie cookieWithName: @"test"
					 value: @"4"
					domain: @"nil.im"];
	cookie4.domain = @".nil.im";
	TEST(@"-[addCookie:forURI:] #4",
	    R([manager addCookie: cookie4 forURI: URI2]))

	TEST(@"-[cookiesForURI:] #4",
	    [[manager cookiesForURI: URI2] isEqual:
	    [OFArray arrayWithObject: cookie4]] &&
	    [[manager cookiesForURI: URI3] isEqual:
	    [OFArray arrayWithObject: cookie4]])

	cookie5 = [OFHTTPCookie cookieWithName: @"bar"
					 value: @"5"
					domain: @"test.nil.im"];
	TEST(@"-[addCookie:forURI:] #5",
	    R([manager addCookie: cookie5 forURI: URI1]))

	TEST(@"-[cookiesForURI:] #5",
	    [[manager cookiesForURI: URI1] isEqual:
	    [OFArray arrayWithObject: cookie4]] &&
	    [[manager cookiesForURI: URI3] isEqual:
	    [OFArray arrayWithObjects: cookie4, cookie5, nil]])

	TEST(@"-[purgeExpiredCookies]",
	    [manager.cookies isEqual:
	    [OFArray arrayWithObjects: cookie3, cookie4, cookie5, nil]] &&
	    R([manager purgeExpiredCookies]) &&
	    [manager.cookies isEqual:
	    [OFArray arrayWithObjects: cookie4, cookie5, nil]])

	objc_autoreleasePoolPop(pool);
}
@end







|


|
|
|
|




|
|

|
|





|
|

|
|

|





|
|

|
|

|






|
|

|
|

|





|
|

|
|

|












20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
static OFString *const module = @"OFHTTPCookieManager";

@implementation TestsAppDelegate (OFHTTPCookieManagerTests)
- (void)HTTPCookieManagerTests
{
	void *pool = objc_autoreleasePoolPush();
	OFHTTPCookieManager *manager = [OFHTTPCookieManager manager];
	OFIRI *IRI1, *IRI2, *IRI3, *IRI4;
	OFHTTPCookie *cookie1, *cookie2, *cookie3, *cookie4, *cookie5;

	IRI1 = [OFIRI IRIWithString: @"http://nil.im/foo"];
	IRI2 = [OFIRI IRIWithString: @"https://nil.im/foo/bar"];
	IRI3 = [OFIRI IRIWithString: @"https://test.nil.im/foo/bar"];
	IRI4 = [OFIRI IRIWithString: @"http://webkeks.org/foo/bar"];

	cookie1 = [OFHTTPCookie cookieWithName: @"test"
					 value: @"1"
					domain: @"nil.im"];
	TEST(@"-[addCookie:forIRI:] #1",
	    R([manager addCookie: cookie1 forIRI: IRI1]))

	TEST(@"-[cookiesForIRI:] #1",
	    [[manager cookiesForIRI: IRI1] isEqual:
	    [OFArray arrayWithObject: cookie1]])

	cookie2 = [OFHTTPCookie cookieWithName: @"test"
					 value: @"2"
					domain: @"webkeks.org"];
	TEST(@"-[addCookie:forIRI:] #2",
	    R([manager addCookie: cookie2 forIRI: IRI1]))

	TEST(@"-[cookiesForIRI:] #2",
	    [[manager cookiesForIRI: IRI1] isEqual:
	    [OFArray arrayWithObject: cookie1]] &&
	    [[manager cookiesForIRI: IRI4] isEqual: [OFArray array]])

	cookie3 = [OFHTTPCookie cookieWithName: @"test"
					 value: @"3"
					domain: @"nil.im"];
	cookie3.secure = true;
	TEST(@"-[addCookie:forIRI:] #3",
	    R([manager addCookie: cookie3 forIRI: IRI2]))

	TEST(@"-[cookiesForIRI:] #3",
	    [[manager cookiesForIRI: IRI2] isEqual:
	    [OFArray arrayWithObject: cookie3]] &&
	    [[manager cookiesForIRI: IRI1] isEqual: [OFArray array]])

	cookie3.expires = [OFDate dateWithTimeIntervalSinceNow: -1];
	cookie4 = [OFHTTPCookie cookieWithName: @"test"
					 value: @"4"
					domain: @"nil.im"];
	cookie4.domain = @".nil.im";
	TEST(@"-[addCookie:forIRI:] #4",
	    R([manager addCookie: cookie4 forIRI: IRI2]))

	TEST(@"-[cookiesForIRI:] #4",
	    [[manager cookiesForIRI: IRI2] isEqual:
	    [OFArray arrayWithObject: cookie4]] &&
	    [[manager cookiesForIRI: IRI3] isEqual:
	    [OFArray arrayWithObject: cookie4]])

	cookie5 = [OFHTTPCookie cookieWithName: @"bar"
					 value: @"5"
					domain: @"test.nil.im"];
	TEST(@"-[addCookie:forIRI:] #5",
	    R([manager addCookie: cookie5 forIRI: IRI1]))

	TEST(@"-[cookiesForIRI:] #5",
	    [[manager cookiesForIRI: IRI1] isEqual:
	    [OFArray arrayWithObject: cookie4]] &&
	    [[manager cookiesForIRI: IRI3] isEqual:
	    [OFArray arrayWithObjects: cookie4, cookie5, nil]])

	TEST(@"-[purgeExpiredCookies]",
	    [manager.cookies isEqual:
	    [OFArray arrayWithObjects: cookie3, cookie4, cookie5, nil]] &&
	    R([manager purgeExpiredCookies]) &&
	    [manager.cookies isEqual:
	    [OFArray arrayWithObjects: cookie4, cookie5, nil]])

	objc_autoreleasePoolPop(pool);
}
@end

Modified tests/OFHTTPCookieTests.m from [beb8a32ced] to [eb0c618283].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73

static OFString *const module = @"OFHTTPCookie";

@implementation TestsAppDelegate (OFHTTPCookieTests)
- (void)HTTPCookieTests
{
	void *pool = objc_autoreleasePoolPush();
	OFURI *URI = [OFURI URIWithString: @"http://nil.im"];
	OFHTTPCookie *cookie1, *cookie2;
	OFArray OF_GENERIC(OFHTTPCookie *) *cookies;

	cookie1 = [OFHTTPCookie cookieWithName: @"foo"
					 value: @"bar"
					domain: @"nil.im"];
	TEST(@"+[cookiesWithResponseHeaderFields:forURI:] #1",
	    [[OFHTTPCookie cookiesWithResponseHeaderFields: [OFDictionary
	    dictionaryWithObject: @"foo=bar"
	    forKey: @"Set-Cookie"] forURI: URI]
	    isEqual: [OFArray arrayWithObject: cookie1]])

	cookie2 = [OFHTTPCookie cookieWithName: @"qux"
					 value: @"cookie"
					domain: @"nil.im"];
	TEST(@"+[cookiesWithResponseHeaderFields:forURI:] #2",
	    [[OFHTTPCookie cookiesWithResponseHeaderFields: [OFDictionary
	    dictionaryWithObject: @"foo=bar,qux=cookie"
	    forKey: @"Set-Cookie"] forURI: URI]
	    isEqual: [OFArray arrayWithObjects: cookie1, cookie2, nil]])

	cookie1.expires = [OFDate dateWithTimeIntervalSince1970: 1234567890];
	cookie2.expires = [OFDate dateWithTimeIntervalSince1970: 1234567890];
	cookie1.path = @"/x";
	cookie2.domain = @"webkeks.org";
	cookie2.path = @"/objfw";
	cookie2.secure = true;
	cookie2.HTTPOnly = true;
	[cookie2.extensions addObject: @"foo"];
	[cookie2.extensions addObject: @"bar"];
	TEST(@"+[cookiesWithResponseHeaderFields:forURI:] #3",
	    [(cookies = [OFHTTPCookie cookiesWithResponseHeaderFields:
	    [OFDictionary dictionaryWithObject:
	    @"foo=bar; Expires=Fri, 13 Feb 2009 23:31:30 GMT; Path=/x,"
	    @"qux=cookie; Expires=Fri, 13 Feb 2009 23:31:30 GMT; "
	    @"Domain=webkeks.org; Path=/objfw; Secure; HTTPOnly; foo; bar"
	    forKey: @"Set-Cookie"] forURI: URI]) isEqual:
	    [OFArray arrayWithObjects: cookie1, cookie2, nil]])

	TEST(@"+[requestHeaderFieldsWithCookies:]",
	    [[OFHTTPCookie requestHeaderFieldsWithCookies: cookies] isEqual:
	    [OFDictionary dictionaryWithObject: @"foo=bar; qux=cookie"
					forKey: @"Cookie"]])

	objc_autoreleasePoolPop(pool);
}
@end







|






|


|





|


|











|





|










19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73

static OFString *const module = @"OFHTTPCookie";

@implementation TestsAppDelegate (OFHTTPCookieTests)
- (void)HTTPCookieTests
{
	void *pool = objc_autoreleasePoolPush();
	OFIRI *IRI = [OFIRI IRIWithString: @"http://nil.im"];
	OFHTTPCookie *cookie1, *cookie2;
	OFArray OF_GENERIC(OFHTTPCookie *) *cookies;

	cookie1 = [OFHTTPCookie cookieWithName: @"foo"
					 value: @"bar"
					domain: @"nil.im"];
	TEST(@"+[cookiesWithResponseHeaderFields:forIRI:] #1",
	    [[OFHTTPCookie cookiesWithResponseHeaderFields: [OFDictionary
	    dictionaryWithObject: @"foo=bar"
	    forKey: @"Set-Cookie"] forIRI: IRI]
	    isEqual: [OFArray arrayWithObject: cookie1]])

	cookie2 = [OFHTTPCookie cookieWithName: @"qux"
					 value: @"cookie"
					domain: @"nil.im"];
	TEST(@"+[cookiesWithResponseHeaderFields:forIRI:] #2",
	    [[OFHTTPCookie cookiesWithResponseHeaderFields: [OFDictionary
	    dictionaryWithObject: @"foo=bar,qux=cookie"
	    forKey: @"Set-Cookie"] forIRI: IRI]
	    isEqual: [OFArray arrayWithObjects: cookie1, cookie2, nil]])

	cookie1.expires = [OFDate dateWithTimeIntervalSince1970: 1234567890];
	cookie2.expires = [OFDate dateWithTimeIntervalSince1970: 1234567890];
	cookie1.path = @"/x";
	cookie2.domain = @"webkeks.org";
	cookie2.path = @"/objfw";
	cookie2.secure = true;
	cookie2.HTTPOnly = true;
	[cookie2.extensions addObject: @"foo"];
	[cookie2.extensions addObject: @"bar"];
	TEST(@"+[cookiesWithResponseHeaderFields:forIRI:] #3",
	    [(cookies = [OFHTTPCookie cookiesWithResponseHeaderFields:
	    [OFDictionary dictionaryWithObject:
	    @"foo=bar; Expires=Fri, 13 Feb 2009 23:31:30 GMT; Path=/x,"
	    @"qux=cookie; Expires=Fri, 13 Feb 2009 23:31:30 GMT; "
	    @"Domain=webkeks.org; Path=/objfw; Secure; HTTPOnly; foo; bar"
	    forKey: @"Set-Cookie"] forIRI: IRI]) isEqual:
	    [OFArray arrayWithObjects: cookie1, cookie2, nil]])

	TEST(@"+[requestHeaderFieldsWithCookies:]",
	    [[OFHTTPCookie requestHeaderFieldsWithCookies: cookies] isEqual:
	    [OFDictionary dictionaryWithObject: @"foo=bar; qux=cookie"
					forKey: @"Cookie"]])

	objc_autoreleasePoolPop(pool);
}
@end

Modified tests/OFINIFileTests.m from [18e2931d0e] to [793add569b].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
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
	    @"[types]\r\n"
	    @"integer=16\r\n"
	    @"bool=false\r\n"
	    @"float=0.25\r\n"
	    @"array1=foo\r\n"
	    @"array1=bar\r\n"
	    @"double=0.75\r\n";
	OFURI *URI;
	OFINIFile *file;
	OFINICategory *tests, *foobar, *types;
	OFArray *array;
#if defined(OF_HAVE_FILES) && !defined(OF_NINTENDO_DS)
	OFURI *writeURI;
#endif

	module = @"OFINIFile";

	URI = [OFURI URIWithString: @"embedded:testfile.ini"];
	TEST(@"+[fileWithURI:encoding:]",
	    (file = [OFINIFile fileWithURI: URI
				  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(@"-[stringForKey:]",
	    [[tests stringForKey: @"foo"] isEqual: @"bar"] &&
	    [[foobar stringForKey: @"quxquxqux"] isEqual: @"hello\"wörld"])

	TEST(@"-[setString:forKey:]",
	    R([tests setString: @"baz" forKey: @"foo"]) &&
	    R([tests setString: @"new" forKey: @"new"]) &&
	    R([foobar setString: @"a\fb" forKey: @"qux3"]))

	TEST(@"-[longLongForKey:defaultValue:]",
	    [types longLongForKey: @"integer" defaultValue: 2] == 0x20)

	TEST(@"-[setLongLong:forKey:]",
	    R([types setLongLong: 0x10 forKey: @"integer"]))

	TEST(@"-[boolForKey:defaultValue:]",
	    [types boolForKey: @"bool" defaultValue: false] == true)


	TEST(@"-[setBool:forKey:]", R([types setBool: false forKey: @"bool"]))

	TEST(@"-[floatForKey:defaultValue:]",
	    [types floatForKey: @"float" defaultValue: 1] == 0.5f)

	TEST(@"-[setFloat:forKey:]",
	    R([types setFloat: 0.25f forKey: @"float"]))

	TEST(@"-[doubleForKey:defaultValue:]",
	    [types doubleForKey: @"double" defaultValue: 3] == 0.25)

	TEST(@"-[setDouble:forKey:]",
	    R([types setDouble: 0.75 forKey: @"double"]))

	array = [OFArray arrayWithObjects: @"1", @"2", nil];
	TEST(@"-[stringArrayForKey:]",
	    [[types stringArrayForKey: @"array1"] isEqual: array] &&
	    [[types stringArrayForKey: @"array2"] isEqual: array] &&
	    [[types stringArrayForKey: @"array3"] isEqual: [OFArray array]])

	array = [OFArray arrayWithObjects: @"foo", @"bar", nil];
	TEST(@"-[setStringArray:forKey:]",
	    R([types setStringArray: 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)
	writeURI = [[OFSystemInfo temporaryDirectoryURI]


	    URIByAppendingPathComponent: @"objfw-tests.ini"
			    isDirectory: false];
	TEST(@"-[writeToFile:encoding:]",
	    R([file writeToURI: writeURI
		      encoding: OFStringEncodingCodepage437]) &&
	    [[OFString stringWithContentsOfURI: writeURI
				      encoding: OFStringEncodingCodepage437]
	    isEqual: output])
	[[OFFileManager defaultManager] removeItemAtURI: writeURI];
#else
	(void)output;
#endif

	objc_autoreleasePoolPop(pool);
}
@end







|




|




|
|
|










|
|
|

|
|
|
|

|
|

|
|

|
|

>
|

|
|

|
|

|
|

|
|


|
|
|
|


|
|









|
>
>
|
|

|

|


|







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
	    @"[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

Modified tests/OFIPXSocketTests.m from [abf65b2714] to [0ae4e44d89].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
24
25
26
27
28
29
30

31
32

33
34
35
36
37
38
39
@implementation TestsAppDelegate (OFIPXSocketTests)
- (void)IPXSocketTests
{
	const unsigned char zeroNode[IPX_NODE_LEN] = { 0 };
	void *pool = objc_autoreleasePoolPush();
	OFIPXSocket *sock;
	OFSocketAddress address1, address2;

	char buffer[5];
	unsigned char node1[IPX_NODE_LEN], node2[IPX_NODE_LEN];


	TEST(@"+[socket]", (sock = [OFIPXSocket socket]))

	@try {
		TEST(@"-[bindToNetwork:node:port:packetType:]",
		R(address1 = [sock bindToNetwork: 0
					    node: zeroNode







>


>







24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
@implementation TestsAppDelegate (OFIPXSocketTests)
- (void)IPXSocketTests
{
	const unsigned char zeroNode[IPX_NODE_LEN] = { 0 };
	void *pool = objc_autoreleasePoolPush();
	OFIPXSocket *sock;
	OFSocketAddress address1, address2;
	OFDictionary *networkInterfaces;
	char buffer[5];
	unsigned char node1[IPX_NODE_LEN], node2[IPX_NODE_LEN];
	unsigned char node[IPX_NODE_LEN];

	TEST(@"+[socket]", (sock = [OFIPXSocket socket]))

	@try {
		TEST(@"-[bindToNetwork:node:port:packetType:]",
		R(address1 = [sock bindToNetwork: 0
					    node: zeroNode
57
58
59
60
61
62
63































64
65
66
67
68
69
70
		default:
			@throw e;
		}

		objc_autoreleasePoolPop(pool);
		return;
	}
































	TEST(@"-[sendBuffer:length:receiver:]",
	    R([sock sendBuffer: "Hello" length: 5 receiver: &address1]))

	TEST(@"-[receiveIntoBuffer:length:sender:]",
	    [sock receiveIntoBuffer: buffer length: 5 sender: &address2] == 5 &&
	    memcmp(buffer, "Hello", 5) == 0 &&







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
		default:
			@throw e;
		}

		objc_autoreleasePoolPop(pool);
		return;
	}

	/*
	 * Find any network interface with IPX and send to it. Any should be
	 * fine since we bound to 0.0.
	 */
	networkInterfaces = [OFSystemInfo networkInterfaces];
	for (OFString *name in networkInterfaces) {
		OFNetworkInterface interface = [networkInterfaces
		    objectForKey: name];
		OFData *addresses = [interface
		    objectForKey: OFNetworkInterfaceIPXAddresses];

		if (addresses.count == 0)
			continue;

		OFSocketAddressSetIPXNetwork(&address1,
		    OFSocketAddressIPXNetwork([addresses itemAtIndex: 0]));
		OFSocketAddressGetIPXNode([addresses itemAtIndex: 0], node);
		OFSocketAddressSetIPXNode(&address1, node);
	}

	OFSocketAddressGetIPXNode(&address1, node);
	if (OFSocketAddressIPXNetwork(&address1) == 0 &&
	    memcmp(node, zeroNode, 6) == 0) {
		[OFStdOut setForegroundColor: [OFColor lime]];
		[OFStdOut writeLine:
		    @"[OFIPXSocket] -[sendBuffer:length:receiver:]: "
		    @"Could not determine own address, skipping tests"];
		objc_autoreleasePoolPop(pool);
		return;
	}

	TEST(@"-[sendBuffer:length:receiver:]",
	    R([sock sendBuffer: "Hello" length: 5 receiver: &address1]))

	TEST(@"-[receiveIntoBuffer:length:sender:]",
	    [sock receiveIntoBuffer: buffer length: 5 sender: &address2] == 5 &&
	    memcmp(buffer, "Hello", 5) == 0 &&

Renamed and modified tests/OFURITests.m [e9cb46977b] to tests/OFIRITests.m [3036a831f2].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42

43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75




76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152

153
154
155
156

157
158
159
160
161
162
163
164
165
166

167
168
169

170
171
172
173
174
175

176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195

196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214




215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#import "TestsAppDelegate.h"

static OFString *const module = @"OFURI";
static OFString *URIString = @"ht+tp://us%3Aer:p%40w@ho%3Ast:1234/"
    @"pa%3Fth?que%23ry=1&f%26oo=b%3dar#frag%23ment";

@implementation TestsAppDelegate (OFURITests)
- (void)URITests
{
	void *pool = objc_autoreleasePoolPush();
	OFURI *URI1, *URI2, *URI3, *URI4, *URI5, *URI6, *URI7, *URI8, *URI9;
	OFURI *URI10;
	OFMutableURI *mutableURI;

	TEST(@"+[URIWithString:]",
	    R(URI1 = [OFURI URIWithString: URIString]) &&
	    R(URI2 = [OFURI URIWithString: @"http://foo:80"]) &&
	    R(URI3 = [OFURI URIWithString: @"http://bar/"]) &&
	    R(URI4 = [OFURI URIWithString: @"file:///etc/passwd"]) &&
	    R(URI5 = [OFURI URIWithString: @"http://foo/bar/qux/foo%2fbar"]) &&
	    R(URI6 = [OFURI URIWithString: @"https://[12:34::56:abcd]/"]) &&
	    R(URI7 = [OFURI URIWithString: @"https://[12:34::56:abcd]:234/"]) &&
	    R(URI8 = [OFURI URIWithString: @"urn:qux:foo"]) &&
	    R(URI9 = [OFURI URIWithString: @"file:/foo?query#frag"]) &&
	    R(URI10 = [OFURI URIWithString: @"file:foo@bar/qux?query#frag"]))


	EXPECT_EXCEPTION(@"+[URIWithString:] fails with invalid characters #1",
	    OFInvalidFormatException,
	    [OFURI URIWithString: @"ht,tp://foo"])

	EXPECT_EXCEPTION(@"+[URIWithString:] fails with invalid characters #2",
	    OFInvalidFormatException,
	    [OFURI URIWithString: @"http://f`oo"])

	EXPECT_EXCEPTION(@"+[URIWithString:] fails with invalid characters #3",
	    OFInvalidFormatException,
	    [OFURI URIWithString: @"http://foo/`"])

	EXPECT_EXCEPTION(@"+[URIWithString:] fails with invalid characters #4",
	    OFInvalidFormatException,
	    [OFURI URIWithString: @"http://foo/foo?`"])

	EXPECT_EXCEPTION(@"+[URIWithString:] fails with invalid characters #5",
	    OFInvalidFormatException,
	    [OFURI URIWithString: @"http://foo/foo?foo#`"])

	EXPECT_EXCEPTION(@"+[URIWithString:] fails with invalid characters #6",
	    OFInvalidFormatException,
	    [OFURI URIWithString: @"https://[g]/"])

	EXPECT_EXCEPTION(@"+[URIWithString:] fails with invalid characters #7",
	    OFInvalidFormatException,
	    [OFURI URIWithString: @"https://[f]:/"])

	EXPECT_EXCEPTION(@"+[URIWithString:] fails with invalid characters #8",
	    OFInvalidFormatException,
	    [OFURI URIWithString: @"https://[f]:f/"])





	TEST(@"+[URIWithString:relativeToURI:]",
	    [[[OFURI URIWithString: @"/foo" relativeToURI: URI1] string]
	    isEqual: @"ht+tp://us%3Aer:p%40w@ho%3Ast:1234/foo"] &&
	    [[[OFURI URIWithString: @"foo/bar?q"
		     relativeToURI: [OFURI URIWithString: @"http://h/qux/quux"]]
	    string] isEqual: @"http://h/qux/foo/bar?q"] &&
	    [[[OFURI URIWithString: @"foo/bar"
		     relativeToURI: [OFURI URIWithString: @"http://h/qux/?x"]]
	    string] isEqual: @"http://h/qux/foo/bar"] &&
	    [[[OFURI URIWithString: @"http://foo/?q"
		     relativeToURI: URI1] string] isEqual: @"http://foo/?q"] &&
	    [[[OFURI URIWithString: @"foo"
		     relativeToURI: [OFURI URIWithString: @"http://foo/bar"]]
	    string] isEqual: @"http://foo/foo"] &&
	    [[[OFURI URIWithString: @"foo"
		     relativeToURI: [OFURI URIWithString: @"http://foo"]]
	    string] isEqual: @"http://foo/foo"])

	EXPECT_EXCEPTION(
	    @"+[URIWithString:relativeToURI:] fails with invalid characters #1",
	    OFInvalidFormatException,
	    [OFURI URIWithString: @"`" relativeToURI: URI1])

	EXPECT_EXCEPTION(
	    @"+[URIWithString:relativeToURI:] fails with invalid characters #2",
	    OFInvalidFormatException,
	    [OFURI URIWithString: @"/`" relativeToURI: URI1])

	EXPECT_EXCEPTION(
	    @"+[URIWithString:relativeToURI:] fails with invalid characters #3",
	    OFInvalidFormatException,
	    [OFURI URIWithString: @"?`" relativeToURI: URI1])

	EXPECT_EXCEPTION(
	    @"+[URIWithString:relativeToURI:] fails with invalid characters #4",
	    OFInvalidFormatException,
	    [OFURI URIWithString: @"#`" relativeToURI: URI1])

#ifdef OF_HAVE_FILES
	TEST(@"+[fileURIWithPath:]",
	    [[[OFURI fileURIWithPath: @"testfile.txt"] fileSystemRepresentation]
	    isEqual: [[OFFileManager defaultManager].currentDirectoryPath
	    stringByAppendingPathComponent: @"testfile.txt"]])

# if defined(OF_WINDOWS) || defined(OF_MSDOS)
	OFURI *tmp;
	TEST(@"+[fileURIWithPath:] for c:\\",
	    (tmp = [OFURI fileURIWithPath: @"c:\\"]) &&
	    [tmp.string isEqual: @"file:/c:/"] &&
	    [tmp.fileSystemRepresentation isEqual: @"c:\\"])
# endif

# ifdef OF_WINDOWS
	TEST(@"+[fileURIWithPath:] with UNC",
	    (tmp = [OFURI fileURIWithPath: @"\\\\foo\\bar"
			      isDirectory: false]) &&
	    [tmp.host isEqual: @"foo"] && [tmp.path isEqual: @"/bar"] &&
	    [tmp.string isEqual: @"file://foo/bar"] &&
	    [tmp.fileSystemRepresentation isEqual: @"\\\\foo\\bar"] &&
	    (tmp = [OFURI fileURIWithPath: @"\\\\test" isDirectory: true]) &&
	    [tmp.host isEqual: @"test"] && [tmp.path isEqual: @"/"] &&
	    [tmp.string isEqual: @"file://test/"] &&
	    [tmp.fileSystemRepresentation isEqual: @"\\\\test"])
# endif
#endif

	TEST(@"-[string]",
	    [URI1.string isEqual: URIString] &&
	    [URI2.string isEqual: @"http://foo:80"] &&
	    [URI3.string isEqual: @"http://bar/"] &&
	    [URI4.string isEqual: @"file:///etc/passwd"] &&
	    [URI5.string isEqual: @"http://foo/bar/qux/foo%2fbar"] &&
	    [URI6.string isEqual: @"https://[12:34::56:abcd]/"] &&
	    [URI7.string isEqual: @"https://[12:34::56:abcd]:234/"] &&
	    [URI8.string isEqual: @"urn:qux:foo"] &&
	    [URI9.string isEqual: @"file:/foo?query#frag"] &&
	    [URI10.string isEqual: @"file:foo@bar/qux?query#frag"])


	TEST(@"-[scheme]",
	    [URI1.scheme isEqual: @"ht+tp"] && [URI4.scheme isEqual: @"file"] &&
	    [URI9.scheme isEqual: @"file"] && [URI10.scheme isEqual: @"file"])


	TEST(@"-[user]", [URI1.user isEqual: @"us:er"] && URI4.user == nil &&
	    URI10.user == nil)
	TEST(@"-[password]",
	    [URI1.password isEqual: @"p@w"] && URI4.password == nil &&
	    URI10.password == nil)
	TEST(@"-[host]", [URI1.host isEqual: @"ho:st"] &&
	    [URI6.host isEqual: @"12:34::56:abcd"] &&
	    [URI7.host isEqual: @"12:34::56:abcd"] &&
	    URI8.host == nil && URI9.host == nil && URI10.host == nil)

	TEST(@"-[port]", URI1.port.unsignedShortValue == 1234 &&
	    [URI4 port] == nil && URI7.port.unsignedShortValue == 234 &&
	    URI8.port == nil && URI9.port == nil && URI10.port == nil)

	TEST(@"-[path]",
	    [URI1.path isEqual: @"/pa?th"] &&
	    [URI4.path isEqual: @"/etc/passwd"] &&
	    [URI8.path isEqual: @"qux:foo"] &&
	    [URI9.path isEqual: @"/foo"] &&
	    [URI10.path isEqual: @"foo@bar/qux"])

	TEST(@"-[pathComponents]",
	    [URI1.pathComponents isEqual:
	    [OFArray arrayWithObjects: @"/", @"pa?th", nil]] &&
	    [URI4.pathComponents isEqual:
	    [OFArray arrayWithObjects: @"/", @"etc", @"passwd", nil]] &&
	    [URI5.pathComponents isEqual:
	    [OFArray arrayWithObjects: @"/", @"bar", @"qux", @"foo/bar", nil]])
	TEST(@"-[lastPathComponent]",
	    [[[OFURI URIWithString: @"http://host/foo//bar/baz"]
	    lastPathComponent] isEqual: @"baz"] &&
	    [[[OFURI URIWithString: @"http://host/foo//bar/baz/"]
	    lastPathComponent] isEqual: @"baz"] &&
	    [[[OFURI URIWithString: @"http://host/foo/"]
	    lastPathComponent] isEqual: @"foo"] &&
	    [[[OFURI URIWithString: @"http://host/"]
	    lastPathComponent] isEqual: @"/"] &&
	    [URI5.lastPathComponent isEqual: @"foo/bar"])
	TEST(@"-[query]",
	    [URI1.query isEqual: @"que#ry=1&f&oo=b=ar"] && URI4.query == nil &&
	    [URI9.query isEqual: @"query"] && [URI10.query isEqual: @"query"])

	TEST(@"-[queryItems]",
	    [URI1.queryItems isEqual: [OFArray arrayWithObjects:
	    [OFPair pairWithFirstObject: @"que#ry" secondObject: @"1"],
	    [OFPair pairWithFirstObject: @"f&oo" secondObject: @"b=ar"], nil]]);
	TEST(@"-[fragment]",
	    [URI1.fragment isEqual: @"frag#ment"] && URI4.fragment == nil &&
	    [URI9.fragment isEqual: @"frag"] &&
	    [URI10.fragment isEqual: @"frag"])

	TEST(@"-[copy]", R(URI4 = [[URI1 copy] autorelease]))

	TEST(@"-[isEqual:]", [URI1 isEqual: URI4] && ![URI2 isEqual: URI3] &&
	    [[OFURI URIWithString: @"HTTP://bar/"] isEqual: URI3])

	TEST(@"-[hash:]", URI1.hash == URI4.hash && URI2.hash != URI3.hash)

	EXPECT_EXCEPTION(@"Detection of invalid format",
	    OFInvalidFormatException, [OFURI URIWithString: @"http"])





	mutableURI = [OFMutableURI URIWithScheme: @"dummy"];

	EXPECT_EXCEPTION(
	    @"-[setPercentEncodedScheme:] with invalid characters fails",
	    OFInvalidFormatException, mutableURI.scheme = @"%20")

	TEST(@"-[setHost:]",
	    (mutableURI.host = @"ho:st") &&
	    [mutableURI.percentEncodedHost isEqual: @"ho%3Ast"] &&
	    (mutableURI.host = @"12:34:ab") &&
	    [mutableURI.percentEncodedHost isEqual: @"[12:34:ab]"] &&
	    (mutableURI.host = @"12:34:aB") &&
	    [mutableURI.percentEncodedHost isEqual: @"[12:34:aB]"] &&
	    (mutableURI.host = @"12:34:g") &&
	    [mutableURI.percentEncodedHost isEqual: @"12%3A34%3Ag"])

	TEST(@"-[setPercentEncodedHost:]",
	    (mutableURI.percentEncodedHost = @"ho%3Ast") &&
	    [mutableURI.host isEqual: @"ho:st"] &&
	    (mutableURI.percentEncodedHost = @"[12:34]") &&
	    [mutableURI.host isEqual: @"12:34"] &&
	    (mutableURI.percentEncodedHost = @"[12::ab]") &&
	    [mutableURI.host isEqual: @"12::ab"])

	EXPECT_EXCEPTION(
	    @"-[setPercentEncodedHost:] with invalid characters fails #1",
	    OFInvalidFormatException,
	    mutableURI.percentEncodedHost = @"/")

	EXPECT_EXCEPTION(
	    @"-[setPercentEncodedHost:] with invalid characters fails #2",
	    OFInvalidFormatException,
	    mutableURI.percentEncodedHost = @"[12:34")

	EXPECT_EXCEPTION(
	    @"-[setPercentEncodedHost:] with invalid characters fails #3",
	    OFInvalidFormatException,
	    mutableURI.percentEncodedHost = @"[a::g]")

	TEST(@"-[setUser:]",
	    (mutableURI.user = @"us:er") &&
	    [mutableURI.percentEncodedUser isEqual: @"us%3Aer"])

	TEST(@"-[setPercentEncodedUser:]",
	    (mutableURI.percentEncodedUser = @"us%3Aer") &&
	    [mutableURI.user isEqual: @"us:er"])

	EXPECT_EXCEPTION(
	    @"-[setPercentEncodedUser:] with invalid characters fails",
	    OFInvalidFormatException,
	    mutableURI.percentEncodedHost = @"/")

	TEST(@"-[setPassword:]",
	    (mutableURI.password = @"pass:word") &&
	    [mutableURI.percentEncodedPassword isEqual: @"pass%3Aword"])

	TEST(@"-[setPercentEncodedPassword:]",
	    (mutableURI.percentEncodedPassword = @"pass%3Aword") &&
	    [mutableURI.password isEqual: @"pass:word"])

	EXPECT_EXCEPTION(
	    @"-[setPercentEncodedPassword:] with invalid characters fails",
	    OFInvalidFormatException,
	    mutableURI.percentEncodedPassword = @"/")

	TEST(@"-[setPath:]",
	    (mutableURI.path = @"pa/th@?") &&
	    [mutableURI.percentEncodedPath isEqual: @"pa/th@%3F"])

	TEST(@"-[setPercentEncodedPath:]",
	    (mutableURI.percentEncodedPath = @"pa/th@%3F") &&
	    [mutableURI.path isEqual: @"pa/th@?"])

	EXPECT_EXCEPTION(
	    @"-[setPercentEncodedPath:] with invalid characters fails",
	    OFInvalidFormatException,
	    mutableURI.percentEncodedPath = @"?")

	TEST(@"-[setQuery:]",
	    (mutableURI.query = @"que/ry?#") &&
	    [mutableURI.percentEncodedQuery isEqual: @"que/ry?%23"])

	TEST(@"-[setPercentEncodedQuery:]",
	    (mutableURI.percentEncodedQuery = @"que/ry?%23") &&
	    [mutableURI.query isEqual: @"que/ry?#"])

	EXPECT_EXCEPTION(
	    @"-[setPercentEncodedQuery:] with invalid characters fails",
	    OFInvalidFormatException,
	    mutableURI.percentEncodedQuery = @"`")

	TEST(@"-[setQueryItems:]",
	    (mutableURI.queryItems = [OFArray arrayWithObjects:
	    [OFPair pairWithFirstObject: @"foo&bar" secondObject: @"baz=qux"],
	    [OFPair pairWithFirstObject: @"f=oobar" secondObject: @"b&azqux"],
	    nil]) && [mutableURI.percentEncodedQuery isEqual:
	    @"foo%26bar=baz%3Dqux&f%3Doobar=b%26azqux"])

	TEST(@"-[setFragment:]",
	    (mutableURI.fragment = @"frag/ment?#") &&
	    [mutableURI.percentEncodedFragment isEqual: @"frag/ment?%23"])

	TEST(@"-[setPercentEncodedFragment:]",
	    (mutableURI.percentEncodedFragment = @"frag/ment?%23") &&
	    [mutableURI.fragment isEqual: @"frag/ment?#"])

	EXPECT_EXCEPTION(
	    @"-[setPercentEncodedFragment:] with invalid characters fails",
	    OFInvalidFormatException,
	    mutableURI.percentEncodedFragment = @"`")

	TEST(@"-[URIByAppendingPathComponent:isDirectory:]",
	    [[[OFURI URIWithString: @"file:///foo/bar"]
	    URIByAppendingPathComponent: @"qux" isDirectory: false] isEqual:
	    [OFURI URIWithString: @"file:///foo/bar/qux"]] &&
	    [[[OFURI URIWithString: @"file:///foo/bar/"]
	    URIByAppendingPathComponent: @"qux" isDirectory: false] isEqual:
	    [OFURI URIWithString: @"file:///foo/bar/qux"]] &&
	    [[[OFURI URIWithString: @"file:///foo/bar/"]
	    URIByAppendingPathComponent: @"qu?x" isDirectory: false] isEqual:
	    [OFURI URIWithString: @"file:///foo/bar/qu%3Fx"]] &&
	    [[[OFURI URIWithString: @"file:///foo/bar/"]
	    URIByAppendingPathComponent: @"qu?x" isDirectory: true] isEqual:
	    [OFURI URIWithString: @"file:///foo/bar/qu%3Fx/"]])

	TEST(@"-[URIByStandardizingPath]",
	    [[[OFURI URIWithString: @"http://foo/bar/.."]
	    URIByStandardizingPath] isEqual:
	    [OFURI URIWithString: @"http://foo/"]] &&
	    [[[OFURI URIWithString: @"http://foo/bar/%2E%2E/../qux/"]
	    URIByStandardizingPath] isEqual:
	    [OFURI URIWithString: @"http://foo/bar/qux/"]] &&
	    [[[OFURI URIWithString: @"http://foo/bar/./././qux/./"]
	    URIByStandardizingPath] isEqual:
	    [OFURI URIWithString: @"http://foo/bar/qux/"]] &&
	    [[[OFURI URIWithString: @"http://foo/bar/../../qux"]
	    URIByStandardizingPath] isEqual:
	    [OFURI URIWithString: @"http://foo/../qux"]])

	objc_autoreleasePoolPop(pool);
}
@end

|

















|
|


|
|


|
|
|

|
|
|
|
|
|
|
|
|
|
|
>

|

|

|

|

|

|

|

|

|

|

|

|

|

|

|

|

>
>
>
>
|
|

|
|

|
|

|
|
|
|

|
|



|

|


|

|


|

|


|

|


|
|




|
|
|





|
|




|







|
|
|
|
|
|
|
|
|
|
>


|
|
>

|
|

|
|
|
|
|
|
>
|
|
|
>

|
|
|
|
|
>

|

|

|


|

|

|

|

|

|
|
>

|



|
|
|

|

|
|

|


|

>
>
>
>
|



|


|
|
|
|
|
|
|
|


|
|
|
|
|
|




|




|




|


|
|


|
|




|


|
|


|
|




|


|
|


|
|




|


|
|


|
|




|


|


|



|
|


|
|




|

|
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
|
|
|




1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
/*
 * Copyright (c) 2008-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 "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

Modified tests/OFInvocationTests.m from [bb91b5d725] to [23f57f7d3a].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the 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 <assert.h>
#include <string.h>

#if defined(HAVE_COMPLEX_H) && !defined(__STDC_NO_COMPLEX__)
# include <complex.h>
#endif

#import "TestsAppDelegate.h"

|















<







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

18
19
20
21
22
23
24
/*
 * Copyright (c) 2008-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>

#if defined(HAVE_COMPLEX_H) && !defined(__STDC_NO_COMPLEX__)
# include <complex.h>
#endif

#import "TestsAppDelegate.h"
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
	memset(&st, '\xFF', sizeof(st));
	st.c = 0x55;
	st.i = 0xAAAAAAAA;

	TEST(@"+[invocationWithMethodSignature:]",
	    (invocation = [OFInvocation invocationWithMethodSignature: sig]))

#ifdef __clang_analyzer__
	assert(invocation != nil);
#endif

	TEST(@"-[setReturnValue]", R([invocation setReturnValue: &st]))

	TEST(@"-[getReturnValue]", R([invocation getReturnValue: &st2]) &&
	    memcmp(&st, &st2, sizeof(st)) == 0)

	memset(&st2, '\0', sizeof(st2));








<
<
<
<







54
55
56
57
58
59
60




61
62
63
64
65
66
67
	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));

Modified tests/OFJSONTests.m from [330199594e] to [92f1f602a7].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified tests/OFKernelEventObserverTests.m from [cec268df6c] to [fd27260531].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65

66
67
68
69
70
71
72

@implementation ObserverTest
- (instancetype)initWithTestsAppDelegate: (TestsAppDelegate *)testsAppDelegate
{
	self = [super init];

	@try {
		uint16_t port;

		_testsAppDelegate = testsAppDelegate;

		_server = [[OFTCPSocket alloc] init];
		port = [_server bindToHost: @"127.0.0.1" port: 0];
		[_server listen];

		_client = [[OFTCPSocket alloc] init];
		[_client connectToHost: @"127.0.0.1" port: port];

		[_client writeBuffer: "0" length: 1];
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;







|




|



|
>







49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73

@implementation ObserverTest
- (instancetype)initWithTestsAppDelegate: (TestsAppDelegate *)testsAppDelegate
{
	self = [super init];

	@try {
		OFSocketAddress address;

		_testsAppDelegate = testsAppDelegate;

		_server = [[OFTCPSocket alloc] init];
		address = [_server bindToHost: @"127.0.0.1" port: 0];
		[_server listen];

		_client = [[OFTCPSocket alloc] init];
		[_client connectToHost: @"127.0.0.1"
				  port: OFSocketAddressIPPort(&address)];
		[_client writeBuffer: "0" length: 1];
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;

Modified tests/OFListTests.m from [43f56ef79d] to [39ffbcd436].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified tests/OFLocaleTests.m from [a51f4edb4e] to [bb15c236d6].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified tests/OFMD5HashTests.m from [5005b07061] to [96fc59cb59].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
    "\x00\x8B\x9D\x1B\x58\xDF\xF8\xFE\xEE\xF3\xAE\x8D\xBB\x68\x2D\x38";

@implementation TestsAppDelegate (OFMD5HashTests)
- (void)MD5HashTests
{
	void *pool = objc_autoreleasePoolPush();
	OFMD5Hash *MD5, *MD5Copy;
	OFURI *URI = [OFURI URIWithString: @"embedded:testfile.bin"];
	OFStream *file = [OFURIHandler openItemAtURI: URI mode: @"r"];

	TEST(@"+[hashWithAllowsSwappableMemory:]",
	    (MD5 = [OFMD5Hash hashWithAllowsSwappableMemory: true]))

	while (!file.atEndOfStream) {
		char buffer[64];
		size_t length = [file readIntoBuffer: buffer length: 64];







|
|







25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
    "\x00\x8B\x9D\x1B\x58\xDF\xF8\xFE\xEE\xF3\xAE\x8D\xBB\x68\x2D\x38";

@implementation TestsAppDelegate (OFMD5HashTests)
- (void)MD5HashTests
{
	void *pool = objc_autoreleasePoolPush();
	OFMD5Hash *MD5, *MD5Copy;
	OFIRI *IRI = [OFIRI IRIWithString: @"embedded:testfile.bin"];
	OFStream *file = [OFIRIHandler openItemAtIRI: IRI mode: @"r"];

	TEST(@"+[hashWithAllowsSwappableMemory:]",
	    (MD5 = [OFMD5Hash hashWithAllowsSwappableMemory: true]))

	while (!file.atEndOfStream) {
		char buffer[64];
		size_t length = [file readIntoBuffer: buffer length: 64];

Added tests/OFMatrix4x4Tests.m version [29d0338fbf].





















































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
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
/*
 * 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 "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

Modified tests/OFMemoryStreamTests.m from [14fae61fb2] to [8479ce3790].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified tests/OFMethodSignatureTests.m from [8b3d41a60c] to [f874f8bb5c].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified tests/OFNotificationCenterTests.m from [4d3ddfb6ba] to [088812ee19].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
	TEST(@"-[postNotification:] #3",
	    R([center postNotification: notification]) &&
	    test1->_received == 1 && test2->_received == 3 &&
	    test3->_received == 0 && test4->_received == 0)

#ifdef OF_HAVE_BLOCKS
	__block bool received = false;
	OFNotificationCenterHandle *handle;

	notification = [OFNotification notificationWithName: notificationName
						     object: self];
	TEST(@"-[addObserverForName:object:usingBlock:]",
	    (handle = [center addObserverForName: notificationName
					  object: self
				      usingBlock: ^ (OFNotification *notif) {







|







105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
	TEST(@"-[postNotification:] #3",
	    R([center postNotification: notification]) &&
	    test1->_received == 1 && test2->_received == 3 &&
	    test3->_received == 0 && test4->_received == 0)

#ifdef OF_HAVE_BLOCKS
	__block bool received = false;
	id handle;

	notification = [OFNotification notificationWithName: notificationName
						     object: self];
	TEST(@"-[addObserverForName:object:usingBlock:]",
	    (handle = [center addObserverForName: notificationName
					  object: self
				      usingBlock: ^ (OFNotification *notif) {

Modified tests/OFNumberTests.m from [c4180587af] to [8e6e4b486d].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified tests/OFObjectTests.m from [fcfeee4a72] to [39c729edc8].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified tests/OFPBKDF2Tests.m from [9316c48e09] to [2febb34313].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified tests/OFPluginTests.m from [bb55705657] to [278848818e].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified tests/OFPropertyListTests.m from [6b258c8840] to [f48a04b761].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified tests/OFRIPEMD160HashTests.m from [c46510efe0] to [4768731328].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
	"\xE6\x08\x8B";

@implementation TestsAppDelegate (OFRIPEMD160HashTests)
- (void)RIPEMD160HashTests
{
	void *pool = objc_autoreleasePoolPush();
	OFRIPEMD160Hash *RIPEMD160, *RIPEMD160Copy;
	OFURI *URI = [OFURI URIWithString: @"embedded:testfile.bin"];
	OFStream *file = [OFURIHandler openItemAtURI: URI mode: @"r"];

	TEST(@"+[hashWithAllowsSwappableMemory:]",
	    (RIPEMD160 = [OFRIPEMD160Hash hashWithAllowsSwappableMemory: true]))

	while (!file.atEndOfStream) {
		char buffer[64];
		size_t length = [file readIntoBuffer: buffer length: 64];







|
|







26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
	"\xE6\x08\x8B";

@implementation TestsAppDelegate (OFRIPEMD160HashTests)
- (void)RIPEMD160HashTests
{
	void *pool = objc_autoreleasePoolPush();
	OFRIPEMD160Hash *RIPEMD160, *RIPEMD160Copy;
	OFIRI *IRI = [OFIRI IRIWithString: @"embedded:testfile.bin"];
	OFStream *file = [OFIRIHandler openItemAtIRI: IRI mode: @"r"];

	TEST(@"+[hashWithAllowsSwappableMemory:]",
	    (RIPEMD160 = [OFRIPEMD160Hash hashWithAllowsSwappableMemory: true]))

	while (!file.atEndOfStream) {
		char buffer[64];
		size_t length = [file readIntoBuffer: buffer length: 64];

Modified tests/OFSHA1HashTests.m from [76d8541713] to [7856801f0e].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
	"\x94\xE7\x17";

@implementation TestsAppDelegate (SHA1HashTests)
- (void)SHA1HashTests
{
	void *pool = objc_autoreleasePoolPush();
	OFSHA1Hash *SHA1, *SHA1Copy;
	OFURI *URI = [OFURI URIWithString: @"embedded:testfile.bin"];
	OFStream *file = [OFURIHandler openItemAtURI: URI mode: @"r"];

	TEST(@"+[hashWithAllowsSwappableMemory:]",
	    (SHA1 = [OFSHA1Hash hashWithAllowsSwappableMemory: true]))

	while (!file.atEndOfStream) {
		char buffer[64];
		size_t length = [file readIntoBuffer: buffer length: 64];







|
|







26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
	"\x94\xE7\x17";

@implementation TestsAppDelegate (SHA1HashTests)
- (void)SHA1HashTests
{
	void *pool = objc_autoreleasePoolPush();
	OFSHA1Hash *SHA1, *SHA1Copy;
	OFIRI *IRI = [OFIRI IRIWithString: @"embedded:testfile.bin"];
	OFStream *file = [OFIRIHandler openItemAtIRI: IRI mode: @"r"];

	TEST(@"+[hashWithAllowsSwappableMemory:]",
	    (SHA1 = [OFSHA1Hash hashWithAllowsSwappableMemory: true]))

	while (!file.atEndOfStream) {
		char buffer[64];
		size_t length = [file readIntoBuffer: buffer length: 64];

Modified tests/OFSHA224HashTests.m from [a723282b7a] to [74da8c08a3].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
	"\x5F\x4F\x20\x02\x4D\x15\xED\x1C\x61\x1F\xF7";

@implementation TestsAppDelegate (SHA224HashTests)
- (void)SHA224HashTests
{
	void *pool = objc_autoreleasePoolPush();
	OFSHA224Hash *SHA224, *SHA224Copy;
	OFURI *URI = [OFURI URIWithString: @"embedded:testfile.bin"];
	OFStream *file = [OFURIHandler openItemAtURI: URI mode: @"r"];

	TEST(@"+[hashWithAllowsSwappableMemory:]",
	    (SHA224 = [OFSHA224Hash hashWithAllowsSwappableMemory: true]))

	while (!file.atEndOfStream) {
		char buffer[64];
		size_t length = [file readIntoBuffer: buffer length: 64];







|
|







26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
	"\x5F\x4F\x20\x02\x4D\x15\xED\x1C\x61\x1F\xF7";

@implementation TestsAppDelegate (SHA224HashTests)
- (void)SHA224HashTests
{
	void *pool = objc_autoreleasePoolPush();
	OFSHA224Hash *SHA224, *SHA224Copy;
	OFIRI *IRI = [OFIRI IRIWithString: @"embedded:testfile.bin"];
	OFStream *file = [OFIRIHandler openItemAtIRI: IRI mode: @"r"];

	TEST(@"+[hashWithAllowsSwappableMemory:]",
	    (SHA224 = [OFSHA224Hash hashWithAllowsSwappableMemory: true]))

	while (!file.atEndOfStream) {
		char buffer[64];
		size_t length = [file readIntoBuffer: buffer length: 64];

Modified tests/OFSHA256HashTests.m from [ea4a5936cb] to [1004803a7d].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
	"\x67\x93\x8F\x0F\x44\x90\xB8\xF5\x35\x89\xF0\x5A\x23\x7F\x69";

@implementation TestsAppDelegate (SHA256HashTests)
- (void)SHA256HashTests
{
	void *pool = objc_autoreleasePoolPush();
	OFSHA256Hash *SHA256, *SHA256Copy;
	OFURI *URI = [OFURI URIWithString: @"embedded:testfile.bin"];
	OFStream *file = [OFURIHandler openItemAtURI: URI mode: @"r"];

	TEST(@"+[hashWithAllowsSwappableMemory:]",
	    (SHA256 = [OFSHA256Hash hashWithAllowsSwappableMemory: true]))

	while (!file.atEndOfStream) {
		char buffer[64];
		size_t length = [file readIntoBuffer: buffer length: 64];







|
|







26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
	"\x67\x93\x8F\x0F\x44\x90\xB8\xF5\x35\x89\xF0\x5A\x23\x7F\x69";

@implementation TestsAppDelegate (SHA256HashTests)
- (void)SHA256HashTests
{
	void *pool = objc_autoreleasePoolPush();
	OFSHA256Hash *SHA256, *SHA256Copy;
	OFIRI *IRI = [OFIRI IRIWithString: @"embedded:testfile.bin"];
	OFStream *file = [OFIRIHandler openItemAtIRI: IRI mode: @"r"];

	TEST(@"+[hashWithAllowsSwappableMemory:]",
	    (SHA256 = [OFSHA256Hash hashWithAllowsSwappableMemory: true]))

	while (!file.atEndOfStream) {
		char buffer[64];
		size_t length = [file readIntoBuffer: buffer length: 64];

Modified tests/OFSHA384HashTests.m from [4335e4cd7c] to [7039b1bf58].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
	"\xE9\x1A\xB3\x51\x70\x8C\x1F\x3F\x56\x12\x44\x01\x91\x54";

@implementation TestsAppDelegate (SHA384HashTests)
- (void)SHA384HashTests
{
	void *pool = objc_autoreleasePoolPush();
	OFSHA384Hash *SHA384, *SHA384Copy;
	OFURI *URI = [OFURI URIWithString: @"embedded:testfile.bin"];
	OFStream *file = [OFURIHandler openItemAtURI: URI mode: @"r"];

	TEST(@"+[hashWithAllowsSwappableMemory:]",
	    (SHA384 = [OFSHA384Hash hashWithAllowsSwappableMemory: true]))

	while (!file.atEndOfStream) {
		char buffer[128];
		size_t length = [file readIntoBuffer: buffer length: 128];







|
|







27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
	"\xE9\x1A\xB3\x51\x70\x8C\x1F\x3F\x56\x12\x44\x01\x91\x54";

@implementation TestsAppDelegate (SHA384HashTests)
- (void)SHA384HashTests
{
	void *pool = objc_autoreleasePoolPush();
	OFSHA384Hash *SHA384, *SHA384Copy;
	OFIRI *IRI = [OFIRI IRIWithString: @"embedded:testfile.bin"];
	OFStream *file = [OFIRIHandler openItemAtIRI: IRI mode: @"r"];

	TEST(@"+[hashWithAllowsSwappableMemory:]",
	    (SHA384 = [OFSHA384Hash hashWithAllowsSwappableMemory: true]))

	while (!file.atEndOfStream) {
		char buffer[128];
		size_t length = [file readIntoBuffer: buffer length: 128];

Modified tests/OFSHA512HashTests.m from [9748b0700b] to [11c494533c].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
	"\xA1\x8A\x41\x64\x33\x69\x21\x8C\x2A\x44\x6D\xF2\xA0";

@implementation TestsAppDelegate (SHA512HashTests)
- (void)SHA512HashTests
{
	void *pool = objc_autoreleasePoolPush();
	OFSHA512Hash *SHA512, *SHA512Copy;
	OFURI *URI = [OFURI URIWithString: @"embedded:testfile.bin"];
	OFStream *file = [OFURIHandler openItemAtURI: URI mode: @"r"];

	TEST(@"+[hashWithAllowsSwappableMemory:]",
	    (SHA512 = [OFSHA512Hash hashWithAllowsSwappableMemory: true]))

	while (!file.atEndOfStream) {
		char buffer[128];
		size_t length = [file readIntoBuffer: buffer length: 128];







|
|







28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
	"\xA1\x8A\x41\x64\x33\x69\x21\x8C\x2A\x44\x6D\xF2\xA0";

@implementation TestsAppDelegate (SHA512HashTests)
- (void)SHA512HashTests
{
	void *pool = objc_autoreleasePoolPush();
	OFSHA512Hash *SHA512, *SHA512Copy;
	OFIRI *IRI = [OFIRI IRIWithString: @"embedded:testfile.bin"];
	OFStream *file = [OFIRIHandler openItemAtIRI: IRI mode: @"r"];

	TEST(@"+[hashWithAllowsSwappableMemory:]",
	    (SHA512 = [OFSHA512Hash hashWithAllowsSwappableMemory: true]))

	while (!file.atEndOfStream) {
		char buffer[128];
		size_t length = [file readIntoBuffer: buffer length: 128];

Modified tests/OFSPXSocketTests.m from [951eb7a23c] to [262f8617dc].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
75
76
77
78
79
80
81

82
83
84
85
86
87
88
	void *pool = objc_autoreleasePoolPush();
	OFSPXSocket *sockClient, *sockServer = nil, *sockAccepted;
	OFSocketAddress address1;
	const OFSocketAddress *address2;
	uint32_t network;
	unsigned char node[IPX_NODE_LEN], node2[IPX_NODE_LEN];
	uint16_t port;

	char buffer[5];
	SPXSocketDelegate *delegate;

	TEST(@"+[socket]", (sockClient = [OFSPXSocket socket]) &&
	    (sockServer = [OFSPXSocket socket]))

	@try {







>







75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
	void *pool = objc_autoreleasePoolPush();
	OFSPXSocket *sockClient, *sockServer = nil, *sockAccepted;
	OFSocketAddress address1;
	const OFSocketAddress *address2;
	uint32_t network;
	unsigned char node[IPX_NODE_LEN], node2[IPX_NODE_LEN];
	uint16_t port;
	OFDictionary *networkInterfaces;
	char buffer[5];
	SPXSocketDelegate *delegate;

	TEST(@"+[socket]", (sockClient = [OFSPXSocket socket]) &&
	    (sockServer = [OFSPXSocket socket]))

	@try {
119
120
121
122
123
124
125


















126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
	}

	network = OFSocketAddressIPXNetwork(&address1);
	OFSocketAddressGetIPXNode(&address1, node);
	port = OFSocketAddressIPXPort(&address1);

	TEST(@"-[listen]", R([sockServer listen]))



















	TEST(@"-[connectToNetwork:node:port:]",
	    R([sockClient connectToNetwork: network node: node port: port]))

	TEST(@"-[accept]", (sockAccepted = [sockServer accept]))

	TEST(@"-[sendBuffer:length:]",
	    R([sockAccepted sendBuffer: "Hello" length: 5]))

	TEST(@"-[receiveIntoBuffer:length:]",
	    [sockClient receiveIntoBuffer: buffer length: 5] == 5 &&
	    memcmp(buffer, "Hello", 5) == 0)

	TEST(@"-[remoteAddress]",
	    (address2 = sockAccepted.remoteAddress) &&
	    OFSocketAddressIPXNetwork(address2) == network &&
	    R(OFSocketAddressGetIPXNode(address2, node2)) &&
	    memcmp(node, node2, IPX_NODE_LEN) == 0)

	delegate = [[[SPXSocketDelegate alloc] init] autorelease];

	sockServer = [OFSPXSocket socket];
	delegate->_expectedServerSocket = sockServer;







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>















<







120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159

160
161
162
163
164
165
166
	}

	network = OFSocketAddressIPXNetwork(&address1);
	OFSocketAddressGetIPXNode(&address1, node);
	port = OFSocketAddressIPXPort(&address1);

	TEST(@"-[listen]", R([sockServer listen]))

	/*
	 * Find any network interface with IPX and send to it. Any should be
	 * fine since we bound to 0.0.
	 */
	networkInterfaces = [OFSystemInfo networkInterfaces];
	for (OFString *name in networkInterfaces) {
		OFNetworkInterface interface = [networkInterfaces
		    objectForKey: name];
		OFData *addresses = [interface
		    objectForKey: OFNetworkInterfaceIPXAddresses];

		if (addresses.count == 0)
			continue;

		network = OFSocketAddressIPXNetwork([addresses itemAtIndex: 0]);
		OFSocketAddressGetIPXNode([addresses itemAtIndex: 0], node);
	}

	TEST(@"-[connectToNetwork:node:port:]",
	    R([sockClient connectToNetwork: network node: node port: port]))

	TEST(@"-[accept]", (sockAccepted = [sockServer accept]))

	TEST(@"-[sendBuffer:length:]",
	    R([sockAccepted sendBuffer: "Hello" length: 5]))

	TEST(@"-[receiveIntoBuffer:length:]",
	    [sockClient receiveIntoBuffer: buffer length: 5] == 5 &&
	    memcmp(buffer, "Hello", 5) == 0)

	TEST(@"-[remoteAddress]",
	    (address2 = sockAccepted.remoteAddress) &&

	    R(OFSocketAddressGetIPXNode(address2, node2)) &&
	    memcmp(node, node2, IPX_NODE_LEN) == 0)

	delegate = [[[SPXSocketDelegate alloc] init] autorelease];

	sockServer = [OFSPXSocket socket];
	delegate->_expectedServerSocket = sockServer;
169
170
171
172
173
174
175







176
177
178
179
180
181
182

		[[OFRunLoop mainRunLoop] runUntilDate:
		    [OFDate dateWithTimeIntervalSinceNow: 2]];

		TEST(@"-[asyncAccept] & -[asyncConnectToNetwork:node:port:]",
		    delegate->_accepted && delegate->_connected)
	} @catch (OFObserveKernelEventsFailedException *e) {







		switch (e.errNo) {
		case ENOTSOCK:
			[OFStdOut setForegroundColor: [OFColor lime]];
			[OFStdOut writeLine:
			    @"\r[OFSPXSocket] -[asyncAccept] & "
			    @"-[asyncConnectToNetwork:node:port:]: select() "
			    @"not supported for SPX, skipping test"];







>
>
>
>
>
>
>







187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207

		[[OFRunLoop mainRunLoop] runUntilDate:
		    [OFDate dateWithTimeIntervalSinceNow: 2]];

		TEST(@"-[asyncAccept] & -[asyncConnectToNetwork:node:port:]",
		    delegate->_accepted && delegate->_connected)
	} @catch (OFObserveKernelEventsFailedException *e) {
		/*
		 * Make sure it doesn't stay in the run loop and throws again
		 * next time we run the run loop.
		 */
		[sockClient cancelAsyncRequests];
		[sockServer cancelAsyncRequests];

		switch (e.errNo) {
		case ENOTSOCK:
			[OFStdOut setForegroundColor: [OFColor lime]];
			[OFStdOut writeLine:
			    @"\r[OFSPXSocket] -[asyncAccept] & "
			    @"-[asyncConnectToNetwork:node:port:]: select() "
			    @"not supported for SPX, skipping test"];

Modified tests/OFSPXStreamSocketTests.m from [ca6bf9ee77] to [37e7d0cfd1].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
75
76
77
78
79
80
81

82
83
84
85
86
87
88
	void *pool = objc_autoreleasePoolPush();
	OFSPXStreamSocket *sockClient, *sockServer = nil, *sockAccepted;
	OFSocketAddress address1;
	const OFSocketAddress *address2;
	uint32_t network;
	unsigned char node[IPX_NODE_LEN], node2[IPX_NODE_LEN];
	uint16_t port;

	char buffer[5];
	SPXStreamSocketDelegate *delegate;

	TEST(@"+[socket]", (sockClient = [OFSPXStreamSocket socket]) &&
	    (sockServer = [OFSPXStreamSocket socket]))

	@try {







>







75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
	void *pool = objc_autoreleasePoolPush();
	OFSPXStreamSocket *sockClient, *sockServer = nil, *sockAccepted;
	OFSocketAddress address1;
	const OFSocketAddress *address2;
	uint32_t network;
	unsigned char node[IPX_NODE_LEN], node2[IPX_NODE_LEN];
	uint16_t port;
	OFDictionary *networkInterfaces;
	char buffer[5];
	SPXStreamSocketDelegate *delegate;

	TEST(@"+[socket]", (sockClient = [OFSPXStreamSocket socket]) &&
	    (sockServer = [OFSPXStreamSocket socket]))

	@try {
120
121
122
123
124
125
126


















127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
	}

	network = OFSocketAddressIPXNetwork(&address1);
	OFSocketAddressGetIPXNode(&address1, node);
	port = OFSocketAddressIPXPort(&address1);

	TEST(@"-[listen]", R([sockServer listen]))



















	TEST(@"-[connectToNetwork:node:port:]",
	    R([sockClient connectToNetwork: network node: node port: port]))

	TEST(@"-[accept]", (sockAccepted = [sockServer accept]))

	/* Test reassembly (this would not work with OFSPXSocket) */
	TEST(@"-[writeBuffer:length:]",
	    R([sockAccepted writeBuffer: "Hello" length: 5]))

	TEST(@"-[readIntoBuffer:length:]",
	    [sockClient readIntoBuffer: buffer length: 2] == 2 &&
	    memcmp(buffer, "He", 2) == 0 &&
	    [sockClient readIntoBuffer: buffer length: 3] == 3 &&
	    memcmp(buffer, "llo", 3) == 0)

	TEST(@"-[remoteAddress]",
	    (address2 = sockAccepted.remoteAddress) &&
	    OFSocketAddressIPXNetwork(address2) == network &&
	    R(OFSocketAddressGetIPXNode(address2, node2)) &&
	    memcmp(node, node2, IPX_NODE_LEN) == 0)

	delegate = [[[SPXStreamSocketDelegate alloc] init] autorelease];

	sockServer = [OFSPXStreamSocket socket];
	delegate->_expectedServerSocket = sockServer;







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>


















<







121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163

164
165
166
167
168
169
170
	}

	network = OFSocketAddressIPXNetwork(&address1);
	OFSocketAddressGetIPXNode(&address1, node);
	port = OFSocketAddressIPXPort(&address1);

	TEST(@"-[listen]", R([sockServer listen]))

	/*
	 * Find any network interface with IPX and send to it. Any should be
	 * fine since we bound to 0.0.
	 */
	networkInterfaces = [OFSystemInfo networkInterfaces];
	for (OFString *name in networkInterfaces) {
		OFNetworkInterface interface = [networkInterfaces
		    objectForKey: name];
		OFData *addresses = [interface
		    objectForKey: OFNetworkInterfaceIPXAddresses];

		if (addresses.count == 0)
			continue;

		network = OFSocketAddressIPXNetwork([addresses itemAtIndex: 0]);
		OFSocketAddressGetIPXNode([addresses itemAtIndex: 0], node);
	}

	TEST(@"-[connectToNetwork:node:port:]",
	    R([sockClient connectToNetwork: network node: node port: port]))

	TEST(@"-[accept]", (sockAccepted = [sockServer accept]))

	/* Test reassembly (this would not work with OFSPXSocket) */
	TEST(@"-[writeBuffer:length:]",
	    R([sockAccepted writeBuffer: "Hello" length: 5]))

	TEST(@"-[readIntoBuffer:length:]",
	    [sockClient readIntoBuffer: buffer length: 2] == 2 &&
	    memcmp(buffer, "He", 2) == 0 &&
	    [sockClient readIntoBuffer: buffer length: 3] == 3 &&
	    memcmp(buffer, "llo", 3) == 0)

	TEST(@"-[remoteAddress]",
	    (address2 = sockAccepted.remoteAddress) &&

	    R(OFSocketAddressGetIPXNode(address2, node2)) &&
	    memcmp(node, node2, IPX_NODE_LEN) == 0)

	delegate = [[[SPXStreamSocketDelegate alloc] init] autorelease];

	sockServer = [OFSPXStreamSocket socket];
	delegate->_expectedServerSocket = sockServer;
173
174
175
176
177
178
179







180
181
182
183
184
185
186

		[[OFRunLoop mainRunLoop] runUntilDate:
		    [OFDate dateWithTimeIntervalSinceNow: 2]];

		TEST(@"-[asyncAccept] & -[asyncConnectToNetwork:node:port:]",
		    delegate->_accepted && delegate->_connected)
	} @catch (OFObserveKernelEventsFailedException *e) {







		switch (e.errNo) {
		case ENOTSOCK:
			[OFStdOut setForegroundColor: [OFColor lime]];
			[OFStdOut writeLine:
			    @"\r[OFSPXStreamSocket] -[asyncAccept] & "
			    @"-[asyncConnectToNetwork:node:port:]: select() "
			    @"not supported for SPX, skipping test"];







>
>
>
>
>
>
>







191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211

		[[OFRunLoop mainRunLoop] runUntilDate:
		    [OFDate dateWithTimeIntervalSinceNow: 2]];

		TEST(@"-[asyncAccept] & -[asyncConnectToNetwork:node:port:]",
		    delegate->_accepted && delegate->_connected)
	} @catch (OFObserveKernelEventsFailedException *e) {
		/*
		 * Make sure it doesn't stay in the run loop and throws again
		 * next time we run the run loop.
		 */
		[sockClient cancelAsyncRequests];
		[sockServer cancelAsyncRequests];

		switch (e.errNo) {
		case ENOTSOCK:
			[OFStdOut setForegroundColor: [OFColor lime]];
			[OFStdOut writeLine:
			    @"\r[OFSPXStreamSocket] -[asyncAccept] & "
			    @"-[asyncConnectToNetwork:node:port:]: select() "
			    @"not supported for SPX, skipping test"];

Modified tests/OFScryptTests.m from [b11c7bebe9] to [3717bd0eab].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Deleted tests/OFSerializationTests.m version [d36329ce8f].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#import "TestsAppDelegate.h"

static OFString *const module = @"OFSerialization";

@implementation TestsAppDelegate (OFSerializationTests)
- (void)serializationTests
{
	void *pool = objc_autoreleasePoolPush();
	OFMutableDictionary *dict = [OFMutableDictionary dictionary];
	OFMutableArray *array = [OFMutableArray array];
	OFList *list = [OFList list];
	OFData *data;
	OFString *string;
	OFUUID *UUID;

	[array addObject: @"Qu\"xbar\ntest"];
	[array addObject: [OFNumber numberWithInt: 1234]];
	[array addObject: [OFNumber numberWithDouble: 1234.5678]];
	[array addObject: [OFMutableString stringWithString: @"asd"]];
	[array addObject: [OFDate dateWithTimeIntervalSince1970: 1234.5678]];

	[dict setObject: @"Hello" forKey: array];
	[dict setObject: @"B\"la" forKey: @"Blub"];

	[list appendObject: @"Hello"];
	[list appendObject: @"Wo\rld!\nHow are you?"];
	[list appendObject: [OFURI URIWithString: @"https://objfw.nil.im/"]];
	[list appendObject:
	    [OFXMLElement elementWithXMLString: @"<x><y/><![CDATA[<]]></x>"]];
	[list appendObject:
	    [OFSet setWithObjects: @"foo", @"foo", @"bar", nil]];
	[list appendObject:
	    [OFCountedSet setWithObjects: @"foo", @"foo", @"bar", nil]];

	[dict setObject: @"list" forKey: list];

	data = [OFData dataWithItems: "0123456789:;<ABCDEFGHJIKLMNOPQRSTUVWXYZ"
			       count: 39];
	[dict setObject: @"data" forKey: data];

	UUID = [OFUUID
	    UUIDWithUUIDString: @"01234567-89AB-CDEF-FEDC-BA9876543210"];
	[dict setObject: @"uuid" forKey: UUID];

	TEST(@"-[stringBySerializing]",
	    (string = dict.stringBySerializing) && [string isEqual:
	    [OFString stringWithContentsOfURI:
	    [OFURI URIWithString: @"embedded:serialization.xml"]]])

	TEST(@"-[objectByDeserializing]",
	    [string.objectByDeserializing isEqual: dict])

	objc_autoreleasePoolPop(pool);
}
@end
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
















































































































































Modified tests/OFSetTests.m from [d6c98b6473] to [4668cbb71a].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#import "TestsAppDelegate.h"

#import "OFSet.h"
#import "OFMapTableSet.h"
#import "OFMutableMapTableSet.h"

static OFString *module;

@interface SimpleSet: OFSet
{
	OFMutableSet *_set;
}

|


















|
|







1
2
3
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.
 */

#include "config.h"

#import "TestsAppDelegate.h"

#import "OFSet.h"
#import "OFConcreteSet.h"
#import "OFConcreteMutableSet.h"

static OFString *module;

@interface SimpleSet: OFSet
{
	OFMutableSet *_set;
}
284
285
286
287
288
289
290
291
292
293
294
295

- (void)setTests
{
	module = @"OFSet";
	[self setTestsWithClass: [SimpleSet class]
		   mutableClass: [SimpleMutableSet class]];

	module = @"OFMapTableSet";
	[self setTestsWithClass: [OFMapTableSet class]
		   mutableClass: [OFMutableMapTableSet class]];
}
@end







|
|
|


284
285
286
287
288
289
290
291
292
293
294
295

- (void)setTests
{
	module = @"OFSet";
	[self setTestsWithClass: [SimpleSet class]
		   mutableClass: [SimpleMutableSet class]];

	module = @"OFConcreteSet";
	[self setTestsWithClass: [OFConcreteSet class]
		   mutableClass: [OFConcreteMutableSet class]];
}
@end

Modified tests/OFSocketTests.m from [0766971ff5] to [2289bf230f].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
111
112
113
114
115
116
117
















118
119
120
121
122
123
124
	    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)

















	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,







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
	    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,
142
143
144
145
146
147
148


149
150
151
152
153
154
155
	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)



	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",







>
>







158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
	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",

Modified tests/OFStreamTests.m from [12c9753c4d] to [b1e1e0bf5b].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified tests/OFStringTests.m from [10adf25aaa] to [dc9aaa2341].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368

#ifdef OF_HAVE_FILES
	TEST(@"+[stringWithContentsOfFile:encoding]", (string = [stringClass
	    stringWithContentsOfFile: @"testfile.txt"
			    encoding: OFStringEncodingISO8859_1]) &&
	    [string isEqual: @"testäöü"])

	TEST(@"+[stringWithContentsOfURI:encoding]", (string = [stringClass
	    stringWithContentsOfURI: [OFURI fileURIWithPath: @"testfile.txt"]
			   encoding: OFStringEncodingISO8859_1]) &&
	    [string isEqual: @"testäöü"])
#endif

	TEST(@"-[appendUTFString:length:]",
	    R([mutableString1 appendUTF8String: "\xEF\xBB\xBF" "barqux"
					length: 6]) &&







|
|







353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368

#ifdef OF_HAVE_FILES
	TEST(@"+[stringWithContentsOfFile:encoding]", (string = [stringClass
	    stringWithContentsOfFile: @"testfile.txt"
			    encoding: OFStringEncodingISO8859_1]) &&
	    [string isEqual: @"testäöü"])

	TEST(@"+[stringWithContentsOfIRI:encoding]", (string = [stringClass
	    stringWithContentsOfIRI: [OFIRI fileIRIWithPath: @"testfile.txt"]
			   encoding: OFStringEncodingISO8859_1]) &&
	    [string isEqual: @"testäöü"])
#endif

	TEST(@"-[appendUTFString:length:]",
	    R([mutableString1 appendUTF8String: "\xEF\xBB\xBF" "barqux"
					length: 6]) &&
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
#else
/* Android, Solaris, HP-UX, DJGPP and AmigaOS 3 do not accept 0x for strtod() */
# if (!defined(OF_SOLARIS) || !defined(OF_X86)) && !defined(OF_AMIGAOS_M68K)
#  define INPUT @"\t-0.123456789 "
#  define EXPECTED -0.123456789
# else
/*
 * Solaris' strtod() has weird rounding on x86, but not on x86_64.
 * AmigaOS 3 with libnix has weird rounding as well.
 */
#  define INPUT @"\t-0.125 "
#  define EXPECTED -0.125
# endif
#endif
	TEST(@"-[doubleValue]",







|







1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
#else
/* Android, Solaris, HP-UX, DJGPP and AmigaOS 3 do not accept 0x for strtod() */
# if (!defined(OF_SOLARIS) || !defined(OF_X86)) && !defined(OF_AMIGAOS_M68K)
#  define INPUT @"\t-0.123456789 "
#  define EXPECTED -0.123456789
# else
/*
 * Solaris' strtod() has weird rounding on x86, but not on AMD64.
 * AmigaOS 3 with libnix has weird rounding as well.
 */
#  define INPUT @"\t-0.125 "
#  define EXPECTED -0.125
# endif
#endif
	TEST(@"-[doubleValue]",
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
	    R([mutableString1 deleteEnclosingWhitespaces]) &&
	    [mutableString1 isEqual: @"asd"] &&
	    (mutableString1 = [mutableStringClass
	    stringWithString: whitespace[1]]) &&
	    R([mutableString1 deleteEnclosingWhitespaces]) &&
	    [mutableString1 isEqual: @""])

#ifdef OF_HAVE_UNICODE_TABLES
	TEST(@"-[decomposedStringWithCanonicalMapping]",
	    [C(@"H\xC3\xA4llj\xC3\xB6").decomposedStringWithCanonicalMapping
	    isEqual: @"H\x61\xCC\x88llj\x6F\xCC\x88"]);

	TEST(@"-[decomposedStringWithCompatibilityMapping]",
	    [C(@"H\xC3\xA4llj\xC3\xB6").decomposedStringWithCompatibilityMapping
	    isEqual: @"H\x61\xCC\x88llj\x6F\xCC\x88"]);
#endif

	TEST(@"-[stringByXMLEscaping]",
	    (string = C(@"<hello> &world'\"!&").stringByXMLEscaping) &&
	    [string isEqual: @"&lt;hello&gt; &amp;world&apos;&quot;!&amp;"])

	TEST(@"-[stringByXMLUnescaping]",
	    [string.stringByXMLUnescaping isEqual: @"<hello> &world'\"!&"] &&
	    [C(@"&#x79;").stringByXMLUnescaping isEqual: @"y"] &&







<
<
<
<
<
<
<
<
<
<







1403
1404
1405
1406
1407
1408
1409










1410
1411
1412
1413
1414
1415
1416
	    R([mutableString1 deleteEnclosingWhitespaces]) &&
	    [mutableString1 isEqual: @"asd"] &&
	    (mutableString1 = [mutableStringClass
	    stringWithString: whitespace[1]]) &&
	    R([mutableString1 deleteEnclosingWhitespaces]) &&
	    [mutableString1 isEqual: @""])











	TEST(@"-[stringByXMLEscaping]",
	    (string = C(@"<hello> &world'\"!&").stringByXMLEscaping) &&
	    [string isEqual: @"&lt;hello&gt; &amp;world&apos;&quot;!&amp;"])

	TEST(@"-[stringByXMLUnescaping]",
	    [string.stringByXMLUnescaping isEqual: @"<hello> &world'\"!&"] &&
	    [C(@"&#x79;").stringByXMLUnescaping isEqual: @"y"] &&

Modified tests/OFSystemInfoTests.m from [5b9edfd152] to [f3db5fbea9].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18



















19
20
21
22
23




24
25
26
27
28
29
30
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#import "TestsAppDelegate.h"




















@implementation TestsAppDelegate (OFSystemInfoTests)
- (void)systemInfoTests
{
	void *pool = objc_autoreleasePoolPush();





	[OFStdOut setForegroundColor: [OFColor lime]];

	[OFStdOut writeFormat: @"[OFSystemInfo] Page size: %zd\n",
	    [OFSystemInfo pageSize]];

	[OFStdOut writeFormat: @"[OFSystemInfo] Number of CPUs: %zd\n",

|
















>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>





>
>
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
/*
 * Copyright (c) 2008-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 "TestsAppDelegate.h"

#ifdef OF_HAVE_SOCKETS
static void
printAddresses(OFData *addresses, bool *firstAddress)
{
	size_t count = addresses.count;

	for (size_t i = 0; i < count; i++) {
		const OFSocketAddress *address = [addresses itemAtIndex: i];

		if (!*firstAddress)
			[OFStdOut writeString: @", "];

		*firstAddress = false;

		[OFStdOut writeString: OFSocketAddressString(address)];
	}
}
#endif

@implementation TestsAppDelegate (OFSystemInfoTests)
- (void)systemInfoTests
{
	void *pool = objc_autoreleasePoolPush();
#ifdef OF_HAVE_SOCKETS
	OFDictionary *networkInterfaces;
	bool firstInterface = true;
#endif

	[OFStdOut setForegroundColor: [OFColor lime]];

	[OFStdOut writeFormat: @"[OFSystemInfo] Page size: %zd\n",
	    [OFSystemInfo pageSize]];

	[OFStdOut writeFormat: @"[OFSystemInfo] Number of CPUs: %zd\n",
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66






67
68
69
70
71
72
73
	[OFStdOut writeFormat: @"[OFSystemInfo] Operating system name: %@\n",
	    [OFSystemInfo operatingSystemName]];

	[OFStdOut writeFormat:
	    @"[OFSystemInfo] Operating system version: %@\n",
	    [OFSystemInfo operatingSystemVersion]];

	[OFStdOut writeFormat: @"[OFSystemInfo] User config URI: %@\n",
	    [OFSystemInfo userConfigURI].string];

	[OFStdOut writeFormat: @"[OFSystemInfo] User data URI: %@\n",
	    [OFSystemInfo userDataURI].string];

	[OFStdOut writeFormat: @"[OFSystemInfo] Temporary directory URI: %@\n",
	    [OFSystemInfo temporaryDirectoryURI].string];

	[OFStdOut writeFormat: @"[OFSystemInfo] CPU vendor: %@\n",
	    [OFSystemInfo CPUVendor]];

	[OFStdOut writeFormat: @"[OFSystemInfo] CPU model: %@\n",
	    [OFSystemInfo CPUModel]];

#if defined(OF_X86_64) || defined(OF_X86)
	[OFStdOut writeFormat: @"[OFSystemInfo] Supports MMX: %d\n",
	    [OFSystemInfo supportsMMX]];







	[OFStdOut writeFormat: @"[OFSystemInfo] Supports SSE: %d\n",
	    [OFSystemInfo supportsSSE]];

	[OFStdOut writeFormat: @"[OFSystemInfo] Supports SSE2: %d\n",
	    [OFSystemInfo supportsSSE2]];








|
|

|
|

|
|







|


>
>
>
>
>
>







65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
	[OFStdOut writeFormat: @"[OFSystemInfo] Operating system name: %@\n",
	    [OFSystemInfo operatingSystemName]];

	[OFStdOut writeFormat:
	    @"[OFSystemInfo] Operating system version: %@\n",
	    [OFSystemInfo operatingSystemVersion]];

	[OFStdOut writeFormat: @"[OFSystemInfo] User config IRI: %@\n",
	    [OFSystemInfo userConfigIRI].string];

	[OFStdOut writeFormat: @"[OFSystemInfo] User data IRI: %@\n",
	    [OFSystemInfo userDataIRI].string];

	[OFStdOut writeFormat: @"[OFSystemInfo] Temporary directory IRI: %@\n",
	    [OFSystemInfo temporaryDirectoryIRI].string];

	[OFStdOut writeFormat: @"[OFSystemInfo] CPU vendor: %@\n",
	    [OFSystemInfo CPUVendor]];

	[OFStdOut writeFormat: @"[OFSystemInfo] CPU model: %@\n",
	    [OFSystemInfo CPUModel]];

#if defined(OF_AMD64) || defined(OF_X86)
	[OFStdOut writeFormat: @"[OFSystemInfo] Supports MMX: %d\n",
	    [OFSystemInfo supportsMMX]];

	[OFStdOut writeFormat: @"[OFSystemInfo] Supports 3DNow!: %d\n",
	    [OFSystemInfo supports3DNow]];

	[OFStdOut writeFormat: @"[OFSystemInfo] Supports enhanced 3DNow!: %d\n",
	    [OFSystemInfo supportsEnhanced3DNow]];

	[OFStdOut writeFormat: @"[OFSystemInfo] Supports SSE: %d\n",
	    [OFSystemInfo supportsSSE]];

	[OFStdOut writeFormat: @"[OFSystemInfo] Supports SSE2: %d\n",
	    [OFSystemInfo supportsSSE2]];

90
91
92
93
94
95
96










































































97
98
99
100
101
102






















































103
104
105
106
	    [OFSystemInfo supportsAVX2]];

	[OFStdOut writeFormat: @"[OFSystemInfo] Supports AES-NI: %d\n",
	    [OFSystemInfo supportsAESNI]];

	[OFStdOut writeFormat: @"[OFSystemInfo] Supports SHA extensions: %d\n",
	    [OFSystemInfo supportsSHAExtensions]];










































































#endif

#ifdef OF_POWERPC
	[OFStdOut writeFormat: @"[OFSystemInfo] Supports AltiVec: %d\n",
	    [OFSystemInfo supportsAltiVec]];
#endif























































	objc_autoreleasePoolPop(pool);
}
@end







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>






>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>




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
	    [OFSystemInfo supportsAVX2]];

	[OFStdOut writeFormat: @"[OFSystemInfo] Supports AES-NI: %d\n",
	    [OFSystemInfo supportsAESNI]];

	[OFStdOut writeFormat: @"[OFSystemInfo] Supports SHA extensions: %d\n",
	    [OFSystemInfo supportsSHAExtensions]];

	[OFStdOut writeFormat: @"[OFSystemInfo] Supports fused multiply-add: "
	    @"%d\n",
	    [OFSystemInfo supportsFusedMultiplyAdd]];

	[OFStdOut writeFormat: @"[OFSystemInfo] Supports F16C: %d\n",
	    [OFSystemInfo supportsF16C]];

	[OFStdOut writeFormat:
	    @"[OFSystemInfo] Supports AVX-512 Foundation: %d\n",
	    [OFSystemInfo supportsAVX512Foundation]];

	[OFStdOut writeFormat:
	    @"[OFSystemInfo] Supports AVX-512 Conflict Detection Instructions: "
	    @"%d\n",
	    [OFSystemInfo supportsAVX512ConflictDetectionInstructions]];

	[OFStdOut writeFormat:
	    @"[OFSystemInfo] Supports AVX-512 Exponential and Reciprocal "
	    @"Instructions: %d\n",
	    [OFSystemInfo supportsAVX512ExponentialAndReciprocalInstructions]];

	[OFStdOut writeFormat:
	    @"[OFSystemInfo] Supports AVX-512 Prefetch Instructions: %d\n",
	    [OFSystemInfo supportsAVX512PrefetchInstructions]];

	[OFStdOut writeFormat:
	    @"[OFSystemInfo] Supports AVX-512 Vector Length Extensions: %d\n",
	    [OFSystemInfo supportsAVX512VectorLengthExtensions]];

	[OFStdOut writeFormat:
	    @"[OFSystemInfo] Supports AVX-512 Doubleword and Quadword "
	    @"Instructions: %d\n",
	    [OFSystemInfo supportsAVX512DoublewordAndQuadwordInstructions]];

	[OFStdOut writeFormat:
	    @"[OFSystemInfo] Supports AVX-512 Byte and Word Instructions: %d\n",
	    [OFSystemInfo supportsAVX512ByteAndWordInstructions]];

	[OFStdOut writeFormat:
	    @"[OFSystemInfo] Supports AVX-512 Integer Fused Multiply Add: %d\n",
	    [OFSystemInfo supportsAVX512IntegerFusedMultiplyAdd]];

	[OFStdOut writeFormat:
	    @"[OFSystemInfo] Supports AVX-512 Vector Byte Manipulation "
	    @"Instructions: %d\n",
	    [OFSystemInfo supportsAVX512VectorByteManipulationInstructions]];

	[OFStdOut writeFormat:
	    @"[OFSystemInfo] Supports AVX-512 Vector Population Count "
	    @"Instruction: %d\n",
	    [OFSystemInfo supportsAVX512VectorPopulationCountInstruction]];

	[OFStdOut writeFormat:
	    @"[OFSystemInfo] Supports AVX-512 Vector Neutral Network "
	    @"Instructions: %d\n",
	    [OFSystemInfo supportsAVX512VectorNeuralNetworkInstructions]];

	[OFStdOut writeFormat:
	    @"[OFSystemInfo] Supports AVX-512 Vector Byte Manipulation "
	    @"Instructions 2: %d\n",
	    [OFSystemInfo supportsAVX512VectorByteManipulationInstructions2]];

	[OFStdOut writeFormat:
	    @"[OFSystemInfo] Supports AVX-512 Bit Algorithms: %d\n",
	    [OFSystemInfo supportsAVX512BitAlgorithms]];

	[OFStdOut writeFormat:
	    @"[OFSystemInfo] Supports AVX-512 Float16 Instructions: %d\n",
	    [OFSystemInfo supportsAVX512Float16Instructions]];

	[OFStdOut writeFormat:
	    @"[OFSystemInfo] Supports AVX-512 BFloat16 Instructions: %d\n",
	    [OFSystemInfo supportsAVX512BFloat16Instructions]];
#endif

#ifdef OF_POWERPC
	[OFStdOut writeFormat: @"[OFSystemInfo] Supports AltiVec: %d\n",
	    [OFSystemInfo supportsAltiVec]];
#endif

#ifdef OF_HAVE_SOCKETS
	networkInterfaces = [OFSystemInfo networkInterfaces];
	[OFStdOut writeString: @"[OFSystemInfo] Network interfaces: "];
	for (OFString *name in networkInterfaces) {
		bool firstAddress = true;
		OFNetworkInterface interface;
		OFData *hardwareAddress;

		if (!firstInterface)
			[OFStdOut writeString: @"; "];

		firstInterface = false;

		[OFStdOut writeFormat: @"%@(", name];

		interface = [networkInterfaces objectForKey: name];

		printAddresses([interface objectForKey:
		    OFNetworkInterfaceIPv4Addresses], &firstAddress);
# ifdef OF_HAVE_IPV6
		printAddresses([interface objectForKey:
		    OFNetworkInterfaceIPv6Addresses], &firstAddress);
# endif
# ifdef OF_HAVE_IPX
		printAddresses([interface objectForKey:
		    OFNetworkInterfaceIPXAddresses], &firstAddress);
# endif
# ifdef OF_HAVE_APPLETALK
		printAddresses([interface objectForKey:
		    OFNetworkInterfaceAppleTalkAddresses], &firstAddress);
# endif

		hardwareAddress = [interface
		    objectForKey: OFNetworkInterfaceHardwareAddress];
		if (hardwareAddress != nil) {
			const unsigned char *bytes = hardwareAddress.items;
			size_t length = hardwareAddress.count;

			if (!firstAddress)
				[OFStdOut writeString: @", "];

			for (size_t i = 0; i < length; i++) {
				if (i > 0)
					[OFStdOut writeString: @":"];

				[OFStdOut writeFormat: @"%02X", bytes[i]];
			}
		}

		[OFStdOut writeString: @")"];
	}
	[OFStdOut writeString: @"\n"];
#endif

	objc_autoreleasePoolPop(pool);
}
@end

Modified tests/OFTCPSocketTests.m from [e205251e21] to [4cfbc85ac3].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
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
static OFString *const module = @"OFTCPSocket";

@implementation TestsAppDelegate (OFTCPSocketTests)
- (void)TCPSocketTests
{
	void *pool = objc_autoreleasePoolPush();
	OFTCPSocket *server, *client = nil, *accepted;
	uint16_t port;
	char buffer[6];

	TEST(@"+[socket]", (server = [OFTCPSocket socket]) &&
	    (client = [OFTCPSocket socket]))

	TEST(@"-[bindToHost:port:]",
	    (port = [server bindToHost: @"127.0.0.1" port: 0]))

	TEST(@"-[listen]", R([server listen]))

	TEST(@"-[connectToHost:port:]",
	    R([client connectToHost: @"127.0.0.1" port: port]))


	TEST(@"-[accept]", (accepted = [server accept]))

	TEST(@"-[remoteAddress]",
	    [OFSocketAddressString(accepted.remoteAddress)
	    isEqual: @"127.0.0.1"])








|






|




|
>







22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
static OFString *const module = @"OFTCPSocket";

@implementation TestsAppDelegate (OFTCPSocketTests)
- (void)TCPSocketTests
{
	void *pool = objc_autoreleasePoolPush();
	OFTCPSocket *server, *client = nil, *accepted;
	OFSocketAddress address;
	char buffer[6];

	TEST(@"+[socket]", (server = [OFTCPSocket socket]) &&
	    (client = [OFTCPSocket socket]))

	TEST(@"-[bindToHost:port:]",
	    R(address = [server bindToHost: @"127.0.0.1" port: 0]))

	TEST(@"-[listen]", R([server listen]))

	TEST(@"-[connectToHost:port:]",
	    R([client connectToHost: @"127.0.0.1"
			       port: OFSocketAddressIPPort(&address)]))

	TEST(@"-[accept]", (accepted = [server accept]))

	TEST(@"-[remoteAddress]",
	    [OFSocketAddressString(accepted.remoteAddress)
	    isEqual: @"127.0.0.1"])

Modified tests/OFThreadTests.m from [3abe7860ab] to [bbeb8a5fbf].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified tests/OFUDPSocketTests.m from [435a3297c3] to [9c08c02308].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
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
static OFString *const module = @"OFUDPSocket";

@implementation TestsAppDelegate (OFUDPSocketTests)
- (void)UDPSocketTests
{
	void *pool = objc_autoreleasePoolPush();
	OFUDPSocket *sock;
	uint16_t port1;
	OFSocketAddress addr1, addr2, addr3;
	char buf[6];

	TEST(@"+[socket]", (sock = [OFUDPSocket socket]))

	TEST(@"-[bindToHost:port:]",
	    (port1 = [sock bindToHost: @"127.0.0.1" port: 0]))

	addr1 = OFSocketAddressParseIP(@"127.0.0.1", port1);

	TEST(@"-[sendBuffer:length:receiver:]",
	    R([sock sendBuffer: "Hello" length: 6 receiver: &addr1]))

	TEST(@"-[receiveIntoBuffer:length:sender:]",
	    [sock receiveIntoBuffer: buf length: 6 sender: &addr2] == 6 &&
	    !memcmp(buf, "Hello", 6) &&
	    [OFSocketAddressString(&addr2) isEqual: @"127.0.0.1"] &&
	    OFSocketAddressIPPort(&addr2) == port1)

	addr3 = OFSocketAddressParseIP(@"127.0.0.1", port1 + 1);


	/*
	 * TODO: Move those tests elsewhere as soon as the DNS resolving part
	 *	 is no longer in OFUDPSocket.
	 */
	TEST(@"OFSocketAddressEqual()",
	    OFSocketAddressEqual(&addr1, &addr2) &&
	    !OFSocketAddressEqual(&addr1, &addr3))

	TEST(@"OFSocketAddressHash()",
	    OFSocketAddressHash(&addr1) == OFSocketAddressHash(&addr2) &&
	    OFSocketAddressHash(&addr1) != OFSocketAddressHash(&addr3))

	objc_autoreleasePoolPop(pool);
}
@end







<






|
<
<








|

|
>

<
<
<
<











22
23
24
25
26
27
28

29
30
31
32
33
34
35


36
37
38
39
40
41
42
43
44
45
46
47
48




49
50
51
52
53
54
55
56
57
58
59
static OFString *const module = @"OFUDPSocket";

@implementation TestsAppDelegate (OFUDPSocketTests)
- (void)UDPSocketTests
{
	void *pool = objc_autoreleasePoolPush();
	OFUDPSocket *sock;

	OFSocketAddress addr1, addr2, addr3;
	char buf[6];

	TEST(@"+[socket]", (sock = [OFUDPSocket socket]))

	TEST(@"-[bindToHost:port:]",
	    R(addr1 = [sock bindToHost: @"127.0.0.1" port: 0]))



	TEST(@"-[sendBuffer:length:receiver:]",
	    R([sock sendBuffer: "Hello" length: 6 receiver: &addr1]))

	TEST(@"-[receiveIntoBuffer:length:sender:]",
	    [sock receiveIntoBuffer: buf length: 6 sender: &addr2] == 6 &&
	    !memcmp(buf, "Hello", 6) &&
	    [OFSocketAddressString(&addr2) isEqual: @"127.0.0.1"] &&
	    OFSocketAddressIPPort(&addr2) == OFSocketAddressIPPort(&addr1))

	addr3 = OFSocketAddressParseIP(@"127.0.0.1",
	    OFSocketAddressIPPort(&addr1) + 1);





	TEST(@"OFSocketAddressEqual()",
	    OFSocketAddressEqual(&addr1, &addr2) &&
	    !OFSocketAddressEqual(&addr1, &addr3))

	TEST(@"OFSocketAddressHash()",
	    OFSocketAddressHash(&addr1) == OFSocketAddressHash(&addr2) &&
	    OFSocketAddressHash(&addr1) != OFSocketAddressHash(&addr3))

	objc_autoreleasePoolPop(pool);
}
@end

Modified tests/OFUNIXDatagramSocketTests.m from [61f9f2c60c] to [588aa866e4].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
	void *pool = objc_autoreleasePoolPush();
	OFString *path;
	OFUNIXDatagramSocket *sock;
	OFSocketAddress address1, address2;
	char buffer[5];

#if defined(OF_HAVE_FILES) && !defined(OF_IOS)
	path = [[OFSystemInfo temporaryDirectoryURI]
	    URIByAppendingPathComponent: [[OFUUID UUID] UUIDString]]
	    .fileSystemRepresentation;
#else
	/*
	 * We can have sockets, including UNIX sockets, while file support is
	 * disabled.
	 *
	 * We also use this code path for iOS, as the temporaryDirectoryURI is
	 * too long on the iOS simulator.
	 */
	path = [OFString stringWithFormat: @"/tmp/%@",
					   [[OFUUID UUID] UUIDString]];
#endif

	TEST(@"+[socket]", (sock = [OFUNIXDatagramSocket socket]))







|
|






|







27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
	void *pool = objc_autoreleasePoolPush();
	OFString *path;
	OFUNIXDatagramSocket *sock;
	OFSocketAddress address1, address2;
	char buffer[5];

#if defined(OF_HAVE_FILES) && !defined(OF_IOS)
	path = [[OFSystemInfo temporaryDirectoryIRI]
	    IRIByAppendingPathComponent: [[OFUUID UUID] UUIDString]]
	    .fileSystemRepresentation;
#else
	/*
	 * We can have sockets, including UNIX sockets, while file support is
	 * disabled.
	 *
	 * We also use this code path for iOS, as the temporaryDirectoryIRI is
	 * too long on the iOS simulator.
	 */
	path = [OFString stringWithFormat: @"/tmp/%@",
					   [[OFUUID UUID] UUIDString]];
#endif

	TEST(@"+[socket]", (sock = [OFUNIXDatagramSocket socket]))

Modified tests/OFUNIXStreamSocketTests.m from [cebf3c029f] to [b3f4ed0fcd].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
{
	void *pool = objc_autoreleasePoolPush();
	OFString *path;
	OFUNIXStreamSocket *sockClient, *sockServer, *sockAccepted;
	char buffer[5];

#if defined(OF_HAVE_FILES) && !defined(OF_IOS)
	path = [[OFSystemInfo temporaryDirectoryURI]
	    URIByAppendingPathComponent: [[OFUUID UUID] UUIDString]]
	    .fileSystemRepresentation;
#else
	/*
	 * We can have sockets, including UNIX sockets, while file support is
	 * disabled.
	 *
	 * We also use this code path for iOS, as the temporaryDirectoryURI is
	 * too long on the iOS simulator.
	 */
	path = [OFString stringWithFormat: @"/tmp/%@",
					   [[OFUUID UUID] UUIDString]];
#endif

	TEST(@"+[socket]", (sockClient = [OFUNIXStreamSocket socket]) &&







|
|






|







26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
{
	void *pool = objc_autoreleasePoolPush();
	OFString *path;
	OFUNIXStreamSocket *sockClient, *sockServer, *sockAccepted;
	char buffer[5];

#if defined(OF_HAVE_FILES) && !defined(OF_IOS)
	path = [[OFSystemInfo temporaryDirectoryIRI]
	    IRIByAppendingPathComponent: [[OFUUID UUID] UUIDString]]
	    .fileSystemRepresentation;
#else
	/*
	 * We can have sockets, including UNIX sockets, while file support is
	 * disabled.
	 *
	 * We also use this code path for iOS, as the temporaryDirectory:RI is
	 * too long on the iOS simulator.
	 */
	path = [OFString stringWithFormat: @"/tmp/%@",
					   [[OFUUID UUID] UUIDString]];
#endif

	TEST(@"+[socket]", (sockClient = [OFUNIXStreamSocket socket]) &&
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
		TEST(@"-[writeBuffer:length:]",
		    R([sockAccepted writeBuffer: "Hello" length: 5]))

		TEST(@"-[readIntoBuffer:length:]",
		    [sockClient readIntoBuffer: buffer length: 5] == 5 &&
		    memcmp(buffer, "Hello", 5) == 0)

		TEST(@"-[remoteAddress]",
		    OFSocketAddressUNIXPath(sockAccepted.remoteAddress) == nil)
	} @finally {
#ifdef OF_HAVE_FILES
		[[OFFileManager defaultManager] removeItemAtPath: path];
#endif
	}

	objc_autoreleasePoolPop(pool);
}
@end







|
|









77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
		TEST(@"-[writeBuffer:length:]",
		    R([sockAccepted writeBuffer: "Hello" length: 5]))

		TEST(@"-[readIntoBuffer:length:]",
		    [sockClient readIntoBuffer: buffer length: 5] == 5 &&
		    memcmp(buffer, "Hello", 5) == 0)

		TEST(@"-[remoteAddress]", OFSocketAddressUNIXPath(
		    sockAccepted.remoteAddress).length == 0)
	} @finally {
#ifdef OF_HAVE_FILES
		[[OFFileManager defaultManager] removeItemAtPath: path];
#endif
	}

	objc_autoreleasePoolPop(pool);
}
@end

Modified tests/OFValueTests.m from [f614b296d4] to [52b7d9b170].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified tests/OFWindowsRegistryKeyTests.m from [ddf274227c] to [0f0fbee00b].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified tests/OFXMLElementBuilderTests.m from [82fd282c44] to [94889a4bd5].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified tests/OFXMLNodeTests.m from [29eb2048b3] to [806daf51ab].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified tests/OFXMLParserTests.m from [dc6afcdede] to [e9e91152cf].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified tests/RuntimeARCTests.m from [62782bae47] to [464cdbc085].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
@end

@implementation RuntimeARCTest
- (instancetype)init
{
	self = [super init];

#if defined(OF_WINDOWS) && defined(OF_X86_64)
	/*
	 * Clang has a bug on Windows where it creates an invalid call into
	 * objc_retainAutoreleasedReturnValue(). Work around it by not using an
	 * autoreleased exception.
	 */
	@throw [[OFException alloc] init];
#else







|







23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
@end

@implementation RuntimeARCTest
- (instancetype)init
{
	self = [super init];

#if defined(OF_WINDOWS) && defined(OF_AMD64)
	/*
	 * Clang has a bug on Windows where it creates an invalid call into
	 * objc_retainAutoreleasedReturnValue(). Work around it by not using an
	 * autoreleased exception.
	 */
	@throw [[OFException alloc] init];
#else

Modified tests/RuntimeTests.m from [9aa59cf983] to [38c7914698].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified tests/TestsAppDelegate.h from [d11eaa5833] to [4ca959eac5].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
74
75
76
77
78
79
80




81
82
83
84
85
86
87
@interface TestsAppDelegate (OFBlockTests)
- (void)blockTests;
@end

@interface TestsAppDelegate (OFCharacterSetTests)
- (void)characterSetTests;
@end





@interface TestsAppDelegate (OFDDPSocketTests)
- (void)DDPSocketTests;
@end

@interface TestsAppDelegate (OFDNSResolverTests)
- (void)DNSResolverTests;







>
>
>
>







74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
@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;
114
115
116
117
118
119
120




121
122
123
124
125
126
127
@interface TestsAppDelegate (OFHTTPCookieManagerTests)
- (void)HTTPCookieManagerTests;
@end

@interface TestsAppDelegate (OFINIFileTests)
- (void)INIFileTests;
@end





@interface TestsAppDelegate (OFIPXSocketTests)
- (void)IPXSocketTests;
@end

@interface TestsAppDelegate (OFInvocationTests)
- (void)invocationTests;







>
>
>
>







118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
@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;
146
147
148
149
150
151
152




153
154
155
156
157
158
159
@interface TestsAppDelegate (OFLocaleTests)
- (void)localeTests;
@end

@interface TestsAppDelegate (OFMD5HashTests)
- (void)MD5HashTests;
@end





@interface TestsAppDelegate  (OFMemoryStreamTests)
- (void)memoryStreamTests;
@end

@interface TestsAppDelegate (OFMethodSignatureTests)
- (void)methodSignatureTests;







>
>
>
>







154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
@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;
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
- (void)SPXSocketTests;
@end

@interface TestsAppDelegate (OFSPXStreamSocketTests)
- (void)SPXStreamSocketTests;
@end

@interface TestsAppDelegate (OFSerializationTests)
- (void)serializationTests;
@end

@interface TestsAppDelegate (OFSetTests)
- (void)setTests;
@end

@interface TestsAppDelegate (OFSystemInfoTests)
- (void)systemInfoTests;
@end







<
<
<
<







235
236
237
238
239
240
241




242
243
244
245
246
247
248
- (void)SPXSocketTests;
@end

@interface TestsAppDelegate (OFSPXStreamSocketTests)
- (void)SPXStreamSocketTests;
@end





@interface TestsAppDelegate (OFSetTests)
- (void)setTests;
@end

@interface TestsAppDelegate (OFSystemInfoTests)
- (void)systemInfoTests;
@end
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
- (void)UNIXDatagramSocketTests;
@end

@interface TestsAppDelegate (OFUNIXStreamSocketTests)
- (void)UNIXStreamSocketTests;
@end

@interface TestsAppDelegate (OFURITests)
- (void)URITests;
@end

@interface TestsAppDelegate (OFValueTests)
- (void)valueTests;
@end

@interface TestsAppDelegate (OFWindowsRegistryKeyTests)
- (void)windowsRegistryKeyTests;
@end







<
<
<
<







275
276
277
278
279
280
281




282
283
284
285
286
287
288
- (void)UNIXDatagramSocketTests;
@end

@interface TestsAppDelegate (OFUNIXStreamSocketTests)
- (void)UNIXStreamSocketTests;
@end





@interface TestsAppDelegate (OFValueTests)
- (void)valueTests;
@end

@interface TestsAppDelegate (OFWindowsRegistryKeyTests)
- (void)windowsRegistryKeyTests;
@end

Modified tests/TestsAppDelegate.m from [8f3bec08f0] to [3a8dda6580].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
	if (OFStdOut.hasTerminal) {
		[OFStdOut writeString: @"\r"];
		[OFStdOut reset];
		[OFStdOut eraseLine];
	}
}

- (void)applicationDidFinishLaunching
{
#if defined(OF_IOS) && defined(OF_HAVE_FILES)
	CFBundleRef mainBundle = CFBundleGetMainBundle();
	CFURLRef resourcesURL = CFBundleCopyResourcesDirectoryURL(mainBundle);
	UInt8 resourcesPath[PATH_MAX];

	if (!CFURLGetFileSystemRepresentation(resourcesURL, true, resourcesPath,







|







345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
	if (OFStdOut.hasTerminal) {
		[OFStdOut writeString: @"\r"];
		[OFStdOut reset];
		[OFStdOut eraseLine];
	}
}

- (void)applicationDidFinishLaunching: (OFNotification *)notification
{
#if defined(OF_IOS) && defined(OF_HAVE_FILES)
	CFBundleRef mainBundle = CFBundleGetMainBundle();
	CFURLRef resourcesURL = CFBundleCopyResourcesDirectoryURL(mainBundle);
	UInt8 resourcesPath[PATH_MAX];

	if (!CFURLGetFileSystemRepresentation(resourcesURL, true, resourcesPath,
387
388
389
390
391
392
393

394
395
396
397
398
399
400
	[self arrayTests];
	[self dictionaryTests];
	[self listTests];
	[self setTests];
	[self dateTests];
	[self valueTests];
	[self numberTests];

	[self streamTests];
	[self memoryStreamTests];
	[self notificationCenterTests];
	[self MD5HashTests];
	[self RIPEMD160HashTests];
	[self SHA1HashTests];
	[self SHA224HashTests];







>







387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
	[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];
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
	[self DDPSocketTests];
# endif
	[self kernelEventObserverTests];
#endif
#ifdef OF_HAVE_THREADS
	[self threadTests];
#endif
	[self URITests];
#if defined(OF_HAVE_SOCKETS) && defined(OF_HAVE_THREADS)
	[self HTTPClientTests];
#endif
#ifdef OF_HAVE_SOCKETS
	[self HTTPCookieTests];
	[self HTTPCookieManagerTests];
#endif
	[self XMLParserTests];
	[self XMLNodeTests];
	[self XMLElementBuilderTests];
	[self serializationTests];
	[self JSONTests];
	[self propertyListTests];
	[self ASN1DERParsingTests];
	[self ASN1DERRepresentationTests];



#if defined(OF_HAVE_PLUGINS)
	[self pluginTests];
#endif

#ifdef OF_WINDOWS
	[self windowsRegistryKeyTests];
#endif

#ifdef OF_HAVE_SOCKETS
	[self DNSResolverTests];
#endif







|










<




>
>
>



>







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
	[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

Modified tests/iOS.xcodeproj/project.pbxproj from [2c6fcc5e96] to [ac2dd7d645].

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/* Begin PBXBuildFile section */
		4B6AB9CD202BA431007BAC7D /* TestPlugin.bundle in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4B6AB9CA202BA408007BAC7D /* TestPlugin.bundle */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
		4BC7FD07201394F300280496 /* ObjFW.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4BC7FD06201394F300280496 /* ObjFW.framework */; };
		4BC7FD092013954B00280496 /* tests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4BC7FD082013954B00280496 /* tests.a */; };
		4BC7FD0B2013956D00280496 /* ObjFW.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4BC7FD06201394F300280496 /* ObjFW.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
		4BC7FD102013960600280496 /* testfile.txt in Resources */ = {isa = PBXBuildFile; fileRef = 4BC7FD0C2013960600280496 /* testfile.txt */; };
		4BC7FD112013960600280496 /* testfile.bin in Resources */ = {isa = PBXBuildFile; fileRef = 4BC7FD0D2013960600280496 /* testfile.bin */; };
		4BC7FD122013960600280496 /* serialization.xml in Resources */ = {isa = PBXBuildFile; fileRef = 4BC7FD0E2013960600280496 /* serialization.xml */; };
		4BC7FD132013960600280496 /* testfile.ini in Resources */ = {isa = PBXBuildFile; fileRef = 4BC7FD0F2013960600280496 /* testfile.ini */; };
		4BEBFB6E2013934E002E8710 /* ImportTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BEBFB6D2013934E002E8710 /* ImportTest.m */; };
/* End PBXBuildFile section */

/* Begin PBXCopyFilesBuildPhase section */
		4B6AB9CC202BA428007BAC7D /* CopyFiles */ = {
			isa = PBXCopyFilesBuildPhase;







<







9
10
11
12
13
14
15

16
17
18
19
20
21
22
/* Begin PBXBuildFile section */
		4B6AB9CD202BA431007BAC7D /* TestPlugin.bundle in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4B6AB9CA202BA408007BAC7D /* TestPlugin.bundle */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
		4BC7FD07201394F300280496 /* ObjFW.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4BC7FD06201394F300280496 /* ObjFW.framework */; };
		4BC7FD092013954B00280496 /* tests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4BC7FD082013954B00280496 /* tests.a */; };
		4BC7FD0B2013956D00280496 /* ObjFW.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4BC7FD06201394F300280496 /* ObjFW.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
		4BC7FD102013960600280496 /* testfile.txt in Resources */ = {isa = PBXBuildFile; fileRef = 4BC7FD0C2013960600280496 /* testfile.txt */; };
		4BC7FD112013960600280496 /* testfile.bin in Resources */ = {isa = PBXBuildFile; fileRef = 4BC7FD0D2013960600280496 /* testfile.bin */; };

		4BC7FD132013960600280496 /* testfile.ini in Resources */ = {isa = PBXBuildFile; fileRef = 4BC7FD0F2013960600280496 /* testfile.ini */; };
		4BEBFB6E2013934E002E8710 /* ImportTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BEBFB6D2013934E002E8710 /* ImportTest.m */; };
/* End PBXBuildFile section */

/* Begin PBXCopyFilesBuildPhase section */
		4B6AB9CC202BA428007BAC7D /* CopyFiles */ = {
			isa = PBXCopyFilesBuildPhase;
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57

/* Begin PBXFileReference section */
		4B6AB9CA202BA408007BAC7D /* TestPlugin.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; name = TestPlugin.bundle; path = plugin/TestPlugin.bundle; sourceTree = "<group>"; };
		4BC7FD06201394F300280496 /* ObjFW.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ObjFW.framework; path = ../src/ObjFW.framework; sourceTree = "<group>"; };
		4BC7FD082013954B00280496 /* tests.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = tests.a; sourceTree = "<group>"; };
		4BC7FD0C2013960600280496 /* testfile.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = testfile.txt; sourceTree = "<group>"; };
		4BC7FD0D2013960600280496 /* testfile.bin */ = {isa = PBXFileReference; lastKnownFileType = archive.macbinary; path = testfile.bin; sourceTree = "<group>"; };
		4BC7FD0E2013960600280496 /* serialization.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = serialization.xml; sourceTree = "<group>"; };
		4BC7FD0F2013960600280496 /* testfile.ini */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = testfile.ini; sourceTree = "<group>"; };
		4BEBFB5B2013934E002E8710 /* tests.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = tests.app; sourceTree = BUILT_PRODUCTS_DIR; };
		4BEBFB6C2013934E002E8710 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = SOURCE_ROOT; };
		4BEBFB6D2013934E002E8710 /* ImportTest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ImportTest.m; sourceTree = SOURCE_ROOT; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */







<







42
43
44
45
46
47
48

49
50
51
52
53
54
55

/* Begin PBXFileReference section */
		4B6AB9CA202BA408007BAC7D /* TestPlugin.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; name = TestPlugin.bundle; path = plugin/TestPlugin.bundle; sourceTree = "<group>"; };
		4BC7FD06201394F300280496 /* ObjFW.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ObjFW.framework; path = ../src/ObjFW.framework; sourceTree = "<group>"; };
		4BC7FD082013954B00280496 /* tests.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = tests.a; sourceTree = "<group>"; };
		4BC7FD0C2013960600280496 /* testfile.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = testfile.txt; sourceTree = "<group>"; };
		4BC7FD0D2013960600280496 /* testfile.bin */ = {isa = PBXFileReference; lastKnownFileType = archive.macbinary; path = testfile.bin; sourceTree = "<group>"; };

		4BC7FD0F2013960600280496 /* testfile.ini */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = testfile.ini; sourceTree = "<group>"; };
		4BEBFB5B2013934E002E8710 /* tests.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = tests.app; sourceTree = BUILT_PRODUCTS_DIR; };
		4BEBFB6C2013934E002E8710 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = SOURCE_ROOT; };
		4BEBFB6D2013934E002E8710 /* ImportTest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ImportTest.m; sourceTree = SOURCE_ROOT; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
			sourceTree = "<group>";
		};
		4BEBFB5D2013934E002E8710 /* tests */ = {
			isa = PBXGroup;
			children = (
				4BEBFB6C2013934E002E8710 /* Info.plist */,
				4BEBFB6D2013934E002E8710 /* ImportTest.m */,
				4BC7FD0E2013960600280496 /* serialization.xml */,
				4BC7FD0D2013960600280496 /* testfile.bin */,
				4BC7FD0F2013960600280496 /* testfile.ini */,
				4BC7FD0C2013960600280496 /* testfile.txt */,
			);
			name = tests;
			sourceTree = "<group>";
		};







<







93
94
95
96
97
98
99

100
101
102
103
104
105
106
			sourceTree = "<group>";
		};
		4BEBFB5D2013934E002E8710 /* tests */ = {
			isa = PBXGroup;
			children = (
				4BEBFB6C2013934E002E8710 /* Info.plist */,
				4BEBFB6D2013934E002E8710 /* ImportTest.m */,

				4BC7FD0D2013960600280496 /* testfile.bin */,
				4BC7FD0F2013960600280496 /* testfile.ini */,
				4BC7FD0C2013960600280496 /* testfile.txt */,
			);
			name = tests;
			sourceTree = "<group>";
		};
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178

/* Begin PBXResourcesBuildPhase section */
		4BEBFB592013934E002E8710 /* Resources */ = {
			isa = PBXResourcesBuildPhase;
			buildActionMask = 2147483647;
			files = (
				4BC7FD102013960600280496 /* testfile.txt in Resources */,
				4BC7FD122013960600280496 /* serialization.xml in Resources */,
				4BC7FD132013960600280496 /* testfile.ini in Resources */,
				4BC7FD112013960600280496 /* testfile.bin in Resources */,
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
/* End PBXResourcesBuildPhase section */








<







161
162
163
164
165
166
167

168
169
170
171
172
173
174

/* Begin PBXResourcesBuildPhase section */
		4BEBFB592013934E002E8710 /* Resources */ = {
			isa = PBXResourcesBuildPhase;
			buildActionMask = 2147483647;
			files = (
				4BC7FD102013960600280496 /* testfile.txt in Resources */,

				4BC7FD132013960600280496 /* testfile.ini in Resources */,
				4BC7FD112013960600280496 /* testfile.bin in Resources */,
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
/* End PBXResourcesBuildPhase section */

305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
				FRAMEWORK_SEARCH_PATHS = "$(PROJECT_DIR)/../src";
				INFOPLIST_FILE = Info.plist;
				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
				LIBRARY_SEARCH_PATHS = (
					"$(inherited)",
					"$(PROJECT_DIR)",
				);
				OTHER_LDFLAGS = "-ObjC";
				PRODUCT_BUNDLE_IDENTIFIER = im.nil.objfw.tests;
				PRODUCT_NAME = "$(TARGET_NAME)";
				TARGETED_DEVICE_FAMILY = "1,2";
			};
			name = Debug;
		};
		4BEBFB732013934E002E8710 /* Release */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
				CODE_SIGN_STYLE = Automatic;
				DEVELOPMENT_TEAM = MXKNFCKFL6;
				FRAMEWORK_SEARCH_PATHS = "$(PROJECT_DIR)/../src";
				INFOPLIST_FILE = Info.plist;
				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
				LIBRARY_SEARCH_PATHS = (
					"$(inherited)",
					"$(PROJECT_DIR)",
				);
				OTHER_LDFLAGS = "-ObjC";
				PRODUCT_BUNDLE_IDENTIFIER = im.nil.objfw.tests;
				PRODUCT_NAME = "$(TARGET_NAME)";
				TARGETED_DEVICE_FAMILY = "1,2";
			};
			name = Release;
		};
/* End XCBuildConfiguration section */







|



















|







301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
				FRAMEWORK_SEARCH_PATHS = "$(PROJECT_DIR)/../src";
				INFOPLIST_FILE = Info.plist;
				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
				LIBRARY_SEARCH_PATHS = (
					"$(inherited)",
					"$(PROJECT_DIR)",
				);
				OTHER_LDFLAGS = "-all_load";
				PRODUCT_BUNDLE_IDENTIFIER = im.nil.objfw.tests;
				PRODUCT_NAME = "$(TARGET_NAME)";
				TARGETED_DEVICE_FAMILY = "1,2";
			};
			name = Debug;
		};
		4BEBFB732013934E002E8710 /* Release */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
				CODE_SIGN_STYLE = Automatic;
				DEVELOPMENT_TEAM = MXKNFCKFL6;
				FRAMEWORK_SEARCH_PATHS = "$(PROJECT_DIR)/../src";
				INFOPLIST_FILE = Info.plist;
				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
				LIBRARY_SEARCH_PATHS = (
					"$(inherited)",
					"$(PROJECT_DIR)",
				);
				OTHER_LDFLAGS = "-all_load";
				PRODUCT_BUNDLE_IDENTIFIER = im.nil.objfw.tests;
				PRODUCT_NAME = "$(TARGET_NAME)";
				TARGETED_DEVICE_FAMILY = "1,2";
			};
			name = Release;
		};
/* End XCBuildConfiguration section */

Modified tests/objc_sync/Makefile from [0df383ed25] to [1e35f54ff7].

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
	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
	rm -f ${OBJFWRT_AMIGA_LIB}
	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}; \







<







10
11
12
13
14
15
16

17
18
19
20
21
22
23
	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}; \
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
		${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
	if test -f ../../src/runtime/${OBJFWRT_AMIGA_LIB}; then \
		${LN_S} ../../src/runtime/${OBJFWRT_AMIGA_LIB} \
		    ${OBJFWRT_AMIGA_LIB}; \
	fi
	LD_LIBRARY_PATH=.$${LD_LIBRARY_PATH+:}$$LD_LIBRARY_PATH \
	DYLD_LIBRARY_PATH=.$${DYLD_LIBRARY_PATH+:}$$DYLD_LIBRARY_PATH \
	LIBRARY_PATH=.$${LIBRARY_PATH+:}$$LIBRARY_PATH \
	${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

CPPFLAGS += -I../../src -I../../src/runtime -I../..
LIBS := -L../../src -lobjfw						\
	-L../../src/runtime -L../../src/runtime/linklib ${RUNTIME_LIBS}	\
	${LIBS}
LD = ${OBJC}







<
<
<
<















|
<
<

42
43
44
45
46
47
48




49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64


65
		${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_LIBRARY_PATH=.$${DYLD_LIBRARY_PATH+:}$$DYLD_LIBRARY_PATH \
	LIBRARY_PATH=.$${LIBRARY_PATH+:}$$LIBRARY_PATH \
	${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

CPPFLAGS += -I../../src -I../../src/runtime -I../..
LIBS := -L../../src -lobjfw -L../../src/runtime ${RUNTIME_LIBS} ${LIBS}


LD = ${OBJC}

Modified tests/objc_sync/test.m from [1f28b08c51] to [a804725d48].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified tests/plugin/TestPlugin.h from [2f9aa9b796] to [0bf4ece135].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified tests/plugin/TestPlugin.m from [5616dbe160] to [f9d32844b0].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Deleted tests/serialization.xml version [ea3d1a36ad].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
<?xml version='1.0' encoding='UTF-8'?>
<serialization xmlns='https://objfw.nil.im/serialization' version='1'>
  <OFMutableDictionary>
    <key>
      <OFUUID>01234567-89ab-cdef-fedc-ba9876543210</OFUUID>
    </key>
    <object>
      <OFString>uuid</OFString>
    </object>
    <key>
      <OFString>Blub</OFString>
    </key>
    <object>
      <OFString>B&quot;la</OFString>
    </object>
    <key>
      <OFList>
        <OFString>Hello</OFString>
        <OFString>Wo&#xD;ld!
How are you?</OFString>
        <OFURI>https://objfw.nil.im/</OFURI>
        <OFXMLElement name='x'>
          <children>
            <OFMutableArray>
              <OFXMLElement name='y'/>
              <OFXMLCDATA><![CDATA[<]]></OFXMLCDATA>
            </OFMutableArray>
          </children>
        </OFXMLElement>
        <OFSet>
          <OFString>bar</OFString>
          <OFString>foo</OFString>
        </OFSet>
        <OFCountedSet>
          <object count='1'>
            <OFString>bar</OFString>
          </object>
          <object count='2'>
            <OFString>foo</OFString>
          </object>
        </OFCountedSet>
      </OFList>
    </key>
    <object>
      <OFString>list</OFString>
    </object>
    <key>
      <OFData>MDEyMzQ1Njc4OTo7PEFCQ0RFRkdISklLTE1OT1BRUlNUVVZXWFla</OFData>
    </key>
    <object>
      <OFString>data</OFString>
    </object>
    <key>
      <OFArray>
        <OFString>Qu&quot;xbar
test</OFString>
        <OFNumber type='signed'>1234</OFNumber>
        <OFNumber type='float'>40934a456d5cfaad</OFNumber>
        <OFMutableString>asd</OFMutableString>
        <OFDate encoding='hex'>40934a456d5cfaad</OFDate>
      </OFArray>
    </key>
    <object>
      <OFString>Hello</OFString>
    </object>
  </OFMutableDictionary>
</serialization>
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<






































































































































Modified tests/terminal/Makefile from [e8770b0b9b] to [6ef6cabc1b].

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
	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
	rm -f ${OBJFWRT_AMIGA_LIB}
	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}; \







<







10
11
12
13
14
15
16

17
18
19
20
21
22
23
	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}; \
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
		${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
	if test -f ../../src/runtime/${OBJFWRT_AMIGA_LIB}; then \
		${LN_S} ../../src/runtime/${OBJFWRT_AMIGA_LIB} \
		    ${OBJFWRT_AMIGA_LIB}; \
	fi
	LD_LIBRARY_PATH=.$${LD_LIBRARY_PATH+:}$$LD_LIBRARY_PATH \
	DYLD_LIBRARY_PATH=.$${DYLD_LIBRARY_PATH+:}$$DYLD_LIBRARY_PATH \
	LIBRARY_PATH=.$${LIBRARY_PATH+:}$$LIBRARY_PATH \
	${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

CPPFLAGS += -I../../src -I../../src/exceptions -I../../src/runtime -I../..
LIBS := -L../../src -lobjfw						\
	-L../../src/runtime -L../../src/runtime/linklib ${RUNTIME_LIBS}	\
	${LIBS}
LD = ${OBJC}







<
<
<
<















|
<
<

42
43
44
45
46
47
48




49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64


65
		${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_LIBRARY_PATH=.$${DYLD_LIBRARY_PATH+:}$$DYLD_LIBRARY_PATH \
	LIBRARY_PATH=.$${LIBRARY_PATH+:}$$LIBRARY_PATH \
	${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

CPPFLAGS += -I../../src -I../../src/exceptions -I../../src/runtime -I../..
LIBS := -L../../src -lobjfw -L../../src/runtime ${RUNTIME_LIBS} ${LIBS}


LD = ${OBJC}

Modified tests/terminal/TerminalTests.m from [695364c6d5] to [17ab7e7ff5].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

@interface TerminalTests: OFObject <OFApplicationDelegate>
@end

OF_APPLICATION_DELEGATE(TerminalTests)

@implementation TerminalTests
- (void)applicationDidFinishLaunching
{
	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];







|







23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

@interface TerminalTests: OFObject <OFApplicationDelegate>
@end

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];

Modified utils/Makefile from [d5d46e8aaf] to [66810ae4c9].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
include ../extra.mk

SUBDIRS += ${OBJFW_NEW}	\
	   ${OFARC}	\
	   ${OFDNS}	\
	   ${OFHASH}	\
	   ${OFHTTP}	\
	   completions

include ../buildsys.mk

DISTCLEAN = objfw-config

install-extra: objfw-config objfw-compile objfw-embed
	for i in objfw-config objfw-compile objfw-embed; do \


|
|
|
|
|
<







1
2
3
4
5
6
7

8
9
10
11
12
13
14
include ../extra.mk

SUBDIRS += ${OBJFW_NEW}		\
	   ${OFARC}		\
	   ${OFDNS}		\
	   ${OFHASH}		\
	   ${OFHTTP}


include ../buildsys.mk

DISTCLEAN = objfw-config

install-extra: objfw-config objfw-compile objfw-embed
	for i in objfw-config objfw-compile objfw-embed; do \

Deleted utils/completions/Makefile version [53ed45f23f].

1
2
3
4
5
include ../../extra.mk

SUBDIRS = ${FISH_COMPLETIONS}

include ../../buildsys.mk
<
<
<
<
<










Deleted utils/completions/fish/Makefile version [6569e87046].

1
2
3
4
5
6
7
8
9
10
DATA = objfw-compile.fish	\
       objfw-config.fish	\
       ofarc.fish		\
       ofdns.fish		\
       ofhash.fish		\
       ofhttp.fish

include ../../../buildsys.mk

PACKAGE_NAME = fish/vendor_completions.d
<
<
<
<
<
<
<
<
<
<




















Deleted utils/completions/fish/objfw-compile.fish version [e113a8c395].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
complete -c objfw-compile -s o -x -d 'Specify the output name (not file name!)'
complete -c objfw-compile -l arc -d 'Use automatic reference counting'
complete -c objfw-compile -l lib -x -d \
    'Compile a library (with the specified version) instead of an application'
complete -c objfw-compile -l plugin \
    -d 'Compile a plugin instead of an application'
complete -c objfw-compile -l package -x -d 'Use the specified package'
complete -c objfw-compile -l builddir -r \
    -d 'Place built objects into the specified directory'
complete -c objfw-compile -s D -x -d 'Pass the specified define to the compiler'
complete -c objfw-compile -o framework -x \
    -d 'Pass the specified -framework argument to the linker (macOS / iOS only)'
# -f* cannot be represented.
complete -c objfw-compile -s F -x \
    -d 'Pass the specified -F flag to the linker (macOS / iOS only)'
# -g* cannot be represented.
complete -c objfw-compile -s I -x \
    -d 'Pass the specified -I flag to the compiler'
complete -c objfw-compile -s l -x -d 'Pass the specified -l flag to the linker'
complete -c objfw-compile -s L -x -d 'Pass the specified -L flag to the linker'
# -m* cannot be represented.
# -O* cannot be represented.
complete -c objfw-compile -o pthread \
    -d 'Pass -pthread to the compiler and linker'
# -std=* cannot be represented.
# -Wl,* cannot be represented.
# -W* cannot be represented.
complete -c objfw-compile -l help -d 'Show this help'
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
























































Deleted utils/completions/fish/objfw-config.fish version [a2dae654a7].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
complete -c objfw-config -l all -d 'Outputs all flags + libs'
complete -c objfw-config -l arc -d 'Outputs the required OBJCFLAGS to use ARC'
complete -c objfw-config -l cflags -d 'Outputs the required CFLAGS'
complete -c objfw-config -l cppflags -d 'Outputs the required CPPFLAGS'
complete -c objfw-config -l cxxflags -d 'Outputs the required CXXFLAGS'
complete -c objfw-config -l framework-libs \
    -d 'Outputs the required LIBS, preferring frameworks'
complete -c objfw-config -l help -d 'Print help'
complete -c objfw-config -l ldflags -d 'Outputs the required LDFLAGS'
complete -c objfw-config -l libs -d 'Outputs the required LIBS'
complete -c objfw-config -l lib-cflags \
    -d 'Outputs CFLAGS for building a library'
complete -c objfw-config -l lib-ldflags \
    -d 'Outputs LDFLAGS for building a library'
complete -c objfw-config -l lib-prefix -d 'Outputs the prefix for libraries'
complete -c objfw-config -l lib-suffix -d 'Outputs the suffix for libraries'
complete -c objfw-config -l objc -d 'Outputs the OBJC used to compile ObjFW'
complete -c objfw-config -l objcflags -d 'Outputs the required OBJCFLAGS'
complete -c objfw-config -l package -x \
    -d 'Additionally outputs the flags for the specified package'
complete -c objfw-config -l packages-dir \
    -d 'Outputs the directory where flags for packages are stored'
complete -c objfw-config -l plugin-cflags \
    -d 'Outputs CFLAGS for building a plugin'
complete -c objfw-config -l plugin-ldflags \
    -d 'Outputs LDFLAGS for building a plugin'
complete -c objfw-config -l plugin-suffix -d 'Outputs the suffix for plugins'
complete -c objfw-config -l prog-suffix -d 'Outputs the suffix for binaries'
complete -c objfw-config -l reexport -d 'Outputs LDFLAGS to reexport ObjFW'
complete -c objfw-config -l rpath -d 'Outputs LDFLAGS for using rpath'
complete -c objfw-config -l static-libs \
    -d 'Outputs the required LIBS to link ObjFW statically'
complete -c objfw-config -l version -d 'Outputs the installed version'
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<


































































Deleted utils/completions/fish/ofarc.fish version [1ed287a4cf].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
complete -c ofarc -s a -l append -d 'Append to archive'
complete -c ofarc -s c -l create -d 'Create archive'
complete -c ofarc -s C -l directory -r -d 'Extract into the specified directory'
complete -c ofarc -s E -l encoding -x \
    -d 'The encoding used by the archive (only tar files)'
complete -c ofarc -s f -l force -d 'Force / overwrite files'
complete -c ofarc -s h -l help -d 'Show help'
complete -c ofarc -s l -l list -d 'List all files in the archive'
complete -c ofarc -s n -l no-clobber -d 'Never overwrite files'
complete -c ofarc -s p -l print -d 'Print one or more files from the archive'
complete -c ofarc -s q -l quiet -d 'Quiet mode (no output, except errors)'
complete -c ofarc -s t -l type -x -a 'gz lha tar tgz zip' -d 'Archive type'
complete -c ofarc -s v -l verbose -d 'Verbose output for file list'
complete -c ofarc -s x -l extract -d 'Extract files'
<
<
<
<
<
<
<
<
<
<
<
<
<
<




























Deleted utils/completions/fish/ofdns.fish version [5080d1ffbb].

1
2
3
4
5
complete -c ofdns -s c -l class -x -d 'The DNS class to query (defaults to IN)'
complete -c ofdns -s h -l help -d 'Show help'
complete -c ofdns -s s -l server -x -d 'The server to query'
complete -c ofdns -s t -l type -x \
    -d 'The record type to query (defaults to ALL, can be repeated)'
<
<
<
<
<










Deleted utils/completions/fish/ofhash.fish version [ffdc6cdbcf].

1
2
3
4
5
6
7
complete -c ofhash --long-option md5
complete -c ofhash --long-option ripemd160
complete -c ofhash --long-option sha1
complete -c ofhash --long-option sha224
complete -c ofhash --long-option sha256
complete -c ofhash --long-option sha384
complete -c ofhash --long-option sha256
<
<
<
<
<
<
<














Deleted utils/completions/fish/ofhttp.fish version [99fd9b7109].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
complete -c ofhttp -x
complete -c ofhttp -s b -l body -r -d 'Specify the file to send as body'
complete -c ofhttp -s c -l continue -d 'Continue download of existing file'
complete -c ofhttp -s f -l force -d 'Force / overwrite existing file'
complete -c ofhttp -s h -l help -d 'Show help'
complete -c ofhttp -s H -l header -x -d 'Add a header (e.g. X-Foo:Bar)'
complete -c ofhttp -s m -l method -x -d 'Set the method of the HTTP request'
complete -c ofhttp -s o -l output -r -d 'Specify output file name'
complete -c ofhttp -s O -l detect-filename \
    -d 'Do a HEAD request to detect the file name'
complete -c ofhttp -s P -l proxy -x -d 'Specify SOCKS5 proxy'
complete -c ofhttp -s q -l quiet -d 'Quiet mode (no output, except errors)'
complete -c ofhttp -s v -l verbose -d 'Verbose mode (print headers)'
complete -c ofhttp -l insecure \
    -d 'Ignore TLS errors and allow insecure redirects'
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<






























Modified utils/objfw-compile from [ffd05ad528] to [300a1e1b6b].

1
2
3
4
5
6
7
8
9
10
#!/bin/sh
#
#  Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
#
#  All rights reserved.
#
#  This file is part of ObjFW. It may be distributed under the terms of the
#  Q Public License 1.0, which can be found in the file LICENSE.QPL included in
#  the packaging of this file.
#


|







1
2
3
4
5
6
7
8
9
10
#!/bin/sh
#
#  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.
#

Modified utils/objfw-config.in from [c7e6aa0918] to [37efdb4540].

1
2
3
4
5
6
7
8
9
10
#!/bin/sh
#
#  Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
#
#  All rights reserved.
#
#  This file is part of ObjFW. It may be distributed under the terms of the
#  Q Public License 1.0, which can be found in the file LICENSE.QPL included in
#  the packaging of this file.
#


|







1
2
3
4
5
6
7
8
9
10
#!/bin/sh
#
#  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.
#

Modified utils/objfw-embed from [b832fbf4cf] to [9ca9ee2bd1].

1
2
3
4
5
6
7
8
9
10
11
12

13



14
15
16
17
18
19
20
21
22
23
24
25
26
#!/bin/sh
if test $# != 3; then
	echo "Usage: $0 source_file filename output.m" 1>&2
	exit 1
fi

exec 1>$3

cat <<EOF
#include <stddef.h>
#include <stdint.h>


extern void OFRegisterEmbeddedFile(const char *, const uint8_t *, size_t);




static const uint8_t bytes[] = {
EOF
od -vtx1 $1 | sed -e '/^[^ ][^ ]*$/d;s/  */ /g' -e 's/ $//g;s/^[^ ][^ ]* //' -e 's/ /, 0x/g' -e 's/^/	0x/' -e 's/$/,/'
cat <<EOF
};

static void __attribute__((__constructor__))
ctor(void)
{
	OFRegisterEmbeddedFile("$2", bytes, sizeof(bytes));
}
EOF












>
|
>
>
>










|


1
2
3
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
#!/bin/sh
if test $# != 3; then
	echo "Usage: $0 source_file filename output.m" 1>&2
	exit 1
fi

exec 1>$3

cat <<EOF
#include <stddef.h>
#include <stdint.h>

#ifdef OF_COMPILING_OBJFW
# import "OFEmbeddedIRIHandler.h"
#else
# import <ObjFW/OFEmbeddedIRIHandler.h>
#endif

static const uint8_t bytes[] = {
EOF
od -vtx1 $1 | sed -e '/^[^ ][^ ]*$/d;s/  */ /g' -e 's/ $//g;s/^[^ ][^ ]* //' -e 's/ /, 0x/g' -e 's/^/	0x/' -e 's/$/,/'
cat <<EOF
};

static void __attribute__((__constructor__))
ctor(void)
{
	OFRegisterEmbeddedFile(@"$2", bytes, sizeof(bytes));
}
EOF

Modified utils/objfw-new/Makefile from [fe068759c6] to [b67c1400ab].

10
11
12
13
14
15
16
17
18
19
20
21

${PROG}: ${LIBOBJFW_DEP_LVL2} ${LIBOBJFWRT_DEP_LVL2}

CPPFLAGS += -I../../src					\
	    -I../../src/runtime				\
	    -I../../src/exceptions			\
	    -I../..
LIBS := -L../../src -lobjfw						\
	-L../../src/runtime -L../../src/runtime/linklib ${RUNTIME_LIBS}	\
	${LIBS}
LD = ${OBJC}
LDFLAGS += ${LDFLAGS_RPATH}







|
<
<


10
11
12
13
14
15
16
17


18
19

${PROG}: ${LIBOBJFW_DEP_LVL2} ${LIBOBJFWRT_DEP_LVL2}

CPPFLAGS += -I../../src					\
	    -I../../src/runtime				\
	    -I../../src/exceptions			\
	    -I../..
LIBS := -L../../src -lobjfw -L../../src/runtime ${RUNTIME_LIBS} ${LIBS}


LD = ${OBJC}
LDFLAGS += ${LDFLAGS_RPATH}

Modified utils/objfw-new/NewApp.m from [a817ca083b] to [88fad54d0b].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
44
45
46
47
48
49
50
51

52
53
54
55
56
57
58
59
			   @"\n"
			   @"@interface %@: OFObject <OFApplicationDelegate>\n"
			   @"@end\n"
			   @"\n"
			   @"OF_APPLICATION_DELEGATE(%@)\n"
			   @"\n"
			   @"@implementation %@\n"
			   @"- (void)applicationDidFinishLaunching\n"

			   @"{\n"
			   @"	[OFApplication terminate];\n"
			   @"}\n"
			   @"@end\n",
			   name, name, name];

	[file close];
}







|
>








44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
			   @"\n"
			   @"@interface %@: OFObject <OFApplicationDelegate>\n"
			   @"@end\n"
			   @"\n"
			   @"OF_APPLICATION_DELEGATE(%@)\n"
			   @"\n"
			   @"@implementation %@\n"
			   @"- (void)applicationDidFinishLaunching: "
			   @"(OFNotification *)notification\n"
			   @"{\n"
			   @"	[OFApplication terminate];\n"
			   @"}\n"
			   @"@end\n",
			   name, name, name];

	[file close];
}

Modified utils/objfw-new/NewClass.m from [13b11d77d3] to [5021124a18].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified utils/objfw-new/ObjFWNew.m from [efa3835453] to [5f604351d2].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
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

extern void newApp(OFString *);
extern void newClass(OFString *, OFString *, OFMutableArray *);

OF_APPLICATION_DELEGATE(ObjFWNew)

static void
showUsage(void)
{

	[OFStdErr writeFormat: @"Usage: %@ --app|--class name\n",
			       [OFApplication programName]];















	[OFApplication terminateWithStatus: 1];
}

@implementation ObjFWNew
- (void)applicationDidFinishLaunching
{
	bool app, class;
	OFString *superclass = nil, *name;
	OFMutableArray OF_GENERIC(OFString *) *properties = nil;
	const OFOptionsParserOption options[] = {
		{ 'a', @"app", 0, &app, NULL },
		{ 'c', @"class", 0, &class, NULL },

		{ 's', @"superclass", 1, NULL, &superclass },
		{ 'p', @"property", 1, NULL, NULL },
		{ '\0', nil, 0, NULL, NULL }
	};
	OFOptionsParser *optionsParser;
	OFUnichar option;




	optionsParser = [OFOptionsParser parserWithOptions: options];
	while ((option = [optionsParser nextOption]) != '\0') {
		switch (option) {



		case 'p':
			if (properties == nil)
				properties = [OFMutableArray array];

			[properties addObject: optionsParser.argument];
			break;
		case '?':
		case ':':
		case '=':
			showUsage();
			break;
		}
	}

	if ((app ^ class) != 1 || optionsParser.remainingArguments.count != 1)
		showUsage();

	if ((superclass && !class)  || (properties != nil && !class))
		showUsage();

	name = optionsParser.remainingArguments.firstObject;
	if ([name rangeOfString: @"."].location != OFNotFound) {
		[OFStdErr writeLine: @"Name must not contain dots!"];
		[OFApplication terminate];
	}

	if (app)
		newApp(name);
	else if (class)
		newClass(name, superclass, properties);
	else
		showUsage();

	[OFApplication terminate];
}
@end







|

>
|
|

>
>
>
>
>
>
>
>
>
>
>
>
>
>
|



|







>






>
>
>




>
>
>









|





|


|












|




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

extern void newApp(OFString *);
extern void newClass(OFString *, OFString *, OFMutableArray *);

OF_APPLICATION_DELEGATE(ObjFWNew)

static void
help(OFStream *stream, bool full, int status)
{
	[stream writeFormat:
	    @"Usage: %@ --app|--class [--superclass=] [--property=] name\n",
	    [OFApplication programName]];

	if (full) {
		[stream writeString: @"\n"];
		[stream writeLine:
		    @"Options:\n"
		    @"    -a  --app          Create a new app\n"
		    @"    -c  --class        Create a new class\n"
		    @"    -h  --help         Show this help\n"
		    @"    -s  --superclass=  Specify the superclass for the "
		    @"class\n"
		    @"    -p  --property=    Add a property to the class.\n"
		    @"                       E.g.: --property='(readonly, "
		    @"nonatomic) id foo'"];
	}

	[OFApplication terminateWithStatus: status];
}

@implementation ObjFWNew
- (void)applicationDidFinishLaunching: (OFNotification *)notification
{
	bool app, class;
	OFString *superclass = nil, *name;
	OFMutableArray OF_GENERIC(OFString *) *properties = nil;
	const OFOptionsParserOption options[] = {
		{ 'a', @"app", 0, &app, NULL },
		{ 'c', @"class", 0, &class, NULL },
		{ 'h', @"help", 0, NULL, NULL },
		{ 's', @"superclass", 1, NULL, &superclass },
		{ 'p', @"property", 1, NULL, NULL },
		{ '\0', nil, 0, NULL, NULL }
	};
	OFOptionsParser *optionsParser;
	OFUnichar option;

	if ([OFApplication arguments].count == 0)
		help(OFStdErr, true, 1);

	optionsParser = [OFOptionsParser parserWithOptions: options];
	while ((option = [optionsParser nextOption]) != '\0') {
		switch (option) {
		case 'h':
			help(OFStdOut, true, 0);
			break;
		case 'p':
			if (properties == nil)
				properties = [OFMutableArray array];

			[properties addObject: optionsParser.argument];
			break;
		case '?':
		case ':':
		case '=':
			help(OFStdErr, false, 1);
			break;
		}
	}

	if ((app ^ class) != 1 || optionsParser.remainingArguments.count != 1)
		help(OFStdErr, false, 1);

	if ((superclass && !class)  || (properties != nil && !class))
		help(OFStdErr, false, 1);

	name = optionsParser.remainingArguments.firstObject;
	if ([name rangeOfString: @"."].location != OFNotFound) {
		[OFStdErr writeLine: @"Name must not contain dots!"];
		[OFApplication terminate];
	}

	if (app)
		newApp(name);
	else if (class)
		newClass(name, superclass, properties);
	else
		help(OFStdErr, false, 1);

	[OFApplication terminate];
}
@end

Modified utils/objfw-new/Property.h from [e9facd5dfc] to [121b8215f2].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified utils/objfw-new/Property.m from [101e199c45] to [befdefcfcf].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified utils/ofarc/Archive.h from [c57fe80fee] to [7732f848c0].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19


20

21
22
23

24
25
26
27
28
29
30
31
32


/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#import "OFObject.h"
#import "OFFile.h"
#import "OFArray.h"



@protocol Archive <OFObject>

+ (instancetype)archiveWithStream: (OF_KINDOF(OFStream *))stream
			     mode: (OFString *)mode
			 encoding: (OFStringEncoding)encoding;

- (instancetype)initWithStream: (OF_KINDOF(OFStream *))stream
			  mode: (OFString *)mode
		      encoding: (OFStringEncoding)encoding;
- (void)listFiles;
- (void)extractFiles: (OFArray OF_GENERIC(OFString *) *)files;
- (void)printFiles: (OFArray OF_GENERIC(OFString *) *)files;
@optional
- (void)addFiles: (OFArray OF_GENERIC(OFString *) *)files;
@end



|

















>
>

>
|
|
|
>
|
|
|






>
>
1
2
3
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 "OFObject.h"
#import "OFFile.h"
#import "OFArray.h"

OF_ASSUME_NONNULL_BEGIN

@protocol Archive <OFObject>
+ (instancetype)archiveWithPath: (nullable OFString *)path
			 stream: (OF_KINDOF(OFStream *))stream
			   mode: (OFString *)mode
		       encoding: (OFStringEncoding)encoding;
- (instancetype)initWithPath: (nullable OFString *)path
		      stream: (OF_KINDOF(OFStream *))stream
			mode: (OFString *)mode
		    encoding: (OFStringEncoding)encoding;
- (void)listFiles;
- (void)extractFiles: (OFArray OF_GENERIC(OFString *) *)files;
- (void)printFiles: (OFArray OF_GENERIC(OFString *) *)files;
@optional
- (void)addFiles: (OFArray OF_GENERIC(OFString *) *)files;
@end

OF_ASSUME_NONNULL_END

Modified utils/ofarc/GZIPArchive.h from [384191029a] to [d84167dde2].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified utils/ofarc/GZIPArchive.m from [2e682cb46c] to [ae6bbc1f46].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
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
@implementation GZIPArchive
+ (void)initialize
{
	if (self == [GZIPArchive class])
		app = (OFArc *)[OFApplication sharedApplication].delegate;
}


+ (instancetype)archiveWithStream: (OF_KINDOF(OFStream *))stream
			     mode: (OFString *)mode
			 encoding: (OFStringEncoding)encoding
{
	return [[[self alloc] initWithStream: stream

					mode: mode
				    encoding: encoding] autorelease];
}


- (instancetype)initWithStream: (OF_KINDOF(OFStream *))stream
			  mode: (OFString *)mode
		      encoding: (OFStringEncoding)encoding
{
	self = [super init];

	@try {
		_stream = [[OFGZIPStream alloc] initWithStream: stream
							  mode: mode];
	} @catch (id e) {







>
|
|
|

|
>
|
|


>
|
|
|







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
@implementation GZIPArchive
+ (void)initialize
{
	if (self == [GZIPArchive class])
		app = (OFArc *)[OFApplication sharedApplication].delegate;
}

+ (instancetype)archiveWithPath: (OFString *)path
			 stream: (OF_KINDOF(OFStream *))stream
			   mode: (OFString *)mode
		       encoding: (OFStringEncoding)encoding
{
	return [[[self alloc] initWithPath: path
				    stream: stream
				      mode: mode
				  encoding: encoding] autorelease];
}

- (instancetype)initWithPath: (OFString *)path
		      stream: (OF_KINDOF(OFStream *))stream
			mode: (OFString *)mode
		    encoding: (OFStringEncoding)encoding
{
	self = [super init];

	@try {
		_stream = [[OFGZIPStream alloc] initWithStream: stream
							  mode: mode];
	} @catch (id e) {
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122

- (void)extractFiles: (OFArray OF_GENERIC(OFString *) *)files
{
	OFString *fileName;
	OFFile *output;

	if (files.count != 0) {
		[OFStdErr writeLine:
		    OF_LOCALIZED(@"cannot_extract_specific_file_from_gz",
		    @"Cannot extract a specific file of a .gz archive!")];
		app->_exitStatus = 1;
		return;
	}

	fileName = app->_archivePath.lastPathComponent
	    .stringByDeletingPathExtension;







|
|







110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125

- (void)extractFiles: (OFArray OF_GENERIC(OFString *) *)files
{
	OFString *fileName;
	OFFile *output;

	if (files.count != 0) {
		[OFStdErr writeLine: OF_LOCALIZED(
		    @"cannot_extract_specific_file_from_gz",
		    @"Cannot extract a specific file of a .gz archive!")];
		app->_exitStatus = 1;
		return;
	}

	fileName = app->_archivePath.lastPathComponent
	    .stringByDeletingPathExtension;

Modified utils/ofarc/LHAArchive.h from [5ad6942309] to [d40b544100].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified utils/ofarc/LHAArchive.m from [7f7a619844] to [0bf9a4ae71].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16


17
18
19
20
21
22
23
24
25
26
27
28


29
30
31
32
33
34
35
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"



#import "OFApplication.h"
#import "OFDate.h"
#import "OFFileManager.h"
#import "OFLocale.h"
#import "OFNumber.h"
#import "OFSet.h"
#import "OFStdIOStream.h"
#import "OFString.h"

#import "LHAArchive.h"
#import "OFArc.h"



static OFArc *app;

static OFString *
indent(OFString *string)
{
	return [string stringByReplacingOccurrencesOfString: @"\n"

|














>
>












>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
/*
 * Copyright (c) 2008-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 <errno.h>

#import "OFApplication.h"
#import "OFDate.h"
#import "OFFileManager.h"
#import "OFLocale.h"
#import "OFNumber.h"
#import "OFSet.h"
#import "OFStdIOStream.h"
#import "OFString.h"

#import "LHAArchive.h"
#import "OFArc.h"

#import "OFSetItemAttributesFailedException.h"

static OFArc *app;

static OFString *
indent(OFString *string)
{
	return [string stringByReplacingOccurrencesOfString: @"\n"
59
60
61
62
63
64
65

66
67




68
69
70
71
72
73
74
75
76

77
78
79
80
81

82
83
84
85

86
87
88
89
90
91
92
93
94
95

static void
setModificationDate(OFString *path, OFLHAArchiveEntry *entry)
{
	OFFileAttributes attributes = [OFDictionary
	    dictionaryWithObject: entry.modificationDate
			  forKey: OFFileModificationDate];

	[[OFFileManager defaultManager] setAttributes: attributes
					 ofItemAtPath: path];




}

@implementation LHAArchive
+ (void)initialize
{
	if (self == [LHAArchive class])
		app = (OFArc *)[OFApplication sharedApplication].delegate;
}


+ (instancetype)archiveWithStream: (OF_KINDOF(OFStream *))stream
			     mode: (OFString *)mode
			 encoding: (OFStringEncoding)encoding
{
	return [[[self alloc] initWithStream: stream

					mode: mode
				    encoding: encoding] autorelease];
}


- (instancetype)initWithStream: (OF_KINDOF(OFStream *))stream
			  mode: (OFString *)mode
		      encoding: (OFStringEncoding)encoding
{
	self = [super init];

	@try {
		_archive = [[OFLHAArchive alloc] initWithStream: stream
							   mode: mode];








>
|
|
>
>
>
>









>
|
|
|

|
>
|
|


>
|
|
|







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

static void
setModificationDate(OFString *path, OFLHAArchiveEntry *entry)
{
	OFFileAttributes attributes = [OFDictionary
	    dictionaryWithObject: entry.modificationDate
			  forKey: OFFileModificationDate];
	@try {
		[[OFFileManager defaultManager] setAttributes: attributes
						 ofItemAtPath: path];
	} @catch (OFSetItemAttributesFailedException *e) {
		if (e.errNo != EISDIR)
			@throw e;
	}
}

@implementation LHAArchive
+ (void)initialize
{
	if (self == [LHAArchive class])
		app = (OFArc *)[OFApplication sharedApplication].delegate;
}

+ (instancetype)archiveWithPath: (OFString *)path
			 stream: (OF_KINDOF(OFStream *))stream
			   mode: (OFString *)mode
		       encoding: (OFStringEncoding)encoding
{
	return [[[self alloc] initWithPath: path
				    stream: stream
				      mode: mode
				  encoding: encoding] autorelease];
}

- (instancetype)initWithPath: (OFString *)path
		      stream: (OF_KINDOF(OFStream *))stream
			mode: (OFString *)mode
		    encoding: (OFStringEncoding)encoding
{
	self = [super init];

	@try {
		_archive = [[OFLHAArchive alloc] initWithStream: stream
							   mode: mode];

Modified utils/ofarc/Makefile from [482a60034a] to [75fcfbcaa1].

16
17
18
19
20
21
22
23
24
25
26
27
${PROG}: ${LIBOBJFW_DEP_LVL2} ${LIBOBJFWRT_DEP_LVL2}

CPPFLAGS += -I../../src							\
	    -I../../src/runtime						\
	    -I../../src/exceptions					\
	    -I../..							\
	    -DLOCALIZATION_DIR=\"${datadir}/ofarc/localization\"
LIBS := -L../../src -lobjfw						\
	-L../../src/runtime -L../../src/runtime/linklib ${RUNTIME_LIBS}	\
	${LIBS}
LD = ${OBJC}
LDFLAGS += ${LDFLAGS_RPATH}







|
<
<


16
17
18
19
20
21
22
23


24
25
${PROG}: ${LIBOBJFW_DEP_LVL2} ${LIBOBJFWRT_DEP_LVL2}

CPPFLAGS += -I../../src							\
	    -I../../src/runtime						\
	    -I../../src/exceptions					\
	    -I../..							\
	    -DLOCALIZATION_DIR=\"${datadir}/ofarc/localization\"
LIBS := -L../../src -lobjfw -L../../src/runtime ${RUNTIME_LIBS} ${LIBS}


LD = ${OBJC}
LDFLAGS += ${LDFLAGS_RPATH}

Modified utils/ofarc/OFArc.h from [926be48eea] to [919560b647].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified utils/ofarc/OFArc.m from [92125fd380] to [ae84a3168a].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
17
18
19
20
21
22
23

24
25
26
27
28
29
30
31
32
33
34
35

#include <string.h>

#import "OFApplication.h"
#import "OFArray.h"
#import "OFFile.h"
#import "OFFileManager.h"

#import "OFLocale.h"
#import "OFOptionsParser.h"
#import "OFSandbox.h"
#import "OFStdIOStream.h"
#import "OFURI.h"

#import "OFArc.h"
#import "GZIPArchive.h"
#import "LHAArchive.h"
#import "TarArchive.h"
#import "ZIPArchive.h"








>




<







17
18
19
20
21
22
23
24
25
26
27
28

29
30
31
32
33
34
35

#include <string.h>

#import "OFApplication.h"
#import "OFArray.h"
#import "OFFile.h"
#import "OFFileManager.h"
#import "OFIRI.h"
#import "OFLocale.h"
#import "OFOptionsParser.h"
#import "OFSandbox.h"
#import "OFStdIOStream.h"


#import "OFArc.h"
#import "GZIPArchive.h"
#import "LHAArchive.h"
#import "TarArchive.h"
#import "ZIPArchive.h"

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

	if (full) {
		[stream writeString: @"\n"];
		[stream writeLine: OF_LOCALIZED(@"full_usage",
		    @"Options:\n"
		    @"    -a  --append      Append to archive\n"
		    @"    -c  --create      Create archive\n"
		    @"    -C  --directory   Extract into the specified "
		    @"directory\n"
		    @"    -E  --encoding    The encoding used by the archive "
		    "(only tar files)\n"
		    @"    -f  --force       Force / overwrite files\n"
		    @"    -h  --help        Show this help\n"
		    @"    -l  --list        List all files in the archive\n"
		    @"    -n  --no-clobber  Never overwrite files\n"
		    @"    -p  --print       Print one or more files from the "
		    @"archive\n"
		    @"    -q  --quiet       Quiet mode (no output, except "
		    @"errors)\n"
		    @"    -t  --type        Archive type (gz, lha, tar, tgz, "
		    @"zip)\n"
		    @"    -v  --verbose     Verbose output for file list\n"
		    @"    -x  --extract     Extract files")];
	}

	[OFApplication terminateWithStatus: status];
}







|

|









|







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

	if (full) {
		[stream writeString: @"\n"];
		[stream writeLine: OF_LOCALIZED(@"full_usage",
		    @"Options:\n"
		    @"    -a  --append      Append to archive\n"
		    @"    -c  --create      Create archive\n"
		    @"    -C  --directory=  Extract into the specified "
		    @"directory\n"
		    @"    -E  --encoding=   The encoding used by the archive "
		    "(only tar files)\n"
		    @"    -f  --force       Force / overwrite files\n"
		    @"    -h  --help        Show this help\n"
		    @"    -l  --list        List all files in the archive\n"
		    @"    -n  --no-clobber  Never overwrite files\n"
		    @"    -p  --print       Print one or more files from the "
		    @"archive\n"
		    @"    -q  --quiet       Quiet mode (no output, except "
		    @"errors)\n"
		    @"    -t  --type=       Archive type (gz, lha, tar, tgz, "
		    @"zip)\n"
		    @"    -v  --verbose     Verbose output for file list\n"
		    @"    -x  --extract     Extract files")];
	}

	[OFApplication terminateWithStatus: status];
}
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
			[expandedFiles addObject: file];
	}

	[archive addFiles: expandedFiles];
}

@implementation OFArc
- (void)applicationDidFinishLaunching
{
	OFString *outputDir, *encodingString, *type;
	const OFOptionsParserOption options[] = {
		{ 'a', @"append", 0, NULL, NULL },
		{ 'c', @"create", 0, NULL, NULL },
		{ 'C', @"directory", 1, NULL, &outputDir },
		{ 'E', @"encoding", 1, NULL, &encodingString },







|







163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
			[expandedFiles addObject: file];
	}

	[archive addFiles: expandedFiles];
}

@implementation OFArc
- (void)applicationDidFinishLaunching: (OFNotification *)notification
{
	OFString *outputDir, *encodingString, *type;
	const OFOptionsParserOption options[] = {
		{ 'a', @"append", 0, NULL, NULL },
		{ 'c', @"create", 0, NULL, NULL },
		{ 'C', @"directory", 1, NULL, &outputDir },
		{ 'E', @"encoding", 1, NULL, &encodingString },
203
204
205
206
207
208
209
210

211
212
213
214
215
216
217
218
219
220
	/* Dropped after parsing options */
	sandbox.allowsUnveil = true;

	[OFApplication of_activateSandbox: sandbox];
#endif

#ifndef OF_AMIGAOS
	[OFLocale addLocalizationDirectory: @LOCALIZATION_DIR];

#else
	[OFLocale addLocalizationDirectory:
	    @"PROGDIR:/share/ofarc/localization"];
#endif

	optionsParser = [OFOptionsParser parserWithOptions: options];
	while ((option = [optionsParser nextOption]) != '\0') {
		switch (option) {
		case 'f':
			if (_overwrite < 0)







|
>

|
|







203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
	/* Dropped after parsing options */
	sandbox.allowsUnveil = true;

	[OFApplication of_activateSandbox: sandbox];
#endif

#ifndef OF_AMIGAOS
	[OFLocale addLocalizationDirectoryIRI:
	    [OFIRI fileIRIWithPath: @LOCALIZATION_DIR]];
#else
	[OFLocale addLocalizationDirectoryIRI:
	    [OFIRI fileIRIWithPath: @"PROGDIR:/share/ofarc/localization"]];
#endif

	optionsParser = [OFOptionsParser parserWithOptions: options];
	while ((option = [optionsParser nextOption]) != '\0') {
		switch (option) {
		case 'f':
			if (_overwrite < 0)
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
			OFString *error = [OFString
			    stringWithCString: strerror(e.errNo)
				     encoding: [OFLocale encoding]];
			[OFStdErr writeString: @"\r"];
			[OFStdErr writeLine: OF_LOCALIZED(
			    @"failed_to_create_directory",
			    @"Failed to create directory %[dir]: %[error]",
			    @"dir", e.URI.fileSystemRepresentation,
			    @"error", error)];
			_exitStatus = 1;
		} @catch (OFOpenItemFailedException *e) {
			OFString *error = [OFString
			    stringWithCString: strerror(e.errNo)
				     encoding: [OFLocale encoding]];
			[OFStdErr writeString: @"\r"];







|







459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
			OFString *error = [OFString
			    stringWithCString: strerror(e.errNo)
				     encoding: [OFLocale encoding]];
			[OFStdErr writeString: @"\r"];
			[OFStdErr writeLine: OF_LOCALIZED(
			    @"failed_to_create_directory",
			    @"Failed to create directory %[dir]: %[error]",
			    @"dir", e.IRI.fileSystemRepresentation,
			    @"error", error)];
			_exitStatus = 1;
		} @catch (OFOpenItemFailedException *e) {
			OFString *error = [OFString
			    stringWithCString: strerror(e.errNo)
				     encoding: [OFLocale encoding]];
			[OFStdErr writeString: @"\r"];
483
484
485
486
487
488
489
490
491
492
493
494


495
496
497
498
499
500
501
		help(OFStdErr, true, 1);
		break;
	}

	[OFApplication terminateWithStatus: _exitStatus];
}

- (id <Archive>)openArchiveWithPath: (OFString *)path
			       type: (OFString *)type
			       mode: (char)mode
			   encoding: (OFStringEncoding)encoding
{


	OFString *modeString, *fileModeString;
	OFStream *file = nil;
	id <Archive> archive = nil;

	[_archivePath release];
	_archivePath = [path copy];








|




>
>







484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
		help(OFStdErr, true, 1);
		break;
	}

	[OFApplication terminateWithStatus: _exitStatus];
}

- (id <Archive>)openArchiveWithPath: (OFString *)path_
			       type: (OFString *)type
			       mode: (char)mode
			   encoding: (OFStringEncoding)encoding
{
	/* To make clang-analyzer happy about assigning nil to path later. */
	OFString *path = path_;
	OFString *modeString, *fileModeString;
	OFStream *file = nil;
	id <Archive> archive = nil;

	[_archivePath release];
	_archivePath = [path copy];

529
530
531
532
533
534
535


536
537
538
539
540
541
542
		case 'p':
		case 'x':
			file = OFStdIn;
			break;
		default:
			@throw [OFInvalidArgumentException exception];
		}


	} else {
		@try {
			file = [OFFile fileWithPath: path mode: fileModeString];
		} @catch (OFOpenItemFailedException *e) {
			OFString *error = [OFString
			    stringWithCString: strerror(e.errNo)
				     encoding: [OFLocale encoding]];







>
>







532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
		case 'p':
		case 'x':
			file = OFStdIn;
			break;
		default:
			@throw [OFInvalidArgumentException exception];
		}

		path = nil;
	} else {
		@try {
			file = [OFFile fileWithPath: path mode: fileModeString];
		} @catch (OFOpenItemFailedException *e) {
			OFString *error = [OFString
			    stringWithCString: strerror(e.errNo)
				     encoding: [OFLocale encoding]];
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
			type = @"tar";
		else
			type = @"zip";
	}

	@try {
		if ([type isEqual: @"gz"])
			archive = [GZIPArchive archiveWithStream: file

							    mode: modeString
							encoding: encoding];
		else if ([type isEqual: @"lha"])
			archive = [LHAArchive archiveWithStream: file

							   mode: modeString
						       encoding: encoding];
		else if ([type isEqual: @"tar"])
			archive = [TarArchive archiveWithStream: file

							   mode: modeString
						       encoding: encoding];
		else if ([type isEqual: @"tgz"]) {
			OFStream *GZIPStream = [OFGZIPStream
			    streamWithStream: file
					mode: modeString];
			archive = [TarArchive archiveWithStream: GZIPStream

							   mode: modeString
						       encoding: encoding];
		} else if ([type isEqual: @"zip"])
			archive = [ZIPArchive archiveWithStream: file

							   mode: modeString
						       encoding: encoding];
		else {
			[OFStdErr writeLine: OF_LOCALIZED(
			    @"unknown_archive_type",
			    @"Unknown archive type: %[type]",
			    @"type", type)];
			goto error;
		}







|
>
|
|

|
>
|
|

|
>
|
|




|
>
|
|

|
>
|
|







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
			type = @"tar";
		else
			type = @"zip";
	}

	@try {
		if ([type isEqual: @"gz"])
			archive = [GZIPArchive archiveWithPath: path
							stream: file
							  mode: modeString
						      encoding: encoding];
		else if ([type isEqual: @"lha"])
			 archive = [LHAArchive archiveWithPath: path
							stream: file
							  mode: modeString
						      encoding: encoding];
		else if ([type isEqual: @"tar"])
			archive = [TarArchive archiveWithPath: path
						       stream: file
							 mode: modeString
						     encoding: encoding];
		else if ([type isEqual: @"tgz"]) {
			OFStream *GZIPStream = [OFGZIPStream
			    streamWithStream: file
					mode: modeString];
			archive = [TarArchive archiveWithPath: path
						       stream: GZIPStream
							 mode: modeString
						     encoding: encoding];
		} else if ([type isEqual: @"zip"])
			archive = [ZIPArchive archiveWithPath: path
						       stream: file
							 mode: modeString
						     encoding: encoding];
		else {
			[OFStdErr writeLine: OF_LOCALIZED(
			    @"unknown_archive_type",
			    @"Unknown archive type: %[type]",
			    @"type", type)];
			goto error;
		}
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
		writingNotSupported(type);
		goto error;
	}

	return archive;

error:
	if (mode == 'c')
		[[OFFileManager defaultManager] removeItemAtPath: path];

	[OFApplication terminateWithStatus: 1];
	return nil;
}

- (bool)shouldExtractFile: (OFString *)fileName
	      outFileName: (OFString *)outFileName
{
	OFString *line;








|



|







645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
		writingNotSupported(type);
		goto error;
	}

	return archive;

error:
	if (mode == 'c' && path != nil)
		[[OFFileManager defaultManager] removeItemAtPath: path];

	[OFApplication terminateWithStatus: 1];
	abort();
}

- (bool)shouldExtractFile: (OFString *)fileName
	      outFileName: (OFString *)outFileName
{
	OFString *line;

Modified utils/ofarc/TarArchive.h from [5ee57845a6] to [c10ec5c88f].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified utils/ofarc/TarArchive.m from [1feea72626] to [5dbe6d6d86].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16


17
18
19
20
21
22
23
24
25
26
27
28


29
30
31
32
33
34
35
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"



#import "OFApplication.h"
#import "OFDate.h"
#import "OFFileManager.h"
#import "OFLocale.h"
#import "OFNumber.h"
#import "OFSet.h"
#import "OFStdIOStream.h"
#import "OFString.h"

#import "TarArchive.h"
#import "OFArc.h"



static OFArc *app;

static void
setPermissions(OFString *path, OFTarArchiveEntry *entry)
{
#ifdef OF_FILE_MANAGER_SUPPORTS_PERMISSIONS

|














>
>












>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
/*
 * Copyright (c) 2008-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 <errno.h>

#import "OFApplication.h"
#import "OFDate.h"
#import "OFFileManager.h"
#import "OFLocale.h"
#import "OFNumber.h"
#import "OFSet.h"
#import "OFStdIOStream.h"
#import "OFString.h"

#import "TarArchive.h"
#import "OFArc.h"

#import "OFSetItemAttributesFailedException.h"

static OFArc *app;

static void
setPermissions(OFString *path, OFTarArchiveEntry *entry)
{
#ifdef OF_FILE_MANAGER_SUPPORTS_PERMISSIONS
52
53
54
55
56
57
58

59
60




61
62
63
64
65
66
67
68
69

70
71
72
73
74

75
76
77
78

79
80
81
82
83
84
85
86
87
88

	if (modificationDate == nil)
		return;

	attributes = [OFDictionary
	    dictionaryWithObject: modificationDate
			  forKey: OFFileModificationDate];

	[[OFFileManager defaultManager] setAttributes: attributes
					 ofItemAtPath: path];




}

@implementation TarArchive
+ (void)initialize
{
	if (self == [TarArchive class])
		app = (OFArc *)[OFApplication sharedApplication].delegate;
}


+ (instancetype)archiveWithStream: (OF_KINDOF(OFStream *))stream
			     mode: (OFString *)mode
			 encoding: (OFStringEncoding)encoding
{
	return [[[self alloc] initWithStream: stream

					mode: mode
				    encoding: encoding] autorelease];
}


- (instancetype)initWithStream: (OF_KINDOF(OFStream *))stream
			  mode: (OFString *)mode
		      encoding: (OFStringEncoding)encoding
{
	self = [super init];

	@try {
		_archive = [[OFTarArchive alloc] initWithStream: stream
							   mode: mode];








>
|
|
>
>
>
>









>
|
|
|

|
>
|
|


>
|
|
|







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

	if (modificationDate == nil)
		return;

	attributes = [OFDictionary
	    dictionaryWithObject: modificationDate
			  forKey: OFFileModificationDate];
	@try {
		[[OFFileManager defaultManager] setAttributes: attributes
						 ofItemAtPath: path];
	} @catch (OFSetItemAttributesFailedException *e) {
		if (e.errNo != EISDIR)
			@throw e;
	}
}

@implementation TarArchive
+ (void)initialize
{
	if (self == [TarArchive class])
		app = (OFArc *)[OFApplication sharedApplication].delegate;
}

+ (instancetype)archiveWithPath: (OFString *)path
			 stream: (OF_KINDOF(OFStream *))stream
			   mode: (OFString *)mode
		       encoding: (OFStringEncoding)encoding
{
	return [[[self alloc] initWithPath: path
				    stream: stream
				      mode: mode
				  encoding: encoding] autorelease];
}

- (instancetype)initWithPath: (OFString *)path
		      stream: (OF_KINDOF(OFStream *))stream
			mode: (OFString *)mode
		    encoding: (OFStringEncoding)encoding
{
	self = [super init];

	@try {
		_archive = [[OFTarArchive alloc] initWithStream: stream
							   mode: mode];

Modified utils/ofarc/ZIPArchive.h from [8566715690] to [5707c10edc].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

22
23
24
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the 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 "OFZIPArchive.h"

#import "Archive.h"

@interface ZIPArchive: OFObject <Archive>
{

	OFZIPArchive *_archive;
}
@end

|

















|

>



1
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 "OFZIPArchive.h"

#import "Archive.h"

@interface ZIPArchive: OFObject <OFZIPArchiveDelegate, Archive>
{
	OFString *_path;
	OFZIPArchive *_archive;
}
@end

Modified utils/ofarc/ZIPArchive.m from [cefb3af267] to [6ca4ff87a1].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *
29
30
31
32
33
34
35

36
37
38
39
40
41
42

#import "ZIPArchive.h"
#import "OFArc.h"

#import "OFInvalidFormatException.h"
#import "OFOpenItemFailedException.h"
#import "OFOutOfRangeException.h"


static OFArc *app;

static void
setPermissions(OFString *path, OFZIPArchiveEntry *entry)
{
#ifdef OF_FILE_MANAGER_SUPPORTS_PERMISSIONS







>







29
30
31
32
33
34
35
36
37
38
39
40
41
42
43

#import "ZIPArchive.h"
#import "OFArc.h"

#import "OFInvalidFormatException.h"
#import "OFOpenItemFailedException.h"
#import "OFOutOfRangeException.h"
#import "OFSetItemAttributesFailedException.h"

static OFArc *app;

static void
setPermissions(OFString *path, OFZIPArchiveEntry *entry)
{
#ifdef OF_FILE_MANAGER_SUPPORTS_PERMISSIONS
62
63
64
65
66
67
68

69
70




71
72
73
74
75
76
77
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

	if (modificationDate == nil)
		return;

	attributes = [OFDictionary
	    dictionaryWithObject: modificationDate
			  forKey: OFFileModificationDate];

	[[OFFileManager defaultManager] setAttributes: attributes
					 ofItemAtPath: path];




}

@implementation ZIPArchive
+ (void)initialize
{
	if (self == [ZIPArchive class])
		app = (OFArc *)[OFApplication sharedApplication].delegate;
}


+ (instancetype)archiveWithStream: (OF_KINDOF(OFStream *))stream
			     mode: (OFString *)mode
			 encoding: (OFStringEncoding)encoding
{
	return [[[self alloc] initWithStream: stream

					mode: mode
				    encoding: encoding] autorelease];
}


- (instancetype)initWithStream: (OF_KINDOF(OFStream *))stream
			  mode: (OFString *)mode
		      encoding: (OFStringEncoding)encoding
{
	self = [super init];

	@try {

		_archive = [[OFZIPArchive alloc] initWithStream: stream
							   mode: mode];

	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (void)dealloc
{

	[_archive release];

	[super dealloc];
}























- (void)listFiles
{
	for (OFZIPArchiveEntry *entry in _archive.entries) {
		void *pool = objc_autoreleasePoolPush();

		[OFStdOut writeLine: entry.fileName];







>
|
|
>
>
>
>









>
|
|
|

|
>
|
|


>
|
|
|




>


>










>




>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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

	if (modificationDate == nil)
		return;

	attributes = [OFDictionary
	    dictionaryWithObject: modificationDate
			  forKey: OFFileModificationDate];
	@try {
		[[OFFileManager defaultManager] setAttributes: attributes
						 ofItemAtPath: path];
	} @catch (OFSetItemAttributesFailedException *e) {
		if (e.errNo != EISDIR)
			@throw e;
	}
}

@implementation ZIPArchive
+ (void)initialize
{
	if (self == [ZIPArchive class])
		app = (OFArc *)[OFApplication sharedApplication].delegate;
}

+ (instancetype)archiveWithPath: (OFString *)path
			 stream: (OF_KINDOF(OFStream *))stream
			   mode: (OFString *)mode
		       encoding: (OFStringEncoding)encoding
{
	return [[[self alloc] initWithPath: path
				    stream: stream
				      mode: mode
				  encoding: encoding] autorelease];
}

- (instancetype)initWithPath: (OFString *)path
		      stream: (OF_KINDOF(OFStream *))stream
			mode: (OFString *)mode
		    encoding: (OFStringEncoding)encoding
{
	self = [super init];

	@try {
		_path = [path copy];
		_archive = [[OFZIPArchive alloc] initWithStream: stream
							   mode: mode];
		_archive.delegate = self;
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (void)dealloc
{
	[_path release];
	[_archive release];

	[super dealloc];
}

- (OFSeekableStream *)archive: (OFZIPArchive *)archive
	    wantsPartNumbered: (unsigned int)partNumber
	       lastPartNumber: (unsigned int)lastPartNumber
{
	OFString *path;

	if ([_path.pathExtension caseInsensitiveCompare: @"zip"] !=
	    OFOrderedSame)
		return nil;

	if (partNumber > 98)
		return nil;

	if (partNumber == lastPartNumber)
		path = _path;
	else
		path = [_path.stringByDeletingPathExtension
		    stringByAppendingFormat: @".z%02u", partNumber + 1];

	return [OFFile fileWithPath: path mode: @"r"];
}

- (void)listFiles
{
	for (OFZIPArchiveEntry *entry in _archive.entries) {
		void *pool = objc_autoreleasePoolPush();

		[OFStdOut writeLine: entry.fileName];

Modified utils/ofarc/localization/de.json from [173fef355f] to [37825c390c].









1



2
3
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








{



    "usage": [
        "Benutzung: %[prog] -[acCfhlnpqtvx] archiv.zip [datei1 datei2 ...]"
    ],
    "full_usage": [
        "Optionen:\n",
        "    -a  --append      Zu Archiv hinzufügen\n",
        "    -c  --create      Archiv erstellen\n",
        "    -C  --directory   In angegebenes Verzeichnis entpacken\n",
        "    -E  --encoding    Das Encoding des Archivs (nur tar-Dateien)\n",
        "    -f  --force       Existierende Dateien überschreiben\n",
        "    -h  --help        Diese Hilfe anzeigen\n",
        "    -l  --list        Alle Dateien im Archiv auflisten\n",
        "    -n  --no-clobber  Dateien niemals überschreiben\n",
        "    -p  --print       Eine oder mehr Dateien aus dem Archiv ausgeben",
        "\n",
        "    -q  --quiet       Ruhiger Modus (keine Ausgabe außer Fehler)\n",
        "    -t  --type        Archiv-Typ (gz, lha, tar, tgz, zip)\n",
        "    -v  --verbose     Ausführlicher Modus für Datei-Liste\n",
        "    -x  --extract     Dateien entpacken"
    ],
    "2_options_mutually_exclusive": [
        "Fehler: -%[shortopt1] / --%[longopt1] und ",
        "-%[shortopt2] / --%[longopt2] schließen sich gegenseitig aus!"
    ],
    "5_options_mutually_exclusive": [
        "Fehler: -%[shortopt1] / --%[longopt1], -%[shortopt2] / ",
        "--%[longopt2], -%[shortopt3] / --%[longopt3], ",
        "-%[shortopt4] / --%[longopt4] und\n",
        "        -%[shortopt5] / --%[longopt5] schließen sich gegenseitig aus!"
    ],
    "option_takes_no_argument": "%[prog]: Option --%[opt] nimmt kein Argument",
    "long_option_requires_argument": [
        "%[prog]: Option --%[opt] benötigt ein Argument"
    ],
    "option_requires_argument": "%[prog]: Option -%[opt] benötigt ein Argument",
    "unknown_long_option": "%[prog]: Unbekannte Option: --%[opt]",
    "unknown_option": "%[prog]: Unbekannte Option: -%[opt]",
    "invalid_encoding": "%[prog]: Invalid encoding: %[encoding]",
    "writing_not_supported": [
        "Schreiben von Dateien des Typs %[type] wird (noch) nicht unterstützt!"
    ],
    "failed_to_create_directory": [
        "Fehler beim Erstellen des Verzeichnis %[dir]: %[error]"
    ],
    "failed_to_open_file": "Fehler beim Öffnen der Datei %[file]: %[error]",
    "unknown_archive_type": "Unbekannter Archivtyp: %[type]",
    "failed_to_read_file": "Fehler beim Lesen der Datei %[file]: %[error]",
    "failed_to_write_file": "Fehler beim Schreiben der Datei %[file]: %[error]",
    "failed_to_seek_in_file": "Fehler beim Suchen in Datei %[file]: %[error]",
    "file_is_not_a_valid_archive": "Datei %[file] ist kein gültiges Archiv!",
    "file_skipped": "übersprungen",
    "ask_overwrite": "%[file] überschreiben? [ynAN?]",
    "ask_overwrite_help": [
        " y: Ja\n",
        " n: Nein\n",
        " A: Immer\n",
        " N: Nie"
    ],
    "skipping_file": "Überspringe %[file]...",
    "extracting_file": "Entpacke %[file]...",
    "extracting_file_percent": "Entpacke %[file]... %[percent]%",
    "extracting_file_done": "Entpacke %[file]... fertig",
    "cannot_list_gz": "Kann Dateien eines .gz-Archivs nicht auflisten!",
    "cannot_extract_specific_file_from_gz": [
        "Kann keine spezifische Datei aus einem .gz-Archiv entpacken!"
    ],
    "cannot_print_specific_file_from_gz": [
        "Kann keine spezifische Datei aus einem .gz-Archiv ausgeben!"
    ],
    "list_size": [
        "Größe: ",
        [
            {"size == 1": "1 Byte"},
            {"": "%[size] Bytes"}
        ]
    ],
    "list_posix_permissions": "POSIX-Berechtigungen: %[perm]",
    "list_owner_account_id": "Besitzerkontennummer: %[id]",
    "list_group_owner_account_id": "Gruppenbesitzerkontennummer: %[id]",
    "list_owner_account_name": "Besitzerkontenname: %[name]",
    "list_group_owner_account_name": "Gruppebesitzerkontenname: %[name]",
    "list_header_level": "Header-Level: %[level]",
    "list_modification_date": "Änderungsdatum: %[date]",
    "list_type_normal": "Typ: Normale Datei",
    "list_type_hardlink": "Typ: Harter Link",
    "list_type_symlink": "Typ: Symbolischer Link",
    "list_link_target": "Zieldateiname: %[target]",
    "list_type_character_device": "Typ: Zeichenorientiertes Gerät",
    "list_type_block_device": "Typ: Blockorientiertes Gerät",
    "list_device_major": "Major-Nummer des Geräts: %[major]",
    "list_device_minor": "Minor-Nummer des Geräts: %[minor]",
    "list_type_directory": "Typ: Verzeichnis",
    "list_type_fifo": "Typ: FIFO",
    "list_type_contiguous_file": "Typ: Zusammenhängende Datei",
    "list_type_unknown": "Typ: Unbekannt",
    "list_compressed_size": [
        "Komprimierte Größe: ",
        [
            {"size == 1": "1 Byte"},
            {"": "%[size] Bytes"}
        ]
    ],
    "list_uncompressed_size": [
        "Unkomprimierte Größe: ",
        [
            {"size == 1": "1 Byte"},
            {"": "%[size] Bytes"}
        ]
    ],
    "list_compression_method": "Kompressionsmethode: %[method]",
    "list_osid": "Betriebssystem-Identifikator: %[osid]",
    "list_extensions": "Erweiterungen: %[extensions]",
    "list_version_made_by": "Erstellt mit Version: %[version]",
    "list_min_version_needed": "Mindestens benötigte Version: %[version]",
    "list_general_purpose_bit_flag": "General Purpose Bit Flag: %[gpbf]",
    "list_extra_field": "Extra-Feld: %[extra]",
    "list_comment": "Kommentar: %[comment]",
    "refusing_to_extract_file": "Verweigere Entpacken von %[file]!",
    "file_not_in_archive": "Datei %[file] ist nicht im Archiv!",
    "print_no_file_specified": [
        "Benötige eine oder mehrere Dateien zum Ausgeben!"
    ],
    "add_no_file_specified": [
        "Benötige eine oder mehrere Dateien zum Hinzufügen!"
    ],
    "adding_file": "Füge %[file] hinzu...",
    "adding_file_percent": "Füge %[file] hinzu... %[percent]%",
    "adding_file_done": "Füge %[file] hinzu... fertig"
}
>
>
>
>
>
>
>
>
|
>
>
>
|


|



|
|







|













|
|


|
|
|
|
|


|


|
|
|
|
|
|
|
|
|





|
|
|
|
|
|


|


|






|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|






|






|
|
|
|
|
|
|
|
|
|
|


|


|
|
|

1
2
3
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
/*
 * German localization for ofarc.
 *
 * Copyright (c) 2017-2024 Jonathan Schleifer <js@nil.im>
 *
 * Permission to use, copy, modify, and/or distribute this localization for
 * any purpose with or without fee is hereby granted.
 */

/* vim: se ft=javascript sw=4 et: */

{
    usage: [
        "Benutzung: %[prog] -[acCfhlnpqtvx] archiv.zip [datei1 datei2 ...]"
    ],
    full_usage: [
        "Optionen:\n",
        "    -a  --append      Zu Archiv hinzufügen\n",
        "    -c  --create      Archiv erstellen\n",
        "    -C  --directory=  In angegebenes Verzeichnis entpacken\n",
        "    -E  --encoding=   Das Encoding des Archivs (nur tar-Dateien)\n",
        "    -f  --force       Existierende Dateien überschreiben\n",
        "    -h  --help        Diese Hilfe anzeigen\n",
        "    -l  --list        Alle Dateien im Archiv auflisten\n",
        "    -n  --no-clobber  Dateien niemals überschreiben\n",
        "    -p  --print       Eine oder mehr Dateien aus dem Archiv ausgeben",
        "\n",
        "    -q  --quiet       Ruhiger Modus (keine Ausgabe außer Fehler)\n",
        "    -t  --type=       Archiv-Typ (gz, lha, tar, tgz, zip)\n",
        "    -v  --verbose     Ausführlicher Modus für Datei-Liste\n",
        "    -x  --extract     Dateien entpacken"
    ],
    "2_options_mutually_exclusive": [
        "Fehler: -%[shortopt1] / --%[longopt1] und ",
        "-%[shortopt2] / --%[longopt2] schließen sich gegenseitig aus!"
    ],
    "5_options_mutually_exclusive": [
        "Fehler: -%[shortopt1] / --%[longopt1], -%[shortopt2] / ",
        "--%[longopt2], -%[shortopt3] / --%[longopt3], ",
        "-%[shortopt4] / --%[longopt4] und\n",
        "        -%[shortopt5] / --%[longopt5] schließen sich gegenseitig aus!"
    ],
    option_takes_no_argument: "%[prog]: Option --%[opt] nimmt kein Argument",
    long_option_requires_argument: [
        "%[prog]: Option --%[opt] benötigt ein Argument"
    ],
    option_requires_argument: "%[prog]: Option -%[opt] benötigt ein Argument",
    unknown_long_option: "%[prog]: Unbekannte Option: --%[opt]",
    unknown_option: "%[prog]: Unbekannte Option: -%[opt]",
    invalid_encoding: "%[prog]: Invalid encoding: %[encoding]",
    writing_not_supported: [
        "Schreiben von Dateien des Typs %[type] wird (noch) nicht unterstützt!"
    ],
    failed_to_create_directory: [
        "Fehler beim Erstellen des Verzeichnis %[dir]: %[error]"
    ],
    failed_to_open_file: "Fehler beim Öffnen der Datei %[file]: %[error]",
    unknown_archive_type: "Unbekannter Archivtyp: %[type]",
    failed_to_read_file: "Fehler beim Lesen der Datei %[file]: %[error]",
    failed_to_write_file: "Fehler beim Schreiben der Datei %[file]: %[error]",
    failed_to_seek_in_file: "Fehler beim Suchen in Datei %[file]: %[error]",
    file_is_not_a_valid_archive: "Datei %[file] ist kein gültiges Archiv!",
    file_skipped: "übersprungen",
    ask_overwrite: "%[file] überschreiben? [ynAN?]",
    ask_overwrite_help: [
        " y: Ja\n",
        " n: Nein\n",
        " A: Immer\n",
        " N: Nie"
    ],
    skipping_file: "Überspringe %[file]...",
    extracting_file: "Entpacke %[file]...",
    extracting_file_percent: "Entpacke %[file]... %[percent]%",
    extracting_file_done: "Entpacke %[file]... fertig",
    cannot_list_gz: "Kann Dateien eines .gz-Archivs nicht auflisten!",
    cannot_extract_specific_file_from_gz: [
        "Kann keine spezifische Datei aus einem .gz-Archiv entpacken!"
    ],
    cannot_print_specific_file_from_gz: [
        "Kann keine spezifische Datei aus einem .gz-Archiv ausgeben!"
    ],
    list_size: [
        "Größe: ",
        [
            {"size == 1": "1 Byte"},
            {"": "%[size] Bytes"}
        ]
    ],
    list_posix_permissions: "POSIX-Berechtigungen: %[perm]",
    list_owner_account_id: "Besitzerkontennummer: %[id]",
    list_group_owner_account_id: "Gruppenbesitzerkontennummer: %[id]",
    list_owner_account_name: "Besitzerkontenname: %[name]",
    list_group_owner_account_name: "Gruppebesitzerkontenname: %[name]",
    list_header_level: "Header-Level: %[level]",
    list_modification_date: "Änderungsdatum: %[date]",
    list_type_normal: "Typ: Normale Datei",
    list_type_hardlink: "Typ: Harter Link",
    list_type_symlink: "Typ: Symbolischer Link",
    list_link_target: "Zieldateiname: %[target]",
    list_type_character_device: "Typ: Zeichenorientiertes Gerät",
    list_type_block_device: "Typ: Blockorientiertes Gerät",
    list_device_major: "Major-Nummer des Geräts: %[major]",
    list_device_minor: "Minor-Nummer des Geräts: %[minor]",
    list_type_directory: "Typ: Verzeichnis",
    list_type_fifo: "Typ: FIFO",
    list_type_contiguous_file: "Typ: Zusammenhängende Datei",
    list_type_unknown: "Typ: Unbekannt",
    list_compressed_size: [
        "Komprimierte Größe: ",
        [
            {"size == 1": "1 Byte"},
            {"": "%[size] Bytes"}
        ]
    ],
    list_uncompressed_size: [
        "Unkomprimierte Größe: ",
        [
            {"size == 1": "1 Byte"},
            {"": "%[size] Bytes"}
        ]
    ],
    list_compression_method: "Kompressionsmethode: %[method]",
    list_osid: "Betriebssystem-Identifikator: %[osid]",
    list_extensions: "Erweiterungen: %[extensions]",
    list_version_made_by: "Erstellt mit Version: %[version]",
    list_min_version_needed: "Mindestens benötigte Version: %[version]",
    list_general_purpose_bit_flag: "General Purpose Bit Flag: %[gpbf]",
    list_extra_field: "Extra-Feld: %[extra]",
    list_comment: "Kommentar: %[comment]",
    refusing_to_extract_file: "Verweigere Entpacken von %[file]!",
    file_not_in_archive: "Datei %[file] ist nicht im Archiv!",
    print_no_file_specified: [
        "Benötige eine oder mehrere Dateien zum Ausgeben!"
    ],
    add_no_file_specified: [
        "Benötige eine oder mehrere Dateien zum Hinzufügen!"
    ],
    adding_file: "Füge %[file] hinzu...",
    adding_file_percent: "Füge %[file] hinzu... %[percent]%",
    adding_file_done: "Füge %[file] hinzu... fertig",
}

Modified utils/ofarc/localization/localizations.json from [1722bb6119] to [df82f11fb6].









1

2


3
4
5
6
7
8
9
10
11








{

    "de": {


        "": "de"
    },
    "deutsch": {
        "": "de"
    },
    "german": {
        "": "de"
    }
}
>
>
>
>
>
>
>
>
|
>
|
>
>


|


|

|

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/*
 * Localization mapping for ofarc.
 *
 * Copyright (c) 2017-2023 Jonathan Schleifer <js@nil.im>
 *
 * Permission to use, copy, modify, and/or distribute this mapping for any
 * purpose with or without fee is hereby granted.
 */

/* vim: se ft=javascript sw=4 et: */

{
    de: {
        "": "de"
    },
    deutsch: {
        "": "de"
    },
    german: {
        "": "de"
    },
}

Modified utils/ofdns/Makefile from [94aeff9904] to [c4d144d3b6].

12
13
14
15
16
17
18
19
20
21
22
23
${PROG}: ${LIBOBJFW_DEP_LVL2} ${LIBOBJFWRT_DEP_LVL2}

CPPFLAGS += -I../../src							\
	    -I../../src/runtime						\
	    -I../../src/exceptions					\
	    -I../..							\
	    -DLOCALIZATION_DIR=\"${datadir}/ofdns/localization\"
LIBS := -L../../src -lobjfw						\
	-L../../src/runtime -L../../src/runtime/linklib ${RUNTIME_LIBS}	\
	${LIBS}
LD = ${OBJC}
LDFLAGS += ${LDFLAGS_RPATH}







|
<
<


12
13
14
15
16
17
18
19


20
21
${PROG}: ${LIBOBJFW_DEP_LVL2} ${LIBOBJFWRT_DEP_LVL2}

CPPFLAGS += -I../../src							\
	    -I../../src/runtime						\
	    -I../../src/exceptions					\
	    -I../..							\
	    -DLOCALIZATION_DIR=\"${datadir}/ofdns/localization\"
LIBS := -L../../src -lobjfw -L../../src/runtime ${RUNTIME_LIBS} ${LIBS}


LD = ${OBJC}
LDFLAGS += ${LDFLAGS_RPATH}

Modified utils/ofdns/OFDNS.m from [7740440ce7] to [dd4eedfc9f].

1
2
3
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
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#import "OFApplication.h"
#import "OFArray.h"
#import "OFDNSResolver.h"

#import "OFLocale.h"
#import "OFOptionsParser.h"
#import "OFSandbox.h"
#import "OFStdIOStream.h"

@interface OFDNS: OFObject <OFApplicationDelegate, OFDNSResolverQueryDelegate>
{
	size_t _inFlight;
	int _errors;
}
@end

OF_APPLICATION_DELEGATE(OFDNS)

static void
help(OFStream *stream, bool full, int status)
{
	[OFStdErr writeLine:
	    OF_LOCALIZED(@"usage",
	    @"Usage: %[prog] -[chst] domain1 [domain2 ...]",
	    @"prog", [OFApplication programName])];

	if (full) {
		[stream writeString: @"\n"];
		[stream writeLine: OF_LOCALIZED(@"full_usage",
		    @"Options:\n    "
		    @"-c  --class "
		    @"  The DNS class to query (defaults to IN)\n    "
		    @"-h  --help  "
		    @"  Show this help\n    "
		    @"-s  --server"
		    @"  The server to query\n    "
		    @"-t  --type  "
		    @"  The record type to query (defaults to ALL, can be "
		    @"repeated)")];


	}

	[OFApplication terminateWithStatus: status];
}

@implementation OFDNS
-  (void)resolver: (OFDNSResolver *)resolver
  didPerformQuery: (OFDNSQuery *)query
	 response: (OFDNSResponse *)response
	exception: (id)exception
{
	_inFlight--;

	if (exception == nil)
		[OFStdOut writeFormat: @"%@\n", response];
	else {
		[OFStdErr writeLine: OF_LOCALIZED(
		    @"failed_to_resolve",
		    @"Failed to resolve: %[exception]",
		    @"exception", exception)];
		_errors++;
	}

	if (_inFlight == 0)
		[OFApplication terminateWithStatus: _errors];
}

- (void)applicationDidFinishLaunching
{
	OFString *DNSClassString, *server;

	const OFOptionsParserOption options[] = {
		{ 'c', @"class", 1, NULL, &DNSClassString },
		{ 'h', @"help", 0, NULL, NULL },
		{ 's', @"server", 1, NULL, &server },
		{ 't', @"type", 1, NULL, NULL },

		{ '\0', nil, 0, NULL, NULL }
	};
	OFMutableArray OF_GENERIC(OFString *) *recordTypes;
	OFOptionsParser *optionsParser;
	OFUnichar option;
	OFArray OF_GENERIC(OFString *) *remainingArguments;
	OFDNSResolver *resolver;
	OFDNSClass DNSClass;

#ifdef OF_HAVE_FILES
# ifndef OF_AMIGAOS
	[OFLocale addLocalizationDirectory: @LOCALIZATION_DIR];

# else
	[OFLocale addLocalizationDirectory:
	    @"PROGDIR:/share/ofdns/localization"];
# endif
#endif

#ifdef OF_HAVE_SANDBOX
	OFSandbox *sandbox = [[OFSandbox alloc] init];
	@try {
		sandbox.allowsStdIO = true;

|


















>

















|
<







|

|

|

|

|
>
>
















|
<









|


>





>











|
>

|
|







1
2
3
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 "OFApplication.h"
#import "OFArray.h"
#import "OFDNSResolver.h"
#import "OFIRI.h"
#import "OFLocale.h"
#import "OFOptionsParser.h"
#import "OFSandbox.h"
#import "OFStdIOStream.h"

@interface OFDNS: OFObject <OFApplicationDelegate, OFDNSResolverQueryDelegate>
{
	size_t _inFlight;
	int _errors;
}
@end

OF_APPLICATION_DELEGATE(OFDNS)

static void
help(OFStream *stream, bool full, int status)
{
	[OFStdErr writeLine: OF_LOCALIZED(@"usage",

	    @"Usage: %[prog] -[chst] domain1 [domain2 ...]",
	    @"prog", [OFApplication programName])];

	if (full) {
		[stream writeString: @"\n"];
		[stream writeLine: OF_LOCALIZED(@"full_usage",
		    @"Options:\n    "
		    @"-c  --class= "
		    @"  The DNS class to query (defaults to IN)\n    "
		    @"-h  --help   "
		    @"  Show this help\n    "
		    @"-s  --server="
		    @"  The server to query\n    "
		    @"-t  --type=  "
		    @"  The record type to query (defaults to ALL, can be "
		    @"repeated)\n    "
		    @"    --tcp   "
		    @"  Force using TCP for the query")];
	}

	[OFApplication terminateWithStatus: status];
}

@implementation OFDNS
-  (void)resolver: (OFDNSResolver *)resolver
  didPerformQuery: (OFDNSQuery *)query
	 response: (OFDNSResponse *)response
	exception: (id)exception
{
	_inFlight--;

	if (exception == nil)
		[OFStdOut writeFormat: @"%@\n", response];
	else {
		[OFStdErr writeLine: OF_LOCALIZED(@"failed_to_resolve",

		    @"Failed to resolve: %[exception]",
		    @"exception", exception)];
		_errors++;
	}

	if (_inFlight == 0)
		[OFApplication terminateWithStatus: _errors];
}

- (void)applicationDidFinishLaunching: (OFNotification *)notification
{
	OFString *DNSClassString, *server;
	bool forceTCP;
	const OFOptionsParserOption options[] = {
		{ 'c', @"class", 1, NULL, &DNSClassString },
		{ 'h', @"help", 0, NULL, NULL },
		{ 's', @"server", 1, NULL, &server },
		{ 't', @"type", 1, NULL, NULL },
		{ '\0', @"tcp", 0, &forceTCP, NULL },
		{ '\0', nil, 0, NULL, NULL }
	};
	OFMutableArray OF_GENERIC(OFString *) *recordTypes;
	OFOptionsParser *optionsParser;
	OFUnichar option;
	OFArray OF_GENERIC(OFString *) *remainingArguments;
	OFDNSResolver *resolver;
	OFDNSClass DNSClass;

#ifdef OF_HAVE_FILES
# ifndef OF_AMIGAOS
	[OFLocale addLocalizationDirectoryIRI:
	    [OFIRI fileIRIWithPath: @LOCALIZATION_DIR]];
# else
	[OFLocale addLocalizationDirectoryIRI:
	    [OFIRI fileIRIWithPath: @"PROGDIR:/share/ofdns/localization"]];
# endif
#endif

#ifdef OF_HAVE_SANDBOX
	OFSandbox *sandbox = [[OFSandbox alloc] init];
	@try {
		sandbox.allowsStdIO = true;
176
177
178
179
180
181
182



183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199

	remainingArguments = optionsParser.remainingArguments;

	if (remainingArguments.count < 1)
		help(OFStdErr, false, 1);

	resolver = [OFDNSResolver resolver];



	DNSClass = (DNSClassString != nil
	    ? OFDNSClassParseName(DNSClassString) : OFDNSClassIN);

	if (recordTypes.count == 0)
		[recordTypes addObject: @"ALL"];

	if (server != nil) {
		resolver.configReloadInterval = 0;
		resolver.nameServers = [OFArray arrayWithObject: server];
	}

	for (OFString *domainName in remainingArguments) {
		for (OFString *recordTypeString in recordTypes) {
			OFDNSRecordType recordType =
			    OFDNSRecordTypeParseName(recordTypeString);
			OFDNSQuery *query =
			    [OFDNSQuery queryWithDomainName: domainName







>
>
>






|
<

<







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

	remainingArguments = optionsParser.remainingArguments;

	if (remainingArguments.count < 1)
		help(OFStdErr, false, 1);

	resolver = [OFDNSResolver resolver];
	resolver.configReloadInterval = 0;
	resolver.forcesTCP = forceTCP;

	DNSClass = (DNSClassString != nil
	    ? OFDNSClassParseName(DNSClassString) : OFDNSClassIN);

	if (recordTypes.count == 0)
		[recordTypes addObject: @"ALL"];

	if (server != nil)

		resolver.nameServers = [OFArray arrayWithObject: server];


	for (OFString *domainName in remainingArguments) {
		for (OFString *recordTypeString in recordTypes) {
			OFDNSRecordType recordType =
			    OFDNSRecordTypeParseName(recordTypeString);
			OFDNSQuery *query =
			    [OFDNSQuery queryWithDomainName: domainName

Modified utils/ofdns/localization/de.json from [a2dd6e542b] to [415733a1a9].









1



2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
17
18








{



    "usage": "Benutzung: %[prog] -[chst] domain1 [domain2 ...]",
    "full_usage": [
        "Optionen:\n",
        "    -c  --class   Die anzufragende DNS-Klasse (standardmäßig IN)\n",
        "    -h  --help    Diese Hilfe anzeigen\n",
        "    -s  --server  Der abzufragende Server\n",
        "    -t  --type    Der anzufragende Record-Typ (standardmäßig ALL,\n",
        "                  kann wiederholt werden)"

    ],
    "long_option_requires_argument": [
        "%[prog]: Option --%[opt] benötigt ein Argument"
    ],
    "option_requires_argument": "%[prog]: Option -%[opt] benötigt ein Argument",
    "unknown_long_option": "%[prog]: Unbekannte Option: --%[opt]",
    "unknown_option": "%[prog]: Unbekannte Option: -%[opt]",
    "failed_to_resolve": "Auflösen fehlgeschlagen: %[exception]"
}
>
>
>
>
>
>
>
>
|
>
>
>
|
|

|
|
|
|
|
>

|


|
|
|
|

1
2
3
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
/*
 * German localization for ofdns.
 *
 * Copyright (c) 2020-2024 Jonathan Schleifer <js@nil.im>
 *
 * Permission to use, copy, modify, and/or distribute this localization for
 * any purpose with or without fee is hereby granted.
 */

/* vim: se ft=javascript sw=4 et: */

{
    usage: "Benutzung: %[prog] -[chst] domain1 [domain2 ...]",
    full_usage: [
        "Optionen:\n",
        "    -c  --class=   Die anzufragende DNS-Klasse (standardmäßig IN)\n",
        "    -h  --help     Diese Hilfe anzeigen\n",
        "    -s  --server=  Der abzufragende Server\n",
        "    -t  --type=    Der anzufragende Record-Typ (standardmäßig ALL,\n",
        "                   kann wiederholt werden)\n",
        "        --tcp      Benutzung von TCP erzwingen"
    ],
    long_option_requires_argument: [
        "%[prog]: Option --%[opt] benötigt ein Argument"
    ],
    option_requires_argument: "%[prog]: Option -%[opt] benötigt ein Argument",
    unknown_long_option: "%[prog]: Unbekannte Option: --%[opt]",
    unknown_option: "%[prog]: Unbekannte Option: -%[opt]",
    failed_to_resolve: "Auflösen fehlgeschlagen: %[exception]",
}

Modified utils/ofdns/localization/localizations.json from [1722bb6119] to [52f2647bf8].









1

2


3
4
5
6
7
8
9
10
11








{

    "de": {


        "": "de"
    },
    "deutsch": {
        "": "de"
    },
    "german": {
        "": "de"
    }
}
>
>
>
>
>
>
>
>
|
>
|
>
>


|


|

|

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/*
 * Localization mapping for ofdns.
 *
 * Copyright (c) 2020-2023 Jonathan Schleifer <js@nil.im>
 *
 * Permission to use, copy, modify, and/or distribute this mapping for any
 * purpose with or without fee is hereby granted.
 */

/* vim: se ft=javascript sw=4 et: */

{
    de: {
        "": "de"
    },
    deutsch: {
        "": "de"
    },
    german: {
        "": "de"
    },
}

Modified utils/ofhash/Makefile from [41087b215e] to [c6f4a35e26].

12
13
14
15
16
17
18
19
20
21
22
23
${PROG}: ${LIBOBJFW_DEP_LVL2} ${LIBOBJFWRT_DEP_LVL2}

CPPFLAGS += -I../../src							\
	    -I../../src/runtime						\
	    -I../../src/exceptions					\
	    -I../..							\
	    -DLOCALIZATION_DIR=\"${datadir}/ofhash/localization\"
LIBS := -L../../src -lobjfw						\
	-L../../src/runtime -L../../src/runtime/linklib ${RUNTIME_LIBS}	\
	${LIBS}
LD = ${OBJC}
LDFLAGS += ${LDFLAGS_RPATH}







|
<
<


12
13
14
15
16
17
18
19


20
21
${PROG}: ${LIBOBJFW_DEP_LVL2} ${LIBOBJFWRT_DEP_LVL2}

CPPFLAGS += -I../../src							\
	    -I../../src/runtime						\
	    -I../../src/exceptions					\
	    -I../..							\
	    -DLOCALIZATION_DIR=\"${datadir}/ofhash/localization\"
LIBS := -L../../src -lobjfw -L../../src/runtime ${RUNTIME_LIBS} ${LIBS}


LD = ${OBJC}
LDFLAGS += ${LDFLAGS_RPATH}

Modified utils/ofhash/OFHash.m from [9cab35b0cf] to [0814b6a1ca].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

21
22
23
24
25
26
27
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#import "OFApplication.h"
#import "OFArray.h"
#import "OFFile.h"

#import "OFLocale.h"
#import "OFMD5Hash.h"
#import "OFOptionsParser.h"
#import "OFRIPEMD160Hash.h"
#import "OFSHA1Hash.h"
#import "OFSHA224Hash.h"
#import "OFSHA256Hash.h"

|


















>







1
2
3
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 "OFApplication.h"
#import "OFArray.h"
#import "OFFile.h"
#import "OFIRI.h"
#import "OFLocale.h"
#import "OFMD5Hash.h"
#import "OFOptionsParser.h"
#import "OFRIPEMD160Hash.h"
#import "OFSHA1Hash.h"
#import "OFSHA224Hash.h"
#import "OFSHA256Hash.h"
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
	for (size_t i = 0; i < digestSize; i++)
		[OFStdOut writeFormat: @"%02x", digest[i]];

	[OFStdOut writeFormat: @"  %@\n", path];
}

@implementation OFHash
- (void)applicationDidFinishLaunching
{
	int exitStatus = 0;
	bool calculateMD5, calculateRIPEMD160, calculateSHA1, calculateSHA224;
	bool calculateSHA256, calculateSHA384, calculateSHA512;
	const OFOptionsParserOption options[] = {
		{ '\0', @"md5", 0, &calculateMD5, NULL },
		{ '\0', @"ripemd160", 0, &calculateRIPEMD160, NULL },







|







65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
	for (size_t i = 0; i < digestSize; i++)
		[OFStdOut writeFormat: @"%02x", digest[i]];

	[OFStdOut writeFormat: @"  %@\n", path];
}

@implementation OFHash
- (void)applicationDidFinishLaunching: (OFNotification *)notification
{
	int exitStatus = 0;
	bool calculateMD5, calculateRIPEMD160, calculateSHA1, calculateSHA224;
	bool calculateSHA256, calculateSHA384, calculateSHA512;
	const OFOptionsParserOption options[] = {
		{ '\0', @"md5", 0, &calculateMD5, NULL },
		{ '\0', @"ripemd160", 0, &calculateRIPEMD160, NULL },
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
	OFSHA1Hash *SHA1Hash = nil;
	OFSHA224Hash *SHA224Hash = nil;
	OFSHA256Hash *SHA256Hash = nil;
	OFSHA384Hash *SHA384Hash = nil;
	OFSHA512Hash *SHA512Hash = nil;

#ifndef OF_AMIGAOS
	[OFLocale addLocalizationDirectory: @LOCALIZATION_DIR];

#else
	[OFLocale addLocalizationDirectory:
	    @"PROGDIR:/share/ofhash/localization"];
#endif

	while ((option = [optionsParser nextOption]) != '\0') {
		switch (option) {
		case '?':
			if (optionsParser.lastLongOption != nil)
				[OFStdErr writeLine:
				    OF_LOCALIZED(@"unknown_long_option",
				    @"%[prog]: Unknown option: --%[opt]",
				    @"prog", [OFApplication programName],
				    @"opt", optionsParser.lastLongOption)];
			else {
				OFString *optStr = [OFString stringWithFormat:
				    @"%c", optionsParser.lastOption];
				[OFStdErr writeLine:
				    OF_LOCALIZED(@"unknown_option",
				    @"%[prog]: Unknown option: -%[opt]",
				    @"prog", [OFApplication programName],
				    @"opt", optStr)];
			}

			[OFApplication terminateWithStatus: 1];
			break;







|
>

|
|






|
|





|
|
|







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
	OFSHA1Hash *SHA1Hash = nil;
	OFSHA224Hash *SHA224Hash = nil;
	OFSHA256Hash *SHA256Hash = nil;
	OFSHA384Hash *SHA384Hash = nil;
	OFSHA512Hash *SHA512Hash = nil;

#ifndef OF_AMIGAOS
	[OFLocale addLocalizationDirectoryIRI:
	    [OFIRI fileIRIWithPath: @LOCALIZATION_DIR]];
#else
	[OFLocale addLocalizationDirectoryIRI:
	    [OFIRI fileIRIWithPath: @"PROGDIR:/share/ofhash/localization"]];
#endif

	while ((option = [optionsParser nextOption]) != '\0') {
		switch (option) {
		case '?':
			if (optionsParser.lastLongOption != nil)
				[OFStdErr writeLine: OF_LOCALIZED(
				    @"unknown_long_option",
				    @"%[prog]: Unknown option: --%[opt]",
				    @"prog", [OFApplication programName],
				    @"opt", optionsParser.lastLongOption)];
			else {
				OFString *optStr = [OFString stringWithFormat:
				    @"%C", optionsParser.lastOption];
				[OFStdErr writeLine: OF_LOCALIZED(
				    @"unknown_option",
				    @"%[prog]: Unknown option: -%[opt]",
				    @"prog", [OFApplication programName],
				    @"opt", optStr)];
			}

			[OFApplication terminateWithStatus: 1];
			break;

Modified utils/ofhash/localization/de.json from [e3d21e1de1] to [946fe7d617].









1



2
3
4
5
6
7
8
9
10








{



    "usage": [
        "Benutzung: %[prog] [--md5] [--ripemd160] [--sha1] [--sha224] ",
        "[--sha256] [--sha384] [--sha512] datei1 [datei2 ...]"
    ],
    "unknown_long_option": "%[prog]: Unbekannte Option: --%[opt]",
    "unknown_option": "%[prog]: Unbekannte Option: -%[opt]",
    "failed_to_open_file": "Fehler beim Öffnen der Datei %[file]: %[error]",
    "failed_to_read_file": "Fehler beim Lesen der Datei %[file]: %[error]"
}
>
>
>
>
>
>
>
>
|
>
>
>
|



|
|
|
|

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/*
 * German localization for ofhash.
 *
 * Copyright (c) 2017-2023 Jonathan Schleifer <js@nil.im>
 *
 * Permission to use, copy, modify, and/or distribute this localization for
 * any purpose with or without fee is hereby granted.
 */

/* vim: se ft=javascript sw=4 et: */

{
    usage: [
        "Benutzung: %[prog] [--md5] [--ripemd160] [--sha1] [--sha224] ",
        "[--sha256] [--sha384] [--sha512] datei1 [datei2 ...]"
    ],
    unknown_long_option: "%[prog]: Unbekannte Option: --%[opt]",
    unknown_option: "%[prog]: Unbekannte Option: -%[opt]",
    failed_to_open_file: "Fehler beim Öffnen der Datei %[file]: %[error]",
    failed_to_read_file: "Fehler beim Lesen der Datei %[file]: %[error]",
}

Modified utils/ofhash/localization/localizations.json from [1722bb6119] to [19e35e3a75].









1

2


3
4
5
6
7
8
9
10
11








{

    "de": {


        "": "de"
    },
    "deutsch": {
        "": "de"
    },
    "german": {
        "": "de"
    }
}
>
>
>
>
>
>
>
>
|
>
|
>
>


|


|

|

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/*
 * Localization mapping for ofhash.
 *
 * Copyright (c) 2017-2023 Jonathan Schleifer <js@nil.im>
 *
 * Permission to use, copy, modify, and/or distribute this mapping for any
 * purpose with or without fee is hereby granted.
 */

/* vim: se ft=javascript sw=4 et: */

{
    de: {
        "": "de"
    },
    deutsch: {
        "": "de"
    },
    german: {
        "": "de"
    },
}

Modified utils/ofhttp/Makefile from [a53c9301a9] to [75e10724b9].

13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
${PROG}: ${LIBOBJFW_DEP_LVL2} ${LIBOBJFWRT_DEP_LVL2}

CPPFLAGS += -I../../src							\
	    -I../../src/runtime						\
	    -I../../src/exceptions					\
	    -I../../src/tls						\
	    -I../..							\
	    -DLOCALIZATION_DIR='"${datadir}/ofhttp/localization"'	\
	    -DLIB_PREFIX='"${LIB_PREFIX}"'				\
	    -DLIB_SUFFIX='"${LIB_SUFFIX}"'
LIBS := -L../../src -L../../src/tls ${OFHTTP_LIBS} -lobjfw		\
	-L../../src/runtime -L../../src/runtime/linklib ${RUNTIME_LIBS}	\
	${LIBS}
LD = ${OBJC}
LDFLAGS += ${LDFLAGS_RPATH}







|
<
<

|



13
14
15
16
17
18
19
20


21
22
23
24
25
${PROG}: ${LIBOBJFW_DEP_LVL2} ${LIBOBJFWRT_DEP_LVL2}

CPPFLAGS += -I../../src							\
	    -I../../src/runtime						\
	    -I../../src/exceptions					\
	    -I../../src/tls						\
	    -I../..							\
	    -DLOCALIZATION_DIR='"${datadir}/ofhttp/localization"'


LIBS := -L../../src -L../../src/tls ${OFHTTP_LIBS} -lobjfw		\
	-L../../src/runtime ${RUNTIME_LIBS}				\
	${LIBS}
LD = ${OBJC}
LDFLAGS += ${LDFLAGS_RPATH}

Modified utils/ofhttp/OFHTTP.m from [36f1e9db6a] to [bf9f7e1c82].

1
2
3
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
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#import "OFApplication.h"
#import "OFArray.h"
#import "OFData.h"

#import "OFDictionary.h"
#import "OFFile.h"
#import "OFFileManager.h"
#import "OFHTTPClient.h"
#import "OFHTTPRequest.h"
#import "OFHTTPResponse.h"

#import "OFLocale.h"
#import "OFOptionsParser.h"
#ifdef OF_HAVE_PLUGINS
# import "OFPlugin.h"
#endif
#import "OFSandbox.h"
#import "OFStdIOStream.h"
#import "OFSystemInfo.h"
#import "OFTCPSocket.h"
#import "OFTLSStream.h"
#import "OFURI.h"

#ifdef HAVE_TLS_SUPPORT
# import "ObjFWTLS.h"
#endif

#import "OFConnectSocketFailedException.h"
#import "OFGetItemAttributesFailedException.h"
#import "OFHTTPRequestFailedException.h"
#import "OFInvalidArgumentException.h"
#import "OFInvalidFormatException.h"
#import "OFInvalidServerResponseException.h"
#import "OFOpenItemFailedException.h"
#import "OFOutOfRangeException.h"
#import "OFReadFailedException.h"
#import "OFResolveHostFailedException.h"


#import "OFUnsupportedProtocolException.h"
#import "OFWriteFailedException.h"

#import "ProgressBar.h"

#define GIBIBYTE (1024 * 1024 * 1024)
#define MEBIBYTE (1024 * 1024)
#define KIBIBYTE (1024)

@interface OFHTTP: OFObject <OFApplicationDelegate, OFHTTPClientDelegate,
    OFStreamDelegate>
{
	OFArray OF_GENERIC(OFString *) *_URIs;
	size_t _URIIndex;
	int _errorCode;
	OFString *_outputPath, *_currentFileName;
	bool _continue, _force, _detectFileName, _detectFileNameRequest;
	bool _detectedFileName, _quiet, _verbose, _insecure, _ignoreStatus;
	bool _useUnicode;
	OFStream *_body;
	OFHTTPRequestMethod _method;
	OFMutableDictionary *_clientHeaders;
	OFHTTPClient *_HTTPClient;
	char *_buffer;
	OFStream *_output;
	unsigned long long _received, _length, _resumedFrom;
	ProgressBar *_progressBar;
}

- (void)downloadNextURI;
@end

#ifdef HAVE_TLS_SUPPORT
void
_reference_to_ObjFWTLS(void)
{
	_ObjFWTLS_reference = 1;
}
#endif

OF_APPLICATION_DELEGATE(OFHTTP)

static void
help(OFStream *stream, bool full, int status)
{
	[OFStdErr writeLine:
	    OF_LOCALIZED(@"usage",
	    @"Usage: %[prog] -[cehHmoOPqv] uri1 [uri2 ...]",
	    @"prog", [OFApplication programName])];

	if (full) {
		[stream writeString: @"\n"];
		[stream writeLine: OF_LOCALIZED(@"full_usage",
		    @"Options:\n    "
		    @"-b  --body           "
		    @"  Specify the file to send as body\n    "
		    @"                     "
		    @"  (- for standard input)\n    "
		    @"-c  --continue       "
		    @"  Continue download of existing file\n    "
		    @"-f  --force          "
		    @"  Force / overwrite existing file\n    "
		    @"-h  --help           "
		    @"  Show this help\n    "
		    @"-H  --header         "
		    @"  Add a header (e.g. X-Foo:Bar)\n    "
		    @"-m  --method         "
		    @"  Set the method of the HTTP request\n    "
		    @"-o  --output         "
		    @"  Specify output file name\n    "
		    @"-O  --detect-filename"
		    @"  Do a HEAD request to detect the file name\n    "
		    @"-P  --proxy          "
		    @"  Specify SOCKS5 proxy\n    "
		    @"-q  --quiet          "
		    @"  Quiet mode (no output, except errors)\n    "
		    @"-v  --verbose        "
		    @"  Verbose mode (print headers)\n    "
		    @"    --insecure       "
		    @"  Ignore TLS errors and allow insecure redirects\n    "

|


















>






>










<















>
>












|
|















|















|
<
|






|









|

|

|



|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101

102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
/*
 * Copyright (c) 2008-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 "OFApplication.h"
#import "OFArray.h"
#import "OFData.h"
#import "OFDate.h"
#import "OFDictionary.h"
#import "OFFile.h"
#import "OFFileManager.h"
#import "OFHTTPClient.h"
#import "OFHTTPRequest.h"
#import "OFHTTPResponse.h"
#import "OFIRI.h"
#import "OFLocale.h"
#import "OFOptionsParser.h"
#ifdef OF_HAVE_PLUGINS
# import "OFPlugin.h"
#endif
#import "OFSandbox.h"
#import "OFStdIOStream.h"
#import "OFSystemInfo.h"
#import "OFTCPSocket.h"
#import "OFTLSStream.h"


#ifdef HAVE_TLS_SUPPORT
# import "ObjFWTLS.h"
#endif

#import "OFConnectSocketFailedException.h"
#import "OFGetItemAttributesFailedException.h"
#import "OFHTTPRequestFailedException.h"
#import "OFInvalidArgumentException.h"
#import "OFInvalidFormatException.h"
#import "OFInvalidServerResponseException.h"
#import "OFOpenItemFailedException.h"
#import "OFOutOfRangeException.h"
#import "OFReadFailedException.h"
#import "OFResolveHostFailedException.h"
#import "OFSetItemAttributesFailedException.h"
#import "OFTLSHandshakeFailedException.h"
#import "OFUnsupportedProtocolException.h"
#import "OFWriteFailedException.h"

#import "ProgressBar.h"

#define GIBIBYTE (1024 * 1024 * 1024)
#define MEBIBYTE (1024 * 1024)
#define KIBIBYTE (1024)

@interface OFHTTP: OFObject <OFApplicationDelegate, OFHTTPClientDelegate,
    OFStreamDelegate>
{
	OFArray OF_GENERIC(OFString *) *_IRIs;
	size_t _IRIIndex;
	int _errorCode;
	OFString *_outputPath, *_currentFileName;
	bool _continue, _force, _detectFileName, _detectFileNameRequest;
	bool _detectedFileName, _quiet, _verbose, _insecure, _ignoreStatus;
	bool _useUnicode;
	OFStream *_body;
	OFHTTPRequestMethod _method;
	OFMutableDictionary *_clientHeaders;
	OFHTTPClient *_HTTPClient;
	char *_buffer;
	OFStream *_output;
	unsigned long long _received, _length, _resumedFrom;
	ProgressBar *_progressBar;
}

- (void)downloadNextIRI;
@end

#ifdef HAVE_TLS_SUPPORT
void
_reference_to_ObjFWTLS(void)
{
	_ObjFWTLS_reference = 1;
}
#endif

OF_APPLICATION_DELEGATE(OFHTTP)

static void
help(OFStream *stream, bool full, int status)
{
	[OFStdErr writeLine: OF_LOCALIZED(@"usage",

	    @"Usage: %[prog] -[cehHmoOPqv] iri1 [iri2 ...]",
	    @"prog", [OFApplication programName])];

	if (full) {
		[stream writeString: @"\n"];
		[stream writeLine: OF_LOCALIZED(@"full_usage",
		    @"Options:\n    "
		    @"-b  --body=          "
		    @"  Specify the file to send as body\n    "
		    @"                     "
		    @"  (- for standard input)\n    "
		    @"-c  --continue       "
		    @"  Continue download of existing file\n    "
		    @"-f  --force          "
		    @"  Force / overwrite existing file\n    "
		    @"-h  --help           "
		    @"  Show this help\n    "
		    @"-H  --header=        "
		    @"  Add a header (e.g. X-Foo:Bar)\n    "
		    @"-m  --method=        "
		    @"  Set the method of the HTTP request\n    "
		    @"-o  --output=        "
		    @"  Specify output file name\n    "
		    @"-O  --detect-filename"
		    @"  Do a HEAD request to detect the file name\n    "
		    @"-P  --proxy=         "
		    @"  Specify SOCKS5 proxy\n    "
		    @"-q  --quiet          "
		    @"  Quiet mode (no output, except errors)\n    "
		    @"-v  --verbose        "
		    @"  Verbose mode (print headers)\n    "
		    @"    --insecure       "
		    @"  Ignore TLS errors and allow insecure redirects\n    "
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
- (void)setMethod: (OFString *)method
{
	void *pool = objc_autoreleasePoolPush();

	method = method.uppercaseString;

	@try {
		_method = OFHTTPRequestMethodParseName(method);
	} @catch (OFInvalidArgumentException *e) {
		[OFStdErr writeLine: OF_LOCALIZED(@"invalid_input_method",
		    @"%[prog]: Invalid request method %[method]!",
		    @"prog", [OFApplication programName],
		    @"method", method)];
		[OFApplication terminateWithStatus: 1];
	}







|







369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
- (void)setMethod: (OFString *)method
{
	void *pool = objc_autoreleasePoolPush();

	method = method.uppercaseString;

	@try {
		_method = OFHTTPRequestMethodParseString(method);
	} @catch (OFInvalidArgumentException *e) {
		[OFStdErr writeLine: OF_LOCALIZED(@"invalid_input_method",
		    @"%[prog]: Invalid request method %[method]!",
		    @"prog", [OFApplication programName],
		    @"method", method)];
		[OFApplication terminateWithStatus: 1];
	}
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
		[OFStdErr writeLine: OF_LOCALIZED(@"invalid_input_proxy",
		    @"%[prog]: Proxy must to be in format host:port!",
		    @"prog", [OFApplication programName])];
		[OFApplication terminateWithStatus: 1];
	}
}

- (void)applicationDidFinishLaunching
{
	OFString *outputPath;
	const OFOptionsParserOption options[] = {
		{ 'b', @"body",	1, NULL, NULL },
		{ 'c', @"continue", 0, &_continue, NULL },
		{ 'f', @"force", 0, &_force, NULL },
		{ 'h', @"help",	0, NULL, NULL },







|







410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
		[OFStdErr writeLine: OF_LOCALIZED(@"invalid_input_proxy",
		    @"%[prog]: Proxy must to be in format host:port!",
		    @"prog", [OFApplication programName])];
		[OFApplication terminateWithStatus: 1];
	}
}

- (void)applicationDidFinishLaunching: (OFNotification *)notification
{
	OFString *outputPath;
	const OFOptionsParserOption options[] = {
		{ 'b', @"body",	1, NULL, NULL },
		{ 'c', @"continue", 0, &_continue, NULL },
		{ 'f', @"force", 0, &_force, NULL },
		{ 'h', @"help",	0, NULL, NULL },
447
448
449
450
451
452
453
454

455
456
457
458
459
460
461
462
463
464
	/* Dropped after parsing options */
	sandbox.allowsUnveil = true;

	[OFApplication of_activateSandbox: sandbox];
#endif

#ifndef OF_AMIGAOS
	[OFLocale addLocalizationDirectory: @LOCALIZATION_DIR];

#else
	[OFLocale addLocalizationDirectory:
	    @"PROGDIR:/share/ofhttp/localization"];
#endif

	optionsParser = [OFOptionsParser parserWithOptions: options];
	while ((option = [optionsParser nextOption]) != '\0') {
		switch (option) {
		case 'b':
			[self setBody: optionsParser.argument];







|
>

|
|







449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
	/* Dropped after parsing options */
	sandbox.allowsUnveil = true;

	[OFApplication of_activateSandbox: sandbox];
#endif

#ifndef OF_AMIGAOS
	[OFLocale addLocalizationDirectoryIRI:
	    [OFIRI fileIRIWithPath: @LOCALIZATION_DIR]];
#else
	[OFLocale addLocalizationDirectoryIRI:
	    [OFIRI fileIRIWithPath: @"PROGDIR:/share/ofhttp/localization"]];
#endif

	optionsParser = [OFOptionsParser parserWithOptions: options];
	while ((option = [optionsParser nextOption]) != '\0') {
		switch (option) {
		case 'b':
			[self setBody: optionsParser.argument];
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
			[self setMethod: optionsParser.argument];
			break;
		case 'P':
			[self setProxy: optionsParser.argument];
			break;
		case ':':
			if (optionsParser.lastLongOption != nil)
				[OFStdErr writeLine:
				    OF_LOCALIZED(@"long_argument_missing",
				    @"%[prog]: Argument for option --%[opt] "
				    @"missing"
				    @"prog", [OFApplication programName],
				    @"opt", optionsParser.lastLongOption)];
			else {
				OFString *optStr = [OFString
				    stringWithFormat: @"%c",
				    optionsParser.lastOption];
				[OFStdErr writeLine:
				    OF_LOCALIZED(@"argument_missing",
				    @"%[prog]: Argument for option -%[opt] "
				    @"missing",
				    @"prog", [OFApplication programName],
				    @"opt", optStr)];
			}

			[OFApplication terminateWithStatus: 1];
			break;
		case '=':
			[OFStdErr writeLine:
			    OF_LOCALIZED(@"option_takes_no_argument",
			    @"%[prog]: Option --%[opt] takes no argument",
			    @"prog", [OFApplication programName],
			    @"opt", optionsParser.lastLongOption)];

			[OFApplication terminateWithStatus: 1];
			break;
		case '?':
			if (optionsParser.lastLongOption != nil)
				[OFStdErr writeLine:
				    OF_LOCALIZED(@"unknown_long_option",
				    @"%[prog]: Unknown option: --%[opt]",
				    @"prog", [OFApplication programName],
				    @"opt", optionsParser.lastLongOption)];
			else {
				OFString *optStr = [OFString
				    stringWithFormat: @"%c",
				    optionsParser.lastOption];
				[OFStdErr writeLine:
				    OF_LOCALIZED(@"unknown_option",
				    @"%[prog]: Unknown option: -%[opt]",
				    @"prog", [OFApplication programName],
				    @"opt", optStr)];
			}

			[OFApplication terminateWithStatus: 1];
			break;







|
|

|




|

|
|









|
|








|
|





|

|
|







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
			[self setMethod: optionsParser.argument];
			break;
		case 'P':
			[self setProxy: optionsParser.argument];
			break;
		case ':':
			if (optionsParser.lastLongOption != nil)
				[OFStdErr writeLine: OF_LOCALIZED(
				    @"long_argument_missing",
				    @"%[prog]: Argument for option --%[opt] "
				    @"missing",
				    @"prog", [OFApplication programName],
				    @"opt", optionsParser.lastLongOption)];
			else {
				OFString *optStr = [OFString
				    stringWithFormat: @"%C",
				    optionsParser.lastOption];
				[OFStdErr writeLine: OF_LOCALIZED(
				    @"argument_missing",
				    @"%[prog]: Argument for option -%[opt] "
				    @"missing",
				    @"prog", [OFApplication programName],
				    @"opt", optStr)];
			}

			[OFApplication terminateWithStatus: 1];
			break;
		case '=':
			[OFStdErr writeLine: OF_LOCALIZED(
			    @"option_takes_no_argument",
			    @"%[prog]: Option --%[opt] takes no argument",
			    @"prog", [OFApplication programName],
			    @"opt", optionsParser.lastLongOption)];

			[OFApplication terminateWithStatus: 1];
			break;
		case '?':
			if (optionsParser.lastLongOption != nil)
				[OFStdErr writeLine: OF_LOCALIZED(
				    @"unknown_long_option",
				    @"%[prog]: Unknown option: --%[opt]",
				    @"prog", [OFApplication programName],
				    @"opt", optionsParser.lastLongOption)];
			else {
				OFString *optStr = [OFString
				    stringWithFormat: @"%C",
				    optionsParser.lastOption];
				[OFStdErr writeLine: OF_LOCALIZED(
				    @"unknown_option",
				    @"%[prog]: Unknown option: -%[opt]",
				    @"prog", [OFApplication programName],
				    @"opt", optStr)];
			}

			[OFApplication terminateWithStatus: 1];
			break;
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
	[sandbox unveilPath: @"/etc/ssl" permissions: @"r"];

	sandbox.allowsUnveil = false;
	[OFApplication of_activateSandbox: sandbox];
#endif

	_outputPath = [outputPath copy];
	_URIs = [optionsParser.remainingArguments copy];

	if (_URIs.count < 1)
		help(OFStdErr, false, 1);

	if (_quiet && _verbose) {
		[OFStdErr writeLine: OF_LOCALIZED(@"quiet_xor_verbose",
		    @"%[prog]: -q / --quiet and -v / --verbose are mutually "
		    @"exclusive!",
		    @"prog", [OFApplication programName])];
		[OFApplication terminateWithStatus: 1];
	}

	if (_outputPath != nil && _detectFileName) {
		[OFStdErr writeLine: OF_LOCALIZED(
		    @"output_xor_detect_filename",
		    @"%[prog]: -o / --output and -O / --detect-filename are "
		    @"mutually exclusive!",
		    @"prog", [OFApplication programName])];
		[OFApplication terminateWithStatus: 1];
	}

	if (_outputPath != nil && _URIs.count > 1) {
		[OFStdErr writeLine:
		    OF_LOCALIZED(@"output_only_with_one_uri",
		    @"%[prog]: Cannot use -o / --output when more than one URI "
		    @"has been specified!",
		    @"prog", [OFApplication programName])];
		[OFApplication terminateWithStatus: 1];
	}

	if (_insecure)
		_HTTPClient.allowsInsecureRedirects = true;

#ifdef OF_WINDOWS
	_useUnicode = [OFSystemInfo isWindowsNT];
#else
	_useUnicode = ([OFLocale encoding] == OFStringEncodingUTF8);
#endif

	[self performSelector: @selector(downloadNextURI) afterDelay: 0];
}

-	(void)client: (OFHTTPClient *)client
  didCreateTLSStream: (OFTLSStream *)stream
	     request: (OFHTTPRequest *)request
{
	/* Use setter instead of property access to work around GCC bug. */







|

|



















|
|
|
|














|







545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
	[sandbox unveilPath: @"/etc/ssl" permissions: @"r"];

	sandbox.allowsUnveil = false;
	[OFApplication of_activateSandbox: sandbox];
#endif

	_outputPath = [outputPath copy];
	_IRIs = [optionsParser.remainingArguments copy];

	if (_IRIs.count < 1)
		help(OFStdErr, false, 1);

	if (_quiet && _verbose) {
		[OFStdErr writeLine: OF_LOCALIZED(@"quiet_xor_verbose",
		    @"%[prog]: -q / --quiet and -v / --verbose are mutually "
		    @"exclusive!",
		    @"prog", [OFApplication programName])];
		[OFApplication terminateWithStatus: 1];
	}

	if (_outputPath != nil && _detectFileName) {
		[OFStdErr writeLine: OF_LOCALIZED(
		    @"output_xor_detect_filename",
		    @"%[prog]: -o / --output and -O / --detect-filename are "
		    @"mutually exclusive!",
		    @"prog", [OFApplication programName])];
		[OFApplication terminateWithStatus: 1];
	}

	if (_outputPath != nil && _IRIs.count > 1) {
		[OFStdErr writeLine: OF_LOCALIZED(
		    @"output_only_with_one_iri",
		    @"%[prog]: Cannot use -o / --output when more than one IRI "
		    @"has been specified!",
		    @"prog", [OFApplication programName])];
		[OFApplication terminateWithStatus: 1];
	}

	if (_insecure)
		_HTTPClient.allowsInsecureRedirects = true;

#ifdef OF_WINDOWS
	_useUnicode = [OFSystemInfo isWindowsNT];
#else
	_useUnicode = ([OFLocale encoding] == OFStringEncodingUTF8);
#endif

	[self performSelector: @selector(downloadNextIRI) afterDelay: 0];
}

-	(void)client: (OFHTTPClient *)client
  didCreateTLSStream: (OFTLSStream *)stream
	     request: (OFHTTPRequest *)request
{
	/* Use setter instead of property access to work around GCC bug. */
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
		char buffer[4096];
		size_t length = [_body readIntoBuffer: buffer length: 4096];
		[body writeBuffer: buffer length: length];
	}
}

-	       (bool)client: (OFHTTPClient *)client
  shouldFollowRedirectToURI: (OFURI *)URI
		 statusCode: (short)statusCode
		    request: (OFHTTPRequest *)request
		   response: (OFHTTPResponse *)response
{
	if (_verbose) {
		void *pool = objc_autoreleasePoolPush();
		OFDictionary OF_GENERIC(OFString *, OFString *) *headers =







|







609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
		char buffer[4096];
		size_t length = [_body readIntoBuffer: buffer length: 4096];
		[body writeBuffer: buffer length: length];
	}
}

-	       (bool)client: (OFHTTPClient *)client
  shouldFollowRedirectToIRI: (OFIRI *)IRI
		 statusCode: (short)statusCode
		    request: (OFHTTPRequest *)request
		   response: (OFHTTPResponse *)response
{
	if (_verbose) {
		void *pool = objc_autoreleasePoolPush();
		OFDictionary OF_GENERIC(OFString *, OFString *) *headers =
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
			[OFStdOut writeFormat: @"  %@: %@\n", key, object];

		objc_autoreleasePoolPop(pool);
	}

	if (!_quiet) {
		if (_useUnicode)
			[OFStdOut writeFormat: @"☇ %@", URI.string];
		else
			[OFStdOut writeFormat: @"< %@", URI.string];
	}

	_length = 0;

	return true;
}

-      (bool)stream: (OFStream *)response
  didReadIntoBuffer: (void *)buffer
	     length: (size_t)length
	  exception: (id)exception
{
	if (exception != nil) {
		OFString *URI;

		[_progressBar stop];
		[_progressBar draw];
		[_progressBar release];
		_progressBar = nil;

		if (!_quiet) {
			[OFStdOut writeString: @"\n  "];
			[OFStdOut writeLine: OF_LOCALIZED(@"download_error",
			    @"Error!")];
		}

		URI = [_URIs objectAtIndex: _URIIndex - 1];
		[OFStdErr writeLine: OF_LOCALIZED(
		    @"download_failed_exception",
		    @"%[prog]: Failed to download <%[uri]>!\n"
		    @"  %[exception]",
		    @"prog", [OFApplication programName],
		    @"uri", URI,
		    @"exception", exception)];

		_errorCode = 1;
		[self performSelector: @selector(downloadNextURI)
			   afterDelay: 0];
		return false;
	}

	[_output writeBuffer: buffer length: length];

	_received += length;







|

|













|












|


|


|



|







631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
			[OFStdOut writeFormat: @"  %@: %@\n", key, object];

		objc_autoreleasePoolPop(pool);
	}

	if (!_quiet) {
		if (_useUnicode)
			[OFStdOut writeFormat: @"☇ %@", IRI.string];
		else
			[OFStdOut writeFormat: @"< %@", IRI.string];
	}

	_length = 0;

	return true;
}

-      (bool)stream: (OFStream *)response
  didReadIntoBuffer: (void *)buffer
	     length: (size_t)length
	  exception: (id)exception
{
	if (exception != nil) {
		OFString *IRI;

		[_progressBar stop];
		[_progressBar draw];
		[_progressBar release];
		_progressBar = nil;

		if (!_quiet) {
			[OFStdOut writeString: @"\n  "];
			[OFStdOut writeLine: OF_LOCALIZED(@"download_error",
			    @"Error!")];
		}

		IRI = [_IRIs objectAtIndex: _IRIIndex - 1];
		[OFStdErr writeLine: OF_LOCALIZED(
		    @"download_failed_exception",
		    @"%[prog]: Failed to download <%[iri]>!\n"
		    @"  %[exception]",
		    @"prog", [OFApplication programName],
		    @"iri", IRI,
		    @"exception", exception)];

		_errorCode = 1;
		[self performSelector: @selector(downloadNextIRI)
			   afterDelay: 0];
		return false;
	}

	[_output writeBuffer: buffer length: length];

	_received += length;
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703

		if (!_quiet) {
			[OFStdOut writeString: @"\n  "];
			[OFStdOut writeLine:
			    OF_LOCALIZED(@"download_done", @"Done!")];
		}

		[self performSelector: @selector(downloadNextURI)
			   afterDelay: 0];
		return false;
	}

	return true;
}








|







692
693
694
695
696
697
698
699
700
701
702
703
704
705
706

		if (!_quiet) {
			[OFStdOut writeString: @"\n  "];
			[OFStdOut writeLine:
			    OF_LOCALIZED(@"download_done", @"Done!")];
		}

		[self performSelector: @selector(downloadNextIRI)
			   afterDelay: 0];
		return false;
	}

	return true;
}

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
{
	if (exception != nil) {
		if ([exception isKindOfClass:
		    [OFResolveHostFailedException class]]) {
			if (!_quiet)
				[OFStdOut writeString: @"\n"];

			[OFStdErr writeLine:
			    OF_LOCALIZED(@"download_resolve_host_failed",
			    @"%[prog]: Failed to download <%[uri]>!\n"
			    @"  Failed to resolve host: %[exception]",
			    @"prog", [OFApplication programName],
			    @"uri", request.URI.string,
			    @"exception", exception)];
		} else if ([exception isKindOfClass:
		    [OFConnectSocketFailedException class]]) {
			if (!_quiet)
				[OFStdOut writeString: @"\n"];

			[OFStdErr writeLine:
			    OF_LOCALIZED(@"download_failed_connection_failed",
			    @"%[prog]: Failed to download <%[uri]>!\n"
			    @"  Connection failed: %[exception]",
			    @"prog", [OFApplication programName],
			    @"uri", request.URI.string,
			    @"exception", exception)];
		} else if ([exception isKindOfClass:
		    [OFInvalidServerResponseException class]]) {
			if (!_quiet)
				[OFStdOut writeString: @"\n"];

			[OFStdErr writeLine: OF_LOCALIZED(
			    @"download_failed_invalid_server_response",
			    @"%[prog]: Failed to download <%[uri]>!\n"
			    @"  Invalid server response!",
			    @"prog", [OFApplication programName],
			    @"uri", request.URI.string)];
		} else if ([exception isKindOfClass:
		    [OFUnsupportedProtocolException class]]) {
			if (!_quiet)
				[OFStdOut writeString: @"\n"];

			[OFStdErr writeLine: OF_LOCALIZED(@"no_tls_support",
			    @"%[prog]: No TLS support in ObjFW!\n"
			    @"  In order to download via HTTPS, you need to "
			    @"either build ObjFW with TLS\n"
			    @"  support or preload a library adding TLS "
			    @"support to ObjFW!",
			    @"prog", [OFApplication programName])];
















		} else if ([exception isKindOfClass:
		    [OFReadOrWriteFailedException class]]) {
			OFString *error = OF_LOCALIZED(
			    @"download_failed_read_or_write_failed_any",
			    @"Read or write failed");

			if (!_quiet)







|
|
|


|






|
|
|


|








|


|












>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
{
	if (exception != nil) {
		if ([exception isKindOfClass:
		    [OFResolveHostFailedException class]]) {
			if (!_quiet)
				[OFStdOut writeString: @"\n"];

			[OFStdErr writeLine: OF_LOCALIZED(
			    @"download_resolve_host_failed",
			    @"%[prog]: Failed to download <%[iri]>!\n"
			    @"  Failed to resolve host: %[exception]",
			    @"prog", [OFApplication programName],
			    @"iri", request.IRI.string,
			    @"exception", exception)];
		} else if ([exception isKindOfClass:
		    [OFConnectSocketFailedException class]]) {
			if (!_quiet)
				[OFStdOut writeString: @"\n"];

			[OFStdErr writeLine: OF_LOCALIZED(
			    @"download_failed_connection_failed",
			    @"%[prog]: Failed to download <%[iri]>!\n"
			    @"  Connection failed: %[exception]",
			    @"prog", [OFApplication programName],
			    @"iri", request.IRI.string,
			    @"exception", exception)];
		} else if ([exception isKindOfClass:
		    [OFInvalidServerResponseException class]]) {
			if (!_quiet)
				[OFStdOut writeString: @"\n"];

			[OFStdErr writeLine: OF_LOCALIZED(
			    @"download_failed_invalid_server_response",
			    @"%[prog]: Failed to download <%[iri]>!\n"
			    @"  Invalid server response!",
			    @"prog", [OFApplication programName],
			    @"iri", request.IRI.string)];
		} else if ([exception isKindOfClass:
		    [OFUnsupportedProtocolException class]]) {
			if (!_quiet)
				[OFStdOut writeString: @"\n"];

			[OFStdErr writeLine: OF_LOCALIZED(@"no_tls_support",
			    @"%[prog]: No TLS support in ObjFW!\n"
			    @"  In order to download via HTTPS, you need to "
			    @"either build ObjFW with TLS\n"
			    @"  support or preload a library adding TLS "
			    @"support to ObjFW!",
			    @"prog", [OFApplication programName])];
		} else if ([exception isKindOfClass:
		    [OFTLSHandshakeFailedException class]]) {
			OFString *error = OFTLSStreamErrorCodeDescription(
			    ((OFTLSHandshakeFailedException *)exception)
			    .errorCode);

			if (!_quiet)
				[OFStdOut writeString: @"\n"];

			[OFStdErr writeLine: OF_LOCALIZED(
			    @"download_failed_tls_handshake_failed",
			    @"%[prog]: Failed to download <%[iri]>!\n"
			    @"  TLS handshake failed: %[error]",
			    @"prog", [OFApplication programName],
			    @"iri", request.IRI.string,
			    @"error", error)];
		} else if ([exception isKindOfClass:
		    [OFReadOrWriteFailedException class]]) {
			OFString *error = OF_LOCALIZED(
			    @"download_failed_read_or_write_failed_any",
			    @"Read or write failed");

			if (!_quiet)
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
				error = OF_LOCALIZED(
				    @"download_failed_read_or_write_failed_"
				    @"write",
				    @"Write failed");

			[OFStdErr writeLine: OF_LOCALIZED(
			    @"download_failed_read_or_write_failed",
			    @"%[prog]: Failed to download <%[uri]>!\n"
			    @"  %[error]: %[exception]",
			    @"prog", [OFApplication programName],
			    @"uri", request.URI.string,
			    @"error", error,
			    @"exception", exception)];
		} else if ([exception isKindOfClass:
		    [OFHTTPRequestFailedException class]]) {
			short statusCode;
			OFString *codeString;

			if (_ignoreStatus) {
				exception = nil;
				goto after_exception_handling;
			}

			statusCode = response.statusCode;
			codeString = [OFString stringWithFormat: @"%hd %@",
			    statusCode, OFHTTPStatusCodeString(statusCode)];
			[OFStdErr writeLine: OF_LOCALIZED(@"download_failed",
			    @"%[prog]: Failed to download <%[uri]>!\n"
			    @"  HTTP status code: %[code]",
			    @"prog", [OFApplication programName],
			    @"uri", request.URI.string,
			    @"code", codeString)];
		} else
			@throw exception;

		_errorCode = 1;
		[self performSelector: @selector(downloadNextURI)
			   afterDelay: 0];
		return;
	}

after_exception_handling:
	if (_method == OFHTTPRequestMethodHead)
		goto next;

	if (_detectFileNameRequest) {
		_currentFileName = [fileNameFromContentDisposition(
		    [response.headers objectForKey: @"Content-Disposition"])
		    copy];
		_detectedFileName = true;

		/* Handle this URI on the next -[downloadNextURI] call */
		_URIIndex--;

		[self performSelector: @selector(downloadNextURI)
			   afterDelay: 0];
		return;
	}

	if ([_outputPath isEqual: @"-"])
		_output = [OFStdOut copy];
	else {







|


|
















|


|





|














|
|

|







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
				error = OF_LOCALIZED(
				    @"download_failed_read_or_write_failed_"
				    @"write",
				    @"Write failed");

			[OFStdErr writeLine: OF_LOCALIZED(
			    @"download_failed_read_or_write_failed",
			    @"%[prog]: Failed to download <%[iri]>!\n"
			    @"  %[error]: %[exception]",
			    @"prog", [OFApplication programName],
			    @"iri", request.IRI.string,
			    @"error", error,
			    @"exception", exception)];
		} else if ([exception isKindOfClass:
		    [OFHTTPRequestFailedException class]]) {
			short statusCode;
			OFString *codeString;

			if (_ignoreStatus) {
				exception = nil;
				goto after_exception_handling;
			}

			statusCode = response.statusCode;
			codeString = [OFString stringWithFormat: @"%hd %@",
			    statusCode, OFHTTPStatusCodeString(statusCode)];
			[OFStdErr writeLine: OF_LOCALIZED(@"download_failed",
			    @"%[prog]: Failed to download <%[iri]>!\n"
			    @"  HTTP status code: %[code]",
			    @"prog", [OFApplication programName],
			    @"iri", request.IRI.string,
			    @"code", codeString)];
		} else
			@throw exception;

		_errorCode = 1;
		[self performSelector: @selector(downloadNextIRI)
			   afterDelay: 0];
		return;
	}

after_exception_handling:
	if (_method == OFHTTPRequestMethodHead)
		goto next;

	if (_detectFileNameRequest) {
		_currentFileName = [fileNameFromContentDisposition(
		    [response.headers objectForKey: @"Content-Disposition"])
		    copy];
		_detectedFileName = true;

		/* Handle this IRI on the next -[downloadNextIRI] call */
		_IRIIndex--;

		[self performSelector: @selector(downloadNextIRI)
			   afterDelay: 0];
		return;
	}

	if ([_outputPath isEqual: @"-"])
		_output = [OFStdOut copy];
	else {
961
962
963
964
965
966
967

































968
969
970
971
972
973
974
			    @"prog", [OFApplication programName],
			    @"filename", _currentFileName,
			    @"exception", e)];

			_errorCode = 1;
			goto next;
		}

































	}

	if (!_quiet) {
		_progressBar = [[ProgressBar alloc]
		    initWithLength: _length
		       resumedFrom: _resumedFrom
			useUnicode: _useUnicode];







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
			    @"prog", [OFApplication programName],
			    @"filename", _currentFileName,
			    @"exception", e)];

			_errorCode = 1;
			goto next;
		}

#ifdef OF_LINUX
		@try {
			OFString *IRIString = request.IRI.string;
			OFData *downloadedFromData = [OFData
			    dataWithItems: IRIString.UTF8String
				    count: IRIString.UTF8StringLength + 1];
			[[OFFileManager defaultManager]
			    setExtendedAttributeData: downloadedFromData
					     forName: @"user.ofhttp."
						      @"downloaded_from"
					ofItemAtPath: _currentFileName];
		} @catch (OFSetItemAttributesFailedException *) {
			/* Ignore */
		}
#endif

#ifdef OF_MACOS
		@try {
			OFString *quarantine = [OFString stringWithFormat:
			    @"0000;%08" @PRIx64 @";ofhttp;",
			    (uint64_t)[[OFDate date] timeIntervalSince1970]];
			OFData *quarantineData = [OFData
			    dataWithItems: quarantine.UTF8String
				    count: quarantine.UTF8StringLength];
			[[OFFileManager defaultManager]
			    setExtendedAttributeData: quarantineData
					     forName: @"com.apple.quarantine"
					ofItemAtPath: _currentFileName];
		} @catch (OFSetItemAttributesFailedException *e) {
			/* Ignore */
		}
#endif
	}

	if (!_quiet) {
		_progressBar = [[ProgressBar alloc]
		    initWithLength: _length
		       resumedFrom: _resumedFrom
			useUnicode: _useUnicode];
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
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
	[response asyncReadIntoBuffer: _buffer length: [OFSystemInfo pageSize]];
	return;

next:
	[_currentFileName release];
	_currentFileName = nil;

	[self performSelector: @selector(downloadNextURI) afterDelay: 0];
}

- (void)downloadNextURI
{
	OFString *URIString = nil;
	OFURI *URI;
	OFMutableDictionary *clientHeaders;
	OFHTTPRequest *request;

	_received = _length = _resumedFrom = 0;

	if (_output != OFStdOut)
		[_output release];
	_output = nil;

	if (_URIIndex >= _URIs.count)
		[OFApplication terminateWithStatus: _errorCode];

	@try {
		URIString = [_URIs objectAtIndex: _URIIndex++];
		URI = [OFURI URIWithString: URIString];
	} @catch (OFInvalidFormatException *e) {
		[OFStdErr writeLine: OF_LOCALIZED(@"invalid_uri",
		    @"%[prog]: Invalid URI: <%[uri]>!",
		    @"prog", [OFApplication programName],
		    @"uri", URIString)];

		_errorCode = 1;
		goto next;
	}

	if (![URI.scheme isEqual: @"http"] && ![URI.scheme isEqual: @"https"]) {
		[OFStdErr writeLine: OF_LOCALIZED(@"invalid_scheme",
		    @"%[prog]: Invalid scheme: <%[uri]>!",
		    @"prog", [OFApplication programName],
		    @"uri", URIString)];

		_errorCode = 1;
		goto next;
	}

	clientHeaders = [[_clientHeaders mutableCopy] autorelease];

	if (_detectFileName && !_detectedFileName) {
		if (!_quiet) {
			if (_useUnicode)
				[OFStdOut writeFormat: @"⠒ %@", URI.string];
			else
				[OFStdOut writeFormat: @"? %@", URI.string];
		}

		request = [OFHTTPRequest requestWithURI: URI];
		request.headers = clientHeaders;
		request.method = OFHTTPRequestMethodHead;

		_detectFileNameRequest = true;
		[_HTTPClient asyncPerformRequest: request];
		return;
	}

	if (!_detectedFileName) {
		[_currentFileName release];
		_currentFileName = nil;
	} else
		_detectedFileName = false;

	if (_currentFileName == nil)
		_currentFileName = [_outputPath copy];

	if (_currentFileName == nil)
		_currentFileName = [URI.path.lastPathComponent copy];

	if ([_currentFileName isEqual: @"/"]) {
		[_currentFileName release];
		_currentFileName = nil;
	}

	if (_currentFileName == nil)
		_currentFileName = @"unnamed";

	if (_continue) {
		@try {
			unsigned long long size =
			    [[OFFileManager defaultManager]
			    attributesOfItemAtPath: _currentFileName].fileSize;
			OFString *range;

			if (size > ULLONG_MAX)
				@throw [OFOutOfRangeException exception];

			_resumedFrom = (unsigned long long)size;

			range = [OFString stringWithFormat: @"bytes=%jd-",
							    _resumedFrom];
			[clientHeaders setObject: range forKey: @"Range"];
		} @catch (OFGetItemAttributesFailedException *e) {
		}
	}

	if (!_quiet) {
		if (_useUnicode)
			[OFStdOut writeFormat: @"⇣ %@", URI.string];
		else
			[OFStdOut writeFormat: @"< %@", URI.string];
	}

	request = [OFHTTPRequest requestWithURI: URI];
	request.headers = clientHeaders;
	request.method = _method;

	_detectFileNameRequest = false;
	[_HTTPClient asyncPerformRequest: request];
	return;

next:
	[self performSelector: @selector(downloadNextURI) afterDelay: 0];
}
@end







|


|

|
|









|



|
|

|
|

|





|

|

|










|

|


|


















|

|



















|








|

|


|








|


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
	[response asyncReadIntoBuffer: _buffer length: [OFSystemInfo pageSize]];
	return;

next:
	[_currentFileName release];
	_currentFileName = nil;

	[self performSelector: @selector(downloadNextIRI) afterDelay: 0];
}

- (void)downloadNextIRI
{
	OFString *IRIString = nil;
	OFIRI *IRI;
	OFMutableDictionary *clientHeaders;
	OFHTTPRequest *request;

	_received = _length = _resumedFrom = 0;

	if (_output != OFStdOut)
		[_output release];
	_output = nil;

	if (_IRIIndex >= _IRIs.count)
		[OFApplication terminateWithStatus: _errorCode];

	@try {
		IRIString = [_IRIs objectAtIndex: _IRIIndex++];
		IRI = [OFIRI IRIWithString: IRIString];
	} @catch (OFInvalidFormatException *e) {
		[OFStdErr writeLine: OF_LOCALIZED(@"invalid_iri",
		    @"%[prog]: Invalid IRI: <%[iri]>!",
		    @"prog", [OFApplication programName],
		    @"iri", IRIString)];

		_errorCode = 1;
		goto next;
	}

	if (![IRI.scheme isEqual: @"http"] && ![IRI.scheme isEqual: @"https"]) {
		[OFStdErr writeLine: OF_LOCALIZED(@"invalid_scheme",
		    @"%[prog]: Invalid scheme: <%[iri]>!",
		    @"prog", [OFApplication programName],
		    @"iri", IRIString)];

		_errorCode = 1;
		goto next;
	}

	clientHeaders = [[_clientHeaders mutableCopy] autorelease];

	if (_detectFileName && !_detectedFileName) {
		if (!_quiet) {
			if (_useUnicode)
				[OFStdOut writeFormat: @"⠒ %@", IRI.string];
			else
				[OFStdOut writeFormat: @"? %@", IRI.string];
		}

		request = [OFHTTPRequest requestWithIRI: IRI];
		request.headers = clientHeaders;
		request.method = OFHTTPRequestMethodHead;

		_detectFileNameRequest = true;
		[_HTTPClient asyncPerformRequest: request];
		return;
	}

	if (!_detectedFileName) {
		[_currentFileName release];
		_currentFileName = nil;
	} else
		_detectedFileName = false;

	if (_currentFileName == nil)
		_currentFileName = [_outputPath copy];

	if (_currentFileName == nil)
		_currentFileName = [IRI.path.lastPathComponent copy];

	if ([_currentFileName isEqual: @"/"] || _currentFileName.length == 0) {
		[_currentFileName release];
		_currentFileName = nil;
	}

	if (_currentFileName == nil)
		_currentFileName = @"unnamed";

	if (_continue) {
		@try {
			unsigned long long size =
			    [[OFFileManager defaultManager]
			    attributesOfItemAtPath: _currentFileName].fileSize;
			OFString *range;

			if (size > ULLONG_MAX)
				@throw [OFOutOfRangeException exception];

			_resumedFrom = (unsigned long long)size;

			range = [OFString stringWithFormat: @"bytes=%ju-",
							    _resumedFrom];
			[clientHeaders setObject: range forKey: @"Range"];
		} @catch (OFGetItemAttributesFailedException *e) {
		}
	}

	if (!_quiet) {
		if (_useUnicode)
			[OFStdOut writeFormat: @"⇣ %@", IRI.string];
		else
			[OFStdOut writeFormat: @"< %@", IRI.string];
	}

	request = [OFHTTPRequest requestWithIRI: IRI];
	request.headers = clientHeaders;
	request.method = _method;

	_detectFileNameRequest = false;
	[_HTTPClient asyncPerformRequest: request];
	return;

next:
	[self performSelector: @selector(downloadNextIRI) afterDelay: 0];
}
@end

Modified utils/ofhttp/ProgressBar.h from [be2c97fe71] to [6f24a36616].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified utils/ofhttp/ProgressBar.m from [9a2768256d] to [2718f12548].

1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2008-2022 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *

|







1
2
3
4
5
6
7
8
9
/*
 * 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.
 *

Modified utils/ofhttp/localization/de.json from [839a028930] to [89ce45218c].









1



2
3
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








{



    "usage": "Benutzung: %[prog] -[cehHmoOPqv] uri1 [uri2 ...]",
    "full_usage": [
        "Optionen:\n",
        "    -b  --body             Angegebene Datei als Body übergeben\n",
        "                           (- für Standard-Eingabe)\n",
        "    -c  --continue         Download von existierender Datei ",
        "fortsetzen\n",
        "    -f  --force            Existierende Datei überschreiben\n",
        "    -h  --help             Diese Hilfe anzeigen\n",
        "    -H  --header           Einen Header (z.B. X-Foo:Bar) hinzufügen\n",
        "    -m  --method           HTTP Request-Methode setzen\n",
        "    -o  --output           Ausgabe-Dateiname angeben\n",
        "    -O  --detect-filename  Dateiname mittels HEAD-Request ermitteln\n",
        "    -P  --proxy            SOCKS5-Proxy angeben\n",
        "    -q  --quiet            Ruhiger Modus (keine Ausgabe außer Fehler)",
        "\n",
        "    -v  --verbose          Ausführlicher Modus (gibt Header aus)\n",
        "        --insecure         TLS-Fehler ignorieren und unsichere\n",
        "                           Weiterleitungen erlauben\n",
        "        --ignore-status    HTTP Status-Code ignorieren"
    ],
    "invalid_input_header": "%[prog]: Header müssen im Format Name:Wert sein!",
    "invalid_input_method": "%[prog]: Ungültige Request-Methode %[method]!",
    "invalid_input_proxy": "%[prog]: Proxy muss im Format Host:Port sein!",
    "long_argument_missing": "%[prog]: Argument für Option --%[opt] fehlt",
    "argument_missing": "%[prog]: Argument für option -%[opt] fehlt",
    "option_takes_no_argument": "%[prog]: Option --%[opt] nimmt kein Argument",
    "unknown_long_option": "%[prog]: Unbekannte Option: --%[opt]",
    "unknown_option": "%[prog]: Unbekannte Option: -%[opt]",
    "quiet_xor_verbose": [
        "%[prog]: -q / --quiet und -v / --verbose schließen sich gegenseitig ",
        "aus!"
    ],
    "output_xor_detect_filename": [
        "%[prog]: -o / --output und -O / --detect-filename schließen sich ",
        "gegenseitig aus!"
    ],
    "output_only_with_one_uri": [
        "%[prog]: -o / --output kann nicht mit mehr als einer URI benutzt ",
        "werden!"
    ],
    "download_resolve_host_failed": [
        "%[prog]: Fehler beim Download von <%[uri]>!\n",
        "  Host auflösen fehlgeschlagen: %[exception]"
    ],
    "download_failed_connection_failed": [
        "%[prog]: Fehler beim Download von <%[uri]>!\n",
        "  Verbindung fehlgeschlagen: %[exception]"
    ],
    "download_failed_invalid_server_response": [
        "%[prog]: Fehler beim Download von <%[uri]>!\n",
        "  Ungültige Antwort vom Server!"
    ],
    "no_tls_support": [
        "%[prog]: Keine TLS-Unterstützung in ObjFW!\n",
        "  Um via HTTPS runterzuladen müssen Sie entweder ObjFW mit TLS-",
        "Unterstützung\n",
        "  kompilieren oder eine Bibliothek mittels „preload” laden, welche ",
        "TLS-Support\n",
        "  zu ObjFW hinzufügt!"
    ],




    "download_failed_read_or_write_failed_any": "Lesen oder Schreiben",
    "download_failed_read_or_write_failed_read": "Lesen",
    "download_failed_read_or_write_failed_write": "Schreiben",
    "download_failed_read_or_write_failed": [
        "%[prog]: Fehler beim Download von <%[uri]>!\n",
        "  %[error]: %[exception]"
    ],
    "download_failed": [
        "%[prog]: Fehler beim Download von <%[uri]>!\n",
        "  HTTP Status-Code: %[code]"
    ],
    "download_error": "Fehler!",
    "download_failed_exception": [
        "%[prog]: Fehler beim Download von <%[uri]>!\n",
        "  %[exception]"
    ],
    "download_done": "Fertig!",
    "invalid_uri": "%[prog]: Ungültige URI: <%[uri]>!",
    "invalid_scheme": "%[prog]: Ungültiges Schema: <%[uri]>!",
    "type_unknown": "unbekannt",
    "size_gib": "%[num] GiB",
    "size_mib": "%[num] MiB",
    "size_kib": "%[num] KiB",
    "size_bytes": [
        [
            {"num == 1": "1 Byte"},
            {"": "%[num] Bytes"}
        ]
    ],
    "size_unknown": "unbekannt",
    "info_name_unaligned": "Name: %[name]",
    "info_name": "Name:  %[name]",
    "info_type": "Typ:   %[type]",
    "info_size": "Größe: %[size]",
    "output_already_exists": "%[prog]: Datei %[filename] existiert bereits!",
    "failed_to_open_output": [
        "%[prog]: Kann Datei %[filename] nicht öffnen: %[exception]"
    ],
    "eta_days": "%[num] t ",
    "progress_bytes": [
        [
            {"num == 1": "1 Byte "},
            {"": "%[num] Bytes"}
        ]
    ]
}
>
>
>
>
>
>
>
>
|
>
>
>
|
|

|





|
|
|

|







|
|
|
|
|
|
|
|
|



|



|
|


|
|


|
|


|
|


|







>
>
>
>
|
|
|
|
|


|
|


|
|
|


|
|
|
|
|
|
|
|





|
|
|
|
|
|
|


|
|




|

1
2
3
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
/*
 * German localization for ofhttp.
 *
 * Copyright (c) 2017-2024 Jonathan Schleifer <js@nil.im>
 *
 * Permission to use, copy, modify, and/or distribute this localization for
 * any purpose with or without fee is hereby granted.
 */

/* vim: se ft=javascript sw=4 et: */

{
    usage: "Benutzung: %[prog] -[cehHmoOPqv] iri1 [iri2 ...]",
    full_usage: [
        "Optionen:\n",
        "    -b  --body=            Angegebene Datei als Body übergeben\n",
        "                           (- für Standard-Eingabe)\n",
        "    -c  --continue         Download von existierender Datei ",
        "fortsetzen\n",
        "    -f  --force            Existierende Datei überschreiben\n",
        "    -h  --help             Diese Hilfe anzeigen\n",
        "    -H  --header=          Einen Header (z.B. X-Foo:Bar) hinzufügen\n",
        "    -m  --method=          HTTP Request-Methode setzen\n",
        "    -o  --output=          Ausgabe-Dateiname angeben\n",
        "    -O  --detect-filename  Dateiname mittels HEAD-Request ermitteln\n",
        "    -P  --proxy=           SOCKS5-Proxy angeben\n",
        "    -q  --quiet            Ruhiger Modus (keine Ausgabe außer Fehler)",
        "\n",
        "    -v  --verbose          Ausführlicher Modus (gibt Header aus)\n",
        "        --insecure         TLS-Fehler ignorieren und unsichere\n",
        "                           Weiterleitungen erlauben\n",
        "        --ignore-status    HTTP Status-Code ignorieren"
    ],
    invalid_input_header: "%[prog]: Header müssen im Format Name:Wert sein!",
    invalid_input_method: "%[prog]: Ungültige Request-Methode %[method]!",
    invalid_input_proxy: "%[prog]: Proxy muss im Format Host:Port sein!",
    long_argument_missing: "%[prog]: Argument für Option --%[opt] fehlt",
    argument_missing: "%[prog]: Argument für option -%[opt] fehlt",
    option_takes_no_argument: "%[prog]: Option --%[opt] nimmt kein Argument",
    unknown_long_option: "%[prog]: Unbekannte Option: --%[opt]",
    unknown_option: "%[prog]: Unbekannte Option: -%[opt]",
    quiet_xor_verbose: [
        "%[prog]: -q / --quiet und -v / --verbose schließen sich gegenseitig ",
        "aus!"
    ],
    output_xor_detect_filename: [
        "%[prog]: -o / --output und -O / --detect-filename schließen sich ",
        "gegenseitig aus!"
    ],
    output_only_with_one_iri: [
        "%[prog]: -o / --output kann nicht mit mehr als einer IRI benutzt ",
        "werden!"
    ],
    download_resolve_host_failed: [
        "%[prog]: Fehler beim Download von <%[iri]>!\n",
        "  Host auflösen fehlgeschlagen: %[exception]"
    ],
    download_failed_connection_failed: [
        "%[prog]: Fehler beim Download von <%[iri]>!\n",
        "  Verbindung fehlgeschlagen: %[exception]"
    ],
    download_failed_invalid_server_response: [
        "%[prog]: Fehler beim Download von <%[iri]>!\n",
        "  Ungültige Antwort vom Server!"
    ],
    no_tls_support: [
        "%[prog]: Keine TLS-Unterstützung in ObjFW!\n",
        "  Um via HTTPS runterzuladen müssen Sie entweder ObjFW mit TLS-",
        "Unterstützung\n",
        "  kompilieren oder eine Bibliothek mittels „preload” laden, welche ",
        "TLS-Support\n",
        "  zu ObjFW hinzufügt!"
    ],
    download_failed_tls_handshake_failed: [
        "%[prog]: Fehler beim Download von <%[iri]>!\n",
        "  TLS-Handshake fehlgeschlagen: %[error]"
    ],
    download_failed_read_or_write_failed_any: "Lesen oder Schreiben",
    download_failed_read_or_write_failed_read: "Lesen",
    download_failed_read_or_write_failed_write: "Schreiben",
    download_failed_read_or_write_failed: [
        "%[prog]: Fehler beim Download von <%[iri]>!\n",
        "  %[error]: %[exception]"
    ],
    download_failed: [
        "%[prog]: Fehler beim Download von <%[iri]>!\n",
        "  HTTP Status-Code: %[code]"
    ],
    download_error: "Fehler!",
    download_failed_exception: [
        "%[prog]: Fehler beim Download von <%[iri]>!\n",
        "  %[exception]"
    ],
    download_done: "Fertig!",
    invalid_iri: "%[prog]: Ungültige IRI: <%[iri]>!",
    invalid_scheme: "%[prog]: Ungültiges Schema: <%[iri]>!",
    type_unknown: "unbekannt",
    size_gib: "%[num] GiB",
    size_mib: "%[num] MiB",
    size_kib: "%[num] KiB",
    size_bytes: [
        [
            {"num == 1": "1 Byte"},
            {"": "%[num] Bytes"}
        ]
    ],
    size_unknown: "unbekannt",
    info_name_unaligned: "Name: %[name]",
    info_name: "Name:  %[name]",
    info_type: "Typ:   %[type]",
    info_size: "Größe: %[size]",
    output_already_exists: "%[prog]: Datei %[filename] existiert bereits!",
    failed_to_open_output: [
        "%[prog]: Kann Datei %[filename] nicht öffnen: %[exception]"
    ],
    eta_days: "%[num] t ",
    progress_bytes: [
        [
            {"num == 1": "1 Byte "},
            {"": "%[num] Bytes"}
        ]
    ],
}

Modified utils/ofhttp/localization/localizations.json from [1722bb6119] to [be4c09810e].









1

2


3
4
5
6
7
8
9
10
11








{

    "de": {


        "": "de"
    },
    "deutsch": {
        "": "de"
    },
    "german": {
        "": "de"
    }
}
>
>
>
>
>
>
>
>
|
>
|
>
>


|


|

|

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/*
 * Localization mapping for ofhttp.
 *
 * Copyright (c) 2017-2023 Jonathan Schleifer <js@nil.im>
 *
 * Permission to use, copy, modify, and/or distribute this mapping for any
 * purpose with or without fee is hereby granted.
 */

/* vim: se ft=javascript sw=4 et: */

{
    de: {
        "": "de"
    },
    deutsch: {
        "": "de"
    },
    german: {
        "": "de"
    },
}