ObjFW  Check-in [55aa600e97]

Overview
Comment:Merge trunk into branch "unix-sockets"
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | unix-sockets
Files: files | file ages | folders
SHA3-256: 55aa600e97f7a18c6bb141290661cfc0e308ec119482654ac873013f35214551
User & Date: js on 2021-10-24 13:40:22
Other Links: branch diff | manifest | tags
Context
2021-10-24
15:14
Add OFUNIXDatagramSocket check-in: 94110c9553 user: js tags: unix-sockets
13:40
Merge trunk into branch "unix-sockets" check-in: 55aa600e97 user: js tags: unix-sockets
11:15
OFScryptTests: Disable 3rd vector on AmigaOS/m68k check-in: 051b264d4a user: js tags: trunk
2021-04-25
20:25
Minor style fix check-in: 05dbd482bf user: js tags: unix-sockets
Changes

Added .github/workflows/amiga-gcc.yml version [16471286d2].











































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
name: amiga-gcc
on: [push, pull_request]
jobs:
  build:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        configure_flags:
          -
          - --disable-amiga-lib
    steps:
    - name: Install dependencies
      run: docker pull amigadev/crosstools:m68k-amigaos
    - uses: actions/checkout@v2
    - name: autogen.sh
      run: ./autogen.sh
    - name: configure
      run: |
        docker run \
          -e PATH="/opt/m68k-amigaos/bin:$PATH" \
          -v "$PWD:/objfw" \
          amigadev/crosstools:m68k-amigaos \
          sh -c 'cd /objfw && ./configure --host=m68k-amigaos ${{ matrix.configure_flags }}'
    - name: make
      run: |
        docker run \
          -e PATH="/opt/m68k-amigaos/bin:$PATH" \
          -v "$PWD:/objfw" \
          amigadev/crosstools:m68k-amigaos \
          sh -c "cd /objfw && make -j$(nproc)"
    - name: make install
      run: |
        docker run \
          -e PATH="/opt/m68k-amigaos/bin:$PATH" \
          -v "$PWD:/objfw" \
          amigadev/crosstools:m68k-amigaos \
          sh -c "cd /objfw && make -j$(nproc)"

Added .github/workflows/ios.yml version [dd34f22809].







































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
name: ios
on: [push, pull_request]
jobs:
  build:
    runs-on: macos-latest
    strategy:
      matrix:
        arch:
          - arm64
          - 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"
        else
          sdk="iphoneos"
        fi
        export OBJC="clang -isysroot $(xcrun --sdk $sdk --show-sdk-path)"
        export OBJC="$OBJC -arch ${{ matrix.arch }}"
        ./configure --host=${{ matrix.arch }}-apple-darwin \
          ${{ matrix.configure_flags }}
    - name: make
      run: make -j$(sysctl -n hw.logicalcpu)
    - name: make install
      run: sudo make install

Added .github/workflows/macos-10.15.yml version [0b4e6d02a3].































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
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-10.15
on: [push, pull_request]
jobs:
  tests:
    runs-on: macos-10.15
    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@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

Added .github/workflows/macos-11.yml version [d79ffc1fb9].































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
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-11
on: [push, pull_request]
jobs:
  tests:
    runs-on: macos-11
    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@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

Added .github/workflows/morphos.yml version [0f27c2ab37].











































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
name: morphos
on: [push, pull_request]
jobs:
  build:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        configure_flags:
          -
          - --disable-amiga-lib
    steps:
    - name: Install dependencies
      run: docker pull amigadev/crosstools:ppc-morphos
    - uses: actions/checkout@v2
    - name: autogen.sh
      run: ./autogen.sh
    - name: configure
      run: |
        docker run \
          -e PATH="/opt/ppc-morphos/bin:$PATH" \
          -v "$PWD:/objfw" \
          amigadev/crosstools:ppc-morphos \
          sh -c 'cd /objfw && ./configure --host=ppc-morphos ${{ matrix.configure_flags }}'
    - name: make
      run: |
        docker run \
          -e PATH="/opt/ppc-morphos/bin:$PATH" \
          -v "$PWD:/objfw" \
          amigadev/crosstools:ppc-morphos \
          sh -c "cd /objfw && make -j$(nproc)"
    - name: make install
      run: |
        docker run \
          -e PATH="/opt/ppc-morphos/bin:$PATH" \
          -v "$PWD:/objfw" \
          amigadev/crosstools:ppc-morphos \
          sh -c "cd /objfw && make -j$(nproc)"

Added .github/workflows/nintendo-3ds.yml version [67061ee611].







































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
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" \
          -v "$PWD:/objfw" \
          devkitpro/devkitarm \
          sh -c 'cd /objfw && ./configure --host=arm-none-eabi --with-3ds'
    - name: make
      run: |
        docker run \
          -e DEVKITPRO=/opt/devkitpro \
          -e PATH="/opt/devkitpro/devkitARM/bin:$PATH" \
          -v "$PWD:/objfw" \
          devkitpro/devkitarm \
          sh -c "cd /objfw && make -j$(nproc)"
    - name: make install
      run: |
        docker run \
          -e DEVKITPRO=/opt/devkitpro \
          -e PATH="/opt/devkitpro/devkitARM/bin:$PATH" \
          -v "$PWD:/objfw" \
          devkitpro/devkitarm \
          sh -c "cd /objfw && make -j$(nproc)"

Added .github/workflows/nintendo-ds.yml version [3d41e0f5f7].







































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
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" \
          -v "$PWD:/objfw" \
          devkitpro/devkitarm \
          sh -c 'cd /objfw && ./configure --host=arm-none-eabi --with-nds'
    - name: make
      run: |
        docker run \
          -e DEVKITPRO=/opt/devkitpro \
          -e PATH="/opt/devkitpro/devkitARM/bin:$PATH" \
          -v "$PWD:/objfw" \
          devkitpro/devkitarm \
          sh -c "cd /objfw && make -j$(nproc)"
    - name: make install
      run: |
        docker run \
          -e DEVKITPRO=/opt/devkitpro \
          -e PATH="/opt/devkitpro/devkitARM/bin:$PATH" \
          -v "$PWD:/objfw" \
          devkitpro/devkitarm \
          sh -c "cd /objfw && make -j$(nproc)"

Added .github/workflows/ubuntu-18.04-32bit.yml version [c84b2e26e8].







































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
name: ubuntu-18.04, 32 bit
on: [push, pull_request]
jobs:
  tests:
    runs-on: ubuntu-18.04
    strategy:
      matrix:
        configure_flags:
          -
          - --enable-seluid24
          - --disable-compiler-tls
          - --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
          - --disable-shared --enable-seluid24
          - --disable-compiler-tls --disable-threads
    steps:
    - name: Install dependencies
      run: sudo apt 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

Added .github/workflows/ubuntu-18.04-gcc-32bit.yml version [fffc9a783b].







































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
name: ubuntu-18.04, GCC, 32 bit
on: [push, pull_request]
jobs:
  tests:
    runs-on: ubuntu-18.04
    strategy:
      matrix:
        configure_flags:
          -
          - --enable-seluid24
          - --disable-compiler-tls
          - --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
          - --disable-shared --enable-seluid24
          - --disable-compiler-tls --disable-threads
    steps:
    - name: Install dependencies
      run: sudo apt 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

Added .github/workflows/ubuntu-18.04-gcc.yml version [abecbdd592].







































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
name: ubuntu-18.04, GCC
on: [push, pull_request]
jobs:
  tests:
    runs-on: ubuntu-18.04
    strategy:
      matrix:
        configure_flags:
          -
          - --enable-seluid24
          - --disable-compiler-tls
          - --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
          - --disable-shared --enable-seluid24
          - --disable-compiler-tls --disable-threads
    steps:
    - name: Install dependencies
      run: sudo apt install gobjc
    - 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

Added .github/workflows/ubuntu-18.04.yml version [1b051883aa].



































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
name: ubuntu-18.04
on: [push, pull_request]
jobs:
  tests:
    runs-on: ubuntu-18.04
    strategy:
      matrix:
        configure_flags:
          -
          - --enable-seluid24
          - --disable-compiler-tls
          - --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
          - --disable-shared --enable-seluid24
          - --disable-compiler-tls --disable-threads
    steps:
    - 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

Added .github/workflows/ubuntu-20.04-32bit.yml version [67fdadee3b].







































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
name: ubuntu-20.04, 32 bit
on: [push, pull_request]
jobs:
  tests:
    runs-on: ubuntu-20.04
    strategy:
      matrix:
        configure_flags:
          -
          - --enable-seluid24
          - --disable-compiler-tls
          - --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
          - --disable-shared --enable-seluid24
          - --disable-compiler-tls --disable-threads
    steps:
    - name: Install dependencies
      run: sudo apt 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

Added .github/workflows/ubuntu-20.04-gcc-32bit.yml version [77cd8547b9].







































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
name: ubuntu-20.04, GCC, 32 bit
on: [push, pull_request]
jobs:
  tests:
    runs-on: ubuntu-20.04
    strategy:
      matrix:
        configure_flags:
          -
          - --enable-seluid24
          - --disable-compiler-tls
          - --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
          - --disable-shared --enable-seluid24
          - --disable-compiler-tls --disable-threads
    steps:
    - name: Install dependencies
      run: sudo apt 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

Added .github/workflows/ubuntu-20.04-gcc.yml version [722d29b103].







































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
name: ubuntu-20.04, GCC
on: [push, pull_request]
jobs:
  tests:
    runs-on: ubuntu-20.04
    strategy:
      matrix:
        configure_flags:
          -
          - --enable-seluid24
          - --disable-compiler-tls
          - --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
          - --disable-shared --enable-seluid24
          - --disable-compiler-tls --disable-threads
    steps:
    - name: Install dependencies
      run: sudo apt install gobjc
    - 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

Added .github/workflows/ubuntu-20.04.yml version [b1e6e1b321].



































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
name: ubuntu-20.04
on: [push, pull_request]
jobs:
  tests:
    runs-on: ubuntu-20.04
    strategy:
      matrix:
        configure_flags:
          -
          - --enable-seluid24
          - --disable-compiler-tls
          - --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
          - --disable-shared --enable-seluid24
          - --disable-compiler-tls --disable-threads
    steps:
    - 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

Added .github/workflows/wii.yml version [39c842705b].







































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
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" \
          -v "$PWD:/objfw" \
          devkitpro/devkitppc \
          sh -c 'cd /objfw && ./configure --host=powerpc-eabi --with-wii'
    - name: make
      run: |
        docker run \
          -e DEVKITPRO=/opt/devkitpro \
          -e PATH="/opt/devkitpro/devkitPPC/bin:$PATH" \
          -v "$PWD:/objfw" \
          devkitpro/devkitppc \
          sh -c "cd /objfw && make -j$(nproc)"
    - name: make install
      run: |
        docker run \
          -e DEVKITPRO=/opt/devkitpro \
          -e PATH="/opt/devkitpro/devkitPPC/bin:$PATH" \
          -v "$PWD:/objfw" \
          devkitpro/devkitppc \
          sh -c "cd /objfw && make -j$(nproc)"

Modified Doxyfile from [51b1f8245c] to [c1793ad29f].

1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
PROJECT_NAME = "ObjFW"
OUTPUT_DIRECTORY = docs/
INPUT = src src/exceptions src/runtime
FILE_PATTERNS = *.h *.m
HTML_OUTPUT = .
GENERATE_LATEX = NO
HIDE_UNDOC_CLASSES = YES
HIDE_UNDOC_MEMBERS = YES

PREDEFINED = __OBJC__				\
	     DOXYGEN				\
	     OF_BOXABLE				\
	     OF_CONSUMED			\
	     OF_DESIGNATED_INITIALIZER		\
	     OF_GENERIC(...)=			\
	     OF_HAVE_BLOCKS			\








>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
PROJECT_NAME = "ObjFW"
OUTPUT_DIRECTORY = docs/
INPUT = src src/exceptions src/runtime
FILE_PATTERNS = *.h *.m
HTML_OUTPUT = .
GENERATE_LATEX = NO
HIDE_UNDOC_CLASSES = YES
HIDE_UNDOC_MEMBERS = YES
TYPEDEF_HIDES_STRUCT = YES
PREDEFINED = __OBJC__				\
	     DOXYGEN				\
	     OF_BOXABLE				\
	     OF_CONSUMED			\
	     OF_DESIGNATED_INITIALIZER		\
	     OF_GENERIC(...)=			\
	     OF_HAVE_BLOCKS			\

Modified Makefile from [b5f8b9bb2c] to [63e28abf9d].

12
13
14
15
16
17
18



19
20
21
22
23
24
25

include buildsys.mk

.PHONY: docs release

utils tests: src




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

release: docs
	echo "Generating tarball for version ${PACKAGE_VERSION}..."
	rm -fr objfw-${PACKAGE_VERSION} objfw-${PACKAGE_VERSION}.tar \







>
>
>







12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

include buildsys.mk

.PHONY: docs release

utils tests: src

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

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

release: docs
	echo "Generating tarball for version ${PACKAGE_VERSION}..."
	rm -fr objfw-${PACKAGE_VERSION} objfw-${PACKAGE_VERSION}.tar \

Modified README.md from [c56b6e4a95] to [df7d0bd20b].

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

 * On [ObjFW](https://objfw.nil.im/)'s homepage, via Fossil
 * On [GitHub](https://github.com/ObjFW/ObjFW)
 * Via an editor or pager, by opening `README.md` from a checkout 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)
     * [Updating MSYS2](#updating-msys2)
     * [Installing MinGW-w64 using MSYS2](#installing-mingw-w64)
     * [Getting, building and installing ObjFW](#steps-windows)
   * [Nintendo DS, Nintendo 3DS and Wii](#nintendo)
     * [Nintendo DS](#nintendo-ds)
     * [Nintendo 3DS](#nintendo-3ds)
     * [Wii](#wii)
   * [Amiga](#amiga)
 * [Writing your first application with ObjFW](#first-app)


|

|


















|
<







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

25
26
27
28
29
30
31
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)

     * [Getting, building and installing ObjFW](#steps-windows)
   * [Nintendo DS, Nintendo 3DS and Wii](#nintendo)
     * [Nintendo DS](#nintendo-ds)
     * [Nintendo 3DS](#nintendo-3ds)
     * [Wii](#wii)
   * [Amiga](#amiga)
 * [Writing your first application with ObjFW](#first-app)
104
105
106
107
108
109
110
111
112
113
114
115
116
117

118
119
120
121
122
123
124
  The main advantage of cloning the Fossil repository over cloning the Git
  repository is that you also get all the tickets, wiki pages, etc.

<h2 id="cloning-fossil">Fossil</h2>

  Clone the Fossil repository like this:

    $ fossil clone https://objfw.nil.im objfw.fossil
    $ mkdir objfw && cd objfw
    $ fossil open ../objfw.fossil

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


    $ 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







|
<
<




>







103
104
105
106
107
108
109
110


111
112
113
114
115
116
117
118
119
120
121
122
  The main advantage of cloning the Fossil repository over cloning the Git
  repository is that you also get all the tickets, wiki pages, etc.

<h2 id="cloning-fossil">Fossil</h2>

  Clone the Fossil repository like this:

    $ fossil clone https://objfw.nil.im



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

  To build for iOS, use 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=arm-apple-darwin

  To build for the iOS simulator, use something like this:

    $ clang="clang -isysroot $(xcrun --sdk iphonesimulator --show-sdk-path)"
    $ export OBJC="$clang -arch i386 -arch x86_64"
    $ export OBJCPP="$clang -arch i386 -E"
    $ export IPHONEOS_DEPLOYMENT_TARGET="9.0"
    $ ./configure --prefix=/usr/local/iossim --host=i386-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







|
|



















|







|







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
  individual commit, branch head or tag, please use Fossil.

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

  To install ObjFW, just run the following commands:

    $ ./configure
    $ 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`.

  To build for iOS, use 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, use something like this:

    $ clang="clang -isysroot $(xcrun --sdk iphonesimulator --show-sdk-path)"
    $ export OBJC="$clang -arch i386 -arch x86_64"
    $ export OBJCPP="$clang -arch i386 -E"
    $ export IPHONEOS_DEPLOYMENT_TARGET="9.0"
    $ ./configure --prefix=/usr/local/iossim --host=x86_64-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
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
  there are many MinGW versions that behave slightly differently and often
  cause problems.

<h3 id="getting-msys2">Getting MSYS2</h3>

  The first thing to install is [MSYS2](https://www.msys2.org) to provide a
  basic UNIX-like environment for Windows. Unfortunately, the binaries are not
  signed and there is no way to verify their integrity, so only download this
  from a trusted connection. Everything else you will download using MSYS2
  later will be cryptographically signed.

<h3 id="updating-msys2">Updating MSYS2</h3>

  The first thing to do is updating MSYS2. It is important to update things in
  a certain order, as `pacman` (the package manager MSYS2 uses, which comes
  from Arch Linux) does not know about a few things that are special on
  Windows.

  First, update the mirror list:

    $ pacman -Sy pacman-mirrors


  Then proceed to update the `msys2-runtime` itself, `bash` and `pacman`:


    $ pacman -S msys2-runtime bash pacman mintty

  Now close the current window and restart MSYS2, as the current window is now
  defunct. In a new MSYS2 window, update the rest of MSYS2:


    $ pacman -Su

  Now you have a fully updated MSYS2. Whenever you want to update MSYS2,
  proceed in this order. Notice that the first `pacman` invocation includes
  `-y` to actually fetch a new list of packages.

<h3 id="installing-mingw-w64">Installing MinGW-w64 using MSYS2</h3>

  Now it's time to install MinGW-w64. If you want to build 32 bit binaries:


    $ pacman -S mingw-w64-i686-clang mingw-w64-i686-gcc-objc

  For 64 bit binaries:


    $ pacman -S mingw-w64-x86_64-clang mingw-w64-x86_64-gcc-objc

  There is nothing wrong with installing them both, as MSYS2 has created two
  entries in your start menu: `MinGW-w64 Win32 Shell` and
  `MinGW-w64 Win64 Shell`. So if you want to build for 32 or 64 bit, you just
  start the correct shell.

  Finally, install a few more things needed to build ObjFW:

    $ pacman -S autoconf automake fossil make

<h3 id="steps-windows">Getting, building and installing ObjFW</h3>

  Start the MinGW-w64 Win32 or Win64 Shell (depening on what version you want
  to build - do *not* use the MSYS2 Shell shortcut, but use the MinGW-w64 Win32
  or Win64 Shell shortcut instead!) and check out ObjFW:

    $ fossil clone https://objfw.nil.im objfw.fossil
    $ mkdir objfw && cd objfw
    $ fossil open ../objfw.fossil

  You can also download a release tarball if you want. Now go to the newly
  checked out repository and build and install it:

    $ ./autogen.sh && ./configure && make -j16 install

  If everything was successfully, you can now build projects using ObjFW for
  Windows using the normal `objfw-compile` and friends.

<h2 id="nintendo">Nintendo DS, Nintendo 3DS and Wii</h2>

  Download and install [devkitPro](https://devkitpro.org/wiki/Getting_Started).

<h3 id="nintendo-ds">Nintendo DS</h3>







|
<
|

|

<
|
<
<
|
<
|
<
>

<
>

|

<
<
>

|

|
<
<

|

<
>

|

<
|
>
|

|
|
<
|

|

|



|
<
|

|
<
<

|




|







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
  there are many MinGW versions that behave slightly differently and often
  cause problems.

<h3 id="getting-msys2">Getting MSYS2</h3>

  The first thing to install is [MSYS2](https://www.msys2.org) to provide a
  basic UNIX-like environment for Windows. Unfortunately, the binaries are not
  signed, so make sure you download it via HTTPS. However, packages you

  download and install via MSYS2 are cryptographically signed.

<h3 id="setting-up-msys2">Setting up MSYS2</h3>


  MSYS2 currently supports 5 different


  [environments](https://www.msys2.org/docs/environments/). All of them except

  for the one called just "MSYS" are supported, but which packages you need to

  install depends on the environment(s) you want to use.


  For MINGW64, use:

    $ pacman -Syu mingw-w64-x86_64-clang mingw-w64-x86_64-fossil



  For UCRT64, use:

    $ pacman -Syu mingw-w64-ucrt-x86_64-clang mingw-w64-ucrt-x86_64-fossil

  For CLANG64, use:



    $ pacman -Syu mingw-w64-clang-x86_64-clang mingw-w64-clang-x86_64-fossil


  For MINGW32, use:

    $ pacman -Syu mingw-w64-i686-clang mingw-w64-i686-fossil


  When using `pacman` to install the packages, `pacman` might tell you to close
  the window. If it does so, close the window, restart MSYS2 and execute the
  `pacman` command again.

  There is nothing wrong with installing multiple environments, as MSYS2 has
  created shortcuts for each of them in your start menu. Just make sure to use

  the correct shortcut for the environment you want to use.

  Finally, install a few more things that are common between all environments:

    $ pacman -S autoconf automake make

<h3 id="steps-windows">Getting, building and installing ObjFW</h3>

  Start the MSYS2 using the shortcut for the environment you want to use and

  check out ObjFW:

    $ fossil clone https://objfw.nil.im



  You can also download a release tarball if you want. Now `cd` to the newly
  checked out repository and build and install it:

    $ ./autogen.sh && ./configure && make -j16 install

  If everything was successful, you can now build projects using ObjFW for
  Windows using the normal `objfw-compile` and friends.

<h2 id="nintendo">Nintendo DS, Nintendo 3DS and Wii</h2>

  Download and install [devkitPro](https://devkitpro.org/wiki/Getting_Started).

<h3 id="nintendo-ds">Nintendo DS</h3>

Modified build-aux/m4/buildsys.m4 from [8a8480cbc5] to [3c7fd1fbe8].

18
19
20
21
22
23
24



25
26
27
28
29
30
31
dnl SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
dnl INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
dnl CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
dnl ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
dnl POSSIBILITY OF SUCH DAMAGE.
dnl




AC_DEFUN([BUILDSYS_INIT], [
	AC_REQUIRE([AC_CANONICAL_BUILD])
	AC_REQUIRE([AC_CANONICAL_HOST])

	case "$build_os" in
	darwin*)
		case "$host_os" in







>
>
>







18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
dnl SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
dnl INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
dnl CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
dnl ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
dnl POSSIBILITY OF SUCH DAMAGE.
dnl

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

AC_DEFUN([BUILDSYS_INIT], [
	AC_REQUIRE([AC_CANONICAL_BUILD])
	AC_REQUIRE([AC_CANONICAL_HOST])

	case "$build_os" in
	darwin*)
		case "$host_os" in
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
	*-*-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'

		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,--out-implib,lib$$out.a'
		LIB_LDFLAGS_INSTALL_NAME=''
		LIB_PREFIX=''
		LIB_SUFFIX='.dll'
		LDFLAGS_RPATH='-Wl,-rpath,${libdir}'
		PLUGIN_CFLAGS=''
		PLUGIN_LDFLAGS='-shared'
		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.a ${DESTDIR}${libdir}/lib$$i.a'
		UNINSTALL_LIB='&& rm -f ${DESTDIR}${bindir}/$$i ${DESTDIR}${libdir}/lib$$i.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}'

		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'

		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'
		LDFLAGS_RPATH=''
		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'

		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'

		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'

		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'







>
|
>

















|


|
<




|












>
|
>

















>
|
>

















<


















>
|
>


















>
|
>

















>
|
>







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
	*-*-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,--out-implib,lib$${out%${LIB_SUFFIX}}.a'
		LIB_LDFLAGS_INSTALL_NAME=''
		LIB_PREFIX=''
		LIB_SUFFIX='${LIB_MAJOR}.dll'

		PLUGIN_CFLAGS=''
		PLUGIN_LDFLAGS='-shared'
		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}}.a ${DESTDIR}${libdir}/lib$${i%${LIB_SUFFIX}}.a'
		UNINSTALL_LIB='&& rm -f ${DESTDIR}${bindir}/$$i ${DESTDIR}${libdir}/lib$$i.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'

Modified buildsys.mk.in from [b068b3ae0b] to [a085f99653].

208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
		${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} ${COPY_HEADERS_DESTINATION} || 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 \







|







208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
		${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 \
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
		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} ${DESTDIR}${includedir}/${includesubdir} && ${INSTALL} -m 644 $$i ${DESTDIR}${includedir}/${includesubdir}/$$i; then \
				${INSTALL_OK}; \
			else \
				${INSTALL_FAILED}; \
			fi \
		done \
	fi








|







729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
		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

Modified configure.ac from [ba1c6c3513] to [75effab5fc].

1
2
3
4
5
6
7
8
AC_INIT(ObjFW, 1.1-dev, 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)
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
45
46
47
48
49
50
51
52

53
54
55
56
57
58
59
	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, objfwrt68k.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)
	])







|
>







45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
	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${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)
	])
76
77
78
79
80
81
82
83

84
85
86
87
88
89
90
	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.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)







|
>







77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
	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)
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
		OBJCFLAGS="$OBJCFLAGS -integrated-as"
		OBJFW_OBJCFLAGS="$OBJFW_OBJCFLAGS -integrated-as"
		;;
	i?86-*-darwin* | x86_64-*-darwin*)
		dnl Don't use -no-integrated-as on Darwin. It breaks building
		dnl for the iOS simulator.
		;;
	i?86-*-* | x86_64-*-*)
		dnl Many older Clang versions don't support jmp short.
		ASFLAGS="$ASFLAGS -no-integrated-as"
		;;
	*-*-mingw*)
		dnl Clang's assembler on Windows is not complete yet and cannot
		dnl compile all .S files.
		ASFLAGS="$ASFLAGS -no-integrated-as"
		;;
	sparc64-*-*openbsd*)
		dnl Clang generates assembly output on SPARC64 that OpenBSD's
		dnl assembler does not accept.
		flag="-integrated-as"
		OBJCFLAGS="$OBJCFLAGS $flag"
		OBJFW_OBJCFLAGS="$OBJFW_OBJCFLAGS $flag"
		;;







<
<
<
<
<
<
<
<
<







258
259
260
261
262
263
264









265
266
267
268
269
270
271
		OBJCFLAGS="$OBJCFLAGS -integrated-as"
		OBJFW_OBJCFLAGS="$OBJFW_OBJCFLAGS -integrated-as"
		;;
	i?86-*-darwin* | x86_64-*-darwin*)
		dnl Don't use -no-integrated-as on Darwin. It breaks building
		dnl for the iOS simulator.
		;;









	sparc64-*-*openbsd*)
		dnl Clang generates assembly output on SPARC64 that OpenBSD's
		dnl assembler does not accept.
		flag="-integrated-as"
		OBJCFLAGS="$OBJCFLAGS $flag"
		OBJFW_OBJCFLAGS="$OBJFW_OBJCFLAGS $flag"
		;;
975
976
977
978
979
980
981

982
983
984
985
986
987
988
		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])
	AC_SUBST(USE_SRCS_THREADS, '${SRCS_THREADS}')


	AC_ARG_ENABLE(compiler-tls,
		AS_HELP_STRING([--disable-compiler-tls],
			[disable compiler thread local storage]))

	case "$host" in
	aarch64*-*-android*)







>







968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
		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])
	AC_SUBST(USE_SRCS_THREADS, '${SRCS_THREADS}')
	AC_SUBST(OBJC_SYNC, objc_sync)

	AC_ARG_ENABLE(compiler-tls,
		AS_HELP_STRING([--disable-compiler-tls],
			[disable compiler thread local storage]))

	case "$host" in
	aarch64*-*-android*)
1367
1368
1369
1370
1371
1372
1373



1374
1375
1376
1377
1378
1379
1380
			#ifdef AF_INET6
			egrep_cpp_yes
			#endif
		], [
			AC_DEFINE(OF_HAVE_IPV6, 1, [Whether we have IPv6])
		])
	], [



	], [
		#ifdef _WIN32
		typedef int BOOL;
		#endif

		#ifdef OF_HAVE_NETINET_IN_H
		# include <netinet/in.h>







>
>
>







1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
			#ifdef AF_INET6
			egrep_cpp_yes
			#endif
		], [
			AC_DEFINE(OF_HAVE_IPV6, 1, [Whether we have IPv6])
		])
	], [
		dnl Work around a bug in autoconf 2.61 that creates a broken
		dnl configure if this branch is empty.
		:
	], [
		#ifdef _WIN32
		typedef int BOOL;
		#endif

		#ifdef OF_HAVE_NETINET_IN_H
		# include <netinet/in.h>
1837
1838
1839
1840
1841
1842
1843





1844
1845
1846
1847
1848
1849
1850
			#ifdef __has_attribute
			# if __has_attribute(objc_root_class)
			__attribute__((__objc_root_class__))
			# endif
			#endif
			@interface Test
			@end





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







>
>
>
>
>







1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
			#ifdef __has_attribute
			# if __has_attribute(objc_root_class)
			__attribute__((__objc_root_class__))
			# endif
			#endif
			@interface Test
			@end

			/**
			 * @struct Foo conftest.m conftest.m
			 */
			typedef struct {} Foo;
		])
	], [
		AC_MSG_RESULT(yes)
	], [
		AC_MSG_RESULT(no)
		OBJCFLAGS="$old_OBJCFLAGS"
	])
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
		;;
	x86_64-*-mingw*)
		AC_CHECK_PROG(WINE, wine64, wine64)
		;;
	esac

	AS_IF([test x"$WINE" != x""], [
		AC_SUBST(RUN_TESTS, "run")
		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_SUBST(RUN_TESTS, "run")
])

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)







<













<
<







1922
1923
1924
1925
1926
1927
1928

1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941


1942
1943
1944
1945
1946
1947
1948
		;;
	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)

Modified extra.mk.in from [70070944b6] to [40ab3148ac].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
OBJFW_SHARED_LIB = @OBJFW_SHARED_LIB@
OBJFW_STATIC_LIB = @OBJFW_STATIC_LIB@
OBJFW_FRAMEWORK = @OBJFW_FRAMEWORK@
OBJFW_LIB_MAJOR = 9
OBJFW_LIB_MINOR = 1
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 = 1
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@




|
|






|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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@

34
35
36
37
38
39
40

41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
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@

OFARC = @OFARC@
OFDNS = @OFDNS@
OFHASH = @OFHASH@
OFHTTP = @OFHTTP@
OF_BLOCK_TESTS_M = @OF_BLOCK_TESTS_M@
OF_EPOLL_KERNEL_EVENT_OBSERVER_M = @OF_EPOLL_KERNEL_EVENT_OBSERVER_M@
OF_HTTP_CLIENT_TESTS_M = @OF_HTTP_CLIENT_TESTS_M@
OF_KQUEUE_KERNEL_EVENT_OBSERVER_M = @OF_KQUEUE_KERNEL_EVENT_OBSERVER_M@
OF_POLL_KERNEL_EVENT_OBSERVER_M = @OF_POLL_KERNEL_EVENT_OBSERVER_M@
OF_SELECT_KERNEL_EVENT_OBSERVER_M = @OF_SELECT_KERNEL_EVENT_OBSERVER_M@
OF_SUBPROCESS_M = @OF_SUBPROCESS_M@
REEXPORT_RUNTIME = @REEXPORT_RUNTIME@
REEXPORT_RUNTIME_FRAMEWORK = @REEXPORT_RUNTIME_FRAMEWORK@
RUNTIME = @RUNTIME@
RUNTIME_ARC_TESTS_M = @RUNTIME_ARC_TESTS_M@
RUNTIME_AUTORELEASE_M = @RUNTIME_AUTORELEASE_M@
RUNTIME_FRAMEWORK_LIBS = @RUNTIME_FRAMEWORK_LIBS@
RUNTIME_INSTANCE_M = @RUNTIME_INSTANCE_M@
RUNTIME_LIBS = @RUNTIME_LIBS@
RUN_TESTS = @RUN_TESTS@
SFDC_INLINE_H = @SFDC_INLINE_H@
SFDC_TARGET = @SFDC_TARGET@
SFD_FILE = @SFD_FILE@
TESTPLUGIN = @TESTPLUGIN@
TESTPLUGIN_LIBS = @TESTPLUGIN_LIBS@
TESTS_LIBS = @TESTS_LIBS@
TESTS_STATIC_LIB = @TESTS_STATIC_LIB@







>



















<







34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60

61
62
63
64
65
66
67
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@
OFARC = @OFARC@
OFDNS = @OFDNS@
OFHASH = @OFHASH@
OFHTTP = @OFHTTP@
OF_BLOCK_TESTS_M = @OF_BLOCK_TESTS_M@
OF_EPOLL_KERNEL_EVENT_OBSERVER_M = @OF_EPOLL_KERNEL_EVENT_OBSERVER_M@
OF_HTTP_CLIENT_TESTS_M = @OF_HTTP_CLIENT_TESTS_M@
OF_KQUEUE_KERNEL_EVENT_OBSERVER_M = @OF_KQUEUE_KERNEL_EVENT_OBSERVER_M@
OF_POLL_KERNEL_EVENT_OBSERVER_M = @OF_POLL_KERNEL_EVENT_OBSERVER_M@
OF_SELECT_KERNEL_EVENT_OBSERVER_M = @OF_SELECT_KERNEL_EVENT_OBSERVER_M@
OF_SUBPROCESS_M = @OF_SUBPROCESS_M@
REEXPORT_RUNTIME = @REEXPORT_RUNTIME@
REEXPORT_RUNTIME_FRAMEWORK = @REEXPORT_RUNTIME_FRAMEWORK@
RUNTIME = @RUNTIME@
RUNTIME_ARC_TESTS_M = @RUNTIME_ARC_TESTS_M@
RUNTIME_AUTORELEASE_M = @RUNTIME_AUTORELEASE_M@
RUNTIME_FRAMEWORK_LIBS = @RUNTIME_FRAMEWORK_LIBS@
RUNTIME_INSTANCE_M = @RUNTIME_INSTANCE_M@
RUNTIME_LIBS = @RUNTIME_LIBS@

SFDC_INLINE_H = @SFDC_INLINE_H@
SFDC_TARGET = @SFDC_TARGET@
SFD_FILE = @SFD_FILE@
TESTPLUGIN = @TESTPLUGIN@
TESTPLUGIN_LIBS = @TESTPLUGIN_LIBS@
TESTS_LIBS = @TESTS_LIBS@
TESTS_STATIC_LIB = @TESTS_STATIC_LIB@

Modified generators/library/FuncArrayGenerator.m from [51e8f1d0df] to [f08469b1f3].

63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
	[super dealloc];
}

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

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







|
|







63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
	[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

Modified generators/library/GlueGenerator.m from [31aa00cfbb] to [bedf754a5e].

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

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

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

	[_impl writeString:
	    @"/* This file is automatically generated from 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];







|
|


|
|







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

- (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];

Modified generators/library/LibraryGenerator.m from [5e005ae799] to [9ff3856624].

32
33
34
35
36
37
38
39
40
41
42
43
44
45
46

@implementation LibraryGenerator
- (void)applicationDidFinishLaunching
{
	OFURL *sourcesURL = [[OFFileManager defaultManager].currentDirectoryURL
	    URLByAppendingPathComponent: @"../../src"];
	OFURL *runtimeLibraryURL = [sourcesURL
	    URLByAppendingPathComponent: @"runtime/library.xml"];
	OFURL *runtimeLinkLibURL = [sourcesURL
	    URLByAppendingPathComponent: @"runtime/linklib/linklib.m"];
	OFURL *runtimeGlueHeaderURL = [sourcesURL
	    URLByAppendingPathComponent: @"runtime/amiga-glue.h"];
	OFURL *runtimeGlueURL = [sourcesURL
	    URLByAppendingPathComponent: @"runtime/amiga-glue.m"];
	OFURL *runtimeFuncArrayURL = [sourcesURL







|







32
33
34
35
36
37
38
39
40
41
42
43
44
45
46

@implementation LibraryGenerator
- (void)applicationDidFinishLaunching
{
	OFURL *sourcesURL = [[OFFileManager defaultManager].currentDirectoryURL
	    URLByAppendingPathComponent: @"../../src"];
	OFURL *runtimeLibraryURL = [sourcesURL
	    URLByAppendingPathComponent: @"runtime/amiga-library.xml"];
	OFURL *runtimeLinkLibURL = [sourcesURL
	    URLByAppendingPathComponent: @"runtime/linklib/linklib.m"];
	OFURL *runtimeGlueHeaderURL = [sourcesURL
	    URLByAppendingPathComponent: @"runtime/amiga-glue.h"];
	OFURL *runtimeGlueURL = [sourcesURL
	    URLByAppendingPathComponent: @"runtime/amiga-glue.m"];
	OFURL *runtimeFuncArrayURL = [sourcesURL

Modified generators/library/LinkLibGenerator.m from [39332583d0] to [eb1406f394].

67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
{
	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 library.xml */\n"
	    @"\n"
	    @"#include \"config.h\"\n"
	    @"\n"];

	for (OFXMLElement *include in [_library elementsForName: @"include"])
		[_impl writeFormat: @"#import \"%@\"\n",
				    include.stringValue];








|
|







67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
{
	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];

Modified generators/library/Makefile from [7064d263a2] to [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
include ../../extra.mk

PROG_NOINST = gen_libraries${PROG_SUFFIX}
SRCS = FuncArrayGenerator.m	\
       GlueGenerator.m		\
       LibraryGenerator.m	\
       LinkLibGenerator.m



.PHONY: run
run: all
	rm -f libobjfw.so.${OBJFW_LIB_MAJOR}
	rm -f libobjfw.so.${OBJFW_LIB_MAJOR_MINOR}
	rm -f objfw.dll libobjfw.${OBJFW_LIB_MAJOR}.dylib
	rm -f libobjfwrt.so.${OBJFWRT_LIB_MAJOR}
	rm -f libobjfwrt.so.${OBJFWRT_LIB_MAJOR_MINOR}

	rm -f objfwrt.dll 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.dll; then \
		${LN_S} ../../src/objfw.dll objfw.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.dll; then \
		${LN_S} ../../src/runtime/objfwrt.dll objfwrt.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 objfw.so.${OBJFW_LIB_MAJOR_MINOR} objfw.dll; \

	rm -f libobjfw.${OBJFW_LIB_MAJOR}.dylib; \
	rm -f libobjfwrt.so.${OBJFWRT_LIB_MAJOR}; \
	rm -f objfwrt.so.${OBJFWRT_LIB_MAJOR_MINOR} objfwrt.dll; \

	rm -f libobjfwrt.${OBJFWRT_LIB_MAJOR}.dylib; \
	exit $$EXIT

include ../../buildsys.mk

CPPFLAGS += -I../../src -I../../src/exceptions -I../../src/runtime -I../..
LIBS := -L../../src -lobjfw -L../../src/runtime ${RUNTIME_LIBS} ${LIBS}
LD = ${OBJC}








>
>




|


>
|









|
|
>













|
|
>
















|
>


|
>



<
<



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
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}

Modified generators/unicode/Makefile from [c6ebd60fbb] to [9009fb89e7].

1
2
3
4
5


6
7
8
9
10
11
12

13
14
15
16
17
18
19
20
21
22
23
24

25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

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

57
58
59

60
61
62
63
64
65
66
67
include ../../extra.mk

PROG_NOINST = gen_tables${PROG_SUFFIX}
SRCS = TableGenerator.m



.PHONY: run
run: all
	rm -f libobjfw.so.${OBJFW_LIB_MAJOR}
	rm -f libobjfw.so.${OBJFW_LIB_MAJOR_MINOR}
	rm -f objfw.dll libobjfw.${OBJFW_LIB_MAJOR}.dylib
	rm -f libobjfwrt.so.${OBJFWRT_LIB_MAJOR}
	rm -f libobjfwrt.so.${OBJFWRT_LIB_MAJOR_MINOR}

	rm -f objfwrt.dll 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.dll; then \
		${LN_S} ../../src/objfw.dll objfw.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.dll; then \
		${LN_S} ../../src/runtime/objfwrt.dll objfwrt.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 objfw.so.${OBJFW_LIB_MAJOR_MINOR} objfw.dll; \

	rm -f libobjfw.${OBJFW_LIB_MAJOR}.dylib; \
	rm -f libobjfwrt.so.${OBJFWRT_LIB_MAJOR}; \
	rm -f objfwrt.so.${OBJFWRT_LIB_MAJOR_MINOR} objfwrt.dll; \

	rm -f libobjfwrt.${OBJFWRT_LIB_MAJOR}.dylib; \
	exit $$EXIT

include ../../buildsys.mk

CPPFLAGS += -I../../src -I../../src/exceptions -I../../src/runtime -I../..
LIBS := -L../../src -lobjfw -L../../src/runtime ${RUNTIME_LIBS} ${LIBS}
LD = ${OBJC}





>
>




|


>
|









|
|
>













|
|
>
















|
>


|
>



<
<



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


70
71
72
include ../../extra.mk

PROG_NOINST = gen_tables${PROG_SUFFIX}
SRCS = TableGenerator.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}

Added objfw.spec version [c6704c25c0].













































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
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
%global libobjfw_major 0
%global libobjfw_minor 0
%global libobjfwrt_major 0
%global libobjfwrt_minor 0
%if 0%{?suse_version}
%global libobjfw_pkgname libobjfw%{libobjfw_major}
%global libobjfwrt_pkgname libobjfwrt%{libobjfwrt_major}
%else
%global libobjfw_pkgname libobjfw
%global libobjfwrt_pkgname libobjfwrt
%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
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 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 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 for %{libobjfwrt_pkgname}
Requires:      %{libobjfwrt_pkgname}%{_isa} = %{version}-%{release}

%description -n %{libobjfwrt_pkgname}-devel
The %{libobjfwrt_pkgname}-devel package contains header files for ObjFW's
Objective-C runtime library.

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

%description -n ofhttp
ofhttp is a command line downloader for HTTP and HTTPS (via ObjOpenSSL) 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 --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
%{_includedir}/ObjFW/OFASPrintF.h
%{_includedir}/ObjFW/OFAcceptFailedException.h
%{_includedir}/ObjFW/OFAllocFailedException.h
%{_includedir}/ObjFW/OFAlreadyConnectedException.h
%{_includedir}/ObjFW/OFApplication.h
%{_includedir}/ObjFW/OFArray.h
%{_includedir}/ObjFW/OFAtomic.h
%{_includedir}/ObjFW/OFBase64.h
%{_includedir}/ObjFW/OFBindFailedException.h
%{_includedir}/ObjFW/OFBlock.h
%{_includedir}/ObjFW/OFCRC16.h
%{_includedir}/ObjFW/OFCRC32.h
%{_includedir}/ObjFW/OFChangeCurrentDirectoryPathFailedException.h
%{_includedir}/ObjFW/OFCharacterSet.h
%{_includedir}/ObjFW/OFChecksumMismatchException.h
%{_includedir}/ObjFW/OFCollection.h
%{_includedir}/ObjFW/OFColor.h
%{_includedir}/ObjFW/OFCondition.h
%{_includedir}/ObjFW/OFConditionBroadcastFailedException.h
%{_includedir}/ObjFW/OFConditionSignalFailedException.h
%{_includedir}/ObjFW/OFConditionStillWaitingException.h
%{_includedir}/ObjFW/OFConditionWaitFailedException.h
%{_includedir}/ObjFW/OFConnectionFailedException.h
%{_includedir}/ObjFW/OFConstantString.h
%{_includedir}/ObjFW/OFCopyItemFailedException.h
%{_includedir}/ObjFW/OFCountedSet.h
%{_includedir}/ObjFW/OFCreateDirectoryFailedException.h
%{_includedir}/ObjFW/OFCreateSymbolicLinkFailedException.h
%{_includedir}/ObjFW/OFCryptographicHash.h
%{_includedir}/ObjFW/OFDNSQuery.h
%{_includedir}/ObjFW/OFDNSQueryFailedException.h
%{_includedir}/ObjFW/OFDNSResolver.h
%{_includedir}/ObjFW/OFDNSResourceRecord.h
%{_includedir}/ObjFW/OFDNSResponse.h
%{_includedir}/ObjFW/OFData+CryptographicHashing.h
%{_includedir}/ObjFW/OFData+MessagePackParsing.h
%{_includedir}/ObjFW/OFData.h
%{_includedir}/ObjFW/OFDatagramSocket.h
%{_includedir}/ObjFW/OFDate.h
%{_includedir}/ObjFW/OFDictionary.h
%{_includedir}/ObjFW/OFEnumerationMutationException.h
%{_includedir}/ObjFW/OFEnumerator.h
%{_includedir}/ObjFW/OFException.h
%{_includedir}/ObjFW/OFFile.h
%{_includedir}/ObjFW/OFFileManager.h
%{_includedir}/ObjFW/OFGZIPStream.h
%{_includedir}/ObjFW/OFGetCurrentDirectoryPathFailedException.h
%{_includedir}/ObjFW/OFGetOptionFailedException.h
%{_includedir}/ObjFW/OFHMAC.h
%{_includedir}/ObjFW/OFHTTPClient.h
%{_includedir}/ObjFW/OFHTTPCookie.h
%{_includedir}/ObjFW/OFHTTPCookieManager.h
%{_includedir}/ObjFW/OFHTTPRequest.h
%{_includedir}/ObjFW/OFHTTPRequestFailedException.h
%{_includedir}/ObjFW/OFHTTPResponse.h
%{_includedir}/ObjFW/OFHTTPServer.h
%{_includedir}/ObjFW/OFHashAlreadyCalculatedException.h
%{_includedir}/ObjFW/OFHuffmanTree.h
%{_includedir}/ObjFW/OFINICategory.h
%{_includedir}/ObjFW/OFINIFile.h
%{_includedir}/ObjFW/OFIPXSocket.h
%{_includedir}/ObjFW/OFInflate64Stream.h
%{_includedir}/ObjFW/OFInflateStream.h
%{_includedir}/ObjFW/OFInitializationFailedException.h
%{_includedir}/ObjFW/OFInvalidArgumentException.h
%{_includedir}/ObjFW/OFInvalidEncodingException.h
%{_includedir}/ObjFW/OFInvalidFormatException.h
%{_includedir}/ObjFW/OFInvalidJSONException.h
%{_includedir}/ObjFW/OFInvalidServerReplyException.h
%{_includedir}/ObjFW/OFInvocation.h
%{_includedir}/ObjFW/OFJSONRepresentation.h
%{_includedir}/ObjFW/OFKernelEventObserver.h
%{_includedir}/ObjFW/OFKeyValueCoding.h
%{_includedir}/ObjFW/OFLHAArchive.h
%{_includedir}/ObjFW/OFLHAArchiveEntry.h
%{_includedir}/ObjFW/OFLinkFailedException.h
%{_includedir}/ObjFW/OFList.h
%{_includedir}/ObjFW/OFListenFailedException.h
%{_includedir}/ObjFW/OFLoadPluginFailedException.h
%{_includedir}/ObjFW/OFLocale.h
%{_includedir}/ObjFW/OFLockFailedException.h
%{_includedir}/ObjFW/OFLocking.h
%{_includedir}/ObjFW/OFMD5Hash.h
%{_includedir}/ObjFW/OFMalformedXMLException.h
%{_includedir}/ObjFW/OFMapTable.h
%{_includedir}/ObjFW/OFMemoryNotPartOfObjectException.h
%{_includedir}/ObjFW/OFMessagePackExtension.h
%{_includedir}/ObjFW/OFMessagePackRepresentation.h
%{_includedir}/ObjFW/OFMethodSignature.h
%{_includedir}/ObjFW/OFMoveItemFailedException.h
%{_includedir}/ObjFW/OFMutableArray.h
%{_includedir}/ObjFW/OFMutableData.h
%{_includedir}/ObjFW/OFMutableDictionary.h
%{_includedir}/ObjFW/OFMutableLHAArchiveEntry.h
%{_includedir}/ObjFW/OFMutablePair.h
%{_includedir}/ObjFW/OFMutableSet.h
%{_includedir}/ObjFW/OFMutableString.h
%{_includedir}/ObjFW/OFMutableTarArchiveEntry.h
%{_includedir}/ObjFW/OFMutableTriple.h
%{_includedir}/ObjFW/OFMutableURL.h
%{_includedir}/ObjFW/OFMutableZIPArchiveEntry.h
%{_includedir}/ObjFW/OFMutex.h
%{_includedir}/ObjFW/OFNotImplementedException.h
%{_includedir}/ObjFW/OFNotOpenException.h
%{_includedir}/ObjFW/OFNull.h
%{_includedir}/ObjFW/OFNumber.h
%{_includedir}/ObjFW/OFObject+KeyValueCoding.h
%{_includedir}/ObjFW/OFObject+Serialization.h
%{_includedir}/ObjFW/OFObject.h
%{_includedir}/ObjFW/OFObserveFailedException.h
%{_includedir}/ObjFW/OFOnce.h
%{_includedir}/ObjFW/OFOpenItemFailedException.h
%{_includedir}/ObjFW/OFOptionsParser.h
%{_includedir}/ObjFW/OFOutOfMemoryException.h
%{_includedir}/ObjFW/OFOutOfRangeException.h
%{_includedir}/ObjFW/OFPBKDF2.h
%{_includedir}/ObjFW/OFPair.h
%{_includedir}/ObjFW/OFPlainCondition.h
%{_includedir}/ObjFW/OFPlainMutex.h
%{_includedir}/ObjFW/OFPlainThread.h
%{_includedir}/ObjFW/OFPlugin.h
%{_includedir}/ObjFW/OFRIPEMD160Hash.h
%{_includedir}/ObjFW/OFReadFailedException.h
%{_includedir}/ObjFW/OFReadOrWriteFailedException.h
%{_includedir}/ObjFW/OFRecursiveMutex.h
%{_includedir}/ObjFW/OFRemoveItemFailedException.h
%{_includedir}/ObjFW/OFResolveHostFailedException.h
%{_includedir}/ObjFW/OFRetrieveItemAttributesFailedException.h
%{_includedir}/ObjFW/OFRunLoop.h
%{_includedir}/ObjFW/OFSHA1Hash.h
%{_includedir}/ObjFW/OFSHA224Hash.h
%{_includedir}/ObjFW/OFSHA224Or256Hash.h
%{_includedir}/ObjFW/OFSHA256Hash.h
%{_includedir}/ObjFW/OFSHA384Hash.h
%{_includedir}/ObjFW/OFSHA384Or512Hash.h
%{_includedir}/ObjFW/OFSHA512Hash.h
%{_includedir}/ObjFW/OFSPXSocket.h
%{_includedir}/ObjFW/OFSPXStreamSocket.h
%{_includedir}/ObjFW/OFScrypt.h
%{_includedir}/ObjFW/OFSecureData.h
%{_includedir}/ObjFW/OFSeekFailedException.h
%{_includedir}/ObjFW/OFSeekableStream.h
%{_includedir}/ObjFW/OFSequencedPacketSocket.h
%{_includedir}/ObjFW/OFSerialization.h
%{_includedir}/ObjFW/OFSet.h
%{_includedir}/ObjFW/OFSetItemAttributesFailedException.h
%{_includedir}/ObjFW/OFSetOptionFailedException.h
%{_includedir}/ObjFW/OFSettings.h
%{_includedir}/ObjFW/OFSocket.h
%{_includedir}/ObjFW/OFSortedList.h
%{_includedir}/ObjFW/OFStdIOStream.h
%{_includedir}/ObjFW/OFStillLockedException.h
%{_includedir}/ObjFW/OFStrPTime.h
%{_includedir}/ObjFW/OFStream.h
%{_includedir}/ObjFW/OFStreamSocket.h
%{_includedir}/ObjFW/OFString+CryptographicHashing.h
%{_includedir}/ObjFW/OFString+JSONParsing.h
%{_includedir}/ObjFW/OFString+PathAdditions.h
%{_includedir}/ObjFW/OFString+PropertyListParsing.h
%{_includedir}/ObjFW/OFString+Serialization.h
%{_includedir}/ObjFW/OFString+URLEncoding.h
%{_includedir}/ObjFW/OFString+XMLEscaping.h
%{_includedir}/ObjFW/OFString+XMLUnescaping.h
%{_includedir}/ObjFW/OFString.h
%{_includedir}/ObjFW/OFSystemInfo.h
%{_includedir}/ObjFW/OFTCPSocket.h
%{_includedir}/ObjFW/OFTLSKey.h
%{_includedir}/ObjFW/OFTLSSocket.h
%{_includedir}/ObjFW/OFTarArchive.h
%{_includedir}/ObjFW/OFTarArchiveEntry.h
%{_includedir}/ObjFW/OFThread.h
%{_includedir}/ObjFW/OFThreadJoinFailedException.h
%{_includedir}/ObjFW/OFThreadPool.h
%{_includedir}/ObjFW/OFThreadStartFailedException.h
%{_includedir}/ObjFW/OFThreadStillRunningException.h
%{_includedir}/ObjFW/OFTimer.h
%{_includedir}/ObjFW/OFTriple.h
%{_includedir}/ObjFW/OFTruncatedDataException.h
%{_includedir}/ObjFW/OFUDPSocket.h
%{_includedir}/ObjFW/OFURL.h
%{_includedir}/ObjFW/OFURLHandler.h
%{_includedir}/ObjFW/OFUnboundNamespaceException.h
%{_includedir}/ObjFW/OFUnboundPrefixException.h
%{_includedir}/ObjFW/OFUndefinedKeyException.h
%{_includedir}/ObjFW/OFUnknownXMLEntityException.h
%{_includedir}/ObjFW/OFUnlockFailedException.h
%{_includedir}/ObjFW/OFUnsupportedProtocolException.h
%{_includedir}/ObjFW/OFUnsupportedVersionException.h
%{_includedir}/ObjFW/OFValue.h
%{_includedir}/ObjFW/OFWriteFailedException.h
%{_includedir}/ObjFW/OFXMLAttribute.h
%{_includedir}/ObjFW/OFXMLCDATA.h
%{_includedir}/ObjFW/OFXMLCharacters.h
%{_includedir}/ObjFW/OFXMLComment.h
%{_includedir}/ObjFW/OFXMLElement+Serialization.h
%{_includedir}/ObjFW/OFXMLElement.h
%{_includedir}/ObjFW/OFXMLElementBuilder.h
%{_includedir}/ObjFW/OFXMLNode.h
%{_includedir}/ObjFW/OFXMLParser.h
%{_includedir}/ObjFW/OFXMLProcessingInstruction.h
%{_includedir}/ObjFW/OFZIPArchive.h
%{_includedir}/ObjFW/OFZIPArchiveEntry.h
%{_includedir}/ObjFW/ObjFW.h
%{_includedir}/ObjFW/macros.h
%{_includedir}/ObjFW/objfw-defs.h
%{_includedir}/ObjFW/platform.h
%{_includedir}/ObjFW/platform/GCC4.7/OFAtomic.h
%{_includedir}/ObjFW/platform/GCC4/OFAtomic.h
%{_includedir}/ObjFW/platform/PowerPC/OFAtomic.h
%{_includedir}/ObjFW/platform/macOS/OFAtomic.h
%{_includedir}/ObjFW/platform/x86/OFAtomic.h
%{_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 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 [fd93e350db] to [47315f910b].

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
       OFTarArchive.m			\
       OFTarArchiveEntry.m		\
       OFThread.m			\
       OFTimer.m			\
       OFTriple.m			\
       OFURL.m				\
       OFURLHandler.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		\
       ${UNICODE_M}			\
       ${USE_SRCS_FILES}		\
       ${USE_SRCS_PLUGINS}		\
       ${USE_SRCS_SOCKETS}		\
       ${USE_SRCS_THREADS}		\
       ${USE_SRCS_WINDOWS}
SRCS_FILES = OFFile.m			\
	     OFINICategory.m		\







>













<







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
       OFTarArchive.m			\
       OFTarArchiveEntry.m		\
       OFThread.m			\
       OFTimer.m			\
       OFTriple.m			\
       OFURL.m				\
       OFURLHandler.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}		\
       ${USE_SRCS_PLUGINS}		\
       ${USE_SRCS_SOCKETS}		\
       ${USE_SRCS_THREADS}		\
       ${USE_SRCS_WINDOWS}
SRCS_FILES = OFFile.m			\
	     OFINICategory.m		\
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
	       OFRecursiveMutex.m	\
	       OFTLSKey.m		\
	       OFThreadPool.m
SRCS_WINDOWS = OFWin32ConsoleStdIOStream.m	\
	       OFWindowsRegistryKey.m

INCLUDES_ATOMIC = OFAtomic.h			\
		  OFAtomic_builtins.h		\
		  OFAtomic_no_threads.h		\
		  OFAtomic_osatomic.h		\
		  OFAtomic_powerpc.h		\
		  OFAtomic_sync_builtins.h	\
		  OFAtomic_x86.h
INCLUDES := ${SRCS:.m=.h}			\
	    OFCollection.h			\
	    OFCryptographicHash.h		\
	    OFJSONRepresentation.h		\
	    OFKernelEventObserver.h		\
	    OFKeyValueCoding.h			\
	    OFLocking.h				\







|
|
|
|
<
|







150
151
152
153
154
155
156
157
158
159
160

161
162
163
164
165
166
167
168
	       OFRecursiveMutex.m	\
	       OFTLSKey.m		\
	       OFThreadPool.m
SRCS_WINDOWS = OFWin32ConsoleStdIOStream.m	\
	       OFWindowsRegistryKey.m

INCLUDES_ATOMIC = OFAtomic.h			\
		  platform/GCC4/OFAtomic.h	\
		  platform/GCC4.7/OFAtomic.h	\
		  platform/PowerPC/OFAtomic.h	\
		  platform/macOS/OFAtomic.h	\

		  platform/x86/OFAtomic.h
INCLUDES := ${SRCS:.m=.h}			\
	    OFCollection.h			\
	    OFCryptographicHash.h		\
	    OFJSONRepresentation.h		\
	    OFKernelEventObserver.h		\
	    OFKeyValueCoding.h			\
	    OFLocking.h				\
196
197
198
199
200
201
202
203

204
205
206
207
208
209
210
	OFRectValue.m			\
	OFSandbox.m			\
	OFSizeValue.m			\
	OFSubarray.m			\
	OFUTF8String.m			\
	${LIBBASES_M}			\
	${RUNTIME_AUTORELEASE_M}	\
	${RUNTIME_INSTANCE_M}

SRCS_FILES += OFFileURLHandler.m	\
	      OFINIFileSettings.m
SRCS_SOCKETS += OFDNSResolverSettings.m			\
		OFHTTPURLHandler.m			\
		OFHostAddressResolver.m			\
		OFIPSocketAsyncConnector.m		\
		OFKernelEventObserver.m			\







|
>







195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
	OFRectValue.m			\
	OFSandbox.m			\
	OFSizeValue.m			\
	OFSubarray.m			\
	OFUTF8String.m			\
	${LIBBASES_M}			\
	${RUNTIME_AUTORELEASE_M}	\
	${RUNTIME_INSTANCE_M}		\
       ${UNICODE_M}
SRCS_FILES += OFFileURLHandler.m	\
	      OFINIFileSettings.m
SRCS_SOCKETS += OFDNSResolverSettings.m			\
		OFHTTPURLHandler.m			\
		OFHostAddressResolver.m			\
		OFIPSocketAsyncConnector.m		\
		OFKernelEventObserver.m			\

Modified src/OFASPrintF.m from [88da2745a9] to [55b5185ec7].

49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
 * configure determined it is broken. In this case, we must make sure there is
 * no name clash.
 */
# define asprintf asprintf_
# define vasprintf vasprintf_
#endif

struct context {
	const char *format;
	size_t formatLen;
	char subformat[maxSubformatLen + 1];
	size_t subformatLen;
	va_list arguments;
	char *buffer;
	size_t bufferLen;







|







49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
 * configure determined it is broken. In this case, we must make sure there is
 * no name clash.
 */
# define asprintf asprintf_
# define vasprintf vasprintf_
#endif

struct Context {
	const char *format;
	size_t formatLen;
	char subformat[maxSubformatLen + 1];
	size_t subformatLen;
	va_list arguments;
	char *buffer;
	size_t bufferLen;
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
	va_end(arguments);

	return ret;
}
#endif

static bool
appendString(struct context *ctx, const char *append, size_t appendLen)
{
	char *newBuf;

	if (appendLen == 0)
		return true;

	if ((newBuf = realloc(ctx->buffer,
	    ctx->bufferLen + appendLen + 1)) == NULL)
		return false;

	memcpy(newBuf + ctx->bufferLen, append, appendLen);

	ctx->buffer = newBuf;
	ctx->bufferLen += appendLen;

	return true;
}

static bool
appendSubformat(struct context *ctx, const char *subformat,
    size_t subformatLen)
{
	if (ctx->subformatLen + subformatLen > maxSubformatLen)
		return false;

	memcpy(ctx->subformat + ctx->subformatLen, subformat, subformatLen);
	ctx->subformatLen += subformatLen;
	ctx->subformat[ctx->subformatLen] = 0;

	return true;
}

static bool
stringState(struct context *ctx)
{
	if (ctx->format[ctx->i] == '%') {
		if (ctx->i > 0)
			if (!appendString(ctx, ctx->format + ctx->last,
			    ctx->i - ctx->last))
				return false;

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

		ctx->last = ctx->i + 1;
		ctx->state = stateFormatFlags;
	}

	return true;
}

static bool
formatFlagsState(struct context *ctx)
{
	switch (ctx->format[ctx->i]) {
	case '-':
	case '+':
	case ' ':
	case '#':
	case '0':







|



















|













|


















|







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
	va_end(arguments);

	return ret;
}
#endif

static bool
appendString(struct Context *ctx, const char *append, size_t appendLen)
{
	char *newBuf;

	if (appendLen == 0)
		return true;

	if ((newBuf = realloc(ctx->buffer,
	    ctx->bufferLen + appendLen + 1)) == NULL)
		return false;

	memcpy(newBuf + ctx->bufferLen, append, appendLen);

	ctx->buffer = newBuf;
	ctx->bufferLen += appendLen;

	return true;
}

static bool
appendSubformat(struct Context *ctx, const char *subformat,
    size_t subformatLen)
{
	if (ctx->subformatLen + subformatLen > maxSubformatLen)
		return false;

	memcpy(ctx->subformat + ctx->subformatLen, subformat, subformatLen);
	ctx->subformatLen += subformatLen;
	ctx->subformat[ctx->subformatLen] = 0;

	return true;
}

static bool
stringState(struct Context *ctx)
{
	if (ctx->format[ctx->i] == '%') {
		if (ctx->i > 0)
			if (!appendString(ctx, ctx->format + ctx->last,
			    ctx->i - ctx->last))
				return false;

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

		ctx->last = ctx->i + 1;
		ctx->state = stateFormatFlags;
	}

	return true;
}

static bool
formatFlagsState(struct Context *ctx)
{
	switch (ctx->format[ctx->i]) {
	case '-':
	case '+':
	case ' ':
	case '#':
	case '0':
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
		break;
	}

	return true;
}

static bool
formatFieldWidthState(struct context *ctx)
{
	if ((ctx->format[ctx->i] >= '0' && ctx->format[ctx->i] <= '9') ||
	    ctx->format[ctx->i] == '*' || ctx->format[ctx->i] == '.') {
		if (!appendSubformat(ctx, ctx->format + ctx->i, 1))
			return false;
	} else {
		ctx->state = stateFormatLengthModifier;
		ctx->i--;
	}

	return true;
}

static bool
formatLengthModifierState(struct context *ctx)
{
	/* Only one allowed */
	switch (ctx->format[ctx->i]) {
	case 'h': /* and also hh */
		if (ctx->formatLen > ctx->i + 1 &&
		    ctx->format[ctx->i + 1] == 'h') {
			if (!appendSubformat(ctx, ctx->format + ctx->i, 2))







|














|







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
		break;
	}

	return true;
}

static bool
formatFieldWidthState(struct Context *ctx)
{
	if ((ctx->format[ctx->i] >= '0' && ctx->format[ctx->i] <= '9') ||
	    ctx->format[ctx->i] == '*' || ctx->format[ctx->i] == '.') {
		if (!appendSubformat(ctx, ctx->format + ctx->i, 1))
			return false;
	} else {
		ctx->state = stateFormatLengthModifier;
		ctx->i--;
	}

	return true;
}

static bool
formatLengthModifierState(struct Context *ctx)
{
	/* Only one allowed */
	switch (ctx->format[ctx->i]) {
	case 'h': /* and also hh */
		if (ctx->formatLen > ctx->i + 1 &&
		    ctx->format[ctx->i + 1] == 'h') {
			if (!appendSubformat(ctx, ctx->format + ctx->i, 2))
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
	}

	ctx->state = stateFormatConversionSpecifier;
	return true;
}

static bool
formatConversionSpecifierState(struct context *ctx)
{
	char *tmp = NULL;
	int tmpLen = 0;
#ifndef HAVE_ASPRINTF_L
	OFString *point;
#endif








|







369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
	}

	ctx->state = stateFormatConversionSpecifier;
	return true;
}

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

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

	ctx->last = ctx->i + 1;
	ctx->state = stateString;

	return true;
}

static bool (*states[])(struct context *) = {
	stringState,
	formatFlagsState,
	formatFieldWidthState,
	formatLengthModifierState,
	formatConversionSpecifierState
};

int
OFVASPrintF(char **string, const char *format, va_list arguments)
{
	struct context ctx;

	ctx.format = format;
	ctx.formatLen = strlen(format);
	memset(ctx.subformat, 0, maxSubformatLen + 1);
	ctx.subformatLen = 0;
	va_copy(ctx.arguments, arguments);
	ctx.bufferLen = 0;







|










|







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

	ctx->last = ctx->i + 1;
	ctx->state = stateString;

	return true;
}

static bool (*states[])(struct Context *) = {
	stringState,
	formatFlagsState,
	formatFieldWidthState,
	formatLengthModifierState,
	formatConversionSpecifierState
};

int
OFVASPrintF(char **string, const char *format, va_list arguments)
{
	struct Context ctx;

	ctx.format = format;
	ctx.formatLen = strlen(format);
	memset(ctx.subformat, 0, maxSubformatLen + 1);
	ctx.subformatLen = 0;
	va_copy(ctx.arguments, arguments);
	ctx.bufferLen = 0;

Modified src/OFArray.h from [091ccdd3f4] to [0789a761b0].

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





48

49
50
51
52
53
54
55
@class OFString;

/**
 * @brief Options for joining the objects of an array.
 *
 * This is a bit mask.
 */
typedef enum OFArrayJoinOptions {
	/** Skip empty components */
	OFArraySkipEmptyComponents = 1
} OFArrayJoinOptions;






typedef enum OFArraySortOptions {

	OFArraySortDescending = 1
} OFArraySortOptions;

#ifdef OF_HAVE_BLOCKS
/**
 * @brief A block for enumerating an OFArray.
 *







|




>
>
>
>
>
|
>







36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
@class OFString;

/**
 * @brief Options for joining the objects of an array.
 *
 * This is a bit mask.
 */
typedef enum {
	/** Skip empty components */
	OFArraySkipEmptyComponents = 1
} OFArrayJoinOptions;

/**
 * @brief Options for sorting an array.
 *
 * This is a bit mask.
 */
typedef enum {
	/** Sort the array descending */
	OFArraySortDescending = 1
} OFArraySortOptions;

#ifdef OF_HAVE_BLOCKS
/**
 * @brief A block for enumerating an OFArray.
 *

Modified src/OFArray.m from [37c945555f] to [8ae58ccb41].

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
		buffer[i] = [self objectAtIndex: range.location + i];
}

- (id const *)objects
{
	size_t count = self.count;
	id *buffer = OFAllocMemory(count, sizeof(id));


	@try {
		[self getObjects: buffer inRange: OFRangeMake(0, count)];

		return [[OFData dataWithItemsNoCopy: buffer
					      count: count
					   itemSize: sizeof(id)
				       freeWhenDone: true] items];
	} @catch (id e) {
		OFFreeMemory(buffer);
		@throw e;
	}


}

- (id)copy
{
	return [self retain];
}








>




|
|
|
|




>
>







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
		buffer[i] = [self objectAtIndex: range.location + i];
}

- (id const *)objects
{
	size_t count = self.count;
	id *buffer = OFAllocMemory(count, sizeof(id));
	id const *ret;

	@try {
		[self getObjects: buffer inRange: OFRangeMake(0, count)];

		ret = [[OFData dataWithItemsNoCopy: buffer
					     count: count
					  itemSize: sizeof(id)
				      freeWhenDone: true] items];
	} @catch (id e) {
		OFFreeMemory(buffer);
		@throw e;
	}

	return ret;
}

- (id)copy
{
	return [self retain];
}

Modified src/OFAtomic.h from [113d14691a] to [cd35260cdb].

18
19
20
21
22
23
24





25













































































































































26
27
28
29
30
31
32
33
34
35
36
37
38
39
#import "macros.h"

#ifndef OF_HAVE_ATOMIC_OPS
# error No atomic operations available!
#endif

#if !defined(OF_HAVE_THREADS)





# import "OFAtomic_no_threads.h"













































































































































#elif (defined(OF_X86_64) || defined(OF_X86)) && defined(__GNUC__)
# import "OFAtomic_x86.h"
#elif defined(OF_POWERPC) && defined(__GNUC__) && !defined(__APPLE_CC__) && \
    !defined(OF_AIX)
# import "OFAtomic_powerpc.h"
#elif defined(OF_HAVE_ATOMIC_BUILTINS)
# import "OFAtomic_builtins.h"
#elif defined(OF_HAVE_SYNC_BUILTINS)
# import "OFAtomic_sync_builtins.h"
#elif defined(OF_HAVE_OSATOMIC)
# import "OFAtomic_osatomic.h"
#else
# error No atomic operations available!
#endif







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

|


|

|

|

|



18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
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
#import "macros.h"

#ifndef OF_HAVE_ATOMIC_OPS
# error No atomic operations available!
#endif

#if !defined(OF_HAVE_THREADS)
static OF_INLINE int
OFAtomicIntAdd(volatile int *_Nonnull p, int i)
{
	return (*p += i);
}

static OF_INLINE int32_t
OFAtomicInt32Add(volatile int32_t *_Nonnull p, int32_t i)
{
	return (*p += i);
}

static OF_INLINE void *_Nullable
OFAtomicPointerAdd(void *volatile _Nullable *_Nonnull p, intptr_t i)
{
	return (*(char *volatile *)p += i);
}

static OF_INLINE int
OFAtomicIntSubtract(volatile int *_Nonnull p, int i)
{
	return (*p -= i);
}

static OF_INLINE int32_t
OFAtomicInt32Subtract(volatile int32_t *_Nonnull p, int32_t i)
{
	return (*p -= i);
}

static OF_INLINE void *_Nullable
OFAtomicPointerSubtract(void *volatile _Nullable *_Nonnull p, intptr_t i)
{
	return (*(char *volatile *)p -= i);
}

static OF_INLINE int
OFAtomicIntIncrease(volatile int *_Nonnull p)
{
	return ++*p;
}

static OF_INLINE int32_t
OFAtomicInt32Increase(volatile int32_t *_Nonnull p)
{
	return ++*p;
}

static OF_INLINE int
OFAtomicIntDecrease(volatile int *_Nonnull p)
{
	return --*p;
}

static OF_INLINE int32_t
OFAtomicInt32Decrease(volatile int32_t *_Nonnull p)
{
	return --*p;
}

static OF_INLINE unsigned int
OFAtomicIntOr(volatile unsigned int *_Nonnull p, unsigned int i)
{
	return (*p |= i);
}

static OF_INLINE uint32_t
OFAtomicInt32Or(volatile uint32_t *_Nonnull p, uint32_t i)
{
	return (*p |= i);
}

static OF_INLINE unsigned int
OFAtomicIntAnd(volatile unsigned int *_Nonnull p, unsigned int i)
{
	return (*p &= i);
}

static OF_INLINE uint32_t
OFAtomicInt32And(volatile uint32_t *_Nonnull p, uint32_t i)
{
	return (*p &= i);
}

static OF_INLINE unsigned int
OFAtomicIntXor(volatile unsigned int *_Nonnull p, unsigned int i)
{
	return (*p ^= i);
}

static OF_INLINE uint32_t
OFAtomicInt32Xor(volatile uint32_t *_Nonnull p, uint32_t i)
{
	return (*p ^= i);
}

static OF_INLINE bool
OFAtomicIntCompareAndSwap(volatile int *_Nonnull p, int o, int n)
{
	if (*p == o) {
		*p = n;
		return true;
	}

	return false;
}

static OF_INLINE bool
OFAtomicInt32CompareAndSwap(volatile int32_t *_Nonnull p, int32_t o, int32_t n)
{
	if (*p == o) {
		*p = n;
		return true;
	}

	return false;
}

static OF_INLINE bool
OFAtomicPointerCompareAndSwap(void *volatile _Nullable *_Nonnull p,
    void *_Nullable o, void *_Nullable n)
{
	if (*p == o) {
		*p = n;
		return true;
	}

	return false;
}

static OF_INLINE void
OFMemoryBarrier(void)
{
	/* nop */
}

static OF_INLINE void
OFAcquireMemoryBarrier(void)
{
	/* nop */
}

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

Deleted src/OFAtomic_no_threads.h version [bc682f9d95].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
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
/*
 * 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.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

static OF_INLINE int
OFAtomicIntAdd(volatile int *_Nonnull p, int i)
{
	return (*p += i);
}

static OF_INLINE int32_t
OFAtomicInt32Add(volatile int32_t *_Nonnull p, int32_t i)
{
	return (*p += i);
}

static OF_INLINE void *_Nullable
OFAtomicPointerAdd(void *volatile _Nullable *_Nonnull p, intptr_t i)
{
	return (*(char *volatile *)p += i);
}

static OF_INLINE int
OFAtomicIntSubtract(volatile int *_Nonnull p, int i)
{
	return (*p -= i);
}

static OF_INLINE int32_t
OFAtomicInt32Subtract(volatile int32_t *_Nonnull p, int32_t i)
{
	return (*p -= i);
}

static OF_INLINE void *_Nullable
OFAtomicPointerSubtract(void *volatile _Nullable *_Nonnull p, intptr_t i)
{
	return (*(char *volatile *)p -= i);
}

static OF_INLINE int
OFAtomicIntIncrease(volatile int *_Nonnull p)
{
	return ++*p;
}

static OF_INLINE int32_t
OFAtomicInt32Increase(volatile int32_t *_Nonnull p)
{
	return ++*p;
}

static OF_INLINE int
OFAtomicIntDecrease(volatile int *_Nonnull p)
{
	return --*p;
}

static OF_INLINE int32_t
OFAtomicInt32Decrease(volatile int32_t *_Nonnull p)
{
	return --*p;
}

static OF_INLINE unsigned int
OFAtomicIntOr(volatile unsigned int *_Nonnull p, unsigned int i)
{
	return (*p |= i);
}

static OF_INLINE uint32_t
OFAtomicInt32Or(volatile uint32_t *_Nonnull p, uint32_t i)
{
	return (*p |= i);
}

static OF_INLINE unsigned int
OFAtomicIntAnd(volatile unsigned int *_Nonnull p, unsigned int i)
{
	return (*p &= i);
}

static OF_INLINE uint32_t
OFAtomicInt32And(volatile uint32_t *_Nonnull p, uint32_t i)
{
	return (*p &= i);
}

static OF_INLINE unsigned int
OFAtomicIntXor(volatile unsigned int *_Nonnull p, unsigned int i)
{
	return (*p ^= i);
}

static OF_INLINE uint32_t
OFAtomicInt32Xor(volatile uint32_t *_Nonnull p, uint32_t i)
{
	return (*p ^= i);
}

static OF_INLINE bool
OFAtomicIntCompareAndSwap(volatile int *_Nonnull p, int o, int n)
{
	if (*p == o) {
		*p = n;
		return true;
	}

	return false;
}

static OF_INLINE bool
OFAtomicInt32CompareAndSwap(volatile int32_t *_Nonnull p, int32_t o, int32_t n)
{
	if (*p == o) {
		*p = n;
		return true;
	}

	return false;
}

static OF_INLINE bool
OFAtomicPointerCompareAndSwap(void *volatile _Nullable *_Nonnull p,
    void *_Nullable o, void *_Nullable n)
{
	if (*p == o) {
		*p = n;
		return true;
	}

	return false;
}

static OF_INLINE void
OFMemoryBarrier(void)
{
	/* nop */
}

static OF_INLINE void
OFAcquireMemoryBarrier(void)
{
	/* nop */
}

static OF_INLINE void
OFReleaseMemoryBarrier(void)
{
	/* nop */
}
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<




































































































































































































































































































































Modified src/OFBlock.h from [b2fc8f8283] to [d0a30cd463].

38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
OF_SUBCLASSING_RESTRICTED
@interface OFMallocBlock: OFBlock
@end

#ifdef __cplusplus
extern "C" {
#endif
extern void *_Block_copy(const void *);
extern void _Block_release(const void *);

# if defined(OF_WINDOWS) && \
    (defined(OF_NO_SHARED) || defined(OF_COMPILING_OBJFW))
/*
 * Clang has implicit declarations for these, but they are dllimport. When
 * compiling ObjFW itself or using it as a static library, these need to be
 * dllexport. Interestingly, this still works when using it as a shared library.







|
|







38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
OF_SUBCLASSING_RESTRICTED
@interface OFMallocBlock: OFBlock
@end

#ifdef __cplusplus
extern "C" {
#endif
extern void *_Nullable _Block_copy(const void *_Nullable);
extern void _Block_release(const void *_Nullable);

# if defined(OF_WINDOWS) && \
    (defined(OF_NO_SHARED) || defined(OF_COMPILING_OBJFW))
/*
 * Clang has implicit declarations for these, but they are dllimport. When
 * compiling ObjFW itself or using it as a static library, these need to be
 * dllexport. Interestingly, this still works when using it as a shared library.

Modified src/OFCondition.m from [48a8d9c9b2] to [17f7291bd2].

102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
	return true;
}

#ifdef OF_AMIGAOS
- (bool)waitForTimeInterval: (OFTimeInterval)timeInterval
	       orExecSignal: (ULONG *)signalMask
{
	int error = OFPlainConditionTimedWaitExecOrSignal(&_condition, &_mutex,
	    timeInterval, signalMask);

	if (error == ETIMEDOUT)
		return false;

	if (error != 0)
		@throw [OFConditionWaitFailedException







|







102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
	return true;
}

#ifdef OF_AMIGAOS
- (bool)waitForTimeInterval: (OFTimeInterval)timeInterval
	       orExecSignal: (ULONG *)signalMask
{
	int error = OFPlainConditionTimedWaitOrExecSignal(&_condition, &_mutex,
	    timeInterval, signalMask);

	if (error == ETIMEDOUT)
		return false;

	if (error != 0)
		@throw [OFConditionWaitFailedException

Modified src/OFDNSResolver.h from [9570988a05] to [d50442556a].

36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
@class OFUDPSocket;

/**
 * @enum OFDNSResolverErrorCode OFDNSResolver.h ObjFW/OFDNSResolver.h
 *
 * @brief An enum describing why resolving a host failed.
 */
typedef enum OFDNSResolverErrorCode {
	/** An unknown error */
	OFDNSResolverErrorCodeUnknown,
	/** The query timed out */
	OFDNSResolverErrorCodeTimeout,
	/** The query was canceled */
	OFDNSResolverErrorCodeCanceled,
	/**







|







36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
@class OFUDPSocket;

/**
 * @enum OFDNSResolverErrorCode OFDNSResolver.h ObjFW/OFDNSResolver.h
 *
 * @brief An enum describing why resolving a host failed.
 */
typedef enum {
	/** An unknown error */
	OFDNSResolverErrorCodeUnknown,
	/** The query timed out */
	OFDNSResolverErrorCodeTimeout,
	/** The query was canceled */
	OFDNSResolverErrorCodeCanceled,
	/**

Modified src/OFDNSResolverSettings.m from [eb1fcb5845] to [e0ccdc2d67].

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
# define RESOLV_CONF_PATH @"/etc/resolv.conf"
#endif

#ifndef OF_WII
static OFString *
domainFromHostname(OFString *hostname)
{


	if (hostname == nil)
		return nil;

	@try {
		OFSocketAddressParseIP(hostname, 0);

		/*
		 * If we are still here, the host name is a valid IP address.
		 * We can't use that as local domain.
		 */
		return nil;
	} @catch (OFInvalidFormatException *e) {
		/* Not an IP address -> we can use it if it contains a dot. */
		size_t pos = [hostname rangeOfString: @"."].location;

		if (pos == OFNotFound)


			return nil;

		return [hostname substringFromIndex: pos + 1];
	}

}
#endif

#if !defined(OF_WII) && !defined(OF_MORPHOS)
static OFString *
obtainHostname(void)
{







>
>










|




|
>
>
|
|
<
|
>







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
# define RESOLV_CONF_PATH @"/etc/resolv.conf"
#endif

#ifndef OF_WII
static OFString *
domainFromHostname(OFString *hostname)
{
	OFString *ret;

	if (hostname == nil)
		return nil;

	@try {
		OFSocketAddressParseIP(hostname, 0);

		/*
		 * If we are still here, the host name is a valid IP address.
		 * We can't use that as local domain.
		 */
		ret = nil;
	} @catch (OFInvalidFormatException *e) {
		/* Not an IP address -> we can use it if it contains a dot. */
		size_t pos = [hostname rangeOfString: @"."].location;

		if (pos != OFNotFound)
			ret = [hostname substringFromIndex: pos + 1];
		else
			ret = nil;
	}


	return ret;
}
#endif

#if !defined(OF_WII) && !defined(OF_MORPHOS)
static OFString *
obtainHostname(void)
{

Modified src/OFDNSResourceRecord.h from [d9a4125a07] to [684c620d59].

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

@class OFArray OF_GENERIC(ObjectType);
@class OFData;

/**
 * @brief The DNS class.
 */
typedef enum OFDNSClass {
	/** IN */
	OFDNSClassIN  =   1,
	/** Any class. Only for queries. */
	OFDNSClassAny = 255,
} OFDNSClass;

/**
 * @brief The type of a DNS resource record.
 */
typedef enum OFDNSRecordType {
	/** A */
	OFDNSRecordTypeA     =   1,
	/** NS */
	OFDNSRecordTypeNS    =   2,
	/** CNAME */
	OFDNSRecordTypeCNAME =   5,
	/** SOA */







|









|







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

@class OFArray OF_GENERIC(ObjectType);
@class OFData;

/**
 * @brief The DNS class.
 */
typedef enum {
	/** IN */
	OFDNSClassIN  =   1,
	/** Any class. Only for queries. */
	OFDNSClassAny = 255,
} OFDNSClass;

/**
 * @brief The type of a DNS resource record.
 */
typedef enum {
	/** A */
	OFDNSRecordTypeA     =   1,
	/** NS */
	OFDNSRecordTypeNS    =   2,
	/** CNAME */
	OFDNSRecordTypeCNAME =   5,
	/** SOA */
616
617
618
619
620
621
622






623







624







625







626
627
628
629
630
631
		 textStrings: (OFArray OF_GENERIC(OFData *) *)textStrings
			 TTL: (uint32_t)TTL OF_DESIGNATED_INITIALIZER;
@end

#ifdef __cplusplus
extern "C" {
#endif






extern OFString *_Nonnull OFDNSClassName(OFDNSClass DNSClass);







extern OFString *_Nonnull OFDNSRecordTypeName(OFDNSRecordType recordType);







extern OFDNSClass OFDNSClassParseName(OFString *_Nonnull string);







extern OFDNSRecordType OFDNSRecordTypeParseName(OFString *_Nonnull string);
#ifdef __cplusplus
}
#endif

OF_ASSUME_NONNULL_END







>
>
>
>
>
>

>
>
>
>
>
>
>

>
>
>
>
>
>
>

>
>
>
>
>
>
>






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
		 textStrings: (OFArray OF_GENERIC(OFData *) *)textStrings
			 TTL: (uint32_t)TTL OF_DESIGNATED_INITIALIZER;
@end

#ifdef __cplusplus
extern "C" {
#endif
/**
 * @brief Returns the name for the specified OFDNSClass.
 *
 * @param DNSClass The OFDNSClass to return the name for
 * @return The name for the specified OFDNSClass
 */
extern OFString *_Nonnull OFDNSClassName(OFDNSClass DNSClass);

/**
 * @brief Returns the name for the specified OFDNSRecordType.
 *
 * @param recordType The OFDNSRecordType to return the name for
 * @return The name for the specified OFDNSRecordType
 */
extern OFString *_Nonnull OFDNSRecordTypeName(OFDNSRecordType recordType);

/**
 * @brief Parses the specified string as an @ref OFDNSClass.
 *
 * @param string The string to parse as an @ref OFDNSClass
 * @return The parsed OFDNSClass
 */
extern OFDNSClass OFDNSClassParseName(OFString *_Nonnull string);

/**
 * @brief Parses the specified string as an @ref OFDNSRecordType.
 *
 * @param string The string to parse as an @ref OFDNSRecordType
 * @return The parsed OFDNSRecordType
 */
extern OFDNSRecordType OFDNSRecordTypeParseName(OFString *_Nonnull string);
#ifdef __cplusplus
}
#endif

OF_ASSUME_NONNULL_END

Modified src/OFData.h from [654367484b] to [b76fc312cd].

25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
@class OFURL;

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

/**
 * @class OFData OFData.h ObjFW/OFData.h
 *







|







25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
@class OFURL;

/**
 * @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
 *
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
+ (instancetype)dataWithItems: (const void *)items
			count: (size_t)count
		     itemSize: (size_t)itemSize;

/**
 * @brief Creates a new OFData with the specified `count` items of size 1 by
 *	  taking over ownership of the specified items pointer.



 *
 * @param items The items to store in the OFData
 * @param count The number of items
 * @param freeWhenDone Whether to free the pointer when it is no longer needed
 *		       by the OFData
 * @return A new autoreleased OFData
 */
+ (instancetype)dataWithItemsNoCopy: (void *)items
			      count: (size_t)count
		       freeWhenDone: (bool)freeWhenDone;

/**
 * @brief Creates a new OFData with the specified `count` items of the
 *	  specified size by taking ownership of the specified items pointer.



 *
 * @param items The items to store in the OFData
 * @param count The number of items
 * @param itemSize The item size of a single item in bytes
 * @param freeWhenDone Whether to free the pointer when it is no longer needed
 *		       by the OFData
 * @return A new autoreleased OFData







>
>
>














>
>
>







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
+ (instancetype)dataWithItems: (const void *)items
			count: (size_t)count
		     itemSize: (size_t)itemSize;

/**
 * @brief Creates a new OFData with the specified `count` items of size 1 by
 *	  taking over ownership of the specified items pointer.
 *
 * If initialization fails for whatever reason, the passed memory is *not*
 * free'd if `freeWhenDone` is true.
 *
 * @param items The items to store in the OFData
 * @param count The number of items
 * @param freeWhenDone Whether to free the pointer when it is no longer needed
 *		       by the OFData
 * @return A new autoreleased OFData
 */
+ (instancetype)dataWithItemsNoCopy: (void *)items
			      count: (size_t)count
		       freeWhenDone: (bool)freeWhenDone;

/**
 * @brief Creates a new OFData with the specified `count` items of the
 *	  specified size by taking ownership of the specified items pointer.
 *
 * If initialization fails for whatever reason, the passed memory is *not*
 * free'd if `freeWhenDone` is true.
 *
 * @param items The items to store in the OFData
 * @param count The number of items
 * @param itemSize The item size of a single item in bytes
 * @param freeWhenDone Whether to free the pointer when it is no longer needed
 *		       by the OFData
 * @return A new autoreleased OFData
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
			count: (size_t)count
		     itemSize: (size_t)itemSize;

/**
 * @brief Initializes an already allocated OFData with the specified `count`
 *	  items of size 1 by taking over ownership of the specified items
 *	  pointer.



 *
 * @param items The items to store in the OFData
 * @param count The number of items
 * @param freeWhenDone Whether to free the pointer when it is no longer needed
 *		       by the OFData
 * @return An initialized OFData
 */
- (instancetype)initWithItemsNoCopy: (void *)items
			      count: (size_t)count
		       freeWhenDone: (bool)freeWhenDone;

/**
 * @brief Initializes an already allocated OFData with the specified `count`
 *	  items of the specified size by taking ownership of the specified
 *	  items pointer.



 *
 * @param items The items to store in the OFData
 * @param count The number of items
 * @param itemSize The item size of a single item in bytes
 * @param freeWhenDone Whether to free the pointer when it is no longer needed
 *		       by the OFData
 * @return An initialized OFData







>
>
>















>
>
>







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
			count: (size_t)count
		     itemSize: (size_t)itemSize;

/**
 * @brief Initializes an already allocated OFData with the specified `count`
 *	  items of size 1 by taking over ownership of the specified items
 *	  pointer.
 *
 * If initialization fails for whatever reason, the passed memory is *not*
 * free'd if `freeWhenDone` is true.
 *
 * @param items The items to store in the OFData
 * @param count The number of items
 * @param freeWhenDone Whether to free the pointer when it is no longer needed
 *		       by the OFData
 * @return An initialized OFData
 */
- (instancetype)initWithItemsNoCopy: (void *)items
			      count: (size_t)count
		       freeWhenDone: (bool)freeWhenDone;

/**
 * @brief Initializes an already allocated OFData with the specified `count`
 *	  items of the specified size by taking ownership of the specified
 *	  items pointer.
 *
 * If initialization fails for whatever reason, the passed memory is *not*
 * free'd if `freeWhenDone` is true.
 *
 * @param items The items to store in the OFData
 * @param count The number of items
 * @param itemSize The item size of a single item in bytes
 * @param freeWhenDone Whether to free the pointer when it is no longer needed
 *		       by the OFData
 * @return An initialized OFData

Modified src/OFDatagramSocket.m from [d32466923e] to [a53bf3d04b].

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

	if (fcntl(_socket, F_SETFL, flags) == -1)
		@throw [OFSetOptionFailedException exceptionWithObject: self
								 errNo: errno];

	_canBlock = canBlock;
#elif defined(OF_WINDOWS)
	u_long v = canBlock;

	if (ioctlsocket(_socket, FIONBIO, &v) == SOCKET_ERROR)
		@throw [OFSetOptionFailedException
		    exceptionWithObject: self
				  errNo: OFSocketErrNo()];

	_canBlock = canBlock;







|







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

	if (fcntl(_socket, F_SETFL, flags) == -1)
		@throw [OFSetOptionFailedException exceptionWithObject: self
								 errNo: errno];

	_canBlock = canBlock;
#elif defined(OF_WINDOWS)
	u_long v = !canBlock;

	if (ioctlsocket(_socket, FIONBIO, &v) == SOCKET_ERROR)
		@throw [OFSetOptionFailedException
		    exceptionWithObject: self
				  errNo: OFSocketErrNo()];

	_canBlock = canBlock;

Modified src/OFFile.h from [7c5aab04f3] to [bac13481b9].

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

#ifndef OF_AMIGAOS
# define OF_FILE_HANDLE_IS_FD
typedef int OFFileHandle;
static const OFFileHandle OFInvalidFileHandle = -1;
#else
typedef struct OFFileHandle *OFFileHandle;
static const OFFileHandle OFInvalidFileHandle = NULL;
#endif

OF_ASSUME_NONNULL_BEGIN

@class OFURL;








|







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

#ifndef OF_AMIGAOS
# define OF_FILE_HANDLE_IS_FD
typedef int OFFileHandle;
static const OFFileHandle OFInvalidFileHandle = -1;
#else
typedef struct _OFFileHandle *OFFileHandle;
static const OFFileHandle OFInvalidFileHandle = NULL;
#endif

OF_ASSUME_NONNULL_BEGIN

@class OFURL;

Modified src/OFFile.m from [cd41ef981c] to [87a6169ed1].

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
#ifndef O_EXLOCK
# define O_EXLOCK 0
#endif

#ifndef OF_AMIGAOS
# define closeHandle(h) close(h)
#else
static struct OFFileHandle
	struct OFFileHandle *previous, *next;
	BPTR handle;
	bool append;
} *firstHandle = NULL;

static void
closeHandle(OFFileHandle handle)
{
	Close(handle->handle);



	if (handle->previous != NULL)
		handle->previous->next = handle->next;
	if (handle->next != NULL)
		handle->next->previous = handle->previous;

	if (firstHandle == handle)
		firstHandle = handle->next;



	OFFreeMemory(handle);
}

OF_DESTRUCTOR()
{
	for (OFFileHandle iter = firstHandle; iter != NULL;







|
|








>
>








>
>







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
#ifndef O_EXLOCK
# define O_EXLOCK 0
#endif

#ifndef OF_AMIGAOS
# define closeHandle(h) close(h)
#else
static struct _OFFileHandle {
	struct _OFFileHandle *previous, *next;
	BPTR handle;
	bool append;
} *firstHandle = NULL;

static void
closeHandle(OFFileHandle handle)
{
	Close(handle->handle);

	Forbid();

	if (handle->previous != NULL)
		handle->previous->next = handle->next;
	if (handle->next != NULL)
		handle->next->previous = handle->previous;

	if (firstHandle == handle)
		firstHandle = handle->next;

	Permit();

	OFFreeMemory(handle);
}

OF_DESTRUCTOR()
{
	for (OFFileHandle iter = firstHandle; iter != NULL;
287
288
289
290
291
292
293


294
295
296
297
298
299
300
301


302
303
304
305
306
307
308
					Close(handle->handle);
					@throw [OFOpenItemFailedException
					    exceptionWithPath: path
							 mode: mode
							errNo: EIO];
				}
			}



			handle->previous = NULL;
			handle->next = firstHandle;

			if (firstHandle != NULL)
				firstHandle->previous = handle;

			firstHandle = handle;


		} @catch (id e) {
			OFFreeMemory(handle);
			@throw e;
		}
#endif

		objc_autoreleasePoolPop(pool);







>
>








>
>







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
					Close(handle->handle);
					@throw [OFOpenItemFailedException
					    exceptionWithPath: path
							 mode: mode
							errNo: EIO];
				}
			}

			Forbid();

			handle->previous = NULL;
			handle->next = firstHandle;

			if (firstHandle != NULL)
				firstHandle->previous = handle;

			firstHandle = handle;

			Permit();
		} @catch (id e) {
			OFFreeMemory(handle);
			@throw e;
		}
#endif

		objc_autoreleasePoolPop(pool);

Modified src/OFFileManager.h from [a969db1ae2] to [8ccfa4987e].

225
226
227
228
229
230
231









232
233
234
235
236
237
238
 */
extern const OFFileAttributeType OFFileTypeBlockSpecial;

/**
 * @brief A socket.
 */
extern const OFFileAttributeType OFFileTypeSocket;









#ifdef __cplusplus
}
#endif

/**
 * @class OFFileManager OFFileManager.h ObjFW/OFFileManager.h
 *







>
>
>
>
>
>
>
>
>







225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
 */
extern const OFFileAttributeType OFFileTypeBlockSpecial;

/**
 * @brief A socket.
 */
extern const OFFileAttributeType OFFileTypeSocket;

/**
 * @brief An unknown file type.
 *
 * This is different from not having an @ref OFFileType at all in that it means
 * that retrieving file types is supported, but the particular file type is
 * unknown.
 */
extern const OFFileAttributeType OFFileTypeUnknown;
#ifdef __cplusplus
}
#endif

/**
 * @class OFFileManager OFFileManager.h ObjFW/OFFileManager.h
 *
396
397
398
399
400
401
402











403
404
405
406
407
408
409
 *
 * @param URL The URL to the directory whose items should be returned
 * @return An array with the URLs of the items in the specified directory
 */
- (OFArray OF_GENERIC(OFURL *) *)contentsOfDirectoryAtURL: (OFURL *)URL;

#ifdef OF_HAVE_FILES











/**
 * @brief Changes the current working directory.
 *
 * @param path The new directory to change to
 */
- (void)changeCurrentDirectoryPath: (OFString *)path;








>
>
>
>
>
>
>
>
>
>
>







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
 *
 * @param URL The URL to the directory whose items should be returned
 * @return An array with the URLs of the items in the specified directory
 */
- (OFArray OF_GENERIC(OFURL *) *)contentsOfDirectoryAtURL: (OFURL *)URL;

#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.
 *
 * @param path The path to the directory whose subpaths should be returned
 * @return An array of OFString with the subpaths of the specified directory
 */
- (OFArray OF_GENERIC(OFString *) *)subpathsOfDirectoryAtPath: (OFString *)path;

/**
 * @brief Changes the current working directory.
 *
 * @param path The new directory to change to
 */
- (void)changeCurrentDirectoryPath: (OFString *)path;

Modified src/OFFileManager.m from [d0ff19a328] to [d2360d47e0].

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
# include <proto/exec.h>
# include <proto/dos.h>
#endif

@interface OFDefaultFileManager: OFFileManager
@end

const OFFileAttributeKey OFFileSize = @"OFFileSize";
const OFFileAttributeKey OFFileType = @"OFFileType";
const OFFileAttributeKey OFFilePOSIXPermissions = @"OFFilePOSIXPermissions";
const OFFileAttributeKey OFFileOwnerAccountID = @"OFFileOwnerAccountID";
const OFFileAttributeKey OFFileGroupOwnerAccountID =
    @"OFFileGroupOwnerAccountID";
const OFFileAttributeKey OFFileOwnerAccountName = @"OFFileOwnerAccountName";
const OFFileAttributeKey OFFileGroupOwnerAccountName =
    @"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";

#ifdef OF_AMIGAOS4
# define CurrentDir(lock) SetCurrentDir(lock)
#endif



static OFFileManager *defaultManager;

#ifdef OF_AMIGAOS
static bool dirChanged = false;
static BPTR originalDirLock = 0;








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



>
>







67
68
69
70
71
72
73

























74
75
76
77
78
79
80
81
82
83
84
85
# include <proto/exec.h>
# include <proto/dos.h>
#endif

@interface OFDefaultFileManager: OFFileManager
@end


























#ifdef OF_AMIGAOS4
# define CurrentDir(lock) SetCurrentDir(lock)
#endif

#include "OFFileManagerConstants.inc"

static OFFileManager *defaultManager;

#ifdef OF_AMIGAOS
static bool dirChanged = false;
static BPTR originalDirLock = 0;

467
468
469
470
471
472
473































474
475
476
477
478
479
480

	URLs = [self contentsOfDirectoryAtURL: [OFURL fileURLWithPath: path]];
	ret = [OFMutableArray arrayWithCapacity: URLs.count];

	for (OFURL *URL in URLs)
		[ret addObject: URL.lastPathComponent];
































	[ret retain];

	objc_autoreleasePoolPop(pool);

	return [ret autorelease];
}








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







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

	URLs = [self contentsOfDirectoryAtURL: [OFURL fileURLWithPath: path]];
	ret = [OFMutableArray arrayWithCapacity: URLs.count];

	for (OFURL *URL in URLs)
		[ret addObject: URL.lastPathComponent];

	[ret makeImmutable];
	[ret retain];

	objc_autoreleasePoolPop(pool);

	return [ret autorelease];
}

- (OFArray OF_GENERIC(OFString *) *)subpathsOfDirectoryAtPath: (OFString *)path
{
	void *pool = objc_autoreleasePoolPush();
	OFMutableArray OF_GENERIC(OFString *) *ret =
	    [OFMutableArray arrayWithObject: path];

	for (OFString *subpath in [self contentsOfDirectoryAtPath: path]) {
		void *pool2 = objc_autoreleasePoolPush();
		OFString *fullSubpath =
		    [path stringByAppendingPathComponent: subpath];
		OFFileAttributes attributes =
		    [self attributesOfItemAtPath: fullSubpath];

		if ([attributes.fileType isEqual: OFFileTypeDirectory])
			[ret addObjectsFromArray:
			    [self subpathsOfDirectoryAtPath: fullSubpath]];
		else
			[ret addObject: fullSubpath];

		objc_autoreleasePoolPop(pool2);
	}

	[ret makeImmutable];
	[ret retain];

	objc_autoreleasePoolPop(pool);

	return [ret autorelease];
}

Added src/OFFileManagerConstants.inc version [e875ee7ab5].

















































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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-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.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

const OFFileAttributeKey OFFileSize = @"OFFileSize";
const OFFileAttributeKey OFFileType = @"OFFileType";
const OFFileAttributeKey OFFilePOSIXPermissions = @"OFFilePOSIXPermissions";
const OFFileAttributeKey OFFileOwnerAccountID = @"OFFileOwnerAccountID";
const OFFileAttributeKey OFFileGroupOwnerAccountID =
    @"OFFileGroupOwnerAccountID";
const OFFileAttributeKey OFFileOwnerAccountName = @"OFFileOwnerAccountName";
const OFFileAttributeKey OFFileGroupOwnerAccountName =
    @"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";

Modified src/OFFileURLHandler.m from [451e6c48b2] to [b0e449d601].

384
385
386
387
388
389
390


391
392
393
394
395
396
397
		[attributes setObject: OFFileTypeBlockSpecial
			       forKey: OFFileType];
#endif
#ifdef S_ISSOCK
	else if (S_ISSOCK(s->st_mode))
		[attributes setObject: OFFileTypeSocket forKey: OFFileType];
#endif


}

static void
setDateAttributes(OFMutableFileAttributes attributes, Stat *s)
{
	/* FIXME: We could be more precise on some OSes */
	[attributes







>
>







384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
		[attributes setObject: OFFileTypeBlockSpecial
			       forKey: OFFileType];
#endif
#ifdef S_ISSOCK
	else if (S_ISSOCK(s->st_mode))
		[attributes setObject: OFFileTypeSocket forKey: OFFileType];
#endif
	else
		[attributes setObject: OFFileTypeUnknown forKey: OFFileType];
}

static void
setDateAttributes(OFMutableFileAttributes attributes, Stat *s)
{
	/* FIXME: We could be more precise on some OSes */
	[attributes

Modified src/OFGZIPStream.h from [dc70b7b057] to [498f0a4cf5].

19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
@class OFInflateStream;

OF_ASSUME_NONNULL_BEGIN

/**
 * @brief The operating system on which compressed the data.
 */
typedef enum OFGZIPStreamOperatingSystem {
	OFGZIPStreamOperatingSystemFAT	       =   0,
	OFGZIPStreamOperatingSystemAmiga       =   1,
	OFGZIPStreamOperatingSystemVMS	       =   2,
	OFGZIPStreamOperatingSystemUNIX	       =   3,
	OFGZIPStreamOperatingSystemVM_CMS      =   4,
	OFGZIPStreamOperatingSystemAtariTOS    =   5,
	OFGZIPStreamOperatingSystemHPFS	       =   6,







|







19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
@class OFInflateStream;

OF_ASSUME_NONNULL_BEGIN

/**
 * @brief The operating system on which compressed the data.
 */
typedef enum {
	OFGZIPStreamOperatingSystemFAT	       =   0,
	OFGZIPStreamOperatingSystemAmiga       =   1,
	OFGZIPStreamOperatingSystemVMS	       =   2,
	OFGZIPStreamOperatingSystemUNIX	       =   3,
	OFGZIPStreamOperatingSystemVM_CMS      =   4,
	OFGZIPStreamOperatingSystemAtariTOS    =   5,
	OFGZIPStreamOperatingSystemHPFS	       =   6,

Modified src/OFHTTPRequest.h from [28493df649] to [e5c26eec6f].

25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
@class OFString;

/** @file */

/**
 * @brief The type of an HTTP request.
 */
typedef enum OFHTTPRequestMethod {
	/** OPTIONS */
	OFHTTPRequestMethodOptions,
	/** GET */
	OFHTTPRequestMethodGet,
	/** HEAD */
	OFHTTPRequestMethodHead,
	/** POST */







|







25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
@class OFString;

/** @file */

/**
 * @brief The type of an HTTP request.
 */
typedef enum {
	/** OPTIONS */
	OFHTTPRequestMethodOptions,
	/** GET */
	OFHTTPRequestMethodGet,
	/** HEAD */
	OFHTTPRequestMethodHead,
	/** POST */
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
} OFHTTPRequestMethod;

/**
 * @struct OFHTTPRequestProtocolVersion OFHTTPRequest.h ObjFW/OFHTTPRequest.h
 *
 * @brief The HTTP version of the HTTP request.
 */
struct OF_BOXABLE OFHTTPRequestProtocolVersion {
	/** The major of the HTTP version */
	unsigned char major;
	/** The minor of the HTTP version */
	unsigned char minor;
};
typedef struct OFHTTPRequestProtocolVersion OFHTTPRequestProtocolVersion;

/**
 * @class OFHTTPRequest OFHTTPRequest.h ObjFW/OFHTTPRequest.h
 *
 * @brief A class for storing HTTP requests.
 */
@interface OFHTTPRequest: OFObject <OFCopying>







|




<
|







49
50
51
52
53
54
55
56
57
58
59
60

61
62
63
64
65
66
67
68
} 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.
 */
@interface OFHTTPRequest: OFObject <OFCopying>

Modified src/OFHTTPServer.m from [76527fc01b] to [d1a692f4d4].

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
#ifdef OF_HAVE_THREADS
OF_DIRECT_MEMBERS
@interface OFHTTPServerThread: OFThread
- (void)stop;
@end
#endif

static OF_INLINE OFString *
normalizedKey(OFString *key)
{
	char *cString = OFStrDup(key.UTF8String);
	unsigned char *tmp = (unsigned char *)cString;
	bool firstLetter = true;


	while (*tmp != '\0') {
		if (!OFASCIIIsAlpha(*tmp)) {
			firstLetter = true;
			tmp++;
			continue;
		}

		*tmp = (firstLetter
		    ? OFASCIIToUpper(*tmp) : OFASCIIToLower(*tmp));

		firstLetter = false;
		tmp++;
	}

	@try {
		return [OFString stringWithUTF8StringNoCopy: cString
					       freeWhenDone: true];
	} @catch (id e) {
		OFFreeMemory(cString);
		@throw e;
	}


}

@implementation OFHTTPServerResponse
- (instancetype)initWithSocket: (OFStreamSocket *)sock
			server: (OFHTTPServer *)server
		       request: (OFHTTPRequest *)request
{







|





>
















|
|




>
>







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
#ifdef OF_HAVE_THREADS
OF_DIRECT_MEMBERS
@interface OFHTTPServerThread: OFThread
- (void)stop;
@end
#endif

static OFString *
normalizedKey(OFString *key)
{
	char *cString = OFStrDup(key.UTF8String);
	unsigned char *tmp = (unsigned char *)cString;
	bool firstLetter = true;
	OFString *ret;

	while (*tmp != '\0') {
		if (!OFASCIIIsAlpha(*tmp)) {
			firstLetter = true;
			tmp++;
			continue;
		}

		*tmp = (firstLetter
		    ? OFASCIIToUpper(*tmp) : OFASCIIToLower(*tmp));

		firstLetter = false;
		tmp++;
	}

	@try {
		ret = [OFString stringWithUTF8StringNoCopy: cString
					      freeWhenDone: true];
	} @catch (id e) {
		OFFreeMemory(cString);
		@throw e;
	}

	return ret;
}

@implementation OFHTTPServerResponse
- (instancetype)initWithSocket: (OFStreamSocket *)sock
			server: (OFHTTPServer *)server
		       request: (OFHTTPRequest *)request
{

Modified src/OFHuffmanTree.h from [694631f046] to [fd05cd38a9].

18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43

#import "macros.h"

#import "OFInvalidFormatException.h"

OF_ASSUME_NONNULL_BEGIN

typedef struct OFHuffmanTree {
	struct OFHuffmanTree *_Nullable leaves[2];
	uint16_t value;
} OFHuffmanTree;

/* Inlined for performance. */
static OF_INLINE bool
OFHuffmanTreeWalk(id _Nullable stream,
    bool (*bitReader)(id _Nullable, uint16_t *_Nonnull, uint8_t),
    OFHuffmanTree *_Nonnull *_Nonnull tree, uint16_t *_Nonnull value)
{
	struct OFHuffmanTree *iter = *tree;
	uint16_t bits;

	while (iter->value == 0xFFFF) {
		if OF_UNLIKELY (!bitReader(stream, &bits, 1)) {
			*tree = iter;
			return false;
		}







|
|

|





|

|







18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43

#import "macros.h"

#import "OFInvalidFormatException.h"

OF_ASSUME_NONNULL_BEGIN

typedef struct _OFHuffmanTree {
	struct _OFHuffmanTree *_Nullable leaves[2];
	uint16_t value;
} *OFHuffmanTree;

/* Inlined for performance. */
static OF_INLINE bool
OFHuffmanTreeWalk(id _Nullable stream,
    bool (*bitReader)(id _Nullable, uint16_t *_Nonnull, uint8_t),
    OFHuffmanTree _Nonnull *_Nonnull tree, uint16_t *_Nonnull value)
{
	OFHuffmanTree iter = *tree;
	uint16_t bits;

	while (iter->value == 0xFFFF) {
		if OF_UNLIKELY (!bitReader(stream, &bits, 1)) {
			*tree = iter;
			return false;
		}
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
	*value = iter->value;
	return true;
}

#ifdef __cplusplus
extern "C" {
#endif
extern OFHuffmanTree *_Nonnull OFHuffmanTreeNew(uint8_t lengths[_Nonnull],
    uint16_t count);
extern OFHuffmanTree *_Nonnull OFHuffmanTreeNewSingle(uint16_t value);
extern void OFHuffmanTreeFree(OFHuffmanTree *_Nonnull tree);
#ifdef __cplusplus
}
#endif

OF_ASSUME_NONNULL_END







|

|
|





51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
	*value = iter->value;
	return true;
}

#ifdef __cplusplus
extern "C" {
#endif
extern OFHuffmanTree _Nonnull OFHuffmanTreeNew(uint8_t lengths[_Nonnull],
    uint16_t count);
extern OFHuffmanTree _Nonnull OFHuffmanTreeNewSingle(uint16_t value);
extern void OFHuffmanTreeFree(OFHuffmanTree _Nonnull tree);
#ifdef __cplusplus
}
#endif

OF_ASSUME_NONNULL_END

Modified src/OFHuffmanTree.m from [e08b704a74] to [f7a4f8d9de].

19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#include <stdlib.h>

#import "OFHuffmanTree.h"

#import "OFInvalidFormatException.h"
#import "OFOutOfMemoryException.h"

static OFHuffmanTree *
newTree(void)
{
	OFHuffmanTree *tree;

	tree = OFAllocMemory(1, sizeof(*tree));
	tree->leaves[0] = tree->leaves[1] = NULL;
	tree->value = 0xFFFF;

	return tree;
}

static void
treeInsert(OFHuffmanTree *tree, uint16_t code, uint8_t length, uint16_t value)
{
	while (length > 0) {
		uint8_t bit;

		length--;
		bit = (code & (1u << length)) >> length;

		if (tree->leaves[bit] == NULL)
			tree->leaves[bit] = newTree();

		tree = tree->leaves[bit];
	}

	tree->value = value;
}

OFHuffmanTree *
OFHuffmanTreeNew(uint8_t lengths[], uint16_t count)
{
	OFHuffmanTree *tree;
	uint16_t *lengthCount = NULL;
	uint16_t code, maxCode = 0, *nextCode = NULL;
	uint_fast8_t maxBit = 0;

	@try {
		for (uint16_t i = 0; i < count; i++) {
			uint_fast8_t length = lengths[i];







|


|









|
















|


|







19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#include <stdlib.h>

#import "OFHuffmanTree.h"

#import "OFInvalidFormatException.h"
#import "OFOutOfMemoryException.h"

static OFHuffmanTree
newTree(void)
{
	OFHuffmanTree tree;

	tree = OFAllocMemory(1, sizeof(*tree));
	tree->leaves[0] = tree->leaves[1] = NULL;
	tree->value = 0xFFFF;

	return tree;
}

static void
treeInsert(OFHuffmanTree tree, uint16_t code, uint8_t length, uint16_t value)
{
	while (length > 0) {
		uint8_t bit;

		length--;
		bit = (code & (1u << length)) >> length;

		if (tree->leaves[bit] == NULL)
			tree->leaves[bit] = newTree();

		tree = tree->leaves[bit];
	}

	tree->value = value;
}

OFHuffmanTree
OFHuffmanTreeNew(uint8_t lengths[], uint16_t count)
{
	OFHuffmanTree tree;
	uint16_t *lengthCount = NULL;
	uint16_t code, maxCode = 0, *nextCode = NULL;
	uint_fast8_t maxBit = 0;

	@try {
		for (uint16_t i = 0; i < count; i++) {
			uint_fast8_t length = lengths[i];
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
		OFFreeMemory(lengthCount);
		OFFreeMemory(nextCode);
	}

	return tree;
}

OFHuffmanTree *
OFHuffmanTreeNewSingle(uint16_t value)
{
	OFHuffmanTree *tree = newTree();

	tree->value = value;

	return tree;
}

void
OFHuffmanTreeFree(OFHuffmanTree *tree)
{
	for (uint_fast8_t i = 0; i < 2; i++)
		if OF_LIKELY (tree->leaves[i] != NULL)
			OFHuffmanTreeFree(tree->leaves[i]);

	OFFreeMemory(tree);
}







|


|







|







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
		OFFreeMemory(lengthCount);
		OFFreeMemory(nextCode);
	}

	return tree;
}

OFHuffmanTree
OFHuffmanTreeNewSingle(uint16_t value)
{
	OFHuffmanTree tree = newTree();

	tree->value = value;

	return tree;
}

void
OFHuffmanTreeFree(OFHuffmanTree tree)
{
	for (uint_fast8_t i = 0; i < 2; i++)
		if OF_LIKELY (tree->leaves[i] != NULL)
			OFHuffmanTreeFree(tree->leaves[i]);

	OFFreeMemory(tree);
}

Modified src/OFINICategory.h from [ce099ffcaa] to [f788995406].

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
 *	   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 stringValuesForKey:), 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 stringValuesForKey:), 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 stringValuesForKey:), 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 stringValuesForKey:), 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 stringValuesForKey:), 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;








|
|









|










|
|









|
|









|







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

206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
 */
- (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 stringValuesForKey:), 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







|








206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
 */
- (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

Modified src/OFIPSocketAsyncConnector.m from [8b23b2fea4] to [f532e1ec24].

169
170
171
172
173
174
175



176

177
178
179
180
181
182
183
	[_socket setCanBlock: true];
#else
	[_socket setCanBlock: false];
#endif

	if (![_socket of_connectSocketToAddress: &address errNo: &errNo]) {
#if !defined(OF_NINTENDO_3DS) && !defined(OF_WII)



		if (errNo == EINPROGRESS) {

			[OFRunLoop of_addAsyncConnectForSocket: _socket
							  mode: runLoopMode
						      delegate: self];
			return;
		} else {
#endif
			[_socket of_closeSocket];







>
>
>

>







169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
	[_socket setCanBlock: true];
#else
	[_socket setCanBlock: false];
#endif

	if (![_socket of_connectSocketToAddress: &address errNo: &errNo]) {
#if !defined(OF_NINTENDO_3DS) && !defined(OF_WII)
# ifdef OF_WINDOWS
		if (errNo == EINPROGRESS || errNo == EWOULDBLOCK) {
# else
		if (errNo == EINPROGRESS) {
# endif
			[OFRunLoop of_addAsyncConnectForSocket: _socket
							  mode: runLoopMode
						      delegate: self];
			return;
		} else {
#endif
			[_socket of_closeSocket];

Modified src/OFIPXSocket.h from [716204a756] to [635704366b].

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 OFSocketAddressPort 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 OFSocketAddressIPXNode to get the IPX node and
 * @ref OFSocketAddressPort 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

Modified src/OFInflate64Stream.h from [ff42990035] to [a6bacf7fa9].

47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
			uint8_t position;
			uint8_t length[4];
		} uncompressedHeader;
		struct {
			uint16_t position, length;
		} uncompressed;
		struct {
			OFHuffmanTree *_Nullable litLenTree;
			OFHuffmanTree *_Nullable distTree;
			OFHuffmanTree *_Nullable codeLenTree;
			OFHuffmanTree *_Nullable treeIter;
			uint8_t *_Nullable lengths;
			uint16_t receivedCount;
			uint8_t value, litLenCodesCount, distCodesCount;
			uint8_t codeLenCodesCount;
		} huffmanTree;
		struct {
			OFHuffmanTree *_Nullable litLenTree;
			OFHuffmanTree *_Nullable distTree;
			OFHuffmanTree *_Nullable treeIter;
			int state;
			uint16_t value, length, distance, extraBits;
		} huffman;
	} _context;
	bool _inLastBlock, _atEndOfStream;
}








|
|
|
|






|
|
|







47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
			uint8_t position;
			uint8_t length[4];
		} uncompressedHeader;
		struct {
			uint16_t position, length;
		} uncompressed;
		struct {
			OFHuffmanTree _Nullable litLenTree;
			OFHuffmanTree _Nullable distTree;
			OFHuffmanTree _Nullable codeLenTree;
			OFHuffmanTree _Nullable treeIter;
			uint8_t *_Nullable lengths;
			uint16_t receivedCount;
			uint8_t value, litLenCodesCount, distCodesCount;
			uint8_t codeLenCodesCount;
		} huffmanTree;
		struct {
			OFHuffmanTree _Nullable litLenTree;
			OFHuffmanTree _Nullable distTree;
			OFHuffmanTree _Nullable treeIter;
			int state;
			uint16_t value, length, distance, extraBits;
		} huffman;
	} _context;
	bool _inLastBlock, _atEndOfStream;
}

Modified src/OFInflateStream.h from [6239bc3935] to [f8763882fa].

47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
			uint8_t position;
			uint8_t length[4];
		} uncompressedHeader;
		struct {
			uint16_t position, length;
		} uncompressed;
		struct {
			OFHuffmanTree *_Nullable litLenTree;
			OFHuffmanTree *_Nullable distTree;
			OFHuffmanTree *_Nullable codeLenTree;
			OFHuffmanTree *_Nullable treeIter;
			uint8_t *_Nullable lengths;
			uint16_t receivedCount;
			uint8_t value, litLenCodesCount, distCodesCount;
			uint8_t codeLenCodesCount;
		} huffmanTree;
		struct {
			OFHuffmanTree *_Nullable litLenTree;
			OFHuffmanTree *_Nullable distTree;
			OFHuffmanTree *_Nullable treeIter;
			int state;
			uint16_t value, length, distance, extraBits;
		} huffman;
	} _context;
	bool _inLastBlock, _atEndOfStream;
}








|
|
|
|






|
|
|







47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
			uint8_t position;
			uint8_t length[4];
		} uncompressedHeader;
		struct {
			uint16_t position, length;
		} uncompressed;
		struct {
			OFHuffmanTree _Nullable litLenTree;
			OFHuffmanTree _Nullable distTree;
			OFHuffmanTree _Nullable codeLenTree;
			OFHuffmanTree _Nullable treeIter;
			uint8_t *_Nullable lengths;
			uint16_t receivedCount;
			uint8_t value, litLenCodesCount, distCodesCount;
			uint8_t codeLenCodesCount;
		} huffmanTree;
		struct {
			OFHuffmanTree _Nullable litLenTree;
			OFHuffmanTree _Nullable distTree;
			OFHuffmanTree _Nullable treeIter;
			int state;
			uint16_t value, length, distance, extraBits;
		} huffman;
	} _context;
	bool _inLastBlock, _atEndOfStream;
}

Modified src/OFInflateStream.m from [94ff1319c4] to [ddc6f9f77f].

95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
	0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10,
	10, 11, 11, 12, 12, 13, 13, 14, 14
};
#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;








|







95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
	0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10,
	10, 11, 11, 12, 12, 13, 13, 14, 14
};
#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;

Modified src/OFJSONRepresentation.h from [a068535d8e] to [02ee58f172].

18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
@class OFString;

OF_ASSUME_NONNULL_BEGIN

/**
 * @brief Options to change the behavior when creating a JSON representation.
 */
typedef enum OFJSONRepresentationOptions {
	/** Optimize for readability */
	OFJSONRepresentationOptionPretty       = 0x01,
	/** Generate JSON5 */
	OFJSONRepresentationOptionJSON5	       = 0x02,
	OFJSONRepresentationOptionIsIdentifier = 0x10
} OFJSONRepresentationOptions;








|







18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
@class OFString;

OF_ASSUME_NONNULL_BEGIN

/**
 * @brief Options to change the behavior when creating a JSON representation.
 */
typedef enum {
	/** Optimize for readability */
	OFJSONRepresentationOptionPretty       = 0x01,
	/** Generate JSON5 */
	OFJSONRepresentationOptionJSON5	       = 0x02,
	OFJSONRepresentationOptionIsIdentifier = 0x10
} OFJSONRepresentationOptions;

Modified src/OFLHAArchive.h from [4b0e86f56f] to [934898264e].

27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
 *
 * @brief A class for accessing and manipulating LHA files.
 */
OF_SUBCLASSING_RESTRICTED
@interface OFLHAArchive: OFObject
{
	OFStream *_stream;
	enum {
		OFLHAArchiveModeRead,
		OFLHAArchiveModeWrite,
		OFLHAArchiveModeAppend
	} _mode;
	OFStringEncoding _encoding;
	OFStream *_Nullable _lastReturnedStream;
}

/**
 * @brief The encoding to use for the archive. Defaults to ISO 8859-1.
 */







<
<
<
<
|







27
28
29
30
31
32
33




34
35
36
37
38
39
40
41
 *
 * @brief A class for accessing and manipulating LHA files.
 */
OF_SUBCLASSING_RESTRICTED
@interface OFLHAArchive: OFObject
{
	OFStream *_stream;




	uint_least8_t _mode;
	OFStringEncoding _encoding;
	OFStream *_Nullable _lastReturnedStream;
}

/**
 * @brief The encoding to use for the archive. Defaults to ISO 8859-1.
 */

Modified src/OFLHAArchive.m from [164897d7b4] to [8caabc2fe9].

30
31
32
33
34
35
36






37
38
39
40
41
42
43
#import "OFChecksumMismatchException.h"
#import "OFInvalidArgumentException.h"
#import "OFNotImplementedException.h"
#import "OFNotOpenException.h"
#import "OFOutOfRangeException.h"
#import "OFTruncatedDataException.h"
#import "OFWriteFailedException.h"







OF_DIRECT_MEMBERS
@interface OFLHAArchiveFileReadStream: OFStream <OFReadyForReadingObserving>
{
	OFStream *_stream, *_decompressedStream;
	OFLHAArchiveEntry *_entry;
	uint32_t _toRead, _bytesConsumed;







>
>
>
>
>
>







30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#import "OFChecksumMismatchException.h"
#import "OFInvalidArgumentException.h"
#import "OFNotImplementedException.h"
#import "OFNotOpenException.h"
#import "OFOutOfRangeException.h"
#import "OFTruncatedDataException.h"
#import "OFWriteFailedException.h"

enum {
	modeRead,
	modeWrite,
	modeAppend
};

OF_DIRECT_MEMBERS
@interface OFLHAArchiveFileReadStream: OFStream <OFReadyForReadingObserving>
{
	OFStream *_stream, *_decompressedStream;
	OFLHAArchiveEntry *_entry;
	uint32_t _toRead, _bytesConsumed;
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
{
	self = [super init];

	@try {
		_stream = [stream retain];

		if ([mode isEqual: @"r"])
			_mode = OFLHAArchiveModeRead;
		else if ([mode isEqual: @"w"])
			_mode = OFLHAArchiveModeWrite;
		else if ([mode isEqual: @"a"])
			_mode = OFLHAArchiveModeAppend;
		else
			@throw [OFInvalidArgumentException exception];

		if ((_mode == OFLHAArchiveModeWrite ||
		    _mode == OFLHAArchiveModeAppend) &&
		    ![_stream isKindOfClass: [OFSeekableStream class]])
			@throw [OFInvalidArgumentException exception];

		if (_mode == OFLHAArchiveModeAppend)
			[(OFSeekableStream *)_stream seekToOffset: 0
							   whence: SEEK_END];

		_encoding = OFStringEncodingISO8859_1;
	} @catch (id e) {
		[self release];
		@throw e;







|

|

|



|
<



|







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
{
	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 == modeWrite || _mode == modeAppend) &&

		    ![_stream isKindOfClass: [OFSeekableStream class]])
			@throw [OFInvalidArgumentException exception];

		if (_mode == modeAppend)
			[(OFSeekableStream *)_stream seekToOffset: 0
							   whence: SEEK_END];

		_encoding = OFStringEncodingISO8859_1;
	} @catch (id e) {
		[self release];
		@throw e;
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164

- (OFLHAArchiveEntry *)nextEntry
{
	OFLHAArchiveEntry *entry;
	char header[21];
	size_t headerLen;

	if (_mode != OFLHAArchiveModeRead)
		@throw [OFInvalidArgumentException exception];

	[(OFLHAArchiveFileReadStream *)_lastReturnedStream of_skip];
	@try {
		[_lastReturnedStream close];
	} @catch (OFNotOpenException *e) {
		/* Might have already been closed by the user - that's fine. */







|







155
156
157
158
159
160
161
162
163
164
165
166
167
168
169

- (OFLHAArchiveEntry *)nextEntry
{
	OFLHAArchiveEntry *entry;
	char header[21];
	size_t headerLen;

	if (_mode != modeRead)
		@throw [OFInvalidArgumentException exception];

	[(OFLHAArchiveFileReadStream *)_lastReturnedStream of_skip];
	@try {
		[_lastReturnedStream close];
	} @catch (OFNotOpenException *e) {
		/* Might have already been closed by the user - that's fine. */
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
			entry: entry];

	return entry;
}

- (OFStream *)streamForReadingCurrentEntry
{
	if (_mode != OFLHAArchiveModeRead)
		@throw [OFInvalidArgumentException exception];

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

	return [[(OFLHAArchiveFileReadStream *)_lastReturnedStream
	    retain] autorelease];
}

- (OFStream *)streamForWritingEntry: (OFLHAArchiveEntry *)entry
{
	OFString *compressionMethod;

	if (_mode != OFLHAArchiveModeWrite && _mode != OFLHAArchiveModeAppend)
		@throw [OFInvalidArgumentException exception];

	compressionMethod = entry.compressionMethod;

	if (![compressionMethod isEqual: @"-lh0-"] &&
	    ![compressionMethod isEqual: @"-lhd-"])
		@throw [OFNotImplementedException exceptionWithSelector: _cmd







|













|







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
			entry: entry];

	return entry;
}

- (OFStream *)streamForReadingCurrentEntry
{
	if (_mode != modeRead)
		@throw [OFInvalidArgumentException exception];

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

	return [[(OFLHAArchiveFileReadStream *)_lastReturnedStream
	    retain] autorelease];
}

- (OFStream *)streamForWritingEntry: (OFLHAArchiveEntry *)entry
{
	OFString *compressionMethod;

	if (_mode != modeWrite && _mode != modeAppend)
		@throw [OFInvalidArgumentException exception];

	compressionMethod = entry.compressionMethod;

	if (![compressionMethod isEqual: @"-lh0-"] &&
	    ![compressionMethod isEqual: @"-lhd-"])
		@throw [OFNotImplementedException exceptionWithSelector: _cmd

Modified src/OFLHADecompressingStream.h from [4239b91057] to [50abfd9a4a].

31
32
33
34
35
36
37
38


39
40
41
42
43
44
45
46
	uint8_t _byte;
	uint8_t _bitIndex, _savedBitsLength;
	uint16_t _savedBits;
	unsigned char *_slidingWindow;
	uint32_t _slidingWindowIndex, _slidingWindowMask;
	int _state;
	uint16_t _symbolsLeft;
	OFHuffmanTree *_Nullable _codeLenTree, *_Nullable _litLenTree;


	OFHuffmanTree *_Nullable _distTree, *_Nullable _treeIter;
	uint16_t _codesCount, _codesReceived;
	bool _currentIsExtendedLength, _skip;
	uint8_t *_Nullable _codesLengths;
	uint16_t _length;
	uint32_t _distance;
}








|
>
>
|







31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
	uint8_t _byte;
	uint8_t _bitIndex, _savedBitsLength;
	uint16_t _savedBits;
	unsigned char *_slidingWindow;
	uint32_t _slidingWindowIndex, _slidingWindowMask;
	int _state;
	uint16_t _symbolsLeft;
	OFHuffmanTree _Nullable _codeLenTree;
	OFHuffmanTree _Nullable _litLenTree;
	OFHuffmanTree _Nullable _distTree;
	OFHuffmanTree _Nullable _treeIter;
	uint16_t _codesCount, _codesReceived;
	bool _currentIsExtendedLength, _skip;
	uint8_t *_Nullable _codesLengths;
	uint16_t _length;
	uint32_t _distance;
}

Modified src/OFList.h from [0e994cc065] to [e9b48b38c5].

16
17
18
19
20
21
22










23
24
25
26
27
28
29
30



31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
#import "OFObject.h"
#import "OFCollection.h"
#import "OFEnumerator.h"
#import "OFSerialization.h"

OF_ASSUME_NONNULL_BEGIN











/**
 * @typedef OFListItem OFList.h ObjFW/OFList.h
 *
 * @brief A list item.
 *
 * See @ref OFListItemNext, @ref OFListItemPrevious and @ref OFListItemObject.
 */
typedef struct OFListItem *OFListItem;




#ifdef __cplusplus
extern "C" {
#endif
/*!
 * @brief Returns the next list item of the list item.
 *
 * @param listItem The list item for which the next list item should be returned
 * @return The next list item of the list item
 */
OFListItem OFListItemNext(OFListItem _Nonnull listItem);

/*!
 * @brief Returns the previous list item of the list item.
 *
 * @param listItem The list item for which the previous list item should be
 *		   returned
 * @return The previous list item of the list item
 */
OFListItem OFListItemPrevious(OFListItem _Nonnull listItem);

/*!
 * @brief Returns the object of the list item.
 *
 * @warning The returned object is not retained and autoreleased - this is the
 *	    caller's responsibility!
 *
 * @param listItem The list item for which the object should be returned
 * @return The object of the list item
 */
id OFListItemObject(OFListItem _Nonnull listItem);
#ifdef __cplusplus
}
#endif

/**
 * @class OFList OFList.h ObjFW/OFList.h
 *







>
>
>
>
>
>
>
>
>
>

|





|
>
>
>










|








|










|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
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
#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
 * thinks is not a struct. Doxygen requires it this way.
 */
#ifdef __clang__
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wdocumentation"
#endif
/**
 * @struct OFListItem OFList.h ObjFW/OFList.h
 *
 * @brief A list item.
 *
 * See @ref OFListItemNext, @ref OFListItemPrevious and @ref OFListItemObject.
 */
typedef struct _OFListItem *OFListItem;
#ifdef __clang__
# pragma clang diagnostic pop
#endif

#ifdef __cplusplus
extern "C" {
#endif
/*!
 * @brief Returns the next list item of the list item.
 *
 * @param listItem The list item for which the next list item should be returned
 * @return The next list item of the list item
 */
extern OFListItem _Nullable OFListItemNext(OFListItem _Nonnull listItem);

/*!
 * @brief Returns the previous list item of the list item.
 *
 * @param listItem The list item for which the previous list item should be
 *		   returned
 * @return The previous list item of the list item
 */
extern OFListItem _Nullable OFListItemPrevious(OFListItem _Nonnull listItem);

/*!
 * @brief Returns the object of the list item.
 *
 * @warning The returned object is not retained and autoreleased - this is the
 *	    caller's responsibility!
 *
 * @param listItem The list item for which the object should be returned
 * @return The object of the list item
 */
extern id _Nonnull OFListItemObject(OFListItem _Nonnull listItem);
#ifdef __cplusplus
}
#endif

/**
 * @class OFList OFList.h ObjFW/OFList.h
 *

Modified src/OFList.m from [71b5abf54f] to [75ee6d9e19].

22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#import "OFString.h"
#import "OFXMLElement.h"
#import "OFArray.h"

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

struct OFListItem {
	OFListItem previous, next;
	id object;
};

OF_DIRECT_MEMBERS
@interface OFListEnumerator: OFEnumerator
{
	OFList *_list;







|
|







22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#import "OFString.h"
#import "OFXMLElement.h"
#import "OFArray.h"

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

struct _OFListItem {
	struct _OFListItem *previous, *next;
	id object;
};

OF_DIRECT_MEMBERS
@interface OFListEnumerator: OFEnumerator
{
	OFList *_list;

Modified src/OFLocale.m from [54708bc402] to [947d4e8829].

422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
		if (GetVar("Charset", buffer, sizeof(buffer), 0) > 0) {
# else
		if (0) {
# endif
			OFStringEncoding ASCII = OFStringEncodingASCII;

			@try {
				_encoding = OFStringEncodingForName(
				    [OFString stringWithCString: buffer
						       encoding: ASCII]);
			} @catch (OFInvalidArgumentException *e) {
				_encoding = OFStringEncodingISO8859_1;
			}
		} else
			_encoding = OFStringEncodingISO8859_1;







|







422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
		if (GetVar("Charset", buffer, sizeof(buffer), 0) > 0) {
# else
		if (0) {
# endif
			OFStringEncoding ASCII = OFStringEncodingASCII;

			@try {
				_encoding = OFStringEncodingParseName(
				    [OFString stringWithCString: buffer
						       encoding: ASCII]);
			} @catch (OFInvalidArgumentException *e) {
				_encoding = OFStringEncodingISO8859_1;
			}
		} else
			_encoding = OFStringEncodingISO8859_1;

Modified src/OFMapTable.h from [0dfbcfb542] to [67af88b431].

21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
/** @file */

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

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







|









<
|







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

38
39
40
41
42
43
44
45
/** @file */

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

} OFMapTableFunctions;

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

Modified src/OFMapTable.m from [6075b5b12b] to [37fa19bf82].

23
24
25
26
27
28
29


30
31
32
33
34
35
36
#import "OFMapTable.h"
#import "OFMapTable+Private.h"
#import "OFEnumerator.h"

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



static const unsigned long minCapacity = 16;

struct OFMapTableBucket {
	void *key, *object;
	unsigned long hash;
};







>
>







23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#import "OFMapTable.h"
#import "OFMapTable+Private.h"
#import "OFEnumerator.h"

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

extern unsigned long OFHashSeed;

static const unsigned long minCapacity = 16;

struct OFMapTableBucket {
	void *key, *object;
	unsigned long hash;
};

Modified src/OFObject.h from [d972931bb6] to [256748162e].

50
51
52
53
54
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
OF_ASSUME_NONNULL_BEGIN

/** @file */

/**
 * @brief A result of a comparison.
 */
typedef enum OFComparisonResult {
	/** The left object is smaller than the right */
	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
 */
typedef OFComparisonResult (^OFComparator)(id _Nonnull left, id _Nonnull right);
#endif

/**
 * @brief An enum for storing endianess.
 */
typedef enum OFByteOrder {
	/** Most significant byte first (big endian) */
	OFByteOrderBigEndian,
	/** Least significant byte first (little endian) */
	OFByteOrderLittleEndian,
	/** Native byte order of the system */
#ifdef OF_BIG_ENDIAN
	OFByteOrderNative = OFByteOrderBigEndian
#else
	OFByteOrderNative = OFByteOrderLittleEndian
#endif
} OFByteOrder;

/**
 * @struct OFRange OFObject.h ObjFW/OFObject.h
 *
 * @brief A range.
 */
struct OF_BOXABLE OFRange {
	/** The start of the range */
	size_t location;
	/** The length of the range */
	size_t length;
};
typedef struct OFRange OFRange;

/**
 * @brief Creates a new OFRange.
 *
 * @param start The starting index of the range
 * @param length The length of the range
 * @return An OFRangeith the specified start and length







|




















|

|

















|




<
|







50
51
52
53
54
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
OF_ASSUME_NONNULL_BEGIN

/** @file */

/**
 * @brief A result of a comparison.
 */
typedef enum {
	/** The left object is smaller than the right */
	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
 */
typedef OFComparisonResult (^OFComparator)(id _Nonnull left, id _Nonnull right);
#endif

/**
 * @brief An enum for representing endianess.
 */
typedef enum {
	/** Most significant byte first (big endian) */
	OFByteOrderBigEndian,
	/** Least significant byte first (little endian) */
	OFByteOrderLittleEndian,
	/** Native byte order of the system */
#ifdef OF_BIG_ENDIAN
	OFByteOrderNative = OFByteOrderBigEndian
#else
	OFByteOrderNative = OFByteOrderLittleEndian
#endif
} 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;

/**
 * @brief Creates a new OFRange.
 *
 * @param start The starting index of the range
 * @param length The length of the range
 * @return An OFRangeith the specified start and length
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
typedef double OFTimeInterval;

/**
 * @struct OFPoint OFObject.h ObjFW/OFObject.h
 *
 * @brief A point.
 */
struct OF_BOXABLE OFPoint {
	/** The x coordinate of the point */
	float x;
	/** The y coordinate of the point */
	float y;
};
typedef struct OFPoint OFPoint;

/**
 * @brief Creates a new OFPoint.
 *
 * @param x The x coordinate of the point
 * @param y The x coordinate of the point
 * @return An OFPoint with the specified coordinates







|




<
|







142
143
144
145
146
147
148
149
150
151
152
153

154
155
156
157
158
159
160
161
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;

/**
 * @brief Creates a new OFPoint.
 *
 * @param x The x coordinate of the point
 * @param y The x coordinate of the point
 * @return An OFPoint with the specified coordinates
190
191
192
193
194
195
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.
 */
struct OF_BOXABLE OFSize {
	/** The width of the size */
	float width;
	/** The height of the size */
	float height;
};
typedef struct OFSize OFSize;

/**
 * @brief Creates a new OFSize.
 *
 * @param width The width of the size
 * @param height The height of the size
 * @return An OFSize with the specified width and height







|




<
|







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

200
201
202
203
204
205
206
207
}

/**
 * @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;

/**
 * @brief Creates a new OFSize.
 *
 * @param width The width of the size
 * @param height The height of the size
 * @return An OFSize with the specified width and height
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
}

/**
 * @struct OFRect OFObject.h ObjFW/OFObject.h
 *
 * @brief A rectangle.
 */
struct OF_BOXABLE OFRect {
	/** The point from where the rectangle originates */
	OFPoint origin;
	/** The size of the rectangle */
	OFSize size;
};
typedef struct OFRect OFRect;

/**
 * @brief Creates a new OFRect.
 *
 * @param x The x coordinate of the top left corner of the rectangle
 * @param y The y coordinate of the top left corner of the rectangle
 * @param width The width of the rectangle







|




<
|







234
235
236
237
238
239
240
241
242
243
244
245

246
247
248
249
250
251
252
253
}

/**
 * @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;

/**
 * @brief Creates a new OFRect.
 *
 * @param x The x coordinate of the top left corner of the rectangle
 * @param y The y coordinate of the top left corner of the rectangle
 * @param width The width of the rectangle
283
284
285
286
287
288
289


















































290
291
292
293
294
295
296
		return false;

	if (!OFSizeEqual(rect1.size, rect2.size))
		return false;

	return true;
}



















































static const size_t OFNotFound = SIZE_MAX;

#ifdef __OBJC__
@class OFMethodSignature;
@class OFString;
@class OFThread;







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







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
		return false;

	if (!OFSizeEqual(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
 * @param byte The byte to add to the hash
 */
static OF_INLINE void
OFHashAdd(unsigned long *_Nonnull hash, unsigned char byte)
{
	uint32_t tmp = (uint32_t)*hash;

	tmp += byte;
	tmp += tmp << 10;
	tmp ^= tmp >> 6;

	*hash = tmp;
}

/**
 * @brief Adds the specified hash to the hash.
 *
 * @param hash A pointer to a hash to add the hash to
 * @param otherHash The hash to add to the hash
 */
static OF_INLINE void
OFHashAddHash(unsigned long *_Nonnull hash, unsigned long otherHash)
{
	OFHashAdd(hash, (otherHash >> 24) & 0xFF);
	OFHashAdd(hash, (otherHash >> 16) & 0xFF);
	OFHashAdd(hash, (otherHash >>  8) & 0xFF);
	OFHashAdd(hash, otherHash & 0xFF);
}

/**
 * @brief Finalizes the specified hash.
 *
 * @param hash A pointer to the hash to finalize
 */
static OF_INLINE void
OFHashFinalize(unsigned long *_Nonnull hash)
{
	uint32_t tmp = (uint32_t)*hash;

	tmp += tmp << 3;
	tmp ^= tmp >> 11;
	tmp += tmp << 15;

	*hash = tmp;
}

static const size_t OFNotFound = SIZE_MAX;

#ifdef __OBJC__
@class OFMethodSignature;
@class OFString;
@class OFThread;
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
/**
 * @brief A method which is called when the class is unloaded from the runtime.
 *
 * Derived classes can override this to execute their own code when the class
 * is unloaded.
 *
 * @warning This is not supported by the Apple runtime and currently only
 *	    called by the ObjFW runtime when objc_unregister_class() or
 *	    objc_exit() has been called!
 *	    In the future, this might also be called by the ObjFW runtime when
 *	    the class is part of a plugin that has been unloaded.
 */
+ (void)unload;

/**
 * @brief A method which is called the moment before the first call to the class
 *	  is being made.
 *







|
<

|







625
626
627
628
629
630
631
632

633
634
635
636
637
638
639
640
641
/**
 * @brief A method which is called when the class is unloaded from the runtime.
 *
 * Derived classes can override this to execute their own code when the class
 * is unloaded.
 *
 * @warning This is not supported by the Apple runtime and currently only
 *	    called by the ObjFW runtime when @ref objc_deinit has been called!

 *	    In the future, this might also be called by the ObjFW runtime when
 *	    the class is part of a plugin that is being unloaded.
 */
+ (void)unload;

/**
 * @brief A method which is called the moment before the first call to the class
 *	  is being made.
 *
1332
1333
1334
1335
1336
1337
1338







1339
1340
1341
1342
1343
1344
1345

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

#include "OFBlock.h"







>
>
>
>
>
>
>







1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397

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

Modified src/OFObject.m from [63795ddfa3] to [4833385eee].

68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
#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, ...);
extern struct stret OFForward_stret(id, SEL, ...);
#else
# define OFForward OFMethodNotFound
# define OFForward_stret OFMethodNotFound_stret
#endif

struct PreIvars {
	int retainCount;







|







68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
#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, ...);
extern struct Stret OFForward_stret(id, SEL, ...);
#else
# define OFForward OFMethodNotFound
# define OFForward_stret OFMethodNotFound_stret
#endif

struct PreIvars {
	int retainCount;
223
224
225
226
227
228
229






230
231
232
233
234
235
236
	OFEnsure(getrandom(&buffer, sizeof(buffer), 0) == sizeof(buffer));

	return buffer;
#else
	return ((uint64_t)OFRandom32() << 32) | OFRandom32();
#endif
}







static const char *
typeEncodingForSelector(Class class, SEL selector)
{
	Method method;

	if ((method = class_getInstanceMethod(class, selector)) == NULL)







>
>
>
>
>
>







223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
	OFEnsure(getrandom(&buffer, sizeof(buffer), 0) == sizeof(buffer));

	return buffer;
#else
	return ((uint64_t)OFRandom32() << 32) | OFRandom32();
#endif
}

void
OFHashInit(unsigned long *hash)
{
	*hash = OFHashSeed;
}

static const char *
typeEncodingForSelector(Class class, SEL selector)
{
	Method method;

	if ((method = class_getInstanceMethod(class, selector)) == NULL)

Modified src/OFOptionsParser.h from [84a06358b9] to [aa712b561c].

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

/**
 * @struct OFOptionsParserOption OFOptionsParser.h ObjFW/OFOptionsParser.h
 *
 * @brief An option which can be parsed by an @ref OFOptionsParser.
 */
struct OFOptionsParserOption {
	/** The short version (e.g. `-v`) of the option or `\0` for none. */
	OFUnichar shortOption;

	/**
	 * The long version (e.g. `--verbose`) of the option or `nil` for none.
	 */
	OFString *__unsafe_unretained _Nullable longOption;







|







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

/**
 * @struct OFOptionsParserOption OFOptionsParser.h ObjFW/OFOptionsParser.h
 *
 * @brief An option which can be parsed by an @ref OFOptionsParser.
 */
typedef struct {
	/** The short version (e.g. `-v`) of the option or `\0` for none. */
	OFUnichar shortOption;

	/**
	 * The long version (e.g. `--verbose`) of the option or `nil` for none.
	 */
	OFString *__unsafe_unretained _Nullable longOption;
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
	bool *_Nullable isSpecifiedPtr;

	/**
	 * An optional pointer to an `OFString *` that is set to the
	 * argument specified for the option or `nil` for no argument.
	 */
	OFString *__autoreleasing _Nullable *_Nullable argumentPtr;
};
typedef struct OFOptionsParserOption OFOptionsParserOption;

/**
 * @class OFOptionsParser OFOptionsParser.h ObjFW/OFOptionsParser.h
 *
 * @brief A class for parsing the program options specified on the command line.
 */
OF_SUBCLASSING_RESTRICTED







<
|







53
54
55
56
57
58
59

60
61
62
63
64
65
66
67
	bool *_Nullable isSpecifiedPtr;

	/**
	 * An optional pointer to an `OFString *` that is set to the
	 * argument specified for the option or `nil` for no argument.
	 */
	OFString *__autoreleasing _Nullable *_Nullable argumentPtr;

} OFOptionsParserOption;

/**
 * @class OFOptionsParser OFOptionsParser.h ObjFW/OFOptionsParser.h
 *
 * @brief A class for parsing the program options specified on the command line.
 */
OF_SUBCLASSING_RESTRICTED

Modified src/OFPBKDF2.h from [bc04db6a17] to [31c9840de8].

27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
/** @file */

@class OFHMAC;

/**
 * @brief The parameters for @ref OFPBKDF2.
 */
typedef struct OFPBKDF2Parameters {
	/** @brief The HMAC to use to derive a key. */
	__unsafe_unretained OFHMAC *HMAC;
	/** @brief The number of iterations to perform. */
	size_t iterations;
	/** @brief The salt to derive a key with. */
	const unsigned char *salt;
	/** @brief The length of the salt. */







|







27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
/** @file */

@class OFHMAC;

/**
 * @brief The parameters for @ref OFPBKDF2.
 */
typedef struct {
	/** @brief The HMAC to use to derive a key. */
	__unsafe_unretained OFHMAC *HMAC;
	/** @brief The number of iterations to perform. */
	size_t iterations;
	/** @brief The salt to derive a key with. */
	const unsigned char *salt;
	/** @brief The length of the salt. */

Modified src/OFPlainCondition.m from [6e88b3caee] to [5c92a31d36].

14
15
16
17
18
19
20
21
22
23
24
25
26
 */

#include "config.h"

#include "platform.h"

#if defined(OF_HAVE_PTHREADS)
# include "platform/posix/OFPlainCondition.m"
#elif defined(OF_WINDOWS)
# include "platform/windows/OFPlainCondition.m"
#elif defined(OF_AMIGAOS)
# include "platform/amiga/OFPlainCondition.m"
#endif







|

|

|

14
15
16
17
18
19
20
21
22
23
24
25
26
 */

#include "config.h"

#include "platform.h"

#if defined(OF_HAVE_PTHREADS)
# include "platform/POSIX/OFPlainCondition.m"
#elif defined(OF_WINDOWS)
# include "platform/Windows/OFPlainCondition.m"
#elif defined(OF_AMIGAOS)
# include "platform/AmigaOS/OFPlainCondition.m"
#endif

Modified src/OFPlainMutex.m from [9e6dac45f3] to [f697ac3445].

14
15
16
17
18
19
20
21
22
23
24
25
26
 */

#include "config.h"

#include "platform.h"

#if defined(OF_HAVE_PTHREADS)
# include "platform/posix/OFPlainMutex.m"
#elif defined(OF_WINDOWS)
# include "platform/windows/OFPlainMutex.m"
#elif defined(OF_AMIGAOS)
# include "platform/amiga/OFPlainMutex.m"
#endif







|

|

|

14
15
16
17
18
19
20
21
22
23
24
25
26
 */

#include "config.h"

#include "platform.h"

#if defined(OF_HAVE_PTHREADS)
# include "platform/POSIX/OFPlainMutex.m"
#elif defined(OF_WINDOWS)
# include "platform/Windows/OFPlainMutex.m"
#elif defined(OF_AMIGAOS)
# include "platform/AmigaOS/OFPlainMutex.m"
#endif

Modified src/OFPlainThread.h from [9dd4ef3d72] to [00cdbb5121].

40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
	struct SignalSemaphore semaphore;
	struct Task *joinTask;
	unsigned char joinSigBit;
	bool detached, done;
} *OFPlainThread;
#endif

typedef struct OFPlainThreadAttributes {
	float priority;
	size_t stackSize;
} OFPlainThreadAttributes;

#if defined(OF_HAVE_PTHREADS)
static OF_INLINE OFPlainThread
OFCurrentPlainThread(void)







|







40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
	struct SignalSemaphore semaphore;
	struct Task *joinTask;
	unsigned char joinSigBit;
	bool detached, done;
} *OFPlainThread;
#endif

typedef struct {
	float priority;
	size_t stackSize;
} OFPlainThreadAttributes;

#if defined(OF_HAVE_PTHREADS)
static OF_INLINE OFPlainThread
OFCurrentPlainThread(void)
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
static OF_INLINE bool
OFPlainThreadIsCurrent(OFPlainThread thread)
{
	return (thread == GetCurrentThread());
}
#elif defined(OF_AMIGAOS)
extern OFPlainThread OFCurrentPlainThread(void);

static OF_INLINE bool
OFPlainThreadIsCurrent(OFPlainThread thread)
{
	return (thread->thread == FindTask(NULL));
}
#endif

#ifdef __cplusplus
extern "C" {
#endif
extern int OFPlainThreadAttributesInit(OFPlainThreadAttributes *attr);
extern int OFPlainThreadNew(OFPlainThread *thread, const char *name,







<
<
|
<
<
<







71
72
73
74
75
76
77


78



79
80
81
82
83
84
85
static OF_INLINE bool
OFPlainThreadIsCurrent(OFPlainThread thread)
{
	return (thread == GetCurrentThread());
}
#elif defined(OF_AMIGAOS)
extern OFPlainThread OFCurrentPlainThread(void);


extern bool OFPlainThreadIsCurrent(OFPlainThread);



#endif

#ifdef __cplusplus
extern "C" {
#endif
extern int OFPlainThreadAttributesInit(OFPlainThreadAttributes *attr);
extern int OFPlainThreadNew(OFPlainThread *thread, const char *name,

Modified src/OFPlainThread.m from [0fae510ae5] to [77054b78a9].

14
15
16
17
18
19
20
21
22
23
24
25
26
 */

#include "config.h"

#include "platform.h"

#if defined(OF_HAVE_PTHREADS)
# include "platform/posix/OFPlainThread.m"
#elif defined(OF_WINDOWS)
# include "platform/windows/OFPlainThread.m"
#elif defined(OF_AMIGAOS)
# include "platform/amiga/OFPlainThread.m"
#endif







|

|

|

14
15
16
17
18
19
20
21
22
23
24
25
26
 */

#include "config.h"

#include "platform.h"

#if defined(OF_HAVE_PTHREADS)
# include "platform/POSIX/OFPlainThread.m"
#elif defined(OF_WINDOWS)
# include "platform/Windows/OFPlainThread.m"
#elif defined(OF_AMIGAOS)
# include "platform/AmigaOS/OFPlainThread.m"
#endif

Modified src/OFPlugin.h from [0127a43dd2] to [53f335d6bf].

17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43




44
45
46
47
48
49
50

@class OFString;

#ifndef OF_WINDOWS
# include <dlfcn.h>
typedef void *OFPluginHandle;

typedef enum OFDLOpenFlags {
	OFDLOpenFlagLazy = RTLD_LAZY,
	OFDLOpenFlagNow  = RTLD_NOW
} OFDLOpenFlags;
#else
# include <windows.h>
typedef HMODULE OFPluginHandle;

typedef enum OFDLOpenFlags {
	OFDLOpenFlagLazy = 0,
	OFDLOpenFlagNow  = 0
} OFDLOpenFlags;
#endif

OF_ASSUME_NONNULL_BEGIN

/**
 * @class OFPlugin OFPlugin.h ObjFW/OFPlugin.h
 *
 * @brief Provides a system for loading plugins at runtime.




 */
@interface OFPlugin: OFObject
{
	OFPluginHandle _pluginHandle;
	OF_RESERVE_IVARS(OFPlugin, 4)
}








|







|











>
>
>
>







17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54

@class OFString;

#ifndef OF_WINDOWS
# include <dlfcn.h>
typedef void *OFPluginHandle;

typedef enum {
	OFDLOpenFlagLazy = RTLD_LAZY,
	OFDLOpenFlagNow  = RTLD_NOW
} OFDLOpenFlags;
#else
# include <windows.h>
typedef HMODULE OFPluginHandle;

typedef enum {
	OFDLOpenFlagLazy = 0,
	OFDLOpenFlagNow  = 0
} OFDLOpenFlags;
#endif

OF_ASSUME_NONNULL_BEGIN

/**
 * @class OFPlugin OFPlugin.h ObjFW/OFPlugin.h
 *
 * @brief Provides a system for loading plugins at runtime.
 *
 * A plugin must subclass @ref OFPlugin and have a global function called
 * `OFPluginInit`, which returns an instance of the @ref OFPlugin subclass and
 * takes no parameters.
 */
@interface OFPlugin: OFObject
{
	OFPluginHandle _pluginHandle;
	OF_RESERVE_IVARS(OFPlugin, 4)
}

Modified src/OFRunLoop.m from [ab97878b5e] to [cc008951a5].

39
40
41
42
43
44
45

46
47
48
49
50
51
52
53
#import "OFSortedList.h"
#import "OFTimer.h"
#import "OFTimer+Private.h"
#import "OFDate.h"

#import "OFObserveFailedException.h"


const OFRunLoopMode OFDefaultRunLoopMode = @"OFDefaultRunLoopMode";
static OFRunLoop *mainRunLoop = nil;

@interface OFRunLoopState: OFObject
#ifdef OF_HAVE_SOCKETS
    <OFKernelEventObserverDelegate>
#endif
{







>
|







39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#import "OFSortedList.h"
#import "OFTimer.h"
#import "OFTimer+Private.h"
#import "OFDate.h"

#import "OFObserveFailedException.h"

#include "OFRunLoopConstants.inc"

static OFRunLoop *mainRunLoop = nil;

@interface OFRunLoopState: OFObject
#ifdef OF_HAVE_SOCKETS
    <OFKernelEventObserverDelegate>
#endif
{
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
- (void)of_removeTimer: (OFTimer *)timer forMode: (OFRunLoopMode)mode
{
	OFRunLoopState *state = stateForMode(self, mode, false);

	if (state == nil)
		return;






#ifdef OF_HAVE_THREADS
	[state->_timersQueueMutex lock];
	@try {
#endif
		for (OFListItem iter = state->_timersQueue.firstListItem;
		    iter != NULL; iter = OFListItemNext(iter)) {
			if ([OFListItemObject(iter) isEqual: timer]) {
				[state->_timersQueue removeListItem: iter];
				break;
			}
		}
#ifdef OF_HAVE_THREADS
	} @finally {
		[state->_timersQueueMutex unlock];
	}
#endif


}

#ifdef OF_AMIGAOS
- (void)addExecSignal: (ULONG)signal target: (id)target selector: (SEL)selector
{
	[self addExecSignal: signal
		    forMode: OFDefaultRunLoopMode







>
>
>
>
>
















>
>







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
- (void)of_removeTimer: (OFTimer *)timer forMode: (OFRunLoopMode)mode
{
	OFRunLoopState *state = stateForMode(self, mode, false);

	if (state == nil)
		return;

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpragmas"
#pragma GCC diagnostic ignored "-Wunknown-warning-option"
#pragma GCC diagnostic ignored "-Wmisleading-indentation"

#ifdef OF_HAVE_THREADS
	[state->_timersQueueMutex lock];
	@try {
#endif
		for (OFListItem iter = state->_timersQueue.firstListItem;
		    iter != NULL; iter = OFListItemNext(iter)) {
			if ([OFListItemObject(iter) isEqual: timer]) {
				[state->_timersQueue removeListItem: iter];
				break;
			}
		}
#ifdef OF_HAVE_THREADS
	} @finally {
		[state->_timersQueueMutex unlock];
	}
#endif

#pragma GCC diagnostic pop
}

#ifdef OF_AMIGAOS
- (void)addExecSignal: (ULONG)signal target: (id)target selector: (SEL)selector
{
	[self addExecSignal: signal
		    forMode: OFDefaultRunLoopMode

Added src/OFRunLoopConstants.inc version [e240ef8cad].

































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/*
 * 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.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

const OFRunLoopMode OFDefaultRunLoopMode = @"OFDefaultRunLoopMode";

Modified src/OFSPXSocket.m from [6a8d63bff0] to [1dcd330269].

113
114
115
116
117
118
119



120

121
122
123
124
125
126
127
		exception = [self of_connectionFailedExceptionForErrNo: errNo];
		goto inform_delegate;
	}

	_socket.canBlock = false;

	if (![_socket of_connectSocketToAddress: &address errNo: &errNo]) {



		if (errNo == EINPROGRESS) {

			[OFRunLoop of_addAsyncConnectForSocket: _socket
							  mode: runLoopMode
						      delegate: self];
			return;
		}

		[_socket of_closeSocket];







>
>
>

>







113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
		exception = [self of_connectionFailedExceptionForErrNo: errNo];
		goto inform_delegate;
	}

	_socket.canBlock = false;

	if (![_socket of_connectSocketToAddress: &address errNo: &errNo]) {
#ifdef OF_WINDOWS
		if (errNo == EINPROGRESS || errNo == EWOULDBLOCK) {
#else
		if (errNo == EINPROGRESS) {
#endif
			[OFRunLoop of_addAsyncConnectForSocket: _socket
							  mode: runLoopMode
						      delegate: self];
			return;
		}

		[_socket of_closeSocket];

Modified src/OFSPXStreamSocket.m from [cf40daf6c1] to [d6a9ec0451].

114
115
116
117
118
119
120



121

122
123
124
125
126
127
128
		exception = [self of_connectionFailedExceptionForErrNo: errNo];
		goto inform_delegate;
	}

	_socket.canBlock = false;

	if (![_socket of_connectSocketToAddress: &address errNo: &errNo]) {



		if (errNo == EINPROGRESS) {

			[OFRunLoop of_addAsyncConnectForSocket: _socket
							  mode: runLoopMode
						      delegate: self];
			return;
		}

		[_socket of_closeSocket];







>
>
>

>







114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
		exception = [self of_connectionFailedExceptionForErrNo: errNo];
		goto inform_delegate;
	}

	_socket.canBlock = false;

	if (![_socket of_connectSocketToAddress: &address errNo: &errNo]) {
#ifdef OF_WINDOWS
		if (errNo == EINPROGRESS || errNo == EWOULDBLOCK) {
#else
		if (errNo == EINPROGRESS) {
#endif
			[OFRunLoop of_addAsyncConnectForSocket: _socket
							  mode: runLoopMode
						      delegate: self];
			return;
		}

		[_socket of_closeSocket];

Modified src/OFScrypt.h from [92dd465a18] to [77947b171a].

27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
/** @file */

@class OFHMAC;

/**
 * @brief The parameters for @ref OFScrypt.
 */
typedef struct OFScryptParameters {
	/** @brief The block size to use. */
	size_t blockSize;
	/** @brief The CPU/memory cost factor to use. */
	size_t costFactor;
	/** @brief The parallelization to use. */
	size_t parallelization;
	/** @brief The salt to derive a key with. */







|







27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
/** @file */

@class OFHMAC;

/**
 * @brief The parameters for @ref OFScrypt.
 */
typedef struct {
	/** @brief The block size to use. */
	size_t blockSize;
	/** @brief The CPU/memory cost factor to use. */
	size_t costFactor;
	/** @brief The parallelization to use. */
	size_t parallelization;
	/** @brief The salt to derive a key with. */

Modified src/OFSecureData.h from [3c696dcd02] to [69bd454c65].

28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
 *	    deallocated. Check the @ref allowsSwappableMemory property to see
 *	    whether a particular OFSecureData might be allocated in swappable
 *	    memory.
 */
OF_SUBCLASSING_RESTRICTED
@interface OFSecureData: OFData
{
	struct page *_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
 *	    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;

Modified src/OFSecureData.m from [850d3da4ab] to [80f9f47dea].

34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#import "OFNotImplementedException.h"
#import "OFOutOfMemoryException.h"
#import "OFOutOfRangeException.h"

#if defined(HAVE_MMAP) && defined(HAVE_MLOCK) && defined(MAP_ANON)
static const size_t chunkSize = 16;

struct page {
	struct page *next, *previous;
	void *map;
	unsigned char *page;
};

# if defined(OF_HAVE_COMPILER_TLS)
static thread_local struct page *firstPage = NULL;
static thread_local struct page *lastPage = NULL;
static thread_local struct page **preallocatedPages = NULL;
static thread_local size_t numPreallocatedPages = 0;
# elif defined(OF_HAVE_THREADS)
static OFTLSKey firstPageKey, lastPageKey;
static OFTLSKey preallocatedPagesKey, numPreallocatedPagesKey;
# else
static struct page *firstPage = NULL;
static struct page *lastPage = NULL;
static struct page **preallocatedPages = NULL;
static size_t numPreallocatedPages = 0;
# endif

static void *
mapPages(size_t numPages)
{
	size_t pageSize = [OFSystemInfo pageSize];







|
|





|
|
|





|
|
|







34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#import "OFNotImplementedException.h"
#import "OFOutOfMemoryException.h"
#import "OFOutOfRangeException.h"

#if defined(HAVE_MMAP) && defined(HAVE_MLOCK) && defined(MAP_ANON)
static const size_t chunkSize = 16;

struct Page {
	struct Page *next, *previous;
	void *map;
	unsigned char *page;
};

# if defined(OF_HAVE_COMPILER_TLS)
static thread_local struct Page *firstPage = NULL;
static thread_local struct Page *lastPage = NULL;
static thread_local struct Page **preallocatedPages = NULL;
static thread_local size_t numPreallocatedPages = 0;
# elif defined(OF_HAVE_THREADS)
static OFTLSKey firstPageKey, lastPageKey;
static OFTLSKey preallocatedPagesKey, numPreallocatedPagesKey;
# else
static struct Page *firstPage = NULL;
static struct Page *lastPage = NULL;
static struct Page **preallocatedPages = NULL;
static size_t numPreallocatedPages = 0;
# endif

static void *
mapPages(size_t numPages)
{
	size_t pageSize = [OFSystemInfo pageSize];
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
	if (numPages > SIZE_MAX / pageSize)
		@throw [OFOutOfRangeException exception];

	munlock(pointer, numPages * pageSize);
	munmap(pointer, numPages * pageSize);
}

static struct page *
addPage(bool allowPreallocated)
{
	size_t pageSize = [OFSystemInfo pageSize];
	size_t mapSize = OFRoundUpToPowerOf2(CHAR_BIT, pageSize / chunkSize) /
	    CHAR_BIT;
	struct page *page;
# if !defined(OF_HAVE_COMPILER_TLS) && defined(OF_HAVE_THREADS)
	struct page *lastPage;
# endif

	if (allowPreallocated) {
# if !defined(OF_HAVE_COMPILER_TLS) && defined(OF_HAVE_THREADS)
		uintptr_t numPreallocatedPages =
		    (uintptr_t)OFTLSKeyGet(numPreallocatedPagesKey);
# endif

		if (numPreallocatedPages > 0) {
# if !defined(OF_HAVE_COMPILER_TLS) && defined(OF_HAVE_THREADS)
			struct page **preallocatedPages =
			    OFTLSKeyGet(preallocatedPagesKey);
# endif

			numPreallocatedPages--;
# if !defined(OF_HAVE_COMPILER_TLS) && defined(OF_HAVE_THREADS)
			OFEnsure(OFTLSKeySet(numPreallocatedPagesKey,
			    (void *)numPreallocatedPages) == 0);







|





|

|










|







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
	if (numPages > SIZE_MAX / pageSize)
		@throw [OFOutOfRangeException exception];

	munlock(pointer, numPages * pageSize);
	munmap(pointer, numPages * pageSize);
}

static struct Page *
addPage(bool allowPreallocated)
{
	size_t pageSize = [OFSystemInfo pageSize];
	size_t mapSize = OFRoundUpToPowerOf2(CHAR_BIT, pageSize / chunkSize) /
	    CHAR_BIT;
	struct Page *page;
# if !defined(OF_HAVE_COMPILER_TLS) && defined(OF_HAVE_THREADS)
	struct Page *lastPage;
# endif

	if (allowPreallocated) {
# if !defined(OF_HAVE_COMPILER_TLS) && defined(OF_HAVE_THREADS)
		uintptr_t numPreallocatedPages =
		    (uintptr_t)OFTLSKeyGet(numPreallocatedPagesKey);
# endif

		if (numPreallocatedPages > 0) {
# if !defined(OF_HAVE_COMPILER_TLS) && defined(OF_HAVE_THREADS)
			struct Page **preallocatedPages =
			    OFTLSKeyGet(preallocatedPagesKey);
# endif

			numPreallocatedPages--;
# if !defined(OF_HAVE_COMPILER_TLS) && defined(OF_HAVE_THREADS)
			OFEnsure(OFTLSKeySet(numPreallocatedPagesKey,
			    (void *)numPreallocatedPages) == 0);
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
		OFEnsure(OFTLSKeySet(firstPageKey, page) == 0);
# endif

	return page;
}

static void
removePageIfEmpty(struct page *page)
{
	unsigned char *map = page->map;
	size_t pageSize = [OFSystemInfo pageSize];
	size_t mapSize = OFRoundUpToPowerOf2(CHAR_BIT, pageSize / chunkSize) /
	    CHAR_BIT;

	for (size_t i = 0; i < mapSize; i++)







|







176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
		OFEnsure(OFTLSKeySet(firstPageKey, page) == 0);
# endif

	return page;
}

static void
removePageIfEmpty(struct Page *page)
{
	unsigned char *map = page->map;
	size_t pageSize = [OFSystemInfo pageSize];
	size_t mapSize = OFRoundUpToPowerOf2(CHAR_BIT, pageSize / chunkSize) /
	    CHAR_BIT;

	for (size_t i = 0; i < mapSize; i++)
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
		OFEnsure(OFTLSKeySet(lastPageKey, page->previous) == 0);
# endif

	OFFreeMemory(page);
}

static void *
allocateMemory(struct page *page, size_t bytes)
{
	size_t chunks, chunksLeft, pageSize, i, firstChunk;

	bytes = OFRoundUpToPowerOf2(chunkSize, bytes);
	chunks = chunksLeft = bytes / chunkSize;
	firstChunk = 0;
	pageSize = [OFSystemInfo pageSize];







|







211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
		OFEnsure(OFTLSKeySet(lastPageKey, page->previous) == 0);
# endif

	OFFreeMemory(page);
}

static void *
allocateMemory(struct Page *page, size_t bytes)
{
	size_t chunks, chunksLeft, pageSize, i, firstChunk;

	bytes = OFRoundUpToPowerOf2(chunkSize, bytes);
	chunks = chunksLeft = bytes / chunkSize;
	firstChunk = 0;
	pageSize = [OFSystemInfo pageSize];
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
		return page->page + (chunkSize * firstChunk);
	}

	return NULL;
}

static void
freeMemory(struct page *page, void *pointer, size_t bytes)
{
	size_t chunks, chunkIndex;

	bytes = OFRoundUpToPowerOf2(chunkSize, bytes);
	chunks = bytes / chunkSize;
	chunkIndex = ((uintptr_t)pointer - (uintptr_t)page->page) / chunkSize;








|







242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
		return page->page + (chunkSize * firstChunk);
	}

	return NULL;
}

static void
freeMemory(struct Page *page, void *pointer, size_t bytes)
{
	size_t chunks, chunkIndex;

	bytes = OFRoundUpToPowerOf2(chunkSize, bytes);
	chunks = bytes / chunkSize;
	chunkIndex = ((uintptr_t)pointer - (uintptr_t)page->page) / chunkSize;

281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303

+ (void)preallocateUnswappableMemoryWithSize: (size_t)size
{
#if defined(HAVE_MMAP) && defined(HAVE_MLOCK) && defined(MAP_ANON)
	size_t pageSize = [OFSystemInfo pageSize];
	size_t numPages = OFRoundUpToPowerOf2(pageSize, size) / pageSize;
# if !defined(OF_HAVE_COMPILER_TLS) && defined(OF_HAVE_THREADS)
	struct page **preallocatedPages = OFTLSKeyGet(preallocatedPagesKey);
	size_t numPreallocatedPages;
# endif
	size_t i;

	if (preallocatedPages != NULL)
		@throw [OFInvalidArgumentException exception];

	preallocatedPages = OFAllocZeroedMemory(numPages, sizeof(struct page));
# if !defined(OF_HAVE_COMPILER_TLS) && defined(OF_HAVE_THREADS)
	OFEnsure(OFTLSKeySet(preallocatedPagesKey, preallocatedPages) == 0);
# endif

	@try {
		for (i = 0; i < numPages; i++)
			preallocatedPages[i] = addPage(false);







|







|







281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303

+ (void)preallocateUnswappableMemoryWithSize: (size_t)size
{
#if defined(HAVE_MMAP) && defined(HAVE_MLOCK) && defined(MAP_ANON)
	size_t pageSize = [OFSystemInfo pageSize];
	size_t numPages = OFRoundUpToPowerOf2(pageSize, size) / pageSize;
# if !defined(OF_HAVE_COMPILER_TLS) && defined(OF_HAVE_THREADS)
	struct Page **preallocatedPages = OFTLSKeyGet(preallocatedPagesKey);
	size_t numPreallocatedPages;
# endif
	size_t i;

	if (preallocatedPages != NULL)
		@throw [OFInvalidArgumentException exception];

	preallocatedPages = OFAllocZeroedMemory(numPages, sizeof(struct Page));
# if !defined(OF_HAVE_COMPILER_TLS) && defined(OF_HAVE_THREADS)
	OFEnsure(OFTLSKeySet(preallocatedPagesKey, preallocatedPages) == 0);
# endif

	@try {
		for (i = 0; i < numPages; i++)
			preallocatedPages[i] = addPage(false);
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
			memset(_items, 0, count * itemSize);
#if defined(HAVE_MMAP) && defined(HAVE_MLOCK) && defined(MAP_ANON)
		} else if (count * itemSize >= pageSize)
			_items = mapPages(OFRoundUpToPowerOf2(pageSize,
			    count * itemSize) / pageSize);
		else {
# if !defined(OF_HAVE_COMPILER_TLS) && defined(OF_HAVE_THREADS)
			struct page *lastPage = OFTLSKeyGet(lastPageKey);
# endif

			for (struct page *page = lastPage; page != NULL;
			    page = page->previous) {
				_items = allocateMemory(page, count * itemSize);

				if (_items != NULL) {
					_page = page;
					break;
				}







|


|







419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
			memset(_items, 0, count * itemSize);
#if defined(HAVE_MMAP) && defined(HAVE_MLOCK) && defined(MAP_ANON)
		} else if (count * itemSize >= pageSize)
			_items = mapPages(OFRoundUpToPowerOf2(pageSize,
			    count * itemSize) / pageSize);
		else {
# if !defined(OF_HAVE_COMPILER_TLS) && defined(OF_HAVE_THREADS)
			struct Page *lastPage = OFTLSKeyGet(lastPageKey);
# endif

			for (struct Page *page = lastPage; page != NULL;
			    page = page->previous) {
				_items = allocateMemory(page, count * itemSize);

				if (_items != NULL) {
					_page = page;
					break;
				}

Modified src/OFSequencedPacketSocket.m from [7bcba89d06] to [d397c2379d].

131
132
133
134
135
136
137
138
139
140
141
142
143
144
145

	if (fcntl(_socket, F_SETFL, flags) == -1)
		@throw [OFSetOptionFailedException exceptionWithObject: self
								 errNo: errno];

	_canBlock = canBlock;
#elif defined(OF_WINDOWS)
	u_long v = canBlock;

	if (ioctlsocket(_socket, FIONBIO, &v) == SOCKET_ERROR)
		@throw [OFSetOptionFailedException
		    exceptionWithObject: self
				  errNo: OFSocketErrNo()];

	_canBlock = canBlock;







|







131
132
133
134
135
136
137
138
139
140
141
142
143
144
145

	if (fcntl(_socket, F_SETFL, flags) == -1)
		@throw [OFSetOptionFailedException exceptionWithObject: self
								 errNo: errno];

	_canBlock = canBlock;
#elif defined(OF_WINDOWS)
	u_long v = !canBlock;

	if (ioctlsocket(_socket, FIONBIO, &v) == SOCKET_ERROR)
		@throw [OFSetOptionFailedException
		    exceptionWithObject: self
				  errNo: OFSocketErrNo()];

	_canBlock = canBlock;

Modified src/OFSocket.h from [789ea6a8ed] to [b11ec9bdab].

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

/**
 * @struct OFSocketAddress OFSocket.h ObjFW/OFSocket.h
 *
 * @brief A struct which represents a host / port pair for a socket.
 */
struct OF_BOXABLE OFSocketAddress {
	/*
	 * Even though struct sockaddr contains the family, we need to use our
	 * own family, as we need to support storing an IPv6 address on systems
	 * that don't support IPv6. These may not have AF_INET6 defined and we
	 * can't just define it, as the value is system-dependent and might
	 * clash with an existing value.
	 */
	OFSocketAddressFamily family;
	union {
		struct sockaddr sockaddr;
		struct sockaddr_in in;
		struct sockaddr_in6 in6;
		struct sockaddr_ipx ipx;
		struct sockaddr_un un;
	} sockaddr;
	socklen_t length;
};
typedef struct OFSocketAddress OFSocketAddress;

#ifdef __cplusplus
extern "C" {
#endif
/**
 * @brief Parses the specified IP (either v4 or v6) and port into an
 *	  @ref OFSocketAddress.







|
















<
|







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

/**
 * @struct OFSocketAddress OFSocket.h ObjFW/OFSocket.h
 *
 * @brief A struct which represents a host / port pair for a socket.
 */
typedef struct OF_BOXABLE {
	/*
	 * Even though struct sockaddr contains the family, we need to use our
	 * own family, as we need to support storing an IPv6 address on systems
	 * that don't support IPv6. These may not have AF_INET6 defined and we
	 * can't just define it, as the value is system-dependent and might
	 * clash with an existing value.
	 */
	OFSocketAddressFamily family;
	union {
		struct sockaddr sockaddr;
		struct sockaddr_in in;
		struct sockaddr_in6 in6;
		struct sockaddr_ipx ipx;
		struct sockaddr_un un;
	} sockaddr;
	socklen_t length;

} OFSocketAddress;

#ifdef __cplusplus
extern "C" {
#endif
/**
 * @brief Parses the specified IP (either v4 or v6) and port into an
 *	  @ref OFSocketAddress.

Modified src/OFStdIOStream.h from [56543eac46] to [95e440fa88].

146
147
148
149
150
151
152
153
154
155

156
157
158










159
160
161
162
163

/**
 * @brief The standard error as an OFStream.
 */
extern OFStdIOStream *_Nullable OFStdErr;

/**
 * @brief Log the specified printf-style format to @ref OFStdErr.
 *
 * This prefixes the output with the date, timestamp, process name and PID and

 * allows `%@` as a printf-style formatted to print objects.
 */
extern void OFLog(OFConstantString *format, ...);










#ifdef __cplusplus
}
#endif

OF_ASSUME_NONNULL_END







|

|
>
|


>
>
>
>
>
>
>
>
>
>





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 The standard error as an OFStream.
 */
extern OFStdIOStream *_Nullable OFStdErr;

/**
 * @brief Logs the specified printf-style format to @ref OFStdErr.
 *
 * This prefixes the output with the date, timestamp, process name and PID.
 *
 * @param format The format for the line to log. See @ref OFStream#writeFormat:.
 */
extern void OFLog(OFConstantString *format, ...);

/**
 * @brief Logs the specified printf-style format to @ref OFStdErr.
 *
 * This prefixes the output with the date, timestamp, process name and PID.
 *
 * @param format The format for the line to log. See @ref OFStream#writeFormat:.
 * @param arguments The arguments for the format
 */
extern void OFLogV(OFConstantString *format, va_list arguments);
#ifdef __cplusplus
}
#endif

OF_ASSUME_NONNULL_END

Modified src/OFStdIOStream.m from [a9dd0b73a2] to [3842c52bb2].

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
	[OFStdErr dealloc];
}
#endif

void
OFLog(OFConstantString *format, ...)
{










	void *pool = objc_autoreleasePoolPush();
	OFDate *date;
	OFString *dateString, *me, *msg;
	va_list arguments;

	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

	va_start(arguments, format);
	msg = [[[OFString alloc] initWithFormat: format
				      arguments: arguments] autorelease];
	va_end(arguments);

	[OFStdErr writeFormat: @"[%@.%03d %@(%d)] %@\n", dateString,
			       date.microsecond / 1000, me, getpid(), msg];

	objc_autoreleasePoolPop(pool);
}








>
>
>
>
>
>
>
>
>
>



<









<


<







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
	[OFStdErr dealloc];
}
#endif

void
OFLog(OFConstantString *format, ...)
{
	va_list arguments;

	va_start(arguments, format);
	OFLogV(format, arguments);
	va_end(arguments);
}

void
OFLogV(OFConstantString *format, va_list arguments)
{
	void *pool = objc_autoreleasePoolPush();
	OFDate *date;
	OFString *dateString, *me, *msg;


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

	objc_autoreleasePoolPop(pool);
}

Modified src/OFStrPTime.h from [4d3408cfa3] to [cb6a50b81d].

25
26
27
28
29
30
31
32
33
34
35
36
37
38
#import "macros.h"

OF_ASSUME_NONNULL_BEGIN

#ifdef __cplusplus
extern "C" {
#endif
extern const char *OFStrPTime(const char *buf, const char *fmt, struct tm *tm,
    short *tz);
#ifdef __cplusplus
}
#endif

OF_ASSUME_NONNULL_END







|
|





25
26
27
28
29
30
31
32
33
34
35
36
37
38
#import "macros.h"

OF_ASSUME_NONNULL_BEGIN

#ifdef __cplusplus
extern "C" {
#endif
extern const char *_Nullable OFStrPTime(const char *buffer, const char *format,
    struct tm *tm, short *_Nullable tz);
#ifdef __cplusplus
}
#endif

OF_ASSUME_NONNULL_END

Modified src/OFStream.h from [b19f1dd539] to [90ab6262e8].

203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
 * @brief Whether the end of the stream has been reached.
 */
@property (readonly, nonatomic, getter=isAtEndOfStream) bool atEndOfStream;

/**
 * @brief Whether writes are buffered.
 */
@property (nonatomic, nonatomic) bool buffersWrites;

/**
 * @brief Whether data is present in the internal read buffer.
 */
@property (readonly, nonatomic) bool hasDataInReadBuffer;

/**







|







203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
 * @brief Whether the end of the stream has been reached.
 */
@property (readonly, nonatomic, getter=isAtEndOfStream) bool atEndOfStream;

/**
 * @brief Whether writes are buffered.
 */
@property (nonatomic) bool buffersWrites;

/**
 * @brief Whether data is present in the internal read buffer.
 */
@property (readonly, nonatomic) bool hasDataInReadBuffer;

/**

Modified src/OFStreamSocket.m from [a955b9500f] to [5b9cb9181f].

160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
	return (size_t)bytesWritten;
}

#if defined(OF_WINDOWS) || defined(OF_AMIGAOS)
- (void)setCanBlock: (bool)canBlock
{
# ifdef OF_WINDOWS
	u_long v = canBlock;
# else
	char v = canBlock;
# endif

	if (ioctlsocket(_socket, FIONBIO, &v) == SOCKET_ERROR)
		@throw [OFSetOptionFailedException
		    exceptionWithObject: self
				  errNo: OFSocketErrNo()];








|

|







160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
	return (size_t)bytesWritten;
}

#if defined(OF_WINDOWS) || defined(OF_AMIGAOS)
- (void)setCanBlock: (bool)canBlock
{
# ifdef OF_WINDOWS
	u_long v = !canBlock;
# else
	char v = !canBlock;
# endif

	if (ioctlsocket(_socket, FIONBIO, &v) == SOCKET_ERROR)
		@throw [OFSetOptionFailedException
		    exceptionWithObject: self
				  errNo: OFSocketErrNo()];

Modified src/OFString+PathAdditions.m from [ea7cb030e3] to [6ba7aac1d0].

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

#include "config.h"

#include "platform.h"

#if defined(OF_WINDOWS) || defined(OF_MSDOS)
# import "platform/windows/OFString+PathAdditions.m"
#elif defined(OF_AMIGAOS)
# import "platform/amiga/OFString+PathAdditions.m"
#elif defined(OF_NINTENDO_3DS) || defined(OF_WII)
# import "platform/libfat/OFString+PathAdditions.m"
#else
# import "platform/posix/OFString+PathAdditions.m"
#endif







|

|



|

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

#include "config.h"

#include "platform.h"

#if defined(OF_WINDOWS) || defined(OF_MSDOS)
# import "platform/Windows/OFString+PathAdditions.m"
#elif defined(OF_AMIGAOS)
# import "platform/AmigaOS/OFString+PathAdditions.m"
#elif defined(OF_NINTENDO_3DS) || defined(OF_WII)
# import "platform/libfat/OFString+PathAdditions.m"
#else
# import "platform/POSIX/OFString+PathAdditions.m"
#endif

Modified src/OFString+URLEncoding.m from [136d9c5f3e] to [a20a83c28d].

80
81
82
83
84
85
86

87
88
89
90
91
92
93
	void *pool = objc_autoreleasePoolPush();
	const char *string = self.UTF8String;
	size_t length = self.UTF8StringLength;
	char *retCString;
	char byte = 0;
	int state = 0;
	size_t i = 0;


	retCString = OFAllocMemory(length + 1, 1);

	while (length--) {
		char c = *string++;

		switch (state) {







>







80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
	void *pool = objc_autoreleasePoolPush();
	const char *string = self.UTF8String;
	size_t length = self.UTF8StringLength;
	char *retCString;
	char byte = 0;
	int state = 0;
	size_t i = 0;
	OFString *ret;

	retCString = OFAllocMemory(length + 1, 1);

	while (length--) {
		char c = *string++;

		switch (state) {
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147


148
	@try {
		retCString = OFResizeMemory(retCString, 1, i + 1);
	} @catch (OFOutOfMemoryException *e) {
		/* We don't care if it fails, as we only made it smaller. */
	}

	@try {
		return [OFString stringWithUTF8StringNoCopy: retCString
						     length: i
					       freeWhenDone: true];
	} @catch (id e) {
		OFFreeMemory(retCString);
		@throw e;
	}
}


@end







|
|
|




|
>
>

134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
	@try {
		retCString = OFResizeMemory(retCString, 1, i + 1);
	} @catch (OFOutOfMemoryException *e) {
		/* We don't care if it fails, as we only made it smaller. */
	}

	@try {
		ret = [OFString stringWithUTF8StringNoCopy: retCString
						    length: i
					      freeWhenDone: true];
	} @catch (id e) {
		OFFreeMemory(retCString);
		@throw e;
	}

	return ret;
}
@end

Modified src/OFString.h from [b4ac5f8ea5] to [43d2fc3670].

61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
typedef uint_least32_t OFChar32;
#endif
typedef OFChar32 OFUnichar;

/**
 * @brief The encoding of a string.
 */
typedef enum OFStringEncoding {
	/*
	 * UTF-8 *has* to be 0, so that if the current @ref OFLocale is
	 * `nil`, `[OFLocale encoding]` returns UTF-8.
	 */
	/** UTF-8 */
	OFStringEncodingUTF8,
	/** ASCII */







|







61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
typedef uint_least32_t OFChar32;
#endif
typedef OFChar32 OFUnichar;

/**
 * @brief The encoding of a string.
 */
typedef enum {
	/*
	 * UTF-8 *has* to be 0, so that if the current @ref OFLocale is
	 * `nil`, `[OFLocale encoding]` returns UTF-8.
	 */
	/** UTF-8 */
	OFStringEncodingUTF8,
	/** ASCII */
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
} OFStringEncoding;

/**
 * @brief Options for searching in strings.
 *
 * This is a bit mask.
 */
typedef enum OFStringSearchOptions {
	/** Search backwards in the string */
	OFStringSearchBackwards = 1
} OFStringSearchOptions;

/**
 * @brief Options for separating strings.
 *
 * This is a bit mask.
 */
typedef enum OFStringSeparationOptions {
	/** Skip empty components */
	OFStringSkipEmptyComponents = 1
} OFStringSeparationOptions;

#ifdef OF_HAVE_BLOCKS
/**
 * @brief A block for enumerating the lines of a string.







|









|







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
} OFStringEncoding;

/**
 * @brief Options for searching in strings.
 *
 * This is a bit mask.
 */
typedef enum {
	/** Search backwards in the string */
	OFStringSearchBackwards = 1
} OFStringSearchOptions;

/**
 * @brief Options for separating strings.
 *
 * This is a bit mask.
 */
typedef enum {
	/** Skip empty components */
	OFStringSkipEmptyComponents = 1
} OFStringSeparationOptions;

#ifdef OF_HAVE_BLOCKS
/**
 * @brief A block for enumerating the lines of a string.
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
+ (instancetype)stringWithUTF8String: (const char *)UTF8String
			      length: (size_t)UTF8StringLength;

/**
 * @brief Creates a new OFString from a UTF-8 encoded C string without copying
 *	  the string, if possible.
 *
 * If initialization fails for whatever reason, the passed C string is free'd
 * if `freeWhenDone` is true.
 *
 * @note OFMutableString always creates a copy!
 *
 * @param UTF8String A UTF-8 encoded C string to initialize the OFString with
 * @param freeWhenDone Whether to free the C string when the OFString gets
 *		       deallocated
 * @return A new autoreleased OFString
 */
+ (instancetype)stringWithUTF8StringNoCopy: (char *)UTF8String
			      freeWhenDone: (bool)freeWhenDone;

/**
 * @brief Creates a new OFString from a UTF-8 encoded C string with the
 *	  specified length without copying the string, if possible.
 *
 * If initialization fails for whatever reason, the passed C string is free'd
 * if `freeWhenDone` is true.
 *
 * @note OFMutableString always creates a copy!
 *
 * @param UTF8String A UTF-8 encoded C string to initialize the OFString with
 * @param UTF8StringLength The length of the UTF-8 encoded C string
 * @param freeWhenDone Whether to free the C string when the OFString gets
 *		       deallocated







|
|















|
|







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
+ (instancetype)stringWithUTF8String: (const char *)UTF8String
			      length: (size_t)UTF8StringLength;

/**
 * @brief Creates a new OFString from a UTF-8 encoded C string without copying
 *	  the string, if possible.
 *
 * If initialization fails for whatever reason, the passed C string is *not*
 * free'd if `freeWhenDone` is true.
 *
 * @note OFMutableString always creates a copy!
 *
 * @param UTF8String A UTF-8 encoded C string to initialize the OFString with
 * @param freeWhenDone Whether to free the C string when the OFString gets
 *		       deallocated
 * @return A new autoreleased OFString
 */
+ (instancetype)stringWithUTF8StringNoCopy: (char *)UTF8String
			      freeWhenDone: (bool)freeWhenDone;

/**
 * @brief Creates a new OFString from a UTF-8 encoded C string with the
 *	  specified length without copying the string, if possible.
 *
 * If initialization fails for whatever reason, the passed C string is *not*
 * free'd if `freeWhenDone` is true.
 *
 * @note OFMutableString always creates a copy!
 *
 * @param UTF8String A UTF-8 encoded C string to initialize the OFString with
 * @param UTF8StringLength The length of the UTF-8 encoded C string
 * @param freeWhenDone Whether to free the C string when the OFString gets
 *		       deallocated
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
- (instancetype)initWithUTF8String: (const char *)UTF8String
			    length: (size_t)UTF8StringLength;

/**
 * @brief Initializes an already allocated OFString from an UTF-8 encoded C
 *	  string without copying the string, if possible.
 *
 * If initialization fails for whatever reason, the passed C string is free'd
 * if `freeWhenDone` is true.
 *
 * @note OFMutableString always creates a copy!
 *
 * @param UTF8String A UTF-8 encoded C string to initialize the OFString with
 * @param freeWhenDone Whether to free the C string when it is not needed
 *		       anymore
 * @return An initialized OFString
 */
- (instancetype)initWithUTF8StringNoCopy: (char *)UTF8String
			    freeWhenDone: (bool)freeWhenDone;

/**
 * @brief Initializes an already allocated OFString from an UTF-8 encoded C
 *	  string with the specified length without copying the string, if
 *	  possible.
 *
 * If initialization fails for whatever reason, the passed C string is free'd
 * if `freeWhenDone` is true.
 *
 * @note OFMutableString always creates a copy!
 *
 * @param UTF8String A UTF-8 encoded C string to initialize the OFString with
 * @param UTF8StringLength The length of the UTF-8 encoded C string
 * @param freeWhenDone Whether to free the C string when it is not needed
 *		       anymore







|
|
















|
|







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
- (instancetype)initWithUTF8String: (const char *)UTF8String
			    length: (size_t)UTF8StringLength;

/**
 * @brief Initializes an already allocated OFString from an UTF-8 encoded C
 *	  string without copying the string, if possible.
 *
 * If initialization fails for whatever reason, the passed C string is *not*
 * free'd if `freeWhenDone` is true.
 *
 * @note OFMutableString always creates a copy!
 *
 * @param UTF8String A UTF-8 encoded C string to initialize the OFString with
 * @param freeWhenDone Whether to free the C string when it is not needed
 *		       anymore
 * @return An initialized OFString
 */
- (instancetype)initWithUTF8StringNoCopy: (char *)UTF8String
			    freeWhenDone: (bool)freeWhenDone;

/**
 * @brief Initializes an already allocated OFString from an UTF-8 encoded C
 *	  string with the specified length without copying the string, if
 *	  possible.
 *
 * If initialization fails for whatever reason, the passed C string is *not*
 * free'd if `freeWhenDone` is true.
 *
 * @note OFMutableString always creates a copy!
 *
 * @param UTF8String A UTF-8 encoded C string to initialize the OFString with
 * @param UTF8StringLength The length of the UTF-8 encoded C string
 * @param freeWhenDone Whether to free the C string when it is not needed
 *		       anymore

Modified src/OFString.m from [d4404e2d68] to [d3f94ba1f6].

1376
1377
1378
1379
1380
1381
1382

1383
1384
1385
1386
1387
1388
1389

- (const char *)of_cStringWithEncoding: (OFStringEncoding)encoding
				 lossy: (bool)lossy
{
	size_t length = self.length;
	char *cString;
	size_t cStringLength;


	switch (encoding) {
	case OFStringEncodingUTF8:
		cString = OFAllocMemory((length * 4) + 1, 1);

		@try {
			cStringLength = [self







>







1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390

- (const char *)of_cStringWithEncoding: (OFStringEncoding)encoding
				 lossy: (bool)lossy
{
	size_t length = self.length;
	char *cString;
	size_t cStringLength;
	const char *ret;

	switch (encoding) {
	case OFStringEncodingUTF8:
		cString = OFAllocMemory((length * 4) + 1, 1);

		@try {
			cStringLength = [self
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443


1444
1445
1446
1447
1448
1449
1450

		break;
	default:
		@throw [OFInvalidEncodingException exception];
	}

	@try {
		return [[OFData dataWithItemsNoCopy: cString
					      count: cStringLength + 1
				       freeWhenDone: true] items];
	} @catch (id e) {
		OFFreeMemory(cString);
		@throw e;
	}


}

- (const char *)cStringWithEncoding: (OFStringEncoding)encoding
{
	return [self of_cStringWithEncoding: encoding lossy: false];
}








|
|
|




>
>







1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453

		break;
	default:
		@throw [OFInvalidEncodingException exception];
	}

	@try {
		ret = [[OFData dataWithItemsNoCopy: cString
					     count: cStringLength + 1
				      freeWhenDone: true] items];
	} @catch (id e) {
		OFFreeMemory(cString);
		@throw e;
	}

	return ret;
}

- (const char *)cStringWithEncoding: (OFStringEncoding)encoding
{
	return [self of_cStringWithEncoding: encoding lossy: false];
}

2535
2536
2537
2538
2539
2540
2541

2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554


2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569

2570
2571
2572
2573
2574
2575
2576
	return value;
}

- (const OFUnichar *)characters
{
	size_t length = self.length;
	OFUnichar *buffer;


	buffer = OFAllocMemory(length, sizeof(OFUnichar));
	@try {
		[self getCharacters: buffer inRange: OFRangeMake(0, length)];

		return [[OFData dataWithItemsNoCopy: buffer
					      count: length
					   itemSize: sizeof(OFUnichar)
				       freeWhenDone: true] items];
	} @catch (id e) {
		OFFreeMemory(buffer);
		@throw e;
	}


}

- (const OFChar16 *)UTF16String
{
	return [self UTF16StringWithByteOrder: OFByteOrderNative];
}

- (const OFChar16 *)UTF16StringWithByteOrder: (OFByteOrder)byteOrder
{
	void *pool = objc_autoreleasePoolPush();
	const OFUnichar *characters = self.characters;
	size_t length = self.length;
	OFChar16 *buffer;
	size_t j;
	bool swap = (byteOrder != OFByteOrderNative);


	/* Allocate memory for the worst case */
	buffer = OFAllocMemory((length + 1) * 2, sizeof(OFChar16));

	j = 0;
	for (size_t i = 0; i < length; i++) {
		OFUnichar c = characters[i];







>





|
|
|
|




>
>















>







2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
	return value;
}

- (const OFUnichar *)characters
{
	size_t length = self.length;
	OFUnichar *buffer;
	const OFUnichar *ret;

	buffer = OFAllocMemory(length, sizeof(OFUnichar));
	@try {
		[self getCharacters: buffer inRange: OFRangeMake(0, length)];

		ret = [[OFData dataWithItemsNoCopy: buffer
					     count: length
					  itemSize: sizeof(OFUnichar)
				      freeWhenDone: true] items];
	} @catch (id e) {
		OFFreeMemory(buffer);
		@throw e;
	}

	return ret;
}

- (const OFChar16 *)UTF16String
{
	return [self UTF16StringWithByteOrder: OFByteOrderNative];
}

- (const OFChar16 *)UTF16StringWithByteOrder: (OFByteOrder)byteOrder
{
	void *pool = objc_autoreleasePoolPush();
	const OFUnichar *characters = self.characters;
	size_t length = self.length;
	OFChar16 *buffer;
	size_t j;
	bool swap = (byteOrder != OFByteOrderNative);
	const OFChar16 *ret;

	/* Allocate memory for the worst case */
	buffer = OFAllocMemory((length + 1) * 2, sizeof(OFChar16));

	j = 0;
	for (size_t i = 0; i < length; i++) {
		OFUnichar c = characters[i];
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618


2619
2620
2621
2622
2623
2624
2625
	} @catch (OFOutOfMemoryException *e) {
		/* We don't care, as we only tried to make it smaller */
	}

	objc_autoreleasePoolPop(pool);

	@try {
		return [[OFData dataWithItemsNoCopy: buffer
					      count: j + 1
					   itemSize: sizeof(OFChar16)
				       freeWhenDone: true] items];
	} @catch (id e) {
		OFFreeMemory(buffer);
		@throw e;
	}


}

- (size_t)UTF16StringLength
{
	const OFUnichar *characters = self.characters;
	size_t length, UTF16StringLength;








|
|
|
|




>
>







2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
	} @catch (OFOutOfMemoryException *e) {
		/* We don't care, as we only tried to make it smaller */
	}

	objc_autoreleasePoolPop(pool);

	@try {
		ret = [[OFData dataWithItemsNoCopy: buffer
					     count: j + 1
					  itemSize: sizeof(OFChar16)
				      freeWhenDone: true] items];
	} @catch (id e) {
		OFFreeMemory(buffer);
		@throw e;
	}

	return ret;
}

- (size_t)UTF16StringLength
{
	const OFUnichar *characters = self.characters;
	size_t length, UTF16StringLength;

2637
2638
2639
2640
2641
2642
2643

2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661


2662
2663
2664
2665
2666
2667
2668
	return [self UTF32StringWithByteOrder: OFByteOrderNative];
}

- (const OFChar32 *)UTF32StringWithByteOrder: (OFByteOrder)byteOrder
{
	size_t length = self.length;
	OFChar32 *buffer;


	buffer = OFAllocMemory(length + 1, sizeof(OFChar32));
	@try {
		[self getCharacters: buffer inRange: OFRangeMake(0, length)];
		buffer[length] = 0;

		if (byteOrder != OFByteOrderNative)
			for (size_t i = 0; i < length; i++)
				buffer[i] = OFByteSwap32(buffer[i]);

		return [[OFData dataWithItemsNoCopy: buffer
					      count: length + 1
					   itemSize: sizeof(OFChar32)
				       freeWhenDone: true] items];
	} @catch (id e) {
		OFFreeMemory(buffer);
		@throw e;
	}


}

- (OFData *)dataWithEncoding: (OFStringEncoding)encoding
{
	void *pool = objc_autoreleasePoolPush();
	OFData *data =
	    [OFData dataWithItems: [self cStringWithEncoding: encoding]







>










|
|
|
|




>
>







2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
	return [self UTF32StringWithByteOrder: OFByteOrderNative];
}

- (const OFChar32 *)UTF32StringWithByteOrder: (OFByteOrder)byteOrder
{
	size_t length = self.length;
	OFChar32 *buffer;
	const OFChar32 *ret;

	buffer = OFAllocMemory(length + 1, sizeof(OFChar32));
	@try {
		[self getCharacters: buffer inRange: OFRangeMake(0, length)];
		buffer[length] = 0;

		if (byteOrder != OFByteOrderNative)
			for (size_t i = 0; i < length; i++)
				buffer[i] = OFByteSwap32(buffer[i]);

		ret = [[OFData dataWithItemsNoCopy: buffer
					     count: length + 1
					  itemSize: sizeof(OFChar32)
				      freeWhenDone: true] items];
	} @catch (id e) {
		OFFreeMemory(buffer);
		@throw e;
	}

	return ret;
}

- (OFData *)dataWithEncoding: (OFStringEncoding)encoding
{
	void *pool = objc_autoreleasePoolPush();
	OFData *data =
	    [OFData dataWithItems: [self cStringWithEncoding: encoding]

Modified src/OFSubprocess.m from [6a65d9f1d2] to [f686b80ad6].

14
15
16
17
18
19
20
21
22
23
24
 */

#include "config.h"

#include "platform.h"

#ifdef OF_WINDOWS
# include "platform/windows/OFSubprocess.m"
#else
# include "platform/posix/OFSubprocess.m"
#endif







|

|

14
15
16
17
18
19
20
21
22
23
24
 */

#include "config.h"

#include "platform.h"

#ifdef OF_WINDOWS
# include "platform/Windows/OFSubprocess.m"
#else
# include "platform/POSIX/OFSubprocess.m"
#endif

Modified src/OFSystemInfo.h from [074e043b50] to [588a8a89cb].

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
 */
+ (nullable OFString *)operatingSystemVersion;

#ifdef OF_HAVE_FILES
/**
 * @brief Returns the path where user data for the application can be stored.
 *
 * On Unix systems, this adheres to the XDG Base Directory specification.@n
 * On Mac OS X and iOS, it uses the `NSApplicationSupportDirectory` directory.@n
 * On Windows, it uses the `APPDATA` environment variable.@n
 * On Haiku, it uses the `B_USER_SETTINGS_DIRECTORY` directory.

 *
 * @return The path where user data for the application can be stored
 */
+ (nullable OFString *)userDataPath;

/**
 * @brief Returns the path where user configuration for the application can be
 *	  stored.
 *
 * On Unix systems, this adheres to the XDG Base Directory specification.@n
 * On Mac OS X and iOS, it uses the `Preferences` directory inside of
 * `NSLibraryDirectory` directory.@n
 * On Windows, it uses the `APPDATA` environment variable.@n
 * On Haiku, it uses the `B_USER_SETTINGS_DIRECTORY` directory.

 *
 * @return The path where user configuration for the application can be stored
 */
+ (nullable OFString *)userConfigPath;


















#endif

/**
 * @brief Returns the vendor of the CPU.
 *
 * If the vendor could not be determined, `nil` is returned instead.
 *







|
|

|
>









|
|



>




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







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
 */
+ (nullable OFString *)operatingSystemVersion;

#ifdef OF_HAVE_FILES
/**
 * @brief Returns the path where user data 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 `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 OFString *)userDataPath;

/**
 * @brief Returns the path where user configuration for the application can be
 *	  stored.
 *
 * On UNIX systems, this adheres to the XDG Base Directory specification.@n
 * On 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 OFString *)userConfigPath;

/**
 * @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 OFString *)temporaryDirectoryPath;
#endif

/**
 * @brief Returns the vendor of the CPU.
 *
 * If the vendor could not be determined, `nil` is returned instead.
 *

Modified src/OFSystemInfo.m from [6fd50f8c07] to [ddb7f4310a].

25
26
27
28
29
30
31





32
33
34
35
36
37
38
39
40
41
42
43
44
45

#ifdef HAVE_SYS_UTSNAME_H
# include <sys/utsname.h>
#endif
#if defined(OF_MACOS) || defined(OF_NETBSD)
# include <sys/sysctl.h>
#endif






#if defined(OF_AMIGAOS4)
# include <exec/exectags.h>
# include <proto/exec.h>
#elif defined(OF_MORPHOS)
# include <exec/system.h>
# include <proto/exec.h>
#endif

#import "OFSystemInfo.h"
#import "OFApplication.h"
#import "OFArray.h"
#import "OFDictionary.h"
#import "OFLocale.h"







>
>
>
>
>



<


<







25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

40
41

42
43
44
45
46
47
48

#ifdef HAVE_SYS_UTSNAME_H
# include <sys/utsname.h>
#endif
#if defined(OF_MACOS) || 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

#import "OFSystemInfo.h"
#import "OFApplication.h"
#import "OFArray.h"
#import "OFDictionary.h"
#import "OFLocale.h"
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
		}
	} @finally {
		objc_autoreleasePoolPop(pool);
	}
# endif
#elif defined(OF_ANDROID)
	/* TODO */
#elif defined(OF_MORPHOS)
	/* TODO */
#elif defined(OF_AMIGAOS4)
	/* TODO */
#elif defined(OF_AMIGAOS_M68K)
	/* TODO */
#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)







|
|
|
|
<
<







213
214
215
216
217
218
219
220
221
222
223


224
225
226
227
228
229
230
		}
	} @finally {
		objc_autoreleasePoolPop(pool);
	}
# 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)
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
+ (OFString *)userDataPath
{
# if defined(OF_MACOS) || defined(OF_IOS)
	char pathC[PATH_MAX];
	OFMutableString *path;

#  ifdef HAVE_SYSDIR_START_SEARCH_PATH_ENUMERATION
	/* (1) to disable dead code warning when it is not a weak symbol */
	if ((1) && &sysdir_start_search_path_enumeration != NULL) {
		sysdir_search_path_enumeration_state state;

		state = sysdir_start_search_path_enumeration(
		    SYSDIR_DIRECTORY_APPLICATION_SUPPORT,
		    SYSDIR_DOMAIN_MASK_USER);
		if (sysdir_get_next_search_path_enumeration(state, pathC) == 0)
			@throw [OFNotImplementedException







|
<







351
352
353
354
355
356
357
358

359
360
361
362
363
364
365
+ (OFString *)userDataPath
{
# if defined(OF_MACOS) || defined(OF_IOS)
	char pathC[PATH_MAX];
	OFMutableString *path;

#  ifdef HAVE_SYSDIR_START_SEARCH_PATH_ENUMERATION
	if (@available(macOS 10.12, iOS 10, *)) {

		sysdir_search_path_enumeration_state state;

		state = sysdir_start_search_path_enumeration(
		    SYSDIR_DIRECTORY_APPLICATION_SUPPORT,
		    SYSDIR_DOMAIN_MASK_USER);
		if (sysdir_get_next_search_path_enumeration(state, pathC) == 0)
			@throw [OFNotImplementedException
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
+ (OFString *)userConfigPath
{
# if defined(OF_MACOS) || defined(OF_IOS)
	char pathC[PATH_MAX];
	OFMutableString *path;

#  ifdef HAVE_SYSDIR_START_SEARCH_PATH_ENUMERATION
	/* (1) to disable dead code warning when it is not a weak symbol */
	if ((1) && &sysdir_start_search_path_enumeration != NULL) {
		sysdir_search_path_enumeration_state state;

		state = sysdir_start_search_path_enumeration(
		    SYSDIR_DIRECTORY_LIBRARY, SYSDIR_DOMAIN_MASK_USER);
		if (sysdir_get_next_search_path_enumeration(state, pathC) == 0)
			@throw [OFNotImplementedException
			    exceptionWithSelector: _cmd







|
<







443
444
445
446
447
448
449
450

451
452
453
454
455
456
457
+ (OFString *)userConfigPath
{
# if defined(OF_MACOS) || defined(OF_IOS)
	char pathC[PATH_MAX];
	OFMutableString *path;

#  ifdef HAVE_SYSDIR_START_SEARCH_PATH_ENUMERATION
	if (@available(macOS 10.12, iOS 10, *)) {

		sysdir_search_path_enumeration_state state;

		state = sysdir_start_search_path_enumeration(
		    SYSDIR_DIRECTORY_LIBRARY, SYSDIR_DOMAIN_MASK_USER);
		if (sysdir_get_next_search_path_enumeration(state, pathC) == 0)
			@throw [OFNotImplementedException
			    exceptionWithSelector: _cmd
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
	if ((var = [env objectForKey: @"HOME"]) == nil)
		@throw [OFNotImplementedException exceptionWithSelector: _cmd
								 object: self];

	return [var stringByAppendingPathComponent: @".config"];
# endif
}



















































#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;
	buffer[1] = regs.edx;
	buffer[2] = regs.ecx;

	return [OFString stringWithCString: (char *)buffer
				  encoding: OFStringEncodingASCII
				    length: 12];


#else
	return nil;
#endif
}

+ (OFString *)CPUModel
{







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


















>
>







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
	if ((var = [env objectForKey: @"HOME"]) == nil)
		@throw [OFNotImplementedException exceptionWithSelector: _cmd
								 object: self];

	return [var stringByAppendingPathComponent: @".config"];
# endif
}

+ (OFString *)temporaryDirectoryPath
{
# if defined(OF_MACOS) || defined(OF_IOS)
	char buffer[PATH_MAX];
	size_t length;

	if ((length = confstr(_CS_DARWIN_USER_TEMP_DIR, buffer, PATH_MAX)) == 0)
		return @"/tmp";

	return [OFString stringWithCString: buffer
				  encoding: [OFLocale encoding]
				    length: length - 1];
# elif defined(OF_WINDOWS)
	if ([self isWindowsNT]) {
		wchar_t buffer[PATH_MAX];

		if (!GetTempPathW(PATH_MAX, buffer))
			return nil;

		return [OFString stringWithUTF16String: buffer];
	} else {
		char buffer[PATH_MAX];

		if (!GetTempPathA(PATH_MAX, buffer))
			return nil;

		return [OFString stringWithCString: buffer
					  encoding: [OFLocale encoding]];
	}
# elif defined(OF_HAIKU)
	char pathC[PATH_MAX];

	if (find_directory(B_SYSTEM_TEMP_DIRECTORY, 0, false,
	    pathC, PATH_MAX) != B_OK)
		@throw [OFNotImplementedException exceptionWithSelector: _cmd
								 object: self];

	return [OFString stringWithUTF8String: pathC];
# elif defined(OF_AMIGAOS)
	return @"T:";
# else
	OFString *path =
	    [[OFApplication environment] objectForKey: @"XDG_RUNTIME_DIR"];

	if (path != nil)
		return path;

	return @"/tmp";
# endif
}
#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;
	buffer[1] = regs.edx;
	buffer[2] = regs.ecx;

	return [OFString stringWithCString: (char *)buffer
				  encoding: OFStringEncodingASCII
				    length: 12];
#elif defined(OF_M68K)
	return @"Motorola";
#else
	return nil;
#endif
}

+ (OFString *)CPUModel
{
572
573
574
575
576
577
578













579
580
581
582
583
584
585
	    GCIT_VersionString, &version, TAG_END);

	if (version != NULL)
		return [OFString stringWithFormat: @"%s V%s", model, version];
	else
		return [OFString stringWithCString: model
					  encoding: OFStringEncodingASCII];













#else
	return nil;
#endif
}

#if defined(OF_X86_64) || defined(OF_X86)
+ (bool)supportsMMX







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







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
	    GCIT_VersionString, &version, TAG_END);

	if (version != NULL)
		return [OFString stringWithFormat: @"%s V%s", model, version];
	else
		return [OFString stringWithCString: model
					  encoding: OFStringEncodingASCII];
#elif defined(OF_AMIGAOS_M68K)
	if (SysBase->AttnFlags & AFF_68060)
		return @"68060";
	if (SysBase->AttnFlags & AFF_68040)
		return @"68040";
	if (SysBase->AttnFlags & AFF_68030)
		return @"68030";
	if (SysBase->AttnFlags & AFF_68020)
		return @"68020";
	if (SysBase->AttnFlags & AFF_68010)
		return @"68010";
	else
		return @"68000";
#else
	return nil;
#endif
}

#if defined(OF_X86_64) || defined(OF_X86)
+ (bool)supportsMMX

Modified src/OFTCPSocketSOCKS5Connector.h from [444395c847] to [a3decd0834].

25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
	OFString *_host;
	uint16_t _port;
	id <OFTCPSocketDelegate> _Nullable _delegate;
#ifdef OF_HAVE_BLOCKS
	OFTCPSocketAsyncConnectBlock _Nullable _block;
#endif
	id _Nullable _exception;
	enum {
		OFSOCKS5StateSendAuthentication = 1,
		OFSOCKS5StateReadVersion,
		OFSOCKS5StateSendRequest,
		OFSOCKS5StateReadResponse,
		OFSOCKS5StateReadAddress,
		OFSOCKS5StateReadAddressLength,
	} _SOCKS5State;
	/* Longest read is domain name (max 255 bytes) + port */
	unsigned char _buffer[257];
	OFMutableData *_Nullable _request;
}

- (instancetype)initWithSocket: (OFTCPSocket *)sock
			  host: (OFString *)host







<
<
<
<
<
<
<
|







25
26
27
28
29
30
31







32
33
34
35
36
37
38
39
	OFString *_host;
	uint16_t _port;
	id <OFTCPSocketDelegate> _Nullable _delegate;
#ifdef OF_HAVE_BLOCKS
	OFTCPSocketAsyncConnectBlock _Nullable _block;
#endif
	id _Nullable _exception;







	uint_least8_t _SOCKS5State;
	/* Longest read is domain name (max 255 bytes) + port */
	unsigned char _buffer[257];
	OFMutableData *_Nullable _request;
}

- (instancetype)initWithSocket: (OFTCPSocket *)sock
			  host: (OFString *)host

Modified src/OFTCPSocketSOCKS5Connector.m from [e52c5629f6] to [cef61681e6].

20
21
22
23
24
25
26









27
28
29
30
31
32
33

#import "OFTCPSocketSOCKS5Connector.h"
#import "OFData.h"
#import "OFRunLoop.h"
#import "OFString.h"

#import "OFConnectionFailedException.h"










@implementation OFTCPSocketSOCKS5Connector
- (instancetype)initWithSocket: (OFTCPSocket *)sock
			  host: (OFString *)host
			  port: (uint16_t)port
		      delegate: (id <OFTCPSocketDelegate>)delegate
#ifdef OF_HAVE_BLOCKS







>
>
>
>
>
>
>
>
>







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

#import "OFTCPSocketSOCKS5Connector.h"
#import "OFData.h"
#import "OFRunLoop.h"
#import "OFString.h"

#import "OFConnectionFailedException.h"

enum {
	stateSendAuthentication = 1,
	stateReadVersion,
	stateSendRequest,
	stateReadResponse,
	stateReadAddress,
	stateReadAddressLength,
};

@implementation OFTCPSocketSOCKS5Connector
- (instancetype)initWithSocket: (OFTCPSocket *)sock
			  host: (OFString *)host
			  port: (uint16_t)port
		      delegate: (id <OFTCPSocketDelegate>)delegate
#ifdef OF_HAVE_BLOCKS
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
		_exception = [exception retain];
		[self didConnect];
		return;
	}

	data = [OFData dataWithItems: "\x05\x01\x00" count: 3];

	_SOCKS5State = OFSOCKS5StateSendAuthentication;
	[_socket asyncWriteData: data
		    runLoopMode: [OFRunLoop currentRunLoop].currentMode];
}

-      (bool)stream: (OFStream *)sock
  didReadIntoBuffer: (void *)buffer
	     length: (size_t)length







|







111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
		_exception = [exception retain];
		[self didConnect];
		return;
	}

	data = [OFData dataWithItems: "\x05\x01\x00" count: 3];

	_SOCKS5State = stateSendAuthentication;
	[_socket asyncWriteData: data
		    runLoopMode: [OFRunLoop currentRunLoop].currentMode];
}

-      (bool)stream: (OFStream *)sock
  didReadIntoBuffer: (void *)buffer
	     length: (size_t)length
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
		[self didConnect];
		return false;
	}

	runLoopMode = [OFRunLoop currentRunLoop].currentMode;

	switch (_SOCKS5State) {
	case OFSOCKS5StateReadVersion:
		SOCKSVersion = buffer;

		if (SOCKSVersion[0] != 5 || SOCKSVersion[1] != 0) {
			_exception = [[OFConnectionFailedException alloc]
			    initWithHost: _host
				    port: _port
				  socket: self







|







136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
		[self didConnect];
		return false;
	}

	runLoopMode = [OFRunLoop currentRunLoop].currentMode;

	switch (_SOCKS5State) {
	case stateReadVersion:
		SOCKSVersion = buffer;

		if (SOCKSVersion[0] != 5 || SOCKSVersion[1] != 0) {
			_exception = [[OFConnectionFailedException alloc]
			    initWithHost: _host
				    port: _port
				  socket: self
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
		[_request addItem: &hostLength];
		[_request addItems: _host.UTF8String count: hostLength];

		port[0] = _port >> 8;
		port[1] = _port & 0xFF;
		[_request addItems: port count: 2];

		_SOCKS5State = OFSOCKS5StateSendRequest;
		[_socket asyncWriteData: _request runLoopMode: runLoopMode];
		return false;
	case OFSOCKS5StateReadResponse:
		response = buffer;

		if (response[0] != 5 || response[2] != 0) {
			_exception = [[OFConnectionFailedException alloc]
			    initWithHost: _host
				    port: _port
				  socket: self







|


|







162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
		[_request addItem: &hostLength];
		[_request addItems: _host.UTF8String count: hostLength];

		port[0] = _port >> 8;
		port[1] = _port & 0xFF;
		[_request addItems: port count: 2];

		_SOCKS5State = stateSendRequest;
		[_socket asyncWriteData: _request runLoopMode: runLoopMode];
		return false;
	case stateReadResponse:
		response = buffer;

		if (response[0] != 5 || response[2] != 0) {
			_exception = [[OFConnectionFailedException alloc]
			    initWithHost: _host
				    port: _port
				  socket: self
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
			[self didConnect];
			return false;
		}

		/* Skip the rest of the response */
		switch (response[3]) {
		case 1: /* IPv4 */
			_SOCKS5State = OFSOCKS5StateReadAddress;
			[_socket asyncReadIntoBuffer: _buffer
					 exactLength: 4 + 2
					 runLoopMode: runLoopMode];
			return false;
		case 3: /* Domain name */
			_SOCKS5State = OFSOCKS5StateReadAddressLength;
			[_socket asyncReadIntoBuffer: _buffer
					 exactLength: 1
					 runLoopMode: runLoopMode];
			return false;
		case 4: /* IPv6 */
			_SOCKS5State = OFSOCKS5StateReadAddress;
			[_socket asyncReadIntoBuffer: _buffer
					 exactLength: 16 + 2
					 runLoopMode: runLoopMode];
			return false;
		default:
			_exception = [[OFConnectionFailedException alloc]
			    initWithHost: _host
				    port: _port
				  socket: self
				   errNo: EPROTONOSUPPORT];
			[self didConnect];
			return false;
		}

		return false;
	case OFSOCKS5StateReadAddress:
		[self didConnect];
		return false;
	case OFSOCKS5StateReadAddressLength:
		addressLength = buffer;

		_SOCKS5State = OFSOCKS5StateReadAddress;
		[_socket asyncReadIntoBuffer: _buffer
				 exactLength: addressLength[0] + 2
				 runLoopMode: runLoopMode];
		return false;
	default:
		assert(0);
		return false;







|





|





|















|


|


|







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
			[self didConnect];
			return false;
		}

		/* Skip the rest of the response */
		switch (response[3]) {
		case 1: /* IPv4 */
			_SOCKS5State = stateReadAddress;
			[_socket asyncReadIntoBuffer: _buffer
					 exactLength: 4 + 2
					 runLoopMode: runLoopMode];
			return false;
		case 3: /* Domain name */
			_SOCKS5State = stateReadAddressLength;
			[_socket asyncReadIntoBuffer: _buffer
					 exactLength: 1
					 runLoopMode: runLoopMode];
			return false;
		case 4: /* IPv6 */
			_SOCKS5State = stateReadAddress;
			[_socket asyncReadIntoBuffer: _buffer
					 exactLength: 16 + 2
					 runLoopMode: runLoopMode];
			return false;
		default:
			_exception = [[OFConnectionFailedException alloc]
			    initWithHost: _host
				    port: _port
				  socket: self
				   errNo: EPROTONOSUPPORT];
			[self didConnect];
			return false;
		}

		return false;
	case stateReadAddress:
		[self didConnect];
		return false;
	case stateReadAddressLength:
		addressLength = buffer;

		_SOCKS5State = stateReadAddress;
		[_socket asyncReadIntoBuffer: _buffer
				 exactLength: addressLength[0] + 2
				 runLoopMode: runLoopMode];
		return false;
	default:
		assert(0);
		return false;
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
		[self didConnect];
		return nil;
	}

	runLoopMode = [OFRunLoop currentRunLoop].currentMode;

	switch (_SOCKS5State) {
	case OFSOCKS5StateSendAuthentication:
		_SOCKS5State = OFSOCKS5StateReadVersion;
		[_socket asyncReadIntoBuffer: _buffer
				 exactLength: 2
				 runLoopMode: runLoopMode];
		return nil;
	case OFSOCKS5StateSendRequest:
		[_request release];
		_request = nil;

		_SOCKS5State = OFSOCKS5StateReadResponse;
		[_socket asyncReadIntoBuffer: _buffer
				 exactLength: 4
				 runLoopMode: runLoopMode];
		return nil;
	default:
		assert(0);
		return nil;
	}
}
@end







|
|




|



|










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
		[self didConnect];
		return nil;
	}

	runLoopMode = [OFRunLoop currentRunLoop].currentMode;

	switch (_SOCKS5State) {
	case stateSendAuthentication:
		_SOCKS5State = stateReadVersion;
		[_socket asyncReadIntoBuffer: _buffer
				 exactLength: 2
				 runLoopMode: runLoopMode];
		return nil;
	case stateSendRequest:
		[_request release];
		_request = nil;

		_SOCKS5State = stateReadResponse;
		[_socket asyncReadIntoBuffer: _buffer
				 exactLength: 4
				 runLoopMode: runLoopMode];
		return nil;
	default:
		assert(0);
		return nil;
	}
}
@end

Modified src/OFTLSKey.h from [7ddd0f3e02] to [befb515045].

32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#elif defined(OF_WINDOWS)
# include <windows.h>
typedef DWORD OFTLSKey;
#elif defined(OF_MORPHOS)
# include <proto/exec.h>
typedef ULONG OFTLSKey;
#elif defined(OF_AMIGAOS)
typedef struct OFTLSKey {
	struct objc_hashtable *table;
	struct OFTLSKey *next, *previous;
} *OFTLSKey;
#endif

#ifdef __cplusplus
extern "C" {
#endif
extern int OFTLSKeyNew(OFTLSKey *key);







|

|







32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#elif defined(OF_WINDOWS)
# include <windows.h>
typedef DWORD OFTLSKey;
#elif defined(OF_MORPHOS)
# include <proto/exec.h>
typedef ULONG OFTLSKey;
#elif defined(OF_AMIGAOS)
typedef struct _OFTLSKey {
	struct objc_hashtable *table;
	struct _OFTLSKey *next, *previous;
} *OFTLSKey;
#endif

#ifdef __cplusplus
extern "C" {
#endif
extern int OFTLSKeyNew(OFTLSKey *key);

Modified src/OFTLSKey.m from [c046d81c67] to [15b8d20ff8].

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

#include "config.h"

#include "platform.h"

#if defined(OF_HAVE_PTHREADS)
# include "platform/posix/OFTLSKey.m"
#elif defined(OF_WINDOWS)
# include "platform/windows/OFTLSKey.m"
#elif defined(OF_MORPHOS)
# include "platform/morphos/OFTLSKey.m"
#elif defined(OF_AMIGAOS)
# include "platform/amiga/OFTLSKey.m"
#endif







|

|

|

|

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

#include "config.h"

#include "platform.h"

#if defined(OF_HAVE_PTHREADS)
# include "platform/POSIX/OFTLSKey.m"
#elif defined(OF_WINDOWS)
# include "platform/Windows/OFTLSKey.m"
#elif defined(OF_MORPHOS)
# include "platform/MorphOS/OFTLSKey.m"
#elif defined(OF_AMIGAOS)
# include "platform/AmigaOS/OFTLSKey.m"
#endif

Modified src/OFTarArchiveEntry.h from [5715325220] to [933ac56d6f].

20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
/** @file */

@class OFDate;

/**
 * @brief The type of the archive entry.
 */
typedef enum OFTarArchiveEntryType {
	/** Normal file */
	OFTarArchiveEntryTypeFile	     = '0',
	/** Hard link */
	OFTarArchiveEntryTypeLink	     = '1',
	/** Symbolic link */
	OFTarArchiveEntryTypeSymlink	     = '2',
	/** Character device */







|







20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
/** @file */

@class OFDate;

/**
 * @brief The type of the archive entry.
 */
typedef enum {
	/** Normal file */
	OFTarArchiveEntryTypeFile	     = '0',
	/** Hard link */
	OFTarArchiveEntryTypeLink	     = '1',
	/** Symbolic link */
	OFTarArchiveEntryTypeSymlink	     = '2',
	/** Character device */

Modified src/OFTimer.h from [2337ad9abd] to [7b53dae76c].

65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
/**
 * @brief The time interval in which the timer will repeat, if it is a
 *	  repeating timer.
 */
@property (readonly, nonatomic) OFTimeInterval timeInterval;

/**
 * @brief Whether the timer is repeating.
 */
@property (readonly, nonatomic, getter=isRepeating) bool repeating;

/**
 * @brief Whether the timer is valid.
 */
@property (readonly, nonatomic, getter=isValid) bool valid;

/**







|

|







65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
/**
 * @brief The time interval in which the timer will repeat, if it is a
 *	  repeating timer.
 */
@property (readonly, nonatomic) OFTimeInterval timeInterval;

/**
 * @brief Whether the timer repeats.
 */
@property (readonly, nonatomic) bool repeats;

/**
 * @brief Whether the timer is valid.
 */
@property (readonly, nonatomic, getter=isValid) bool valid;

/**

Modified src/OFTimer.m from [f881c0a34b] to [4643374dad].

27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#ifdef OF_HAVE_THREADS
# import "OFCondition.h"
#endif

#import "OFInvalidArgumentException.h"

@implementation OFTimer
@synthesize timeInterval = _interval, repeating = _repeats, valid = _valid;

+ (instancetype)scheduledTimerWithTimeInterval: (OFTimeInterval)timeInterval
					target: (id)target
				      selector: (SEL)selector
				       repeats: (bool)repeats
{
	void *pool = objc_autoreleasePoolPush();







|







27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#ifdef OF_HAVE_THREADS
# import "OFCondition.h"
#endif

#import "OFInvalidArgumentException.h"

@implementation OFTimer
@synthesize timeInterval = _interval, repeats = _repeats, valid = _valid;

+ (instancetype)scheduledTimerWithTimeInterval: (OFTimeInterval)timeInterval
					target: (id)target
				      selector: (SEL)selector
				       repeats: (bool)repeats
{
	void *pool = objc_autoreleasePoolPush();
662
663
664
665
666
667
668





























669

		[_condition wait];
	} @finally {
		[_condition unlock];
	}
}
#endif





























@end







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

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

		[_condition wait];
	} @finally {
		[_condition unlock];
	}
}
#endif

- (OFString *)description
{
#ifdef OF_HAVE_BLOCKS
	if (_block != NULL)
		return [OFString stringWithFormat:
		    @"<%@:\n"
		    @"\tFire date: %@\n"
		    @"\tInterval: %lf\n"
		    @"\tRepeats: %s\n"
		    @"\tBlock: %@\n"
		    @"\tValid: %s\n"
		    @">",
		    self.class, _fireDate, _interval, (_repeats ? "yes" : "no"),
		    _block, (_valid ? "yes" : "no")];
	else
#endif
		return [OFString stringWithFormat:
		    @"<%@:\n"
		    @"\tFire date: %@\n"
		    @"\tInterval: %lf\n"
		    @"\tRepeats: %s\n"
		    @"\tTarget: %@\n"
		    @"\tSelector: %s\n"
		    @"\tValid: %s\n"
		    @">",
		    self.class, _fireDate, _interval, (_repeats ? "yes" : "no"),
		    _target, sel_getName(_selector), (_valid ? "yes" : "no")];
}
@end

Modified src/OFUDPSocket.m from [5d65cff83a] to [bb035d1ec6].

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

			while (rnd < 1024)
				rnd = (uint16_t)rand();

			OFSocketAddressSetPort(address, rnd);

			if ((ret = bind(_socket, &address->sockaddr.sockaddr,
			    address->length)) == 0) {
				port = rnd;
				break;
			}

			if (OFSocketErrNo() != EADDRINUSE) {
				int errNo = OFSocketErrNo();
				OFString *host = OFSocketAddressString(address);
				uint16_t port = OFSocketAddressPort(port);

				closesocket(_socket);
				_socket = OFInvalidSocketHandle;

				@throw [OFBindFailedException
				    exceptionWithHost: host
						 port: port







|
<

<




|







90
91
92
93
94
95
96
97

98

99
100
101
102
103
104
105
106
107
108
109
110

			while (rnd < 1024)
				rnd = (uint16_t)rand();

			OFSocketAddressSetPort(address, rnd);

			if ((ret = bind(_socket, &address->sockaddr.sockaddr,
			    address->length)) == 0)

				break;


			if (OFSocketErrNo() != EADDRINUSE) {
				int errNo = OFSocketErrNo();
				OFString *host = OFSocketAddressString(address);
				port = OFSocketAddressPort(address);

				closesocket(_socket);
				_socket = OFInvalidSocketHandle;

				@throw [OFBindFailedException
				    exceptionWithHost: host
						 port: port

Modified src/OFURL.m from [110acb1505] to [73419ef6a6].

584
585
586
587
588
589
590












591
592

593
594
595
596
597
598
599
				    initWithUTF8String: tmp + 1];

				OFURLVerifyIsEscaped(_URLEncodedQuery,
				    [OFCharacterSet
				    URLQueryAllowedCharacterSet]);
			}













			UTF8String--;
			*UTF8String = '/';


			_URLEncodedPath = [[OFString alloc]
			    initWithUTF8String: UTF8String];

			OFURLVerifyIsEscaped(_URLEncodedPath,
			    [OFCharacterSet URLPathAllowedCharacterSet]);
		}







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


>







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
				    initWithUTF8String: tmp + 1];

				OFURLVerifyIsEscaped(_URLEncodedQuery,
				    [OFCharacterSet
				    URLQueryAllowedCharacterSet]);
			}

			/*
			 * Some versions of GCC issue a false-positive warning
			 * (turned error) about a string overflow. This is a
			 * false positive because UTF8String is set to tmp
			 * above and tmp is either NULL or points *after* the
			 * slash for the path. So all we do here is go back to
			 * that slash and restore it.
			 */
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpragmas"
#pragma GCC diagnostic ignored "-Wunknown-warning-option"
#pragma GCC diagnostic ignored "-Wstringop-overflow"
			UTF8String--;
			*UTF8String = '/';
#pragma GCC diagnostic pop

			_URLEncodedPath = [[OFString alloc]
			    initWithUTF8String: UTF8String];

			OFURLVerifyIsEscaped(_URLEncodedPath,
			    [OFCharacterSet URLPathAllowedCharacterSet]);
		}

Modified src/OFUTF8String.m from [18e27cfd00] to [48ac930e37].

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
	return array;
}

- (const OFUnichar *)characters
{
	OFUnichar *buffer = OFAllocMemory(_s->length, sizeof(OFUnichar));
	size_t i = 0, j = 0;


	while (i < _s->cStringLength) {
		OFUnichar c;
		ssize_t cLen;

		cLen = OFUTF8StringDecode(_s->cString + i,
		    _s->cStringLength - i, &c);

		if (cLen <= 0 || c > 0x10FFFF) {
			OFFreeMemory(buffer);
			@throw [OFInvalidEncodingException exception];
		}

		buffer[j++] = c;
		i += cLen;
	}


	return [[OFData dataWithItemsNoCopy: buffer
				      count: _s->length
				   itemSize: sizeof(OFUnichar)
			       freeWhenDone: true] items];






}

- (const OFChar32 *)UTF32StringWithByteOrder: (OFByteOrder)byteOrder
{
	OFChar32 *buffer = OFAllocMemory(_s->length + 1, sizeof(OFChar32));
	size_t i = 0, j = 0;


	while (i < _s->cStringLength) {
		OFChar32 c;
		ssize_t cLen;

		cLen = OFUTF8StringDecode(_s->cString + i,
		    _s->cStringLength - i, &c);







>

















>
|
|
|
|
>
>
>
>
>
>






>







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
	return array;
}

- (const OFUnichar *)characters
{
	OFUnichar *buffer = OFAllocMemory(_s->length, sizeof(OFUnichar));
	size_t i = 0, j = 0;
	const OFUnichar *ret;

	while (i < _s->cStringLength) {
		OFUnichar c;
		ssize_t cLen;

		cLen = OFUTF8StringDecode(_s->cString + i,
		    _s->cStringLength - i, &c);

		if (cLen <= 0 || c > 0x10FFFF) {
			OFFreeMemory(buffer);
			@throw [OFInvalidEncodingException exception];
		}

		buffer[j++] = c;
		i += cLen;
	}

	@try {
		ret = [[OFData dataWithItemsNoCopy: buffer
					     count: _s->length
					  itemSize: sizeof(OFUnichar)
				      freeWhenDone: true] items];
	} @catch (id e) {
		OFFreeMemory(buffer);
		@throw e;
	}

	return ret;
}

- (const OFChar32 *)UTF32StringWithByteOrder: (OFByteOrder)byteOrder
{
	OFChar32 *buffer = OFAllocMemory(_s->length + 1, sizeof(OFChar32));
	size_t i = 0, j = 0;
	const OFChar32 *ret;

	while (i < _s->cStringLength) {
		OFChar32 c;
		ssize_t cLen;

		cLen = OFUTF8StringDecode(_s->cString + i,
		    _s->cStringLength - i, &c);
1202
1203
1204
1205
1206
1207
1208

1209
1210
1211
1212






1213
1214
1215
1216
1217
1218
1219
		else
			buffer[j++] = c;

		i += cLen;
	}
	buffer[j] = 0;


	return [[OFData dataWithItemsNoCopy: buffer
				      count: _s->length + 1
				   itemSize: sizeof(OFChar32)
			       freeWhenDone: true] items];






}

#ifdef OF_HAVE_BLOCKS
- (void)enumerateLinesUsingBlock: (OFStringLineEnumerationBlock)block
{
	void *pool;
	const char *cString = _s->cString;







>
|
|
|
|
>
>
>
>
>
>







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
		else
			buffer[j++] = c;

		i += cLen;
	}
	buffer[j] = 0;

	@try {
		ret = [[OFData dataWithItemsNoCopy: buffer
					     count: _s->length + 1
					  itemSize: sizeof(OFChar32)
				      freeWhenDone: true] items];
	} @catch (id e) {
		OFFreeMemory(buffer);
		@throw e;
	}

	return ret;
}

#ifdef OF_HAVE_BLOCKS
- (void)enumerateLinesUsingBlock: (OFStringLineEnumerationBlock)block
{
	void *pool;
	const char *cString = _s->cString;

Added src/OFUUID.h version [71a4287501].















































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
/*
 * Copyright (c) 2008-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.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either 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.
 */
@property (readonly, nonatomic) OFString *UUIDString;

/**
 * @brief Creates a new random UUID as per RFC 4122 version 4.
 *
 * @return A new, autoreleased OFUUID
 */
+ (instancetype)UUID;

/**
 * @brief Creates a new UUID with the specified bytes.
 *
 * @param bytes The bytes for the UUID
 * @return A new, autoreleased OFUUID
 */
+ (instancetype)UUIDWithUUIDBytes: (const unsigned char [_Nonnull 16])bytes;

/**
 * @brief Creates a new UUID with the specified UUID string.
 *
 * @param string The UUID string for the UUID
 * @return A new, autoreleased OFUUID
 */
+ (instancetype)UUIDWithUUIDString: (OFString *)string;

/**
 * @brief Initializes an already allocated OFUUID as a new random UUID as per
 *	  RFC 4122 version 4.
 *
 * @return An initialized OFUUID
 */
- (instancetype)init;

/**
 * @brief Initializes an already allocated OFUUID with the specified bytes.
 *
 * @param bytes The bytes to initialize the OFUUID with
 * @return An initialized OFUUID
 */
- (instancetype)initWithUUIDBytes: (const unsigned char [_Nonnull 16])bytes;

/**
 * @brief Initializes an already allocated OFUUID with the specified UUID
 *	  string.
 *
 * @param string The UUID string to initialize the OFUUID with
 * @return An initialized OFUUID
 */
- (instancetype)initWithUUIDString: (OFString *)string;

/**
 * @brief Compares the UUID to another UUID.
 *
 * @param UUID The UUID to compare to
 * @return The result of the comparison
 */
- (OFComparisonResult)compare: (OFUUID *)UUID;

/**
 * @brief Gets the bytes of the UUID.
 *
 * @param bytes An array of 16 bytes into which to write the UUID
 */
- (void)getUUIDBytes: (unsigned char [_Nonnull 16])bytes;
@end

OF_ASSUME_NONNULL_END

Added src/OFUUID.m version [2d4d775406].

























































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
/*
 * Copyright (c) 2008-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.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 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

@implementation OFUUID
+ (instancetype)UUID
{
	return [[[self alloc] init] autorelease];
}

+ (instancetype)UUIDWithUUIDBytes: (const unsigned char [16])bytes
{
	return [[[self alloc] initWithUUIDBytes: bytes] autorelease];
}

+ (instancetype)UUIDWithUUIDString: (OFString *)string
{
	return [[[self alloc] initWithUUIDString: string] autorelease];
}

- (instancetype)init
{
	uint64_t r;

	self = [super init];

	r = OFRandom64();
	memcpy(_bytes, &r, 8);
	r = OFRandom64();
	memcpy(_bytes + 8, &r, 8);

	_bytes[6] &= ~((1 << 7) | (1 << 5) | (1 << 4));
	_bytes[6] |= (1 << 6);
	_bytes[8] &= ~(1 << 6);
	_bytes[8] |= (1 << 7);

	return self;
}

- (instancetype)initWithUUIDBytes: (const unsigned char [16])bytes
{
	self = [super init];

	memcpy(_bytes, bytes, sizeof(_bytes));

	return self;
}

static void
decode(OFArray OF_GENERIC(OFString *) *components, size_t componentIndex,
    size_t componentLength, unsigned char *bytes, size_t *i)
{
	void *pool = objc_autoreleasePoolPush();
	OFString *component = [components objectAtIndex: componentIndex];
	const char *cString;

	if (component.UTF8StringLength != componentLength)
		@throw [OFInvalidFormatException exception];

	if (*i + componentLength / 2 > bytesSize)
		@throw [OFOutOfRangeException exception];

	cString = component.UTF8String;

	for (size_t j = 0; j < componentLength; j += 2) {
		uint8_t value;

		if (cString[j] >= '0' && cString[j] <= '9')
			value = cString[j] - '0';
		else if (cString[j] >= 'a' && cString[j] <= 'f')
			value = cString[j] - 'a' + 10;
		else if (cString[j] >= 'A' && cString[j] <= 'F')
			value = cString[j] - 'A' + 10;
		else
			@throw [OFInvalidFormatException exception];

		value <<= 4;

		if (cString[j + 1] >= '0' && cString[j + 1] <= '9')
			value |= cString[j + 1] - '0';
		else if (cString[j + 1] >= 'a' && cString[j + 1] <= 'f')
			value |= cString[j + 1] - 'a' + 10;
		else if (cString[j + 1] >= 'A' && cString[j + 1] <= 'F')
			value |= cString[j + 1] - 'A' + 10;
		else
			@throw [OFInvalidFormatException exception];

		bytes[(*i)++] = value;
	}

	objc_autoreleasePoolPop(pool);
}

- (instancetype)initWithUUIDString: (OFString *)string
{
	self = [super init];

	@try {
		void *pool = objc_autoreleasePoolPush();
		size_t i = 0;
		OFArray OF_GENERIC(OFString *) *components =
		    [string componentsSeparatedByString: @"-"];

		if (components.count != 5)
			@throw [OFInvalidFormatException exception];

		decode(components, 0, 8, _bytes, &i);
		decode(components, 1, 4, _bytes, &i);
		decode(components, 2, 4, _bytes, &i);
		decode(components, 3, 4, _bytes, &i);
		decode(components, 4, 12, _bytes, &i);

		OFEnsure(i == 16);

		objc_autoreleasePoolPop(pool);
	} @catch (id e) {
		[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;

	UUID = object;

	return (memcmp(_bytes, UUID->_bytes, sizeof(_bytes)) == 0);
}

- (unsigned long)hash
{
	unsigned long hash;

	OFHashInit(&hash);

	for (size_t i = 0; i < sizeof(_bytes); i++)
		OFHashAdd(&hash, _bytes[i]);

	OFHashFinalize(&hash);

	return hash;
}

- (id)copy
{
	return [self retain];
}

- (OFComparisonResult)compare: (OFUUID *)UUID
{
	int comparison;

	if (![UUID isKindOfClass: [OFUUID class]])
		@throw [OFInvalidArgumentException exception];

	if ((comparison = memcmp(_bytes, UUID->_bytes, sizeof(_bytes))) == 0)
		return OFOrderedSame;

	if (comparison > 0)
		return OFOrderedDescending;
	else
		return OFOrderedAscending;
}

- (void)getUUIDBytes: (unsigned char [16])bytes
{
	memcpy(bytes, _bytes, sizeof(_bytes));
}

- (OFString *)UUIDString
{
	return [OFString stringWithFormat:
	    @"%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-"
	    @"%02X%02X%02X%02X%02X%02X",
	    _bytes[0], _bytes[1], _bytes[2], _bytes[3],
	    _bytes[4], _bytes[5], _bytes[6], _bytes[7],
	    _bytes[8], _bytes[9], _bytes[10], _bytes[11],
	    _bytes[12], _bytes[13], _bytes[14], _bytes[15]];
}

- (OFString *)description
{
	return self.UUIDString;
}

- (OFXMLElement *)XMLElementBySerializing
{
	void *pool = objc_autoreleasePoolPush();
	OFXMLElement *element = [OFXMLElement elementWithName: self.className
						    namespace: OFSerializationNS
						  stringValue: self.UUIDString];

	[element retain];

	objc_autoreleasePoolPop(pool);

	return [element autorelease];
}
@end

Modified src/OFXMLParser.h from [1fb96ae9fc] to [fd86d1b01d].

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
 * OFXMLParser is an event-based XML parser which calls the delegate's callbacks
 * as soon as it finds something, thus suitable for streams as well.
 */
OF_SUBCLASSING_RESTRICTED
@interface OFXMLParser: OFObject
{
	id <OFXMLParserDelegate> _Nullable _delegate;
	enum {
		OFXMLParserStateInByteOrderMark,
		OFXMLParserStateOutsideTag,
		OFXMLParserStateTagOpened,
		OFXMLParserStateInProcessingInstruction,
		OFXMLParserStateInTagName,
		OFXMLParserStateInCloseTagName,
		OFXMLParserStateInTag,
		OFXMLParserStateInAttributeName,
		OFXMLParserStateExpectAttributeEqualSign,
		OFXMLParserStateExpectAttributeDelimiter,
		OFXMLParserStateInAttributeValue,
		OFXMLParserStateExpectTagClose,
		OFXMLParserStateExpectSpaceOrTagClose,
		OFXMLParserStateInExclamationMark,
		OFXMLParserStateInCDATAOpening,
		OFXMLParserStateInCDATA,
		OFXMLParserStateInCommentOpening,
		OFXMLParserStateInComment1,
		OFXMLParserStateInComment2,
		OFXMLParserStateInDOCTYPE
	} _state;
	size_t _i, _last;
	const char *_Nullable _data;
	OFMutableData *_buffer;
	OFString *_Nullable _name, *_Nullable _prefix;
	OFMutableArray
	    OF_GENERIC(OFMutableDictionary OF_GENERIC(OFString *, OFString *) *)
	    *_namespaces;







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







126
127
128
129
130
131
132





















133
134
135
136
137
138
139
140
 * OFXMLParser is an event-based XML parser which calls the delegate's callbacks
 * as soon as it finds something, thus suitable for streams as well.
 */
OF_SUBCLASSING_RESTRICTED
@interface OFXMLParser: OFObject
{
	id <OFXMLParserDelegate> _Nullable _delegate;





















	uint_least8_t _state;
	size_t _i, _last;
	const char *_Nullable _data;
	OFMutableData *_buffer;
	OFString *_Nullable _name, *_Nullable _prefix;
	OFMutableArray
	    OF_GENERIC(OFMutableDictionary OF_GENERIC(OFString *, OFString *) *)
	    *_namespaces;

Modified src/OFXMLParser.m from [a4ea06f928] to [885a5c6d01].

35
36
37
38
39
40
41























42
43
44
45
46
47
48
#import "OFInitializationFailedException.h"
#import "OFInvalidArgumentException.h"
#import "OFInvalidEncodingException.h"
#import "OFInvalidFormatException.h"
#import "OFMalformedXMLException.h"
#import "OFOutOfRangeException.h"
#import "OFUnboundPrefixException.h"
























@interface OFXMLParser () <OFStringXMLUnescapingDelegate>
@end

static void inByteOrderMarkState(OFXMLParser *);
static void outsideTagState(OFXMLParser *);
static void tagOpenedState(OFXMLParser *);







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







35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
#import "OFInitializationFailedException.h"
#import "OFInvalidArgumentException.h"
#import "OFInvalidEncodingException.h"
#import "OFInvalidFormatException.h"
#import "OFMalformedXMLException.h"
#import "OFOutOfRangeException.h"
#import "OFUnboundPrefixException.h"

enum {
	stateInByteOrderMark,
	stateOutsideTag,
	stateTagOpened,
	stateInProcessingInstruction,
	stateInTagName,
	stateInCloseTagName,
	stateInTag,
	stateInAttributeName,
	stateExpectAttributeEqualSign,
	stateExpectAttributeDelimiter,
	stateInAttributeValue,
	stateExpectTagClose,
	stateExpectSpaceOrTagClose,
	stateInExclamationMark,
	stateInCDATAOpening,
	stateInCDATA,
	stateInCommentOpening,
	stateInComment1,
	stateInComment2,
	stateInDOCTYPE
};

@interface OFXMLParser () <OFStringXMLUnescapingDelegate>
@end

static void inByteOrderMarkState(OFXMLParser *);
static void outsideTagState(OFXMLParser *);
static void tagOpenedState(OFXMLParser *);
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
static void inCDATAState(OFXMLParser *);
static void inCommentOpeningState(OFXMLParser *);
static void inCommentState1(OFXMLParser *);
static void inCommentState2(OFXMLParser *);
static void inDOCTYPEState(OFXMLParser *);
typedef void (*StateFunction)(OFXMLParser *);
static StateFunction lookupTable[] = {
	[OFXMLParserStateInByteOrderMark] = inByteOrderMarkState,
	[OFXMLParserStateOutsideTag] = outsideTagState,
	[OFXMLParserStateTagOpened] = tagOpenedState,
	[OFXMLParserStateInProcessingInstruction] =
	    inProcessingInstructionState,
	[OFXMLParserStateInTagName] = inTagNameState,
	[OFXMLParserStateInCloseTagName] = inCloseTagNameState,
	[OFXMLParserStateInTag] = inTagState,
	[OFXMLParserStateInAttributeName] = inAttributeNameState,
	[OFXMLParserStateExpectAttributeEqualSign] =
	    expectAttributeEqualSignState,
	[OFXMLParserStateExpectAttributeDelimiter] =
	    expectAttributeDelimiterState,
	[OFXMLParserStateInAttributeValue] = inAttributeValueState,
	[OFXMLParserStateExpectTagClose] = expectTagCloseState,
	[OFXMLParserStateExpectSpaceOrTagClose] = expectSpaceOrTagCloseState,
	[OFXMLParserStateInExclamationMark] = inExclamationMarkState,
	[OFXMLParserStateInCDATAOpening] = inCDATAOpeningState,
	[OFXMLParserStateInCDATA] = inCDATAState,
	[OFXMLParserStateInCommentOpening] = inCommentOpeningState,
	[OFXMLParserStateInComment1] = inCommentState1,
	[OFXMLParserStateInComment2] = inCommentState2,
	[OFXMLParserStateInDOCTYPE] = inDOCTYPEState
};

static OF_INLINE void
appendToBuffer(OFMutableData *buffer, const char *string,
    OFStringEncoding encoding, size_t length)
{
	if OF_LIKELY(encoding == OFStringEncodingUTF8)







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







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
static void inCDATAState(OFXMLParser *);
static void inCommentOpeningState(OFXMLParser *);
static void inCommentState1(OFXMLParser *);
static void inCommentState2(OFXMLParser *);
static void inDOCTYPEState(OFXMLParser *);
typedef void (*StateFunction)(OFXMLParser *);
static StateFunction lookupTable[] = {
	[stateInByteOrderMark] = inByteOrderMarkState,
	[stateOutsideTag] = outsideTagState,
	[stateTagOpened] = tagOpenedState,
	[stateInProcessingInstruction] = inProcessingInstructionState,

	[stateInTagName] = inTagNameState,
	[stateInCloseTagName] = inCloseTagNameState,
	[stateInTag] = inTagState,
	[stateInAttributeName] = inAttributeNameState,

	[stateExpectAttributeEqualSign] = expectAttributeEqualSignState,

	[stateExpectAttributeDelimiter] = expectAttributeDelimiterState,
	[stateInAttributeValue] = inAttributeValueState,
	[stateExpectTagClose] = expectTagCloseState,
	[stateExpectSpaceOrTagClose] = expectSpaceOrTagCloseState,
	[stateInExclamationMark] = inExclamationMarkState,
	[stateInCDATAOpening] = inCDATAOpeningState,
	[stateInCDATA] = inCDATAState,
	[stateInCommentOpening] = inCommentOpeningState,
	[stateInComment1] = inCommentState1,
	[stateInComment2] = inCommentState2,
	[stateInDOCTYPE] = inDOCTYPEState
};

static OF_INLINE void
appendToBuffer(OFMutableData *buffer, const char *string,
    OFStringEncoding encoding, size_t length)
{
	if OF_LIKELY(encoding == OFStringEncodingUTF8)
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
		if (_data[_i] == '\r' || (_data[_i] == '\n' &&
		    !_lastCarriageReturn))
			_lineNumber++;

		_lastCarriageReturn = (_data[_i] == '\r');
	}

	/* In OFXMLParserStateInTag, there can be only spaces */
	if (length - _last > 0 && _state != OFXMLParserStateInTag)
		appendToBuffer(_buffer, _data + _last, _encoding,
		    length - _last);
}

- (void)parseString: (OFString *)string
{
	[self parseBuffer: string.UTF8String length: string.UTF8StringLength];







|
|







274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
		if (_data[_i] == '\r' || (_data[_i] == '\n' &&
		    !_lastCarriageReturn))
			_lineNumber++;

		_lastCarriageReturn = (_data[_i] == '\r');
	}

	/* In stateInTag, there can be only spaces */
	if (length - _last > 0 && _state != stateInTag)
		appendToBuffer(_buffer, _data + _last, _encoding,
		    length - _last);
}

- (void)parseString: (OFString *)string
{
	[self parseBuffer: string.UTF8String length: string.UTF8StringLength];
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
}

static void
inByteOrderMarkState(OFXMLParser *self)
{
	if (self->_data[self->_i] != "\xEF\xBB\xBF"[self->_level]) {
		if (self->_level == 0) {
			self->_state = OFXMLParserStateOutsideTag;
			self->_i--;
			return;
		}

		@throw [OFMalformedXMLException exceptionWithParser: self];
	}

	if (self->_level++ == 2)
		self->_state = OFXMLParserStateOutsideTag;

	self->_last = self->_i + 1;
}

/* Not in a tag */
static void
outsideTagState(OFXMLParser *self)







|








|







306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
}

static void
inByteOrderMarkState(OFXMLParser *self)
{
	if (self->_data[self->_i] != "\xEF\xBB\xBF"[self->_level]) {
		if (self->_level == 0) {
			self->_state = stateOutsideTag;
			self->_i--;
			return;
		}

		@throw [OFMalformedXMLException exceptionWithParser: self];
	}

	if (self->_level++ == 2)
		self->_state = stateOutsideTag;

	self->_last = self->_i + 1;
}

/* Not in a tag */
static void
outsideTagState(OFXMLParser *self)
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

		objc_autoreleasePoolPop(pool);
	}

	[self->_buffer removeAllItems];

	self->_last = self->_i + 1;
	self->_state = OFXMLParserStateTagOpened;
}

/* Tag was just opened */
static void
tagOpenedState(OFXMLParser *self)
{
	if (self->_finishedParsing && self->_data[self->_i] != '!' &&
	    self->_data[self->_i] != '?')
		@throw [OFMalformedXMLException exceptionWithParser: self];

	switch (self->_data[self->_i]) {
	case '?':
		self->_last = self->_i + 1;
		self->_state = OFXMLParserStateInProcessingInstruction;
		self->_level = 0;
		break;
	case '/':
		self->_last = self->_i + 1;
		self->_state = OFXMLParserStateInCloseTagName;
		self->_acceptProlog = false;
		break;
	case '!':
		self->_last = self->_i + 1;
		self->_state = OFXMLParserStateInExclamationMark;
		self->_acceptProlog = false;
		break;
	default:
		if (self->_depthLimit > 0 &&
		    self->_previous.count >= self->_depthLimit)
			@throw [OFOutOfRangeException exception];

		self->_state = OFXMLParserStateInTagName;
		self->_acceptProlog = false;
		self->_i--;
		break;
	}
}

/* <?xml […]?> */







|













|




|




|







|







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

		objc_autoreleasePoolPop(pool);
	}

	[self->_buffer removeAllItems];

	self->_last = self->_i + 1;
	self->_state = stateTagOpened;
}

/* Tag was just opened */
static void
tagOpenedState(OFXMLParser *self)
{
	if (self->_finishedParsing && self->_data[self->_i] != '!' &&
	    self->_data[self->_i] != '?')
		@throw [OFMalformedXMLException exceptionWithParser: self];

	switch (self->_data[self->_i]) {
	case '?':
		self->_last = self->_i + 1;
		self->_state = stateInProcessingInstruction;
		self->_level = 0;
		break;
	case '/':
		self->_last = self->_i + 1;
		self->_state = stateInCloseTagName;
		self->_acceptProlog = false;
		break;
	case '!':
		self->_last = self->_i + 1;
		self->_state = stateInExclamationMark;
		self->_acceptProlog = false;
		break;
	default:
		if (self->_depthLimit > 0 &&
		    self->_previous.count >= self->_depthLimit)
			@throw [OFOutOfRangeException exception];

		self->_state = stateInTagName;
		self->_acceptProlog = false;
		self->_i--;
		break;
	}
}

/* <?xml […]?> */
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
							    data: data];

		objc_autoreleasePoolPop(pool);

		[self->_buffer removeAllItems];

		self->_last = self->_i + 1;
		self->_state = OFXMLParserStateOutsideTag;
	} else
		self->_level = 0;
}

/* Inside a tag, no name yet */
static void
inTagNameState(OFXMLParser *self)







|







532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
							    data: data];

		objc_autoreleasePoolPop(pool);

		[self->_buffer removeAllItems];

		self->_last = self->_i + 1;
		self->_state = stateOutsideTag;
	} else
		self->_level = 0;
}

/* Inside a tag, no name yet */
static void
inTagNameState(OFXMLParser *self)
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
			[self->_previous addObject: bufferString];

		[self->_name release];
		[self->_prefix release];
		self->_name = self->_prefix = nil;

		self->_state = (self->_data[self->_i] == '/'
		    ? OFXMLParserStateExpectTagClose
		    : OFXMLParserStateOutsideTag);
	} else
		self->_state = OFXMLParserStateInTag;

	if (self->_data[self->_i] != '/')
		[self->_namespaces addObject: [OFMutableDictionary dictionary]];

	objc_autoreleasePoolPop(pool);

	[self->_buffer removeAllItems];







|
<

|







610
611
612
613
614
615
616
617

618
619
620
621
622
623
624
625
626
			[self->_previous addObject: bufferString];

		[self->_name release];
		[self->_prefix release];
		self->_name = self->_prefix = nil;

		self->_state = (self->_data[self->_i] == '/'
		    ? stateExpectTagClose : stateOutsideTag);

	} else
		self->_state = stateInTag;

	if (self->_data[self->_i] != '/')
		[self->_namespaces addObject: [OFMutableDictionary dictionary]];

	objc_autoreleasePoolPop(pool);

	[self->_buffer removeAllItems];
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
	[self->_namespaces removeLastObject];
	[self->_name release];
	[self->_prefix release];
	self->_name = self->_prefix = nil;

	self->_last = self->_i + 1;
	self->_state = (self->_data[self->_i] == '>'
	    ? OFXMLParserStateOutsideTag
	    : OFXMLParserStateExpectSpaceOrTagClose);

	if (self->_previous.count == 0)
		self->_finishedParsing = true;
}

/* Inside a tag, name found */
static void
inTagState(OFXMLParser *self)
{
	void *pool;
	OFString *namespace;
	OFXMLAttribute *const *attributesObjects;
	size_t attributesCount;

	if (self->_data[self->_i] != '>' && self->_data[self->_i] != '/') {
		if (self->_data[self->_i] != ' ' &&
		    self->_data[self->_i] != '\t' &&
		    self->_data[self->_i] != '\n' &&
		    self->_data[self->_i] != '\r') {
			self->_last = self->_i;
			self->_state = OFXMLParserStateInAttributeName;
			self->_i--;
		}

		return;
	}

	attributesObjects = self->_attributes.objects;







<
|




















|







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
	[self->_namespaces removeLastObject];
	[self->_name release];
	[self->_prefix release];
	self->_name = self->_prefix = nil;

	self->_last = self->_i + 1;
	self->_state = (self->_data[self->_i] == '>'

	    ? stateOutsideTag : stateExpectSpaceOrTagClose);

	if (self->_previous.count == 0)
		self->_finishedParsing = true;
}

/* Inside a tag, name found */
static void
inTagState(OFXMLParser *self)
{
	void *pool;
	OFString *namespace;
	OFXMLAttribute *const *attributesObjects;
	size_t attributesCount;

	if (self->_data[self->_i] != '>' && self->_data[self->_i] != '/') {
		if (self->_data[self->_i] != ' ' &&
		    self->_data[self->_i] != '\t' &&
		    self->_data[self->_i] != '\n' &&
		    self->_data[self->_i] != '\r') {
			self->_last = self->_i;
			self->_state = stateInAttributeName;
			self->_i--;
		}

		return;
	}

	attributesObjects = self->_attributes.objects;
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
	[self->_name release];
	[self->_prefix release];
	[self->_attributes removeAllObjects];
	self->_name = self->_prefix = nil;

	self->_last = self->_i + 1;
	self->_state = (self->_data[self->_i] == '/'
	    ? OFXMLParserStateExpectTagClose : OFXMLParserStateOutsideTag);
}

/* Looking for attribute name */
static void
inAttributeNameState(OFXMLParser *self)
{
	void *pool;







|







770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
	[self->_name release];
	[self->_prefix release];
	[self->_attributes removeAllObjects];
	self->_name = self->_prefix = nil;

	self->_last = self->_i + 1;
	self->_state = (self->_data[self->_i] == '/'
	    ? stateExpectTagClose : stateOutsideTag);
}

/* Looking for attribute name */
static void
inAttributeNameState(OFXMLParser *self)
{
	void *pool;
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

	objc_autoreleasePoolPop(pool);

	[self->_buffer removeAllItems];

	self->_last = self->_i + 1;
	self->_state = (self->_data[self->_i] == '='
	    ? OFXMLParserStateExpectAttributeDelimiter
	    : OFXMLParserStateExpectAttributeEqualSign);
}

/* Expecting equal sign of an attribute */
static void
expectAttributeEqualSignState(OFXMLParser *self)
{
	if (self->_data[self->_i] == '=') {
		self->_last = self->_i + 1;
		self->_state = OFXMLParserStateExpectAttributeDelimiter;
		return;
	}

	if (self->_data[self->_i] != ' '  && self->_data[self->_i] != '\t' &&
	    self->_data[self->_i] != '\n' && self->_data[self->_i] != '\r')
		@throw [OFMalformedXMLException exceptionWithParser: self];
}







|
<








|







818
819
820
821
822
823
824
825

826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841

	objc_autoreleasePoolPop(pool);

	[self->_buffer removeAllItems];

	self->_last = self->_i + 1;
	self->_state = (self->_data[self->_i] == '='
	    ? stateExpectAttributeDelimiter : stateExpectAttributeEqualSign);

}

/* Expecting equal sign of an attribute */
static void
expectAttributeEqualSignState(OFXMLParser *self)
{
	if (self->_data[self->_i] == '=') {
		self->_last = self->_i + 1;
		self->_state = stateExpectAttributeDelimiter;
		return;
	}

	if (self->_data[self->_i] != ' '  && self->_data[self->_i] != '\t' &&
	    self->_data[self->_i] != '\n' && self->_data[self->_i] != '\r')
		@throw [OFMalformedXMLException exceptionWithParser: self];
}
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
	    self->_data[self->_i] == '\n' || self->_data[self->_i] == '\r')
		return;

	if (self->_data[self->_i] != '\'' && self->_data[self->_i] != '"')
		@throw [OFMalformedXMLException exceptionWithParser: self];

	self->_delimiter = self->_data[self->_i];
	self->_state = OFXMLParserStateInAttributeValue;
}

/* Looking for attribute value */
static void
inAttributeValueState(OFXMLParser *self)
{
	void *pool;







|







850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
	    self->_data[self->_i] == '\n' || self->_data[self->_i] == '\r')
		return;

	if (self->_data[self->_i] != '\'' && self->_data[self->_i] != '"')
		@throw [OFMalformedXMLException exceptionWithParser: self];

	self->_delimiter = self->_data[self->_i];
	self->_state = stateInAttributeValue;
}

/* Looking for attribute value */
static void
inAttributeValueState(OFXMLParser *self)
{
	void *pool;
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

	[self->_buffer removeAllItems];
	[self->_attributeName release];
	[self->_attributePrefix release];
	self->_attributeName = self->_attributePrefix = nil;

	self->_last = self->_i + 1;
	self->_state = OFXMLParserStateInTag;
}

/* Expecting closing '>' */
static void
expectTagCloseState(OFXMLParser *self)
{
	if (self->_data[self->_i] == '>') {
		self->_last = self->_i + 1;
		self->_state = OFXMLParserStateOutsideTag;
	} else
		@throw [OFMalformedXMLException exceptionWithParser: self];
}

/* Expecting closing '>' or space */
static void
expectSpaceOrTagCloseState(OFXMLParser *self)
{
	if (self->_data[self->_i] == '>') {
		self->_last = self->_i + 1;
		self->_state = OFXMLParserStateOutsideTag;
	} else if (self->_data[self->_i] != ' ' &&
	    self->_data[self->_i] != '\t' && self->_data[self->_i] != '\n' &&
	    self->_data[self->_i] != '\r')
		@throw [OFMalformedXMLException exceptionWithParser: self];
}

/* In <! */
static void
inExclamationMarkState(OFXMLParser *self)
{
	if (self->_finishedParsing && self->_data[self->_i] != '-')
		@throw [OFMalformedXMLException exceptionWithParser: self];

	if (self->_data[self->_i] == '-')
		self->_state = OFXMLParserStateInCommentOpening;
	else if (self->_data[self->_i] == '[') {
		self->_state = OFXMLParserStateInCDATAOpening;
		self->_level = 0;
	} else if (self->_data[self->_i] == 'D') {
		self->_state = OFXMLParserStateInDOCTYPE;
		self->_level = 0;
	} else
		@throw [OFMalformedXMLException exceptionWithParser: self];

	self->_last = self->_i + 1;
}

/* CDATA */
static void
inCDATAOpeningState(OFXMLParser *self)
{
	if (self->_data[self->_i] != "CDATA["[self->_level])
		@throw [OFMalformedXMLException exceptionWithParser: self];

	if (++self->_level == 6) {
		self->_state = OFXMLParserStateInCDATA;
		self->_level = 0;
	}

	self->_last = self->_i + 1;
}

static void







|








|










|














|

|


|















|







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

	[self->_buffer removeAllItems];
	[self->_attributeName release];
	[self->_attributePrefix release];
	self->_attributeName = self->_attributePrefix = nil;

	self->_last = self->_i + 1;
	self->_state = stateInTag;
}

/* Expecting closing '>' */
static void
expectTagCloseState(OFXMLParser *self)
{
	if (self->_data[self->_i] == '>') {
		self->_last = self->_i + 1;
		self->_state = stateOutsideTag;
	} else
		@throw [OFMalformedXMLException exceptionWithParser: self];
}

/* Expecting closing '>' or space */
static void
expectSpaceOrTagCloseState(OFXMLParser *self)
{
	if (self->_data[self->_i] == '>') {
		self->_last = self->_i + 1;
		self->_state = stateOutsideTag;
	} else if (self->_data[self->_i] != ' ' &&
	    self->_data[self->_i] != '\t' && self->_data[self->_i] != '\n' &&
	    self->_data[self->_i] != '\r')
		@throw [OFMalformedXMLException exceptionWithParser: self];
}

/* In <! */
static void
inExclamationMarkState(OFXMLParser *self)
{
	if (self->_finishedParsing && self->_data[self->_i] != '-')
		@throw [OFMalformedXMLException exceptionWithParser: self];

	if (self->_data[self->_i] == '-')
		self->_state = stateInCommentOpening;
	else if (self->_data[self->_i] == '[') {
		self->_state = stateInCDATAOpening;
		self->_level = 0;
	} else if (self->_data[self->_i] == 'D') {
		self->_state = stateInDOCTYPE;
		self->_level = 0;
	} else
		@throw [OFMalformedXMLException exceptionWithParser: self];

	self->_last = self->_i + 1;
}

/* CDATA */
static void
inCDATAOpeningState(OFXMLParser *self)
{
	if (self->_data[self->_i] != "CDATA["[self->_level])
		@throw [OFMalformedXMLException exceptionWithParser: self];

	if (++self->_level == 6) {
		self->_state = stateInCDATA;
		self->_level = 0;
	}

	self->_last = self->_i + 1;
}

static void
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
			[self->_delegate parser: self foundCDATA: CDATA];

		objc_autoreleasePoolPop(pool);

		[self->_buffer removeAllItems];

		self->_last = self->_i + 1;
		self->_state = OFXMLParserStateOutsideTag;
	} else
		self->_level = 0;
}

/* Comment */
static void
inCommentOpeningState(OFXMLParser *self)
{
	if (self->_data[self->_i] != '-')
		@throw [OFMalformedXMLException exceptionWithParser: self];

	self->_last = self->_i + 1;
	self->_state = OFXMLParserStateInComment1;
	self->_level = 0;
}

static void
inCommentState1(OFXMLParser *self)
{
	if (self->_data[self->_i] == '-')
		self->_level++;
	else
		self->_level = 0;

	if (self->_level == 2)
		self->_state = OFXMLParserStateInComment2;
}

static void
inCommentState2(OFXMLParser *self)
{
	void *pool;
	OFString *comment;







|












|












|







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
			[self->_delegate parser: self foundCDATA: CDATA];

		objc_autoreleasePoolPop(pool);

		[self->_buffer removeAllItems];

		self->_last = self->_i + 1;
		self->_state = stateOutsideTag;
	} else
		self->_level = 0;
}

/* Comment */
static void
inCommentOpeningState(OFXMLParser *self)
{
	if (self->_data[self->_i] != '-')
		@throw [OFMalformedXMLException exceptionWithParser: self];

	self->_last = self->_i + 1;
	self->_state = stateInComment1;
	self->_level = 0;
}

static void
inCommentState1(OFXMLParser *self)
{
	if (self->_data[self->_i] == '-')
		self->_level++;
	else
		self->_level = 0;

	if (self->_level == 2)
		self->_state = stateInComment2;
}

static void
inCommentState2(OFXMLParser *self)
{
	void *pool;
	OFString *comment;
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
		[self->_delegate parser: self foundComment: comment];

	objc_autoreleasePoolPop(pool);

	[self->_buffer removeAllItems];

	self->_last = self->_i + 1;
	self->_state = OFXMLParserStateOutsideTag;
}

/* In <!DOCTYPE ...> */
static void
inDOCTYPEState(OFXMLParser *self)
{
	if ((self->_level < 6 &&
	    self->_data[self->_i] != "OCTYPE"[self->_level]) ||
	    (self->_level == 6 && self->_data[self->_i] != ' ' &&
	    self->_data[self->_i] != '\t' && self->_data[self->_i] != '\n' &&
	    self->_data[self->_i] != '\r'))
		@throw [OFMalformedXMLException exceptionWithParser: self];

	self->_level++;

	if (self->_level > 6 && self->_data[self->_i] == '>')
		self->_state = OFXMLParserStateOutsideTag;

	self->_last = self->_i + 1;
}

- (size_t)lineNumber
{
	return _lineNumber;







|
















|







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
		[self->_delegate parser: self foundComment: comment];

	objc_autoreleasePoolPop(pool);

	[self->_buffer removeAllItems];

	self->_last = self->_i + 1;
	self->_state = stateOutsideTag;
}

/* In <!DOCTYPE ...> */
static void
inDOCTYPEState(OFXMLParser *self)
{
	if ((self->_level < 6 &&
	    self->_data[self->_i] != "OCTYPE"[self->_level]) ||
	    (self->_level == 6 && self->_data[self->_i] != ' ' &&
	    self->_data[self->_i] != '\t' && self->_data[self->_i] != '\n' &&
	    self->_data[self->_i] != '\r'))
		@throw [OFMalformedXMLException exceptionWithParser: self];

	self->_level++;

	if (self->_level > 6 && self->_data[self->_i] == '>')
		self->_state = stateOutsideTag;

	self->_last = self->_i + 1;
}

- (size_t)lineNumber
{
	return _lineNumber;

Modified src/OFZIPArchive.h from [35e140687b] to [3dde37049e].

30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
 * @brief A class for accessing and manipulating ZIP files.
 */
OF_SUBCLASSING_RESTRICTED
@interface OFZIPArchive: OFObject
{
	OFStream *_stream;
	int64_t _offset;
	enum {
		OFZIPArchiveModeRead,
		OFZIPArchiveModeWrite,
		OFZIPArchiveModeAppend
	} _mode;
	uint32_t _diskNumber, _centralDirectoryDisk;
	uint64_t _centralDirectoryEntriesInDisk, _centralDirectoryEntries;
	uint64_t _centralDirectorySize;
	int64_t _centralDirectoryOffset;
	OFString *_Nullable _archiveComment;
	OFMutableArray OF_GENERIC(OFZIPArchiveEntry *) *_entries;
	OFMutableDictionary OF_GENERIC(OFString *, OFZIPArchiveEntry *)







<
<
<
<
|







30
31
32
33
34
35
36




37
38
39
40
41
42
43
44
 * @brief A class for accessing and manipulating ZIP files.
 */
OF_SUBCLASSING_RESTRICTED
@interface OFZIPArchive: OFObject
{
	OFStream *_stream;
	int64_t _offset;




	uint_least8_t _mode;
	uint32_t _diskNumber, _centralDirectoryDisk;
	uint64_t _centralDirectoryEntriesInDisk, _centralDirectoryEntries;
	uint64_t _centralDirectorySize;
	int64_t _centralDirectoryOffset;
	OFString *_Nullable _archiveComment;
	OFMutableArray OF_GENERIC(OFZIPArchiveEntry *) *_entries;
	OFMutableDictionary OF_GENERIC(OFString *, OFZIPArchiveEntry *)

Modified src/OFZIPArchive.m from [2bb1e08022] to [952e87c05c].

44
45
46
47
48
49
50






51
52
53
54
55
56
57
#import "OFUnsupportedVersionException.h"

/*
 * FIXME: Current limitations:
 *  - Split archives are not supported.
 *  - Encrypted files cannot be read.
 */







OF_DIRECT_MEMBERS
@interface OFZIPArchive ()
- (void)of_readZIPInfo;
- (void)of_readEntries;
- (void)of_closeLastReturnedStream;
- (void)of_writeCentralDirectory;







>
>
>
>
>
>







44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
#import "OFUnsupportedVersionException.h"

/*
 * FIXME: Current limitations:
 *  - Split archives are not supported.
 *  - Encrypted files cannot be read.
 */

enum {
	modeRead,
	modeWrite,
	modeAppend
};

OF_DIRECT_MEMBERS
@interface OFZIPArchive ()
- (void)of_readZIPInfo;
- (void)of_readEntries;
- (void)of_closeLastReturnedStream;
- (void)of_writeCentralDirectory;
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

- (instancetype)initWithStream: (OFStream *)stream mode: (OFString *)mode
{
	self = [super init];

	@try {
		if ([mode isEqual: @"r"])
			_mode = OFZIPArchiveModeRead;
		else if ([mode isEqual: @"w"])
			_mode = OFZIPArchiveModeWrite;
		else if ([mode isEqual: @"a"])
			_mode = OFZIPArchiveModeAppend;
		else
			@throw [OFInvalidArgumentException exception];

		_stream = [stream retain];
		_entries = [[OFMutableArray alloc] init];
		_pathToEntryMap = [[OFMutableDictionary alloc] init];

		if (_mode == OFZIPArchiveModeRead ||
		    _mode == OFZIPArchiveModeAppend) {
			if (![stream isKindOfClass: [OFSeekableStream class]])
				@throw [OFInvalidArgumentException exception];

			[self of_readZIPInfo];
			[self of_readEntries];
		}

		if (_mode == OFZIPArchiveModeAppend) {
			_offset = _centralDirectoryOffset;
			seekOrThrowInvalidFormat((OFSeekableStream *)_stream,
			    (OFFileOffset)_offset, SEEK_SET);
		}
	} @catch (id e) {
		/*
		 * If we are in write or append mode, we do not want -[close]







|

|

|







|
<







|







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

- (instancetype)initWithStream: (OFStream *)stream mode: (OFString *)mode
{
	self = [super init];

	@try {
		if ([mode isEqual: @"r"])
			_mode = modeRead;
		else if ([mode isEqual: @"w"])
			_mode = modeWrite;
		else if ([mode isEqual: @"a"])
			_mode = modeAppend;
		else
			@throw [OFInvalidArgumentException exception];

		_stream = [stream retain];
		_entries = [[OFMutableArray alloc] init];
		_pathToEntryMap = [[OFMutableDictionary alloc] init];

		if (_mode == modeRead || _mode == modeAppend) {

			if (![stream isKindOfClass: [OFSeekableStream class]])
				@throw [OFInvalidArgumentException exception];

			[self of_readZIPInfo];
			[self of_readEntries];
		}

		if (_mode == modeAppend) {
			_offset = _centralDirectoryOffset;
			seekOrThrowInvalidFormat((OFSeekableStream *)_stream,
			    (OFFileOffset)_offset, SEEK_SET);
		}
	} @catch (id e) {
		/*
		 * If we are in write or append mode, we do not want -[close]
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
{
	@try {
		[_lastReturnedStream close];
	} @catch (OFNotOpenException *e) {
		/* Might have already been closed by the user - that's fine. */
	}

	if ((_mode == OFZIPArchiveModeWrite ||
	    _mode == OFZIPArchiveModeAppend) &&
	    [_lastReturnedStream isKindOfClass:
	    [OFZIPArchiveFileWriteStream class]]) {
		OFZIPArchiveFileWriteStream *stream =
		    (OFZIPArchiveFileWriteStream *)_lastReturnedStream;

		if (INT64_MAX - _offset < stream->_bytesWritten)
			@throw [OFOutOfRangeException exception];







|
<







401
402
403
404
405
406
407
408

409
410
411
412
413
414
415
{
	@try {
		[_lastReturnedStream close];
	} @catch (OFNotOpenException *e) {
		/* Might have already been closed by the user - that's fine. */
	}

	if ((_mode == modeWrite || _mode == modeAppend) &&

	    [_lastReturnedStream isKindOfClass:
	    [OFZIPArchiveFileWriteStream class]]) {
		OFZIPArchiveFileWriteStream *stream =
		    (OFZIPArchiveFileWriteStream *)_lastReturnedStream;

		if (INT64_MAX - _offset < stream->_bytesWritten)
			@throw [OFOutOfRangeException exception];
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
- (OFStream *)streamForReadingFile: (OFString *)path
{
	void *pool = objc_autoreleasePoolPush();
	OFZIPArchiveEntry *entry;
	OFZIPArchiveLocalFileHeader *localFileHeader;
	int64_t offset64;

	if (_mode != OFZIPArchiveModeRead)
		@throw [OFInvalidArgumentException exception];

	if ((entry = [_pathToEntryMap objectForKey: path]) == nil)
		@throw [OFOpenItemFailedException exceptionWithPath: path
							       mode: @"r"
							      errNo: ENOENT];








|







430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
- (OFStream *)streamForReadingFile: (OFString *)path
{
	void *pool = objc_autoreleasePoolPush();
	OFZIPArchiveEntry *entry;
	OFZIPArchiveLocalFileHeader *localFileHeader;
	int64_t offset64;

	if (_mode != modeRead)
		@throw [OFInvalidArgumentException exception];

	if ((entry = [_pathToEntryMap objectForKey: path]) == nil)
		@throw [OFOpenItemFailedException exceptionWithPath: path
							       mode: @"r"
							      errNo: ENOENT];

476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
	int64_t offsetAdd = 0;
	void *pool;
	OFMutableZIPArchiveEntry *entry;
	OFString *fileName;
	OFData *extraField;
	uint16_t fileNameLength, extraFieldLength;

	if (_mode != OFZIPArchiveModeWrite && _mode != OFZIPArchiveModeAppend)
		@throw [OFInvalidArgumentException exception];

	pool = objc_autoreleasePoolPush();
	entry = [[entry_ mutableCopy] autorelease];

	if ([_pathToEntryMap objectForKey: entry.fileName] != nil)
		@throw [OFOpenItemFailedException







|







480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
	int64_t offsetAdd = 0;
	void *pool;
	OFMutableZIPArchiveEntry *entry;
	OFString *fileName;
	OFData *extraField;
	uint16_t fileNameLength, extraFieldLength;

	if (_mode != modeWrite && _mode != modeAppend)
		@throw [OFInvalidArgumentException exception];

	pool = objc_autoreleasePoolPush();
	entry = [[entry_ mutableCopy] autorelease];

	if ([_pathToEntryMap objectForKey: entry.fileName] != nil)
		@throw [OFOpenItemFailedException
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
- (void)close
{
	if (_stream == nil)
		@throw [OFNotOpenException exceptionWithObject: self];

	[self of_closeLastReturnedStream];

	if (_mode == OFZIPArchiveModeWrite || _mode == OFZIPArchiveModeAppend)
		[self of_writeCentralDirectory];

	[_stream release];
	_stream = nil;
}
@end








|







613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
- (void)close
{
	if (_stream == nil)
		@throw [OFNotOpenException exceptionWithObject: self];

	[self of_closeLastReturnedStream];

	if (_mode == modeWrite || _mode == modeAppend)
		[self of_writeCentralDirectory];

	[_stream release];
	_stream = nil;
}
@end

Modified src/OFZIPArchiveEntry.h from [79b0008ba2] to [e18b985df3].

15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48

#import "OFObject.h"

OF_ASSUME_NONNULL_BEGIN

/** @file */

typedef enum OFZIPArchiveEntryCompressionMethod {
	OFZIPArchiveEntryCompressionMethodNone		=  0,
	OFZIPArchiveEntryCompressionMethodShrink	=  1,
	OFZIPArchiveEntryCompressionMethodReduceFactor1 =  2,
	OFZIPArchiveEntryCompressionMethodReduceFactor2 =  3,
	OFZIPArchiveEntryCompressionMethodReduceFactor3 =  4,
	OFZIPArchiveEntryCompressionMethodReduceFactor4 =  5,
	OFZIPArchiveEntryCompressionMethodImplode	=  6,
	OFZIPArchiveEntryCompressionMethodDeflate	=  8,
	OFZIPArchiveEntryCompressionMethodDeflate64	=  9,
	OFZIPArchiveEntryCompressionMethodBZIP2		= 12,
	OFZIPArchiveEntryCompressionMethodLZMA		= 14,
	OFZIPArchiveEntryCompressionMethodWavPack	= 97,
	OFZIPArchiveEntryCompressionMethodPPMd		= 98
} OFZIPArchiveEntryCompressionMethod;

/**
 * @brief Attribute compatibility part of ZIP versions.
 */
typedef enum OFZIPArchiveEntryAttributeCompatibility {
	/** MS-DOS and OS/2 */
	OFZIPArchiveEntryAttributeCompatibilityMSDOS	    =  0,
	/** Amiga */
	OFZIPArchiveEntryAttributeCompatibilityAmiga	    =  1,
	/** OpenVMS */
	OFZIPArchiveEntryAttributeCompatibilityOpenVMS	    =  2,
	/** UNIX */







|


















|







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48

#import "OFObject.h"

OF_ASSUME_NONNULL_BEGIN

/** @file */

typedef enum {
	OFZIPArchiveEntryCompressionMethodNone		=  0,
	OFZIPArchiveEntryCompressionMethodShrink	=  1,
	OFZIPArchiveEntryCompressionMethodReduceFactor1 =  2,
	OFZIPArchiveEntryCompressionMethodReduceFactor2 =  3,
	OFZIPArchiveEntryCompressionMethodReduceFactor3 =  4,
	OFZIPArchiveEntryCompressionMethodReduceFactor4 =  5,
	OFZIPArchiveEntryCompressionMethodImplode	=  6,
	OFZIPArchiveEntryCompressionMethodDeflate	=  8,
	OFZIPArchiveEntryCompressionMethodDeflate64	=  9,
	OFZIPArchiveEntryCompressionMethodBZIP2		= 12,
	OFZIPArchiveEntryCompressionMethodLZMA		= 14,
	OFZIPArchiveEntryCompressionMethodWavPack	= 97,
	OFZIPArchiveEntryCompressionMethodPPMd		= 98
} OFZIPArchiveEntryCompressionMethod;

/**
 * @brief Attribute compatibility part of ZIP versions.
 */
typedef enum {
	/** MS-DOS and OS/2 */
	OFZIPArchiveEntryAttributeCompatibilityMSDOS	    =  0,
	/** Amiga */
	OFZIPArchiveEntryAttributeCompatibilityAmiga	    =  1,
	/** OpenVMS */
	OFZIPArchiveEntryAttributeCompatibilityOpenVMS	    =  2,
	/** UNIX */
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
	/** OS X (Darwin) */
	OFZIPArchiveEntryAttributeCompatibilityOSX	    = 19
} OFZIPArchiveEntryAttributeCompatibility;

/**
 * @brief Tags for the extra field.
 */
typedef enum OFZIPArchiveEntryExtraFieldTag {
	/** ZIP64 extra field tag */
	OFZIPArchiveEntryExtraFieldTagZIP64 = 0x0001
} OFZIPArchiveEntryExtraFieldTag;

@class OFString;
@class OFData;
@class OFFile;







|







80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
	/** OS X (Darwin) */
	OFZIPArchiveEntryAttributeCompatibilityOSX	    = 19
} OFZIPArchiveEntryAttributeCompatibility;

/**
 * @brief Tags for the extra field.
 */
typedef enum {
	/** ZIP64 extra field tag */
	OFZIPArchiveEntryExtraFieldTagZIP64 = 0x0001
} OFZIPArchiveEntryExtraFieldTag;

@class OFString;
@class OFData;
@class OFFile;

Modified src/ObjFW.h from [304cf44661] to [59913cb5c3].

41
42
43
44
45
46
47

48
49
50
51
52
53
54
#import "OFNull.h"

#import "OFMethodSignature.h"
#import "OFInvocation.h"

#import "OFNumber.h"
#import "OFDate.h"

#import "OFURL.h"
#import "OFURLHandler.h"
#import "OFColor.h"

#import "OFStream.h"
#import "OFStdIOStream.h"
#import "OFInflateStream.h"







>







41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
#import "OFNull.h"

#import "OFMethodSignature.h"
#import "OFInvocation.h"

#import "OFNumber.h"
#import "OFDate.h"
#import "OFUUID.h"
#import "OFURL.h"
#import "OFURLHandler.h"
#import "OFColor.h"

#import "OFStream.h"
#import "OFStdIOStream.h"
#import "OFInflateStream.h"

Modified src/exceptions/OFException.m from [d414760729] to [5ced4219b2].

45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# define HAVE_ARM_EHABI_EXCEPTIONS
#endif

struct _Unwind_Context;
typedef enum {
	_URC_OK		  = 0,
	_URC_END_OF_STACK = 5
}_Unwind_Reason_Code;

struct BacktraceCtx {
	void **backtrace;
	uint8_t i;
};

#ifdef HAVE__UNWIND_BACKTRACE







|







45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# define HAVE_ARM_EHABI_EXCEPTIONS
#endif

struct _Unwind_Context;
typedef enum {
	_URC_OK		  = 0,
	_URC_END_OF_STACK = 5
} _Unwind_Reason_Code;

struct BacktraceCtx {
	void **backtrace;
	uint8_t i;
};

#ifdef HAVE__UNWIND_BACKTRACE

Modified src/macros.h from [3a3771fba4] to [13da37c718].

605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
# define OFToLittleEndian64(i) (i)
#endif

#ifdef OF_FLOAT_BIG_ENDIAN
# define OFFromBigEndianFloat(f) (f)
# define OFFromBigEndianDouble(d) (d)
# define OFFromLittleEndianFloat(f) OFByteSwapFloat(f)
# define OFFromLittleEndianDouble(i) OFByteSwapDouble(d)
# define OFToBigEndianFloat(f) (f)
# define OFToBigEndianDouble(d) (d)
# define OFToLittleEndianFloat(f) OFByteSwapFloat(f)
# define OFToLittleEndianDouble(i) OFByteSwapDouble(d)
#else
# define OFFromBigEndianFloat(f) OFByteSwapFloat(f)
# define OFFromBigEndianDouble(d) OFByteSwapDouble(d)
# define OFFromLittleEndianFloat(f) (f)
# define OFFromLittleEndianDouble(d) (d)
# define OFToBigEndianFloat(f) OFByteSwapFloat(f)
# define OFToBigEndianDouble(d) OFByteSwapDouble(d)







|



|







605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
# define OFToLittleEndian64(i) (i)
#endif

#ifdef OF_FLOAT_BIG_ENDIAN
# define OFFromBigEndianFloat(f) (f)
# define OFFromBigEndianDouble(d) (d)
# define OFFromLittleEndianFloat(f) OFByteSwapFloat(f)
# define OFFromLittleEndianDouble(d) OFByteSwapDouble(d)
# define OFToBigEndianFloat(f) (f)
# define OFToBigEndianDouble(d) (d)
# define OFToLittleEndianFloat(f) OFByteSwapFloat(f)
# define OFToLittleEndianDouble(d) OFByteSwapDouble(d)
#else
# define OFFromBigEndianFloat(f) OFByteSwapFloat(f)
# define OFFromBigEndianDouble(d) OFByteSwapDouble(d)
# define OFFromLittleEndianFloat(f) (f)
# define OFFromLittleEndianDouble(d) (d)
# define OFToBigEndianFloat(f) OFByteSwapFloat(f)
# define OFToBigEndianDouble(d) OFByteSwapDouble(d)
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
    ? ((value) >> ((bits) % (sizeof(value) * 8))) |			\
    ((value) << (sizeof(value) * 8 - ((bits) % (sizeof(value) * 8))))	\
    : (value))

#define OFRoundUpToPowerOf2(pow2, value)	\
    (((value) + (pow2) - 1) & ~((pow2) - 1))

extern unsigned long OFHashSeed;

static OF_INLINE void
OFHashInit(unsigned long *_Nonnull hash)
{
	*hash = OFHashSeed;
}

static OF_INLINE void
OFHashAdd(unsigned long *_Nonnull hash, unsigned char byte)
{
	uint32_t tmp = (uint32_t)*hash;

	tmp += byte;
	tmp += tmp << 10;
	tmp ^= tmp >> 6;

	*hash = tmp;
}

static OF_INLINE void
OFHashAddHash(unsigned long *_Nonnull hash, unsigned long otherHash)
{
	OFHashAdd(hash, (otherHash >> 24) & 0xFF);
	OFHashAdd(hash, (otherHash >> 16) & 0xFF);
	OFHashAdd(hash, (otherHash >>  8) & 0xFF);
	OFHashAdd(hash, otherHash & 0xFF);
}

static OF_INLINE void
OFHashFinalize(unsigned long *_Nonnull hash)
{
	uint32_t tmp = (uint32_t)*hash;

	tmp += tmp << 3;
	tmp ^= tmp >> 11;
	tmp += tmp << 15;

	*hash = tmp;
}

static OF_INLINE bool
OFBitsetIsSet(unsigned char *_Nonnull storage, size_t idx)
{
	return storage[idx / CHAR_BIT] & (1u << (idx % CHAR_BIT));
}

static OF_INLINE void







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







635
636
637
638
639
640
641









































642
643
644
645
646
647
648
    ? ((value) >> ((bits) % (sizeof(value) * 8))) |			\
    ((value) << (sizeof(value) * 8 - ((bits) % (sizeof(value) * 8))))	\
    : (value))

#define OFRoundUpToPowerOf2(pow2, value)	\
    (((value) + (pow2) - 1) & ~((pow2) - 1))










































static OF_INLINE bool
OFBitsetIsSet(unsigned char *_Nonnull storage, size_t idx)
{
	return storage[idx / CHAR_BIT] & (1u << (idx % CHAR_BIT));
}

static OF_INLINE void

Modified src/module.modulemap from [4964b69439] to [33c24fc753].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
framework module ObjFW {
	umbrella header "ObjFW.h"

	/*
	 * These are included by OFAtomic.h, but should never be included
	 * directly.
	 */
	exclude header "OFAtomic_builtins.h"
	exclude header "OFAtomic_no_threads.h"
	exclude header "OFAtomic_osatomic.h"
	exclude header "OFAtomic_powerpc.h"
	exclude header "OFAtomic_sync_builtins.h"
	exclude header "OFAtomic_x86.h"

	export *
}







|
|
|
|
<
|



1
2
3
4
5
6
7
8
9
10
11

12
13
14
15
framework module ObjFW {
	umbrella header "ObjFW.h"

	/*
	 * These are included by OFAtomic.h, but should never be included
	 * directly.
	 */
	exclude header "platform/GCC4/OFAtomic.h"
	exclude header "platform/GCC4.7/OFAtomic.h"
	exclude header "platform/PowerPC/OFAtomic.h"
	exclude header "platform/macOS/OFAtomic.h"

	exclude header "platform/x86/OFAtomic.h"

	export *
}

Name change from src/platform/amiga/OFPlainCondition.m to src/platform/AmigaOS/OFPlainCondition.m.

Name change from src/platform/amiga/OFPlainMutex.m to src/platform/AmigaOS/OFPlainMutex.m.

Renamed and modified src/platform/amiga/OFPlainThread.m [d05f96868a] to src/platform/AmigaOS/OFPlainThread.m [874b38ae30].

155
156
157
158
159
160
161






162
163
164
165
166
167
168
}

OFPlainThread
OFCurrentPlainThread(void)
{
	return OFTLSKeyGet(threadKey);
}







int
OFPlainThreadJoin(OFPlainThread thread)
{
	ObtainSemaphore(&thread->semaphore);

	if (thread->done) {







>
>
>
>
>
>







155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
}

OFPlainThread
OFCurrentPlainThread(void)
{
	return OFTLSKeyGet(threadKey);
}

bool
OFPlainThreadIsCurrent(OFPlainThread thread)
{
	return (thread->task == FindTask(NULL));
}

int
OFPlainThreadJoin(OFPlainThread thread)
{
	ObtainSemaphore(&thread->semaphore);

	if (thread->done) {

Name change from src/platform/amiga/OFString+PathAdditions.m to src/platform/AmigaOS/OFString+PathAdditions.m.

Name change from src/platform/amiga/OFTLSKey.m to src/platform/AmigaOS/OFTLSKey.m.

Name change from src/OFAtomic_builtins.h to src/platform/GCC4.7/OFAtomic.h.

Renamed and modified src/OFAtomic_sync_builtins.h [cebe486547] to src/platform/GCC4/OFAtomic.h [16dfce6eb3].

112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
static OF_INLINE bool
OFAtomicIntCompareAndSwap(volatile int *_Nonnull p, int o, int n)
{
	return __sync_bool_compare_and_swap(p, o, n);
}

static OF_INLINE bool
OFAtomicInt32CompAndSwap(volatile int32_t *_Nonnull p, int32_t o, int32_t n)
{
	return __sync_bool_compare_and_swap(p, o, n);
}

static OF_INLINE bool
OFAtomicPointerCompareAndSwap(void *volatile _Nullable *_Nonnull p,
    void *_Nullable o, void *_Nullable n)







|







112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
static OF_INLINE bool
OFAtomicIntCompareAndSwap(volatile int *_Nonnull p, int o, int n)
{
	return __sync_bool_compare_and_swap(p, o, n);
}

static OF_INLINE bool
OFAtomicInt32CompareAndSwap(volatile int32_t *_Nonnull p, int32_t o, int32_t n)
{
	return __sync_bool_compare_and_swap(p, o, n);
}

static OF_INLINE bool
OFAtomicPointerCompareAndSwap(void *volatile _Nullable *_Nonnull p,
    void *_Nullable o, void *_Nullable n)

Renamed and modified src/platform/morphos/OFTLSKey.m [8de1ab9b4a] to src/platform/MorphOS/OFTLSKey.m [493207d475].

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

#include "config.h"

#import "OFTLSKey.h"

int
OFTLSKeyNew(OFTLSKeyT *key)
{
	*key = TLSAllocA(NULL);

	if (*key == TLS_INVALID_INDEX)
		return EAGAIN;

	return 0;
}

int
OFTLSKeyFree(OFTLSKeyT key)
{
	return (TLSFree(key) ? 0 : EINVAL);
}







|










|



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

#include "config.h"

#import "OFTLSKey.h"

int
OFTLSKeyNew(OFTLSKey *key)
{
	*key = TLSAllocA(NULL);

	if (*key == TLS_INVALID_INDEX)
		return EAGAIN;

	return 0;
}

int
OFTLSKeyFree(OFTLSKey key)
{
	return (TLSFree(key) ? 0 : EINVAL);
}

Name change from src/platform/posix/OFPlainCondition.m to src/platform/POSIX/OFPlainCondition.m.

Name change from src/platform/posix/OFPlainMutex.m to src/platform/POSIX/OFPlainMutex.m.

Name change from src/platform/posix/OFPlainThread.m to src/platform/POSIX/OFPlainThread.m.

Name change from src/platform/posix/OFString+PathAdditions.m to src/platform/POSIX/OFString+PathAdditions.m.

Name change from src/platform/posix/OFSubprocess.m to src/platform/POSIX/OFSubprocess.m.

Name change from src/platform/posix/OFTLSKey.m to src/platform/POSIX/OFTLSKey.m.

Renamed and modified src/OFAtomic_powerpc.h [b84702cb04] to src/platform/PowerPC/OFAtomic.h [44b886c5c2].

290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
	    : "cc", "memory"
	);

	return i;
}

static OF_INLINE bool
OFAtomicIntCompAndSwap(volatile int *_Nonnull p, int o, int n)
{
	int r;

	__asm__ __volatile__ (
	    "0:\n\t"
	    "lwarx	%0, 0, %3\n\t"
	    "cmpw	%0, %1\n\t"







|







290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
	    : "cc", "memory"
	);

	return i;
}

static OF_INLINE bool
OFAtomicIntCompareAndSwap(volatile int *_Nonnull p, int o, int n)
{
	int r;

	__asm__ __volatile__ (
	    "0:\n\t"
	    "lwarx	%0, 0, %3\n\t"
	    "cmpw	%0, %1\n\t"

Name change from src/platform/windows/OFPlainCondition.m to src/platform/Windows/OFPlainCondition.m.

Name change from src/platform/windows/OFPlainMutex.m to src/platform/Windows/OFPlainMutex.m.

Name change from src/platform/windows/OFPlainThread.m to src/platform/Windows/OFPlainThread.m.

Name change from src/platform/windows/OFString+PathAdditions.m to src/platform/Windows/OFString+PathAdditions.m.

Name change from src/platform/windows/OFSubprocess.m to src/platform/Windows/OFSubprocess.m.

Name change from src/platform/windows/OFTLSKey.m to src/platform/Windows/OFTLSKey.m.

Name change from src/OFAtomic_osatomic.h to src/platform/macOS/OFAtomic.h.

Name change from src/OFAtomic_x86.h to src/platform/x86/OFAtomic.h.

Modified src/runtime/ObjFWRT.h from [1456702210] to [4089c697eb].

142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
typedef id _Nullable (*IMP)(id _Nonnull object, SEL _Nonnull selector, ...);

/**
 * @brief A handler for uncaught exceptions.
 *
 * @param exception The exception which was not caught.
 */
typedef void (*objc_uncaught_exception_handler_t)(id _Nullable exception);

/**
 * @brief A handler for mutation during enumeration.
 *
 * @param object The object that was mutated during enumeration
 */
typedef void (*objc_enumeration_mutation_handler_t)(id _Nonnull object);

/**
 * @brief A struct representing a call to super.
 */
struct objc_super {
	/**
	 * @brief The object on which to perform the super call.







|






|







142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
typedef id _Nullable (*IMP)(id _Nonnull object, SEL _Nonnull selector, ...);

/**
 * @brief A handler for uncaught exceptions.
 *
 * @param exception The exception which was not caught.
 */
typedef void (*objc_uncaught_exception_handler)(id _Nullable exception);

/**
 * @brief A handler for mutation during enumeration.
 *
 * @param object The object that was mutated during enumeration
 */
typedef void (*objc_enumeration_mutation_handler)(id _Nonnull object);

/**
 * @brief A struct representing a call to super.
 */
struct objc_super {
	/**
	 * @brief The object on which to perform the super call.
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
 * @return A copy of the attribute value. You need to call `free()` on it when
 *	   done.
 */
extern char *_Nullable property_copyAttributeValue(
    objc_property_t _Nonnull property, const char *_Nonnull name);

/**
 * @brief Exits the Objective-C runtime.
 *
 * This frees all data structures used by the runtime, after which Objective-C
 * can no longer be used inside the current process. This is only useful for
 * debugging.
 */
extern void objc_exit(void);

/**
 * @brief Sets the handler for uncaught exceptions.
 *
 * @param handler The new handler for uncaught exceptions
 * @return The old handler for uncaught exceptions
 */
extern _Nullable objc_uncaught_exception_handler_t
    objc_setUncaughtExceptionHandler(
    objc_uncaught_exception_handler_t _Nullable handler);

/**
 * @brief Sets the forwarding handler for unimplemented methods.
 *
 * @param forward The forwarding handler for regular methods
 * @param stretForward The forwarding handler for methods using the struct
 *		       return ABI
 */
extern void objc_setForwardHandler(IMP _Nullable forward,
    IMP _Nullable stretForward);

/**
 * @brief Sets the handler for mutations during enumeration.
 *
 * @param handler The handler for mutations during enumeration
 */
extern void objc_setEnumerationMutationHandler(
    objc_enumeration_mutation_handler_t _Nullable handler);

/**
 * @brief Constructs an instance of the specified class in the specified array
 *	  of bytes.
 *
 * @param class_ The class of which to construct an instance
 * @param bytes An array of bytes of at least the length of the instance size.







|



|

|







|

|

















|







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
 * @return A copy of the attribute value. You need to call `free()` on it when
 *	   done.
 */
extern char *_Nullable property_copyAttributeValue(
    objc_property_t _Nonnull property, const char *_Nonnull name);

/**
 * @brief Deinitializes the Objective-C runtime.
 *
 * This frees all data structures used by the runtime, after which Objective-C
 * can no longer be used inside the current process. This is only useful for
 * debugging and tests.
 */
extern void objc_deinit(void);

/**
 * @brief Sets the handler for uncaught exceptions.
 *
 * @param handler The new handler for uncaught exceptions
 * @return The old handler for uncaught exceptions
 */
extern _Nullable objc_uncaught_exception_handler
    objc_setUncaughtExceptionHandler(
    objc_uncaught_exception_handler _Nullable handler);

/**
 * @brief Sets the forwarding handler for unimplemented methods.
 *
 * @param forward The forwarding handler for regular methods
 * @param stretForward The forwarding handler for methods using the struct
 *		       return ABI
 */
extern void objc_setForwardHandler(IMP _Nullable forward,
    IMP _Nullable stretForward);

/**
 * @brief Sets the handler for mutations during enumeration.
 *
 * @param handler The handler for mutations during enumeration
 */
extern void objc_setEnumerationMutationHandler(
    objc_enumeration_mutation_handler _Nullable handler);

/**
 * @brief Constructs an instance of the specified class in the specified array
 *	  of bytes.
 *
 * @param class_ The class of which to construct an instance
 * @param bytes An array of bytes of at least the length of the instance size.

Modified src/runtime/amiga-funcarray.inc from [674e168c3f] to [4a87a7ea0f].

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

/* This file is automatically generated from 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,







|







9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

/* 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,
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
(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_exit,
(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,







|







75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
(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,

Modified src/runtime/amiga-glue.h from [51945d63f3] to [f6e0849e8b].

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

/* This file is automatically generated from library.xml */

#import "ObjFWRT.h"
#import "private.h"

#ifdef OF_AMIGAOS_M68K
# define PPC_PARAMS(...) (void)
# define M68K_ARG(type, name, reg)		\







|







9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

/* 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)		\
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
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_t glue_objc_setUncaughtExceptionHandler PPC_PARAMS(objc_uncaught_exception_handler_t _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_t _Nullable hadler);
extern id _Nullable glue_objc_constructInstance PPC_PARAMS(Class _Nullable class, void *_Nullable bytes);
extern void glue_objc_exit(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);







|

|

|







84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
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);

Modified src/runtime/amiga-glue.m from [fef86ecf8c] to [f5c525c10e].

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

/* This file is automatically generated from library.xml */

#include "config.h"

#import "amiga-glue.h"

#ifdef OF_MORPHOS
/* All __saveds functions in this file need to use the SysV ABI */







|







9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

/* 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 */
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
{
	M68K_ARG(Protocol *_Nonnull, protocol1, a0)
	M68K_ARG(Protocol *_Nonnull, protocol2, a1)

	return protocol_conformsToProtocol(protocol1, protocol2);
}

_Nullable objc_uncaught_exception_handler_t __saveds
glue_objc_setUncaughtExceptionHandler PPC_PARAMS(objc_uncaught_exception_handler_t _Nullable handler)
{
	M68K_ARG(objc_uncaught_exception_handler_t _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_t _Nullable hadler)
{
	M68K_ARG(objc_enumeration_mutation_handler_t _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_exit(void)
{
	objc_exit();
}

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)







|
|

|














|

|














|

|







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

Renamed and modified src/runtime/library.xml [99fa55d924] to src/runtime/amiga-library.xml [f6565586a9].

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
    <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_t'>
    <argument name='handler' type='objc_uncaught_exception_handler_t _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_t _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_exit'/>
  <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>







|
|







|






|







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

Deleted src/runtime/amigaos3.sfd version [27d28cf09f].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
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
==base _ObjFWRTBase
==basetype struct Library *
==libname objfwrt68k.library
==bias 30
==public
* The following function is only for the linklib.
bool glue_objc_init(unsigned int version, struct objc_libc *libc)(d0,a0)
void glue___objc_exec_class(struct objc_module *_Nonnull module)(a0)
IMP _Nonnull glue_objc_msg_lookup(id _Nullable object, SEL _Nonnull selector)(a0,a1)
IMP _Nonnull glue_objc_msg_lookup_stret(id _Nullable object, SEL _Nonnull selector)(a0,a1)
IMP _Nonnull glue_objc_msg_lookup_super(struct objc_super *_Nonnull super, SEL _Nonnull selector)(a0,a1)
IMP _Nonnull glue_objc_msg_lookup_super_stret(struct objc_super *_Nonnull super, SEL _Nonnull selector)(a0,a1)
Class _Nullable glue_objc_lookUpClass(const char *_Nonnull name)(a0)
Class _Nullable glue_objc_getClass(const char *_Nonnull name)(a0)
Class _Nonnull glue_objc_getRequiredClass(const char *_Nonnull name)(a0)
Class _Nullable glue_objc_lookup_class(const char *_Nonnull name)(a0)
Class _Nonnull glue_objc_get_class(const char *_Nonnull name)(a0)
void glue_objc_exception_throw(id _Nonnull object)(a0)
int glue_objc_sync_enter(id _Nullable object)(a0)
int glue_objc_sync_exit(id _Nullable object)(a0)
id glue_objc_getProperty(id _Nonnull self, SEL _Nonnull _cmd, ptrdiff_t offset, bool atomic)(a0,a1,d0,d1)
void glue_objc_setProperty(id _Nonnull self, SEL _Nonnull _cmd, ptrdiff_t offset, id value, bool atomic, signed char copy)(a0,a1,d0,a2,d1,d2)
void glue_objc_getPropertyStruct(void *_Nonnull dest, const void *_Nonnull src, ptrdiff_t size, bool atomic, bool strong)(a0,a1,d0,d1,d2)
void glue_objc_setPropertyStruct(void *_Nonnull dest, const void *_Nonnull src, ptrdiff_t size, bool atomic, bool strong)(a0,a1,d0,d1,d2)
void glue_objc_enumerationMutation(id _Nonnull object)(a0)
int glue___gnu_objc_personality(int version, int actions, uint64_t *_Nonnull exClass, void *_Nonnull ex, void *_Nonnull ctx)(d0,d1,d2,a0,a1)
id _Nullable glue_objc_retain(id _Nullable object)(a0)
id _Nullable glue_objc_retainBlock(id _Nullable block)(a0)
id _Nullable glue_objc_retainAutorelease(id _Nullable object)(a0)
void glue_objc_release(id _Nullable object)(a0)
id _Nullable glue_objc_autorelease(id _Nullable object)(a0)
id _Nullable glue_objc_autoreleaseReturnValue(id _Nullable object)(a0)
id _Nullable glue_objc_retainAutoreleaseReturnValue(id _Nullable object)(a0)
id _Nullable glue_objc_retainAutoreleasedReturnValue(id _Nullable object)(a0)
id _Nullable glue_objc_storeStrong(id _Nullable *_Nonnull object, id _Nullable value)(a0,a1)
id _Nullable glue_objc_storeWeak(id _Nullable *_Nonnull object, id _Nullable value)(a0,a1)
id _Nullable glue_objc_loadWeakRetained(id _Nullable *_Nonnull object)(a0)
id _Nullable glue_objc_initWeak(id _Nullable *_Nonnull object, id _Nullable value)(a0,a1)
void glue_objc_destroyWeak(id _Nullable *_Nonnull object)(a0)
id _Nullable glue_objc_loadWeak(id _Nullable *_Nonnull object)(a0)
void glue_objc_copyWeak(id _Nullable *_Nonnull dest, id _Nullable *_Nonnull src)(a0,a1)
void glue_objc_moveWeak(id _Nullable *_Nonnull dest, id _Nullable *_Nonnull src)(a0,a1)
SEL _Nonnull glue_sel_registerName(const char *_Nonnull name)(a0)
const char *_Nonnull glue_sel_getName(SEL _Nonnull selector)(a0)
bool glue_sel_isEqual(SEL _Nonnull selector1, SEL _Nonnull selector2)(a0,a1)
Class _Nonnull glue_objc_allocateClassPair(Class _Nullable superclass, const char *_Nonnull name, size_t extraBytes)(a0,a1,d0)
void glue_objc_registerClassPair(Class _Nonnull class_)(a0)
unsigned int glue_objc_getClassList(Class _Nonnull *_Nullable buffer, unsigned int count)(a0,d0)
Class _Nonnull *_Nonnull glue_objc_copyClassList(unsigned int *_Nullable length)(a0)
bool glue_class_isMetaClass(Class _Nullable class_)(a0)
const char *_Nullable glue_class_getName(Class _Nullable class_)(a0)
Class _Nullable glue_class_getSuperclass(Class _Nullable class_)(a0)
unsigned long glue_class_getInstanceSize(Class _Nullable class_)(a0)
bool glue_class_respondsToSelector(Class _Nullable class_, SEL _Nonnull selector)(a0,a1)
bool glue_class_conformsToProtocol(Class _Nullable class_, Protocol *_Nonnull p)(a0,a1)
IMP _Nullable glue_class_getMethodImplementation(Class _Nullable class_, SEL _Nonnull selector)(a0,a1)
IMP _Nullable glue_class_getMethodImplementation_stret(Class _Nullable class_, SEL _Nonnull selector)(a0,a1)
Method _Nullable glue_class_getInstanceMethod(Class _Nullable class_, SEL _Nonnull selector)(a0,a1)
bool glue_class_addMethod(Class _Nonnull class_, SEL _Nonnull selector, IMP _Nonnull implementation, const char *_Nullable typeEncoding)(a0,a1,a2,a3)
IMP _Nullable glue_class_replaceMethod(Class _Nonnull class_, SEL _Nonnull selector, IMP _Nonnull implementation, const char *_Nullable typeEncoding)(a0,a1,a2,a3)
Class _Nullable glue_object_getClass(id _Nullable object)(a0)
Class _Nullable glue_object_setClass(id _Nullable object, Class _Nonnull class_)(a0,a1)
const char *_Nullable glue_object_getClassName(id _Nullable object)(a0)
const char *_Nonnull glue_protocol_getName(Protocol *_Nonnull protocol)(a0)
bool glue_protocol_isEqual(Protocol *_Nonnull protocol1, Protocol *_Nonnull protocol2)(a0,a1)
bool glue_protocol_conformsToProtocol(Protocol *_Nonnull protocol1, Protocol *_Nonnull protocol2)(a0,a1)
_Nullable objc_uncaught_exception_handler_t glue_objc_setUncaughtExceptionHandler(objc_uncaught_exception_handler_t _Nullable handler)(a0)
void glue_objc_setForwardHandler(IMP _Nullable forward, IMP _Nullable stretForward)(a0,a1)
void glue_objc_setEnumerationMutationHandler(objc_enumeration_mutation_handler_t _Nullable handler)(a0)
id _Nullable glue_objc_constructInstance(Class _Nullable class_, void *_Nullable bytes)(a0,a1)
void glue_objc_exit(void)()
Ivar _Nullable *_Nullable glue_class_copyIvarList(Class _Nullable class_, unsigned int *_Nullable outCount)(a0,a1)
const char *_Nonnull glue_ivar_getName(Ivar _Nonnull ivar)(a0)
const char *_Nonnull glue_ivar_getTypeEncoding(Ivar _Nonnull ivar)(a0)
ptrdiff_t glue_ivar_getOffset(Ivar _Nonnull ivar)(a0)
Method _Nullable *_Nullable glue_class_copyMethodList(Class _Nullable class_, unsigned int *_Nullable outCount)(a0,a1)
SEL _Nonnull glue_method_getName(Method _Nonnull method)(a0)
const char *_Nullable glue_method_getTypeEncoding(Method _Nonnull method)(a0)
objc_property_t _Nullable *_Nullable glue_class_copyPropertyList(Class _Nullable class_, unsigned int *_Nullable outCount)(a0,a1)
const char *_Nonnull glue_property_getName(objc_property_t _Nonnull property)(a0)
char *_Nullable glue_property_copyAttributeValue(objc_property_t _Nonnull property, const char *_Nonnull name)(a0,a1)
void *_Nullable glue_objc_destructInstance(id _Nullable object)(a0)
void *_Null_unspecified glue_objc_autoreleasePoolPush(void)()
void glue_objc_autoreleasePoolPop(void *_Null_unspecified pool)(a0)
id _Nullable glue__objc_rootAutorelease(id _Nullable object)(a0)
* The following functions are private! Don't use!
struct objc_hashtable *_Nonnull glue_objc_hashtable_new(objc_hashtable_hash_func hash, objc_hashtable_equal_func equal, uint32_t size)(a0,a1,d0)
void glue_objc_hashtable_set(struct objc_hashtable *_Nonnull table, const void *_Nonnull key, const void *_Nonnull object)(a0,a1,a2)
void *_Nullable glue_objc_hashtable_get(struct objc_hashtable *_Nonnull table, const void *_Nonnull key)(a0,a1)
void glue_objc_hashtable_delete(struct objc_hashtable *_Nonnull table, const void *_Nonnull key)(a0,a1)
void glue_objc_hashtable_free(struct objc_hashtable *_Nonnull table)(a0)
* Public functions again
void glue_objc_setTaggedPointerSecret(uintptr_t secret)(d0)
int glue_objc_registerTaggedPointerClass(Class _Nonnull class_)(a0)
bool glue_object_isTaggedPointer(id _Nullable object)(a0)
uintptr_t glue_object_getTaggedPointerValue(id _Nonnull object)(a0)
id _Nullable glue_objc_createTaggedPointer(int class_, uintptr_t value)(d0,d1)
==end
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<




































































































































































































Modified src/runtime/arc.m from [8ccdb1ee10] to [1147559114].

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

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

struct weakref {
	id **locations;
	size_t count;
};

static struct objc_hashtable *hashtable;
#ifdef OF_HAVE_THREADS
static OFSpinlock spinlock;







|







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

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

struct WeakRef {
	id **locations;
	size_t count;
};

static struct objc_hashtable *hashtable;
#ifdef OF_HAVE_THREADS
static OFSpinlock spinlock;
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127

	return value;
}

id
objc_storeWeak(id *object, id value)
{
	struct weakref *old;

#ifdef OF_HAVE_THREADS
	if (OFSpinlockLock(&spinlock) != 0)
		OBJC_ERROR("Failed to lock spinlock!");
#endif

	if (*object != nil &&







|







113
114
115
116
117
118
119
120
121
122
123
124
125
126
127

	return value;
}

id
objc_storeWeak(id *object, id value)
{
	struct WeakRef *old;

#ifdef OF_HAVE_THREADS
	if (OFSpinlockLock(&spinlock) != 0)
		OBJC_ERROR("Failed to lock spinlock!");
#endif

	if (*object != nil &&
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
				break;
			}
		}
	}

	if (value != nil && class_respondsToSelector(object_getClass(value),
	    @selector(allowsWeakReference)) && [value allowsWeakReference]) {
		struct weakref *ref = objc_hashtable_get(hashtable, value);

		if (ref == NULL) {
			if ((ref = calloc(1, sizeof(*ref))) == NULL)
				OBJC_ERROR("Not enough memory to allocate weak "
				    "reference!");

			objc_hashtable_set(hashtable, value, ref);







|







151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
				break;
			}
		}
	}

	if (value != nil && class_respondsToSelector(object_getClass(value),
	    @selector(allowsWeakReference)) && [value allowsWeakReference]) {
		struct WeakRef *ref = objc_hashtable_get(hashtable, value);

		if (ref == NULL) {
			if ((ref = calloc(1, sizeof(*ref))) == NULL)
				OBJC_ERROR("Not enough memory to allocate weak "
				    "reference!");

			objc_hashtable_set(hashtable, value, ref);
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
	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 &&







|







184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
	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 &&
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
{
	objc_release(objc_initWeak(dest, objc_loadWeakRetained(src)));
}

void
objc_moveWeak(id *dest, id *src)
{
	struct weakref *ref;

#ifdef OF_HAVE_THREADS
	if (OFSpinlockLock(&spinlock) != 0)
		OBJC_ERROR("Failed to lock spinlock!");
#endif

	if (*src != nil &&







|







235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
{
	objc_release(objc_initWeak(dest, objc_loadWeakRetained(src)));
}

void
objc_moveWeak(id *dest, id *src)
{
	struct WeakRef *ref;

#ifdef OF_HAVE_THREADS
	if (OFSpinlockLock(&spinlock) != 0)
		OBJC_ERROR("Failed to lock spinlock!");
#endif

	if (*src != nil &&
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
#ifdef OF_HAVE_THREADS
	if (OFSpinlockUnlock(&spinlock) != 0)
		OBJC_ERROR("Failed to unlock spinlock!");
#endif
}

void
objc_zero_weak_references(id value)
{
	struct weakref *ref;

#ifdef OF_HAVE_THREADS
	if (OFSpinlockLock(&spinlock) != 0)
		OBJC_ERROR("Failed to lock spinlock!");
#endif

	if ((ref = objc_hashtable_get(hashtable, value)) != NULL) {







|

|







262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
#ifdef OF_HAVE_THREADS
	if (OFSpinlockUnlock(&spinlock) != 0)
		OBJC_ERROR("Failed to unlock spinlock!");
#endif
}

void
objc_zeroWeakReferences(id value)
{
	struct WeakRef *ref;

#ifdef OF_HAVE_THREADS
	if (OFSpinlockLock(&spinlock) != 0)
		OBJC_ERROR("Failed to lock spinlock!");
#endif

	if ((ref = objc_hashtable_get(hashtable, value)) != NULL) {

Modified src/runtime/autorelease.m from [2b09f19f70] to [4890f3bc38].

31
32
33
34
35
36
37





38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56

57
58
59
60
61
62
63
#endif

#ifndef OF_OBJFW_RUNTIME
@interface DummyObject
- (void)release;
@end
#endif






#if defined(OF_HAVE_COMPILER_TLS)
static thread_local id *objects = NULL;
static thread_local uintptr_t count = 0;
static thread_local uintptr_t size = 0;
#elif defined(OF_HAVE_THREADS)
static OFTLSKey objectsKey, countKey, sizeKey;
#else
static id *objects = NULL;
static uintptr_t count = 0;
static uintptr_t size = 0;
#endif

#if !defined(OF_HAVE_COMPILER_TLS) && defined(OF_HAVE_THREADS)
OF_CONSTRUCTOR()
{
	OFEnsure(OFTLSKeyNew(&objectsKey) == 0);
	OFEnsure(OFTLSKeyNew(&countKey) == 0);
	OFEnsure(OFTLSKeyNew(&sizeKey) == 0);

}
#endif

void *
objc_autoreleasePoolPush()
{
#if !defined(OF_HAVE_COMPILER_TLS) && defined(OF_HAVE_THREADS)







>
>
>
>
>
















|
<
|
>







31
32
33
34
35
36
37
38
39
40
41
42
43
44
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

#ifndef OF_OBJFW_RUNTIME
@interface DummyObject
- (void)release;
@end
#endif

#ifndef OBJC_ERROR
/* This is also used with old Apple runtimes that lack autorelease pools. */
# define OBJC_ERROR(...) abort()
#endif

#if defined(OF_HAVE_COMPILER_TLS)
static thread_local id *objects = NULL;
static thread_local uintptr_t count = 0;
static thread_local uintptr_t size = 0;
#elif defined(OF_HAVE_THREADS)
static OFTLSKey objectsKey, countKey, sizeKey;
#else
static id *objects = NULL;
static uintptr_t count = 0;
static uintptr_t size = 0;
#endif

#if !defined(OF_HAVE_COMPILER_TLS) && defined(OF_HAVE_THREADS)
OF_CONSTRUCTOR()
{
	if (OFTLSKeyNew(&objectsKey) != 0 || OFTLSKeyNew(&countKey) != 0 ||

	    OFTLSKeyNew(&sizeKey) != 0)
		OBJC_ERROR("Failed to create TLS keys!");
}
#endif

void *
objc_autoreleasePoolPush()
{
#if !defined(OF_HAVE_COMPILER_TLS) && defined(OF_HAVE_THREADS)
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

	if (freeMem) {
		free(objects);
		objects = NULL;
#if defined(OF_HAVE_COMPILER_TLS) || !defined(OF_HAVE_THREADS)
		size = 0;
#else
		OFEnsure(OFTLSKeySet(objectsKey, objects) == 0);
		OFEnsure(OFTLSKeySet(sizeKey, (void *)0) == 0);

#endif
	}

#if !defined(OF_HAVE_COMPILER_TLS) && defined(OF_HAVE_THREADS)
	OFEnsure(OFTLSKeySet(countKey, (void *)count) == 0);

#endif
}

id
_objc_rootAutorelease(id object)
{
#if !defined(OF_HAVE_COMPILER_TLS) && defined(OF_HAVE_THREADS)
	id *objects = OFTLSKeyGet(objectsKey);
	uintptr_t count = (uintptr_t)OFTLSKeyGet(countKey);
	uintptr_t size = (uintptr_t)OFTLSKeyGet(sizeKey);
#endif

	if (count >= size) {
		if (size == 0)
			size = 16;
		else
			size *= 2;

		OFEnsure((objects =
		    realloc(objects, size * sizeof(id))) != NULL);


#if !defined(OF_HAVE_COMPILER_TLS) && defined(OF_HAVE_THREADS)
		OFEnsure(OFTLSKeySet(objectsKey, objects) == 0);
		OFEnsure(OFTLSKeySet(sizeKey, (void *)size) == 0);

#endif
	}

	objects[count++] = object;

#if !defined(OF_HAVE_COMPILER_TLS) && defined(OF_HAVE_THREADS)
	OFEnsure(OFTLSKeySet(countKey, (void *)count) == 0);

#endif

	return object;
}







|
|
>




|
>


















<
|
>


|
|
>






|
>




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

	if (freeMem) {
		free(objects);
		objects = NULL;
#if defined(OF_HAVE_COMPILER_TLS) || !defined(OF_HAVE_THREADS)
		size = 0;
#else
		if (OFTLSKeySet(objectsKey, objects) != 0 ||
		    OFTLSKeySet(sizeKey, (void *)0) != 0)
			OBJC_ERROR("Failed to set TLS key!");
#endif
	}

#if !defined(OF_HAVE_COMPILER_TLS) && defined(OF_HAVE_THREADS)
	if (OFTLSKeySet(countKey, (void *)count) != 0)
		OBJC_ERROR("Failed to set TLS key!");
#endif
}

id
_objc_rootAutorelease(id object)
{
#if !defined(OF_HAVE_COMPILER_TLS) && defined(OF_HAVE_THREADS)
	id *objects = OFTLSKeyGet(objectsKey);
	uintptr_t count = (uintptr_t)OFTLSKeyGet(countKey);
	uintptr_t size = (uintptr_t)OFTLSKeyGet(sizeKey);
#endif

	if (count >= size) {
		if (size == 0)
			size = 16;
		else
			size *= 2;


		if ((objects = realloc(objects, size * sizeof(id))) == NULL)
			OBJC_ERROR("Failed to resize autorelease pool!");

#if !defined(OF_HAVE_COMPILER_TLS) && defined(OF_HAVE_THREADS)
		if (OFTLSKeySet(objectsKey, objects) != 0 ||
		    OFTLSKeySet(sizeKey, (void *)size) != 0)
			OBJC_ERROR("Failed to set TLS key!");
#endif
	}

	objects[count++] = object;

#if !defined(OF_HAVE_COMPILER_TLS) && defined(OF_HAVE_THREADS)
	if (OFTLSKeySet(countKey, (void *)count) != 0)
		OBJC_ERROR("Failed to set TLS key!");
#endif

	return object;
}

Modified src/runtime/category.m from [e672c2edf4] to [5b97638d56].

28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
registerSelectors(struct objc_category *category)
{
	struct objc_method_list *iter;
	unsigned int i;

	for (iter = category->instanceMethods; iter != NULL; iter = iter->next)
		for (i = 0; i < iter->count; i++)
			objc_register_selector(&iter->methods[i].selector);

	for (iter = category->classMethods; iter != NULL; iter = iter->next)
		for (i = 0; i < iter->count; i++)
			objc_register_selector(&iter->methods[i].selector);
}

static void
registerCategory(struct objc_category *category)
{
	struct objc_category **categories;
	Class class = objc_classname_to_class(category->className, false);

	if (categoriesMap == NULL)
		categoriesMap = objc_hashtable_new(
		    objc_hash_string, objc_equal_string, 2);

	categories = (struct objc_category **)objc_hashtable_get(
	    categoriesMap, category->className);

	if (categories != NULL) {
		struct objc_category **newCategories;
		size_t i;







|



|






|



|







28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
registerSelectors(struct objc_category *category)
{
	struct objc_method_list *iter;
	unsigned int i;

	for (iter = category->instanceMethods; iter != NULL; iter = iter->next)
		for (i = 0; i < iter->count; i++)
			objc_registerSelector(&iter->methods[i].selector);

	for (iter = category->classMethods; iter != NULL; iter = iter->next)
		for (i = 0; i < iter->count; i++)
			objc_registerSelector(&iter->methods[i].selector);
}

static void
registerCategory(struct objc_category *category)
{
	struct objc_category **categories;
	Class class = objc_classnameToClass(category->className, false);

	if (categoriesMap == NULL)
		categoriesMap = objc_hashtable_new(
		    objc_string_hash, objc_string_equal, 2);

	categories = (struct objc_category **)objc_hashtable_get(
	    categoriesMap, category->className);

	if (categories != NULL) {
		struct objc_category **newCategories;
		size_t i;
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

		newCategories[i] = category;
		newCategories[i + 1] = NULL;
		objc_hashtable_set(categoriesMap, category->className,
		    newCategories);

		if (class != Nil && class->info & OBJC_CLASS_INFO_SETUP) {
			objc_update_dtable(class);
			objc_update_dtable(class->isa);
		}

		return;
	}

	if ((categories = malloc(2 * sizeof(*categories))) == NULL)
		OBJC_ERROR("Not enough memory for category %s of class %s!\n",
		    category->categoryName, category->className);

	categories[0] = category;
	categories[1] = NULL;
	objc_hashtable_set(categoriesMap, category->className, categories);

	if (class != Nil && class->info & OBJC_CLASS_INFO_SETUP) {
		objc_update_dtable(class);
		objc_update_dtable(class->isa);
	}
}

void
objc_register_all_categories(struct objc_symtab *symtab)
{
	struct objc_category **categories =
	    (struct objc_category **)symtab->defs + symtab->classDefsCount;

	for (size_t i = 0; i < symtab->categoryDefsCount; i++) {
		registerSelectors(categories[i]);
		registerCategory(categories[i]);
	}
}

struct objc_category **
objc_categories_for_class(Class class)
{
	if (categoriesMap == NULL)
		return NULL;

	return (struct objc_category **)objc_hashtable_get(categoriesMap,
	    class->name);
}

void
objc_unregister_all_categories(void)
{
	if (categoriesMap == NULL)
		return;

	for (uint32_t i = 0; i < categoriesMap->size; i++)
		if (categoriesMap->data[i] != NULL)
			free((void *)categoriesMap->data[i]->object);

	objc_hashtable_free(categoriesMap);
	categoriesMap = NULL;
}







|
|














|
|




|











|









|











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

		newCategories[i] = category;
		newCategories[i + 1] = NULL;
		objc_hashtable_set(categoriesMap, category->className,
		    newCategories);

		if (class != Nil && class->info & OBJC_CLASS_INFO_SETUP) {
			objc_updateDTable(class);
			objc_updateDTable(class->isa);
		}

		return;
	}

	if ((categories = malloc(2 * sizeof(*categories))) == NULL)
		OBJC_ERROR("Not enough memory for category %s of class %s!\n",
		    category->categoryName, category->className);

	categories[0] = category;
	categories[1] = NULL;
	objc_hashtable_set(categoriesMap, category->className, categories);

	if (class != Nil && class->info & OBJC_CLASS_INFO_SETUP) {
		objc_updateDTable(class);
		objc_updateDTable(class->isa);
	}
}

void
objc_registerAllCategories(struct objc_symtab *symtab)
{
	struct objc_category **categories =
	    (struct objc_category **)symtab->defs + symtab->classDefsCount;

	for (size_t i = 0; i < symtab->categoryDefsCount; i++) {
		registerSelectors(categories[i]);
		registerCategory(categories[i]);
	}
}

struct objc_category **
objc_categoriesForClass(Class class)
{
	if (categoriesMap == NULL)
		return NULL;

	return (struct objc_category **)objc_hashtable_get(categoriesMap,
	    class->name);
}

void
objc_unregisterAllCategories(void)
{
	if (categoriesMap == NULL)
		return;

	for (uint32_t i = 0; i < categoriesMap->size; i++)
		if (categoriesMap->data[i] != NULL)
			free((void *)categoriesMap->data[i]->object);

	objc_hashtable_free(categoriesMap);
	categoriesMap = NULL;
}

Modified src/runtime/class.m from [93b6de8609] to [8556b52111].

32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
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
static struct objc_sparsearray *fastPath = NULL;

static void
registerClass(Class class)
{
	if (classes == NULL)
		classes = objc_hashtable_new(
		    objc_hash_string, objc_equal_string, 2);

	objc_hashtable_set(classes, class->name, class);

	if (emptyDTable == NULL)
		emptyDTable = objc_dtable_new();

	class->DTable = emptyDTable;
	class->isa->DTable = emptyDTable;

	if (strcmp(class->name, "Protocol") != 0)
		classesCount++;
}

bool
class_registerAlias_np(Class class, const char *name)
{
	objc_global_mutex_lock();

	if (classes == NULL) {
		objc_global_mutex_unlock();

		return NO;
	}

	objc_hashtable_set(classes, name, (Class)((uintptr_t)class | 1));

	objc_global_mutex_unlock();

	return YES;
}

static void
registerSelectors(Class class)
{
	struct objc_method_list *iter;
	unsigned int i;

	for (iter = class->methodList; iter != NULL; iter = iter->next)
		for (i = 0; i < iter->count; i++)
			objc_register_selector(&iter->methods[i].selector);
}

Class
objc_classname_to_class(const char *name, bool cache)
{
	Class class;

	if (classes == NULL)
		return Nil;

	/*







|






|
|








|


|






|












|



|







32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
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
static struct objc_sparsearray *fastPath = NULL;

static void
registerClass(Class class)
{
	if (classes == NULL)
		classes = objc_hashtable_new(
		    objc_string_hash, objc_string_equal, 2);

	objc_hashtable_set(classes, class->name, class);

	if (emptyDTable == NULL)
		emptyDTable = objc_dtable_new();

	class->dTable = emptyDTable;
	class->isa->dTable = emptyDTable;

	if (strcmp(class->name, "Protocol") != 0)
		classesCount++;
}

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

	for (iter = class->methodList; iter != NULL; iter = iter->next)
		for (i = 0; i < iter->count; i++)
			objc_registerSelector(&iter->methods[i].selector);
}

Class
objc_classnameToClass(const char *name, bool cache)
{
	Class class;

	if (classes == NULL)
		return 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
	if (cache && fastPath != NULL) {
		class = objc_sparsearray_get(fastPath, (uintptr_t)name);

		if (class != Nil)
			return class;
	}

	objc_global_mutex_lock();

	class = (Class)((uintptr_t)objc_hashtable_get(classes, name) & ~1);

	if (cache && fastPath == NULL && --lookupsUntilFastPath == 0)
		fastPath = objc_sparsearray_new(sizeof(uintptr_t));

	if (cache && fastPath != NULL)
		objc_sparsearray_set(fastPath, (uintptr_t)name, class);

	objc_global_mutex_unlock();

	return class;
}

static void
callSelector(Class class, SEL selector)
{







|









|







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
	if (cache && fastPath != NULL) {
		class = objc_sparsearray_get(fastPath, (uintptr_t)name);

		if (class != Nil)
			return class;
	}

	objc_globalMutex_lock();

	class = (Class)((uintptr_t)objc_hashtable_get(classes, name) & ~1);

	if (cache && fastPath == NULL && --lookupsUntilFastPath == 0)
		fastPath = objc_sparsearray_new(sizeof(uintptr_t));

	if (cache && fastPath != NULL)
		objc_sparsearray_set(fastPath, (uintptr_t)name, class);

	objc_globalMutex_unlock();

	return class;
}

static void
callSelector(Class class, SEL 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

	callSelector(class, loadSel);

	class->info |= OBJC_CLASS_INFO_LOADED;
}

void
objc_update_dtable(Class class)
{
	struct objc_category **categories;

	if (!(class->info & OBJC_CLASS_INFO_DTABLE))
		return;

	if (class->DTable == emptyDTable)
		class->DTable = objc_dtable_new();

	if (class->superclass != Nil)
		objc_dtable_copy(class->DTable, class->superclass->DTable);

	for (struct objc_method_list *methodList = class->methodList;
	    methodList != NULL; methodList = methodList->next)
		for (unsigned int i = 0; i < methodList->count; i++)
			objc_dtable_set(class->DTable,
			    (uint32_t)methodList->methods[i].selector.UID,
			    methodList->methods[i].implementation);

	if ((categories = objc_categories_for_class(class)) != NULL) {
		for (unsigned int i = 0; categories[i] != NULL; i++) {
			struct objc_method_list *methodList =
			    (class->info & OBJC_CLASS_INFO_CLASS
			    ? categories[i]->instanceMethods
			    : categories[i]->classMethods);

			for (; methodList != NULL;
			    methodList = methodList->next)
				for (unsigned int j = 0;
				    j < methodList->count; j++)
					objc_dtable_set(class->DTable,
					    (uint32_t)methodList->methods[j]
					    .selector.UID,
					    methodList->methods[j]
					    .implementation);
		}
	}

	if (class->subclassList != NULL)
		for (Class *iter = class->subclassList; *iter != NULL; iter++)
			objc_update_dtable(*iter);
}

static void
addSubclass(Class class)
{
	size_t i;








|






|
|


|




|



|










|









|







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

	callSelector(class, loadSel);

	class->info |= OBJC_CLASS_INFO_LOADED;
}

void
objc_updateDTable(Class class)
{
	struct objc_category **categories;

	if (!(class->info & OBJC_CLASS_INFO_DTABLE))
		return;

	if (class->dTable == emptyDTable)
		class->dTable = objc_dtable_new();

	if (class->superclass != Nil)
		objc_dtable_copy(class->dTable, class->superclass->dTable);

	for (struct objc_method_list *methodList = class->methodList;
	    methodList != NULL; methodList = methodList->next)
		for (unsigned int i = 0; i < methodList->count; i++)
			objc_dtable_set(class->dTable,
			    (uint32_t)methodList->methods[i].selector.UID,
			    methodList->methods[i].implementation);

	if ((categories = objc_categoriesForClass(class)) != NULL) {
		for (unsigned int i = 0; categories[i] != NULL; i++) {
			struct objc_method_list *methodList =
			    (class->info & OBJC_CLASS_INFO_CLASS
			    ? categories[i]->instanceMethods
			    : categories[i]->classMethods);

			for (; methodList != NULL;
			    methodList = methodList->next)
				for (unsigned int j = 0;
				    j < methodList->count; j++)
					objc_dtable_set(class->dTable,
					    (uint32_t)methodList->methods[j]
					    .selector.UID,
					    methodList->methods[j]
					    .implementation);
		}
	}

	if (class->subclassList != NULL)
		for (Class *iter = class->subclassList; *iter != NULL; iter++)
			objc_updateDTable(*iter);
}

static void
addSubclass(Class class)
{
	size_t i;

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
		}
	} else
		for (unsigned int i = 0; i < class->ivars->count; i++)
			*class->ivarOffsets[i] = class->ivars->ivars[i].offset;
}

static void
setupClass(Class class)
{
	const char *superclassName;

	if (class->info & OBJC_CLASS_INFO_SETUP)
		return;

	superclassName = (const char *)class->superclass;
	if (superclassName != NULL) {
		Class super = objc_classname_to_class(superclassName, false);
		Class rootClass;

		if (super == Nil)
			return;

		setupClass(super);

		if (!(super->info & OBJC_CLASS_INFO_SETUP))
			return;

		/*
		 * GCC sets class->isa->isa to the name of the root class,
		 * while Clang just sets it to Nil. Therefore always calculate







|








|





|







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
		}
	} else
		for (unsigned int i = 0; i < class->ivars->count; i++)
			*class->ivarOffsets[i] = class->ivars->ivars[i].offset;
}

static void
setUpClass(Class class)
{
	const char *superclassName;

	if (class->info & OBJC_CLASS_INFO_SETUP)
		return;

	superclassName = (const char *)class->superclass;
	if (superclassName != NULL) {
		Class super = objc_classnameToClass(superclassName, false);
		Class rootClass;

		if (super == Nil)
			return;

		setUpClass(super);

		if (!(super->info & OBJC_CLASS_INFO_SETUP))
			return;

		/*
		 * GCC sets class->isa->isa to the name of the root class,
		 * while Clang just sets it to Nil. Therefore always calculate
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
	 */
	if (class->info & OBJC_CLASS_INFO_INITIALIZED)
		return;

	class->info |= OBJC_CLASS_INFO_DTABLE;
	class->isa->info |= OBJC_CLASS_INFO_DTABLE;

	objc_update_dtable(class);
	objc_update_dtable(class->isa);

	/*
	 * Set it first to prevent calling it recursively due to message sends
	 * in the initialize method
	 */
	class->info |= OBJC_CLASS_INFO_INITIALIZED;
	class->isa->info |= OBJC_CLASS_INFO_INITIALIZED;







|
|







347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
	 */
	if (class->info & OBJC_CLASS_INFO_INITIALIZED)
		return;

	class->info |= OBJC_CLASS_INFO_DTABLE;
	class->isa->info |= OBJC_CLASS_INFO_DTABLE;

	objc_updateDTable(class);
	objc_updateDTable(class->isa);

	/*
	 * Set it first to prevent calling it recursively due to message sends
	 * in the initialize method
	 */
	class->info |= OBJC_CLASS_INFO_INITIALIZED;
	class->isa->info |= OBJC_CLASS_INFO_INITIALIZED;
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
		    objc_msg_lookup(class, initializeSel);

		initialize(class, initializeSel);
	}
}

void
objc_initialize_class(Class class)
{
	if (class->info & OBJC_CLASS_INFO_INITIALIZED)
		return;

	objc_global_mutex_lock();

	/*
	 * It's possible that two threads try to initialize a class at the same
	 * time. Make sure that the thread which held the lock did not already
	 * initialize it.
	 */
	if (class->info & OBJC_CLASS_INFO_INITIALIZED) {
		objc_global_mutex_unlock();
		return;
	}

	setupClass(class);

	if (!(class->info & OBJC_CLASS_INFO_SETUP)) {
		objc_global_mutex_unlock();
		return;
	}

	initializeClass(class);

	objc_global_mutex_unlock();
}

static void
processLoadQueue()
{
	for (size_t i = 0; i < loadQueueCount; i++) {
		setupClass(loadQueue[i]);

		if (loadQueue[i]->info & OBJC_CLASS_INFO_SETUP) {
			callLoad(loadQueue[i]);

			loadQueueCount--;

			if (loadQueueCount == 0) {







|




|







|



|


|





|






|







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
		    objc_msg_lookup(class, initializeSel);

		initialize(class, initializeSel);
	}
}

void
objc_initializeClass(Class class)
{
	if (class->info & OBJC_CLASS_INFO_INITIALIZED)
		return;

	objc_globalMutex_lock();

	/*
	 * It's possible that two threads try to initialize a class at the same
	 * time. Make sure that the thread which held the lock did not already
	 * initialize it.
	 */
	if (class->info & OBJC_CLASS_INFO_INITIALIZED) {
		objc_globalMutex_unlock();
		return;
	}

	setUpClass(class);

	if (!(class->info & OBJC_CLASS_INFO_SETUP)) {
		objc_globalMutex_unlock();
		return;
	}

	initializeClass(class);

	objc_globalMutex_unlock();
}

static void
processLoadQueue()
{
	for (size_t i = 0; i < loadQueueCount; i++) {
		setUpClass(loadQueue[i]);

		if (loadQueue[i]->info & OBJC_CLASS_INFO_SETUP) {
			callLoad(loadQueue[i]);

			loadQueueCount--;

			if (loadQueueCount == 0) {
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
			if (loadQueue == NULL)
				OBJC_ERROR("Not enough memory for load queue!");
		}
	}
}

void
objc_register_all_classes(struct objc_symtab *symtab)
{
	for (uint16_t i = 0; i < symtab->classDefsCount; i++) {
		Class class = (Class)symtab->defs[i];

		registerClass(class);
		registerSelectors(class);
		registerSelectors(class->isa);
	}

	for (uint16_t i = 0; i < symtab->classDefsCount; i++) {
		Class class = (Class)symtab->defs[i];

		if (hasLoad(class)) {
			setupClass(class);

			if (class->info & OBJC_CLASS_INFO_SETUP)
				callLoad(class);
			else {
				loadQueue = realloc(loadQueue,
				    sizeof(Class) * (loadQueueCount + 1));








|













|







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
			if (loadQueue == NULL)
				OBJC_ERROR("Not enough memory for load queue!");
		}
	}
}

void
objc_registerAllClasses(struct objc_symtab *symtab)
{
	for (uint16_t i = 0; i < symtab->classDefsCount; i++) {
		Class class = (Class)symtab->defs[i];

		registerClass(class);
		registerSelectors(class);
		registerSelectors(class->isa);
	}

	for (uint16_t i = 0; i < symtab->classDefsCount; i++) {
		Class class = (Class)symtab->defs[i];

		if (hasLoad(class)) {
			setUpClass(class);

			if (class->info & OBJC_CLASS_INFO_SETUP)
				callLoad(class);
			else {
				loadQueue = realloc(loadQueue,
				    sizeof(Class) * (loadQueueCount + 1));

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

Class
objc_allocateClassPair(Class superclass, const char *name, size_t extraBytes)
{
	struct objc_class *class, *metaclass;
	Class iter, rootclass = Nil;

	if (extraBytes > LONG_MAX)
		OBJC_ERROR("extraBytes out of range!");

	if ((class = calloc(1, sizeof(*class))) == NULL ||
	    (metaclass = calloc(1, sizeof(*class))) == NULL)
		OBJC_ERROR("Not enough memory to allocate class pair for class "
		    "%s!", name);

	class->isa = metaclass;
	class->superclass = superclass;
	class->name = name;
	class->info = OBJC_CLASS_INFO_CLASS;
	class->instanceSize = (superclass != Nil ?
	    superclass->instanceSize : 0) + (long)extraBytes;







	for (iter = superclass; iter != Nil; iter = iter->superclass)
		rootclass = iter;

	metaclass->isa = (rootclass != Nil ? rootclass->isa : class);
	metaclass->superclass = (superclass != Nil ? superclass->isa : Nil);
	metaclass->name = name;
	metaclass->info = OBJC_CLASS_INFO_CLASS;
	metaclass->instanceSize = (superclass != Nil ?
	    superclass->isa->instanceSize : 0) + (long)extraBytes;

	return class;
}

void
objc_registerClassPair(Class class)
{
	objc_global_mutex_lock();

	registerClass(class);

	if (class->superclass != Nil) {
		addSubclass(class);
		addSubclass(class->isa);
	}

	class->info |= OBJC_CLASS_INFO_SETUP;
	class->isa->info |= OBJC_CLASS_INFO_SETUP;

	if (hasLoad(class))
		callLoad(class);
	else
		class->info |= OBJC_CLASS_INFO_LOADED;

	processLoadQueue();

	objc_global_mutex_unlock();
}

Class
objc_lookUpClass(const char *name)
{
	Class class;

	if ((class = objc_classname_to_class(name, true)) == NULL)
		return Nil;

	if (class->info & OBJC_CLASS_INFO_SETUP)
		return class;

	objc_global_mutex_lock();

	setupClass(class);

	objc_global_mutex_unlock();

	if (!(class->info & OBJC_CLASS_INFO_SETUP))
		return Nil;

	return class;
}








<
<
<










|
>
>
>
>
>
>

















|


















|







|





|

|

|







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

Class
objc_allocateClassPair(Class superclass, const char *name, size_t extraBytes)
{
	struct objc_class *class, *metaclass;
	Class iter, rootclass = Nil;




	if ((class = calloc(1, sizeof(*class))) == NULL ||
	    (metaclass = calloc(1, sizeof(*class))) == NULL)
		OBJC_ERROR("Not enough memory to allocate class pair for class "
		    "%s!", name);

	class->isa = metaclass;
	class->superclass = superclass;
	class->name = name;
	class->info = OBJC_CLASS_INFO_CLASS;
	class->instanceSize = (superclass != Nil ?
	    superclass->instanceSize : 0);

	if (extraBytes > LONG_MAX ||
	    LONG_MAX - class->instanceSize < (long)extraBytes)
		OBJC_ERROR("extraBytes too large!");

	class->instanceSize += (long)extraBytes;

	for (iter = superclass; iter != Nil; iter = iter->superclass)
		rootclass = iter;

	metaclass->isa = (rootclass != Nil ? rootclass->isa : class);
	metaclass->superclass = (superclass != Nil ? superclass->isa : Nil);
	metaclass->name = name;
	metaclass->info = OBJC_CLASS_INFO_CLASS;
	metaclass->instanceSize = (superclass != Nil ?
	    superclass->isa->instanceSize : 0) + (long)extraBytes;

	return class;
}

void
objc_registerClassPair(Class class)
{
	objc_globalMutex_lock();

	registerClass(class);

	if (class->superclass != Nil) {
		addSubclass(class);
		addSubclass(class->isa);
	}

	class->info |= OBJC_CLASS_INFO_SETUP;
	class->isa->info |= OBJC_CLASS_INFO_SETUP;

	if (hasLoad(class))
		callLoad(class);
	else
		class->info |= OBJC_CLASS_INFO_LOADED;

	processLoadQueue();

	objc_globalMutex_unlock();
}

Class
objc_lookUpClass(const char *name)
{
	Class class;

	if ((class = objc_classnameToClass(name, true)) == NULL)
		return Nil;

	if (class->info & OBJC_CLASS_INFO_SETUP)
		return class;

	objc_globalMutex_lock();

	setUpClass(class);

	objc_globalMutex_unlock();

	if (!(class->info & OBJC_CLASS_INFO_SETUP))
		return Nil;

	return class;
}

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
	return objc_getRequiredClass(name);
}

unsigned int
objc_getClassList(Class *buffer, unsigned int count)
{
	unsigned int j;
	objc_global_mutex_lock();

	if (buffer == NULL)
		return classesCount;

	if (classesCount < count)
		count = classesCount;

	j = 0;
	for (uint32_t i = 0; i < classes->size; i++) {
		void *class;

		if (j >= count) {
			objc_global_mutex_unlock();
			return j;
		}

		if (classes->data[i] == NULL)
			continue;

		if (strcmp(classes->data[i]->key, "Protocol") == 0)
			continue;

		class = (Class)classes->data[i]->object;

		if (class == Nil || (uintptr_t)class & 1)
			continue;

		buffer[j++] = class;
	}

	objc_global_mutex_unlock();

	return j;
}

Class *
objc_copyClassList(unsigned int *length)
{
	Class *ret;
	unsigned int count;

	objc_global_mutex_lock();

	if ((ret = malloc((classesCount + 1) * sizeof(Class))) == NULL)
		OBJC_ERROR("Failed to allocate memory for class list!");

	count = objc_getClassList(ret, classesCount);
	OFEnsure(count == classesCount);


	ret[count] = Nil;

	if (length != NULL)
		*length = count;

	objc_global_mutex_unlock();

	return ret;
}

bool
class_isMetaClass(Class class)
{







|












|

















|










|





|
>






|







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
	return objc_getRequiredClass(name);
}

unsigned int
objc_getClassList(Class *buffer, unsigned int count)
{
	unsigned int j;
	objc_globalMutex_lock();

	if (buffer == NULL)
		return classesCount;

	if (classesCount < count)
		count = classesCount;

	j = 0;
	for (uint32_t i = 0; i < classes->size; i++) {
		void *class;

		if (j >= count) {
			objc_globalMutex_unlock();
			return j;
		}

		if (classes->data[i] == NULL)
			continue;

		if (strcmp(classes->data[i]->key, "Protocol") == 0)
			continue;

		class = (Class)classes->data[i]->object;

		if (class == Nil || (uintptr_t)class & 1)
			continue;

		buffer[j++] = class;
	}

	objc_globalMutex_unlock();

	return j;
}

Class *
objc_copyClassList(unsigned int *length)
{
	Class *ret;
	unsigned int count;

	objc_globalMutex_lock();

	if ((ret = malloc((classesCount + 1) * sizeof(Class))) == NULL)
		OBJC_ERROR("Failed to allocate memory for class list!");

	count = objc_getClassList(ret, classesCount);
	if (count != classesCount)
		OBJC_ERROR("Fatal internal inconsistency!");

	ret[count] = Nil;

	if (length != NULL)
		*length = count;

	objc_globalMutex_unlock();

	return ret;
}

bool
class_isMetaClass(Class class)
{
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
}

static struct objc_method *
getMethod(Class class, SEL selector)
{
	struct objc_category **categories;

	if ((categories = objc_categories_for_class(class)) != NULL) {
		for (; *categories != NULL; categories++) {
			struct objc_method_list *methodList =
			    (class->info & OBJC_CLASS_INFO_METACLASS
			    ? (*categories)->classMethods
			    : (*categories)->instanceMethods);

			for (; methodList != NULL;







|







726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
}

static struct objc_method *
getMethod(Class class, SEL selector)
{
	struct objc_category **categories;

	if ((categories = objc_categoriesForClass(class)) != NULL) {
		for (; *categories != NULL; categories++) {
			struct objc_method_list *methodList =
			    (class->info & OBJC_CLASS_INFO_METACLASS
			    ? (*categories)->classMethods
			    : (*categories)->instanceMethods);

			for (; methodList != NULL;
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

static void
addMethod(Class class, SEL selector, IMP implementation,
    const char *typeEncoding)
{
	struct objc_method_list *methodList;

	/* FIXME: We need a way to free this at objc_exit() */
	if ((methodList = malloc(sizeof(*methodList))) == NULL)
		OBJC_ERROR("Not enough memory to replace method!");

	methodList->next = class->methodList;
	methodList->count = 1;
	methodList->methods[0].selector.UID = selector->UID;
	methodList->methods[0].selector.typeEncoding = typeEncoding;
	methodList->methods[0].implementation = implementation;

	class->methodList = methodList;

	objc_update_dtable(class);
}

Method
class_getInstanceMethod(Class class, SEL selector)
{
	Method method;
	Class superclass;

	if (class == Nil)
		return NULL;

	objc_global_mutex_lock();

	if ((method = getMethod(class, selector)) != NULL) {
		objc_global_mutex_unlock();
		return method;
	}

	superclass = class->superclass;

	objc_global_mutex_unlock();

	if (superclass != Nil)
		return class_getInstanceMethod(superclass, selector);

	return NULL;
}

bool
class_addMethod(Class class, SEL selector, IMP implementation,
    const char *typeEncoding)
{
	bool ret;

	objc_global_mutex_lock();

	if (getMethod(class, selector) == NULL) {
		addMethod(class, selector, implementation, typeEncoding);
		ret = true;
	} else
		ret = false;

	objc_global_mutex_unlock();

	return ret;
}

IMP
class_replaceMethod(Class class, SEL selector, IMP implementation,
    const char *typeEncoding)
{
	struct objc_method *method;
	IMP oldImplementation;

	objc_global_mutex_lock();

	if ((method = getMethod(class, selector)) != NULL) {
		oldImplementation = method->implementation;
		method->implementation = implementation;
		objc_update_dtable(class);
	} else {
		oldImplementation = NULL;
		addMethod(class, selector, implementation, typeEncoding);
	}

	objc_global_mutex_unlock();

	return oldImplementation;
}

Class
object_getClass(id object_)
{







|











|











|


|





|













|







|











|




|





|







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

static void
addMethod(Class class, SEL selector, IMP implementation,
    const char *typeEncoding)
{
	struct objc_method_list *methodList;

	/* FIXME: We need a way to free this at objc_deinit() */
	if ((methodList = malloc(sizeof(*methodList))) == NULL)
		OBJC_ERROR("Not enough memory to replace method!");

	methodList->next = class->methodList;
	methodList->count = 1;
	methodList->methods[0].selector.UID = selector->UID;
	methodList->methods[0].selector.typeEncoding = typeEncoding;
	methodList->methods[0].implementation = implementation;

	class->methodList = methodList;

	objc_updateDTable(class);
}

Method
class_getInstanceMethod(Class class, SEL selector)
{
	Method method;
	Class superclass;

	if (class == Nil)
		return NULL;

	objc_globalMutex_lock();

	if ((method = getMethod(class, selector)) != NULL) {
		objc_globalMutex_unlock();
		return method;
	}

	superclass = class->superclass;

	objc_globalMutex_unlock();

	if (superclass != Nil)
		return class_getInstanceMethod(superclass, selector);

	return NULL;
}

bool
class_addMethod(Class class, SEL selector, IMP implementation,
    const char *typeEncoding)
{
	bool ret;

	objc_globalMutex_lock();

	if (getMethod(class, selector) == NULL) {
		addMethod(class, selector, implementation, typeEncoding);
		ret = true;
	} else
		ret = false;

	objc_globalMutex_unlock();

	return ret;
}

IMP
class_replaceMethod(Class class, SEL selector, IMP implementation,
    const char *typeEncoding)
{
	struct objc_method *method;
	IMP oldImplementation;

	objc_globalMutex_lock();

	if ((method = getMethod(class, selector)) != NULL) {
		oldImplementation = method->implementation;
		method->implementation = implementation;
		objc_updateDTable(class);
	} else {
		oldImplementation = NULL;
		addMethod(class, selector, implementation, typeEncoding);
	}

	objc_globalMutex_unlock();

	return oldImplementation;
}

Class
object_getClass(id object_)
{
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
	}

	if (class->subclassList != NULL) {
		free(class->subclassList);
		class->subclassList = NULL;
	}

	if (class->DTable != NULL && class->DTable != emptyDTable)
		objc_dtable_free(class->DTable);

	class->DTable = NULL;

	if ((class->info & OBJC_CLASS_INFO_SETUP) && class->superclass != Nil)
		class->superclass = (Class)class->superclass->name;

	class->info &= ~OBJC_CLASS_INFO_SETUP;
}

void
objc_unregister_class(Class class)
{
	static SEL unloadSel = NULL;



	if (unloadSel == NULL)
		unloadSel = sel_registerName("unload");

	while (class->subclassList != NULL && class->subclassList[0] != Nil)
		objc_unregister_class(class->subclassList[0]);

	if (class->info & OBJC_CLASS_INFO_LOADED)
		callSelector(class, unloadSel);

	objc_hashtable_delete(classes, class->name);

	if (strcmp(class_getName(class), "Protocol") != 0)
		classesCount--;

	unregisterClass(class);
	unregisterClass(class->isa);


}

void
objc_unregister_all_classes(void)
{
	if (classes == NULL)
		return;

	for (uint32_t i = 0; i < classes->size; i++) {
		if (classes->data[i] != NULL &&
		    classes->data[i] != &objc_deleted_bucket) {
			void *class = (Class)classes->data[i]->object;

			if (class == Nil || (uintptr_t)class & 1)
				continue;

			objc_unregister_class(class);

			/*
			 * The table might have been resized, so go back to the
			 * start again.
			 *
			 * Due to the i++ in the for loop, we need to set it to
			 * UINT32_MAX so that it will get increased at the end
			 * of the loop and thus become 0.
			 */
			i = UINT32_MAX;
		}
	}

	OFEnsure(classesCount == 0);


	if (emptyDTable != NULL) {
		objc_dtable_free(emptyDTable);
		emptyDTable = NULL;
	}

	objc_sparsearray_free(fastPath);
	fastPath = NULL;

	objc_hashtable_free(classes);
	classes = NULL;
}







|
|

|








|


>
>





|











>
>



|






|





|













|
>












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
	}

	if (class->subclassList != NULL) {
		free(class->subclassList);
		class->subclassList = NULL;
	}

	if (class->dTable != NULL && class->dTable != emptyDTable)
		objc_dtable_free(class->dTable);

	class->dTable = NULL;

	if ((class->info & OBJC_CLASS_INFO_SETUP) && class->superclass != Nil)
		class->superclass = (Class)class->superclass->name;

	class->info &= ~OBJC_CLASS_INFO_SETUP;
}

void
objc_unregisterClass(Class class)
{
	static SEL unloadSel = NULL;

	objc_globalMutex_lock();

	if (unloadSel == NULL)
		unloadSel = sel_registerName("unload");

	while (class->subclassList != NULL && class->subclassList[0] != Nil)
		objc_unregisterClass(class->subclassList[0]);

	if (class->info & OBJC_CLASS_INFO_LOADED)
		callSelector(class, unloadSel);

	objc_hashtable_delete(classes, class->name);

	if (strcmp(class_getName(class), "Protocol") != 0)
		classesCount--;

	unregisterClass(class);
	unregisterClass(class->isa);

	objc_globalMutex_unlock();
}

void
objc_unregisterAllClasses(void)
{
	if (classes == NULL)
		return;

	for (uint32_t i = 0; i < classes->size; i++) {
		if (classes->data[i] != NULL &&
		    classes->data[i] != &objc_deletedBucket) {
			void *class = (Class)classes->data[i]->object;

			if (class == Nil || (uintptr_t)class & 1)
				continue;

			objc_unregisterClass(class);

			/*
			 * The table might have been resized, so go back to the
			 * start again.
			 *
			 * Due to the i++ in the for loop, we need to set it to
			 * UINT32_MAX so that it will get increased at the end
			 * of the loop and thus become 0.
			 */
			i = UINT32_MAX;
		}
	}

	if (classesCount != 0)
		OBJC_ERROR("Fatal internal inconsistency!");

	if (emptyDTable != NULL) {
		objc_dtable_free(emptyDTable);
		emptyDTable = NULL;
	}

	objc_sparsearray_free(fastPath);
	fastPath = NULL;

	objc_hashtable_free(classes);
	classes = NULL;
}

Modified src/runtime/dtable.m from [d61b5652b8] to [fe23892d25].

26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
static struct objc_dtable_level3 *emptyLevel3 = NULL;
#endif

static void
init(void)
{
	if ((emptyLevel2 = malloc(sizeof(*emptyLevel2))) == NULL)
		OBJC_ERROR("Not enough memory to allocate dtable!");

#ifdef OF_SELUID24
	if ((emptyLevel3 = malloc(sizeof(*emptyLevel3))) == NULL)
		OBJC_ERROR("Not enough memory to allocate dtable!");
#endif

#ifdef OF_SELUID24
	for (uint_fast16_t i = 0; i < 256; i++) {
		emptyLevel2->buckets[i] = emptyLevel3;
		emptyLevel3->buckets[i] = (IMP)0;
	}
#else
	for (uint_fast16_t i = 0; i < 256; i++)
		emptyLevel2->buckets[i] = (IMP)0;
#endif
}

struct objc_dtable *
objc_dtable_new(void)
{
	struct objc_dtable *DTable;

#ifdef OF_SELUID24
	if (emptyLevel2 == NULL || emptyLevel3 == NULL)
		init();
#else
	if (emptyLevel2 == NULL)
		init();
#endif

	if ((DTable = malloc(sizeof(*DTable))) == NULL)
		OBJC_ERROR("Not enough memory to allocate dtable!");

	for (uint_fast16_t i = 0; i < 256; i++)
		DTable->buckets[i] = emptyLevel2;

	return DTable;
}

void
objc_dtable_copy(struct objc_dtable *dest, struct objc_dtable *src)
{
	for (uint_fast16_t i = 0; i < 256; i++) {
		if (src->buckets[i] == emptyLevel2)







|



|
















|









|
|


|

|







26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
static struct objc_dtable_level3 *emptyLevel3 = NULL;
#endif

static void
init(void)
{
	if ((emptyLevel2 = malloc(sizeof(*emptyLevel2))) == NULL)
		OBJC_ERROR("Not enough memory to allocate dispatch table!");

#ifdef OF_SELUID24
	if ((emptyLevel3 = malloc(sizeof(*emptyLevel3))) == NULL)
		OBJC_ERROR("Not enough memory to allocate dispatch table!");
#endif

#ifdef OF_SELUID24
	for (uint_fast16_t i = 0; i < 256; i++) {
		emptyLevel2->buckets[i] = emptyLevel3;
		emptyLevel3->buckets[i] = (IMP)0;
	}
#else
	for (uint_fast16_t i = 0; i < 256; i++)
		emptyLevel2->buckets[i] = (IMP)0;
#endif
}

struct objc_dtable *
objc_dtable_new(void)
{
	struct objc_dtable *dTable;

#ifdef OF_SELUID24
	if (emptyLevel2 == NULL || emptyLevel3 == NULL)
		init();
#else
	if (emptyLevel2 == NULL)
		init();
#endif

	if ((dTable = malloc(sizeof(*dTable))) == NULL)
		OBJC_ERROR("Not enough memory to allocate dispatch table!");

	for (uint_fast16_t i = 0; i < 256; i++)
		dTable->buckets[i] = emptyLevel2;

	return dTable;
}

void
objc_dtable_copy(struct objc_dtable *dest, struct objc_dtable *src)
{
	for (uint_fast16_t i = 0; i < 256; i++) {
		if (src->buckets[i] == emptyLevel2)
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
			objc_dtable_set(dest, idx, implementation);
		}
#endif
	}
}

void
objc_dtable_set(struct objc_dtable *DTable, uint32_t idx, IMP implementation)
{
#ifdef OF_SELUID24
	uint8_t i = idx >> 16;
	uint8_t j = idx >> 8;
	uint8_t k = idx;
#else
	uint8_t i = idx >> 8;
	uint8_t j = idx;
#endif

	if (DTable->buckets[i] == emptyLevel2) {
		struct objc_dtable_level2 *level2 = malloc(sizeof(*level2));

		if (level2 == NULL)
			OBJC_ERROR("Not enough memory to insert into dtable!");


		for (uint_fast16_t l = 0; l < 256; l++)
#ifdef OF_SELUID24
			level2->buckets[l] = emptyLevel3;
#else
			level2->buckets[l] = (IMP)0;
#endif

		DTable->buckets[i] = level2;
	}

#ifdef OF_SELUID24
	if (DTable->buckets[i]->buckets[j] == emptyLevel3) {
		struct objc_dtable_level3 *level3 = malloc(sizeof(*level3));

		if (level3 == NULL)
			OBJC_ERROR("Not enough memory to insert into dtable!");


		for (uint_fast16_t l = 0; l < 256; l++)
			level3->buckets[l] = (IMP)0;

		DTable->buckets[i]->buckets[j] = level3;
	}

	DTable->buckets[i]->buckets[j]->buckets[k] = implementation;
#else
	DTable->buckets[i]->buckets[j] = implementation;
#endif
}

void
objc_dtable_free(struct objc_dtable *DTable)
{
	for (uint_fast16_t i = 0; i < 256; i++) {
		if (DTable->buckets[i] == emptyLevel2)
			continue;

#ifdef OF_SELUID24
		for (uint_fast16_t j = 0; j < 256; j++)
			if (DTable->buckets[i]->buckets[j] != emptyLevel3)
				free(DTable->buckets[i]->buckets[j]);
#endif

		free(DTable->buckets[i]);
	}

	free(DTable);
}

void
objc_dtable_cleanup(void)
{
	if (emptyLevel2 != NULL)
		free(emptyLevel2);







|










|



|
>








|



|



|
>




|


|

|




|


|




|
|


|


|







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
			objc_dtable_set(dest, idx, implementation);
		}
#endif
	}
}

void
objc_dtable_set(struct objc_dtable *dTable, uint32_t idx, IMP implementation)
{
#ifdef OF_SELUID24
	uint8_t i = idx >> 16;
	uint8_t j = idx >> 8;
	uint8_t k = idx;
#else
	uint8_t i = idx >> 8;
	uint8_t j = idx;
#endif

	if (dTable->buckets[i] == emptyLevel2) {
		struct objc_dtable_level2 *level2 = malloc(sizeof(*level2));

		if (level2 == NULL)
			OBJC_ERROR("Not enough memory to insert into "
			    "dispatch table!");

		for (uint_fast16_t l = 0; l < 256; l++)
#ifdef OF_SELUID24
			level2->buckets[l] = emptyLevel3;
#else
			level2->buckets[l] = (IMP)0;
#endif

		dTable->buckets[i] = level2;
	}

#ifdef OF_SELUID24
	if (dTable->buckets[i]->buckets[j] == emptyLevel3) {
		struct objc_dtable_level3 *level3 = malloc(sizeof(*level3));

		if (level3 == NULL)
			OBJC_ERROR("Not enough memory to insert into "
			    "dispatch table!");

		for (uint_fast16_t l = 0; l < 256; l++)
			level3->buckets[l] = (IMP)0;

		dTable->buckets[i]->buckets[j] = level3;
	}

	dTable->buckets[i]->buckets[j]->buckets[k] = implementation;
#else
	dTable->buckets[i]->buckets[j] = implementation;
#endif
}

void
objc_dtable_free(struct objc_dtable *dTable)
{
	for (uint_fast16_t i = 0; i < 256; i++) {
		if (dTable->buckets[i] == emptyLevel2)
			continue;

#ifdef OF_SELUID24
		for (uint_fast16_t j = 0; j < 256; j++)
			if (dTable->buckets[i]->buckets[j] != emptyLevel3)
				free(dTable->buckets[i]->buckets[j]);
#endif

		free(dTable->buckets[i]);
	}

	free(dTable);
}

void
objc_dtable_cleanup(void)
{
	if (emptyLevel2 != NULL)
		free(emptyLevel2);

Modified src/runtime/exception.m from [814fd82d64] to [b58329f870].

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
# define CALL_PERSONALITY(func) func(state, ex, ctx)
#endif

#define GNUCOBJC_EXCEPTION_CLASS UINT64_C(0x474E55434F424A43) /* GNUCOBJC */
#define GNUCCXX0_EXCEPTION_CLASS UINT64_C(0x474E5543432B2B00) /* GNUCC++\0 */
#define CLNGCXX0_EXCEPTION_CLASS UINT64_C(0x434C4E47432B2B00) /* CLNGC++\0 */

#define NUM_EMERGENCY_EXCEPTIONS 4


#define _UA_SEARCH_PHASE  0x01
#define _UA_CLEANUP_PHASE 0x02
#define _UA_HANDLER_FRAME 0x04
#define _UA_FORCE_UNWIND  0x08



#define DW_EH_PE_absptr	  0x00

#define DW_EH_PE_uleb128  0x01
#define DW_EH_PE_udata2	  0x02
#define DW_EH_PE_udata4	  0x03
#define DW_EH_PE_udata8	  0x04

#define DW_EH_PE_signed	  0x08
#define DW_EH_PE_sleb128  (DW_EH_PE_signed | DW_EH_PE_uleb128)
#define DW_EH_PE_sdata2	  (DW_EH_PE_signed | DW_EH_PE_udata2)
#define DW_EH_PE_sdata4	  (DW_EH_PE_signed | DW_EH_PE_udata4)
#define DW_EH_PE_sdata8	  (DW_EH_PE_signed | DW_EH_PE_udata8)

#define DW_EH_PE_pcrel	  0x10
#define DW_EH_PE_textrel  0x20
#define DW_EH_PE_datarel  0x30
#define DW_EH_PE_funcrel  0x40
#define DW_EH_PE_aligned  0x50

#define DW_EH_PE_indirect 0x80

#define DW_EH_PE_omit	  0xFF



#define CLEANUP_FOUND	  0x01
#define HANDLER_FOUND	  0x02


struct _Unwind_Context;

typedef enum {
	_URC_OK			= 0,
	_URC_FATAL_PHASE1_ERROR	= 3,
	_URC_END_OF_STACK	= 5,







|

>
|
|
|
|
>

>
|

|
|
|
|

|
|
|
|
|

|
|
|
|
|

|

|
>

>
|
|
>







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
# define CALL_PERSONALITY(func) func(state, ex, ctx)
#endif

#define GNUCOBJC_EXCEPTION_CLASS UINT64_C(0x474E55434F424A43) /* GNUCOBJC */
#define GNUCCXX0_EXCEPTION_CLASS UINT64_C(0x474E5543432B2B00) /* GNUCC++\0 */
#define CLNGCXX0_EXCEPTION_CLASS UINT64_C(0x434C4E47432B2B00) /* CLNGC++\0 */

#define numEmergencyExceptions 4

enum {
	_UA_SEARCH_PHASE  = 0x01,
	_UA_CLEANUP_PHASE = 0x02,
	_UA_HANDLER_FRAME = 0x04,
	_UA_FORCE_UNWIND  = 0x08
};

enum {
	DW_EH_PE_absptr	  = 0x00,

	DW_EH_PE_uleb128  = 0x01,
	DW_EH_PE_udata2	  = 0x02,
	DW_EH_PE_udata4	  = 0x03,
	DW_EH_PE_udata8	  = 0x04,

	DW_EH_PE_signed	  = 0x08,
	DW_EH_PE_sleb128  = (DW_EH_PE_signed | DW_EH_PE_uleb128),
	DW_EH_PE_sdata2	  = (DW_EH_PE_signed | DW_EH_PE_udata2),
	DW_EH_PE_sdata4	  = (DW_EH_PE_signed | DW_EH_PE_udata4),
	DW_EH_PE_sdata8	  = (DW_EH_PE_signed | DW_EH_PE_udata8),

	DW_EH_PE_pcrel	  = 0x10,
	DW_EH_PE_textrel  = 0x20,
	DW_EH_PE_datarel  = 0x30,
	DW_EH_PE_funcrel  = 0x40,
	DW_EH_PE_aligned  = 0x50,

	DW_EH_PE_indirect = 0x80,

	DW_EH_PE_omit	  = 0xFF
};

enum {
	CLEANUP_FOUND = 0x01,
	HANDLER_FOUND = 0x02
};

struct _Unwind_Context;

typedef enum {
	_URC_OK			= 0,
	_URC_FATAL_PHASE1_ERROR	= 3,
	_URC_END_OF_STACK	= 5,
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
	id object;
#ifndef HAVE_ARM_EHABI_EXCEPTIONS
	uintptr_t landingpad;
	intptr_t filter;
#endif
};

struct lsda {
	uintptr_t regionStart, landingpadsStart;
	uint8_t typesTableEnc;
	const uint8_t *typesTable;
	uintptr_t typesTableBase;
	uint8_t callsitesEnc;
	const uint8_t *callsites, *actionTable;
};







|







160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
	id object;
#ifndef HAVE_ARM_EHABI_EXCEPTIONS
	uintptr_t landingpad;
	intptr_t filter;
#endif
};

struct LSDA {
	uintptr_t regionStart, landingpadsStart;
	uint8_t typesTableEnc;
	const uint8_t *typesTable;
	uintptr_t typesTableBase;
	uint8_t callsitesEnc;
	const uint8_t *callsites, *actionTable;
};
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257

#ifdef HAVE_SEH_EXCEPTIONS
extern EXCEPTION_DISPOSITION _GCC_specific_handler(PEXCEPTION_RECORD, void *,
    PCONTEXT, PDISPATCHER_CONTEXT, _Unwind_Reason_Code (*)(int, int, uint64_t,
    struct _Unwind_Exception *, struct _Unwind_Context *));
#endif

static objc_uncaught_exception_handler_t uncaughtExceptionHandler;
static struct objc_exception emergencyExceptions[NUM_EMERGENCY_EXCEPTIONS];
#ifdef OF_HAVE_THREADS
static OFSpinlock emergencyExceptionsSpinlock;

OF_CONSTRUCTOR()
{
	if (OFSpinlockNew(&emergencyExceptionsSpinlock) != 0)
		OBJC_ERROR("Cannot create spinlock!");
}
#endif

static uint64_t
readULEB128(const uint8_t **ptr)
{
	uint64_t value = 0;







|
|






|







241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263

#ifdef HAVE_SEH_EXCEPTIONS
extern EXCEPTION_DISPOSITION _GCC_specific_handler(PEXCEPTION_RECORD, void *,
    PCONTEXT, PDISPATCHER_CONTEXT, _Unwind_Reason_Code (*)(int, int, uint64_t,
    struct _Unwind_Exception *, struct _Unwind_Context *));
#endif

static objc_uncaught_exception_handler uncaughtExceptionHandler;
static struct objc_exception emergencyExceptions[numEmergencyExceptions];
#ifdef OF_HAVE_THREADS
static OFSpinlock emergencyExceptionsSpinlock;

OF_CONSTRUCTOR()
{
	if (OFSpinlockNew(&emergencyExceptionsSpinlock) != 0)
		OBJC_ERROR("Failed to create spinlock!");
}
#endif

static uint64_t
readULEB128(const uint8_t **ptr)
{
	uint64_t value = 0;
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
		value = *(uintptr_t *)(uintptr_t)value;

	return value;
}
#endif

static void
readLSDA(struct _Unwind_Context *ctx, const uint8_t *ptr, struct lsda *LSDA)
{
	uint8_t landingpadsStartEnc;
	uintptr_t callsitesSize;

	LSDA->regionStart = _Unwind_GetRegionStart(ctx);
	LSDA->landingpadsStart = LSDA->regionStart;
	LSDA->typesTable = NULL;







|







401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
		value = *(uintptr_t *)(uintptr_t)value;

	return value;
}
#endif

static void
readLSDA(struct _Unwind_Context *ctx, const uint8_t *ptr, struct LSDA *LSDA)
{
	uint8_t landingpadsStartEnc;
	uintptr_t callsitesSize;

	LSDA->regionStart = _Unwind_GetRegionStart(ctx);
	LSDA->landingpadsStart = LSDA->regionStart;
	LSDA->typesTable = NULL;
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
	callsitesSize = (uintptr_t)readULEB128(&ptr);
	LSDA->callsites = ptr;

	LSDA->actionTable = LSDA->callsites + callsitesSize;
}

static bool
findCallsite(struct _Unwind_Context *ctx, struct lsda *LSDA,
    uintptr_t *landingpad, const uint8_t **actionRecords)
{
	uintptr_t IP = _Unwind_GetIP(ctx);
	const uint8_t *ptr = LSDA->callsites;

	*landingpad = 0;
	*actionRecords = NULL;







|







429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
	callsitesSize = (uintptr_t)readULEB128(&ptr);
	LSDA->callsites = ptr;

	LSDA->actionTable = LSDA->callsites + callsitesSize;
}

static bool
findCallsite(struct _Unwind_Context *ctx, struct LSDA *LSDA,
    uintptr_t *landingpad, const uint8_t **actionRecords)
{
	uintptr_t IP = _Unwind_GetIP(ctx);
	const uint8_t *ptr = LSDA->callsites;

	*landingpad = 0;
	*actionRecords = NULL;
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
		if (iter == class)
			return true;

	return false;
}

static uint8_t
findActionRecord(const uint8_t *actionRecords, struct lsda *LSDA, int actions,
    bool foreign, struct objc_exception *e, intptr_t *filterPtr)
{
	const uint8_t *ptr;
	intptr_t filter, displacement;

	do {
		ptr = actionRecords;







|







506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
		if (iter == class)
			return true;

	return false;
}

static uint8_t
findActionRecord(const uint8_t *actionRecords, struct LSDA *LSDA, int actions,
    bool foreign, struct objc_exception *e, intptr_t *filterPtr)
{
	const uint8_t *ptr;
	intptr_t filter, displacement;

	do {
		ptr = actionRecords;
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
	}

	_Unwind_SetGR(ctx, 12, (uintptr_t)ex);
#endif
	struct objc_exception *e = (struct objc_exception *)ex;
	bool foreign = (exClass != GNUCOBJC_EXCEPTION_CLASS);
	const uint8_t *LSDAAddr, *actionRecords;
	struct lsda LSDA;
	uintptr_t landingpad = 0;
	uint8_t found = 0;
	intptr_t filter = 0;

	if (foreign) {
		switch (exClass) {
#ifdef CXX_PERSONALITY







|







602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
	}

	_Unwind_SetGR(ctx, 12, (uintptr_t)ex);
#endif
	struct objc_exception *e = (struct objc_exception *)ex;
	bool foreign = (exClass != GNUCOBJC_EXCEPTION_CLASS);
	const uint8_t *LSDAAddr, *actionRecords;
	struct LSDA LSDA;
	uintptr_t landingpad = 0;
	uint8_t found = 0;
	intptr_t filter = 0;

	if (foreign) {
		switch (exClass) {
#ifdef CXX_PERSONALITY
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

static void
emergencyExceptionCleanup(_Unwind_Reason_Code reason,
    struct _Unwind_Exception *ex)
{
#ifdef OF_HAVE_THREADS
	if (OFSpinlockLock(&emergencyExceptionsSpinlock) != 0)
		OBJC_ERROR("Cannot lock spinlock!");
#endif

	ex->class = 0;

#ifdef OF_HAVE_THREADS
	if (OFSpinlockUnlock(&emergencyExceptionsSpinlock) != 0)
		OBJC_ERROR("Cannot unlock spinlock!");
#endif
}

void
objc_exception_throw(id object)
{
	struct objc_exception *e = calloc(1, sizeof(*e));
	bool emergency = false;

	if (e == NULL) {
#ifdef OF_HAVE_THREADS
		if (OFSpinlockLock(&emergencyExceptionsSpinlock) != 0)
			OBJC_ERROR("Cannot lock spinlock!");
#endif

		for (uint_fast8_t i = 0; i < NUM_EMERGENCY_EXCEPTIONS; i++) {
			if (emergencyExceptions[i].exception.class == 0) {
				e = &emergencyExceptions[i];
				e->exception.class = GNUCOBJC_EXCEPTION_CLASS;
				emergency = true;

				break;
			}
		}

#ifdef OF_HAVE_THREADS
		if (OFSpinlockUnlock(&emergencyExceptionsSpinlock) != 0)
			OBJC_ERROR("Cannot lock spinlock!");
#endif
	}

	if (e == NULL)
		OBJC_ERROR("Not enough memory to allocate exception!");

	e->exception.class = GNUCOBJC_EXCEPTION_CLASS;
	e->exception.cleanup = (emergency
	    ? emergencyExceptionCleanup : cleanup);
	e->object = object;

	_Unwind_RaiseException(&e->exception);

	if (uncaughtExceptionHandler != NULL)
		uncaughtExceptionHandler(object);

	OBJC_ERROR("_Unwind_RaiseException() returned!");
}

objc_uncaught_exception_handler_t
objc_setUncaughtExceptionHandler(objc_uncaught_exception_handler_t handler)
{
	objc_uncaught_exception_handler_t old = uncaughtExceptionHandler;
	uncaughtExceptionHandler = handler;

	return old;
}

#ifdef HAVE_SEH_EXCEPTIONS
typedef EXCEPTION_DISPOSITION (*seh_personality_fn)(PEXCEPTION_RECORD, void *,







|






|












|


|











|



















|
|

|







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

static void
emergencyExceptionCleanup(_Unwind_Reason_Code reason,
    struct _Unwind_Exception *ex)
{
#ifdef OF_HAVE_THREADS
	if (OFSpinlockLock(&emergencyExceptionsSpinlock) != 0)
		OBJC_ERROR("Failed to lock spinlock!");
#endif

	ex->class = 0;

#ifdef OF_HAVE_THREADS
	if (OFSpinlockUnlock(&emergencyExceptionsSpinlock) != 0)
		OBJC_ERROR("Failed to unlock spinlock!");
#endif
}

void
objc_exception_throw(id object)
{
	struct objc_exception *e = calloc(1, sizeof(*e));
	bool emergency = false;

	if (e == NULL) {
#ifdef OF_HAVE_THREADS
		if (OFSpinlockLock(&emergencyExceptionsSpinlock) != 0)
			OBJC_ERROR("Failed to lock spinlock!");
#endif

		for (uint_fast8_t i = 0; i < numEmergencyExceptions; i++) {
			if (emergencyExceptions[i].exception.class == 0) {
				e = &emergencyExceptions[i];
				e->exception.class = GNUCOBJC_EXCEPTION_CLASS;
				emergency = true;

				break;
			}
		}

#ifdef OF_HAVE_THREADS
		if (OFSpinlockUnlock(&emergencyExceptionsSpinlock) != 0)
			OBJC_ERROR("Failed to lock spinlock!");
#endif
	}

	if (e == NULL)
		OBJC_ERROR("Not enough memory to allocate exception!");

	e->exception.class = GNUCOBJC_EXCEPTION_CLASS;
	e->exception.cleanup = (emergency
	    ? emergencyExceptionCleanup : cleanup);
	e->object = object;

	_Unwind_RaiseException(&e->exception);

	if (uncaughtExceptionHandler != NULL)
		uncaughtExceptionHandler(object);

	OBJC_ERROR("_Unwind_RaiseException() returned!");
}

objc_uncaught_exception_handler
objc_setUncaughtExceptionHandler(objc_uncaught_exception_handler handler)
{
	objc_uncaught_exception_handler old = uncaughtExceptionHandler;
	uncaughtExceptionHandler = handler;

	return old;
}

#ifdef HAVE_SEH_EXCEPTIONS
typedef EXCEPTION_DISPOSITION (*seh_personality_fn)(PEXCEPTION_RECORD, void *,

Modified src/runtime/hashtable.m from [4ff03c1700] to [ad954a7a5c].

20
21
22
23
24
25
26
27
28
29
30
31
32
33
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 <stdio.h>
#include <stdlib.h>
#include <string.h>

#import "ObjFWRT.h"
#import "private.h"

struct objc_hashtable_bucket objc_deleted_bucket;

uint32_t
objc_hash_string(const void *str_)
{
	const char *str = str_;
	uint32_t hash = 0;

	while (*str != 0) {
		hash += *str;
		hash += (hash << 10);
		hash ^= (hash >> 6);
		str++;
	}

	hash += (hash << 3);
	hash ^= (hash >> 11);
	hash += (hash << 15);

	return hash;
}

bool
objc_equal_string(const void *ptr1, const void *ptr2)
{
	return (strcmp(ptr1, ptr2) == 0);
}

struct objc_hashtable *
objc_hashtable_new(uint32_t (*hash)(const void *),
    bool (*equal)(const void *, const void *), uint32_t size)







|


|



















|







20
21
22
23
24
25
26
27
28
29
30
31
32
33
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 <stdio.h>
#include <stdlib.h>
#include <string.h>

#import "ObjFWRT.h"
#import "private.h"

struct objc_hashtable_bucket objc_deletedBucket;

uint32_t
objc_string_hash(const void *str_)
{
	const char *str = str_;
	uint32_t hash = 0;

	while (*str != 0) {
		hash += *str;
		hash += (hash << 10);
		hash ^= (hash >> 6);
		str++;
	}

	hash += (hash << 3);
	hash ^= (hash >> 11);
	hash += (hash << 15);

	return hash;
}

bool
objc_string_equal(const void *ptr1, const void *ptr2)
{
	return (strcmp(ptr1, ptr2) == 0);
}

struct objc_hashtable *
objc_hashtable_new(uint32_t (*hash)(const void *),
    bool (*equal)(const void *, const void *), uint32_t size)
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
		return;

	if ((newData = calloc(newSize, sizeof(*newData))) == NULL)
		OBJC_ERROR("Not enough memory to resize hash table!");

	for (uint32_t i = 0; i < table->size; i++) {
		if (table->data[i] != NULL &&
		    table->data[i] != &objc_deleted_bucket) {
			uint32_t j, last;

			last = newSize;

			for (j = table->data[i]->hash & (newSize - 1);
			    j < last && newData[j] != NULL; j++);

			if (j >= last) {
				last = table->data[i]->hash & (newSize - 1);

				for (j = 0; j < last && newData[j] != NULL;
				    j++);
			}

			if (j >= last)
				OBJC_ERROR("No free bucket!");

			newData[j] = table->data[i];
		}
	}

	free(table->data);
	table->data = newData;
	table->size = newSize;
}

static inline bool
indexForKey(struct objc_hashtable *table, const void *key, uint32_t *idx)
{
	uint32_t i, hash;

	hash = table->hash(key) & (table->size - 1);

	for (i = hash; i < table->size && table->data[i] != NULL; i++) {
		if (table->data[i] == &objc_deleted_bucket)
			continue;

		if (table->equal(table->data[i]->key, key)) {
			*idx = i;
			return true;
		}
	}

	if (i < table->size)
		return false;

	for (i = 0; i < hash && table->data[i] != NULL; i++) {
		if (table->data[i] == &objc_deleted_bucket)
			continue;

		if (table->equal(table->data[i]->key, key)) {
			*idx = i;
			return true;
		}
	}







|















|


















|












|







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

	if ((newData = calloc(newSize, sizeof(*newData))) == NULL)
		OBJC_ERROR("Not enough memory to resize hash table!");

	for (uint32_t i = 0; i < table->size; i++) {
		if (table->data[i] != NULL &&
		    table->data[i] != &objc_deletedBucket) {
			uint32_t j, last;

			last = newSize;

			for (j = table->data[i]->hash & (newSize - 1);
			    j < last && newData[j] != NULL; j++);

			if (j >= last) {
				last = table->data[i]->hash & (newSize - 1);

				for (j = 0; j < last && newData[j] != NULL;
				    j++);
			}

			if (j >= last)
				OBJC_ERROR("No free bucket in hash table!");

			newData[j] = table->data[i];
		}
	}

	free(table->data);
	table->data = newData;
	table->size = newSize;
}

static inline bool
indexForKey(struct objc_hashtable *table, const void *key, uint32_t *idx)
{
	uint32_t i, hash;

	hash = table->hash(key) & (table->size - 1);

	for (i = hash; i < table->size && table->data[i] != NULL; i++) {
		if (table->data[i] == &objc_deletedBucket)
			continue;

		if (table->equal(table->data[i]->key, key)) {
			*idx = i;
			return true;
		}
	}

	if (i < table->size)
		return false;

	for (i = 0; i < hash && table->data[i] != NULL; i++) {
		if (table->data[i] == &objc_deletedBucket)
			continue;

		if (table->equal(table->data[i]->key, key)) {
			*idx = i;
			return true;
		}
	}
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

	resize(table, table->count + 1);

	hash = table->hash(key);
	last = table->size;

	for (i = hash & (table->size - 1); i < last && table->data[i] != NULL &&
	    table->data[i] != &objc_deleted_bucket; i++);

	if (i >= last) {
		last = hash & (table->size - 1);

		for (i = 0; i < last && table->data[i] != NULL &&
		    table->data[i] != &objc_deleted_bucket; i++);
	}

	if (i >= last)
		OBJC_ERROR("No free bucket!");

	if ((bucket = malloc(sizeof(*bucket))) == NULL)
		OBJC_ERROR("Not enough memory to allocate hash table bucket!");

	bucket->key = key;
	bucket->hash = hash;
	bucket->object = object;







|





|



|







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

	resize(table, table->count + 1);

	hash = table->hash(key);
	last = table->size;

	for (i = hash & (table->size - 1); i < last && table->data[i] != NULL &&
	    table->data[i] != &objc_deletedBucket; i++);

	if (i >= last) {
		last = hash & (table->size - 1);

		for (i = 0; i < last && table->data[i] != NULL &&
		    table->data[i] != &objc_deletedBucket; i++);
	}

	if (i >= last)
		OBJC_ERROR("No free bucket in hash table!");

	if ((bucket = malloc(sizeof(*bucket))) == NULL)
		OBJC_ERROR("Not enough memory to allocate hash table bucket!");

	bucket->key = key;
	bucket->hash = hash;
	bucket->object = object;
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
{
	uint32_t idx;

	if (!indexForKey(table, key, &idx))
		return;

	free(table->data[idx]);
	table->data[idx] = &objc_deleted_bucket;

	table->count--;
	resize(table, table->count);
}

void
objc_hashtable_free(struct objc_hashtable *table)
{
	for (uint32_t i = 0; i < table->size; i++)
		if (table->data[i] != NULL &&
		    table->data[i] != &objc_deleted_bucket)
			free(table->data[i]);

	free(table->data);
	free(table);
}







|










|





220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
{
	uint32_t idx;

	if (!indexForKey(table, key, &idx))
		return;

	free(table->data[idx]);
	table->data[idx] = &objc_deletedBucket;

	table->count--;
	resize(table, table->count);
}

void
objc_hashtable_free(struct objc_hashtable *table)
{
	for (uint32_t i = 0; i < table->size; i++)
		if (table->data[i] != NULL &&
		    table->data[i] != &objc_deletedBucket)
			free(table->data[i]);

	free(table->data);
	free(table);
}

Modified src/runtime/init.m from [b626330f56] to [930fe22400].

17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46

#import "ObjFWRT.h"
#import "private.h"

void
__objc_exec_class(struct objc_module *module)
{
	objc_global_mutex_lock();

	objc_register_all_selectors(module->symtab);
	objc_register_all_classes(module->symtab);
	objc_register_all_categories(module->symtab);
	objc_init_static_instances(module->symtab);

	objc_global_mutex_unlock();
}

void
objc_exit(void)
{
	objc_global_mutex_lock();

	objc_unregister_all_categories();
	objc_unregister_all_classes();
	objc_unregister_all_selectors();
	objc_forget_pending_static_instances();
	objc_dtable_cleanup();

	objc_global_mutex_unlock();
}







|

|
|
|
|

|



|

|

|
|
|
|


|

17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46

#import "ObjFWRT.h"
#import "private.h"

void
__objc_exec_class(struct objc_module *module)
{
	objc_globalMutex_lock();

	objc_registerAllSelectors(module->symtab);
	objc_registerAllClasses(module->symtab);
	objc_registerAllCategories(module->symtab);
	objc_initStaticInstances(module->symtab);

	objc_globalMutex_unlock();
}

void
objc_deinit(void)
{
	objc_globalMutex_lock();

	objc_unregisterAllCategories();
	objc_unregisterAllClasses();
	objc_unregisterAllSelectors();
	objc_forgetPendingStaticInstances();
	objc_dtable_cleanup();

	objc_globalMutex_unlock();
}

Modified src/runtime/instance.m from [c5fcd18398] to [3d0ab38eff].

77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
	Class class;
	void (*last)(id, SEL) = NULL;

	if (object == nil)
		return NULL;

#ifdef OF_OBJFW_RUNTIME
	objc_zero_weak_references(object);
#endif

	if (destructSelector == NULL)
		destructSelector = sel_registerName(".cxx_destruct");

	for (class = object_getClass(object); class != Nil;
	    class = class_getSuperclass(class)) {







|







77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
	Class class;
	void (*last)(id, SEL) = NULL;

	if (object == nil)
		return NULL;

#ifdef OF_OBJFW_RUNTIME
	objc_zeroWeakReferences(object);
#endif

	if (destructSelector == NULL)
		destructSelector = sel_registerName(".cxx_destruct");

	for (class = object_getClass(object); class != Nil;
	    class = class_getSuperclass(class)) {

Modified src/runtime/ivar.m from [3e8ec570e1] to [5caeed37fa].

27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
	if (class == Nil) {
		if (outCount != NULL)
			*outCount = 0;

		return NULL;
	}

	objc_global_mutex_lock();

	count = (class->ivars != NULL ? class->ivars->count : 0);

	if (count == 0) {
		if (outCount != NULL)
			*outCount = 0;

		objc_global_mutex_unlock();
		return NULL;
	}

	if ((ivars = malloc((count + 1) * sizeof(Ivar))) == NULL)
		OBJC_ERROR("Not enough memory to copy ivars");

	for (unsigned int i = 0; i < count; i++)
		ivars[i] = &class->ivars->ivars[i];
	ivars[count] = NULL;

	if (outCount != NULL)
		*outCount = count;

	objc_global_mutex_unlock();

	return ivars;
}

const char *
ivar_getName(Ivar ivar)
{







|







|




|








|







27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
	if (class == Nil) {
		if (outCount != NULL)
			*outCount = 0;

		return NULL;
	}

	objc_globalMutex_lock();

	count = (class->ivars != NULL ? class->ivars->count : 0);

	if (count == 0) {
		if (outCount != NULL)
			*outCount = 0;

		objc_globalMutex_unlock();
		return NULL;
	}

	if ((ivars = malloc((count + 1) * sizeof(Ivar))) == NULL)
		OBJC_ERROR("Not enough memory to copy ivars!");

	for (unsigned int i = 0; i < count; i++)
		ivars[i] = &class->ivars->ivars[i];
	ivars[count] = NULL;

	if (outCount != NULL)
		*outCount = count;

	objc_globalMutex_unlock();

	return ivars;
}

const char *
ivar_getName(Ivar ivar)
{

Modified src/runtime/linklib/linklib.m from [e1e21b28b9] to [2cef24eea5].

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

/* This file is automatically generated from library.xml */

#include "config.h"

#import "ObjFWRT.h"
#import "private.h"

extern struct Library *ObjFWRTBase;







|







9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

/* This file is automatically generated from amiga-library.xml */

#include "config.h"

#import "ObjFWRT.h"
#import "private.h"

extern struct Library *ObjFWRTBase;
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
	    :: "r"(ObjFWRTBase) : "r12"
	);

	return __extension__ ((bool (*)(Protocol *_Nonnull, Protocol *_Nonnull))*(void **)(((uintptr_t)ObjFWRTBase) - 382))(protocol1, protocol2);
#endif
}

_Nullable objc_uncaught_exception_handler_t
objc_setUncaughtExceptionHandler(objc_uncaught_exception_handler_t _Nullable handler)
{
#if defined(OF_AMIGAOS_M68K)
	register struct Library *a6 __asm__("a6") = ObjFWRTBase;
	(void)a6;
	return ((_Nullable objc_uncaught_exception_handler_t (*)(objc_uncaught_exception_handler_t _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_t (*)(objc_uncaught_exception_handler_t _Nullable))*(void **)(((uintptr_t)ObjFWRTBase) - 388))(handler);
#endif
}

void
objc_setForwardHandler(IMP _Nullable forward, IMP _Nullable stretForward)
{
#if defined(OF_AMIGAOS_M68K)







|
|




|






|







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
	    :: "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)
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
	);

	__extension__ ((void (*)(IMP _Nullable, IMP _Nullable))*(void **)(((uintptr_t)ObjFWRTBase) - 394))(forward, stretForward);
#endif
}

void
objc_setEnumerationMutationHandler(objc_enumeration_mutation_handler_t _Nullable hadler)
{
#if defined(OF_AMIGAOS_M68K)
	register struct Library *a6 __asm__("a6") = ObjFWRTBase;
	(void)a6;
	((void (*)(objc_enumeration_mutation_handler_t _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_t _Nullable))*(void **)(((uintptr_t)ObjFWRTBase) - 400))(hadler);
#endif
}

id _Nullable
objc_constructInstance(Class _Nullable class, void *_Nullable bytes)
{
#if defined(OF_AMIGAOS_M68K)







|




|






|







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

	__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)
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
	);

	return __extension__ ((id _Nullable (*)(Class _Nullable, void *_Nullable))*(void **)(((uintptr_t)ObjFWRTBase) - 406))(class, bytes);
#endif
}

void
objc_exit()
{
#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__ (







|







1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
	);

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

Modified src/runtime/lookup-asm/lookup-asm-arm-elf.S from [7443d47cf7] to [40d58a6394].

19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

.globl objc_msg_lookup
.globl objc_msg_lookup_stret
.globl objc_msg_lookup_super
.globl objc_msg_lookup_super_stret

.section .text
.macro generate_lookup name not_found
\name:
	cmp	r0, #0
	beq	ret_nil

	tst	r0, #1
	bne	.Ltagged_pointer_\name

	ldr	r2, [r0, #0]
	ldr	r2, [r2, #32]

.Lmain_\name:
#ifndef OF_BIG_ENDIAN
# ifdef OF_SELUID24







|


|


|







19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

.globl objc_msg_lookup
.globl objc_msg_lookup_stret
.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]

.Lmain_\name:
#ifndef OF_BIG_ENDIAN
# ifdef OF_SELUID24
52
53
54
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
	ldrb	r3, [r1, #2]
	ldr	r2, [r2, r3, lsl #2]
	ldrb	r3, [r1, #3]
	ldr	r2, [r2, r3, lsl #2]
#endif

	cmp	r2, #0
	beq	\not_found(PLT)

	mov	r0, r2
	bx	lr

.Ltagged_pointer_\name:
	ldr	r2, .Lgot$indirect_.Ltagged_pointer_\name
	add	r2, pc, r2

	ldr	r3, .Lgot$indirect_.Ltagged_pointer_\name+4
	ldr	r3, [r2, r3]
	ldr	r3, [r3]
	eor	r0, r0, r3
	and	r0, r0, #0xE
	lsl	r0, r0, #1

	ldr	r3, .Lgot$indirect_.Ltagged_pointer_\name+8
	ldr	r3, [r2, r3]
	ldr	r2, [r3, r0]
	ldr	r2, [r2, #32]

	b	.Lmain_\name
.type \name, %function
.size \name, .-\name

.Lgot$indirect_.Ltagged_pointer_\name:
	.long	_GLOBAL_OFFSET_TABLE_-(.Ltagged_pointer_\name+12)
	.long	objc_tagged_pointer_secret(GOT)
	.long	objc_tagged_pointer_classes(GOT)
.endm

.macro generate_lookup_super name lookup
\name:
	mov	r2, r0
	ldr	r0, [r0, #0]
	cmp	r0, #0
	beq	ret_nil

	ldr	r2, [r2, #4]
	ldr	r2, [r2, #32]

	b	.Lmain_\lookup
.type \name, %function
.size \name, .-\name
.endm

generate_lookup objc_msg_lookup objc_method_not_found
generate_lookup objc_msg_lookup_stret objc_method_not_found_stret
generate_lookup_super objc_msg_lookup_super objc_msg_lookup
generate_lookup_super objc_msg_lookup_super_stret objc_msg_lookup_stret

ret_nil:
	adr	r0, nil_method
	bx	lr

nil_method:
	mov	r0, #0
	bx	lr

#ifdef OF_LINUX
.section .note.GNU-stack, "", %progbits
#endif







|




|
|


|






|








|
|
|
|


|




|









|
|
|
|

|
|


|






52
53
54
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
	ldrb	r3, [r1, #2]
	ldr	r2, [r2, r3, lsl #2]
	ldrb	r3, [r1, #3]
	ldr	r2, [r2, r3, lsl #2]
#endif

	cmp	r2, #0
	beq	\notFound(PLT)

	mov	r0, r2
	bx	lr

.LtaggedPointer_\name:
	ldr	r2, .Lgot$indirect_.LtaggedPointer_\name
	add	r2, pc, r2

	ldr	r3, .Lgot$indirect_.LtaggedPointer_\name+4
	ldr	r3, [r2, r3]
	ldr	r3, [r3]
	eor	r0, r0, r3
	and	r0, r0, #0xE
	lsl	r0, r0, #1

	ldr	r3, .Lgot$indirect_.LtaggedPointer_\name+8
	ldr	r3, [r2, r3]
	ldr	r2, [r3, r0]
	ldr	r2, [r2, #32]

	b	.Lmain_\name
.type \name, %function
.size \name, .-\name

.Lgot$indirect_.LtaggedPointer_\name:
	.long	_GLOBAL_OFFSET_TABLE_-(.LtaggedPointer_\name+12)
	.long	objc_taggedPointerSecret(GOT)
	.long	objc_taggedPointerClasses(GOT)
.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

Modified src/runtime/lookup-asm/lookup-asm-arm64-elf.S from [7551faefd3] to [77601b6969].

19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
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

.globl objc_msg_lookup
.globl objc_msg_lookup_stret
.globl objc_msg_lookup_super
.globl objc_msg_lookup_super_stret

.section .text
.macro generate_lookup name not_found
\name:
	cbz	x0, ret_nil

	tst	x0, #1
	b.ne	.Ltagged_pointer_\name

	ldr	x2, [x0]
	ldr	x2, [x2, #64]

.Lmain_\name:
#ifdef OF_SELUID24
	ldrb	w3, [x1, #2]
	ldr	x2, [x2, x3, lsl #3]
#endif
	ldrb	w3, [x1, #1]
	ldr	x2, [x2, x3, lsl #3]
	ldrb	w3, [x1]
	ldr	x2, [x2, x3, lsl #3]

	cbz	x2, \not_found

	mov	x0, x2
	ret

.Ltagged_pointer_\name:
	adrp	x2, :got:objc_tagged_pointer_secret
	ldr	x2, [x2, #:got_lo12:objc_tagged_pointer_secret]
	ldr	x2, [x2]
	eor	x0, x0, x2
	and	x0, x0, #0xE
	lsl	x0, x0, #2

	adrp	x2, :got:objc_tagged_pointer_classes
	ldr	x2, [x2, #:got_lo12:objc_tagged_pointer_classes]
	ldr	x2, [x2, x0]
	ldr	x2, [x2, #64]

	b	.Lmain_\name
.type \name, %function
.size \name, .-\name
.endm

.macro generate_lookup_super name lookup
\name:
	mov	x2, x0
	ldr	x0, [x0]
	cbz	x0, ret_nil

	ldr	x2, [x2, #8]
	ldr	x2, [x2, #64]

	b	.Lmain_\lookup
.type \name, %function
.size \name, .-\name
.endm

generate_lookup objc_msg_lookup objc_method_not_found
generate_lookup objc_msg_lookup_stret objc_method_not_found_stret
generate_lookup_super objc_msg_lookup_super objc_msg_lookup
generate_lookup_super objc_msg_lookup_super_stret objc_msg_lookup_stret

ret_nil:
	adr	x0, nil_method
	ret

nil_method:
	mov	x0, #0
	ret

#ifdef OF_LINUX
.section .note.GNU-stack, "", %progbits
#endif







|

|


|














|




|
|
|





|
|








|



|









|
|
|
|

|
|


|






19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
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

.globl objc_msg_lookup
.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]

.Lmain_\name:
#ifdef OF_SELUID24
	ldrb	w3, [x1, #2]
	ldr	x2, [x2, x3, lsl #3]
#endif
	ldrb	w3, [x1, #1]
	ldr	x2, [x2, x3, lsl #3]
	ldrb	w3, [x1]
	ldr	x2, [x2, x3, lsl #3]

	cbz	x2, \notFound

	mov	x0, x2
	ret

.LtaggedPointer_\name:
	adrp	x2, :got:objc_taggedPointerSecret
	ldr	x2, [x2, #:got_lo12:objc_taggedPointerSecret]
	ldr	x2, [x2]
	eor	x0, x0, x2
	and	x0, x0, #0xE
	lsl	x0, x0, #2

	adrp	x2, :got:objc_taggedPointerClasses
	ldr	x2, [x2, #:got_lo12:objc_taggedPointerClasses]
	ldr	x2, [x2, x0]
	ldr	x2, [x2, #64]

	b	.Lmain_\name
.type \name, %function
.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

Modified src/runtime/lookup-asm/lookup-asm-mips-elf.S from [b2c0fd7a36] to [16aa30af7f].

19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

.globl objc_msg_lookup
.globl objc_msg_lookup_stret
.globl objc_msg_lookup_super
.globl objc_msg_lookup_super_stret

.section .text
.macro generate_lookup name not_found
\name:
	beqz	$a0, 0f

	andi	$t0, $a0, 1
	bnez	$t0, .Ltagged_pointer_\name

	lw	$t0, 0($a0)
	lw	$t0, 32($t0)

.Lmain_\name:
#ifdef OF_BIG_ENDIAN
# ifdef OF_SELUID24







|




|







19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

.globl objc_msg_lookup
.globl objc_msg_lookup_stret
.globl objc_msg_lookup_super
.globl objc_msg_lookup_super_stret

.section .text
.macro GENERATE_LOOKUP name notFound
\name:
	beqz	$a0, 0f

	andi	$t0, $a0, 1
	bnez	$t0, .LtaggedPointer_\name

	lw	$t0, 0($a0)
	lw	$t0, 32($t0)

.Lmain_\name:
#ifdef OF_BIG_ENDIAN
# ifdef OF_SELUID24
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
	lw	$t0, 0($t0)
	addu	$t0, $t0, $t3
	lw	$t0, 0($t0)

#ifdef OF_PIC
	beqz	$t0, 1f
#else
	beqz	$t0, \not_found
#endif

	move	$v0, $t0
	jr	$ra

0:
#ifdef OF_PIC
	addiu	$v0, $t9, nil_method-\name
#else
	la	$v0, nil_method
#endif
	jr	$ra

#ifdef OF_PIC
1:
	lui	$gp, %hi(_gp_disp)
	addiu	$gp, $gp, %lo(_gp_disp)
	addu	$gp, $gp, $t9
	addiu	$gp, $gp, 1b-\name

	lw	$t9, %call16(\not_found)($gp)
	jr	$t9
#endif

.Ltagged_pointer_\name:
#ifdef OF_PIC
0:
	lui	$gp, %hi(_gp_disp)
	addiu	$gp, $gp, %lo(_gp_disp)
	addu	$gp, $gp, $t9
	addiu	$gp, $gp, 0b-\name

	lw	$t0, %got(objc_tagged_pointer_secret)($gp)
#else
	la	$t0, objc_tagged_pointer_secret
#endif
	lw	$t0, 0($t0)
	xor	$t0, $a0, $t0
	and	$t0, $t0, 0xE
	sll	$t0, $t0, 1

#ifdef OF_PIC
	lw	$t1, %got(objc_tagged_pointer_classes)($gp)
#else
	la	$t1, objc_tagged_pointer_classes
#endif
	addu	$t0, $t1, $t0
	ld	$t0, ($t0)
	ld	$t0, 32($t0)

	b	.Lmain_\name
.type \name, %function
.size \name, .-\name
.endm

.macro generate_lookup_super name lookup
\name:
	move	$t0, $a0
	lw	$a0, 0($a0)
	beqz	$a0, 0f

	lw	$t0, 4($t0)
	lw	$t0, 32($t0)

	addiu	$t9, $t9, \lookup-\name
	b	.Lmain_\lookup

0:
#ifdef OF_PIC
	addiu	$v0, $t9, nil_method-\name
#else
	la	$v0, nil_method
#endif
	jr	$ra
.type \name, %function
.size \name, .-\name
.endm

generate_lookup objc_msg_lookup objc_method_not_found
generate_lookup objc_msg_lookup_stret objc_method_not_found_stret
generate_lookup_super objc_msg_lookup_super objc_msg_lookup
generate_lookup_super objc_msg_lookup_super_stret objc_msg_lookup_stret

nil_method:
	move	$v0, $zero
	jr	$ra

#ifdef OF_LINUX
.section .note.GNU-stack, "", %progbits
#endif







|







|

|










|



|







|

|







|

|










|













|

|






|
|
|
|

|






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
	lw	$t0, 0($t0)
	addu	$t0, $t0, $t3
	lw	$t0, 0($t0)

#ifdef OF_PIC
	beqz	$t0, 1f
#else
	beqz	$t0, \notFound
#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)
	addu	$gp, $gp, $t9
	addiu	$gp, $gp, 1b-\name

	lw	$t9, %call16(\notFound)($gp)
	jr	$t9
#endif

.LtaggedPointer_\name:
#ifdef OF_PIC
0:
	lui	$gp, %hi(_gp_disp)
	addiu	$gp, $gp, %lo(_gp_disp)
	addu	$gp, $gp, $t9
	addiu	$gp, $gp, 0b-\name

	lw	$t0, %got(objc_taggedPointerSecret)($gp)
#else
	la	$t0, objc_taggedPointerSecret
#endif
	lw	$t0, 0($t0)
	xor	$t0, $a0, $t0
	and	$t0, $t0, 0xE
	sll	$t0, $t0, 1

#ifdef OF_PIC
	lw	$t1, %got(objc_taggedPointerClasses)($gp)
#else
	la	$t1, objc_taggedPointerClasses
#endif
	addu	$t0, $t1, $t0
	ld	$t0, ($t0)
	ld	$t0, 32($t0)

	b	.Lmain_\name
.type \name, %function
.size \name, .-\name
.endm

.macro GENERATE_LOOKUP_SUPER name lookup
\name:
	move	$t0, $a0
	lw	$a0, 0($a0)
	beqz	$a0, 0f

	lw	$t0, 4($t0)
	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

Modified src/runtime/lookup-asm/lookup-asm-mips64-n64-elf.S from [34f3dd7a14] to [6719050384].

19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

.globl objc_msg_lookup
.globl objc_msg_lookup_stret
.globl objc_msg_lookup_super
.globl objc_msg_lookup_super_stret

.section .text
.macro generate_lookup name not_found
\name:
	beqz	$a0, 0f

	andi	$t0, $a0, 1
	bnez	$t0, .Ltagged_pointer_\name

	ld	$t0, ($a0)
	ld	$t0, 64($t0)

.Lmain_\name:
#ifdef OF_BIG_ENDIAN
# ifdef OF_SELUID24







|




|







19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

.globl objc_msg_lookup
.globl objc_msg_lookup_stret
.globl objc_msg_lookup_super
.globl objc_msg_lookup_super_stret

.section .text
.macro GENERATE_LOOKUP name notFound
\name:
	beqz	$a0, 0f

	andi	$t0, $a0, 1
	bnez	$t0, .LtaggedPointer_\name

	ld	$t0, ($a0)
	ld	$t0, 64($t0)

.Lmain_\name:
#ifdef OF_BIG_ENDIAN
# ifdef OF_SELUID24
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
	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(nil_method)($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(\not_found)($t0)
	jr	$t9

.Ltagged_pointer_\name:
	lui	$t0, %hi(%neg(%gp_rel(\name)))
	daddiu	$t0, $t0, %lo(%neg(%gp_rel(\name)))
	daddu	$t0, $t0, $t9

	ld	$t1, %got_disp(objc_tagged_pointer_secret)($t0)
	ld	$t1, 0($t1)
	xor	$t1, $a0, $t1
	and	$t1, $t1, 0xE
	dsll	$t1, $t1, 2

	ld	$t0, %got_disp(objc_tagged_pointer_classes)($t0)
	daddu	$t0, $t0, $t1
	ld	$t0, ($t0)
	ld	$t0, 64($t0)

	b	.Lmain_\name
.type \name, %function
.size \name, .-\name
.endm

.macro generate_lookup_super name lookup
\name:
	move	$t0, $a0
	ld	$a0, ($a0)
	beqz	$a0, 0f

	ld	$t0, 8($t0)
	ld	$t0, 64($t0)

	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(nil_method)($v0)
	jr	$ra
.type \name, %function
.size \name, .-\name
.endm

generate_lookup objc_msg_lookup objc_method_not_found
generate_lookup objc_msg_lookup_stret objc_method_not_found_stret
generate_lookup_super objc_msg_lookup_super objc_msg_lookup
generate_lookup_super objc_msg_lookup_super_stret objc_msg_lookup_stret

nil_method:
	move	$v0, $zero
	jr	$ra

#ifdef OF_LINUX
.section .note.GNU-stack, "", %progbits
#endif







|






|


|




|





|









|















|





|
|
|
|

|






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
	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)
	jr	$t9

.LtaggedPointer_\name:
	lui	$t0, %hi(%neg(%gp_rel(\name)))
	daddiu	$t0, $t0, %lo(%neg(%gp_rel(\name)))
	daddu	$t0, $t0, $t9

	ld	$t1, %got_disp(objc_taggedPointerSecret)($t0)
	ld	$t1, 0($t1)
	xor	$t1, $a0, $t1
	and	$t1, $t1, 0xE
	dsll	$t1, $t1, 2

	ld	$t0, %got_disp(objc_taggedPointerClasses)($t0)
	daddu	$t0, $t0, $t1
	ld	$t0, ($t0)
	ld	$t0, 64($t0)

	b	.Lmain_\name
.type \name, %function
.size \name, .-\name
.endm

.macro GENERATE_LOOKUP_SUPER name lookup
\name:
	move	$t0, $a0
	ld	$a0, ($a0)
	beqz	$a0, 0f

	ld	$t0, 8($t0)
	ld	$t0, 64($t0)

	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

Modified src/runtime/lookup-asm/lookup-asm-powerpc-elf.S from [e20fe0b40d] to [7227a38be1].

19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

.globl objc_msg_lookup
.globl objc_msg_lookup_stret
.globl objc_msg_lookup_super
.globl objc_msg_lookup_super_stret

.section .text
.macro generate_lookup name not_found
\name:
	cmpwi	%r3, 0
	beq-	ret_nil

	andi.	%r0, %r3, 1
	bne-	.Ltagged_pointer_\name

	lwz	%r5, 0(%r3)
	lwz	%r5, 32(%r5)

.Lmain_\name:
	lwz	%r8, 0(%r4)
#ifdef OF_SELUID24







|


|


|







19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

.globl objc_msg_lookup
.globl objc_msg_lookup_stret
.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)

.Lmain_\name:
	lwz	%r8, 0(%r4)
#ifdef OF_SELUID24
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

	bl	0f
0:
	mflr	%r30
	addis	%r30, %r30, .Lbiased_got2-0b@ha
	addi	%r30, %r30, .Lbiased_got2-0b@l

	lwz	%r0, .Lgot_\not_found-.Lbiased_got2(%r30)
	mtctr	%r0

	lwz	%r30, 8(%r1)
	lwz	%r0, 20(%r1)
	addi	%r1, %r1, 16
	mtlr	%r0

	bctr
#else
	b	\not_found
#endif

.Ltagged_pointer_\name:
#if defined(OF_PIC)
	mflr	%r7
	bl	0f
0:
	mflr	%r6
	mtlr	%r7
	addis	%r6, %r6, .Lbiased_got2-0b@ha
	addi	%r6, %r6, .Lbiased_got2-0b@l

	lwz	%r5, .Lgot_objc_tagged_pointer_secret-.Lbiased_got2(%r6)
	lwz	%r5, 0(%r5)
#elif defined(OF_BASEREL)
	addis	%r5, %r13, objc_tagged_pointer_secret@drel@ha
	lwz	%r5, objc_tagged_pointer_secret@drel@l(%r5)
#else
	lis	%r5, objc_tagged_pointer_secret@ha
	lwz	%r5, objc_tagged_pointer_secret@l(%r5)
#endif
	xor	%r5, %r3, %r5
	rlwinm	%r5, %r5, 1, 0x1C

#if defined(OF_PIC)
	lwz	%r6, .Lgot_objc_tagged_pointer_classes-.Lbiased_got2(%r6)
#elif defined(OF_BASEREL)
	addis	%r6, %r13, objc_tagged_pointer_classes@drel@ha
	addi	%r6, %r6, objc_tagged_pointer_classes@drel@l
#else
	lis	%r6, objc_tagged_pointer_classes@ha
	addi	%r6, %r6, objc_tagged_pointer_classes@l
#endif
	lwzx	%r5, %r6, %r5
	lwz	%r5, 32(%r5)

	b	.Lmain_\name
.type \name, @function
.size \name, .-\name
.endm

.macro generate_lookup_super name lookup
\name:
	mr	%r5, %r3
	lwz	%r3, 0(%r3)
	cmpwi	%r3, 0
	beq-	ret_nil

	lwz	%r5, 4(%r5)
	lwz	%r5, 32(%r5)

	b	.Lmain_\lookup
.type \name, @function
.size \name, .-\name
.endm

generate_lookup objc_msg_lookup objc_method_not_found
generate_lookup objc_msg_lookup_stret objc_method_not_found_stret
generate_lookup_super objc_msg_lookup_super objc_msg_lookup
generate_lookup_super objc_msg_lookup_super_stret objc_msg_lookup_stret

ret_nil:
	mflr	%r0
	bl	get_pc
	mtlr	%r0
0:
	addi	%r3, %r3, nil_method-0b
	blr

nil_method:
	li	%r3, 0
	blr

get_pc:
	mflr	%r3
	blr

#ifdef OF_PIC
.section .got2, "aw"
.Lbiased_got2 = .+0x8000
.Lgot_objc_method_not_found:
	.long objc_method_not_found
.Lgot_objc_method_not_found_stret:
	.long objc_method_not_found_stret
.Lgot_objc_tagged_pointer_secret:
	.long objc_tagged_pointer_secret
.Lgot_objc_tagged_pointer_classes:
	.long objc_tagged_pointer_classes
#endif

#ifdef OF_LINUX
.section .note.GNU-stack, "", @progbits
#endif







|









|


|









|


|
|

|
|





|

|
|

|
|









|




|









|
|
|
|

|

|


|


|



|






|
|
|
|
|
|
|
|





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

	bl	0f
0:
	mflr	%r30
	addis	%r30, %r30, .Lbiased_got2-0b@ha
	addi	%r30, %r30, .Lbiased_got2-0b@l

	lwz	%r0, .Lgot_\notFound-.Lbiased_got2(%r30)
	mtctr	%r0

	lwz	%r30, 8(%r1)
	lwz	%r0, 20(%r1)
	addi	%r1, %r1, 16
	mtlr	%r0

	bctr
#else
	b	\notFound
#endif

.LtaggedPointer_\name:
#if defined(OF_PIC)
	mflr	%r7
	bl	0f
0:
	mflr	%r6
	mtlr	%r7
	addis	%r6, %r6, .Lbiased_got2-0b@ha
	addi	%r6, %r6, .Lbiased_got2-0b@l

	lwz	%r5, .Lgot_objc_taggedPointerSecret-.Lbiased_got2(%r6)
	lwz	%r5, 0(%r5)
#elif defined(OF_BASEREL)
	addis	%r5, %r13, objc_taggedPointerSecret@drel@ha
	lwz	%r5, objc_taggedPointerSecret@drel@l(%r5)
#else
	lis	%r5, objc_taggedPointerSecret@ha
	lwz	%r5, objc_taggedPointerSecret@l(%r5)
#endif
	xor	%r5, %r3, %r5
	rlwinm	%r5, %r5, 1, 0x1C

#if defined(OF_PIC)
	lwz	%r6, .Lgot_objc_taggedPointerClasses-.Lbiased_got2(%r6)
#elif defined(OF_BASEREL)
	addis	%r6, %r13, objc_taggedPointerClasses@drel@ha
	addi	%r6, %r6, objc_taggedPointerClasses@drel@l
#else
	lis	%r6, objc_taggedPointerClasses@ha
	addi	%r6, %r6, objc_taggedPointerClasses@l
#endif
	lwzx	%r5, %r6, %r5
	lwz	%r5, 32(%r5)

	b	.Lmain_\name
.type \name, @function
.size \name, .-\name
.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

Added src/runtime/lookup-asm/lookup-asm-powerpc64-elf.S version [abf2533c1d].





















































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
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
/*
 * 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.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 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"

.globl objc_msg_lookup
.globl objc_msg_lookup_stret
.globl objc_msg_lookup_super
.globl objc_msg_lookup_super_stret

.section .text
.macro GENERATE_LOOKUP name notFound
.section .opd, "aw", @progbits
\name:
	.p2align 3
	.quad .Lbegin_\name
	.quad .TOC.@tocbase
	.quad 0
.text
.Lbegin_\name:
	cmpdi	%r3, 0
	beq-	.LreturnNilMethod

	andi.	%r0, %r3, 1
	bne-	.LtaggedPointer_\name

	ld	%r5, 0(%r3)
	ld	%r5, 64(%r5)

.Lmain_\name:
	ld	%r8, 0(%r4)
#ifdef OF_SELUID24
	rlwinm	%r6, %r8, 19, 0x7F8
#endif
	rlwinm	%r7, %r8, 27, 0x7F8
	rlwinm	%r8, %r8, 3, 0x7F8

#ifdef OF_SELUID24
	ldx	%r5, %r5, %r6
#endif
	ldx	%r5, %r5, %r7
	ldx	%r5, %r5, %r8

	cmpdi	%r5, 0
	beq-	0f

	mr	%r3, %r5
	blr

0:
	mflr	%r0
	std	%r0, 16(%r1)
	stdu	%r1, -112(%r1)
	bl	\notFound
	nop
	addi	%r1, %r1, 112
	ld	%r0, 16(%r1)
	mtlr	%r0
	blr

.LtaggedPointer_\name:
	addis	%r5, %r2, objc_taggedPointerSecret@toc@ha
	ld	%r5, objc_taggedPointerSecret@toc@l(%r5)
	xor	%r5, %r3, %r5
	rlwinm	%r5, %r5, 2, 0x38

	addis	%r6, %r2, objc_taggedPointerClasses@toc@ha
	addi	%r6, %r6, objc_taggedPointerClasses@toc@l
	ldx	%r5, %r6, %r5
	ld	%r5, 64(%r5)

	b	.Lmain_\name
.type \name, @function
.size \name, .-.Lbegin_\name
.endm

.macro GENERATE_LOOKUP_SUPER name lookup
.section .opd, "aw", @progbits
\name:
	.p2align 3
	.quad .Lbegin_\name
	.quad .TOC.@tocbase
	.quad 0
.text
.Lbegin_\name:
	mr	%r5, %r3
	ld	%r3, 0(%r3)
	cmpdi	%r3, 0
	beq-	.LreturnNilMethod

	ld	%r5, 8(%r5)
	ld	%r5, 64(%r5)

	b	.Lmain_\lookup
.type \name, @function
.size \name, .-.Lbegin_\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:
	addis	%r3, %r2, nilMethod@toc@ha
	addi	%r3, %r3, nilMethod@toc@l
	blr

.section .opd, "aw", @progbits
nilMethod:
	.p2align 3
	.quad .Lbegin_nilMethod
	.quad .TOC.@tocbase
	.quad 0
.text
.Lbegin_nilMethod:
	li	%r3, 0
	blr
.type nilMethod, @function
.size nilMethod, .-.Lbegin_nilMethod

#ifdef OF_LINUX
.section .note.GNU-stack, "", @progbits
#endif

Modified src/runtime/lookup-asm/lookup-asm-sparc-elf.S from [97ba2c63db] to [c6e8c65e49].

19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

.globl objc_msg_lookup
.globl objc_msg_lookup_stret
.globl objc_msg_lookup_super
.globl objc_msg_lookup_super_stret

.section .text
.macro generate_lookup name not_found
\name:
	tst	%o0
	bz	ret_nil
	 btst	1, %o0
	bnz	.Ltagged_pointer_\name	
	 nop

	ld	[%o0], %o2
	ld	[%o2 + 32], %o2

.Lmain_\name:
#ifdef OF_SELUID24







|


|

|







19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

.globl objc_msg_lookup
.globl objc_msg_lookup_stret
.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

.Lmain_\name:
#ifdef OF_SELUID24
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
	 nop

	retl
	 mov	%o2, %o0

0:
	mov	%o7, %g1
	call	\not_found
	 mov	%g1, %o7

.Ltagged_pointer_\name:
#ifdef OF_PIC
	mov	%o7, %g1
	sethi	%hi(_GLOBAL_OFFSET_TABLE_ - 4), %o3
	call	0f
	 or	%o3, %lo(_GLOBAL_OFFSET_TABLE_ + 4), %o3
0:
	add	%o7, %o3, %o3
	mov	%g1, %o7
#endif

	sethi	%hi(objc_tagged_pointer_secret), %o2
	or	%o2, %lo(objc_tagged_pointer_secret), %o2
#ifdef OF_PIC
	ld	[%o3 + %o2], %o2
#endif
	ld	[%o2], %o2
	xor	%o0, %o2, %o0
	and	%o0, 0xE, %o0
	sll	%o0, 1, %o0

	sethi	%hi(objc_tagged_pointer_classes), %o2
	or	%o2, %lo(objc_tagged_pointer_classes), %o2
#ifdef OF_PIC
	ld	[%o3 + %o2], %o2
#endif

	ld	[%o2 + %o0], %o2
	ba	.Lmain_\name
	 ld	[%o2 + 32], %o2
.type \name, %function
.size \name, .-\name
.endm

.macro generate_lookup_super name lookup
\name:
	mov	%o0, %o2
	ld	[%o0], %o0
	cmp	%o0, 0
	be	ret_nil
	 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_method_not_found
generate_lookup objc_msg_lookup_stret objc_method_not_found_stret
generate_lookup_super objc_msg_lookup_super objc_msg_lookup
generate_lookup_super objc_msg_lookup_super_stret objc_msg_lookup_stret

ret_nil:
#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(nil_method), %o0
	or	%o0, %lo(nil_method), %o0

	jmpl	%g1 + 8, %g0
	 ld	[%o1 + %o0], %o0
#else
	sethi	%hi(nil_method), %o0
	retl
	 or	%o0, %lo(nil_method), %o0
#endif

nil_method:
	retl
	 clr	%o0

#ifdef OF_LINUX
.section .note.GNU-stack, "", %progbits
#endif







|


|










|
|








|
|











|




|









|
|
|
|

|









|
|




|

|


|






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
	 nop

	retl
	 mov	%o2, %o0

0:
	mov	%o7, %g1
	call	\notFound
	 mov	%g1, %o7

.LtaggedPointer_\name:
#ifdef OF_PIC
	mov	%o7, %g1
	sethi	%hi(_GLOBAL_OFFSET_TABLE_ - 4), %o3
	call	0f
	 or	%o3, %lo(_GLOBAL_OFFSET_TABLE_ + 4), %o3
0:
	add	%o7, %o3, %o3
	mov	%g1, %o7
#endif

	sethi	%hi(objc_taggedPointerSecret), %o2
	or	%o2, %lo(objc_taggedPointerSecret), %o2
#ifdef OF_PIC
	ld	[%o3 + %o2], %o2
#endif
	ld	[%o2], %o2
	xor	%o0, %o2, %o0
	and	%o0, 0xE, %o0
	sll	%o0, 1, %o0

	sethi	%hi(objc_taggedPointerClasses), %o2
	or	%o2, %lo(objc_taggedPointerClasses), %o2
#ifdef OF_PIC
	ld	[%o3 + %o2], %o2
#endif

	ld	[%o2 + %o0], %o2
	ba	.Lmain_\name
	 ld	[%o2 + 32], %o2
.type \name, %function
.size \name, .-\name
.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

Modified src/runtime/lookup-asm/lookup-asm-sparc64-elf.S from [f2aa28d73c] to [ddfe4e7ce8].

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

.globl objc_msg_lookup
.globl objc_msg_lookup_stret
.globl objc_msg_lookup_super
.globl objc_msg_lookup_super_stret

.section .text
.macro generate_lookup name not_found
\name:
	brz,pn	%o0, ret_nil
	 and	%o0, 1, %o2
	brnz,pn	%o2, .Ltagged_pointer_\name
	 nop

	ldx	[%o0], %o2
	ldx	[%o2 + 64], %o2

.Lmain_\name:
#ifdef OF_SELUID24







|

|

|







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

.globl objc_msg_lookup
.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

.Lmain_\name:
#ifdef OF_SELUID24
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
	 nop

	retl
	 mov	%o2, %o0

0:
	mov	%o7, %g1
	call	\not_found
	 mov	%g1, %o7

.Ltagged_pointer_\name:
#ifdef OF_PIC
	mov	%o7, %g1
	sethi	%hi(_GLOBAL_OFFSET_TABLE_ - 4), %o3
	call	0f
	 or	%o3, %lo(_GLOBAL_OFFSET_TABLE_ + 4), %o3
0:
	add	%o7, %o3, %o3
	mov	%g1, %o7
#endif

	sethi	%hi(objc_tagged_pointer_secret), %o2
	or	%o2, %lo(objc_tagged_pointer_secret), %o2
#ifdef OF_PIC
	ldx	[%o3 + %o2], %o2
#endif
	ldx	[%o2], %o2
	xor	%o0, %o2, %o0
	and	%o0, 0xE, %o0
	sll	%o0, 2, %o0

	sethi	%hi(objc_tagged_pointer_classes), %o2
	or	%o2, %lo(objc_tagged_pointer_classes), %o2
#ifdef OF_PIC
	ldx	[%o3 + %o2], %o2
#endif

	ldx	[%o2 + %o0], %o2
	ba	.Lmain_\name
	 ldx	[%o2 + 64], %o2
.type \name, %function
.size \name, .-\name
.endm

.macro generate_lookup_super name lookup
\name:
	mov	%o0, %o2
	ldx	[%o0], %o0
	brz,pn	%o0, ret_nil
	 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_method_not_found
generate_lookup objc_msg_lookup_stret objc_method_not_found_stret
generate_lookup_super objc_msg_lookup_super objc_msg_lookup
generate_lookup_super objc_msg_lookup_super_stret objc_msg_lookup_stret

ret_nil:
#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(nil_method), %o0
	or	%o0, %lo(nil_method), %o0

	jmpl	%g1 + 8, %g0
	 ldx	[%o1 + %o0], %o0
#else
	sethi	%hi(nil_method), %o0
	retl
	 or	%o0, %lo(nil_method), %o0
#endif

nil_method:
	retl
	 clr	%o0

#ifdef OF_LINUX
.section .note.GNU-stack, "", %progbits
#endif







|


|










|
|








|
|











|



|









|
|
|
|

|









|
|




|

|


|






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
	 nop

	retl
	 mov	%o2, %o0

0:
	mov	%o7, %g1
	call	\notFound
	 mov	%g1, %o7

.LtaggedPointer_\name:
#ifdef OF_PIC
	mov	%o7, %g1
	sethi	%hi(_GLOBAL_OFFSET_TABLE_ - 4), %o3
	call	0f
	 or	%o3, %lo(_GLOBAL_OFFSET_TABLE_ + 4), %o3
0:
	add	%o7, %o3, %o3
	mov	%g1, %o7
#endif

	sethi	%hi(objc_taggedPointerSecret), %o2
	or	%o2, %lo(objc_taggedPointerSecret), %o2
#ifdef OF_PIC
	ldx	[%o3 + %o2], %o2
#endif
	ldx	[%o2], %o2
	xor	%o0, %o2, %o0
	and	%o0, 0xE, %o0
	sll	%o0, 2, %o0

	sethi	%hi(objc_taggedPointerClasses), %o2
	or	%o2, %lo(objc_taggedPointerClasses), %o2
#ifdef OF_PIC
	ldx	[%o3 + %o2], %o2
#endif

	ldx	[%o2 + %o0], %o2
	ba	.Lmain_\name
	 ldx	[%o2 + 64], %o2
.type \name, %function
.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

Modified src/runtime/lookup-asm/lookup-asm-x86-elf.S from [89119220a2] to [584c3797d2].

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

.globl objc_msg_lookup
.globl objc_msg_lookup_stret
.globl objc_msg_lookup_super
.globl objc_msg_lookup_super_stret

.section .text
.macro generate_lookup name not_found
\name:
	movl	4(%esp), %edx
	testl	%edx, %edx
	jz	ret_nil

	testb	$1, %dl
	jnz	.Ltagged_pointer_\name

	movl	(%edx), %edx
	movl	32(%edx), %edx

.Lmain_\name:
	movl	8(%esp), %eax








|



|


|







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

.globl objc_msg_lookup
.globl objc_msg_lookup_stret
.globl objc_msg_lookup_super
.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

.Lmain_\name:
	movl	8(%esp), %eax

49
50
51
52
53
54
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	get_eip
	addl	$_GLOBAL_OFFSET_TABLE_, %eax
	lea	\not_found@GOTOFF(%eax), %eax
	jmp	*%eax

.Ltagged_pointer_\name:
	call	get_eip
	addl	$_GLOBAL_OFFSET_TABLE_, %eax

	leal	objc_tagged_pointer_secret@GOTOFF(%eax), %ecx
	xorl	(%ecx), %edx
	andb	$0xE, %dl
	movzbl	%dl, %edx

	leal	objc_tagged_pointer_classes@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	ret_nil

	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_method_not_found
generate_lookup objc_msg_lookup_stret objc_method_not_found_stret
generate_lookup_super objc_msg_lookup_super objc_msg_lookup
generate_lookup_super objc_msg_lookup_super_stret objc_msg_lookup_stret

ret_nil:
	call	get_eip
	addl	$_GLOBAL_OFFSET_TABLE_, %eax
	leal	nil_method@GOTOFF(%eax), %eax
	ret

nil_method:
	xorl	%eax, %eax
	ret

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

Modified src/runtime/lookup-asm/lookup-asm-x86-win32.S from [e53fa327a6] to [82a8f4610f].

17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
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

.globl _objc_msg_lookup
.globl _objc_msg_lookup_stret
.globl _objc_msg_lookup_super
.globl _objc_msg_lookup_super_stret

.section .text
.macro generate_lookup name not_found
\name:
	movl	4(%esp), %edx
	testl	%edx, %edx
	jz	ret_nil

	testb	$1, %dl
	jnz	.Ltagged_pointer_\name

	movl	(%edx), %edx
	movl	32(%edx), %edx

.Lmain_\name:
	movl	8(%esp), %eax

#ifdef OF_SELUID24
	movzbl	2(%eax), %ecx
	movl	(%edx,%ecx,4), %edx
#endif
	movzbl	1(%eax), %ecx
	movl	(%edx,%ecx,4), %edx
	movzbl	(%eax), %ecx
	movl	(%edx,%ecx,4), %eax

	testl	%eax, %eax
	jz	\not_found

	ret

.Ltagged_pointer_\name:
	xorl	_objc_tagged_pointer_secret, %edx
	andb	$0xE, %dl
	movzbl	%dl, %edx

	movl	_objc_tagged_pointer_classes(,%edx,2), %edx
	movl	32(%edx), %edx

	jmp	.Lmain_\name
.def \name
.scl 2
.type 32
.endef
.endm

.macro generate_lookup_super name lookup
\name:
	movl	4(%esp), %edx
	movl	(%edx), %eax
	test	%eax, %eax
	jz	ret_nil

	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_method_not_found
generate_lookup _objc_msg_lookup_stret _objc_method_not_found_stret
generate_lookup_super _objc_msg_lookup_super _objc_msg_lookup
generate_lookup_super _objc_msg_lookup_super_stret _objc_msg_lookup_stret

ret_nil:
	movl	$nil_method, %eax
	ret

nil_method:
	xorl	%eax, %eax
	ret







|



|


|

















|



|
|



|









|




|











|
|
|
|

|
|


|


17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
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

.globl _objc_msg_lookup
.globl _objc_msg_lookup_stret
.globl _objc_msg_lookup_super
.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

.Lmain_\name:
	movl	8(%esp), %eax

#ifdef OF_SELUID24
	movzbl	2(%eax), %ecx
	movl	(%edx,%ecx,4), %edx
#endif
	movzbl	1(%eax), %ecx
	movl	(%edx,%ecx,4), %edx
	movzbl	(%eax), %ecx
	movl	(%edx,%ecx,4), %eax

	testl	%eax, %eax
	jz	\notFound

	ret

.LtaggedPointer_\name:
	xorl	_objc_taggedPointerSecret, %edx
	andb	$0xE, %dl
	movzbl	%dl, %edx

	movl	_objc_taggedPointerClasses(,%edx,2), %edx
	movl	32(%edx), %edx

	jmp	.Lmain_\name
.def \name
.scl 2
.type 32
.endef
.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

Modified src/runtime/lookup-asm/lookup-asm-x86_64-elf.S from [e0cdb81196] to [a4b34307ef].

19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
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

.globl objc_msg_lookup
.globl objc_msg_lookup_stret
.globl objc_msg_lookup_super
.globl objc_msg_lookup_super_stret

.section .text
.macro generate_lookup name not_found
\name:
	testq	%rdi, %rdi
	jz	ret_nil

	testb	$1, %dil
	jnz	.Ltagged_pointer_\name

	movq	(%rdi), %r8
	movq	64(%r8), %r8

.Lmain_\name:
	movq	(%rsi), %rax
	movzbl	%ah, %ecx
	movzbl	%al, %edx
#ifdef OF_SELUID24
	shrl	$16, %eax

	movq	(%r8,%rax,8), %r8
#endif
	movq	(%r8,%rcx,8), %r8
	movq	(%r8,%rdx,8), %rax

	testq	%rax, %rax
	jz	\not_found@PLT

	ret

.Ltagged_pointer_\name:
	movq	objc_tagged_pointer_secret@GOTPCREL(%rip), %rax
	xorq	(%rax), %rdi
	andb	$0xE, %dil
	movzbl	%dil, %r8d

	movq	objc_tagged_pointer_classes@GOTPCREL(%rip), %rax
	movq	(%rax,%r8,4), %r8
	movq	64(%r8), %r8

	jmp	.Lmain_\name
.type \name, %function
.size \name, .-\name
.endm

.macro generate_lookup_super name lookup
\name:
	movq	%rdi, %r8
	movq	(%rdi), %rdi
	testq	%rdi, %rdi
	jz	ret_nil

	movq	8(%r8), %r8
	movq	64(%r8), %r8
	jmp	.Lmain_\lookup
.type \name, %function
.size \name, .-\name
.endm

generate_lookup objc_msg_lookup objc_method_not_found
generate_lookup objc_msg_lookup_stret objc_method_not_found_stret
generate_lookup_super objc_msg_lookup_super objc_msg_lookup
generate_lookup_super objc_msg_lookup_super_stret objc_msg_lookup_stret

ret_nil:
	leaq	nil_method(%rip), %rax
	ret

nil_method:
	xorq	%rax, %rax
	ret

#ifdef OF_LINUX
.section .note.GNU-stack, "", %progbits
#endif







|


|


|

















|



|
|




|








|




|








|
|
|
|

|
|


|






19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
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

.globl objc_msg_lookup
.globl objc_msg_lookup_stret
.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

.Lmain_\name:
	movq	(%rsi), %rax
	movzbl	%ah, %ecx
	movzbl	%al, %edx
#ifdef OF_SELUID24
	shrl	$16, %eax

	movq	(%r8,%rax,8), %r8
#endif
	movq	(%r8,%rcx,8), %r8
	movq	(%r8,%rdx,8), %rax

	testq	%rax, %rax
	jz	\notFound@PLT

	ret

.LtaggedPointer_\name:
	movq	objc_taggedPointerSecret@GOTPCREL(%rip), %rax
	xorq	(%rax), %rdi
	andb	$0xE, %dil
	movzbl	%dil, %r8d

	movq	objc_taggedPointerClasses@GOTPCREL(%rip), %rax
	movq	(%rax,%r8,4), %r8
	movq	64(%r8), %r8

	jmp	.Lmain_\name
.type \name, %function
.size \name, .-\name
.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

Modified src/runtime/lookup-asm/lookup-asm-x86_64-macho.S from [30cd6d5c1f] to [75f4b5e2f7].

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

.globl _objc_msg_lookup
.globl _objc_msg_lookup_stret
.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	ret_nil

	testb	$$1, %dil
	jnz	Ltagged_pointer_$0

	movq	(%rdi), %r8
	movq	64(%r8), %r8

Lmain_$0:
	movq	(%rsi), %rax
	movzbl	%ah, %ecx







|


|


|







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

.globl _objc_msg_lookup
.globl _objc_msg_lookup_stret
.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

Lmain_$0:
	movq	(%rsi), %rax
	movzbl	%ah, %ecx
45
46
47
48
49
50
51
52
53
54
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
	movq	(%r8,%rdx,8), %rax

	testq	%rax, %rax
	jz	$1

	ret

Ltagged_pointer_$0:
	movq	_objc_tagged_pointer_secret@GOTPCREL(%rip), %rax
	xorq	(%rax), %rdi
	andb	$$0xE, %dil
	movzbl	%dil, %r8d

	movq	_objc_tagged_pointer_classes@GOTPCREL(%rip), %rax
	movq	(%rax,%r8,4), %r8
	movq	64(%r8), %r8

	jmp	Lmain_$0
.endmacro

.macro generate_lookup_super
$0:
	movq	%rdi, %r8
	movq	(%rdi), %rdi
	testq	%rdi, %rdi
	jz	ret_nil

	movq	8(%r8), %r8
	movq	64(%r8), %r8
	jmp	Lmain_$1
.endmacro

generate_lookup _objc_msg_lookup, _objc_method_not_found
generate_lookup _objc_msg_lookup_stret, _objc_method_not_found_stret
generate_lookup_super _objc_msg_lookup_super, _objc_msg_lookup
generate_lookup_super _objc_msg_lookup_super_stret, _objc_msg_lookup_stret

ret_nil:
	leaq	nil_method(%rip), %rax
	ret

nil_method:
	xorq	%rax, %rax
	ret







|
|




|






|




|






|
|
|
|

|
|


|


45
46
47
48
49
50
51
52
53
54
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
	movq	(%r8,%rdx,8), %rax

	testq	%rax, %rax
	jz	$1

	ret

LtaggedPointer_$0:
	movq	_objc_taggedPointerSecret@GOTPCREL(%rip), %rax
	xorq	(%rax), %rdi
	andb	$$0xE, %dil
	movzbl	%dil, %r8d

	movq	_objc_taggedPointerClasses@GOTPCREL(%rip), %rax
	movq	(%rax,%r8,4), %r8
	movq	64(%r8), %r8

	jmp	Lmain_$0
.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

Modified src/runtime/lookup-asm/lookup-asm-x86_64-win64.S from [57823d1901] to [bc3f6ee83e].

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

.globl objc_msg_lookup
.globl objc_msg_lookup_stret
.globl objc_msg_lookup_super
.globl objc_msg_lookup_super_stret

.section .text
.macro generate_lookup name not_found
\name:
	testq	%rcx, %rcx
	jz	ret_nil

	testb	$1, %cl
	jnz	.Ltagged_pointer_\name

	movq	(%rcx), %r8
	movq	56(%r8), %r8

.Lmain_\name:
	movq	%rcx, %r10
	movq	%rdx, %r11







|


|


|







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

.globl objc_msg_lookup
.globl objc_msg_lookup_stret
.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

.Lmain_\name:
	movq	%rcx, %r10
	movq	%rdx, %r11
51
52
53
54
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
	jz	0f

	ret

0:
	movq	%r10, %rcx
	movq	%r11, %rdx
	jmp	\not_found

.Ltagged_pointer_\name:
	xorq	objc_tagged_pointer_secret(%rip), %rcx
	andb	$0xE, %cl
	movzbl	%cl, %r8d

	leaq	objc_tagged_pointer_classes(%rip), %rax
	movq	(%rax,%r8,4), %r8
	movq	56(%r8), %r8

	jmp	.Lmain_\name
.def \name
.scl 2
.type 32
.endef
.endm

.macro generate_lookup_super name lookup
\name:
	movq	%rcx, %r8
	movq	(%rcx), %rcx
	testq	%rcx, %rcx
	jz	ret_nil

	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_method_not_found
generate_lookup objc_msg_lookup_stret objc_method_not_found_stret
generate_lookup_super objc_msg_lookup_super objc_msg_lookup
generate_lookup_super objc_msg_lookup_super_stret objc_msg_lookup_stret

ret_nil:
	leaq	nil_method(%rip), %rax
	ret

nil_method:
	xorq	%rax, %rax
	ret







|

|
|



|










|




|










|
|
|
|

|
|


|


51
52
53
54
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
	jz	0f

	ret

0:
	movq	%r10, %rcx
	movq	%r11, %rdx
	jmp	\notFound

.LtaggedPointer_\name:
	xorq	objc_taggedPointerSecret(%rip), %rcx
	andb	$0xE, %cl
	movzbl	%cl, %r8d

	leaq	objc_taggedPointerClasses(%rip), %rax
	movq	(%rax,%r8,4), %r8
	movq	56(%r8), %r8

	jmp	.Lmain_\name
.def \name
.scl 2
.type 32
.endef
.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

Modified src/runtime/lookup-asm/lookup-asm.S from [079786db12] to [3a40e34c24].

22
23
24
25
26
27
28


29
30
31
32
33
34
35
36
#  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_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"







>
>
|







22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#  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) && (!defined(_CALL_ELF) || _CALL_ELF == 1)
#  include "lookup-asm-powerpc64-elf.S"
# elif defined(OF_POWERPC) && (!defined(_CALL_ELF) || _CALL_ELF == 1)
#  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"

Modified src/runtime/lookup.m from [041b8ab433] to [61816856c1].

37
38
39
40
41
42
43
44
45
46
47

48
49
50
51
52
53
54
55
	bool isClass =
	    object_getClass(object)->info & OBJC_CLASS_INFO_METACLASS;

	if (!(object_getClass(object)->info & OBJC_CLASS_INFO_INITIALIZED)) {
		Class class = (isClass
		    ? (Class)object : object_getClass(object));

		objc_initialize_class(class);

		if (!(class->info & OBJC_CLASS_INFO_SETUP))
			OBJC_ERROR("Could not dispatch message for incomplete "

			    "class %s!", class_getName(class));

		/*
		 * We don't need to handle the case that super was called.
		 * The reason for this is that a call to super is not possible
		 * before a message to the class has been sent and it thus has
		 * been initialized together with its superclasses.
		 */







|


|
>
|







37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
	bool isClass =
	    object_getClass(object)->info & OBJC_CLASS_INFO_METACLASS;

	if (!(object_getClass(object)->info & OBJC_CLASS_INFO_INITIALIZED)) {
		Class class = (isClass
		    ? (Class)object : object_getClass(object));

		objc_initializeClass(class);

		if (!(class->info & OBJC_CLASS_INFO_SETUP))
			OBJC_ERROR("Could not dispatch message %s for "
			    "incomplete class %s!",
			    sel_getName(selector), class_getName(class));

		/*
		 * We don't need to handle the case that super was called.
		 * The reason for this is that a call to super is not possible
		 * before a message to the class has been sent and it thus has
		 * been initialized together with its superclasses.
		 */
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

	OBJC_ERROR("Selector %c[%s] is not implemented for class %s!",
	    (isClass ? '+' : '-'), sel_getName(selector),
	    object_getClassName(object));
}

IMP
objc_method_not_found(id object, SEL selector)
{
	return commonMethodNotFound(object, selector, objc_msg_lookup,
	    forwardHandler);
}

IMP
objc_method_not_found_stret(id object, SEL selector)
{
	return commonMethodNotFound(object, selector, objc_msg_lookup_stret,
	    stretForwardHandler);
}

void
objc_setForwardHandler(IMP forward, IMP stretForward)
{
	forwardHandler = forward;
	stretForwardHandler = stretForward;
}

bool
class_respondsToSelector(Class class, SEL selector)
{
	if (class == Nil)
		return false;

	return (objc_dtable_get(class->DTable,
	    (uint32_t)selector->UID) != (IMP)0);
}

#ifndef OF_ASM_LOOKUP
static id
nilMethod(id self, SEL _cmd)
{
	return nil;
}

static OF_INLINE IMP
commonLookup(id object, SEL selector, IMP (*notFound)(id, SEL))
{
	IMP imp;

	if (object == nil)
		return (IMP)nilMethod;

	imp = objc_dtable_get(object_getClass(object)->DTable,
	    (uint32_t)selector->UID);

	if (imp == (IMP)0)
		return notFound(object, selector);

	return imp;
}

IMP
objc_msg_lookup(id object, SEL selector)
{
	return commonLookup(object, selector, objc_method_not_found);
}

IMP
objc_msg_lookup_stret(id object, SEL selector)
{
	return commonLookup(object, selector, objc_method_not_found_stret);
}

static OF_INLINE IMP
commonSuperLookup(struct objc_super *super, SEL selector,
    IMP (*notFound)(id, SEL))
{
	IMP imp;

	if (super->self == nil)
		return (IMP)nilMethod;

	imp = objc_dtable_get(super->class->DTable, (uint32_t)selector->UID);

	if (imp == (IMP)0)
		return notFound(super->self, selector);

	return imp;
}

IMP
objc_msg_lookup_super(struct objc_super *super, SEL selector)
{
	return commonSuperLookup(super, selector, objc_method_not_found);
}

IMP
objc_msg_lookup_super_stret(struct objc_super *super, SEL selector)
{
	return commonSuperLookup(super, selector, objc_method_not_found_stret);
}
#endif







|






|


















|


















|











|





|











|










|





|


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

	OBJC_ERROR("Selector %c[%s] is not implemented for class %s!",
	    (isClass ? '+' : '-'), sel_getName(selector),
	    object_getClassName(object));
}

IMP
objc_methodNotFound(id object, SEL selector)
{
	return commonMethodNotFound(object, selector, objc_msg_lookup,
	    forwardHandler);
}

IMP
objc_methodNotFound_stret(id object, SEL selector)
{
	return commonMethodNotFound(object, selector, objc_msg_lookup_stret,
	    stretForwardHandler);
}

void
objc_setForwardHandler(IMP forward, IMP stretForward)
{
	forwardHandler = forward;
	stretForwardHandler = stretForward;
}

bool
class_respondsToSelector(Class class, SEL selector)
{
	if (class == Nil)
		return false;

	return (objc_dtable_get(class->dTable,
	    (uint32_t)selector->UID) != (IMP)0);
}

#ifndef OF_ASM_LOOKUP
static id
nilMethod(id self, SEL _cmd)
{
	return nil;
}

static OF_INLINE IMP
commonLookup(id object, SEL selector, IMP (*notFound)(id, SEL))
{
	IMP imp;

	if (object == nil)
		return (IMP)nilMethod;

	imp = objc_dtable_get(object_getClass(object)->dTable,
	    (uint32_t)selector->UID);

	if (imp == (IMP)0)
		return notFound(object, selector);

	return imp;
}

IMP
objc_msg_lookup(id object, SEL selector)
{
	return commonLookup(object, selector, objc_methodNotFound);
}

IMP
objc_msg_lookup_stret(id object, SEL selector)
{
	return commonLookup(object, selector, objc_methodNotFound_stret);
}

static OF_INLINE IMP
commonSuperLookup(struct objc_super *super, SEL selector,
    IMP (*notFound)(id, SEL))
{
	IMP imp;

	if (super->self == nil)
		return (IMP)nilMethod;

	imp = objc_dtable_get(super->class->dTable, (uint32_t)selector->UID);

	if (imp == (IMP)0)
		return notFound(super->self, selector);

	return imp;
}

IMP
objc_msg_lookup_super(struct objc_super *super, SEL selector)
{
	return commonSuperLookup(super, selector, objc_methodNotFound);
}

IMP
objc_msg_lookup_super_stret(struct objc_super *super, SEL selector)
{
	return commonSuperLookup(super, selector, objc_methodNotFound_stret);
}
#endif

Modified src/runtime/method.m from [be8bb331cc] to [4ccd14f099].

28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55

56


57
58
59
60
61
62
63
64
65
66
67
68
69
	if (class == Nil) {
		if (outCount != NULL)
			*outCount = 0;

		return NULL;
	}

	objc_global_mutex_lock();

	count = 0;
	for (iter = class->methodList; iter != NULL; iter = iter->next)
		count += iter->count;

	if (count == 0) {
		if (outCount != NULL)
			*outCount = 0;

		objc_global_mutex_unlock();
		return NULL;
	}

	if ((methods = malloc((count + 1) * sizeof(Method))) == NULL)
		OBJC_ERROR("Not enough memory to copy methods");

	i = 0;
	for (iter = class->methodList; iter != NULL; iter = iter->next)
		for (unsigned int j = 0; j < iter->count; j++)
			methods[i++] = &iter->methods[j];

	OFEnsure(i == count);


	methods[count] = NULL;

	if (outCount != NULL)
		*outCount = count;

	objc_global_mutex_unlock();

	return methods;
}

SEL
method_getName(Method method)
{







|









|










>
|
>
>





|







28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
	if (class == Nil) {
		if (outCount != NULL)
			*outCount = 0;

		return NULL;
	}

	objc_globalMutex_lock();

	count = 0;
	for (iter = class->methodList; iter != NULL; iter = iter->next)
		count += iter->count;

	if (count == 0) {
		if (outCount != NULL)
			*outCount = 0;

		objc_globalMutex_unlock();
		return NULL;
	}

	if ((methods = malloc((count + 1) * sizeof(Method))) == NULL)
		OBJC_ERROR("Not enough memory to copy methods");

	i = 0;
	for (iter = class->methodList; iter != NULL; iter = iter->next)
		for (unsigned int j = 0; j < iter->count; j++)
			methods[i++] = &iter->methods[j];

	if (i != count)
		OBJC_ERROR("Fatal internal inconsistency!");

	methods[count] = NULL;

	if (outCount != NULL)
		*outCount = count;

	objc_globalMutex_unlock();

	return methods;
}

SEL
method_getName(Method method)
{

Modified src/runtime/misc.m from [3f2babee79] to [45165f1a7f].

33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# define __NOLIBBASE__
# define Class IntuitionClass
# include <proto/intuition.h>
# undef Class
# undef __NOLIBBASE__
#endif

static objc_enumeration_mutation_handler_t enumerationMutationHandler = NULL;

void
objc_enumerationMutation(id object)
{
	if (enumerationMutationHandler != NULL)
		enumerationMutationHandler(object);
	else
		OBJC_ERROR("Object was mutated during enumeration!");
}

void
objc_setEnumerationMutationHandler(objc_enumeration_mutation_handler_t handler)
{
	enumerationMutationHandler = handler;
}

void
objc_error(const char *title, const char *format, ...)
{
#if defined(OF_WINDOWS) || defined(OF_AMIGAOS)
# define BUF_LEN 512
	char message[BUF_LEN];
	int status;
	va_list args;

	va_start(args, format);
	status = vsnprintf(message, BUF_LEN, format, args);
	if (status <= 0 || status >= BUF_LEN)
		message[0] = '\0';
	va_end(args);
# undef BUF_LEN
#endif

#if defined(OF_WINDOWS)
	fprintf(stderr, "[%s] %s\n", title, message);







|











|








|
|




|
|







33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# 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)
{
	if (enumerationMutationHandler != NULL)
		enumerationMutationHandler(object);
	else
		OBJC_ERROR("Object was mutated during enumeration!");
}

void
objc_setEnumerationMutationHandler(objc_enumeration_mutation_handler handler)
{
	enumerationMutationHandler = handler;
}

void
objc_error(const char *title, const char *format, ...)
{
#if defined(OF_WINDOWS) || defined(OF_AMIGAOS)
# define messageLen 512
	char message[messageLen];
	int status;
	va_list args;

	va_start(args, format);
	status = vsnprintf(message, messageLen, format, args);
	if (status <= 0 || status >= messageLen)
		message[0] = '\0';
	va_end(args);
# undef BUF_LEN
#endif

#if defined(OF_WINDOWS)
	fprintf(stderr, "[%s] %s\n", title, message);
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147

	abort();
#endif

	OF_UNREACHABLE
}

static char *
objc_strdup(const char *string)
{
	char *copy;
	size_t length = strlen(string);

	if ((copy = (char *)malloc(length + 1)) == NULL)
		return NULL;

	memcpy(copy, string, length + 1);

	return copy;
}







|












128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147

	abort();
#endif

	OF_UNREACHABLE
}

char *
objc_strdup(const char *string)
{
	char *copy;
	size_t length = strlen(string);

	if ((copy = (char *)malloc(length + 1)) == NULL)
		return NULL;

	memcpy(copy, string, length + 1);

	return copy;
}

Deleted src/runtime/morphos-clib.h version [750cbb9d7c].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
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
/* The following function is only for the linklib. */
bool glue_objc_init(unsigned int, struct objc_libc *);
void glue___objc_exec_class(struct objc_module *);
IMP glue_objc_msg_lookup(id, SEL);
IMP glue_objc_msg_lookup_stret(id, SEL);
IMP glue_objc_msg_lookup_super(struct objc_super *, SEL);
IMP glue_objc_msg_lookup_super_stret(struct objc_super *, SEL);
Class glue_objc_lookUpClass(const char *);
Class glue_objc_getClass(const char *);
Class glue_objc_getRequiredClass(const char *);
Class glue_objc_lookup_class(const char *);
Class glue_objc_get_class(const char *);
void glue_objc_exception_throw(id);
int glue_objc_sync_enter(id);
int glue_objc_sync_exit(id);
id glue_objc_getProperty(id, SEL, ptrdiff_t, bool);
void glue_objc_setProperty(id, SEL, ptrdiff_t, id, bool, signed char);
void glue_objc_getPropertyStruct(void *, const void *, ptrdiff_t, bool, bool);
void glue_objc_setPropertyStruct(void *, const void *, ptrdiff_t, bool, bool);
void glue_objc_enumerationMutation(id);
int glue___gnu_objc_personality(int, int, uint64_t, void *, void *);
id glue_objc_retain(id);
id glue_objc_retainBlock(id);
id glue_objc_retainAutorelease(id);
void glue_objc_release(id);
id glue_objc_autorelease(id);
id glue_objc_autoreleaseReturnValue(id);
id glue_objc_retainAutoreleaseReturnValue(id);
id glue_objc_retainAutoreleasedReturnValue(id);
id glue_objc_storeStrong(id *, id);
id glue_objc_storeWeak(id *, id);
id glue_objc_loadWeakRetained(id *);
id glue_objc_initWeak(id *, id);
void glue_objc_destroyWeak(id *);
id glue_objc_loadWeak(id *);
void glue_objc_copyWeak(id *, id *);
void glue_objc_moveWeak(id *, id *);
SEL glue_sel_registerName(const char *);
const char *glue_sel_getName(SEL);
bool glue_sel_isEqual(SEL, SEL);
Class glue_objc_allocateClassPair(Class, const char *, size_t);
void glue_objc_registerClassPair(Class);
unsigned int glue_objc_getClassList(Class *, unsigned int);
Class *glue_objc_copyClassList(unsigned int *);
bool glue_class_isMetaClass(Class);
const char *glue_class_getName(Class);
Class glue_class_getSuperclass(Class);
unsigned long glue_class_getInstanceSize(Class);
bool glue_class_respondsToSelector(Class, SEL);
bool glue_class_conformsToProtocol(Class, Protocol *);
IMP glue_class_getMethodImplementation(Class, SEL);
IMP glue_class_getMethodImplementation_stret(Class, SEL);
Method glue_class_getInstanceMethod(Class, SEL);
bool glue_class_addMethod(Class, SEL, IMP, const char *);
IMP glue_class_replaceMethod(Class, SEL, IMP, const char *);
Class glue_object_getClass(id);
Class glue_object_setClass(id, Class);
const char *glue_object_getClassName(id);
const char *glue_protocol_getName(Protocol *);
bool glue_protocol_isEqual(Protocol *, Protocol *);
bool glue_protocol_conformsToProtocol(Protocol *, Protocol *);
objc_uncaught_exception_handler_t glue_objc_setUncaughtExceptionHandler(objc_uncaught_exception_handler_t);
void glue_objc_setForwardHandler(IMP, IMP);
void glue_objc_setEnumerationMutationHandler(objc_enumeration_mutation_handler_t);
id glue_objc_constructInstance(Class, void *);
void glue_objc_exit(void);
Ivar *glue_class_copyIvarList(Class, unsigned int *);
const char *glue_ivar_getName(Ivar);
const char *glue_ivar_getTypeEncoding(Ivar);
ptrdiff_t glue_ivar_getOffset(Ivar);
Method *glue_class_copyMethodList(Class, unsigned int *);
SEL glue_method_getName(Method);
const char *glue_method_getTypeEncoding(Method);
objc_property_t *glue_class_copyPropertyList(Class, unsigned int *);
const char *glue_property_getName(objc_property_t);
char *glue_property_copyAttributeValue(objc_property_t, const char *);
void *glue_objc_destructInstance(id);
void *glue_objc_autoreleasePoolPush(void);
void glue_objc_autoreleasePoolPop(void *);
id glue__objc_rootAutorelease(id);
/* The following functions are private! Don't use! */
struct objc_hashtable *glue_objc_hashtable_new(objc_hashtable_hash_func, objc_hashtable_equal_func, uint32_t);
void glue_objc_hashtable_set(struct objc_hashtable *, const void *, const void *);
void *glue_objc_hashtable_get(struct objc_hashtable *, const void *);
void glue_objc_hashtable_delete(struct objc_hashtable *, const void *);
void glue_objc_hashtable_free(struct objc_hashtable *);
/* Public functions again */
void glue_objc_setTaggedPointerSecret(uintptr_t);
int glue_objc_registerTaggedPointerClass(Class);
bool glue_object_isTaggedPointer(id);
uintptr_t glue_object_getTaggedPointerValue(id);
id glue_objc_createTaggedPointer(int, uintptr_t);
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
























































































































































































Deleted src/runtime/morphos.fd version [4a176c28f2].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
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
##base _ObjFWRTBase
##bias 30
##public
* The following function is only for the linklib.
glue_objc_init(version,libc)(sysv,r12base)
glue___objc_exec_class(module)(sysv,r12base)
glue_objc_msg_lookup(object,selector)(sysv,r12base)
glue_objc_msg_lookup_stret(object,selector)(sysv,r12base)
glue_objc_msg_lookup_super(super,selector)(sysv,r12base)
glue_objc_msg_lookup_super_stret(super,selector)(sysv,r12base)
glue_objc_lookUpClass(name)(sysv,r12base)
glue_objc_getClass(name)(sysv,r12base)
glue_objc_getRequiredClass(name)(sysv,r12base)
glue_objc_lookup_class(name)(sysv,r12base)
glue_objc_get_class(name)(sysv,r12base)
glue_objc_exception_throw(object)(sysv,r12base)
glue_objc_sync_enter(object)(sysv,r12base)
glue_objc_sync_exit(object)(sysv,r12base)
glue_objc_getProperty(self,_cmd,offset,atomic)(sysv,r12base)
glue_objc_setProperty(self,_cmd,offset,value,atomic,copy)(sysv,r12base)
glue_objc_getPropertyStruct(dest,src,size,atomic,strong)(sysv,r12base)
glue_objc_setPropertyStruct(dest,src,size,atomic,strong)(sysv,r12base)
glue_objc_enumerationMutation(object)(sysv,r12base)
glue___gnu_objc_personality(version,actions,exClass,ex,ctx)(sysv,r12base)
glue_objc_retain(object)(sysv,r12base)
glue_objc_retainBlock(block)(sysv,r12base)
glue_objc_retainAutorelease(object)(sysv,r12base)
glue_objc_release(object)(sysv,r12base)
glue_objc_autorelease(object)(sysv,r12base)
glue_objc_autoreleaseReturnValue(object)(sysv,r12base)
glue_objc_retainAutoreleaseReturnValue(object)(sysv,r12base)
glue_objc_retainAutoreleasedReturnValue(object)(sysv,r12base)
glue_objc_storeStrong(object,value)(sysv,r12base)
glue_objc_storeWeak(object,value)(sysv,r12base)
glue_objc_loadWeakRetained(object)(sysv,r12base)
glue_objc_initWeak(object,value)(sysv,r12base)
glue_objc_destroyWeak(object)(sysv,r12base)
glue_objc_loadWeak(object)(sysv,r12base)
glue_objc_copyWeak(dest,src)(sysv,r12base)
glue_objc_moveWeak(dest,src)(sysv,r12base)
glue_sel_registerName(name)(sysv,r12base)
glue_sel_getName(selector)(sysv,r12base)
glue_sel_isEqual(selector1,selector2)(sysv,r12base)
glue_objc_allocateClassPair(superclass,name,extraBytes)(sysv,r12base)
glue_objc_registerClassPair(class_)(sysv,r12base)
glue_objc_getClassList(buffer,count)(sysv,r12base)
glue_objc_copyClassList(length)(sysv,r12base)
glue_class_isMetaClass(class_)(sysv,r12base)
glue_class_getName(class_)(sysv,r12base)
glue_class_getSuperclass(class_)(sysv,r12base)
glue_class_getInstanceSize(class_)(sysv,r12base)
glue_class_respondsToSelector(class_,selector)(sysv,r12base)
glue_class_conformsToProtocol(class_,p)(sysv,r12base)
glue_class_getMethodImplementation(class_,selector)(sysv,r12base)
glue_class_getMethodImplementation_stret(class_,selector)(sysv,r12base)
glue_class_getInstanceMethod(class_,selector)(sysv,r12base)
glue_class_addMethod(class_,selector,implementation,typeEncoding)(sysv,r12base)
glue_class_replaceMethod(class_,selector,implementation,typeEncoding)(sysv,r12base)
glue_object_getClass(object)(sysv,r12base)
glue_object_setClass(object,class_)(sysv,r12base)
glue_object_getClassName(object)(sysv,r12base)
glue_protocol_getName(protocol)(sysv,r12base)
glue_protocol_isEqual(protocol1,protocol2)(sysv,r12base)
glue_protocol_conformsToProtocol(protocol1,protocol2)(sysv,r12base)
glue_objc_setUncaughtExceptionHandler(handler)(sysv,r12base)
glue_objc_setForwardHandler(forward,stretForward)(sysv,r12base)
glue_objc_setEnumerationMutationHandler(handler)(sysv,r12base)
glue_objc_constructInstance(class_,bytes)(sysv,r12base)
glue_objc_exit()(sysv,r12base)
glue_class_copyIvarList(class_,outCount)(sysv,r12base)
glue_ivar_getName(ivar)(sysv,r12base)
glue_ivar_getTypeEncoding(ivar)(sysv,r12base)
glue_ivar_getOffset(ivar)(sysv,r12base)
glue_class_copyMethodList(class_,outCount)(sysv,r12base)
glue_method_getName(method)(sysv,r12base)
glue_method_getTypeEncoding(method)(sysv,r12base)
glue_class_copyPropertyList(class_,outCount)(sysv,r12base)
glue_property_getName(property)(sysv,r12base)
glue_property_copyAttributeValue(property,name)(sysv,r12base)
glue_objc_destructInstance(object)(sysv,r12base)
glue_objc_autoreleasePoolPush()(sysv,r12base)
glue_objc_autoreleasePoolPop(pool)(sysv,r12base)
glue__objc_rootAutorelease(object)(sysv,r12base)
* The following functions are private! Don't use!
glue_objc_hashtable_new(hash,equal,size)(sysv,r12base)
glue_objc_hashtable_set(table,key,object)(sysv,r12base)
glue_objc_hashtable_get(table,key)(sysv,r12base)
glue_objc_hashtable_delete(table,key)(sysv,r12base)
glue_objc_hashtable_free(table)(sysv,r12base)
* Public functions again
glue_objc_setTaggedPointerSecret(secret)(sysv,r12base)
glue_objc_registerTaggedPointerClass(class_)(sysv,r12base)
glue_object_isTaggedPointer(object)(sysv,r12base)
glue_object_getTaggedPointerValue(object)(sysv,r12base)
glue_objc_createTaggedPointer(class_,value)(sysv,r12base)
##end
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
































































































































































































Modified src/runtime/private.h from [13fad70e4b] to [fc9de45cb0].

36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
	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;







|







36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
	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;
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
	struct objc_hashtable_bucket *_Nonnull *_Nullable data;
};

struct objc_sparsearray {
	struct objc_sparsearray_data {
		void *_Nullable next[256];
	} *_Nonnull data;
	uint8_t indexSize;
};

struct objc_dtable {
	struct objc_dtable_level2 {
#ifdef OF_SELUID24
		struct objc_dtable_level3 {
			IMP _Nullable buckets[256];







|







197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
	struct objc_hashtable_bucket *_Nonnull *_Nullable data;
};

struct objc_sparsearray {
	struct objc_sparsearray_data {
		void *_Nullable next[256];
	} *_Nonnull data;
	uint8_t levels;
};

struct objc_dtable {
	struct objc_dtable_level2 {
#ifdef OF_SELUID24
		struct objc_dtable_level3 {
			IMP _Nullable buckets[256];
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
	__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_register_all_categories(struct objc_symtab *_Nonnull);
extern struct objc_category *_Nullable *_Nullable
    objc_categories_for_class(Class _Nonnull);
extern void objc_unregister_all_categories(void);
extern void objc_initialize_class(Class _Nonnull);
extern void objc_update_dtable(Class _Nonnull);
extern void objc_register_all_classes(struct objc_symtab *_Nonnull);
extern Class _Nullable objc_classname_to_class(const char *_Nonnull, bool);
extern void objc_unregister_class(Class _Nonnull);
extern void objc_unregister_all_classes(void);
extern uint32_t objc_hash_string(const void *_Nonnull);
extern bool objc_equal_string(const void *_Nonnull, const void *_Nonnull);
extern struct objc_hashtable *_Nonnull objc_hashtable_new(
    objc_hashtable_hash_func, objc_hashtable_equal_func, uint32_t);
extern struct objc_hashtable_bucket objc_deleted_bucket;
extern void objc_hashtable_set(struct objc_hashtable *_Nonnull,
    const void *_Nonnull, const void *_Nonnull);
extern void *_Nullable objc_hashtable_get(struct objc_hashtable *_Nonnull,
    const void *_Nonnull);
extern void objc_hashtable_delete(struct objc_hashtable *_Nonnull,
    const void *_Nonnull);
extern void objc_hashtable_free(struct objc_hashtable *_Nonnull);
extern void objc_register_selector(struct objc_selector *_Nonnull);
extern void objc_register_all_selectors(struct objc_symtab *_Nonnull);
extern void objc_unregister_all_selectors(void);
extern struct objc_sparsearray *_Nonnull objc_sparsearray_new(uint8_t);
extern void *_Nullable objc_sparsearray_get(struct objc_sparsearray *_Nonnull,
    uintptr_t);
extern void objc_sparsearray_set(struct objc_sparsearray *_Nonnull, uintptr_t,
    void *_Nullable);
extern void objc_sparsearray_free(struct objc_sparsearray *_Nonnull);
extern struct objc_dtable *_Nonnull objc_dtable_new(void);
extern void objc_dtable_copy(struct objc_dtable *_Nonnull,
    struct objc_dtable *_Nonnull);
extern void objc_dtable_set(struct objc_dtable *_Nonnull, uint32_t,
    IMP _Nullable);
extern void objc_dtable_free(struct objc_dtable *_Nonnull);
extern void objc_dtable_cleanup(void);
extern void objc_init_static_instances(struct objc_symtab *_Nonnull);
extern void objc_forget_pending_static_instances(void);
extern void objc_zero_weak_references(id _Nonnull);
extern Class _Nullable object_getTaggedPointerClass(id _Nonnull);
#ifdef OF_HAVE_THREADS
extern void objc_global_mutex_lock(void);
extern void objc_global_mutex_unlock(void);
extern void objc_global_mutex_free(void);
#else
# define objc_global_mutex_lock()
# define objc_global_mutex_unlock()
# define objc_global_mutex_free()
#endif
extern char *_Nullable objc_strdup(const char *_Nonnull string);

static inline IMP _Nullable
objc_dtable_get(const struct objc_dtable *_Nonnull dtable, uint32_t idx)
{
#ifdef OF_SELUID24







|

|
|
|
|
|
|
|
|
|
|


|







|
|
|













|
|
|


|
|
|

|
|
|







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
	__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);
extern Class _Nullable objc_classnameToClass(const char *_Nonnull, bool);
extern void objc_unregisterClass(Class _Nonnull);
extern void objc_unregisterAllClasses(void);
extern uint32_t objc_string_hash(const void *_Nonnull);
extern bool objc_string_equal(const void *_Nonnull, const void *_Nonnull);
extern struct objc_hashtable *_Nonnull objc_hashtable_new(
    objc_hashtable_hash_func, objc_hashtable_equal_func, uint32_t);
extern struct objc_hashtable_bucket objc_deletedBucket;
extern void objc_hashtable_set(struct objc_hashtable *_Nonnull,
    const void *_Nonnull, const void *_Nonnull);
extern void *_Nullable objc_hashtable_get(struct objc_hashtable *_Nonnull,
    const void *_Nonnull);
extern void objc_hashtable_delete(struct objc_hashtable *_Nonnull,
    const void *_Nonnull);
extern void objc_hashtable_free(struct objc_hashtable *_Nonnull);
extern void objc_registerSelector(struct objc_selector *_Nonnull);
extern void objc_registerAllSelectors(struct objc_symtab *_Nonnull);
extern void objc_unregisterAllSelectors(void);
extern struct objc_sparsearray *_Nonnull objc_sparsearray_new(uint8_t);
extern void *_Nullable objc_sparsearray_get(struct objc_sparsearray *_Nonnull,
    uintptr_t);
extern void objc_sparsearray_set(struct objc_sparsearray *_Nonnull, uintptr_t,
    void *_Nullable);
extern void objc_sparsearray_free(struct objc_sparsearray *_Nonnull);
extern struct objc_dtable *_Nonnull objc_dtable_new(void);
extern void objc_dtable_copy(struct objc_dtable *_Nonnull,
    struct objc_dtable *_Nonnull);
extern void objc_dtable_set(struct objc_dtable *_Nonnull, uint32_t,
    IMP _Nullable);
extern void objc_dtable_free(struct objc_dtable *_Nonnull);
extern void objc_dtable_cleanup(void);
extern void objc_initStaticInstances(struct objc_symtab *_Nonnull);
extern void objc_forgetPendingStaticInstances(void);
extern void objc_zeroWeakReferences(id _Nonnull);
extern Class _Nullable object_getTaggedPointerClass(id _Nonnull);
#ifdef OF_HAVE_THREADS
extern void objc_globalMutex_lock(void);
extern void objc_globalMutex_unlock(void);
extern void objc_globalMutex_free(void);
#else
# define objc_globalMutex_lock()
# define objc_globalMutex_unlock()
# define objc_globalMutex_free()
#endif
extern char *_Nullable objc_strdup(const char *_Nonnull string);

static inline IMP _Nullable
objc_dtable_get(const struct objc_dtable *_Nonnull dtable, uint32_t idx)
{
#ifdef OF_SELUID24
354
355
356
357
358
359
360
361
362
363
364
365





366
367
368
369
370
371
372
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_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)







|




>
>
>
>
>







354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
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_ARM64) || defined(OF_ARM) || \
    defined(OF_MIPS64_N64) || defined(OF_MIPS) || \
    defined(OF_SPARC64) || defined(OF_SPARC)
#  define OF_ASM_LOOKUP
# endif
# if defined(OF_POWERPC64) || defined(OF_POWERPC)
#  if !defined(_CALL_ELF) || _CALL_ELF == 1
#   define OF_ASM_LOOKUP
#  endif
# 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)

Modified src/runtime/property.m from [34b7870e2a] to [6e20bc37ae].

18
19
20
21
22
23
24
25
26
27






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

48
49
50
51

52
53
54
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
#include <string.h>

#import "ObjFWRT.h"
#import "private.h"

#ifdef OF_HAVE_THREADS
# import "OFPlainMutex.h"
# define NUM_SPINLOCKS 8	/* needs to be a power of 2 */
# define SPINLOCK_HASH(p) ((unsigned)((uintptr_t)p >> 4) & (NUM_SPINLOCKS - 1))
static OFSpinlock spinlocks[NUM_SPINLOCKS];






#endif

#ifdef OF_HAVE_THREADS
OF_CONSTRUCTOR()
{
	for (size_t i = 0; i < NUM_SPINLOCKS; i++)
		if (OFSpinlockNew(&spinlocks[i]) != 0)
			OBJC_ERROR("Failed to initialize spinlocks!");
}
#endif

id
objc_getProperty(id self, SEL _cmd, ptrdiff_t offset, bool atomic)
{
	if (atomic) {
		id *ptr = (id *)(void *)((char *)self + offset);
#ifdef OF_HAVE_THREADS
		unsigned hash = SPINLOCK_HASH(ptr);

		OFEnsure(OFSpinlockLock(&spinlocks[hash]) == 0);

		@try {
			return [[*ptr retain] autorelease];
		} @finally {
			OFEnsure(OFSpinlockUnlock(&spinlocks[hash]) == 0);

		}
#else
		return [[*ptr retain] autorelease];
#endif
	}

	return *(id *)(void *)((char *)self + offset);
}

void
objc_setProperty(id self, SEL _cmd, ptrdiff_t offset, id value, bool atomic,
    signed char copy)
{
	if (atomic) {
		id *ptr = (id *)(void *)((char *)self + offset);
#ifdef OF_HAVE_THREADS
		unsigned hash = SPINLOCK_HASH(ptr);

		OFEnsure(OFSpinlockLock(&spinlocks[hash]) == 0);

		@try {
#endif
			id old = *ptr;

			switch (copy) {
			case 0:
				*ptr = [value retain];
				break;
			case 2:
				*ptr = [value mutableCopy];
				break;
			default:
				*ptr = [value copy];
			}

			[old release];
#ifdef OF_HAVE_THREADS
		} @finally {
			OFEnsure(OFSpinlockUnlock(&spinlocks[hash]) == 0);

		}
#endif

		return;
	}

	id *ptr = (id *)(void *)((char *)self + offset);







|
<
|
>
>
>
>
>
>





|

|









|

|
>



|
>
















|

|
>


















|
>







18
19
20
21
22
23
24
25

26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
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
#include <string.h>

#import "ObjFWRT.h"
#import "private.h"

#ifdef OF_HAVE_THREADS
# import "OFPlainMutex.h"
# define numSpinlocks 8	/* needs to be a power of 2 */

static OFSpinlock spinlocks[numSpinlocks];

static OF_INLINE size_t
spinlockSlot(const void *ptr)
{
	return ((size_t)((uintptr_t)ptr >> 4) & (numSpinlocks - 1));
}
#endif

#ifdef OF_HAVE_THREADS
OF_CONSTRUCTOR()
{
	for (size_t i = 0; i < numSpinlocks; i++)
		if (OFSpinlockNew(&spinlocks[i]) != 0)
			OBJC_ERROR("Failed to create spinlocks!");
}
#endif

id
objc_getProperty(id self, SEL _cmd, ptrdiff_t offset, bool atomic)
{
	if (atomic) {
		id *ptr = (id *)(void *)((char *)self + offset);
#ifdef OF_HAVE_THREADS
		size_t slot = spinlockSlot(ptr);

		if (OFSpinlockLock(&spinlocks[slot]) != 0)
			OBJC_ERROR("Failed to lock spinlock!");
		@try {
			return [[*ptr retain] autorelease];
		} @finally {
			if (OFSpinlockUnlock(&spinlocks[slot]) != 0)
				OBJC_ERROR("Failed to unlock spinlock!");
		}
#else
		return [[*ptr retain] autorelease];
#endif
	}

	return *(id *)(void *)((char *)self + offset);
}

void
objc_setProperty(id self, SEL _cmd, ptrdiff_t offset, id value, bool atomic,
    signed char copy)
{
	if (atomic) {
		id *ptr = (id *)(void *)((char *)self + offset);
#ifdef OF_HAVE_THREADS
		size_t slot = spinlockSlot(ptr);

		if (OFSpinlockLock(&spinlocks[slot]) != 0)
			OBJC_ERROR("Failed to lock spinlock!");
		@try {
#endif
			id old = *ptr;

			switch (copy) {
			case 0:
				*ptr = [value retain];
				break;
			case 2:
				*ptr = [value mutableCopy];
				break;
			default:
				*ptr = [value copy];
			}

			[old release];
#ifdef OF_HAVE_THREADS
		} @finally {
			if (OFSpinlockUnlock(&spinlocks[slot]) != 0)
				OBJC_ERROR("Failed to unlock spinlock!");
		}
#endif

		return;
	}

	id *ptr = (id *)(void *)((char *)self + offset);
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
/* The following methods are only required for GCC >= 4.6 */
void
objc_getPropertyStruct(void *dest, const void *src, ptrdiff_t size, bool atomic,
    bool strong)
{
	if (atomic) {
#ifdef OF_HAVE_THREADS
		unsigned hash = SPINLOCK_HASH(src);

		OFEnsure(OFSpinlockLock(&spinlocks[hash]) == 0);

#endif
		memcpy(dest, src, size);
#ifdef OF_HAVE_THREADS
		OFEnsure(OFSpinlockUnlock(&spinlocks[hash]) == 0);

#endif

		return;
	}

	memcpy(dest, src, size);
}

void
objc_setPropertyStruct(void *dest, const void *src, ptrdiff_t size, bool atomic,
    bool strong)
{
	if (atomic) {
#ifdef OF_HAVE_THREADS
		unsigned hash = SPINLOCK_HASH(src);

		OFEnsure(OFSpinlockLock(&spinlocks[hash]) == 0);

#endif
		memcpy(dest, src, size);
#ifdef OF_HAVE_THREADS
		OFEnsure(OFSpinlockUnlock(&spinlocks[hash]) == 0);

#endif

		return;
	}

	memcpy(dest, src, size);
}







|

|
>



|
>














|

|
>



|
>







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
/* The following methods are only required for GCC >= 4.6 */
void
objc_getPropertyStruct(void *dest, const void *src, ptrdiff_t size, bool atomic,
    bool strong)
{
	if (atomic) {
#ifdef OF_HAVE_THREADS
		size_t slot = spinlockSlot(src);

		if (OFSpinlockLock(&spinlocks[slot]) != 0)
			OBJC_ERROR("Failed to lock spinlock!");
#endif
		memcpy(dest, src, size);
#ifdef OF_HAVE_THREADS
		if (OFSpinlockUnlock(&spinlocks[slot]) != 0)
			OBJC_ERROR("Failed to unlock spinlock!");
#endif

		return;
	}

	memcpy(dest, src, size);
}

void
objc_setPropertyStruct(void *dest, const void *src, ptrdiff_t size, bool atomic,
    bool strong)
{
	if (atomic) {
#ifdef OF_HAVE_THREADS
		size_t slot = spinlockSlot(src);

		if (OFSpinlockLock(&spinlocks[slot]) != 0)
			OBJC_ERROR("Failed to lock spinlock!");
#endif
		memcpy(dest, src, size);
#ifdef OF_HAVE_THREADS
		if (OFSpinlockUnlock(&spinlocks[slot]) != 0)
			OBJC_ERROR("Failed to unlock spinlock!");
#endif

		return;
	}

	memcpy(dest, src, size);
}
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 (class == Nil) {
		if (outCount != NULL)
			*outCount = 0;

		return NULL;
	}

	objc_global_mutex_lock();

	count = 0;
	if (class->info & OBJC_CLASS_INFO_NEW_ABI)
		for (iter = class->propertyList; iter != NULL;
		    iter = iter->next)
			count += iter->count;

	if (count == 0) {
		if (outCount != NULL)
			*outCount = 0;

		objc_global_mutex_unlock();
		return NULL;
	}

	properties = malloc((count + 1) * sizeof(objc_property_t));
	if (properties == NULL)
		OBJC_ERROR("Not enough memory to copy properties");

	i = 0;
	for (iter = class->propertyList; iter != NULL; iter = iter->next)
		for (unsigned int j = 0; j < iter->count; j++)
			properties[i++] = &iter->properties[j];

	OFEnsure(i == count);


	properties[count] = NULL;

	if (outCount != NULL)
		*outCount = count;

	objc_global_mutex_unlock();

	return properties;
}

const char *
property_getName(objc_property_t property)
{







|











|











>
|
>
>





|







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
	if (class == Nil) {
		if (outCount != NULL)
			*outCount = 0;

		return NULL;
	}

	objc_globalMutex_lock();

	count = 0;
	if (class->info & OBJC_CLASS_INFO_NEW_ABI)
		for (iter = class->propertyList; iter != NULL;
		    iter = iter->next)
			count += iter->count;

	if (count == 0) {
		if (outCount != NULL)
			*outCount = 0;

		objc_globalMutex_unlock();
		return NULL;
	}

	properties = malloc((count + 1) * sizeof(objc_property_t));
	if (properties == NULL)
		OBJC_ERROR("Not enough memory to copy properties");

	i = 0;
	for (iter = class->propertyList; iter != NULL; iter = iter->next)
		for (unsigned int j = 0; j < iter->count; j++)
			properties[i++] = &iter->properties[j];

	if (i != count)
		OBJC_ERROR("Fatal internal inconsistency!");

	properties[count] = NULL;

	if (outCount != NULL)
		*outCount = count;

	objc_globalMutex_unlock();

	return properties;
}

const char *
property_getName(objc_property_t property)
{
249
250
251
252
253
254
255
256
257
258
259
	BOOL_CASE('D', extendedAttributes, OBJC_PROPERTY_DYNAMIC)
	BOOL_CASE('W', extendedAttributes, OBJC_PROPERTY_WEAK)
#undef BOOL_CASE
	}

	if (nullIsError && ret == NULL)
		OBJC_ERROR("Not enough memory to copy property attribute "
		    "value");

	return ret;
}







|



265
266
267
268
269
270
271
272
273
274
275
	BOOL_CASE('D', extendedAttributes, OBJC_PROPERTY_DYNAMIC)
	BOOL_CASE('W', extendedAttributes, OBJC_PROPERTY_WEAK)
#undef BOOL_CASE
	}

	if (nullIsError && ret == NULL)
		OBJC_ERROR("Not enough memory to copy property attribute "
		    "value!");

	return ret;
}

Modified src/runtime/protocol.m from [7bac61bcb9] to [375dff745f].

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
	for (struct objc_protocol_list *protocolList = class->protocols;
	    protocolList != NULL; protocolList = protocolList->next)
		for (long i = 0; i < protocolList->count; i++)
			if (protocol_conformsToProtocol(protocolList->list[i],
			    protocol))
				return true;

	objc_global_mutex_lock();

	if ((categories = objc_categories_for_class(class)) == NULL) {
		objc_global_mutex_unlock();
		return false;
	}

	for (long i = 0; categories[i] != NULL; i++) {
		for (struct objc_protocol_list *protocolList =
		    categories[i]->protocols; protocolList != NULL;
		    protocolList = protocolList->next) {
			for (long j = 0; j < protocolList->count; j++) {
				if (protocol_conformsToProtocol(
				    protocolList->list[j], protocol)) {
					objc_global_mutex_unlock();
					return true;
				}
			}
		}
	}

	objc_global_mutex_unlock();

	return false;
}







|

|
|










|






|



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
	for (struct objc_protocol_list *protocolList = class->protocols;
	    protocolList != NULL; protocolList = protocolList->next)
		for (long i = 0; i < protocolList->count; i++)
			if (protocol_conformsToProtocol(protocolList->list[i],
			    protocol))
				return true;

	objc_globalMutex_lock();

	if ((categories = objc_categoriesForClass(class)) == NULL) {
		objc_globalMutex_unlock();
		return false;
	}

	for (long i = 0; categories[i] != NULL; i++) {
		for (struct objc_protocol_list *protocolList =
		    categories[i]->protocols; protocolList != NULL;
		    protocolList = protocolList->next) {
			for (long j = 0; j < protocolList->count; j++) {
				if (protocol_conformsToProtocol(
				    protocolList->list[j], protocol)) {
					objc_globalMutex_unlock();
					return true;
				}
			}
		}
	}

	objc_globalMutex_unlock();

	return false;
}

Modified src/runtime/selector.m from [7cee0dae00] to [595eb87101].

21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
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

#import "ObjFWRT.h"
#import "private.h"

#import "macros.h"

#ifdef OF_SELUID24
# define SEL_MAX 0xFFFFFF
# define SEL_SIZE 3
#else
# define SEL_MAX 0xFFFF
# define SEL_SIZE 2
#endif

static struct objc_hashtable *selectors = NULL;
static uint32_t selectorsCount = 0;
static struct objc_sparsearray *selectorNames = NULL;
static void **freeList = NULL;
static size_t freeListCount = 0;

void
objc_register_selector(struct objc_selector *selector)
{
	SEL existingSelector;
	const char *name;

	if (selectorsCount > SEL_MAX)
		OBJC_ERROR("Out of selector slots!");

	if (selectors == NULL)
		selectors = objc_hashtable_new(
		    objc_hash_string, objc_equal_string, 2);
	else if ((existingSelector = objc_hashtable_get(selectors,
	    (const char *)selector->UID)) != NULL) {
		selector->UID = existingSelector->UID;
		return;
	}

	if (selectorNames == NULL)
		selectorNames = objc_sparsearray_new(SEL_SIZE);

	name = (const char *)selector->UID;
	selector->UID = selectorsCount++;

	objc_hashtable_set(selectors, name, selector);
	objc_sparsearray_set(selectorNames, (uint32_t)selector->UID,
	    (void *)name);
}

SEL
sel_registerName(const char *name)
{
	struct objc_selector *selector;

	objc_global_mutex_lock();

	if (selectors != NULL &&
	    (selector = objc_hashtable_get(selectors, name)) != NULL) {
		objc_global_mutex_unlock();
		return (SEL)selector;
	}

	if ((selector = malloc(sizeof(*selector))) == NULL)
		OBJC_ERROR("Not enough memory to allocate selector!");

	if ((selector->UID = (uintptr_t)objc_strdup(name)) == 0)
		OBJC_ERROR("Not enough memory to allocate selector!");

	selector->typeEncoding = NULL;

	if ((freeList = realloc(freeList,
	    sizeof(void *) * (freeListCount + 2))) == NULL)
		OBJC_ERROR("Not enough memory to allocate selector!");

	freeList[freeListCount++] = selector;
	freeList[freeListCount++] = (char *)selector->UID;

	objc_register_selector(selector);

	objc_global_mutex_unlock();
	return (SEL)selector;
}

void
objc_register_all_selectors(struct objc_symtab *symtab)
{
	struct objc_selector *selector;

	if (symtab->selectorRefs == NULL)
		return;

	for (selector = symtab->selectorRefs; selector->UID != 0; selector++)
		objc_register_selector(selector);
}

const char *
sel_getName(SEL selector)
{
	const char *ret;

	objc_global_mutex_lock();
	ret = objc_sparsearray_get(selectorNames, (uint32_t)selector->UID);
	objc_global_mutex_unlock();

	return ret;
}

bool
sel_isEqual(SEL selector1, SEL selector2)
{
	return (selector1->UID == selector2->UID);
}

void
objc_unregister_all_selectors(void)
{
	objc_hashtable_free(selectors);
	objc_sparsearray_free(selectorNames);

	if (freeList != NULL) {
		for (size_t i = 0; i < freeListCount; i++)
			free(freeList[i]);







|
|

|
|









|




|




|







|














|



|



|
<
<
|











|

|




|







|







|

|











|







21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
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

#import "ObjFWRT.h"
#import "private.h"

#import "macros.h"

#ifdef OF_SELUID24
static const uint32_t maxSel = 0xFFFFFF;
static const uint8_t selLevels = 3;
#else
static const uint32_t maxSel = 0xFFFF;
static const uint8_t selLevels = 2;
#endif

static struct objc_hashtable *selectors = NULL;
static uint32_t selectorsCount = 0;
static struct objc_sparsearray *selectorNames = NULL;
static void **freeList = NULL;
static size_t freeListCount = 0;

void
objc_registerSelector(struct objc_selector *selector)
{
	SEL existingSelector;
	const char *name;

	if (selectorsCount > maxSel)
		OBJC_ERROR("Out of selector slots!");

	if (selectors == NULL)
		selectors = objc_hashtable_new(
		    objc_string_hash, objc_string_equal, 2);
	else if ((existingSelector = objc_hashtable_get(selectors,
	    (const char *)selector->UID)) != NULL) {
		selector->UID = existingSelector->UID;
		return;
	}

	if (selectorNames == NULL)
		selectorNames = objc_sparsearray_new(selLevels);

	name = (const char *)selector->UID;
	selector->UID = selectorsCount++;

	objc_hashtable_set(selectors, name, selector);
	objc_sparsearray_set(selectorNames, (uint32_t)selector->UID,
	    (void *)name);
}

SEL
sel_registerName(const char *name)
{
	struct objc_selector *selector;

	objc_globalMutex_lock();

	if (selectors != NULL &&
	    (selector = objc_hashtable_get(selectors, name)) != NULL) {
		objc_globalMutex_unlock();
		return (SEL)selector;
	}

	if ((selector = malloc(sizeof(*selector))) == NULL ||


	    (selector->UID = (uintptr_t)objc_strdup(name)) == 0)
		OBJC_ERROR("Not enough memory to allocate selector!");

	selector->typeEncoding = NULL;

	if ((freeList = realloc(freeList,
	    sizeof(void *) * (freeListCount + 2))) == NULL)
		OBJC_ERROR("Not enough memory to allocate selector!");

	freeList[freeListCount++] = selector;
	freeList[freeListCount++] = (char *)selector->UID;

	objc_registerSelector(selector);

	objc_globalMutex_unlock();
	return (SEL)selector;
}

void
objc_registerAllSelectors(struct objc_symtab *symtab)
{
	struct objc_selector *selector;

	if (symtab->selectorRefs == NULL)
		return;

	for (selector = symtab->selectorRefs; selector->UID != 0; selector++)
		objc_registerSelector(selector);
}

const char *
sel_getName(SEL selector)
{
	const char *ret;

	objc_globalMutex_lock();
	ret = objc_sparsearray_get(selectorNames, (uint32_t)selector->UID);
	objc_globalMutex_unlock();

	return ret;
}

bool
sel_isEqual(SEL selector1, SEL selector2)
{
	return (selector1->UID == selector2->UID);
}

void
objc_unregisterAllSelectors(void)
{
	objc_hashtable_free(selectors);
	objc_sparsearray_free(selectorNames);

	if (freeList != NULL) {
		for (size_t i = 0; i < freeListCount; i++)
			free(freeList[i]);

Modified src/runtime/sparsearray.m from [dc25cc4021] to [0600278cf2].

18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
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 <stdio.h>
#include <stdlib.h>

#import "ObjFWRT.h"
#import "private.h"

struct objc_sparsearray *
objc_sparsearray_new(uint8_t indexSize)
{
	struct objc_sparsearray *sparsearray;

	if ((sparsearray = calloc(1, sizeof(*sparsearray))) == NULL)
		OBJC_ERROR("Failed to allocate memory for sparse array!");

	if ((sparsearray->data = calloc(1, sizeof(*sparsearray->data))) == NULL)
		OBJC_ERROR("Failed to allocate memory for sparse array!");

	sparsearray->indexSize = indexSize;

	return sparsearray;
}

void *
objc_sparsearray_get(struct objc_sparsearray *sparsearray, uintptr_t idx)
{
	struct objc_sparsearray_data *iter = sparsearray->data;

	for (uint8_t i = 0; i < sparsearray->indexSize - 1; i++) {
		uintptr_t j =
		    (idx >> ((sparsearray->indexSize - i - 1) * 8)) & 0xFF;

		if ((iter = iter->next[j]) == NULL)
			return NULL;
	}

	return iter->next[idx & 0xFF];
}

void
objc_sparsearray_set(struct objc_sparsearray *sparsearray, uintptr_t idx,
    void *value)
{
	struct objc_sparsearray_data *iter = sparsearray->data;

	for (uint8_t i = 0; i < sparsearray->indexSize - 1; i++) {
		uintptr_t j =
		    (idx >> ((sparsearray->indexSize - i - 1) * 8)) & 0xFF;

		if (iter->next[j] == NULL)
			if ((iter->next[j] = calloc(1,
			    sizeof(struct objc_sparsearray_data))) == NULL)
				OBJC_ERROR("Failed to allocate memory for "
				    "sparse array!");








|



|
<
<
|


|









|

|














|

|







18
19
20
21
22
23
24
25
26
27
28
29


30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#include <stdio.h>
#include <stdlib.h>

#import "ObjFWRT.h"
#import "private.h"

struct objc_sparsearray *
objc_sparsearray_new(uint8_t levels)
{
	struct objc_sparsearray *sparsearray;

	if ((sparsearray = calloc(1, sizeof(*sparsearray))) == NULL ||


	    (sparsearray->data = calloc(1, sizeof(*sparsearray->data))) == NULL)
		OBJC_ERROR("Failed to allocate memory for sparse array!");

	sparsearray->levels = levels;

	return sparsearray;
}

void *
objc_sparsearray_get(struct objc_sparsearray *sparsearray, uintptr_t idx)
{
	struct objc_sparsearray_data *iter = sparsearray->data;

	for (uint8_t i = 0; i < sparsearray->levels - 1; i++) {
		uintptr_t j =
		    (idx >> ((sparsearray->levels - i - 1) * 8)) & 0xFF;

		if ((iter = iter->next[j]) == NULL)
			return NULL;
	}

	return iter->next[idx & 0xFF];
}

void
objc_sparsearray_set(struct objc_sparsearray *sparsearray, uintptr_t idx,
    void *value)
{
	struct objc_sparsearray_data *iter = sparsearray->data;

	for (uint8_t i = 0; i < sparsearray->levels - 1; i++) {
		uintptr_t j =
		    (idx >> ((sparsearray->levels - i - 1) * 8)) & 0xFF;

		if (iter->next[j] == NULL)
			if ((iter->next[j] = calloc(1,
			    sizeof(struct objc_sparsearray_data))) == NULL)
				OBJC_ERROR("Failed to allocate memory for "
				    "sparse array!");

86
87
88
89
90
91
92
93
94
95

	free(data);
}

void
objc_sparsearray_free(struct objc_sparsearray *sparsearray)
{
	freeSparsearrayData(sparsearray->data, sparsearray->indexSize);
	free(sparsearray);
}







|


84
85
86
87
88
89
90
91
92
93

	free(data);
}

void
objc_sparsearray_free(struct objc_sparsearray *sparsearray)
{
	freeSparsearrayData(sparsearray->data, sparsearray->levels);
	free(sparsearray);
}

Modified src/runtime/static-instances.m from [9308a0dd6f] to [5b5e1b3d9a].

21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#import "ObjFWRT.h"
#import "private.h"

static struct objc_static_instances **staticInstancesList = NULL;
static size_t staticInstancesCount = 0;

void
objc_init_static_instances(struct objc_symtab *symtab)
{
	struct objc_static_instances **staticInstances;

	/* Check if the class for a static instance became available */
	for (size_t i = 0; i < staticInstancesCount; i++) {
		Class class = objc_lookUpClass(
		    staticInstancesList[i]->className);







|







21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#import "ObjFWRT.h"
#import "private.h"

static struct objc_static_instances **staticInstancesList = NULL;
static size_t staticInstancesCount = 0;

void
objc_initStaticInstances(struct objc_symtab *symtab)
{
	struct objc_static_instances **staticInstances;

	/* Check if the class for a static instance became available */
	for (size_t i = 0; i < staticInstancesCount; i++) {
		Class class = objc_lookUpClass(
		    staticInstancesList[i]->className);
91
92
93
94
95
96
97
98
99
100
101
102
103
			staticInstancesList[staticInstancesCount++] =
			    *staticInstances;
		}
	}
}

void
objc_forget_pending_static_instances()
{
	free(staticInstancesList);
	staticInstancesList = NULL;
	staticInstancesCount = 0;
}







|





91
92
93
94
95
96
97
98
99
100
101
102
103
			staticInstancesList[staticInstancesCount++] =
			    *staticInstances;
		}
	}
}

void
objc_forgetPendingStaticInstances()
{
	free(staticInstancesList);
	staticInstancesList = NULL;
	staticInstancesCount = 0;
}

Modified src/runtime/synchronized.m from [90a59dedf3] to [4edf9604c8].

20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57

#import "ObjFWRT.h"
#import "private.h"

#ifdef OF_HAVE_THREADS
# import "OFPlainMutex.h"

static struct lock {
	id object;
	int count;
	OFPlainRecursiveMutex rmutex;
	struct lock *next;
} *locks = NULL;

static OFPlainMutex mutex;

OF_CONSTRUCTOR()
{
	if (OFPlainMutexNew(&mutex) != 0)
		OBJC_ERROR("Failed to create mutex!");
}
#endif

int
objc_sync_enter(id object)
{
	if (object == nil)
		return 0;

#ifdef OF_HAVE_THREADS
	struct lock *lock;

	if (OFPlainMutexLock(&mutex) != 0)
		OBJC_ERROR("Failed to lock mutex!");

	/* Look if we already have a lock */
	for (lock = locks; lock != NULL; lock = lock->next) {
		if (lock->object != object)







|



|


















|







20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57

#import "ObjFWRT.h"
#import "private.h"

#ifdef OF_HAVE_THREADS
# import "OFPlainMutex.h"

static struct Lock {
	id object;
	int count;
	OFPlainRecursiveMutex rmutex;
	struct Lock *next;
} *locks = NULL;

static OFPlainMutex mutex;

OF_CONSTRUCTOR()
{
	if (OFPlainMutexNew(&mutex) != 0)
		OBJC_ERROR("Failed to create mutex!");
}
#endif

int
objc_sync_enter(id object)
{
	if (object == nil)
		return 0;

#ifdef OF_HAVE_THREADS
	struct Lock *lock;

	if (OFPlainMutexLock(&mutex) != 0)
		OBJC_ERROR("Failed to lock mutex!");

	/* Look if we already have a lock */
	for (lock = locks; lock != NULL; lock = lock->next) {
		if (lock->object != object)
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
int
objc_sync_exit(id object)
{
	if (object == nil)
		return 0;

#ifdef OF_HAVE_THREADS
	struct lock *lock, *last = NULL;

	if (OFPlainMutexLock(&mutex) != 0)
		OBJC_ERROR("Failed to lock mutex!");

	for (lock = locks; lock != NULL; lock = lock->next) {
		if (lock->object != object) {
			last = lock;







|







94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
int
objc_sync_exit(id object)
{
	if (object == nil)
		return 0;

#ifdef OF_HAVE_THREADS
	struct Lock *lock, *last = NULL;

	if (OFPlainMutexLock(&mutex) != 0)
		OBJC_ERROR("Failed to lock mutex!");

	for (lock = locks; lock != NULL; lock = lock->next) {
		if (lock->object != object) {
			last = lock;
126
127
128
129
130
131
132
133
134
135
136
137

		if (OFPlainMutexUnlock(&mutex) != 0)
			OBJC_ERROR("Failed to unlock mutex!");

		return 0;
	}

	OBJC_ERROR("objc_sync_exit() was called for an object not locked!");
#else
	return 0;
#endif
}







|




126
127
128
129
130
131
132
133
134
135
136
137

		if (OFPlainMutexUnlock(&mutex) != 0)
			OBJC_ERROR("Failed to unlock mutex!");

		return 0;
	}

	OBJC_ERROR("objc_sync_exit() was called for an unlocked object!");
#else
	return 0;
#endif
}

Modified src/runtime/tagged-pointer.m from [a6a4aa7d0f] to [84026d482b].

13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
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
 * file.
 */

#import "ObjFWRT.h"

#import "private.h"

#define TAGGED_POINTER_BITS 4
#define NUM_TAGGED_POINTER_CLASSES (1 << (TAGGED_POINTER_BITS - 1))

Class objc_tagged_pointer_classes[NUM_TAGGED_POINTER_CLASSES];
static int taggedPointerClassesCount;
uintptr_t objc_tagged_pointer_secret;

void
objc_setTaggedPointerSecret(uintptr_t secret)
{
	objc_tagged_pointer_secret = secret & ~(uintptr_t)1;
}

int
objc_registerTaggedPointerClass(Class class)
{
	int i;

	objc_global_mutex_lock();

	if (taggedPointerClassesCount == NUM_TAGGED_POINTER_CLASSES) {
		objc_global_mutex_unlock();
		return -1;
	}

	i = taggedPointerClassesCount++;
	objc_tagged_pointer_classes[i] = class;

	objc_global_mutex_unlock();

	return i;
}

bool
object_isTaggedPointer(id object)
{
	uintptr_t pointer = (uintptr_t)object;

	return pointer & 1;
}

Class
object_getTaggedPointerClass(id object)
{
	uintptr_t pointer = (uintptr_t)object ^ objc_tagged_pointer_secret;

	pointer &= (1 << TAGGED_POINTER_BITS) - 1;
	pointer >>= 1;

	if (pointer >= NUM_TAGGED_POINTER_CLASSES)
		return Nil;

	return objc_tagged_pointer_classes[pointer];
}

uintptr_t
object_getTaggedPointerValue(id object)
{
	uintptr_t pointer = (uintptr_t)object ^ objc_tagged_pointer_secret;

	pointer >>= TAGGED_POINTER_BITS;

	return pointer;
}

id
objc_createTaggedPointer(int class, uintptr_t value)
{
	uintptr_t pointer;

	if (class < 0 || class >= NUM_TAGGED_POINTER_CLASSES)
		return nil;

	if (value > (UINTPTR_MAX >> TAGGED_POINTER_BITS))
		return nil;

	pointer = (class << 1) | 1;
	pointer |= (value << TAGGED_POINTER_BITS);

	return (id)(pointer ^ objc_tagged_pointer_secret);
}







|
|

|

|




|







|

|
|




|

|















|

|


|


|





|

|









|


|



|

|

13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
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
 * file.
 */

#import "ObjFWRT.h"

#import "private.h"

#define numTaggedPointerBits 4
#define maxNumTaggedPointerClasses (1 << (numTaggedPointerBits - 1))

Class objc_taggedPointerClasses[maxNumTaggedPointerClasses];
static int taggedPointerClassesCount;
uintptr_t objc_taggedPointerSecret;

void
objc_setTaggedPointerSecret(uintptr_t secret)
{
	objc_taggedPointerSecret = secret & ~(uintptr_t)1;
}

int
objc_registerTaggedPointerClass(Class class)
{
	int i;

	objc_globalMutex_lock();

	if (taggedPointerClassesCount == maxNumTaggedPointerClasses) {
		objc_globalMutex_unlock();
		return -1;
	}

	i = taggedPointerClassesCount++;
	objc_taggedPointerClasses[i] = class;

	objc_globalMutex_unlock();

	return i;
}

bool
object_isTaggedPointer(id object)
{
	uintptr_t pointer = (uintptr_t)object;

	return pointer & 1;
}

Class
object_getTaggedPointerClass(id object)
{
	uintptr_t pointer = (uintptr_t)object ^ objc_taggedPointerSecret;

	pointer &= (1 << numTaggedPointerBits) - 1;
	pointer >>= 1;

	if (pointer >= maxNumTaggedPointerClasses)
		return Nil;

	return objc_taggedPointerClasses[pointer];
}

uintptr_t
object_getTaggedPointerValue(id object)
{
	uintptr_t pointer = (uintptr_t)object ^ objc_taggedPointerSecret;

	pointer >>= numTaggedPointerBits;

	return pointer;
}

id
objc_createTaggedPointer(int class, uintptr_t value)
{
	uintptr_t pointer;

	if (class < 0 || class >= maxNumTaggedPointerClasses)
		return nil;

	if (value > (UINTPTR_MAX >> numTaggedPointerBits))
		return nil;

	pointer = (class << 1) | 1;
	pointer |= (value << numTaggedPointerBits);

	return (id)(pointer ^ objc_taggedPointerSecret);
}

Modified src/runtime/threading.m from [34d13c2d7f] to [9fcf574ba3].

30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
init(void)
{
	if (OFPlainRecursiveMutexNew(&globalMutex) != 0)
		OBJC_ERROR("Failed to create global mutex!");
}

void
objc_global_mutex_lock(void)
{
	static OFOnceControl onceControl = OFOnceControlInitValue;
	OFOnce(&onceControl, init);

	if (OFPlainRecursiveMutexLock(&globalMutex) != 0)
		OBJC_ERROR("Failed to lock global mutex!");
}

void
objc_global_mutex_unlock(void)
{
	if (OFPlainRecursiveMutexUnlock(&globalMutex) != 0)
		OBJC_ERROR("Failed to unlock global mutex!");
}







|









|




30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
init(void)
{
	if (OFPlainRecursiveMutexNew(&globalMutex) != 0)
		OBJC_ERROR("Failed to create global mutex!");
}

void
objc_globalMutex_lock(void)
{
	static OFOnceControl onceControl = OFOnceControlInitValue;
	OFOnce(&onceControl, init);

	if (OFPlainRecursiveMutexLock(&globalMutex) != 0)
		OBJC_ERROR("Failed to lock global mutex!");
}

void
objc_globalMutex_unlock(void)
{
	if (OFPlainRecursiveMutexUnlock(&globalMutex) != 0)
		OBJC_ERROR("Failed to unlock global mutex!");
}

Modified tests/ForwardingTests.m from [243d088ca9] to [4df4ada152].

15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
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 "config.h"

#include <string.h>

#import "TestsAppDelegate.h"

#define FMT @"%@ %@ %@ %@ %@ %@ %@ %@ %@ %g %g %g %g %g %g %g %g %g"
#define ARGS @"a", @"b", @"c", @"d", @"e", @"f", @"g", @"h", @"i", \
	    1.5, 2.25, 3.125, 4.0625, 5.03125, 6.5, 7.25, 8.0, 9.0
#define RESULT @"a b c d e f g h i 1.5 2.25 3.125 4.0625 5.03125 6.5 7.25 8 9"

static OFString *module = @"Forwarding";
static size_t forwardings = 0;
static bool success = false;
static id target = nil;

struct stret_test {
	char s[1024];
};

@interface ForwardingTest: OFObject
@end

@interface ForwardingTest (Test)
+ (void)test;
- (void)test;
- (uint32_t)forwardingTargetTest: (intptr_t)a0
				: (intptr_t)a1
				: (double)a2
				: (double)a3;
- (OFString *)forwardingTargetVarArgTest: (OFConstantString *)fmt, ...;
- (long double)forwardingTargetFPRetTest;
- (struct stret_test)forwardingTargetStRetTest;
- (void)forwardingTargetNilTest;
- (void)forwardingTargetSelfTest;
- (struct stret_test)forwardingTargetNilStRetTest;
- (struct stret_test)forwardingTargetSelfStRetTest;
@end

@interface ForwardingTarget: OFObject
@end

static void
test(id self, SEL _cmd)
{
	success = true;
}

@implementation ForwardingTest
+ (bool)resolveClassMethod: (SEL)selector
{
	forwardings++;

	if (sel_isEqual(selector, @selector(test))) {
		class_replaceMethod(object_getClass(self), @selector(test),
		    (IMP)test, "v#:");
		return YES;
	}

	return NO;
}

+ (bool)resolveInstanceMethod: (SEL)selector
{
	forwardings++;

	if (sel_isEqual(selector, @selector(test))) {
		class_replaceMethod(self, @selector(test), (IMP)test, "v@:");
		return YES;
	}

	return NO;







|




|
|



|
|












|

|


|
|














|












|







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
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 "config.h"

#include <string.h>

#import "TestsAppDelegate.h"

#define FORMAT @"%@ %@ %@ %@ %@ %@ %@ %@ %@ %g %g %g %g %g %g %g %g %g"
#define ARGS @"a", @"b", @"c", @"d", @"e", @"f", @"g", @"h", @"i", \
	    1.5, 2.25, 3.125, 4.0625, 5.03125, 6.5, 7.25, 8.0, 9.0
#define RESULT @"a b c d e f g h i 1.5 2.25 3.125 4.0625 5.03125 6.5 7.25 8 9"

static OFString *const module = @"Forwarding";
static size_t forwardingsCount = 0;
static bool success = false;
static id target = nil;

struct StretTest {
	char buffer[1024];
};

@interface ForwardingTest: OFObject
@end

@interface ForwardingTest (Test)
+ (void)test;
- (void)test;
- (uint32_t)forwardingTargetTest: (intptr_t)a0
				: (intptr_t)a1
				: (double)a2
				: (double)a3;
- (OFString *)forwardingTargetVarArgTest: (OFConstantString *)format, ...;
- (long double)forwardingTargetFPRetTest;
- (struct StretTest)forwardingTargetStRetTest;
- (void)forwardingTargetNilTest;
- (void)forwardingTargetSelfTest;
- (struct StretTest)forwardingTargetNilStRetTest;
- (struct StretTest)forwardingTargetSelfStRetTest;
@end

@interface ForwardingTarget: OFObject
@end

static void
test(id self, SEL _cmd)
{
	success = true;
}

@implementation ForwardingTest
+ (bool)resolveClassMethod: (SEL)selector
{
	forwardingsCount++;

	if (sel_isEqual(selector, @selector(test))) {
		class_replaceMethod(object_getClass(self), @selector(test),
		    (IMP)test, "v#:");
		return YES;
	}

	return NO;
}

+ (bool)resolveInstanceMethod: (SEL)selector
{
	forwardingsCount++;

	if (sel_isEqual(selector, @selector(test))) {
		class_replaceMethod(self, @selector(test), (IMP)test, "v@:");
		return YES;
	}

	return NO;
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
		return 0;
	if (a3 != 2.75)
		return 0;

	return 0x12345678;
}

- (OFString *)forwardingTargetVarArgTest: (OFConstantString *)fmt, ...
{
	va_list args;
	OFString *ret;

	OFEnsure(self == target);

	va_start(args, fmt);
	ret = [[[OFString alloc] initWithFormat: fmt
				      arguments: args] autorelease];
	va_end(args);

	return ret;
}

- (long double)forwardingTargetFPRetTest
{
	OFEnsure(self == target);

	return 12345678.00006103515625;
}

- (struct stret_test)forwardingTargetStRetTest
{
	struct stret_test ret = { { 0 } };

	OFEnsure(self == target);

	memcpy(ret.s, "abcdefghijklmnopqrstuvwxyz", 27);

	return ret;
}
@end

@implementation TestsAppDelegate (ForwardingTests)
- (void)forwardingTests
{
	void *pool = objc_autoreleasePoolPush();

	TEST(@"Forwarding a message and adding a class method",
	    R([ForwardingTest test]) && success &&
	    R([ForwardingTest test]) && forwardings == 1);


	ForwardingTest *t = [[[ForwardingTest alloc] init] autorelease];

	success = false;
	forwardings = 0;

	TEST(@"Forwarding a message and adding an instance method",
	    R([t test]) && success && R([t test]) && forwardings == 1);


#ifdef OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR
	target = [[[ForwardingTarget alloc] init] autorelease];
	TEST(@"-[forwardingTargetForSelector:]",
	    [t forwardingTargetTest: 0xDEADBEEF
				   : -1
				   : 1.25
				   : 2.75] == 0x12345678)
	TEST(@"-[forwardingTargetForSelector:] variable arguments",
	    [[t forwardingTargetVarArgTest: FMT, 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",
	    [t forwardingTargetFPRetTest] == 12345678.00006103515625)
# endif
# ifdef OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR_STRET
	TEST(@"-[forwardingTargetForSelector:] struct return",
	    !memcmp([t forwardingTargetStRetTest].s,
	    "abcdefghijklmnopqrstuvwxyz", 27))
# endif
	EXPECT_EXCEPTION(@"-[forwardingTargetForSelector:] nil target",
	    OFNotImplementedException, [t forwardingTargetNilTest])
	EXPECT_EXCEPTION(@"-[forwardingTargetForSelector:] self target",
	    OFNotImplementedException, [t forwardingTargetSelfTest])
# ifdef OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR_STRET
	EXPECT_EXCEPTION(@"-[forwardingTargetForSelector:] nil target + "
	    @"stret", OFNotImplementedException,
	    [t forwardingTargetNilStRetTest])
	EXPECT_EXCEPTION(@"-[forwardingTargetForSelector:] self target + "
	    @"stret", OFNotImplementedException,
	    [t forwardingTargetSelfStRetTest])
# endif
#endif

	objc_autoreleasePoolPop(pool);
}
@end







|






|
|













|

|



|












|

>
|


|


|
>




|
|
|
|

|
>







|



|



|

|



|


|






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
		return 0;
	if (a3 != 2.75)
		return 0;

	return 0x12345678;
}

- (OFString *)forwardingTargetVarArgTest: (OFConstantString *)format, ...
{
	va_list args;
	OFString *ret;

	OFEnsure(self == target);

	va_start(args, format);
	ret = [[[OFString alloc] initWithFormat: format
				      arguments: args] autorelease];
	va_end(args);

	return ret;
}

- (long double)forwardingTargetFPRetTest
{
	OFEnsure(self == target);

	return 12345678.00006103515625;
}

- (struct StretTest)forwardingTargetStRetTest
{
	struct StretTest ret = { { 0 } };

	OFEnsure(self == target);

	memcpy(ret.buffer, "abcdefghijklmnopqrstuvwxyz", 27);

	return ret;
}
@end

@implementation TestsAppDelegate (ForwardingTests)
- (void)forwardingTests
{
	void *pool = objc_autoreleasePoolPush();

	TEST(@"Forwarding a message and adding a class method",
	    R([ForwardingTest test]) && success &&
	    R([ForwardingTest test]) && forwardingsCount == 1);

	ForwardingTest *testObject =
	    [[[ForwardingTest alloc] init] autorelease];

	success = false;
	forwardingsCount = 0;

	TEST(@"Forwarding a message and adding an instance method",
	    R([testObject test]) && success && R([testObject test]) &&
	    forwardingsCount == 1);

#ifdef OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR
	target = [[[ForwardingTarget alloc] init] autorelease];
	TEST(@"-[forwardingTargetForSelector:]",
	    [testObject forwardingTargetTest: 0xDEADBEEF
					    : -1
					    : 1.25
					    : 2.75] == 0x12345678)
	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))
# endif
	EXPECT_EXCEPTION(@"-[forwardingTargetForSelector:] nil target",
	    OFNotImplementedException, [testObject forwardingTargetNilTest])
	EXPECT_EXCEPTION(@"-[forwardingTargetForSelector:] self target",
	    OFNotImplementedException, [testObject forwardingTargetSelfTest])
# ifdef OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR_STRET
	EXPECT_EXCEPTION(@"-[forwardingTargetForSelector:] nil target + "
	    @"stret", OFNotImplementedException,
	    [testObject forwardingTargetNilStRetTest])
	EXPECT_EXCEPTION(@"-[forwardingTargetForSelector:] self target + "
	    @"stret", OFNotImplementedException,
	    [testObject forwardingTargetSelfStRetTest])
# endif
#endif

	objc_autoreleasePoolPop(pool);
}
@end

Modified tests/Makefile from [a491bea751] to [c0f76538e2].

1
2
3


4
5
6
7
8
9
10
include ../extra.mk

SUBDIRS = ${TESTPLUGIN}



CLEAN = EBOOT.PBP		\
	boot.dol		\
	${PROG_NOINST}.arm9	\
	${PROG_NOINST}.nds
DISTCLEAN = Info.plist



|
>
>







1
2
3
4
5
6
7
8
9
10
11
12
include ../extra.mk

SUBDIRS = ${TESTPLUGIN}	\
	  ${OBJC_SYNC}	\
	  terminal

CLEAN = EBOOT.PBP		\
	boot.dol		\
	${PROG_NOINST}.arm9	\
	${PROG_NOINST}.nds
DISTCLEAN = Info.plist

20
21
22
23
24
25
26

27

28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
       OFInvocationTests.m		\
       OFJSONTests.m			\
       OFListTests.m			\
       OFLocaleTests.m			\
       OFMethodSignatureTests.m		\
       OFNumberTests.m			\
       OFObjectTests.m			\

       OFPropertyListTests.m		\

       OFSetTests.m			\
       OFStreamTests.m			\
       OFStringTests.m			\
       OFSystemInfoTests.m		\
       OFURLTests.m			\
       OFValueTests.m			\
       OFXMLElementBuilderTests.m	\
       OFXMLNodeTests.m			\
       OFXMLParserTests.m		\
       PBKDF2Tests.m			\
       RuntimeTests.m			\
       ${RUNTIME_ARC_TESTS_M}		\
       ScryptTests.m			\
       TestsAppDelegate.m		\
       ${USE_SRCS_FILES}		\
       ${USE_SRCS_PLUGINS}		\
       ${USE_SRCS_SOCKETS}		\
       ${USE_SRCS_THREADS}		\
       ${USE_SRCS_WINDOWS}
SRCS_FILES = OFHMACTests.m		\







>

>









<


<







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

41
42

43
44
45
46
47
48
49
       OFInvocationTests.m		\
       OFJSONTests.m			\
       OFListTests.m			\
       OFLocaleTests.m			\
       OFMethodSignatureTests.m		\
       OFNumberTests.m			\
       OFObjectTests.m			\
       OFPBKDF2Tests.m			\
       OFPropertyListTests.m		\
       OFScryptTests.m			\
       OFSetTests.m			\
       OFStreamTests.m			\
       OFStringTests.m			\
       OFSystemInfoTests.m		\
       OFURLTests.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}
SRCS_FILES = OFHMACTests.m		\
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
	   OFSPXStreamSocketTests.m
SRCS_PLUGINS = OFPluginTests.m
SRCS_SOCKETS = OFDNSResolverTests.m		\
	       ${OF_HTTP_CLIENT_TESTS_M}	\
	       OFHTTPCookieTests.m		\
	       OFHTTPCookieManagerTests.m	\
	       OFKernelEventObserverTests.m	\
	       OFTCPSocketTests.m		\
	       OFUDPSocketTests.m		\
	       SocketTests.m			\
	       ${USE_SRCS_IPX}
SRCS_THREADS = OFThreadTests.m
SRCS_WINDOWS = OFWindowsRegistryKeyTests.m

IOS_USER ?= mobile
IOS_TMP ?= /tmp/objfw-test

include ../buildsys.mk

post-all: ${RUN_TESTS}

.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.dll libobjfw.${OBJFW_LIB_MAJOR}.dylib
	rm -f libobjfwrt.so.${OBJFWRT_LIB_MAJOR}
	rm -f libobjfwrt.so.${OBJFWRT_LIB_MAJOR_MINOR}

	rm -f objfwrt.dll 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.dll; then \
		${LN_S} ../src/objfw.dll objfw.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.dll; then \
		${LN_S} ../src/runtime/objfwrt.dll objfwrt.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} objfw.dll; \

	rm -f libobjfw.${OBJFW_LIB_MAJOR}.dylib; \
	rm -f libobjfwrt.so.${OBJFWRT_LIB_MAJOR}; \
	rm -f libobjfwrt.so.${OBJFWRT_LIB_MAJOR_MINOR} objfwrt.dll; \

	rm -f libobjfwrt.${OBJFWRT_LIB_MAJOR}.dylib; \
	exit $$EXIT

run-on-ios: all
	if [ -z "${IOS_HOST}" ]; then \
		echo "Please set IOS_HOST to the hostname of your iOS host!"; \
		exit 1; \







|
|
|









<
<




|


>
|









|
|
>













|
|
>
















|
>


|
>







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
	   OFSPXStreamSocketTests.m
SRCS_PLUGINS = OFPluginTests.m
SRCS_SOCKETS = OFDNSResolverTests.m		\
	       ${OF_HTTP_CLIENT_TESTS_M}	\
	       OFHTTPCookieTests.m		\
	       OFHTTPCookieManagerTests.m	\
	       OFKernelEventObserverTests.m	\
	       OFSocketTests.m			\
	       OFTCPSocketTests.m		\
	       OFUDPSocketTests.m		\
	       ${USE_SRCS_IPX}
SRCS_THREADS = OFThreadTests.m
SRCS_WINDOWS = OFWindowsRegistryKeyTests.m

IOS_USER ?= mobile
IOS_TMP ?= /tmp/objfw-test

include ../buildsys.mk



.PHONY: run run-on-ios run-on-android
run:
	rm -f libobjfw.so.${OBJFW_LIB_MAJOR}
	rm -f libobjfw.so.${OBJFW_LIB_MAJOR_MINOR}
	rm -f objfw${OBJFW_LIB_MAJOR}.dll libobjfw.${OBJFW_LIB_MAJOR}.dylib
	rm -f libobjfwrt.so.${OBJFWRT_LIB_MAJOR}
	rm -f libobjfwrt.so.${OBJFWRT_LIB_MAJOR_MINOR}
	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

run-on-ios: all
	if [ -z "${IOS_HOST}" ]; then \
		echo "Please set IOS_HOST to the hostname of your iOS host!"; \
		exit 1; \

Modified tests/OFArrayTests.m from [f58673a4b1] to [0c4712974c].

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

#include "config.h"

#import "TestsAppDelegate.h"

static OFString *module = nil;
static OFString *c_ary[] = {
	@"Foo",
	@"Bar",
	@"Baz"
};

@interface SimpleArray: OFArray
{







|
|







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

#include "config.h"

#import "TestsAppDelegate.h"

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

@interface SimpleArray: OFArray
{
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
@end

@implementation TestsAppDelegate (OFArrayTests)
- (void)arrayTestsWithClass: (Class)arrayClass
	       mutableClass: (Class)mutableArrayClass
{
	void *pool = objc_autoreleasePoolPush();
	OFArray *a[3];
	OFMutableArray *m[2];
	OFEnumerator *enumerator;
	id obj;
	bool ok;
	size_t i;

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

	TEST(@"+[arrayWithObjects:]",

	    (a[0] = [arrayClass arrayWithObjects: @"Foo", @"Bar", @"Baz", nil]))

	TEST(@"+[arrayWithObjects:count:]",
	    (a[1] = [arrayClass arrayWithObjects: c_ary count: 3]) &&
	    [a[1] isEqual: a[0]])

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

	TEST(@"-[addObject:]", R([m[0] addObject: c_ary[0]]) &&

	    R([m[0] addObject: c_ary[2]]))

	TEST(@"-[insertObject:atIndex:]",
	    R([m[0] insertObject: c_ary[1] atIndex: 1]))

	TEST(@"-[count]", m[0].count == 3 && a[0].count == 3 && a[1].count == 3)


	TEST(@"-[isEqual:]", [m[0] isEqual: a[0]] && [a[0] isEqual: a[1]])


	TEST(@"-[objectAtIndex:]",
	    [[m[0] objectAtIndex: 0] isEqual: c_ary[0]] &&
	    [[m[0] objectAtIndex: 1] isEqual: c_ary[1]] &&
	    [[m[0] objectAtIndex: 2] isEqual: c_ary[2]] &&
	    [[a[0] objectAtIndex: 0] isEqual: c_ary[0]] &&
	    [[a[0] objectAtIndex: 1] isEqual: c_ary[1]] &&
	    [[a[0] objectAtIndex: 2] isEqual: c_ary[2]] &&
	    [[a[1] objectAtIndex: 0] isEqual: c_ary[0]] &&
	    [[a[1] objectAtIndex: 1] isEqual: c_ary[1]] &&
	    [[a[1] objectAtIndex: 2] isEqual: c_ary[2]])

	TEST(@"-[containsObject:]",
	    [a[0] containsObject: c_ary[1]] &&
	    ![a[0] containsObject: @"nonexistent"])

	TEST(@"-[containsObjectIdenticalTo:]",
	    [a[0] containsObjectIdenticalTo: c_ary[1]] &&
	    ![a[0] containsObjectIdenticalTo:
	    [OFString stringWithString: c_ary[1]]])

	TEST(@"-[indexOfObject:]", [a[0] indexOfObject: c_ary[1]] == 1)

	TEST(@"-[indexOfObjectIdenticalTo:]",
	    [a[1] indexOfObjectIdenticalTo: c_ary[1]] == 1)

	TEST(@"-[objectsInRange:]",
	    [[a[0] objectsInRange: OFRangeMake(1, 2)] isEqual:
	    [arrayClass arrayWithObjects: c_ary[1], c_ary[2], nil]])

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

	TEST(@"-[replaceObject:identicalTo:]",
	    R([m[0] replaceObjectIdenticalTo: c_ary[0] withObject: c_ary[1]]) &&

	    [[m[0] objectAtIndex: 0] isEqual: c_ary[1]] &&
	    [[m[0] objectAtIndex: 1] isEqual: c_ary[0]] &&
	    [[m[0] objectAtIndex: 2] isEqual: c_ary[2]])

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

	TEST(@"-[removeObject:]",
	    R([m[0] removeObject: c_ary[0]]) && m[0].count == 2)


	TEST(@"-[removeObjectIdenticalTo:]",
	    R([m[0] removeObjectIdenticalTo: c_ary[2]]) && m[0].count == 1)


	m[1] = [[a[0] mutableCopy] autorelease];
	TEST(@"-[removeObjectAtIndex:]", R([m[1] removeObjectAtIndex: 1]) &&


	    m[1].count == 2 && [[m[1] objectAtIndex: 1] isEqual: c_ary[2]])

	m[1] = [[a[0] mutableCopy] autorelease];
	TEST(@"-[removeObjectsInRange:]",
	    R([m[1] removeObjectsInRange: OFRangeMake(0, 2)]) &&

	    m[1].count == 1 && [[m[1] objectAtIndex: 0] isEqual: c_ary[2]])

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




	m[1] = [[a[0] mutableCopy] autorelease];
	[m[1] addObject: @"qux"];
	[m[1] addObject: @"last"];
	TEST(@"-[reversedArray]",

	    [[m[1] reversedArray] isEqual: [arrayClass arrayWithObjects:
	    @"last", @"qux", @"Baz", @"Bar", @"Foo", nil]])

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

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

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

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

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

	m[0] = [[a[0] mutableCopy] autorelease];
	ok = true;
	i = 0;

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


	while ((obj = [enumerator nextObject]) != nil) {
		if (![obj isEqual: c_ary[i]])
			ok = false;
		[m[0] replaceObjectAtIndex: i withObject: @""];
		i++;
	}

	if (m[0].count != i)
		ok = false;

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

	[m[0] removeObjectAtIndex: 0];

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

	m[0] = [[a[0] mutableCopy] autorelease];
	ok = true;
	i = 0;

	for (OFString *s in m[0]) {
		if (![s isEqual: c_ary[i]])
			ok = false;
		[m[0] replaceObjectAtIndex: i withObject: @""];
		i++;
	}

	if (m[0].count != i)
		ok = false;

	TEST(@"Fast Enumeration", ok)

	[m[0] replaceObjectAtIndex: 0 withObject: c_ary[0]];
	[m[0] replaceObjectAtIndex: 1 withObject: c_ary[1]];
	[m[0] replaceObjectAtIndex: 2 withObject: c_ary[2]];

	ok = false;
	i = 0;
	@try {
		for (OFString *s in m[0]) {
			(void)s;

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

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

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

	[m[0] removeLastObject];

#ifdef OF_HAVE_BLOCKS
	{
		__block bool blockOk = true;
		__block size_t count = 0;
		OFArray *cmp = a[0];
		OFMutableArray *a2;

		m[0] = [[a[0] mutableCopy] autorelease];
		[m[0] enumerateObjectsUsingBlock:
		    ^ (id object, size_t idx, bool *stop) {
			    count++;

			    if (![object isEqual: [cmp objectAtIndex: idx]])
				    blockOk = false;
		}];

		if (count != cmp.count)
			blockOk = false;

		TEST(@"Enumeration using blocks", blockOk)

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

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

	TEST(@"-[replaceObjectsUsingBlock:]",
	    R([m[0] replaceObjectsUsingBlock: ^ id (id object, size_t idx) {

		switch (idx) {
		case 0:
			return @"foo";
		case 1:
			return @"bar";
		}

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

	TEST(@"-[mappedArrayUsingBlock:]",
	    [[m[0] mappedArrayUsingBlock: ^ id (id object, size_t idx) {

		switch (idx) {
		case 0:
			return @"foobar";
		case 1:
			return @"qux";
		}

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

	TEST(@"-[filteredArrayUsingBlock:]",
	    [[m[0] filteredArrayUsingBlock: ^ bool (id object, size_t idx) {

		return [object isEqual: @"foo"];
	    }].description isEqual: @"(\n\tfoo\n)"])

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

	TEST(@"-[valueForKey:]",
	    [[[arrayClass arrayWithObjects: @"foo", @"bar", @"quxqux", nil]
	    valueForKey: @"length"] isEqual:
	    [arrayClass arrayWithObjects: [OFNumber numberWithInt: 3],
	    [OFNumber numberWithInt: 3], [OFNumber numberWithInt: 6], nil]] &&
	    [[[arrayClass arrayWithObjects: @"1", @"2", nil]
	    valueForKey: @"@count"] isEqual: [OFNumber numberWithInt: 2]])

	m[0] = [mutableArrayClass arrayWithObjects:
	    [OFMutableURL URLWithString: @"http://foo.bar/"],
	    [OFMutableURL URLWithString: @"http://bar.qux/"],
	    [OFMutableURL URLWithString: @"http://qux.quxqux/"], nil];
	TEST(@"-[setValue:forKey:]",
	    R([m[0] setValue: [OFNumber numberWithShort: 1234]
		      forKey: @"port"]) &&
	    [m[0] isEqual: [arrayClass arrayWithObjects:
	    [OFURL URLWithString: @"http://foo.bar:1234/"],
	    [OFURL URLWithString: @"http://bar.qux:1234/"],
	    [OFURL URLWithString: @"http://qux.quxqux:1234/"], nil]])

	objc_autoreleasePoolPop(pool);
}








|
|

|



|


>
|


|
|


|

|
>
|


|

|
>

|
>


|
|
|
|
|
|
|
|
|


|
|


|
|
|

|


|


|
|


|
|
|
|


|
>
|
|
|


|
|
|
|


|
>


|
>

|
|
>
>
|

|

|
>
|

|
|
|

<
<
>
>
>

|
|
|

>
|


|
|
|

|

|
|




|


|
|


|

|
|
|


|
|
|
|


|



|
>

|
|

|



|




|




|



|
|

|



|




|
|
|




|
|


|









|



|

|
|

|
|
|
|
>
|
|


|
|

|

|
|

|
|
|


|








|



|
>
|
|
|
|
|
|

|
|


|
>
|
|
|
|
|
|

|



|
>
|





|
|











|




|
|
|







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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

	mutableArray2 = [[array1 mutableCopy] autorelease];
	[mutableArray2 addObject: @"qux"];
	[mutableArray2 addObject: @"last"];
	TEST(@"-[reverse]",


	    R([mutableArray2 reverse]) &&
	    [mutableArray2 isEqual: [arrayClass arrayWithObjects:
	    @"last", @"qux", @"Baz", @"Bar", @"Foo", nil]])

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

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

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

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

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

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

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

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

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

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

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

	[mutableArray1 removeObjectAtIndex: 0];

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

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

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

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

	TEST(@"Fast Enumeration", ok)

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

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

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

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

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

	[mutableArray1 removeLastObject];

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

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

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

		TEST(@"Enumeration using blocks", blockOK)

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

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

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

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

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

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

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

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

	TEST(@"-[valueForKey:]",
	    [[[arrayClass arrayWithObjects: @"foo", @"bar", @"quxqux", nil]
	    valueForKey: @"length"] isEqual:
	    [arrayClass arrayWithObjects: [OFNumber numberWithInt: 3],
	    [OFNumber numberWithInt: 3], [OFNumber numberWithInt: 6], nil]] &&
	    [[[arrayClass arrayWithObjects: @"1", @"2", nil]
	    valueForKey: @"@count"] isEqual: [OFNumber numberWithInt: 2]])

	mutableArray1 = [mutableArrayClass arrayWithObjects:
	    [OFMutableURL URLWithString: @"http://foo.bar/"],
	    [OFMutableURL URLWithString: @"http://bar.qux/"],
	    [OFMutableURL URLWithString: @"http://qux.quxqux/"], nil];
	TEST(@"-[setValue:forKey:]",
	    R([mutableArray1 setValue: [OFNumber numberWithShort: 1234]
			       forKey: @"port"]) &&
	    [mutableArray1 isEqual: [arrayClass arrayWithObjects:
	    [OFURL URLWithString: @"http://foo.bar:1234/"],
	    [OFURL URLWithString: @"http://bar.qux:1234/"],
	    [OFURL URLWithString: @"http://qux.quxqux:1234/"], nil]])

	objc_autoreleasePoolPop(pool);
}

Modified tests/OFBlockTests.m from [dc2e6666e8] to [6cfef2073c].

13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
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
 * file.
 */

#include "config.h"

#import "TestsAppDelegate.h"

static OFString *module = @"OFBlock";

#if defined(OF_OBJFW_RUNTIME)
extern struct objc_class _NSConcreteStackBlock;
extern struct objc_class _NSConcreteGlobalBlock;
extern struct objc_class _NSConcreteMallocBlock;
#elif defined(OF_APPLE_RUNTIME)
extern void *_NSConcreteStackBlock;
extern void *_NSConcreteGlobalBlock;
extern void *_NSConcreteMallocBlock;
#endif

static void (^g)(void) = ^ {};

static int
(^returnStackBlock(void))(void)
{
	__block int i = 42;

	return [Block_copy(^ int { return ++i; }) autorelease];
}

static double
forwardTest(void)
{
	__block double d;
	void (^b)(void) = Block_copy(^ {
		d = 5;
	});

	b();
	Block_release(b);

	return d;
}

@implementation TestsAppDelegate (OFBlockTests)
- (void)blockTests
{
	void *pool = objc_autoreleasePoolPush();
	__block int x;
	void (^s)(void) = ^ { x = 0; };

	void (^m)(void);

	int (^v)(void);


	TEST(@"Class of stack block",
	    (Class)&_NSConcreteStackBlock == objc_getClass("OFStackBlock") &&
	    [s isKindOfClass: [OFBlock class]])

#if !defined(OF_WINDOWS) || !defined(__clang__) || !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") &&
	    [g isKindOfClass: [OFBlock class]])
#endif

	TEST(@"Class of a malloc block",
	    (Class)&_NSConcreteMallocBlock == objc_getClass("OFMallocBlock"))

	TEST(@"Copying a stack block",
	    (m = [[s copy] autorelease]) &&
	    [m class] == objc_getClass("OFMallocBlock") &&
	    [m isKindOfClass: [OFBlock class]])

	TEST(@"Copying a stack block and referencing its variable",
	    forwardTest() == 5)

	TEST(@"Copying a stack block and using its copied variable",
	    (v = returnStackBlock()) && v() == 43 && v() == 44 && v() == 45)


	TEST(@"Copying a global block", (id)g == [[g copy] autorelease])


#ifndef __clang_analyzer__
	TEST(@"Copying a malloc block",

	    (id)m == [m copy] && [m retainCount] == 2)
#endif

	TEST(@"Autorelease a stack block", R([s autorelease]))

	TEST(@"Autorelease a global block", R([g autorelease]))

#ifndef __clang_analyzer__
	TEST(@"Autorelease a malloc block", R([m autorelease]))
#endif

	objc_autoreleasePoolPop(pool);
}
@end







|











|













|



|
|









|
>
|
>
|
>



|








|






|
|
|





|
>

|
>



>
|


|

|


|





13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
 * file.
 */

#include "config.h"

#import "TestsAppDelegate.h"

static OFString *const module = @"OFBlock";

#if defined(OF_OBJFW_RUNTIME)
extern struct objc_class _NSConcreteStackBlock;
extern struct objc_class _NSConcreteGlobalBlock;
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];
}

static double
forwardTest(void)
{
	__block double d;
	void (^block)(void) = Block_copy(^ {
		d = 5;
	});

	block();
	Block_release(block);

	return d;
}

@implementation TestsAppDelegate (OFBlockTests)
- (void)blockTests
{
	void *pool = objc_autoreleasePoolPush();
	__block int x;
	void (^stackBlock)(void) = ^ {
		x = 0;
		(void)x;
	};
	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

Modified tests/OFCharacterSetTests.m from [f4f81f5355] to [11fed19a2c].

17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
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

#import "TestsAppDelegate.h"

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

static OFString *module = nil;

@interface SimpleCharacterSet: OFCharacterSet
@end

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

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

	module = @"OFCharacterSet";

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

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

	module = @"OFBitSetCharacterSet";

	TEST(@"+[characterSetWithCharactersInString:]",
	    (cs = [OFCharacterSet characterSetWithCharactersInString:
	    @"0123456789"]) &&
	    [cs isKindOfClass: [OFBitSetCharacterSet class]])

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

	module = @"OFRangeCharacterSet";

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

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

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

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

	objc_autoreleasePoolPop(pool);
}
@end







|















|




|




|

|







|

|




|

|







|

|




|

|





|


|

|





|




17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107

#import "TestsAppDelegate.h"

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

static OFString *module;

@interface SimpleCharacterSet: OFCharacterSet
@end

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

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

	module = @"OFCharacterSet";

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

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

	module = @"OFBitSetCharacterSet";

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

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

	module = @"OFRangeCharacterSet";

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

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

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

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

	objc_autoreleasePoolPop(pool);
}
@end

Modified tests/OFDataTests.m from [6024274dc3] to [def38bc628].

15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
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

#include "config.h"

#include <string.h>

#import "TestsAppDelegate.h"

static OFString *module = @"OFData";
const char *str = "Hello!";

@implementation TestsAppDelegate (OFDataTests)
- (void)dataTests
{
	void *pool = objc_autoreleasePoolPush();
	OFMutableData *mutable;
	OFData *immutable;
	void *raw[2];
	OFRange range;

	TEST(@"+[dataWithItemSize:]",
	    (mutable = [OFMutableData dataWithItemSize: 4096]))

	raw[0] = OFAllocMemory(1, 4096);
	raw[1] = OFAllocMemory(1, 4096);
	memset(raw[0], 0xFF, 4096);
	memset(raw[1], 0x42, 4096);

	TEST(@"-[addItem:]", R([mutable addItem: raw[0]]) &&
	    R([mutable addItem: raw[1]]))

	TEST(@"-[itemAtIndex:]",
	    memcmp([mutable itemAtIndex: 0], raw[0], 4096) == 0 &&
	    memcmp([mutable itemAtIndex: 1], raw[1], 4096) == 0)

	TEST(@"-[lastItem]", memcmp(mutable.lastItem, raw[1], 4096) == 0)

	TEST(@"-[count]", mutable.count == 2)

	TEST(@"-[isEqual:]",
	    (immutable = [OFData dataWithItems: mutable.items
					 count: mutable.count
				      itemSize: mutable.itemSize]) &&
	    [immutable isEqual: mutable] &&
	    R([mutable removeLastItem]) && ![mutable isEqual: immutable])

	TEST(@"-[mutableCopy]",
	    (mutable = [[immutable mutableCopy] autorelease]) &&
	    [mutable isEqual: immutable])

	TEST(@"-[compare]", [mutable compare: immutable] == 0 &&
	    R([mutable removeLastItem]) &&
	    [immutable compare: mutable] == OFOrderedDescending &&
	    [mutable compare: immutable] == OFOrderedAscending &&
	    [[OFData dataWithItems: "aa" count: 2] compare:
	    [OFData dataWithItems: "z" count: 1]] == OFOrderedAscending)

	TEST(@"-[hash]", immutable.hash == 0x634A529F)

	mutable = [OFMutableData dataWithItems: "abcdef" count: 6];

	TEST(@"-[removeLastItem]", R([mutable removeLastItem]) &&

	    mutable.count == 5 && memcmp(mutable.items, "abcde", 5) == 0)

	TEST(@"-[removeItemsInRange:]",
	    R([mutable removeItemsInRange: OFRangeMake(1, 2)]) &&
	    mutable.count == 3 && memcmp(mutable.items, "ade", 3) == 0)

	TEST(@"-[insertItems:atIndex:count:]",
	    R([mutable insertItems: "bc" atIndex: 1 count: 2]) &&

	    mutable.count == 5 && memcmp(mutable.items, "abcde", 5) == 0)

	immutable = [OFData dataWithItems: "aaabaccdacaabb"
				    count: 7
				 itemSize: 2];

	range = [immutable rangeOfData: [OFData dataWithItems: "aa"
							count: 1
						     itemSize: 2]
			       options: 0
				 range: OFRangeMake(0, 7)];
	TEST(@"-[rangeOfData:options:range:] #1",
	    range.location == 0 && range.length == 1)

	range = [immutable rangeOfData: [OFData dataWithItems: "aa"
							count: 1
						     itemSize: 2]
			       options: OFDataSearchBackwards
				 range: OFRangeMake(0, 7)];
	TEST(@"-[rangeOfData:options:range:] #2",
	    range.location == 5 && range.length == 1)

	range = [immutable rangeOfData: [OFData dataWithItems: "ac"
							count: 1
						     itemSize: 2]
			       options: 0
				 range: OFRangeMake(0, 7)];
	TEST(@"-[rangeOfData:options:range:] #3",
	    range.location == 2 && range.length == 1)

	range = [immutable rangeOfData: [OFData dataWithItems: "aabb"
							count: 2
						     itemSize: 2]
			       options: 0
				 range: OFRangeMake(0, 7)];
	TEST(@"-[rangeOfData:options:range:] #4",
	    range.location == 5 && range.length == 2)

	TEST(@"-[rangeOfData:options:range:] #5",
	    R(range = [immutable rangeOfData: [OFData dataWithItems: "aa"
							      count: 1
							   itemSize: 2]
				     options: 0
				       range: OFRangeMake(1, 6)]) &&
	    range.location == 5 && range.length == 1)

	range = [immutable rangeOfData: [OFData dataWithItems: "aa"
							count: 1
						     itemSize: 2]
			       options: OFDataSearchBackwards
				 range: OFRangeMake(0, 5)];
	TEST(@"-[rangeOfData:options:range:] #6",
	    range.location == 0 && range.length == 1)

	EXPECT_EXCEPTION(
	    @"-[rangeOfData:options:range:] failing on different itemSize",
	    OFInvalidArgumentException,
	    [immutable rangeOfData: [OFData dataWithItems: "aaa"
						    count: 1
						 itemSize: 3]
			   options: 0
			     range: OFRangeMake(0, 1)])

	EXPECT_EXCEPTION(
	    @"-[rangeOfData:options:range:] failing on out of range",
	    OFOutOfRangeException,
	    [immutable rangeOfData: [OFData dataWithItems: ""
						    count: 0
						 itemSize: 2]
			   options: 0
			     range: OFRangeMake(8, 1)])

	TEST(@"-[subdataWithRange:]",
	    [[immutable subdataWithRange: OFRangeMake(2, 4)]
	    isEqual: [OFData dataWithItems: "accdacaa"
				     count: 4
				  itemSize: 2]] &&
	    [[mutable subdataWithRange: OFRangeMake(2, 3)]
	    isEqual: [OFData dataWithItems: "cde"
				     count: 3]])

	EXPECT_EXCEPTION(@"-[subdataWithRange:] failing on out of range #1",
	    OFOutOfRangeException,
	    [immutable subdataWithRange: OFRangeMake(7, 1)])

	EXPECT_EXCEPTION(@"-[subdataWithRange:] failing on out of range #2",
	    OFOutOfRangeException,
	    [mutable subdataWithRange: OFRangeMake(6, 1)])

	TEST(@"-[stringByMD5Hashing]", [mutable.stringByMD5Hashing

	    isEqual: @"ab56b4d92b40713acc5af89985d4b786"])

	TEST(@"-[stringByRIPEMD160Hashing]", [mutable.stringByRIPEMD160Hashing

	    isEqual: @"973398b6e6c6cfa6b5e6a5173f195ce3274bf828"])

	TEST(@"-[stringBySHA1Hashing]", [mutable.stringBySHA1Hashing

	    isEqual: @"03de6c570bfe24bfc328ccd7ca46b76eadaf4334"])

	TEST(@"-[stringBySHA224Hashing]", [mutable.stringBySHA224Hashing

	    isEqual: @"bdd03d560993e675516ba5a50638b6531ac2ac3d5847c61916cfced6"
	    ])

	TEST(@"-[stringBySHA256Hashing]", [mutable.stringBySHA256Hashing

	    isEqual: @"36bbe50ed96841d10443bcb670d6554f0a34b761be67ec9c4a8ad2c0"
		     @"c44ca42c"])

	TEST(@"-[stringBySHA384Hashing]", [mutable.stringBySHA384Hashing

	    isEqual: @"4c525cbeac729eaf4b4665815bc5db0c84fe6300068a727cf74e2813"
		     @"521565abc0ec57a37ee4d8be89d097c0d2ad52f0"])

	TEST(@"-[stringBySHA512Hashing]", [mutable.stringBySHA512Hashing

	    isEqual: @"878ae65a92e86cac011a570d4c30a7eaec442b85ce8eca0c2952b5e3"
		     @"cc0628c2e79d889ad4d5c7c626986d452dd86374b6ffaa7cd8b67665"
		     @"bef2289a5c70b0a1"])

	TEST(@"-[stringByBase64Encoding]",
	    [mutable.stringByBase64Encoding isEqual: @"YWJjZGU="])

	TEST(@"+[dataWithBase64EncodedString:]",
	    memcmp([[OFData dataWithBase64EncodedString: @"YWJjZGU="]
	    items], "abcde", 5) == 0)

	TEST(@"Building strings",
	    (mutable = [OFMutableData dataWithItems: str count: 6]) &&
	    R([mutable addItem: ""]) &&
	    strcmp(mutable.items, str) == 0)

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

	EXPECT_EXCEPTION(@"Detect out of range in -[addItems:count:]",
	    OFOutOfRangeException, [mutable addItems: raw[0] count: SIZE_MAX])


	EXPECT_EXCEPTION(@"Detect out of range in -[removeItemsInRange:]",
	    OFOutOfRangeException,
	    [mutable removeItemsInRange: OFRangeMake(mutable.count, 1)])

	OFFreeMemory(raw[0]);
	OFFreeMemory(raw[1]);

	objc_autoreleasePoolPop(pool);
}
@end







|
<





|
|




|






|
|


|
|

|

|


|
|
|
|
|


|
|

|
|
|
|



|

|

|
>
|


|
|


|
>
|

|
<
<

|
|
|
|
|



|
|
|
|
|



|
|
|
|
|



|
|
|
|
|




|
|
|
|
|


|
|
|
|
|






|
|
|
|
|




|
<
<
|
|


|
|
<
<
|
|
<



|



|

|
>


|
>


|
>


|
>



|
>



|
>



|
>





|


|
|


|
|
|


|


|
>



|







15
16
17
18
19
20
21
22

23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
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

#include "config.h"

#include <string.h>

#import "TestsAppDelegate.h"

static OFString *const module = @"OFData";


@implementation TestsAppDelegate (OFDataTests)
- (void)dataTests
{
	void *pool = objc_autoreleasePoolPush();
	OFMutableData *mutableData;
	OFData *data;
	void *raw[2];
	OFRange range;

	TEST(@"+[dataWithItemSize:]",
	    (mutableData = [OFMutableData dataWithItemSize: 4096]))

	raw[0] = OFAllocMemory(1, 4096);
	raw[1] = OFAllocMemory(1, 4096);
	memset(raw[0], 0xFF, 4096);
	memset(raw[1], 0x42, 4096);

	TEST(@"-[addItem:]", R([mutableData addItem: raw[0]]) &&
	    R([mutableData addItem: raw[1]]))

	TEST(@"-[itemAtIndex:]",
	    memcmp([mutableData itemAtIndex: 0], raw[0], 4096) == 0 &&
	    memcmp([mutableData itemAtIndex: 1], raw[1], 4096) == 0)

	TEST(@"-[lastItem]", memcmp(mutableData.lastItem, raw[1], 4096) == 0)

	TEST(@"-[count]", mutableData.count == 2)

	TEST(@"-[isEqual:]",
	    (data = [OFData dataWithItems: mutableData.items
				    count: mutableData.count
				 itemSize: mutableData.itemSize]) &&
	    [data isEqual: mutableData] &&
	    R([mutableData removeLastItem]) && ![mutableData isEqual: data])

	TEST(@"-[mutableCopy]",
	    (mutableData = [[data mutableCopy] autorelease]) &&
	    [mutableData isEqual: data])

	TEST(@"-[compare]", [mutableData compare: data] == 0 &&
	    R([mutableData removeLastItem]) &&
	    [data compare: mutableData] == OFOrderedDescending &&
	    [mutableData compare: data] == OFOrderedAscending &&
	    [[OFData dataWithItems: "aa" count: 2] compare:
	    [OFData dataWithItems: "z" count: 1]] == OFOrderedAscending)

	TEST(@"-[hash]", data.hash == 0x634A529F)

	mutableData = [OFMutableData dataWithItems: "abcdef" count: 6];

	TEST(@"-[removeLastItem]",
	    R([mutableData removeLastItem]) && mutableData.count == 5 &&
	    memcmp(mutableData.items, "abcde", 5) == 0)

	TEST(@"-[removeItemsInRange:]",
	    R([mutableData removeItemsInRange: OFRangeMake(1, 2)]) &&
	    mutableData.count == 3 && memcmp(mutableData.items, "ade", 3) == 0)

	TEST(@"-[insertItems:atIndex:count:]",
	    R([mutableData insertItems: "bc" atIndex: 1 count: 2]) &&
	    mutableData.count == 5 &&
	    memcmp(mutableData.items, "abcde", 5) == 0)

	data = [OFData dataWithItems: "aaabaccdacaabb" count: 7 itemSize: 2];



	range = [data rangeOfData: [OFData dataWithItems: "aa"
						   count: 1
						itemSize: 2]
			  options: 0
			    range: OFRangeMake(0, 7)];
	TEST(@"-[rangeOfData:options:range:] #1",
	    range.location == 0 && range.length == 1)

	range = [data rangeOfData: [OFData dataWithItems: "aa"
						   count: 1
						itemSize: 2]
			  options: OFDataSearchBackwards
			    range: OFRangeMake(0, 7)];
	TEST(@"-[rangeOfData:options:range:] #2",
	    range.location == 5 && range.length == 1)

	range = [data rangeOfData: [OFData dataWithItems: "ac"
						   count: 1
						itemSize: 2]
			  options: 0
			    range: OFRangeMake(0, 7)];
	TEST(@"-[rangeOfData:options:range:] #3",
	    range.location == 2 && range.length == 1)

	range = [data rangeOfData: [OFData dataWithItems: "aabb"
						   count: 2
						itemSize: 2]
			  options: 0
			    range: OFRangeMake(0, 7)];
	TEST(@"-[rangeOfData:options:range:] #4",
	    range.location == 5 && range.length == 2)

	TEST(@"-[rangeOfData:options:range:] #5",
	    R(range = [data rangeOfData: [OFData dataWithItems: "aa"
							 count: 1
						      itemSize: 2]
				options: 0
				  range: OFRangeMake(1, 6)]) &&
	    range.location == 5 && range.length == 1)

	range = [data rangeOfData: [OFData dataWithItems: "aa"
						   count: 1
						itemSize: 2]
			  options: OFDataSearchBackwards
			    range: OFRangeMake(0, 5)];
	TEST(@"-[rangeOfData:options:range:] #6",
	    range.location == 0 && range.length == 1)

	EXPECT_EXCEPTION(
	    @"-[rangeOfData:options:range:] failing on different itemSize",
	    OFInvalidArgumentException,
	    [data rangeOfData: [OFData dataWithItems: "aaa"
					       count: 1
					    itemSize: 3]
		      options: 0
			range: OFRangeMake(0, 1)])

	EXPECT_EXCEPTION(
	    @"-[rangeOfData:options:range:] failing on out of range",
	    OFOutOfRangeException,
	    [data rangeOfData: [OFData dataWithItems: "" count: 0 itemSize: 2]


		      options: 0
			range: OFRangeMake(8, 1)])

	TEST(@"-[subdataWithRange:]",
	    [[data subdataWithRange: OFRangeMake(2, 4)]
	    isEqual: [OFData dataWithItems: "accdacaa" count: 4 itemSize: 2]] &&


	    [[mutableData subdataWithRange: OFRangeMake(2, 3)]
	    isEqual: [OFData dataWithItems: "cde" count: 3]])


	EXPECT_EXCEPTION(@"-[subdataWithRange:] failing on out of range #1",
	    OFOutOfRangeException,
	    [data subdataWithRange: OFRangeMake(7, 1)])

	EXPECT_EXCEPTION(@"-[subdataWithRange:] failing on out of range #2",
	    OFOutOfRangeException,
	    [mutableData subdataWithRange: OFRangeMake(6, 1)])

	TEST(@"-[stringByMD5Hashing]",
	    [mutableData.stringByMD5Hashing
	    isEqual: @"ab56b4d92b40713acc5af89985d4b786"])

	TEST(@"-[stringByRIPEMD160Hashing]",
	    [mutableData.stringByRIPEMD160Hashing
	    isEqual: @"973398b6e6c6cfa6b5e6a5173f195ce3274bf828"])

	TEST(@"-[stringBySHA1Hashing]",
	    [mutableData.stringBySHA1Hashing
	    isEqual: @"03de6c570bfe24bfc328ccd7ca46b76eadaf4334"])

	TEST(@"-[stringBySHA224Hashing]",
	    [mutableData.stringBySHA224Hashing
	    isEqual: @"bdd03d560993e675516ba5a50638b6531ac2ac3d5847c61916cfced6"
	    ])

	TEST(@"-[stringBySHA256Hashing]",
	    [mutableData.stringBySHA256Hashing
	    isEqual: @"36bbe50ed96841d10443bcb670d6554f0a34b761be67ec9c4a8ad2c0"
		     @"c44ca42c"])

	TEST(@"-[stringBySHA384Hashing]",
	    [mutableData.stringBySHA384Hashing
	    isEqual: @"4c525cbeac729eaf4b4665815bc5db0c84fe6300068a727cf74e2813"
		     @"521565abc0ec57a37ee4d8be89d097c0d2ad52f0"])

	TEST(@"-[stringBySHA512Hashing]",
	    [mutableData.stringBySHA512Hashing
	    isEqual: @"878ae65a92e86cac011a570d4c30a7eaec442b85ce8eca0c2952b5e3"
		     @"cc0628c2e79d889ad4d5c7c626986d452dd86374b6ffaa7cd8b67665"
		     @"bef2289a5c70b0a1"])

	TEST(@"-[stringByBase64Encoding]",
	    [mutableData.stringByBase64Encoding isEqual: @"YWJjZGU="])

	TEST(@"+[dataWithBase64EncodedString:]",
	    memcmp([[OFData dataWithBase64EncodedString: @"YWJjZGU="] items],
	    "abcde", 5) == 0)

	TEST(@"Building strings",
	    (mutableData = [OFMutableData dataWithItems: "Hello!" count: 6]) &&
	    R([mutableData addItem: ""]) &&
	    strcmp(mutableData.items, "Hello!") == 0)

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

	EXPECT_EXCEPTION(@"Detect out of range in -[addItems:count:]",
	    OFOutOfRangeException,
	    [mutableData addItems: raw[0] count: SIZE_MAX])

	EXPECT_EXCEPTION(@"Detect out of range in -[removeItemsInRange:]",
	    OFOutOfRangeException,
	    [mutableData removeItemsInRange: OFRangeMake(mutableData.count, 1)])

	OFFreeMemory(raw[0]);
	OFFreeMemory(raw[1]);

	objc_autoreleasePoolPop(pool);
}
@end

Modified tests/OFDateTests.m from [ad515445a9] to [7e834c33fc].

15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
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 "config.h"

#include <time.h>

#import "TestsAppDelegate.h"

static OFString *module = @"OFDate";

@implementation TestsAppDelegate (OFDateTests)
- (void)dateTests
{
	void *pool = objc_autoreleasePoolPush();
	OFDate *d1, *d2;

	struct tm tm;
	int16_t tz;
	const char *dstr = "Wed, 09 Jun 2021 +0200x";
	TEST(@"OFStrPTime()",
	    OFStrPTime(dstr, "%a, %d %b %Y %z", &tm, &tz) == dstr + 22 &&
	    tm.tm_wday == 3 && tm.tm_mday == 9 && tm.tm_mon == 5 &&
	    tm.tm_year == 2021 - 1900 && tz == 2 * 60)

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

	TEST(@"-[dateByAddingTimeInterval:]",
	    (d2 = [d1 dateByAddingTimeInterval: 3600 * 25 + 5.000002]))

	TEST(@"-[description]",
	    [d1.description isEqual: @"1970-01-01T00:00:00Z"] &&
	    [d2.description isEqual: @"1970-01-02T01:00:05Z"])

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

	EXPECT_EXCEPTION(@"Detection of unparsed in "







|





|










|


|


|
|







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
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 "config.h"

#include <time.h>

#import "TestsAppDelegate.h"

static OFString *const module = @"OFDate";

@implementation TestsAppDelegate (OFDateTests)
- (void)dateTests
{
	void *pool = objc_autoreleasePoolPush();
	OFDate *date1, *date2;

	struct tm tm;
	int16_t tz;
	const char *dstr = "Wed, 09 Jun 2021 +0200x";
	TEST(@"OFStrPTime()",
	    OFStrPTime(dstr, "%a, %d %b %Y %z", &tm, &tz) == dstr + 22 &&
	    tm.tm_wday == 3 && tm.tm_mday == 9 && tm.tm_mon == 5 &&
	    tm.tm_year == 2021 - 1900 && tz == 2 * 60)

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

	TEST(@"-[dateByAddingTimeInterval:]",
	    (date2 = [date1 dateByAddingTimeInterval: 3600 * 25 + 5.000002]))

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

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

	EXPECT_EXCEPTION(@"Detection of unparsed in "
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

	EXPECT_EXCEPTION(@"Detection of unparsed in "
	    @"+[dateWithLocalDateString:format:] #2", OFInvalidFormatException,
	    [OFDate dateWithLocalDateString: @"2000-06-20T12:34:56+0200x"
				     format: @"%Y-%m-%dT%H:%M:%S%z"])

	TEST(@"-[isEqual:]",
	    [d1 isEqual: [OFDate dateWithTimeIntervalSince1970: 0]] &&
	    ![d1 isEqual: [OFDate dateWithTimeIntervalSince1970: 0.0000001]])

	TEST(@"-[compare:]", [d1 compare: d2] == OFOrderedAscending)

	TEST(@"-[second]", d1.second == 0 && d2.second == 5)

	TEST(@"-[microsecond]", d1.microsecond == 0 && d2.microsecond == 2)


	TEST(@"-[minute]", d1.minute == 0 && d2.minute == 0)

	TEST(@"-[hour]", d1.hour == 0 && d2.hour == 1)

	TEST(@"-[dayOfMonth]", d1.dayOfMonth == 1 && d2.dayOfMonth == 2)

	TEST(@"-[monthOfYear]", d1.monthOfYear == 1 && d2.monthOfYear == 1)


	TEST(@"-[year]", d1.year == 1970 && d2.year == 1970)

	TEST(@"-[dayOfWeek]", d1.dayOfWeek == 4 && d2.dayOfWeek == 5)

	TEST(@"-[dayOfYear]", d1.dayOfYear == 1 && d2.dayOfYear == 2)

	TEST(@"-[earlierDate:]", [[d1 earlierDate: d2] isEqual: d1])

	TEST(@"-[laterDate:]", [[d1 laterDate: d2] isEqual: d2])

	objc_autoreleasePoolPop(pool);
}
@end







|
|

|

|

|
>

|

|

|

|
>

|

|

|

|

|




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

	EXPECT_EXCEPTION(@"Detection of unparsed in "
	    @"+[dateWithLocalDateString:format:] #2", OFInvalidFormatException,
	    [OFDate dateWithLocalDateString: @"2000-06-20T12:34:56+0200x"
				     format: @"%Y-%m-%dT%H:%M:%S%z"])

	TEST(@"-[isEqual:]",
	    [date1 isEqual: [OFDate dateWithTimeIntervalSince1970: 0]] &&
	    ![date1 isEqual: [OFDate dateWithTimeIntervalSince1970: 0.0000001]])

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

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

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

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

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

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

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

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

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

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

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

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

	objc_autoreleasePoolPop(pool);
}
@end

Modified tests/OFDictionaryTests.m from [fdcd71652e] to [545415a78a].

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

#include "config.h"

#import "TestsAppDelegate.h"

static OFString *module = nil;
static OFString *keys[] = {
	@"key1",
	@"key2"
};
static OFString *values[] = {
	@"value1",
	@"value2"







|







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

#include "config.h"

#import "TestsAppDelegate.h"

static OFString *module;
static OFString *keys[] = {
	@"key1",
	@"key2"
};
static OFString *values[] = {
	@"value1",
	@"value2"
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
- (id)objectForKey: (id)key
{
	return [_dictionary objectForKey: key];
}

- (size_t)count
{
	return [_dictionary count];
}

- (OFEnumerator *)keyEnumerator
{
	return [_dictionary keyEnumerator];
}
@end







|







100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
- (id)objectForKey: (id)key
{
	return [_dictionary objectForKey: key];
}

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

- (OFEnumerator *)keyEnumerator
{
	return [_dictionary keyEnumerator];
}
@end
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
@end

@implementation TestsAppDelegate (OFDictionaryTests)
- (void)dictionaryTestsWithClass: (Class)dictionaryClass
		    mutableClass: (Class)mutableDictionaryClass
{
	void *pool = objc_autoreleasePoolPush();
	OFMutableDictionary *mutDict = [mutableDictionaryClass dictionary];
	OFDictionary *dict;
	OFEnumerator *keyEnumerator, *objectEnumerator;
	OFArray *keysArray, *valuesArray;

	[mutDict setObject: values[0] forKey: keys[0]];
	[mutDict setValue: values[1] forKey: keys[1]];

	TEST(@"-[objectForKey:]",
	    [[mutDict objectForKey: keys[0]] isEqual: values[0]] &&
	    [[mutDict objectForKey: keys[1]] isEqual: values[1]] &&
	    [mutDict objectForKey: @"key3"] == nil)

	TEST(@"-[valueForKey:]",
	    [[mutDict valueForKey: keys[0]] isEqual: values[0]] &&
	    [[mutDict valueForKey: @"@count"] isEqual:
	    [OFNumber numberWithInt: 2]])

	EXPECT_EXCEPTION(@"Catching -[setValue:forKey:] on immutable "
	    @"dictionary", OFUndefinedKeyException,
	    [[dictionaryClass dictionary] setValue: @"x" forKey: @"x"])

	TEST(@"-[containsObject:]",
	    [mutDict containsObject: values[0]] &&
	    ![mutDict containsObject: @"nonexistent"])

	TEST(@"-[containsObjectIdenticalTo:]",
	    [mutDict containsObjectIdenticalTo: values[0]] &&
	    ![mutDict containsObjectIdenticalTo:
	    [OFString stringWithString: values[0]]])

	TEST(@"-[description]",
	    [[mutDict description] isEqual:
	    @"{\n\tkey1 = value1;\n\tkey2 = value2;\n}"])

	TEST(@"-[allKeys]",
	    [[mutDict allKeys] isEqual: [OFArray arrayWithObjects: keys[0],
	    keys[1], nil]])

	TEST(@"-[allObjects]",
	    [[mutDict allObjects] isEqual: [OFArray arrayWithObjects: values[0],
	    values[1], nil]])

	TEST(@"-[keyEnumerator]", (keyEnumerator = [mutDict keyEnumerator]))
	TEST(@"-[objectEnumerator]",
	    (objectEnumerator = [mutDict objectEnumerator]))

	TEST(@"OFEnumerator's -[nextObject]",
	    [[keyEnumerator nextObject] isEqual: keys[0]] &&
	    [[objectEnumerator nextObject] isEqual: values[0]] &&
	    [[keyEnumerator nextObject] isEqual: keys[1]] &&
	    [[objectEnumerator nextObject] isEqual: values[1]] &&
	    [keyEnumerator nextObject] == nil &&
	    [objectEnumerator nextObject] == nil)

	[mutDict removeObjectForKey: keys[0]];

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

	[mutDict setObject: values[0] forKey: keys[0]];

	size_t i = 0;
	bool ok = true;

	for (OFString *key in mutDict) {
		if (i > 1 || ![key isEqual: keys[i]]) {
			ok = false;
			break;
		}


		[mutDict setObject: [mutDict objectForKey: key] forKey: key];
		i++;
	}

	TEST(@"Fast Enumeration", ok)

	ok = false;
	@try {
		for (OFString *key in mutDict) {
			(void)key;
			[mutDict setObject: @"" forKey: @""];
		}
	} @catch (OFEnumerationMutationException *e) {
		ok = true;
	}

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

	[mutDict removeObjectForKey: @""];

	TEST(@"-[stringByURLEncoding]",
	    [[[OFDictionary dictionaryWithKeysAndObjects: @"foo", @"bar",
							  @"q&x", @"q=x", nil]
	    stringByURLEncoding] isEqual: @"q%26x=q%3Dx&foo=bar"])

#ifdef OF_HAVE_BLOCKS
	{
		__block size_t j = 0;
		__block bool blockOk = true;

		[mutDict enumerateKeysAndObjectsUsingBlock:
		    ^ (id key, id object, bool *stop) {
			if (j > 1 || ![key isEqual: keys[j]]) {
				blockOk = false;
				*stop = true;
				return;
			}

			[mutDict setObject: [mutDict objectForKey: key]
				    forKey: key];
			j++;
		}];

		TEST(@"Enumeration using blocks", blockOk)

		blockOk = false;
		@try {
			[mutDict enumerateKeysAndObjectsUsingBlock:
			    ^ (id key, id object, bool *stop) {
				[mutDict setObject: @""
					    forKey: @""];
			}];
		} @catch (OFEnumerationMutationException *e) {
			blockOk = true;
		}

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

		[mutDict removeObjectForKey: @""];
	}

	TEST(@"-[replaceObjectsUsingBlock:]",
	    R([mutDict replaceObjectsUsingBlock: ^ id (id key, id object) {
		if ([key isEqual: keys[0]])
			return @"value_1";
		if ([key isEqual: keys[1]])
			return @"value_2";

		return nil;
	    }]) && [[mutDict objectForKey: keys[0]] isEqual: @"value_1"] &&
	    [[mutDict objectForKey: keys[1]] isEqual: @"value_2"])

	TEST(@"-[mappedDictionaryUsingBlock:]",
	    [[[mutDict mappedDictionaryUsingBlock: ^ id (id key, id object) {

		if ([key isEqual: keys[0]])
			return @"val1";
		if ([key isEqual: keys[1]])
			return @"val2";

		return nil;
	    }] description] isEqual: @"{\n\tkey1 = val1;\n\tkey2 = val2;\n}"])

	TEST(@"-[filteredDictionaryUsingBlock:]",
	    [[[mutDict filteredDictionaryUsingBlock:
	    ^ bool (id key, id object) {
		return [key isEqual: keys[0]];
	    }] description] isEqual: @"{\n\tkey1 = value_1;\n}"])
#endif

	TEST(@"-[count]", mutDict.count == 2)

	TEST(@"+[dictionaryWithKeysAndObjects:]",
	    (dict = [dictionaryClass dictionaryWithKeysAndObjects:
	    @"foo", @"bar", @"baz", @"qux", nil]) &&
	    [[dict objectForKey: @"foo"] isEqual: @"bar"] &&
	    [[dict objectForKey: @"baz"] isEqual: @"qux"])








|




|
|


|
|
|


|
|







|
|


|
|



|



|
|


|
|

|

|









|




|




|





>
|







|

|







|











|







|
|







|

|
<








|



|
|
|
|
|

|
|
|


|
>
|
|
|
|





|
|
|



|







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

@implementation TestsAppDelegate (OFDictionaryTests)
- (void)dictionaryTestsWithClass: (Class)dictionaryClass
		    mutableClass: (Class)mutableDictionaryClass
{
	void *pool = objc_autoreleasePoolPush();
	OFMutableDictionary *mutableDict = [mutableDictionaryClass dictionary];
	OFDictionary *dict;
	OFEnumerator *keyEnumerator, *objectEnumerator;
	OFArray *keysArray, *valuesArray;

	[mutableDict setObject: values[0] forKey: keys[0]];
	[mutableDict setValue: values[1] forKey: keys[1]];

	TEST(@"-[objectForKey:]",
	    [[mutableDict objectForKey: keys[0]] isEqual: values[0]] &&
	    [[mutableDict objectForKey: keys[1]] isEqual: values[1]] &&
	    [mutableDict objectForKey: @"key3"] == nil)

	TEST(@"-[valueForKey:]",
	    [[mutableDict valueForKey: keys[0]] isEqual: values[0]] &&
	    [[mutableDict valueForKey: @"@count"] isEqual:
	    [OFNumber numberWithInt: 2]])

	EXPECT_EXCEPTION(@"Catching -[setValue:forKey:] on immutable "
	    @"dictionary", OFUndefinedKeyException,
	    [[dictionaryClass dictionary] setValue: @"x" forKey: @"x"])

	TEST(@"-[containsObject:]",
	    [mutableDict containsObject: values[0]] &&
	    ![mutableDict containsObject: @"nonexistent"])

	TEST(@"-[containsObjectIdenticalTo:]",
	    [mutableDict containsObjectIdenticalTo: values[0]] &&
	    ![mutableDict containsObjectIdenticalTo:
	    [OFString stringWithString: values[0]]])

	TEST(@"-[description]",
	    [[mutableDict description] isEqual:
	    @"{\n\tkey1 = value1;\n\tkey2 = value2;\n}"])

	TEST(@"-[allKeys]",
	    [[mutableDict allKeys] isEqual:
	    [OFArray arrayWithObjects: keys[0], keys[1], nil]])

	TEST(@"-[allObjects]",
	    [[mutableDict allObjects] isEqual:
	    [OFArray arrayWithObjects: values[0], values[1], nil]])

	TEST(@"-[keyEnumerator]", (keyEnumerator = [mutableDict keyEnumerator]))
	TEST(@"-[objectEnumerator]",
	    (objectEnumerator = [mutableDict objectEnumerator]))

	TEST(@"OFEnumerator's -[nextObject]",
	    [[keyEnumerator nextObject] isEqual: keys[0]] &&
	    [[objectEnumerator nextObject] isEqual: values[0]] &&
	    [[keyEnumerator nextObject] isEqual: keys[1]] &&
	    [[objectEnumerator nextObject] isEqual: values[1]] &&
	    [keyEnumerator nextObject] == nil &&
	    [objectEnumerator nextObject] == nil)

	[mutableDict removeObjectForKey: keys[0]];

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

	[mutableDict setObject: values[0] forKey: keys[0]];

	size_t i = 0;
	bool ok = true;

	for (OFString *key in mutableDict) {
		if (i > 1 || ![key isEqual: keys[i]]) {
			ok = false;
			break;
		}

		[mutableDict setObject: [mutableDict objectForKey: key]
				forKey: key];
		i++;
	}

	TEST(@"Fast Enumeration", ok)

	ok = false;
	@try {
		for (OFString *key in mutableDict) {
			(void)key;
			[mutableDict setObject: @"" forKey: @""];
		}
	} @catch (OFEnumerationMutationException *e) {
		ok = true;
	}

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

	[mutableDict removeObjectForKey: @""];

	TEST(@"-[stringByURLEncoding]",
	    [[[OFDictionary dictionaryWithKeysAndObjects: @"foo", @"bar",
							  @"q&x", @"q=x", nil]
	    stringByURLEncoding] isEqual: @"q%26x=q%3Dx&foo=bar"])

#ifdef OF_HAVE_BLOCKS
	{
		__block size_t j = 0;
		__block bool blockOk = true;

		[mutableDict enumerateKeysAndObjectsUsingBlock:
		    ^ (id key, id object, bool *stop) {
			if (j > 1 || ![key isEqual: keys[j]]) {
				blockOk = false;
				*stop = true;
				return;
			}

			[mutableDict setObject: [mutableDict objectForKey: key]
					forKey: key];
			j++;
		}];

		TEST(@"Enumeration using blocks", blockOk)

		blockOk = false;
		@try {
			[mutableDict enumerateKeysAndObjectsUsingBlock:
			    ^ (id key, id object, bool *stop) {
				[mutableDict setObject: @"" forKey: @""];

			}];
		} @catch (OFEnumerationMutationException *e) {
			blockOk = true;
		}

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

		[mutableDict removeObjectForKey: @""];
	}

	TEST(@"-[replaceObjectsUsingBlock:]",
	    R([mutableDict replaceObjectsUsingBlock: ^ id (id key, id object) {
		    if ([key isEqual: keys[0]])
			    return @"value_1";
		    if ([key isEqual: keys[1]])
			    return @"value_2";

		    return nil;
	    }]) && [[mutableDict objectForKey: keys[0]] isEqual: @"value_1"] &&
	    [[mutableDict objectForKey: keys[1]] isEqual: @"value_2"])

	TEST(@"-[mappedDictionaryUsingBlock:]",
	    [[[mutableDict mappedDictionaryUsingBlock:
		^ id (id key, id object) {
		    if ([key isEqual: keys[0]])
			    return @"val1";
		    if ([key isEqual: keys[1]])
			    return @"val2";

		return nil;
	    }] description] isEqual: @"{\n\tkey1 = val1;\n\tkey2 = val2;\n}"])

	TEST(@"-[filteredDictionaryUsingBlock:]",
	    [[[mutableDict filteredDictionaryUsingBlock:
		^ bool (id key, id object) {
		    return [key isEqual: keys[0]];
	    }] description] isEqual: @"{\n\tkey1 = value_1;\n}"])
#endif

	TEST(@"-[count]", mutableDict.count == 2)

	TEST(@"+[dictionaryWithKeysAndObjects:]",
	    (dict = [dictionaryClass dictionaryWithKeysAndObjects:
	    @"foo", @"bar", @"baz", @"qux", nil]) &&
	    [[dict objectForKey: @"foo"] isEqual: @"bar"] &&
	    [[dict objectForKey: @"baz"] isEqual: @"qux"])

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

	TEST(@"-[copy]",
	    (dict = [[dict copy] autorelease]) &&
	    [[dict objectForKey: keys[0]] isEqual: values[0]] &&
	    [[dict objectForKey: keys[1]] isEqual: values[1]])

	TEST(@"-[mutableCopy]",
	    (mutDict = [[dict mutableCopy] autorelease]) &&
	    mutDict.count == dict.count &&
	    [[mutDict objectForKey: keys[0]] isEqual: values[0]] &&
	    [[mutDict objectForKey: keys[1]] isEqual: values[1]] &&
	    R([mutDict setObject: @"value3" forKey: @"key3"]) &&
	    [[mutDict objectForKey: @"key3"] isEqual: @"value3"] &&
	    [[mutDict objectForKey: keys[0]] isEqual: values[0]] &&
	    R([mutDict setObject: @"foo" forKey: keys[0]]) &&
	    [[mutDict objectForKey: keys[0]] isEqual: @"foo"])

	TEST(@"-[removeObjectForKey:]",
	    R([mutDict removeObjectForKey: keys[0]]) &&
	    [mutDict objectForKey: keys[0]] == nil)

	[mutDict setObject: @"foo" forKey: keys[0]];
	TEST(@"-[isEqual:]", ![mutDict isEqual: dict] &&
	    R([mutDict removeObjectForKey: @"key3"]) &&
	    ![mutDict isEqual: dict] &&
	    R([mutDict setObject: values[0] forKey: keys[0]]) &&
	    [mutDict isEqual: dict])

	objc_autoreleasePoolPop(pool);
}

- (void)dictionaryTests
{
	module = @"OFDictionary";







|
|
|
|
|
|
|
|
|


|
|

|
|
|
|
|
|







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

	TEST(@"-[copy]",
	    (dict = [[dict copy] autorelease]) &&
	    [[dict objectForKey: keys[0]] isEqual: values[0]] &&
	    [[dict objectForKey: keys[1]] isEqual: values[1]])

	TEST(@"-[mutableCopy]",
	    (mutableDict = [[dict mutableCopy] autorelease]) &&
	    mutableDict.count == dict.count &&
	    [[mutableDict objectForKey: keys[0]] isEqual: values[0]] &&
	    [[mutableDict objectForKey: keys[1]] isEqual: values[1]] &&
	    R([mutableDict setObject: @"value3" forKey: @"key3"]) &&
	    [[mutableDict objectForKey: @"key3"] isEqual: @"value3"] &&
	    [[mutableDict objectForKey: keys[0]] isEqual: values[0]] &&
	    R([mutableDict setObject: @"foo" forKey: keys[0]]) &&
	    [[mutableDict objectForKey: keys[0]] isEqual: @"foo"])

	TEST(@"-[removeObjectForKey:]",
	    R([mutableDict removeObjectForKey: keys[0]]) &&
	    [mutableDict objectForKey: keys[0]] == nil)

	[mutableDict setObject: @"foo" forKey: keys[0]];
	TEST(@"-[isEqual:]", ![mutableDict isEqual: dict] &&
	    R([mutableDict removeObjectForKey: @"key3"]) &&
	    ![mutableDict isEqual: dict] &&
	    R([mutableDict setObject: values[0] forKey: keys[0]]) &&
	    [mutableDict isEqual: dict])

	objc_autoreleasePoolPop(pool);
}

- (void)dictionaryTests
{
	module = @"OFDictionary";

Modified tests/OFHMACTests.m from [51628de7e9] to [f54d111cd0].

15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
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

#include "config.h"

#include <string.h>

#import "TestsAppDelegate.h"

static OFString *module = @"OFHMAC";
static const uint8_t key[] =
    "yM9h8K6IWnJRvxC/0F8XRWG7RnACDBz8wqK2tbXrYVLoKC3vPLeJikyJSM47tVHc"
    "DlXHww9zULAC2sJUlm2Kg1z4oz2aXY3Y1PQSB4VkC/m0DQ7hCI6cAg4TWnKdzWTy"
    "cvYGX+Y6HWeDY79/PGSd8fNItme6I8w4HDBqU7BP2sum3jbePJqoiSnhcyJZQTeZ"
    "jw0ZXoyrfHgOYD2M+NsTDaGpLblFtQ7n5CczjKtafG40PkEwx1dcrd46U9i3GyTK";
static const size_t key_length = sizeof(key);
static const uint8_t digest_md5[] =
    "\xCC\x1F\xEF\x09\x29\xA3\x25\x1A\x06\xA9\x83\x99\xF9\xBC\x8F\x42";
static const uint8_t digest_sha1[] =
    "\x94\xB9\x0A\x6F\xFB\xA7\x13\x6A\x75\x55"
    "\xD5\x7F\x5D\xB7\xF4\xCA\xEB\x4A\xDE\xBF";
static const uint8_t digest_rmd160[] =
    "\x2C\xE1\xED\x41\xC6\xF3\x51\xA8\x04\xD2"
    "\xC3\x9B\x08\x33\x3B\xD5\xC9\x00\x39\x50";
static const uint8_t digest_sha256[] =
    "\xFB\x8C\xDA\x88\xB3\x81\x32\x16\xD7\xD8\x62\xD4\xA6\x26\x9D\x77"
    "\x01\x99\x62\x65\x29\x02\x41\xE6\xEF\xA1\x02\x31\xA8\x9D\x77\x5D";
static const uint8_t digest_sha384[] =
    "\x2F\x4A\x47\xAE\x13\x8E\x96\x52\xF1\x8F\x05\xFD\x65\xCD\x9A\x97"
    "\x93\x2F\xC9\x02\xD6\xC6\xAB\x2E\x15\x76\xC0\xA7\xA0\x05\xF4\xEF"
    "\x14\x52\x33\x4B\x9C\x5F\xD8\x07\x4E\x98\xAE\x97\x46\x29\x24\xB4";
static const uint8_t digest_sha512[] =
    "\xF5\x8C\x3F\x9C\xA2\x2F\x0A\xF3\x26\xD8\xC0\x7E\x20\x63\x88\x61"
    "\xC9\xE1\x1F\xD7\xC7\xE5\x59\x33\xD5\x2F\xAF\x56\x1C\x94\xC8\xA4"
    "\x61\xB3\xF9\x1A\xE3\x09\x43\xA6\x5B\x85\xB1\x50\x5B\xCB\x1A\x2E"
    "\xB7\xE8\x87\xC1\x73\x19\x63\xF6\xA2\x91\x8D\x7E\x2E\xCC\xEC\x99";

@implementation TestsAppDelegate (OFHMACTests)
- (void)HMACTests
{
	void *pool = objc_autoreleasePoolPush();
	OFFile *f = [OFFile fileWithPath: @"testfile.bin" mode: @"r"];
	OFHMAC *HMAC_MD5, *HMAC_SHA1, *HMAC_RMD160;
	OFHMAC *HMAC_SHA256, *HMAC_SHA384, *HMAC_SHA512;

	TEST(@"+[HMACWithHashClass:] with MD5",
	    (HMAC_MD5 = [OFHMAC HMACWithHashClass: [OFMD5Hash class]
			    allowsSwappableMemory: true]))
	TEST(@"+[HMACWithHashClass:] with SHA-1",
	    (HMAC_SHA1 = [OFHMAC HMACWithHashClass: [OFSHA1Hash class]
			     allowsSwappableMemory: true]))
	TEST(@"+[HMACWithHashClass:] with RIPEMD-160",
	    (HMAC_RMD160 = [OFHMAC HMACWithHashClass: [OFRIPEMD160Hash class]
			       allowsSwappableMemory: true]))
	TEST(@"+[HMACWithHashClass:] with SHA-256",
	    (HMAC_SHA256 = [OFHMAC HMACWithHashClass: [OFSHA256Hash class]
			       allowsSwappableMemory: true]))
	TEST(@"+[HMACWithHashClass:] with SHA-384",
	    (HMAC_SHA384 = [OFHMAC HMACWithHashClass: [OFSHA384Hash class]
			       allowsSwappableMemory: true]))
	TEST(@"+[HMACWithHashClass:] with SHA-512",
	    (HMAC_SHA512 = [OFHMAC HMACWithHashClass: [OFSHA512Hash class]
			       allowsSwappableMemory: true]))

	EXPECT_EXCEPTION(@"Detection of missing key",
	    OFInvalidArgumentException, [HMAC_MD5 updateWithBuffer: ""
							    length: 0])

	TEST(@"-[setKey:length:] with MD5",
	    R([HMAC_MD5 setKey: key length: key_length]))
	TEST(@"-[setKey:length:] with SHA-1",
	    R([HMAC_SHA1 setKey: key length: key_length]))
	TEST(@"-[setKey:length:] with RIPEMD-160",
	    R([HMAC_RMD160 setKey: key length: key_length]))
	TEST(@"-[setKey:length:] with SHA-256",
	    R([HMAC_SHA256 setKey: key length: key_length]))
	TEST(@"-[setKey:length:] with SHA-384",
	    R([HMAC_SHA384 setKey: key length: key_length]))
	TEST(@"-[setKey:length:] with SHA-512",
	    R([HMAC_SHA512 setKey: key length: key_length]))

	while (!f.atEndOfStream) {
		char buf[64];
		size_t len = [f readIntoBuffer: buf length: 64];
		[HMAC_MD5 updateWithBuffer: buf length: len];
		[HMAC_SHA1 updateWithBuffer: buf length: len];
		[HMAC_RMD160 updateWithBuffer: buf length: len];
		[HMAC_SHA256 updateWithBuffer: buf length: len];
		[HMAC_SHA384 updateWithBuffer: buf length: len];
		[HMAC_SHA512 updateWithBuffer: buf length: len];
	}
	[f close];

	TEST(@"-[digest] with MD5",
	    memcmp(HMAC_MD5.digest, digest_md5, HMAC_MD5.digestSize) == 0)
	TEST(@"-[digest] with SHA-1",
	    memcmp(HMAC_SHA1.digest, digest_sha1, HMAC_SHA1.digestSize) == 0)
	TEST(@"-[digest] with RIPEMD-160",
	    memcmp(HMAC_RMD160.digest, digest_rmd160,
	    HMAC_RMD160.digestSize) == 0)
	TEST(@"-[digest] with SHA-256",
	    memcmp(HMAC_SHA256.digest, digest_sha256,
	    HMAC_SHA256.digestSize) == 0)
	TEST(@"-[digest] with SHA-384",
	    memcmp(HMAC_SHA384.digest, digest_sha384,
	    HMAC_SHA384.digestSize) == 0)
	TEST(@"-[digest] with SHA-512",
	    memcmp(HMAC_SHA512.digest, digest_sha512,
	    HMAC_SHA512.digestSize) == 0)

	objc_autoreleasePoolPop(pool);
}
@end







|





|
|

|


|


|


|



|









|
|
|


|
|

|
|

|
|

|
|

|
|

|
|


|
|


|

|

|

|

|

|

|
|
|
|
|
|
|
|
|

|


|

|

|
|

|
<

|
<

|
<




15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
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

#include "config.h"

#include <string.h>

#import "TestsAppDelegate.h"

static OFString *const module = @"OFHMAC";
static const uint8_t key[] =
    "yM9h8K6IWnJRvxC/0F8XRWG7RnACDBz8wqK2tbXrYVLoKC3vPLeJikyJSM47tVHc"
    "DlXHww9zULAC2sJUlm2Kg1z4oz2aXY3Y1PQSB4VkC/m0DQ7hCI6cAg4TWnKdzWTy"
    "cvYGX+Y6HWeDY79/PGSd8fNItme6I8w4HDBqU7BP2sum3jbePJqoiSnhcyJZQTeZ"
    "jw0ZXoyrfHgOYD2M+NsTDaGpLblFtQ7n5CczjKtafG40PkEwx1dcrd46U9i3GyTK";
static const size_t keyLength = sizeof(key);
static const uint8_t MD5Digest[] =
    "\xCC\x1F\xEF\x09\x29\xA3\x25\x1A\x06\xA9\x83\x99\xF9\xBC\x8F\x42";
static const uint8_t SHA1Digest[] =
    "\x94\xB9\x0A\x6F\xFB\xA7\x13\x6A\x75\x55"
    "\xD5\x7F\x5D\xB7\xF4\xCA\xEB\x4A\xDE\xBF";
static const uint8_t RIPEMD160Digest[] =
    "\x2C\xE1\xED\x41\xC6\xF3\x51\xA8\x04\xD2"
    "\xC3\x9B\x08\x33\x3B\xD5\xC9\x00\x39\x50";
static const uint8_t SHA256Digest[] =
    "\xFB\x8C\xDA\x88\xB3\x81\x32\x16\xD7\xD8\x62\xD4\xA6\x26\x9D\x77"
    "\x01\x99\x62\x65\x29\x02\x41\xE6\xEF\xA1\x02\x31\xA8\x9D\x77\x5D";
static const uint8_t SHA384Digest[] =
    "\x2F\x4A\x47\xAE\x13\x8E\x96\x52\xF1\x8F\x05\xFD\x65\xCD\x9A\x97"
    "\x93\x2F\xC9\x02\xD6\xC6\xAB\x2E\x15\x76\xC0\xA7\xA0\x05\xF4\xEF"
    "\x14\x52\x33\x4B\x9C\x5F\xD8\x07\x4E\x98\xAE\x97\x46\x29\x24\xB4";
static const uint8_t SHA512Digest[] =
    "\xF5\x8C\x3F\x9C\xA2\x2F\x0A\xF3\x26\xD8\xC0\x7E\x20\x63\x88\x61"
    "\xC9\xE1\x1F\xD7\xC7\xE5\x59\x33\xD5\x2F\xAF\x56\x1C\x94\xC8\xA4"
    "\x61\xB3\xF9\x1A\xE3\x09\x43\xA6\x5B\x85\xB1\x50\x5B\xCB\x1A\x2E"
    "\xB7\xE8\x87\xC1\x73\x19\x63\xF6\xA2\x91\x8D\x7E\x2E\xCC\xEC\x99";

@implementation TestsAppDelegate (OFHMACTests)
- (void)HMACTests
{
	void *pool = objc_autoreleasePoolPush();
	OFFile *file = [OFFile fileWithPath: @"testfile.bin" mode: @"r"];
	OFHMAC *HMACMD5, *HMACSHA1, *HMACRMD160;
	OFHMAC *HMACSHA256, *HMACSHA384, *HMACSHA512;

	TEST(@"+[HMACWithHashClass:] with MD5",
	    (HMACMD5 = [OFHMAC HMACWithHashClass: [OFMD5Hash class]
			   allowsSwappableMemory: true]))
	TEST(@"+[HMACWithHashClass:] with SHA-1",
	    (HMACSHA1 = [OFHMAC HMACWithHashClass: [OFSHA1Hash class]
			    allowsSwappableMemory: true]))
	TEST(@"+[HMACWithHashClass:] with RIPEMD-160",
	    (HMACRMD160 = [OFHMAC HMACWithHashClass: [OFRIPEMD160Hash class]
			      allowsSwappableMemory: true]))
	TEST(@"+[HMACWithHashClass:] with SHA-256",
	    (HMACSHA256 = [OFHMAC HMACWithHashClass: [OFSHA256Hash class]
			      allowsSwappableMemory: true]))
	TEST(@"+[HMACWithHashClass:] with SHA-384",
	    (HMACSHA384 = [OFHMAC HMACWithHashClass: [OFSHA384Hash class]
			      allowsSwappableMemory: true]))
	TEST(@"+[HMACWithHashClass:] with SHA-512",
	    (HMACSHA512 = [OFHMAC HMACWithHashClass: [OFSHA512Hash class]
			      allowsSwappableMemory: true]))

	EXPECT_EXCEPTION(@"Detection of missing key",
	    OFInvalidArgumentException,
	    [HMACMD5 updateWithBuffer: "" length: 0])

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

	while (!file.atEndOfStream) {
		char buffer[64];
		size_t length = [file readIntoBuffer: buffer length: 64];
		[HMACMD5 updateWithBuffer: buffer length: length];
		[HMACSHA1 updateWithBuffer: buffer length: length];
		[HMACRMD160 updateWithBuffer: buffer length: length];
		[HMACSHA256 updateWithBuffer: buffer length: length];
		[HMACSHA384 updateWithBuffer: buffer length: length];
		[HMACSHA512 updateWithBuffer: buffer length: length];
	}
	[file close];

	TEST(@"-[digest] with MD5",
	    memcmp(HMACMD5.digest, MD5Digest, HMACMD5.digestSize) == 0)
	TEST(@"-[digest] with SHA-1",
	    memcmp(HMACSHA1.digest, SHA1Digest, HMACSHA1.digestSize) == 0)
	TEST(@"-[digest] with RIPEMD-160",
	    memcmp(HMACRMD160.digest, RIPEMD160Digest,
	    HMACRMD160.digestSize) == 0)
	TEST(@"-[digest] with SHA-256",
	    memcmp(HMACSHA256.digest, SHA256Digest, HMACSHA256.digestSize) == 0)

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

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


	objc_autoreleasePoolPop(pool);
}
@end

Modified tests/OFHTTPClientTests.m from [76a48837cf] to [1197c752e1].

16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
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
#include "config.h"

#include <inttypes.h>
#include <string.h>

#import "TestsAppDelegate.h"

static OFString *module = @"OFHTTPClient";
static OFCondition *cond;
static OFHTTPResponse *response = nil;

@interface TestsAppDelegate (HTTPClientTests) <OFHTTPClientDelegate>
@end

@interface HTTPClientTestsServer: OFThread
{
@public
	uint16_t _port;
}
@end

@implementation HTTPClientTestsServer
- (id)main
{
	OFTCPSocket *listener, *client;
	char buffer[5];

	[cond lock];

	listener = [OFTCPSocket socket];
	_port = [listener bindToHost: @"127.0.0.1" port: 0];
	[listener listen];

	[cond signal];
	[cond unlock];

	client = [listener accept];

	if (![[client readLine] isEqual: @"GET /foo HTTP/1.1"])
		OFEnsure(0);

	if (![[client readLine] hasPrefix: @"User-Agent:"])
		OFEnsure(0);

	if (![[client readLine] isEqual: @"Content-Length: 5"])
		OFEnsure(0);

	if (![[client readLine] isEqual:
	    @"Content-Type: application/x-www-form-urlencoded; charset=UTF-8"])
		OFEnsure(0);

	if (![[client readLine] isEqual:
	    [OFString stringWithFormat: @"Host: 127.0.0.1:%" @PRIu16, _port]])
		OFEnsure(0);

	if (![[client readLine] isEqual: @""])
		OFEnsure(0);

	[client readIntoBuffer: buffer exactLength: 5];
	if (memcmp(buffer, "Hello", 5) != 0)
		OFEnsure(0);

	[client writeString: @"HTTP/1.0 200 OK\r\n"
			     @"cONTeNT-lENgTH: 7\r\n"
			     @"\r\n"
			     @"foo\n"
			     @"bar"];
	[client close];







|
|


















|





|
|



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





|
<


|
<







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
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 "config.h"

#include <inttypes.h>
#include <string.h>

#import "TestsAppDelegate.h"

static OFString *const module = @"OFHTTPClient";
static OFCondition *condition;
static OFHTTPResponse *response = nil;

@interface TestsAppDelegate (HTTPClientTests) <OFHTTPClientDelegate>
@end

@interface HTTPClientTestsServer: OFThread
{
@public
	uint16_t _port;
}
@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];

	OFEnsure([[client readLine] isEqual: @"GET /foo HTTP/1.1"]);


	OFEnsure([[client readLine] hasPrefix: @"User-Agent:"]);


	OFEnsure([[client readLine] isEqual: @"Content-Length: 5"]);


	OFEnsure([[client readLine] isEqual:
	    @"Content-Type: application/x-www-form-urlencoded; charset=UTF-8"]);


	if (![[client readLine] isEqual:
	    [OFString stringWithFormat: @"Host: 127.0.0.1:%" @PRIu16, _port]])
		OFEnsure(0);

	OFEnsure([[client readLine] isEqual: @""]);


	[client readIntoBuffer: buffer exactLength: 5];
	OFEnsure(memcmp(buffer, "Hello", 5) == 0);


	[client writeString: @"HTTP/1.0 200 OK\r\n"
			     @"cONTeNT-lENgTH: 7\r\n"
			     @"\r\n"
			     @"foo\n"
			     @"bar"];
	[client close];
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
	void *pool = objc_autoreleasePoolPush();
	HTTPClientTestsServer *server;
	OFURL *URL;
	OFHTTPClient *client;
	OFHTTPRequest *request;
	OFData *data;

	cond = [OFCondition condition];
	[cond lock];

	server = [[[HTTPClientTestsServer alloc] init] autorelease];
	server.supportsSockets = true;
	[server start];

	[cond wait];
	[cond unlock];

	URL = [OFURL URLWithString:
	    [OFString stringWithFormat: @"http://127.0.0.1:%" @PRIu16 "/foo",
					server->_port]];

	TEST(@"-[asyncPerformRequest:]",
	    (client = [OFHTTPClient client]) && (client.delegate = self) &&







|
|





|
|







102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
	void *pool = objc_autoreleasePoolPush();
	HTTPClientTestsServer *server;
	OFURL *URL;
	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];

	URL = [OFURL URLWithString:
	    [OFString stringWithFormat: @"http://127.0.0.1:%" @PRIu16 "/foo",
					server->_port]];

	TEST(@"-[asyncPerformRequest:]",
	    (client = [OFHTTPClient client]) && (client.delegate = self) &&

Modified tests/OFHTTPCookieManagerTests.m from [8226ed0409] to [d8c3ff9fea].

13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
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
 * file.
 */

#include "config.h"

#import "TestsAppDelegate.h"

static OFString *module = @"OFHTTPCookieManager";

@implementation TestsAppDelegate (OFHTTPCookieManagerTests)
- (void)HTTPCookieManagerTests
{
	void *pool = objc_autoreleasePoolPush();
	OFHTTPCookieManager *manager = [OFHTTPCookieManager manager];
	OFURL *URL[4];
	OFHTTPCookie *cookie[5];

	URL[0] = [OFURL URLWithString: @"http://nil.im/foo"];
	URL[1] = [OFURL URLWithString: @"https://nil.im/foo/bar"];
	URL[2] = [OFURL URLWithString: @"https://test.nil.im/foo/bar"];
	URL[3] = [OFURL URLWithString: @"http://webkeks.org/foo/bar"];

	cookie[0] = [OFHTTPCookie cookieWithName: @"test"
					   value: @"1"
					  domain: @"nil.im"];
	TEST(@"-[addCookie:forURL:] #1", R([manager addCookie: cookie[0]
						       forURL: URL[0]]))

	TEST(@"-[cookiesForURL:] #1",
	    [[manager cookiesForURL: URL[0]] isEqual:
	    [OFArray arrayWithObject: cookie[0]]])

	cookie[1] = [OFHTTPCookie cookieWithName: @"test"
					   value: @"2"
					  domain: @"webkeks.org"];
	TEST(@"-[addCookie:forURL:] #2",
	    R([manager addCookie: cookie[1] forURL: URL[0]]))

	TEST(@"-[cookiesForURL:] #2",
	    [[manager cookiesForURL: URL[0]] isEqual:
	    [OFArray arrayWithObject: cookie[0]]] &&
	    [[manager cookiesForURL: URL[3]] isEqual: [OFArray array]])

	cookie[2] = [OFHTTPCookie cookieWithName: @"test"
					   value: @"3"
					  domain: @"nil.im"];
	cookie[2].secure = true;
	TEST(@"-[addCookie:forURL:] #3",
	    R([manager addCookie: cookie[2] forURL: URL[1]]))

	TEST(@"-[cookiesForURL:] #3",
	    [[manager cookiesForURL: URL[1]] isEqual:
	    [OFArray arrayWithObject: cookie[2]]] &&
	    [[manager cookiesForURL: URL[0]] isEqual: [OFArray array]])

	cookie[2].expires = [OFDate dateWithTimeIntervalSinceNow: -1];
	cookie[3] = [OFHTTPCookie cookieWithName: @"test"
					   value: @"4"
					  domain: @"nil.im"];
	cookie[3].domain = @".nil.im";
	TEST(@"-[addCookie:forURL:] #4",
	    R([manager addCookie: cookie[3] forURL: URL[1]]))

	TEST(@"-[cookiesForURL:] #4",
	    [[manager cookiesForURL: URL[1]] isEqual:
	    [OFArray arrayWithObject: cookie[3]]] &&
	    [[manager cookiesForURL: URL[2]] isEqual:
	    [OFArray arrayWithObject: cookie[3]]])

	cookie[4] = [OFHTTPCookie cookieWithName: @"bar"
					   value: @"5"
					  domain: @"test.nil.im"];
	TEST(@"-[addCookie:forURL:] #5",
	    R([manager addCookie: cookie[4] forURL: URL[0]]))

	TEST(@"-[cookiesForURL:] #5",
	    [[manager cookiesForURL: URL[0]] isEqual:
	    [OFArray arrayWithObject: cookie[3]]] &&
	    [[manager cookiesForURL: URL[2]] isEqual:
	    [OFArray arrayWithObjects: cookie[3], cookie[4], nil]])

	TEST(@"-[purgeExpiredCookies]",
	    [manager.cookies isEqual:
	    [OFArray arrayWithObjects: cookie[2], cookie[3], cookie[4], nil]] &&
	    R([manager purgeExpiredCookies]) &&
	    [manager.cookies isEqual:
	    [OFArray arrayWithObjects: cookie[3], cookie[4], nil]])

	objc_autoreleasePoolPop(pool);
}
@end







|






|
|

|
|
|
|

|
|
|
|
|


|
|

|
|
|

|


|
|
|

|
|
|
|

|


|
|
|

|
|
|
|
|

|


|
|
|
|

|
|
|

|


|
|
|
|



|


|




13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
 * file.
 */

#include "config.h"

#import "TestsAppDelegate.h"

static OFString *const module = @"OFHTTPCookieManager";

@implementation TestsAppDelegate (OFHTTPCookieManagerTests)
- (void)HTTPCookieManagerTests
{
	void *pool = objc_autoreleasePoolPush();
	OFHTTPCookieManager *manager = [OFHTTPCookieManager manager];
	OFURL *URL1, *URL2, *URL3, *URL4;
	OFHTTPCookie *cookie1, *cookie2, *cookie3, *cookie4, *cookie5;

	URL1 = [OFURL URLWithString: @"http://nil.im/foo"];
	URL2 = [OFURL URLWithString: @"https://nil.im/foo/bar"];
	URL3 = [OFURL URLWithString: @"https://test.nil.im/foo/bar"];
	URL4 = [OFURL URLWithString: @"http://webkeks.org/foo/bar"];

	cookie1 = [OFHTTPCookie cookieWithName: @"test"
					 value: @"1"
					domain: @"nil.im"];
	TEST(@"-[addCookie:forURL:] #1",
	    R([manager addCookie: cookie1 forURL: URL1]))

	TEST(@"-[cookiesForURL:] #1",
	    [[manager cookiesForURL: URL1] isEqual:
	    [OFArray arrayWithObject: cookie1]])

	cookie2 = [OFHTTPCookie cookieWithName: @"test"
					 value: @"2"
					domain: @"webkeks.org"];
	TEST(@"-[addCookie:forURL:] #2",
	    R([manager addCookie: cookie2 forURL: URL1]))

	TEST(@"-[cookiesForURL:] #2",
	    [[manager cookiesForURL: URL1] isEqual:
	    [OFArray arrayWithObject: cookie1]] &&
	    [[manager cookiesForURL: URL4] isEqual: [OFArray array]])

	cookie3 = [OFHTTPCookie cookieWithName: @"test"
					 value: @"3"
					domain: @"nil.im"];
	cookie3.secure = true;
	TEST(@"-[addCookie:forURL:] #3",
	    R([manager addCookie: cookie3 forURL: URL2]))

	TEST(@"-[cookiesForURL:] #3",
	    [[manager cookiesForURL: URL2] isEqual:
	    [OFArray arrayWithObject: cookie3]] &&
	    [[manager cookiesForURL: URL1] isEqual: [OFArray array]])

	cookie3.expires = [OFDate dateWithTimeIntervalSinceNow: -1];
	cookie4 = [OFHTTPCookie cookieWithName: @"test"
					 value: @"4"
					domain: @"nil.im"];
	cookie4.domain = @".nil.im";
	TEST(@"-[addCookie:forURL:] #4",
	    R([manager addCookie: cookie4 forURL: URL2]))

	TEST(@"-[cookiesForURL:] #4",
	    [[manager cookiesForURL: URL2] isEqual:
	    [OFArray arrayWithObject: cookie4]] &&
	    [[manager cookiesForURL: URL3] isEqual:
	    [OFArray arrayWithObject: cookie4]])

	cookie5 = [OFHTTPCookie cookieWithName: @"bar"
					 value: @"5"
					domain: @"test.nil.im"];
	TEST(@"-[addCookie:forURL:] #5",
	    R([manager addCookie: cookie5 forURL: URL1]))

	TEST(@"-[cookiesForURL:] #5",
	    [[manager cookiesForURL: URL1] isEqual:
	    [OFArray arrayWithObject: cookie4]] &&
	    [[manager cookiesForURL: URL3] 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 [ea70ec9f7e] to [3f137e64cb].

13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
 * file.
 */

#include "config.h"

#import "TestsAppDelegate.h"

static OFString *module = @"OFHTTPCookie";

@implementation TestsAppDelegate (OFHTTPCookieTests)
- (void)HTTPCookieTests
{
	void *pool = objc_autoreleasePoolPush();
	OFURL *URL = [OFURL URLWithString: @"http://nil.im"];
	OFHTTPCookie *cookie[2];
	OFArray OF_GENERIC(OFHTTPCookie *) *cookies;

	cookie[0] = [OFHTTPCookie cookieWithName: @"foo"
					   value: @"bar"
					  domain: @"nil.im"];
	TEST(@"+[cookiesWithResponseHeaderFields:forURL:] #1",
	    [[OFHTTPCookie cookiesWithResponseHeaderFields: [OFDictionary
	    dictionaryWithObject: @"foo=bar"
	    forKey: @"Set-Cookie"] forURL: URL]
	    isEqual: [OFArray arrayWithObject: cookie[0]]])

	cookie[1] = [OFHTTPCookie cookieWithName: @"qux"
					   value: @"cookie"
					  domain: @"nil.im"];
	TEST(@"+[cookiesWithResponseHeaderFields:forURL:] #2",
	    [[OFHTTPCookie cookiesWithResponseHeaderFields: [OFDictionary
	    dictionaryWithObject: @"foo=bar,qux=cookie"
	    forKey: @"Set-Cookie"] forURL: URL]
	    isEqual: [OFArray arrayWithObjects: cookie[0], cookie[1], nil]])

	cookie[0].expires = [OFDate dateWithTimeIntervalSince1970: 1234567890];
	cookie[1].expires = [OFDate dateWithTimeIntervalSince1970: 1234567890];
	cookie[0].path = @"/x";
	cookie[1].domain = @"webkeks.org";
	cookie[1].path = @"/objfw";
	cookie[1].secure = true;
	cookie[1].HTTPOnly = true;
	[cookie[1].extensions addObject: @"foo"];
	[cookie[1].extensions addObject: @"bar"];
	TEST(@"+[cookiesWithResponseHeaderFields:forURL:] #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"] forURL: URL]) isEqual:
	    [OFArray arrayWithObjects: cookie[0], cookie[1], nil]])

	TEST(@"+[requestHeaderFieldsWithCookies:]",
	    [[OFHTTPCookie requestHeaderFieldsWithCookies: cookies] isEqual:
	    [OFDictionary dictionaryWithObject: @"foo=bar; qux=cookie"
					forKey: @"Cookie"]])

	objc_autoreleasePoolPop(pool);
}
@end







|






|


|
|
|




|

|
|
|




|

|
|
|
|
|
|
|
|
|







|









13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
 * file.
 */

#include "config.h"

#import "TestsAppDelegate.h"

static OFString *const module = @"OFHTTPCookie";

@implementation TestsAppDelegate (OFHTTPCookieTests)
- (void)HTTPCookieTests
{
	void *pool = objc_autoreleasePoolPush();
	OFURL *URL = [OFURL URLWithString: @"http://nil.im"];
	OFHTTPCookie *cookie1, *cookie2;
	OFArray OF_GENERIC(OFHTTPCookie *) *cookies;

	cookie1 = [OFHTTPCookie cookieWithName: @"foo"
					 value: @"bar"
					domain: @"nil.im"];
	TEST(@"+[cookiesWithResponseHeaderFields:forURL:] #1",
	    [[OFHTTPCookie cookiesWithResponseHeaderFields: [OFDictionary
	    dictionaryWithObject: @"foo=bar"
	    forKey: @"Set-Cookie"] forURL: URL]
	    isEqual: [OFArray arrayWithObject: cookie1]])

	cookie2 = [OFHTTPCookie cookieWithName: @"qux"
					 value: @"cookie"
					domain: @"nil.im"];
	TEST(@"+[cookiesWithResponseHeaderFields:forURL:] #2",
	    [[OFHTTPCookie cookiesWithResponseHeaderFields: [OFDictionary
	    dictionaryWithObject: @"foo=bar,qux=cookie"
	    forKey: @"Set-Cookie"] forURL: URL]
	    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:forURL:] #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"] forURL: URL]) 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 [0d85330d49] to [9af27af9d8].

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

#include "config.h"

#import "TestsAppDelegate.h"

static OFString *module = @"OFINIFile";

@implementation TestsAppDelegate (OFINIFileTests)
- (void)INIFileTests
{
	void *pool = objc_autoreleasePoolPush();
	OFString *output = @"[tests]\r\n"
	    @"foo=baz\r\n"







|







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

#include "config.h"

#import "TestsAppDelegate.h"

static OFString *module;

@implementation TestsAppDelegate (OFINIFileTests)
- (void)INIFileTests
{
	void *pool = objc_autoreleasePoolPush();
	OFString *output = @"[tests]\r\n"
	    @"foo=baz\r\n"
45
46
47
48
49
50
51


52
53
54
55
56
57
58
	    @"double=0.75\r\n";
	OFINIFile *file;
	OFINICategory *tests, *foobar, *types;
	OFArray *array;
#ifndef OF_NINTENDO_DS
	OFString *writePath;
#endif



	TEST(@"+[fileWithPath:encoding:]",
	    (file = [OFINIFile fileWithPath: @"testfile.ini"
				   encoding: OFStringEncodingCodepage437]))

	tests = [file categoryForName: @"tests"];
	foobar = [file categoryForName: @"foobar"];







>
>







45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
	    @"double=0.75\r\n";
	OFINIFile *file;
	OFINICategory *tests, *foobar, *types;
	OFArray *array;
#ifndef OF_NINTENDO_DS
	OFString *writePath;
#endif

	module = @"OFINIFile";

	TEST(@"+[fileWithPath:encoding:]",
	    (file = [OFINIFile fileWithPath: @"testfile.ini"
				   encoding: OFStringEncodingCodepage437]))

	tests = [file categoryForName: @"tests"];
	foobar = [file categoryForName: @"foobar"];
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
	    R([foobar removeValueForKey: @"quxqux "]) &&
	    R([types removeValueForKey: @"array2"]))

	module = @"OFINIFile";

	/* FIXME: Find a way to write files on Nintendo DS */
#ifndef OF_NINTENDO_DS
# ifndef OF_IOS
	writePath = @"tmpfile.ini";
# else
	writePath = [OFString pathWithComponents: [OFArray arrayWithObjects:
	    [[OFApplication environment] objectForKey: @"HOME"],
	    @"tmp", @"tmpfile.ini", nil]];
# endif
	TEST(@"-[writeToFile:encoding:]",
	    R([file writeToFile: writePath
		       encoding: OFStringEncodingCodepage437]) &&
	    [[OFString
		stringWithContentsOfFile: writePath
				encoding: OFStringEncodingCodepage437]
	    isEqual: output])
	[[OFFileManager defaultManager] removeItemAtPath: writePath];
#else
	(void)output;
#endif

	objc_autoreleasePoolPop(pool);
}
@end







<
|
<
|
<
<
<



<
|
|









110
111
112
113
114
115
116

117

118



119
120
121

122
123
124
125
126
127
128
129
130
131
132
	    R([foobar removeValueForKey: @"quxqux "]) &&
	    R([types removeValueForKey: @"array2"]))

	module = @"OFINIFile";

	/* FIXME: Find a way to write files on Nintendo DS */
#ifndef OF_NINTENDO_DS

	writePath = [[OFSystemInfo temporaryDirectoryPath]

	    stringByAppendingPathComponent: @"objfw-tests.ini"];



	TEST(@"-[writeToFile:encoding:]",
	    R([file writeToFile: writePath
		       encoding: OFStringEncodingCodepage437]) &&

	    [[OFString stringWithContentsOfFile: writePath
				       encoding: OFStringEncodingCodepage437]
	    isEqual: output])
	[[OFFileManager defaultManager] removeItemAtPath: writePath];
#else
	(void)output;
#endif

	objc_autoreleasePoolPop(pool);
}
@end

Modified tests/OFIPXSocketTests.m from [d96f547fea] to [a26f3af451].

15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

#include "config.h"

#include <errno.h>

#import "TestsAppDelegate.h"

static OFString *module = @"OFIPXSocket";

@implementation TestsAppDelegate (OFIPXSocketTests)
- (void)IPXSocketTests
{
	void *pool = objc_autoreleasePoolPush();
	OFIPXSocket *sock;
	OFSocketAddress address1, address2;







|







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

#include "config.h"

#include <errno.h>

#import "TestsAppDelegate.h"

static OFString *const module = @"OFIPXSocket";

@implementation TestsAppDelegate (OFIPXSocketTests)
- (void)IPXSocketTests
{
	void *pool = objc_autoreleasePoolPush();
	OFIPXSocket *sock;
	OFSocketAddress address1, address2;

Modified tests/OFInvocationTests.m from [475125e587] to [a2e3d6960f].

20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56

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

#import "TestsAppDelegate.h"

static OFString *module = @"OFInvocation";

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

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

- (void)invocationTests
{
	void *pool = objc_autoreleasePoolPush();
	SEL selector = @selector(invocationTestMethod1::::);
	OFMethodSignature *sig = [self methodSignatureForSelector: selector];
	OFInvocation *invocation;
	struct test_struct st, st2, *stp = &st, *stp2;
	unsigned const char c = 0xAA;
	unsigned char c2;
	const unsigned int i = 0x55555555;
	unsigned int i2;

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







|

|





|
|
|
|










|







20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56

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

#import "TestsAppDelegate.h"

static OFString *const module = @"OFInvocation";

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

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

- (void)invocationTests
{
	void *pool = objc_autoreleasePoolPush();
	SEL selector = @selector(invocationTestMethod1::::);
	OFMethodSignature *sig = [self methodSignatureForSelector: selector];
	OFInvocation *invocation;
	struct TestStruct st, st2, *stp = &st, *stp2;
	unsigned const char c = 0xAA;
	unsigned char c2;
	const unsigned int i = 0x55555555;
	unsigned int i2;

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

Modified tests/OFJSONTests.m from [15d8e0cc74] to [4a647fbb7e].

13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

40
41

42
43
44
45

46
47
48
49
50

51
52
53
54
55
56
57
58
 * file.
 */

#include "config.h"

#import "TestsAppDelegate.h"

static OFString *module = @"OFJSON";

@implementation TestsAppDelegate (JSONTests)
- (void)JSONTests
{
	void *pool = objc_autoreleasePoolPush();
	OFString *s = @"{\"foo\"\t:'b\\na\\r', \"x\":/*foo*/ [.5\r,0xF,null"
	    @"//bar\n,\"foo\",false]}";
	OFDictionary *d = [OFDictionary dictionaryWithKeysAndObjects:
	    @"foo", @"b\na\r",
	    @"x", [OFArray arrayWithObjects:
	    [OFNumber numberWithFloat: .5f],
	    [OFNumber numberWithInt: 0xF],
	    [OFNull null],
	    @"foo",
	    [OFNumber numberWithBool: false],
	    nil],
	    nil];

	TEST(@"-[objectByParsingJSON] #1", [s.objectByParsingJSON isEqual: d])


	TEST(@"-[JSONRepresentation]", [[d JSONRepresentation] isEqual:

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

	TEST(@"OFJSONRepresentationOptionPretty",
	    [[d JSONRepresentationWithOptions: OFJSONRepresentationOptionPretty]

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

	TEST(@"OFJSONRepresentationOptionJSON5",
	    [[d JSONRepresentationWithOptions: OFJSONRepresentationOptionJSON5]

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

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







|





|
|
|


|
|
|
|
|
|


|
>

|
>



|
>
|
|


|
>
|







13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
 * file.
 */

#include "config.h"

#import "TestsAppDelegate.h"

static OFString *const module = @"OFJSON";

@implementation TestsAppDelegate (JSONTests)
- (void)JSONTests
{
	void *pool = objc_autoreleasePoolPush();
	OFString *string = @"{\"foo\"\t:'b\\na\\r', \"x\":/*foo*/ [.5\r,0xF,"
	    @"null//bar\n,\"foo\",false]}";
	OFDictionary *dict = [OFDictionary dictionaryWithKeysAndObjects:
	    @"foo", @"b\na\r",
	    @"x", [OFArray arrayWithObjects:
		[OFNumber numberWithFloat: .5f],
		[OFNumber numberWithInt: 0xF],
		[OFNull null],
		@"foo",
		[OFNumber numberWithBool: false],
		nil],
	    nil];

	TEST(@"-[objectByParsingJSON] #1",
	    [string.objectByParsingJSON isEqual: dict])

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

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

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

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

Modified tests/OFKernelEventObserverTests.m from [e1e120ef88] to [f4ab45b387].

26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#endif
#ifdef HAVE_SELECT
# import "OFSelectKernelEventObserver.h"
#endif

#import "TestsAppDelegate.h"

#define EXPECTED_EVENTS 3

static OFString *module;

@interface ObserverTest: OFObject <OFKernelEventObserverDelegate>
{
@public
	TestsAppDelegate *_testsAppDelegate;







|







26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#endif
#ifdef HAVE_SELECT
# import "OFSelectKernelEventObserver.h"
#endif

#import "TestsAppDelegate.h"

static const size_t numExpectedEvents = 3;

static OFString *module;

@interface ObserverTest: OFObject <OFKernelEventObserverDelegate>
{
@public
	TestsAppDelegate *_testsAppDelegate;
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
	OFDate *deadline;
	bool deadlineExceeded = false;

	[_testsAppDelegate outputTesting: @"-[observe] with listening socket"
				inModule: module];

	deadline = [OFDate dateWithTimeIntervalSinceNow: 1];
	while (_events < EXPECTED_EVENTS) {
		if (deadline.timeIntervalSinceNow < 0) {
			deadlineExceeded = true;
			break;
		}

		[_observer observeForTimeInterval: 0.01];
	}

	if (!deadlineExceeded)
		[_testsAppDelegate
		    outputSuccess: @"-[observe] not exceeding deadline"
			 inModule: module];
	else {
		[_testsAppDelegate
		    outputFailure: @"-[observe] not exceeding deadline"
			 inModule: module];
		_fails++;
	}

	if (_events == EXPECTED_EVENTS)
		[_testsAppDelegate
		    outputSuccess: @"-[observe] handling all events"
			 inModule: module];
	else {
		[_testsAppDelegate
		    outputFailure: @"-[observe] handling all events"
			 inModule: module];
		_fails++;
	}
}

- (void)objectIsReadyForReading: (id)object
{
	char buf;

	switch (_events++) {
	case 0:
		if (object == _server)
			[_testsAppDelegate
			    outputSuccess: @"-[observe] with listening socket"
				 inModule: module];







|



















|













|







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
	OFDate *deadline;
	bool deadlineExceeded = false;

	[_testsAppDelegate outputTesting: @"-[observe] with listening socket"
				inModule: module];

	deadline = [OFDate dateWithTimeIntervalSinceNow: 1];
	while (_events < numExpectedEvents) {
		if (deadline.timeIntervalSinceNow < 0) {
			deadlineExceeded = true;
			break;
		}

		[_observer observeForTimeInterval: 0.01];
	}

	if (!deadlineExceeded)
		[_testsAppDelegate
		    outputSuccess: @"-[observe] not exceeding deadline"
			 inModule: module];
	else {
		[_testsAppDelegate
		    outputFailure: @"-[observe] not exceeding deadline"
			 inModule: module];
		_fails++;
	}

	if (_events == numExpectedEvents)
		[_testsAppDelegate
		    outputSuccess: @"-[observe] handling all events"
			 inModule: module];
	else {
		[_testsAppDelegate
		    outputFailure: @"-[observe] handling all events"
			 inModule: module];
		_fails++;
	}
}

- (void)objectIsReadyForReading: (id)object
{
	char buffer;

	switch (_events++) {
	case 0:
		if (object == _server)
			[_testsAppDelegate
			    outputSuccess: @"-[observe] with listening socket"
				 inModule: module];
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
		[_testsAppDelegate
		    outputTesting: @"-[observe] with data ready to read"
			 inModule: module];

		break;
	case 1:
		if (object == _accepted &&
		    [object readIntoBuffer: &buf length: 1] == 1 && buf == '0')

			[_testsAppDelegate
			    outputSuccess: @"-[observe] with data ready to read"
				 inModule: module];
		else {
			[_testsAppDelegate
			    outputFailure: @"-[observe] with data ready to read"
				 inModule: module];
			_fails++;
		}

		[_client close];

		[_testsAppDelegate
		    outputTesting: @"-[observe] with closed connection"
			 inModule: module];

		break;
	case 2:
		if (object == _accepted &&
		    [object readIntoBuffer: &buf length: 1] == 0)
			[_testsAppDelegate
			    outputSuccess: @"-[observe] with closed connection"
				 inModule: module];
		else {
			[_testsAppDelegate
			    outputFailure: @"-[observe] with closed connection"
				 inModule: module];







|
>



















|







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
		[_testsAppDelegate
		    outputTesting: @"-[observe] with data ready to read"
			 inModule: module];

		break;
	case 1:
		if (object == _accepted &&
		    [object readIntoBuffer: &buffer length: 1] == 1 &&
		    buffer == '0')
			[_testsAppDelegate
			    outputSuccess: @"-[observe] with data ready to read"
				 inModule: module];
		else {
			[_testsAppDelegate
			    outputFailure: @"-[observe] with data ready to read"
				 inModule: module];
			_fails++;
		}

		[_client close];

		[_testsAppDelegate
		    outputTesting: @"-[observe] with closed connection"
			 inModule: module];

		break;
	case 2:
		if (object == _accepted &&
		    [object readIntoBuffer: &buffer length: 1] == 0)
			[_testsAppDelegate
			    outputSuccess: @"-[observe] with closed connection"
				 inModule: module];
		else {
			[_testsAppDelegate
			    outputFailure: @"-[observe] with closed connection"
				 inModule: module];

Modified tests/OFListTests.m from [ede47645fa] to [890c1e2652].

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

#include "config.h"

#import "TestsAppDelegate.h"

static OFString *module = @"OFList";
static OFString *strings[] = {
	@"Foo",
	@"Bar",
	@"Baz"
};

@implementation TestsAppDelegate (OFListTests)
- (void)listTests
{
	void *pool = objc_autoreleasePoolPush();
	OFList *list;
	OFEnumerator *enumerator;
	OFListItem iter;
	OFString *obj;
	size_t i;
	bool ok;

	TEST(@"+[list]", (list = [OFList list]))

	TEST(@"-[appendObject:]", [list appendObject: strings[0]] &&
	    [list appendObject: strings[1]] && [list appendObject: strings[2]])







|













|







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

#include "config.h"

#import "TestsAppDelegate.h"

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

@implementation TestsAppDelegate (OFListTests)
- (void)listTests
{
	void *pool = objc_autoreleasePoolPush();
	OFList *list;
	OFEnumerator *enumerator;
	OFListItem iter;
	OFString *object;
	size_t i;
	bool ok;

	TEST(@"+[list]", (list = [OFList list]))

	TEST(@"-[appendObject:]", [list appendObject: strings[0]] &&
	    [list appendObject: strings[1]] && [list appendObject: strings[2]])
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
	    [list.description isEqual: @"[\n\tFoo,\n\tBar,\n\tBaz\n]"])

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

	iter = list.firstListItem;
	i = 0;
	ok = true;
	while ((obj = [enumerator nextObject]) != nil) {
		if (![obj isEqual: OFListItemObject(iter)])
			ok = false;

		iter = OFListItemNext(iter);
		i++;
	}

	if (list.count != i)







|
|







93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
	    [list.description isEqual: @"[\n\tFoo,\n\tBar,\n\tBaz\n]"])

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

	iter = list.firstListItem;
	i = 0;
	ok = true;
	while ((object = [enumerator nextObject]) != nil) {
		if (![object isEqual: OFListItemObject(iter)])
			ok = false;

		iter = OFListItemNext(iter);
		i++;
	}

	if (list.count != i)
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

	[list prependObject: strings[0]];

	iter = list.firstListItem;
	i = 0;
	ok = true;

	for (OFString *object in list) {
		if (![object isEqual: OFListItemObject(iter)])
			ok = false;

		iter = OFListItemNext(iter);
		i++;
	}

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

	TEST(@"Fast Enumeration", ok)

	ok = false;
	@try {
		for (OFString *object in list) {
			(void)object;

			[list removeListItem: list.lastListItem];
		}
	} @catch (OFEnumerationMutationException *e) {
		ok = true;
	}

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

	objc_autoreleasePoolPop(pool);
}
@end







|
|













|
|












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

	[list prependObject: strings[0]];

	iter = list.firstListItem;
	i = 0;
	ok = true;

	for (OFString *object_ in list) {
		if (![object_ isEqual: OFListItemObject(iter)])
			ok = false;

		iter = OFListItemNext(iter);
		i++;
	}

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

	TEST(@"Fast Enumeration", ok)

	ok = false;
	@try {
		for (OFString *object_ in list) {
			(void)object_;

			[list removeListItem: list.lastListItem];
		}
	} @catch (OFEnumerationMutationException *e) {
		ok = true;
	}

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

	objc_autoreleasePoolPop(pool);
}
@end

Modified tests/OFMD5HashTests.m from [73092aedf1] to [e16a55e7a6].

15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
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 "config.h"

#include <string.h>

#import "TestsAppDelegate.h"

static OFString *module = @"OFMD5Hash";

const uint8_t testfile_md5[16] =
	"\x00\x8B\x9D\x1B\x58\xDF\xF8\xFE\xEE\xF3\xAE\x8D\xBB\x68\x2D\x38";

@implementation TestsAppDelegate (OFMD5HashTests)
- (void)MD5HashTests
{
	void *pool = objc_autoreleasePoolPush();
	OFMD5Hash *md5, *copy;
	OFFile *f = [OFFile fileWithPath: @"testfile.bin" mode: @"r"];

	TEST(@"+[hashWithAllowsSwappableMemory:]",
	    (md5 = [OFMD5Hash hashWithAllowsSwappableMemory: true]))

	while (!f.atEndOfStream) {
		char buf[64];
		size_t len = [f readIntoBuffer: buf length: 64];
		[md5 updateWithBuffer: buf length: len];
	}
	[f close];

	TEST(@"-[copy]", (copy = [[md5 copy] autorelease]))

	TEST(@"-[digest]",
	    memcmp(md5.digest, testfile_md5, 16) == 0 &&
	    memcmp(copy.digest, testfile_md5, 16) == 0)

	EXPECT_EXCEPTION(@"Detect invalid call of "
	    @"-[updateWithBuffer:length]", OFHashAlreadyCalculatedException,
	    [md5 updateWithBuffer: "" length: 1])

	objc_autoreleasePoolPop(pool);
}
@end







|

|
|





|
|


|

|
|
|
|

|

|


|
|



|




15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
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 "config.h"

#include <string.h>

#import "TestsAppDelegate.h"

static OFString *const module = @"OFMD5Hash";

const uint8_t testFileMD5[16] =
    "\x00\x8B\x9D\x1B\x58\xDF\xF8\xFE\xEE\xF3\xAE\x8D\xBB\x68\x2D\x38";

@implementation TestsAppDelegate (OFMD5HashTests)
- (void)MD5HashTests
{
	void *pool = objc_autoreleasePoolPush();
	OFMD5Hash *MD5, *MD5Copy;
	OFFile *file = [OFFile fileWithPath: @"testfile.bin" mode: @"r"];

	TEST(@"+[hashWithAllowsSwappableMemory:]",
	    (MD5 = [OFMD5Hash hashWithAllowsSwappableMemory: true]))

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

	TEST(@"-[copy]", (MD5Copy = [[MD5 copy] autorelease]))

	TEST(@"-[digest]",
	    memcmp(MD5.digest, testFileMD5, 16) == 0 &&
	    memcmp(MD5Copy.digest, testFileMD5, 16) == 0)

	EXPECT_EXCEPTION(@"Detect invalid call of "
	    @"-[updateWithBuffer:length]", OFHashAlreadyCalculatedException,
	    [MD5 updateWithBuffer: "" length: 1])

	objc_autoreleasePoolPop(pool);
}
@end

Modified tests/OFMethodSignatureTests.m from [364a3b706f] to [ebd654aa45].

19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
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

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

#import "TestsAppDelegate.h"

static OFString *module = @"OFMethodSignature";

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

struct test2_struct {
	char c;
	struct {
		short s;
		int i;
	} st;
	union {
		char c;
		int i;
	} u;
	double d;
};

#if !defined(__STDC_NO_COMPLEX__) && defined(HAVE_COMPLEX_H)
struct test3_struct {
	char c;
	complex double cd;
};
#endif

union test3_union {
	char c;
	int i;
	double d;
};

union test4_union {
	char c;
	struct {
		short x, y;
	} st;
	int i;
	union {
		float f;
		double d;
	} u;
};

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

	TEST(@"-[signatureWithObjCTypes:] #1",
	    (ms = [OFMethodSignature signatureWithObjCTypes:
	    "i28@0:8S16*20"]) && ms.numberOfArguments == 4 &&

	    strcmp(ms.methodReturnType, "i") == 0 &&
	    strcmp([ms argumentTypeAtIndex: 0], "@") == 0 &&
	    strcmp([ms argumentTypeAtIndex: 1], ":") == 0 &&
	    strcmp([ms argumentTypeAtIndex: 2], "S") == 0 &&
	    strcmp([ms argumentTypeAtIndex: 3], "*") == 0 &&

	    ms.frameLength == 28 && [ms argumentOffsetAtIndex: 0] == 0 &&
	    [ms argumentOffsetAtIndex: 1] == 8 &&
	    [ms argumentOffsetAtIndex: 2] == 16 &&
	    [ms argumentOffsetAtIndex: 3] == 20)

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

	    "{s0=csi(u1={s2=iii{s3=(u4=ic^v*)}})}") == 0 &&
	    strcmp([ms argumentTypeAtIndex: 0], "@") == 0 &&
	    strcmp([ms argumentTypeAtIndex: 1], ":") == 0 &&
	    strcmp([ms argumentTypeAtIndex: 2],
	    "^{s0=csi(u1={s2=iii{s3=(u4=ic^v*)}})}") == 0 &&

	    ms.frameLength == 24 && [ms argumentOffsetAtIndex: 0] == 0 &&
	    [ms argumentOffsetAtIndex: 1] == 8 &&
	    [ms argumentOffsetAtIndex: 2] == 16)

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

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

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

	EXPECT_EXCEPTION(@"-[signatureWithObjCTypes:] #6",
	    OFInvalidFormatException,
	    [OFMethodSignature signatureWithObjCTypes: "{{}0"])

	TEST(@"OFSizeOfTypeEncoding() #1",
	    OFSizeOfTypeEncoding(@encode(struct test1_struct)) ==
	    sizeof(struct test1_struct))

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

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

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

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

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

	TEST(@"OFAlignmentOfTypeEncoding() #1",
	    OFAlignmentOfTypeEncoding(@encode(struct test1_struct)) ==
	    OF_ALIGNOF(struct test1_struct))

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

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

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

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

	TEST(@"OFAlignmentOfTypeEncoding() #6",
	    OFAlignmentOfTypeEncoding(@encode(struct test1_struct [5])) ==
	    OF_ALIGNOF(struct test1_struct [5]))

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

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

#import "TestsAppDelegate.h"

static OFString *const module = @"OFMethodSignature";

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

struct Test2Struct {
	char c;
	struct {
		short s;
		int i;
	} st;
	union {
		char c;
		int i;
	} u;
	double d;
};

#if !defined(__STDC_NO_COMPLEX__) && defined(HAVE_COMPLEX_H)
struct Test3Struct {
	char c;
	complex double cd;
};
#endif

union Test3Union {
	char c;
	int i;
	double d;
};

union Test4Union {
	char c;
	struct {
		short x, y;
	} st;
	int i;
	union {
		float f;
		double d;
	} u;
};

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

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

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

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

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

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

	EXPECT_EXCEPTION(@"-[signatureWithObjCTypes:] #6",
	    OFInvalidFormatException,
	    [OFMethodSignature signatureWithObjCTypes: "{{}0"])

	TEST(@"OFSizeOfTypeEncoding() #1",
	    OFSizeOfTypeEncoding(@encode(struct Test1Struct)) ==
	    sizeof(struct Test1Struct))

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

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

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

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

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

	TEST(@"OFAlignmentOfTypeEncoding() #1",
	    OFAlignmentOfTypeEncoding(@encode(struct Test1Struct)) ==
	    OF_ALIGNOF(struct Test1Struct))

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

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

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

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

	TEST(@"OFAlignmentOfTypeEncoding() #6",
	    OFAlignmentOfTypeEncoding(@encode(struct Test1Struct [5])) ==
	    OF_ALIGNOF(struct Test1Struct [5]))

	objc_autoreleasePoolPop(pool);
}
@end

Modified tests/OFNumberTests.m from [92564f033d] to [c0de3f5f8b].

13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
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
 * file.
 */

#include "config.h"

#import "TestsAppDelegate.h"

static OFString *module = @"OFNumber";

@implementation TestsAppDelegate (OFNumberTests)
- (void)numberTests
{
	void *pool = objc_autoreleasePoolPush();
	OFNumber *num;

	TEST(@"+[numberWithLongLong:]",
	    (num = [OFNumber numberWithLongLong: 123456789]))

	TEST(@"-[isEqual:]",
	    [num isEqual: [OFNumber numberWithLong: 123456789]])

	TEST(@"-[hash]", num.hash == 0x82D8BC42)

	TEST(@"-[charValue]", num.charValue == 21)

	TEST(@"-[doubleValue]", num.doubleValue == 123456789.L)

	TEST(@"signed char minimum & maximum unmodified",
	    (num = [OFNumber numberWithChar: SCHAR_MIN]) &&
	    num.charValue == SCHAR_MIN &&
	    (num = [OFNumber numberWithChar: SCHAR_MAX]) &&
	    num.charValue == SCHAR_MAX)

	TEST(@"short minimum & maximum unmodified",
	    (num = [OFNumber numberWithShort: SHRT_MIN]) &&
	    num.shortValue == SHRT_MIN &&
	    (num = [OFNumber numberWithShort: SHRT_MAX]) &&
	    num.shortValue == SHRT_MAX)

	TEST(@"int minimum & maximum unmodified",
	    (num = [OFNumber numberWithInt: INT_MIN]) &&
	    num.intValue == INT_MIN &&
	    (num = [OFNumber numberWithInt: INT_MAX]) &&
	    num.intValue == INT_MAX)

	TEST(@"long minimum & maximum unmodified",
	    (num = [OFNumber numberWithLong: LONG_MIN]) &&
	    num.longValue == LONG_MIN &&
	    (num = [OFNumber numberWithLong: LONG_MAX]) &&
	    num.longValue == LONG_MAX)

	TEST(@"long long minimum & maximum unmodified",
	    (num = [OFNumber numberWithLongLong: LLONG_MIN]) &&
	    num.longLongValue == LLONG_MIN &&
	    (num = [OFNumber numberWithLongLong: LLONG_MAX]) &&
	    num.longLongValue == LLONG_MAX)

	TEST(@"unsigned char maximum unmodified",
	    (num = [OFNumber numberWithUnsignedChar: UCHAR_MAX]) &&
	    num.unsignedCharValue == UCHAR_MAX)

	TEST(@"unsigned short maximum unmodified",
	    (num = [OFNumber numberWithUnsignedShort: USHRT_MAX]) &&
	    num.unsignedShortValue == USHRT_MAX)

	TEST(@"unsigned int maximum unmodified",
	    (num = [OFNumber numberWithUnsignedInt: UINT_MAX]) &&
	    num.unsignedIntValue == UINT_MAX)

	TEST(@"unsigned long maximum unmodified",
	    (num = [OFNumber numberWithUnsignedLong: ULONG_MAX]) &&
	    num.unsignedLongValue == ULONG_MAX)

	TEST(@"unsigned long long maximum unmodified",
	    (num = [OFNumber numberWithUnsignedLongLong: ULLONG_MAX]) &&
	    num.unsignedLongLongValue == ULLONG_MAX)

	objc_autoreleasePoolPop(pool);
}
@end







|





|


|


|

|

|

|


|
|
|
|


|
|
|
|


|
|
|
|


|
|
|
|


|
|
|
|


|
|


|
|


|
|


|
|


|
|




13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
 * file.
 */

#include "config.h"

#import "TestsAppDelegate.h"

static OFString *const module = @"OFNumber";

@implementation TestsAppDelegate (OFNumberTests)
- (void)numberTests
{
	void *pool = objc_autoreleasePoolPush();
	OFNumber *number;

	TEST(@"+[numberWithLongLong:]",
	    (number = [OFNumber numberWithLongLong: 123456789]))

	TEST(@"-[isEqual:]",
	    [number isEqual: [OFNumber numberWithLong: 123456789]])

	TEST(@"-[hash]", number.hash == 0x82D8BC42)

	TEST(@"-[charValue]", number.charValue == 21)

	TEST(@"-[doubleValue]", number.doubleValue == 123456789.L)

	TEST(@"signed char minimum & maximum unmodified",
	    (number = [OFNumber numberWithChar: SCHAR_MIN]) &&
	    number.charValue == SCHAR_MIN &&
	    (number = [OFNumber numberWithChar: SCHAR_MAX]) &&
	    number.charValue == SCHAR_MAX)

	TEST(@"short minimum & maximum unmodified",
	    (number = [OFNumber numberWithShort: SHRT_MIN]) &&
	    number.shortValue == SHRT_MIN &&
	    (number = [OFNumber numberWithShort: SHRT_MAX]) &&
	    number.shortValue == SHRT_MAX)

	TEST(@"int minimum & maximum unmodified",
	    (number = [OFNumber numberWithInt: INT_MIN]) &&
	    number.intValue == INT_MIN &&
	    (number = [OFNumber numberWithInt: INT_MAX]) &&
	    number.intValue == INT_MAX)

	TEST(@"long minimum & maximum unmodified",
	    (number = [OFNumber numberWithLong: LONG_MIN]) &&
	    number.longValue == LONG_MIN &&
	    (number = [OFNumber numberWithLong: LONG_MAX]) &&
	    number.longValue == LONG_MAX)

	TEST(@"long long minimum & maximum unmodified",
	    (number = [OFNumber numberWithLongLong: LLONG_MIN]) &&
	    number.longLongValue == LLONG_MIN &&
	    (number = [OFNumber numberWithLongLong: LLONG_MAX]) &&
	    number.longLongValue == LLONG_MAX)

	TEST(@"unsigned char maximum unmodified",
	    (number = [OFNumber numberWithUnsignedChar: UCHAR_MAX]) &&
	    number.unsignedCharValue == UCHAR_MAX)

	TEST(@"unsigned short maximum unmodified",
	    (number = [OFNumber numberWithUnsignedShort: USHRT_MAX]) &&
	    number.unsignedShortValue == USHRT_MAX)

	TEST(@"unsigned int maximum unmodified",
	    (number = [OFNumber numberWithUnsignedInt: UINT_MAX]) &&
	    number.unsignedIntValue == UINT_MAX)

	TEST(@"unsigned long maximum unmodified",
	    (number = [OFNumber numberWithUnsignedLong: ULONG_MAX]) &&
	    number.unsignedLongValue == ULONG_MAX)

	TEST(@"unsigned long long maximum unmodified",
	    (number = [OFNumber numberWithUnsignedLongLong: ULLONG_MAX]) &&
	    number.unsignedLongLongValue == ULLONG_MAX)

	objc_autoreleasePoolPop(pool);
}
@end

Modified tests/OFObjectTests.m from [15af30b63f] to [84ff5d698c].

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

#if (defined(OF_DRAGONFLYBSD) && defined(__LP64__)) || defined(OF_NINTENDO_3DS)
# define TOO_BIG (SIZE_MAX / 3)
#else
# define TOO_BIG (SIZE_MAX - 128)
#endif

static OFString *module = @"OFObject";

@interface MyObj: OFObject
{
	id _objectValue;
	Class _classValue;
	bool _boolValue;
	char _charValue;
	short _shortValue;
	int _intValue;







|

|







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

#if (defined(OF_DRAGONFLYBSD) && defined(__LP64__)) || defined(OF_NINTENDO_3DS)
# define TOO_BIG (SIZE_MAX / 3)
#else
# define TOO_BIG (SIZE_MAX - 128)
#endif

static OFString *const module = @"OFObject";

@interface MyObject: OFObject
{
	id _objectValue;
	Class _classValue;
	bool _boolValue;
	char _charValue;
	short _shortValue;
	int _intValue;
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
@property (nonatomic) unsigned int unsignedIntValue;
@property (nonatomic) unsigned long unsignedLongValue;
@property (nonatomic) unsigned long long unsignedLongLongValue;
@property (nonatomic) float floatValue;
@property (nonatomic) double doubleValue;
@end

@implementation MyObj
@synthesize objectValue = _objectValue, classValue = _classValue;
@synthesize boolValue = _boolValue, charValue = _charValue;
@synthesize shortValue = _shortValue, intValue = _intValue;
@synthesize longValue = _longValue, longLongValue = _longLongValue;
@synthesize unsignedCharValue = _unsignedCharValue;
@synthesize unsignedShortValue = _unsignedShortValue;
@synthesize unsignedIntValue = _unsignedIntValue;







|







57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
@property (nonatomic) unsigned int unsignedIntValue;
@property (nonatomic) unsigned long unsignedLongValue;
@property (nonatomic) unsigned long long unsignedLongLongValue;
@property (nonatomic) float floatValue;
@property (nonatomic) double doubleValue;
@end

@implementation MyObject
@synthesize objectValue = _objectValue, classValue = _classValue;
@synthesize boolValue = _boolValue, charValue = _charValue;
@synthesize shortValue = _shortValue, intValue = _intValue;
@synthesize longValue = _longValue, longLongValue = _longLongValue;
@synthesize unsignedCharValue = _unsignedCharValue;
@synthesize unsignedShortValue = _unsignedShortValue;
@synthesize unsignedIntValue = _unsignedIntValue;
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
}
@end

@implementation TestsAppDelegate (OFObjectTests)
- (void)objectTests
{
	void *pool = objc_autoreleasePoolPush();
	OFObject *o;
	MyObj *m;

	TEST(@"+[description]",
	    [[OFObject description] isEqual: @"OFObject"] &&
	    [[MyObj description] isEqual: @"MyObj"])

	o = [[[OFObject alloc] init] autorelease];
	m = [[[MyObj alloc] init] autorelease];

	TEST(@"-[description]",
	    [o.description isEqual: @"<OFObject>"] &&
	    [m.description isEqual: @"<MyObj>"])

	m.objectValue = @"Hello";
	m.classValue = [m class];
	TEST(@"-[valueForKey:]",
	    [[m valueForKey: @"objectValue"] isEqual: @"Hello"] &&
	    [[m valueForKey: @"classValue"] isEqual: m.class] &&
	    [[m valueForKey: @"class"] isEqual: m.class])

	EXPECT_EXCEPTION(@"-[valueForKey:] with undefined key",
	    OFUndefinedKeyException, [m valueForKey: @"undefined"])

	TEST(@"-[setValue:forKey:]",
	    R([m setValue: @"World" forKey: @"objectValue"]) &&
	    R([m setValue: [OFObject class] forKey: @"classValue"]) &&
	    [m.objectValue isEqual: @"World"] &&
	    [m.classValue isEqual: [OFObject class]])

	EXPECT_EXCEPTION(@"-[setValue:forKey:] with undefined key",
	    OFUndefinedKeyException, [m setValue: @"x" forKey: @"undefined"])


	m.boolValue = 1;
	m.charValue = 2;
	m.shortValue = 3;
	m.intValue = 4;
	m.longValue = 5;
	m.longLongValue = 6;
	m.unsignedCharValue = 7;
	m.unsignedShortValue = 8;
	m.unsignedIntValue = 9;
	m.unsignedLongValue = 10;
	m.unsignedLongLongValue = 11;
	m.floatValue = 12;
	m.doubleValue = 13;
	TEST(@"Auto-wrapping of -[valueForKey:]",
	    [[m valueForKey: @"boolValue"] isEqual:
	    [OFNumber numberWithBool: 1]] &&
	    [[m valueForKey: @"charValue"] isEqual:
	    [OFNumber numberWithChar: 2]] &&
	    [[m valueForKey: @"shortValue"] isEqual:
	    [OFNumber numberWithShort: 3]] &&
	    [[m valueForKey: @"intValue"] isEqual:
	    [OFNumber numberWithInt: 4]] &&
	    [[m valueForKey: @"longValue"] isEqual:
	    [OFNumber numberWithLong: 5]] &&
	    [[m valueForKey: @"longLongValue"] isEqual:
	    [OFNumber numberWithLongLong: 6]] &&
	    [[m valueForKey: @"unsignedCharValue"] isEqual:
	    [OFNumber numberWithUnsignedChar: 7]] &&
	    [[m valueForKey: @"unsignedShortValue"] isEqual:
	    [OFNumber numberWithUnsignedShort: 8]] &&
	    [[m valueForKey: @"unsignedIntValue"] isEqual:
	    [OFNumber numberWithUnsignedInt: 9]] &&
	    [[m valueForKey: @"unsignedLongValue"] isEqual:
	    [OFNumber numberWithUnsignedLong: 10]] &&
	    [[m valueForKey: @"unsignedLongLongValue"] isEqual:
	    [OFNumber numberWithUnsignedLongLong: 11]] &&
	    [[m valueForKey: @"floatValue"] isEqual:
	    [OFNumber numberWithFloat: 12]] &&
	    [[m valueForKey: @"doubleValue"] isEqual:
	    [OFNumber numberWithDouble: 13]])

	TEST(@"Auto-wrapping of -[setValue:forKey:]",
	    R([m setValue: [OFNumber numberWithBool: 0]
		   forKey: @"boolValue"]) &&
	    R([m setValue: [OFNumber numberWithChar: 10]
		   forKey: @"charValue"]) &&
	    R([m setValue: [OFNumber numberWithShort: 20]
		   forKey: @"shortValue"]) &&
	    R([m setValue: [OFNumber numberWithInt: 30]
		   forKey: @"intValue"]) &&
	    R([m setValue: [OFNumber numberWithLong: 40]
		   forKey: @"longValue"]) &&
	    R([m setValue: [OFNumber numberWithLongLong: 50]
		   forKey: @"longLongValue"]) &&
	    R([m setValue: [OFNumber numberWithUnsignedChar: 60]
		   forKey: @"unsignedCharValue"]) &&
	    R([m setValue: [OFNumber numberWithUnsignedShort: 70]
		   forKey: @"unsignedShortValue"]) &&
	    R([m setValue: [OFNumber numberWithUnsignedInt: 80]
		   forKey: @"unsignedIntValue"]) &&
	    R([m setValue: [OFNumber numberWithUnsignedLong: 90]
		   forKey: @"unsignedLongValue"]) &&
	    R([m setValue: [OFNumber numberWithUnsignedLongLong: 100]
		   forKey: @"unsignedLongLongValue"]) &&
	    R([m setValue: [OFNumber numberWithFloat: 110]
		   forKey: @"floatValue"]) &&
	    R([m setValue: [OFNumber numberWithDouble: 120]
		   forKey: @"doubleValue"]) &&
	    m.isBoolValue == 0 && m.charValue == 10 && m.shortValue == 20 &&

	    m.intValue == 30 && m.longValue == 40 && m.longLongValue == 50 &&

	    m.unsignedCharValue == 60 && m.unsignedShortValue == 70 &&

	    m.unsignedIntValue == 80 && m.unsignedLongValue == 90 &&
	    m.unsignedLongLongValue == 100 && m.floatValue == 110 &&

	    m.doubleValue == 120)

	EXPECT_EXCEPTION(@"Catch -[setValue:forKey:] with nil key for scalar",
	    OFInvalidArgumentException, [m setValue: (id _Nonnull)nil
					     forKey: @"intValue"])

	TEST(@"-[valueForKeyPath:]",
	    (m = [[[MyObj alloc] init] autorelease]) &&
	    (m.objectValue = [[[MyObj alloc] init] autorelease]) &&
	    R([m.objectValue
	    setObjectValue: [[[MyObj alloc] init] autorelease]]) &&
	    R([[m.objectValue objectValue] setDoubleValue: 0.5]) &&
	    [[m valueForKeyPath: @"objectValue.objectValue.doubleValue"]
	    doubleValue] == 0.5)

	TEST(@"[-setValue:forKeyPath:]",
	    R([m setValue: [OFNumber numberWithDouble: 0.75]
	       forKeyPath: @"objectValue.objectValue.doubleValue"]) &&
	    [[m.objectValue objectValue] doubleValue] == 0.75)

	objc_autoreleasePoolPop(pool);
}
@end







|
|



|

|
|


|
|

|
|

|
|
|


|


|
|
|
|


|
>

|
|
|
|
|
|
|
|
|
|
|
|
|

|

|

|

|

|

|

|

|

|

|

|

|

|



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


|
|


|
|
|
|
|
|



|
|
|




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
}
@end

@implementation TestsAppDelegate (OFObjectTests)
- (void)objectTests
{
	void *pool = objc_autoreleasePoolPush();
	OFObject *object;
	MyObject *myObject;

	TEST(@"+[description]",
	    [[OFObject description] isEqual: @"OFObject"] &&
	    [[MyObject description] isEqual: @"MyObject"])

	object = [[[OFObject alloc] init] autorelease];
	myObject = [[[MyObject alloc] init] autorelease];

	TEST(@"-[description]",
	    [object.description isEqual: @"<OFObject>"] &&
	    [myObject.description isEqual: @"<MyObject>"])

	myObject.objectValue = @"Hello";
	myObject.classValue = myObject.class;
	TEST(@"-[valueForKey:]",
	    [[myObject valueForKey: @"objectValue"] isEqual: @"Hello"] &&
	    [[myObject valueForKey: @"classValue"] isEqual: myObject.class] &&
	    [[myObject valueForKey: @"class"] isEqual: myObject.class])

	EXPECT_EXCEPTION(@"-[valueForKey:] with undefined key",
	    OFUndefinedKeyException, [myObject valueForKey: @"undefined"])

	TEST(@"-[setValue:forKey:]",
	    R([myObject setValue: @"World" forKey: @"objectValue"]) &&
	    R([myObject setValue: [OFObject class] forKey: @"classValue"]) &&
	    [myObject.objectValue isEqual: @"World"] &&
	    [myObject.classValue isEqual: [OFObject class]])

	EXPECT_EXCEPTION(@"-[setValue:forKey:] with undefined key",
	    OFUndefinedKeyException,
	    [myObject setValue: @"x" forKey: @"undefined"])

	myObject.boolValue = 1;
	myObject.charValue = 2;
	myObject.shortValue = 3;
	myObject.intValue = 4;
	myObject.longValue = 5;
	myObject.longLongValue = 6;
	myObject.unsignedCharValue = 7;
	myObject.unsignedShortValue = 8;
	myObject.unsignedIntValue = 9;
	myObject.unsignedLongValue = 10;
	myObject.unsignedLongLongValue = 11;
	myObject.floatValue = 12;
	myObject.doubleValue = 13;
	TEST(@"Auto-wrapping of -[valueForKey:]",
	    [[myObject valueForKey: @"boolValue"] isEqual:
	    [OFNumber numberWithBool: 1]] &&
	    [[myObject valueForKey: @"charValue"] isEqual:
	    [OFNumber numberWithChar: 2]] &&
	    [[myObject valueForKey: @"shortValue"] isEqual:
	    [OFNumber numberWithShort: 3]] &&
	    [[myObject valueForKey: @"intValue"] isEqual:
	    [OFNumber numberWithInt: 4]] &&
	    [[myObject valueForKey: @"longValue"] isEqual:
	    [OFNumber numberWithLong: 5]] &&
	    [[myObject valueForKey: @"longLongValue"] isEqual:
	    [OFNumber numberWithLongLong: 6]] &&
	    [[myObject valueForKey: @"unsignedCharValue"] isEqual:
	    [OFNumber numberWithUnsignedChar: 7]] &&
	    [[myObject valueForKey: @"unsignedShortValue"] isEqual:
	    [OFNumber numberWithUnsignedShort: 8]] &&
	    [[myObject valueForKey: @"unsignedIntValue"] isEqual:
	    [OFNumber numberWithUnsignedInt: 9]] &&
	    [[myObject valueForKey: @"unsignedLongValue"] isEqual:
	    [OFNumber numberWithUnsignedLong: 10]] &&
	    [[myObject valueForKey: @"unsignedLongLongValue"] isEqual:
	    [OFNumber numberWithUnsignedLongLong: 11]] &&
	    [[myObject valueForKey: @"floatValue"] isEqual:
	    [OFNumber numberWithFloat: 12]] &&
	    [[myObject valueForKey: @"doubleValue"] isEqual:
	    [OFNumber numberWithDouble: 13]])

	TEST(@"Auto-wrapping of -[setValue:forKey:]",
	    R([myObject setValue: [OFNumber numberWithBool: 0]
			  forKey: @"boolValue"]) &&
	    R([myObject setValue: [OFNumber numberWithChar: 10]
			  forKey: @"charValue"]) &&
	    R([myObject setValue: [OFNumber numberWithShort: 20]
			  forKey: @"shortValue"]) &&
	    R([myObject setValue: [OFNumber numberWithInt: 30]
			  forKey: @"intValue"]) &&
	    R([myObject setValue: [OFNumber numberWithLong: 40]
			  forKey: @"longValue"]) &&
	    R([myObject setValue: [OFNumber numberWithLongLong: 50]
			  forKey: @"longLongValue"]) &&
	    R([myObject setValue: [OFNumber numberWithUnsignedChar: 60]
			  forKey: @"unsignedCharValue"]) &&
	    R([myObject setValue: [OFNumber numberWithUnsignedShort: 70]
			  forKey: @"unsignedShortValue"]) &&
	    R([myObject setValue: [OFNumber numberWithUnsignedInt: 80]
			  forKey: @"unsignedIntValue"]) &&
	    R([myObject setValue: [OFNumber numberWithUnsignedLong: 90]
			  forKey: @"unsignedLongValue"]) &&
	    R([myObject setValue: [OFNumber numberWithUnsignedLongLong: 100]
			  forKey: @"unsignedLongLongValue"]) &&
	    R([myObject setValue: [OFNumber numberWithFloat: 110]
			  forKey: @"floatValue"]) &&
	    R([myObject setValue: [OFNumber numberWithDouble: 120]
			  forKey: @"doubleValue"]) &&
	    myObject.isBoolValue == 0 && myObject.charValue == 10 &&
	    myObject.shortValue == 20 && myObject.intValue == 30 &&
	    myObject.longValue == 40 && myObject.longLongValue == 50 &&
	    myObject.unsignedCharValue == 60 &&
	    myObject.unsignedShortValue == 70 &&
	    myObject.unsignedIntValue == 80 &&
	    myObject.unsignedLongValue == 90 &&
	    myObject.unsignedLongLongValue == 100 &&
	    myObject.floatValue == 110 &&
	    myObject.doubleValue == 120)

	EXPECT_EXCEPTION(@"Catch -[setValue:forKey:] with nil key for scalar",
	    OFInvalidArgumentException,
	    [myObject setValue: (id _Nonnull)nil forKey: @"intValue"])

	TEST(@"-[valueForKeyPath:]",
	    (myObject = [[[MyObject alloc] init] autorelease]) &&
	    (myObject.objectValue = [[[MyObject alloc] init] autorelease]) &&
	    R([myObject.objectValue
	    setObjectValue: [[[MyObject alloc] init] autorelease]]) &&
	    R([[myObject.objectValue objectValue] setDoubleValue: 0.5]) &&
	    [[myObject valueForKeyPath: @"objectValue.objectValue.doubleValue"]
	    doubleValue] == 0.5)

	TEST(@"[-setValue:forKeyPath:]",
	    R([myObject setValue: [OFNumber numberWithDouble: 0.75]
		      forKeyPath: @"objectValue.objectValue.doubleValue"]) &&
	    [[myObject.objectValue objectValue] doubleValue] == 0.75)

	objc_autoreleasePoolPop(pool);
}
@end

Renamed and modified tests/PBKDF2Tests.m [c97ca65028] to tests/OFPBKDF2Tests.m [650e1671f9].

15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

#include "config.h"

#include <string.h>

#import "TestsAppDelegate.h"

static OFString *module = @"PBKDF2";

@implementation TestsAppDelegate (PBKDF2Tests)
- (void)PBKDF2Tests
{
	void *pool = objc_autoreleasePoolPush();
	OFHMAC *HMAC = [OFHMAC HMACWithHashClass: [OFSHA1Hash class]
			   allowsSwappableMemory: true];
	unsigned char key[25];








|

|







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

#include "config.h"

#include <string.h>

#import "TestsAppDelegate.h"

static OFString *const module = @"OFPBKDF2";

@implementation TestsAppDelegate (OFPBKDF2Tests)
- (void)PBKDF2Tests
{
	void *pool = objc_autoreleasePoolPush();
	OFHMAC *HMAC = [OFHMAC HMACWithHashClass: [OFSHA1Hash class]
			   allowsSwappableMemory: true];
	unsigned char key[25];

Modified tests/OFPluginTests.m from [79f8663f0b] to [4801b7fe9e].

16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include "config.h"

#import "TestsAppDelegate.h"

#import "plugin/TestPlugin.h"

#ifndef OF_IOS
# define PLUGIN_PATH @"plugin/TestPlugin"
#else
# define PLUGIN_PATH @"PlugIns/TestPlugin"
#endif

static OFString *module = @"OFPlugin";

@implementation TestsAppDelegate (OFPluginTests)
- (void)pluginTests
{
	void *pool = objc_autoreleasePoolPush();
	TestPlugin *plugin;

	TEST(@"+[pluginWithPath:]",
	    (plugin = [OFPlugin pluginWithPath: PLUGIN_PATH]))

	TEST(@"TestPlugin's -[test:]", [plugin test: 1234] == 2468)

	objc_autoreleasePoolPop(pool);
}
@end







|

|


|








|






16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include "config.h"

#import "TestsAppDelegate.h"

#import "plugin/TestPlugin.h"

#ifndef OF_IOS
static OFString *const pluginPath = @"plugin/TestPlugin";
#else
static OFString *const pluginPath = @"PlugIns/TestPlugin";
#endif

static OFString *const module = @"OFPlugin";

@implementation TestsAppDelegate (OFPluginTests)
- (void)pluginTests
{
	void *pool = objc_autoreleasePoolPush();
	TestPlugin *plugin;

	TEST(@"+[pluginWithPath:]",
	    (plugin = [OFPlugin pluginWithPath: pluginPath]))

	TEST(@"TestPlugin's -[test:]", [plugin test: 1234] == 2468)

	objc_autoreleasePoolPop(pool);
}
@end

Modified tests/OFPropertyListTests.m from [f46fac19eb] to [9ca2969379].

21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
	@"<?xml version=\"1.0\" encoding=\"UTF-8\"?>"			\
	@"<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" "	\
	@"\"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">"		\
	@"<plist version=\"1.0\">\n"					\
	x @"\n"								\
	@"</plist>"

static OFString *module = @"OFPropertyList";
static OFString *PLIST1 = PLIST(@"<string>Hello</string>");
static OFString *PLIST2 = PLIST(
    @"<array>"
    @" <string>Hello</string>"
    @" <data>V29ybGQh</data>"
    @" <date>2018-03-14T12:34:56Z</date>"
    @" <true/>"
    @" <false/>"
    @" <real>12.25</real>"
    @" <integer>-10</integer>"
    @"</array>");
static OFString *PLIST3 = PLIST(
    @"<dict>"
    @" <key>array</key>"
    @" <array>"
    @"  <string>Hello</string>"
    @"  <data>V29ybGQh</data>"
    @"  <date>2018-03-14T12:34:56Z</date>"
    @"  <true/>"







|
|
|









|







21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
	@"<?xml version=\"1.0\" encoding=\"UTF-8\"?>"			\
	@"<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" "	\
	@"\"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">"		\
	@"<plist version=\"1.0\">\n"					\
	x @"\n"								\
	@"</plist>"

static OFString *const module = @"OFPropertyList";
static OFString *const PLIST1 = PLIST(@"<string>Hello</string>");
static OFString *const PLIST2 = PLIST(
    @"<array>"
    @" <string>Hello</string>"
    @" <data>V29ybGQh</data>"
    @" <date>2018-03-14T12:34:56Z</date>"
    @" <true/>"
    @" <false/>"
    @" <real>12.25</real>"
    @" <integer>-10</integer>"
    @"</array>");
static OFString *const PLIST3 = PLIST(
    @"<dict>"
    @" <key>array</key>"
    @" <array>"
    @"  <string>Hello</string>"
    @"  <data>V29ybGQh</data>"
    @"  <date>2018-03-14T12:34:56Z</date>"
    @"  <true/>"

Modified tests/OFRIPEMD160HashTests.m from [4b2bd712b4] to [00f15b1edb].

15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
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 <string.h>

#import "TestsAppDelegate.h"

static OFString *module = @"OFRIPEMD160Hash";

const uint8_t testfile_rmd160[20] =
	"\x46\x02\x97\xF5\x85\xDF\xB9\x21\x00\xC8\xF9\x87\xC6\xEC\x84\x0D\xCE"
	"\xE6\x08\x8B";

@implementation TestsAppDelegate (OFRIPEMD160HashTests)
- (void)RIPEMD160HashTests
{
	void *pool = objc_autoreleasePoolPush();
	OFRIPEMD160Hash *rmd160, *copy;
	OFFile *f = [OFFile fileWithPath: @"testfile.bin" mode: @"r"];

	TEST(@"+[hashWithAllowsSwappableMemory:]",
	    (rmd160 = [OFRIPEMD160Hash hashWithAllowsSwappableMemory: true]))

	while (!f.atEndOfStream) {
		char buf[64];
		size_t len = [f readIntoBuffer: buf length: 64];
		[rmd160 updateWithBuffer: buf length: len];
	}
	[f close];

	TEST(@"-[copy]", (copy = [[rmd160 copy] autorelease]))

	TEST(@"-[digest]",
	    memcmp(rmd160.digest, testfile_rmd160, 20) == 0 &&
	    memcmp(copy.digest, testfile_rmd160, 20) == 0)

	EXPECT_EXCEPTION(@"Detect invalid call of "
	    @"-[updateWithBuffer:length]", OFHashAlreadyCalculatedException,
	    [rmd160 updateWithBuffer: "" length: 1])

	objc_autoreleasePoolPop(pool);
}
@end







|

|







|
|


|

|
|
|
|

|

|


|
|



|




15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
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 <string.h>

#import "TestsAppDelegate.h"

static OFString *const module = @"OFRIPEMD160Hash";

const uint8_t testFileRIPEMD160[20] =
	"\x46\x02\x97\xF5\x85\xDF\xB9\x21\x00\xC8\xF9\x87\xC6\xEC\x84\x0D\xCE"
	"\xE6\x08\x8B";

@implementation TestsAppDelegate (OFRIPEMD160HashTests)
- (void)RIPEMD160HashTests
{
	void *pool = objc_autoreleasePoolPush();
	OFRIPEMD160Hash *RIPEMD160, *RIPEMD160Copy;
	OFFile *file = [OFFile fileWithPath: @"testfile.bin" mode: @"r"];

	TEST(@"+[hashWithAllowsSwappableMemory:]",
	    (RIPEMD160 = [OFRIPEMD160Hash hashWithAllowsSwappableMemory: true]))

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

	TEST(@"-[copy]", (RIPEMD160Copy = [[RIPEMD160 copy] autorelease]))

	TEST(@"-[digest]",
	    memcmp(RIPEMD160.digest, testFileRIPEMD160, 20) == 0 &&
	    memcmp(RIPEMD160Copy.digest, testFileRIPEMD160, 20) == 0)

	EXPECT_EXCEPTION(@"Detect invalid call of "
	    @"-[updateWithBuffer:length]", OFHashAlreadyCalculatedException,
	    [RIPEMD160 updateWithBuffer: "" length: 1])

	objc_autoreleasePoolPop(pool);
}
@end

Modified tests/OFSHA1HashTests.m from [3bceacae61] to [4f485b9d65].

15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
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 <string.h>

#import "TestsAppDelegate.h"

static OFString *module = @"OFSHA1Hash";

const uint8_t testfile_sha1[20] =
	"\xC9\x9A\xB8\x7E\x1E\xC8\xEC\x65\xD5\xEB\xE4\x2E\x0D\xA6\x80\x96\xF5"
	"\x94\xE7\x17";

@implementation TestsAppDelegate (SHA1HashTests)
- (void)SHA1HashTests
{
	void *pool = objc_autoreleasePoolPush();
	OFSHA1Hash *sha1, *copy;
	OFFile *f = [OFFile fileWithPath: @"testfile.bin" mode: @"r"];

	TEST(@"+[hashWithAllowsSwappableMemory:]",
	    (sha1 = [OFSHA1Hash hashWithAllowsSwappableMemory: true]))

	while (!f.atEndOfStream) {
		char buf[64];
		size_t len = [f readIntoBuffer: buf length: 64];
		[sha1 updateWithBuffer: buf length: len];
	}
	[f close];

	TEST(@"-[copy]", (copy = [[sha1 copy] autorelease]))

	TEST(@"-[digest]",
	    memcmp(sha1.digest, testfile_sha1, 20) == 0 &&
	    memcmp(copy.digest, testfile_sha1, 20) == 0)

	EXPECT_EXCEPTION(@"Detect invalid call of "
	    @"-[updateWithBuffer:length:]", OFHashAlreadyCalculatedException,
	    [sha1 updateWithBuffer: "" length: 1])

	objc_autoreleasePoolPop(pool);
}
@end







|

|







|
|


|

|
|
|
|

|

|


|
|



|




15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
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 <string.h>

#import "TestsAppDelegate.h"

static OFString *const module = @"OFSHA1Hash";

const uint8_t testFileSHA1[20] =
	"\xC9\x9A\xB8\x7E\x1E\xC8\xEC\x65\xD5\xEB\xE4\x2E\x0D\xA6\x80\x96\xF5"
	"\x94\xE7\x17";

@implementation TestsAppDelegate (SHA1HashTests)
- (void)SHA1HashTests
{
	void *pool = objc_autoreleasePoolPush();
	OFSHA1Hash *SHA1, *SHA1Copy;
	OFFile *file = [OFFile fileWithPath: @"testfile.bin" mode: @"r"];

	TEST(@"+[hashWithAllowsSwappableMemory:]",
	    (SHA1 = [OFSHA1Hash hashWithAllowsSwappableMemory: true]))

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

	TEST(@"-[copy]", (SHA1Copy = [[SHA1 copy] autorelease]))

	TEST(@"-[digest]",
	    memcmp(SHA1.digest, testFileSHA1, 20) == 0 &&
	    memcmp(SHA1Copy.digest, testFileSHA1, 20) == 0)

	EXPECT_EXCEPTION(@"Detect invalid call of "
	    @"-[updateWithBuffer:length:]", OFHashAlreadyCalculatedException,
	    [SHA1 updateWithBuffer: "" length: 1])

	objc_autoreleasePoolPop(pool);
}
@end

Modified tests/OFSHA224HashTests.m from [4309676a79] to [d949087e30].

15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
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 <string.h>

#import "TestsAppDelegate.h"

static OFString *module = @"OFSHA224Hash";

const uint8_t testfile_sha224[28] =
	"\x27\x69\xD8\x04\x2D\x0F\xCA\x84\x6C\xF1\x62\x44\xBA\x0C\xBD\x46\x64"
	"\x5F\x4F\x20\x02\x4D\x15\xED\x1C\x61\x1F\xF7";

@implementation TestsAppDelegate (SHA224HashTests)
- (void)SHA224HashTests
{
	void *pool = objc_autoreleasePoolPush();
	OFSHA224Hash *sha224, *copy;
	OFFile *f = [OFFile fileWithPath: @"testfile.bin" mode: @"r"];

	TEST(@"+[hashWithAllowsSwappableMemory:]",
	    (sha224 = [OFSHA224Hash hashWithAllowsSwappableMemory: true]))

	while (!f.atEndOfStream) {
		char buf[64];
		size_t len = [f readIntoBuffer: buf length: 64];
		[sha224 updateWithBuffer: buf length: len];
	}
	[f close];

	TEST(@"-[copy]", (copy = [[sha224 copy] autorelease]))

	TEST(@"-[digest]",
	    memcmp(sha224.digest, testfile_sha224, 28) == 0 &&
	    memcmp(copy.digest, testfile_sha224, 28) == 0)

	EXPECT_EXCEPTION(@"Detect invalid call of "
	    @"-[updateWithBuffer:length:]", OFHashAlreadyCalculatedException,
	    [sha224 updateWithBuffer: "" length: 1])

	objc_autoreleasePoolPop(pool);
}
@end







|

|







|
|


|

|
|
|
|

|

|


|
|



|




15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
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 <string.h>

#import "TestsAppDelegate.h"

static OFString *const module = @"OFSHA224Hash";

const uint8_t testFileSHA224[28] =
	"\x27\x69\xD8\x04\x2D\x0F\xCA\x84\x6C\xF1\x62\x44\xBA\x0C\xBD\x46\x64"
	"\x5F\x4F\x20\x02\x4D\x15\xED\x1C\x61\x1F\xF7";

@implementation TestsAppDelegate (SHA224HashTests)
- (void)SHA224HashTests
{
	void *pool = objc_autoreleasePoolPush();
	OFSHA224Hash *SHA224, *SHA224Copy;
	OFFile *file = [OFFile fileWithPath: @"testfile.bin" mode: @"r"];

	TEST(@"+[hashWithAllowsSwappableMemory:]",
	    (SHA224 = [OFSHA224Hash hashWithAllowsSwappableMemory: true]))

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

	TEST(@"-[copy]", (SHA224Copy = [[SHA224 copy] autorelease]))

	TEST(@"-[digest]",
	    memcmp(SHA224.digest, testFileSHA224, 28) == 0 &&
	    memcmp(SHA224Copy.digest, testFileSHA224, 28) == 0)

	EXPECT_EXCEPTION(@"Detect invalid call of "
	    @"-[updateWithBuffer:length:]", OFHashAlreadyCalculatedException,
	    [SHA224 updateWithBuffer: "" length: 1])

	objc_autoreleasePoolPop(pool);
}
@end

Modified tests/OFSHA256HashTests.m from [2f9948771c] to [f90460efa2].

15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
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 <string.h>

#import "TestsAppDelegate.h"

static OFString *module = @"OFSHA256Hash";

const uint8_t testfile_sha256[32] =
	"\x1A\x02\xD6\x46\xF5\xA6\xBA\xAA\xFF\x7F\xD5\x87\xBA\xC3\xF6\xC6\xB5"
	"\x67\x93\x8F\x0F\x44\x90\xB8\xF5\x35\x89\xF0\x5A\x23\x7F\x69";

@implementation TestsAppDelegate (SHA256HashTests)
- (void)SHA256HashTests
{
	void *pool = objc_autoreleasePoolPush();
	OFSHA256Hash *sha256, *copy;
	OFFile *f = [OFFile fileWithPath: @"testfile.bin" mode: @"r"];

	TEST(@"+[hashWithAllowsSwappableMemory:]",
	    (sha256 = [OFSHA256Hash hashWithAllowsSwappableMemory: true]))

	while (!f.atEndOfStream) {
		char buf[64];
		size_t len = [f readIntoBuffer: buf length: 64];
		[sha256 updateWithBuffer: buf length: len];
	}
	[f close];

	TEST(@"-[copy]", (copy = [[sha256 copy] autorelease]))

	TEST(@"-[digest]",
	    memcmp(sha256.digest, testfile_sha256, 32) == 0 &&
	    memcmp(copy.digest, testfile_sha256, 32) == 0)

	EXPECT_EXCEPTION(@"Detect invalid call of "
	    @"-[updateWithBuffer:length:]", OFHashAlreadyCalculatedException,
	    [sha256 updateWithBuffer: "" length: 1])

	objc_autoreleasePoolPop(pool);
}
@end







|

|







|
|


|

|
|
|
|

|

|


|
|



|




15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
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 <string.h>

#import "TestsAppDelegate.h"

static OFString *const module = @"OFSHA256Hash";

const uint8_t testFileSHA256[32] =
	"\x1A\x02\xD6\x46\xF5\xA6\xBA\xAA\xFF\x7F\xD5\x87\xBA\xC3\xF6\xC6\xB5"
	"\x67\x93\x8F\x0F\x44\x90\xB8\xF5\x35\x89\xF0\x5A\x23\x7F\x69";

@implementation TestsAppDelegate (SHA256HashTests)
- (void)SHA256HashTests
{
	void *pool = objc_autoreleasePoolPush();
	OFSHA256Hash *SHA256, *SHA256Copy;
	OFFile *file = [OFFile fileWithPath: @"testfile.bin" mode: @"r"];

	TEST(@"+[hashWithAllowsSwappableMemory:]",
	    (SHA256 = [OFSHA256Hash hashWithAllowsSwappableMemory: true]))

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

	TEST(@"-[copy]", (SHA256Copy = [[SHA256 copy] autorelease]))

	TEST(@"-[digest]",
	    memcmp(SHA256.digest, testFileSHA256, 32) == 0 &&
	    memcmp(SHA256Copy.digest, testFileSHA256, 32) == 0)

	EXPECT_EXCEPTION(@"Detect invalid call of "
	    @"-[updateWithBuffer:length:]", OFHashAlreadyCalculatedException,
	    [SHA256 updateWithBuffer: "" length: 1])

	objc_autoreleasePoolPop(pool);
}
@end

Modified tests/OFSHA384HashTests.m from [fdfc8fecb8] to [7fee81f984].

15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
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 <string.h>

#import "TestsAppDelegate.h"

static OFString *module = @"OFSHA384Hash";

const uint8_t testfile_sha384[48] =
	"\x7E\xDE\x62\xE2\x10\xA5\x1E\x18\x8A\x11\x7F\x78\xD7\xC7\x55\xB6\x43"
	"\x94\x1B\xD2\x78\x5C\xCF\xF3\x8A\xB8\x98\x22\xC7\x0E\xFE\xF1\xEC\x53"
	"\xE9\x1A\xB3\x51\x70\x8C\x1F\x3F\x56\x12\x44\x01\x91\x54";

@implementation TestsAppDelegate (SHA384HashTests)
- (void)SHA384HashTests
{
	void *pool = objc_autoreleasePoolPush();
	OFSHA384Hash *sha384, *copy;
	OFFile *f = [OFFile fileWithPath: @"testfile.bin" mode: @"r"];

	TEST(@"+[hashWithAllowsSwappableMemory:]",
	    (sha384 = [OFSHA384Hash hashWithAllowsSwappableMemory: true]))

	while (!f.atEndOfStream) {
		char buf[128];
		size_t len = [f readIntoBuffer: buf length: 128];
		[sha384 updateWithBuffer: buf length: len];
	}
	[f close];

	TEST(@"-[copy]", (copy = [[sha384 copy] autorelease]))

	TEST(@"-[digest]",
	    memcmp(sha384.digest, testfile_sha384, 48) == 0 &&
	    memcmp(copy.digest, testfile_sha384, 48) == 0)

	EXPECT_EXCEPTION(@"Detect invalid call of "
	    @"-[updateWithBuffer:length:]", OFHashAlreadyCalculatedException,
	    [sha384 updateWithBuffer: "" length: 1])

	objc_autoreleasePoolPop(pool);
}
@end







|

|








|
|


|

|
|
|
|

|

|


|
|



|




15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
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 <string.h>

#import "TestsAppDelegate.h"

static OFString *const module = @"OFSHA384Hash";

const uint8_t testFileSHA384[48] =
	"\x7E\xDE\x62\xE2\x10\xA5\x1E\x18\x8A\x11\x7F\x78\xD7\xC7\x55\xB6\x43"
	"\x94\x1B\xD2\x78\x5C\xCF\xF3\x8A\xB8\x98\x22\xC7\x0E\xFE\xF1\xEC\x53"
	"\xE9\x1A\xB3\x51\x70\x8C\x1F\x3F\x56\x12\x44\x01\x91\x54";

@implementation TestsAppDelegate (SHA384HashTests)
- (void)SHA384HashTests
{
	void *pool = objc_autoreleasePoolPush();
	OFSHA384Hash *SHA384, *SHA384Copy;
	OFFile *file = [OFFile fileWithPath: @"testfile.bin" mode: @"r"];

	TEST(@"+[hashWithAllowsSwappableMemory:]",
	    (SHA384 = [OFSHA384Hash hashWithAllowsSwappableMemory: true]))

	while (!file.atEndOfStream) {
		char buffer[128];
		size_t length = [file readIntoBuffer: buffer length: 128];
		[SHA384 updateWithBuffer: buffer length: length];
	}
	[file close];

	TEST(@"-[copy]", (SHA384Copy = [[SHA384 copy] autorelease]))

	TEST(@"-[digest]",
	    memcmp(SHA384.digest, testFileSHA384, 48) == 0 &&
	    memcmp(SHA384Copy.digest, testFileSHA384, 48) == 0)

	EXPECT_EXCEPTION(@"Detect invalid call of "
	    @"-[updateWithBuffer:length:]", OFHashAlreadyCalculatedException,
	    [SHA384 updateWithBuffer: "" length: 1])

	objc_autoreleasePoolPop(pool);
}
@end

Modified tests/OFSHA512HashTests.m from [ff0238e62b] to [b65f0f5008].

15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59

#include "config.h"

#include <string.h>

#import "TestsAppDelegate.h"

static OFString *module = @"OFSHA512Hash";

const uint8_t testfile_sha512[64] =
	"\x8F\x36\x6E\x3C\x19\x4B\xBB\xC7\x82\xAA\xCD\x7D\x55\xA2\xD3\x29\x29"
	"\x97\x6A\x3F\xEB\x9B\xB2\xCB\x75\xC9\xEC\xC8\x10\x07\xD6\x07\x31\x4A"
	"\xB1\x30\x97\x82\x58\xA5\x1F\x71\x42\xE6\x56\x07\x99\x57\xB2\xB8\x3B"
	"\xA1\x8A\x41\x64\x33\x69\x21\x8C\x2A\x44\x6D\xF2\xA0";

@implementation TestsAppDelegate (SHA512HashTests)
- (void)SHA512HashTests
{
	void *pool = objc_autoreleasePoolPush();
	OFSHA512Hash *sha512, *copy;
	OFFile *f = [OFFile fileWithPath: @"testfile.bin" mode: @"r"];

	TEST(@"+[hashWithAllowsSwappableMemory:]",
	    (sha512 = [OFSHA512Hash hashWithAllowsSwappableMemory: true]))

	while (!f.atEndOfStream) {
		char buf[128];
		size_t len = [f readIntoBuffer: buf length: 128];
		[sha512 updateWithBuffer: buf length: len];
	}
	[f close];

	TEST(@"-[copy]", (copy = [[sha512 copy] autorelease]))

	TEST(@"-[digest]",
	    memcmp(sha512.digest, testfile_sha512, 64) == 0 &&
	    memcmp(copy.digest, testfile_sha512, 64) == 0)

	EXPECT_EXCEPTION(@"Detect invalid call of "
	    @"-[updateWithBuffer:length:]", OFHashAlreadyCalculatedException,
	    [sha512 updateWithBuffer: "" length: 1])

	objc_autoreleasePoolPop(pool);
}
@end







|

|









|
|


|

|
|
|
|

|

|


|
|



|




15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59

#include "config.h"

#include <string.h>

#import "TestsAppDelegate.h"

static OFString *const module = @"OFSHA512Hash";

const uint8_t testFileSHA512[64] =
	"\x8F\x36\x6E\x3C\x19\x4B\xBB\xC7\x82\xAA\xCD\x7D\x55\xA2\xD3\x29\x29"
	"\x97\x6A\x3F\xEB\x9B\xB2\xCB\x75\xC9\xEC\xC8\x10\x07\xD6\x07\x31\x4A"
	"\xB1\x30\x97\x82\x58\xA5\x1F\x71\x42\xE6\x56\x07\x99\x57\xB2\xB8\x3B"
	"\xA1\x8A\x41\x64\x33\x69\x21\x8C\x2A\x44\x6D\xF2\xA0";

@implementation TestsAppDelegate (SHA512HashTests)
- (void)SHA512HashTests
{
	void *pool = objc_autoreleasePoolPush();
	OFSHA512Hash *SHA512, *SHA512Copy;
	OFFile *file = [OFFile fileWithPath: @"testfile.bin" mode: @"r"];

	TEST(@"+[hashWithAllowsSwappableMemory:]",
	    (SHA512 = [OFSHA512Hash hashWithAllowsSwappableMemory: true]))

	while (!file.atEndOfStream) {
		char buffer[128];
		size_t length = [file readIntoBuffer: buffer length: 128];
		[SHA512 updateWithBuffer: buffer length: length];
	}
	[file close];

	TEST(@"-[copy]", (SHA512Copy = [[SHA512 copy] autorelease]))

	TEST(@"-[digest]",
	    memcmp(SHA512.digest, testFileSHA512, 64) == 0 &&
	    memcmp(SHA512Copy.digest, testFileSHA512, 64) == 0)

	EXPECT_EXCEPTION(@"Detect invalid call of "
	    @"-[updateWithBuffer:length:]", OFHashAlreadyCalculatedException,
	    [SHA512 updateWithBuffer: "" length: 1])

	objc_autoreleasePoolPop(pool);
}
@end

Modified tests/OFSPXSocketTests.m from [8af68629fd] to [1c45b38ca1].

15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

#include "config.h"

#include <errno.h>

#import "TestsAppDelegate.h"

static OFString *module = @"OFSPXSocket";

@interface SPXSocketDelegate: OFObject <OFSPXSocketDelegate>
{
@public
	OFSequencedPacketSocket *_expectedServerSocket;
	OFSPXSocket *_expectedClientSocket;
	unsigned char _expectedNode[IPX_NODE_LEN];







|







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

#include "config.h"

#include <errno.h>

#import "TestsAppDelegate.h"

static OFString *const module = @"OFSPXSocket";

@interface SPXSocketDelegate: OFObject <OFSPXSocketDelegate>
{
@public
	OFSequencedPacketSocket *_expectedServerSocket;
	OFSPXSocket *_expectedClientSocket;
	unsigned char _expectedNode[IPX_NODE_LEN];

Modified tests/OFSPXStreamSocketTests.m from [e27033149d] to [0326ef9bb8].

15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

#include "config.h"

#include <errno.h>

#import "TestsAppDelegate.h"

static OFString *module = @"OFSPXStreamSocket";

@interface SPXStreamSocketDelegate: OFObject <OFSPXStreamSocketDelegate>
{
@public
	OFStreamSocket *_expectedServerSocket;
	OFSPXStreamSocket *_expectedClientSocket;
	unsigned char _expectedNode[IPX_NODE_LEN];







|







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

#include "config.h"

#include <errno.h>

#import "TestsAppDelegate.h"

static OFString *const module = @"OFSPXStreamSocket";

@interface SPXStreamSocketDelegate: OFObject <OFSPXStreamSocketDelegate>
{
@public
	OFStreamSocket *_expectedServerSocket;
	OFSPXStreamSocket *_expectedClientSocket;
	unsigned char _expectedNode[IPX_NODE_LEN];

Renamed and modified tests/ScryptTests.m [dc5f2613fe] to tests/OFScryptTests.m [728fb073b3].

15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

#include "config.h"

#include <string.h>

#import "TestsAppDelegate.h"

static OFString *module = @"scrypt";
/* Test vectors form RFC 7914 */
static const unsigned char salsa20Input[64] = {
	0x7E, 0x87, 0x9A, 0x21, 0x4F, 0x3E, 0xC9, 0x86, 0x7C, 0xA9, 0x40, 0xE6,
	0x41, 0x71, 0x8F, 0x26, 0xBA, 0xEE, 0x55, 0x5B, 0x8C, 0x61, 0xC1, 0xB5,
	0x0D, 0xF8, 0x46, 0x11, 0x6D, 0xCD, 0x3B, 0x1D, 0xEE, 0x24, 0xF3, 0x19,
	0xDF, 0x9B, 0x3D, 0x85, 0x14, 0x12, 0x1E, 0x4B, 0x5A, 0xC5, 0xAA, 0x32,
	0x76, 0x02, 0x1D, 0x29, 0x09, 0xC7, 0x48, 0x29, 0xED, 0xEB, 0xC6, 0x8D,







|







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

#include "config.h"

#include <string.h>

#import "TestsAppDelegate.h"

static OFString *const module = @"OFScrypt";
/* Test vectors form RFC 7914 */
static const unsigned char salsa20Input[64] = {
	0x7E, 0x87, 0x9A, 0x21, 0x4F, 0x3E, 0xC9, 0x86, 0x7C, 0xA9, 0x40, 0xE6,
	0x41, 0x71, 0x8F, 0x26, 0xBA, 0xEE, 0x55, 0x5B, 0x8C, 0x61, 0xC1, 0xB5,
	0x0D, 0xF8, 0x46, 0x11, 0x6D, 0xCD, 0x3B, 0x1D, 0xEE, 0x24, 0xF3, 0x19,
	0xDF, 0x9B, 0x3D, 0x85, 0x14, 0x12, 0x1E, 0x4B, 0x5A, 0xC5, 0xAA, 0x32,
	0x76, 0x02, 0x1D, 0x29, 0x09, 0xC7, 0x48, 0x29, 0xED, 0xEB, 0xC6, 0x8D,
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
	0xFD, 0xBA, 0xBE, 0x1C, 0x9D, 0x34, 0x72, 0x00, 0x78, 0x56, 0xE7, 0x19,
	0x0D, 0x01, 0xE9, 0xFE, 0x7C, 0x6A, 0xD7, 0xCB, 0xC8, 0x23, 0x78, 0x30,
	0xE7, 0x73, 0x76, 0x63, 0x4B, 0x37, 0x31, 0x62, 0x2E, 0xAF, 0x30, 0xD9,
	0x2E, 0x22, 0xA3, 0x88, 0x6F, 0xF1, 0x09, 0x27, 0x9D, 0x98, 0x30, 0xDA,
	0xC7, 0x27, 0xAF, 0xB9, 0x4A, 0x83, 0xEE, 0x6D, 0x83, 0x60, 0xCB, 0xDF,
	0xA2, 0xCC, 0x06, 0x40
};


static const unsigned char testVector3[64] = {
	0x70, 0x23, 0xBD, 0xCB, 0x3A, 0xFD, 0x73, 0x48, 0x46, 0x1C, 0x06, 0xCD,
	0x81, 0xFD, 0x38, 0xEB, 0xFD, 0xA8, 0xFB, 0xBA, 0x90, 0x4F, 0x8E, 0x3E,
	0xA9, 0xB5, 0x43, 0xF6, 0x54, 0x5D, 0xA1, 0xF2, 0xD5, 0x43, 0x29, 0x55,
	0x61, 0x3F, 0x0F, 0xCF, 0x62, 0xD4, 0x97, 0x05, 0x24, 0x2A, 0x9A, 0xF9,
	0xE6, 0x1E, 0x85, 0xDC, 0x0D, 0x65, 0x1E, 0x40, 0xDF, 0xCF, 0x01, 0x7B,
	0x45, 0x57, 0x58, 0x87
};

/* The forth test vector is too expensive to include it in the tests. */
#if 0
static const unsigned char testVector4[64] = {
	0x21, 0x01, 0xCB, 0x9B, 0x6A, 0x51, 0x1A, 0xAE, 0xAD, 0xDB, 0xBE, 0x09,
	0xCF, 0x70, 0xF8, 0x81, 0xEC, 0x56, 0x8D, 0x57, 0x4A, 0x2F, 0xFD, 0x4D,
	0xAB, 0xE5, 0xEE, 0x98, 0x20, 0xAD, 0xAA, 0x47, 0x8E, 0x56, 0xFD, 0x8F,
	0x4B, 0xA5, 0xD0, 0x9F, 0xFA, 0x1C, 0x6D, 0x92, 0x7C, 0x40, 0xF4, 0xC3,
	0x37, 0x30, 0x40, 0x49, 0xE8, 0xA9, 0x52, 0xFB, 0xCB, 0xF4, 0x5C, 0x6F,
	0xA7, 0x7A, 0x41, 0xA4
};
#endif

@implementation TestsAppDelegate (ScryptTests)
- (void)scryptTests
{
	void *pool = objc_autoreleasePoolPush();
	uint32_t salsa20Buffer[16];
	uint32_t blockMixBuffer[32];
	uint32_t ROMixBuffer[32], ROMixTmp[17 * 32];
	unsigned char output[64];







>
>








>












|







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
	0xFD, 0xBA, 0xBE, 0x1C, 0x9D, 0x34, 0x72, 0x00, 0x78, 0x56, 0xE7, 0x19,
	0x0D, 0x01, 0xE9, 0xFE, 0x7C, 0x6A, 0xD7, 0xCB, 0xC8, 0x23, 0x78, 0x30,
	0xE7, 0x73, 0x76, 0x63, 0x4B, 0x37, 0x31, 0x62, 0x2E, 0xAF, 0x30, 0xD9,
	0x2E, 0x22, 0xA3, 0x88, 0x6F, 0xF1, 0x09, 0x27, 0x9D, 0x98, 0x30, 0xDA,
	0xC7, 0x27, 0xAF, 0xB9, 0x4A, 0x83, 0xEE, 0x6D, 0x83, 0x60, 0xCB, 0xDF,
	0xA2, 0xCC, 0x06, 0x40
};
/* The third test vector is too expensive for m68k Amigas. */
#ifndef OF_AMIGAOS_M68K
static const unsigned char testVector3[64] = {
	0x70, 0x23, 0xBD, 0xCB, 0x3A, 0xFD, 0x73, 0x48, 0x46, 0x1C, 0x06, 0xCD,
	0x81, 0xFD, 0x38, 0xEB, 0xFD, 0xA8, 0xFB, 0xBA, 0x90, 0x4F, 0x8E, 0x3E,
	0xA9, 0xB5, 0x43, 0xF6, 0x54, 0x5D, 0xA1, 0xF2, 0xD5, 0x43, 0x29, 0x55,
	0x61, 0x3F, 0x0F, 0xCF, 0x62, 0xD4, 0x97, 0x05, 0x24, 0x2A, 0x9A, 0xF9,
	0xE6, 0x1E, 0x85, 0xDC, 0x0D, 0x65, 0x1E, 0x40, 0xDF, 0xCF, 0x01, 0x7B,
	0x45, 0x57, 0x58, 0x87
};
#endif
/* The forth test vector is too expensive to include it in the tests. */
#if 0
static const unsigned char testVector4[64] = {
	0x21, 0x01, 0xCB, 0x9B, 0x6A, 0x51, 0x1A, 0xAE, 0xAD, 0xDB, 0xBE, 0x09,
	0xCF, 0x70, 0xF8, 0x81, 0xEC, 0x56, 0x8D, 0x57, 0x4A, 0x2F, 0xFD, 0x4D,
	0xAB, 0xE5, 0xEE, 0x98, 0x20, 0xAD, 0xAA, 0x47, 0x8E, 0x56, 0xFD, 0x8F,
	0x4B, 0xA5, 0xD0, 0x9F, 0xFA, 0x1C, 0x6D, 0x92, 0x7C, 0x40, 0xF4, 0xC3,
	0x37, 0x30, 0x40, 0x49, 0xE8, 0xA9, 0x52, 0xFB, 0xCB, 0xF4, 0x5C, 0x6F,
	0xA7, 0x7A, 0x41, 0xA4
};
#endif

@implementation TestsAppDelegate (OFScryptTests)
- (void)scryptTests
{
	void *pool = objc_autoreleasePoolPush();
	uint32_t salsa20Buffer[16];
	uint32_t blockMixBuffer[32];
	uint32_t ROMixBuffer[32], ROMixTmp[17 * 32];
	unsigned char output[64];
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
		.password              = "password",
		.passwordLength        = 8,
		.key                   = output,
		.keyLength             = 64,
		.allowsSwappableMemory = true
	    })) && memcmp(output, testVector2, 64) == 0)



	TEST(@"scrypt test vector #3",
	    R(OFScrypt((OFScryptParameters){
		.blockSize             = 8,
		.costFactor            = 16384,
		.parallelization       = 1,
		.salt                  = (unsigned char *)"SodiumChloride",
		.saltLength            = 14,
		.password              = "pleaseletmein",
		.passwordLength        = 13,
		.key                   = output,
		.keyLength             = 64,
		.allowsSwappableMemory = true
	    })) && memcmp(output, testVector3, 64) == 0)


	/* The forth test vector is too expensive to include it in the tests. */
#if 0
	TEST(@"scrypt test vector #4",
	    R(OFScrypt((OFScryptParameters){
		.blockSize             = 8,
		.costFactor            = 1048576,







>
>













>







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
		.password              = "password",
		.passwordLength        = 8,
		.key                   = output,
		.keyLength             = 64,
		.allowsSwappableMemory = true
	    })) && memcmp(output, testVector2, 64) == 0)

	/* The third test vector is too expensive for m68k Amigas. */
#ifndef OF_AMIGAOS_M68K
	TEST(@"scrypt test vector #3",
	    R(OFScrypt((OFScryptParameters){
		.blockSize             = 8,
		.costFactor            = 16384,
		.parallelization       = 1,
		.salt                  = (unsigned char *)"SodiumChloride",
		.saltLength            = 14,
		.password              = "pleaseletmein",
		.passwordLength        = 13,
		.key                   = output,
		.keyLength             = 64,
		.allowsSwappableMemory = true
	    })) && memcmp(output, testVector3, 64) == 0)
#endif

	/* The forth test vector is too expensive to include it in the tests. */
#if 0
	TEST(@"scrypt test vector #4",
	    R(OFScrypt((OFScryptParameters){
		.blockSize             = 8,
		.costFactor            = 1048576,

Modified tests/OFSerializationTests.m from [5f6e7408a0] to [1a4c0ebd86].

13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

31
32
33
34
35
36
37
38
39
40
41
42
43
44
45

46
47
48
49
50
51
52
53
54
55




56
57
58
59
60

61
62
63
64
 * file.
 */

#include "config.h"

#import "TestsAppDelegate.h"

static OFString *module = @"OFSerialization";

@implementation TestsAppDelegate (OFSerializationTests)
- (void)serializationTests
{
	void *pool = objc_autoreleasePoolPush();
	OFMutableDictionary *d = [OFMutableDictionary dictionary];
	OFMutableArray *a = [OFMutableArray array];
	OFList *l = [OFList list];
	OFData *data;
	OFString *s;


	[a addObject: @"Qu\"xbar\ntest"];
	[a addObject: [OFNumber numberWithInt: 1234]];
	[a addObject: [OFNumber numberWithDouble: 1234.5678]];
	[a addObject: [OFMutableString stringWithString: @"asd"]];
	[a addObject: [OFDate dateWithTimeIntervalSince1970: 1234.5678]];

	[d setObject: @"Hello" forKey: a];
	[d setObject: @"B\"la" forKey: @"Blub"];

	[l appendObject: @"Hello"];
	[l appendObject: @"Wo\rld!\nHow are you?"];
	[l appendObject: [OFURL URLWithString: @"https://objfw.nil.im/"]];
	[l appendObject:
	    [OFXMLElement elementWithXMLString: @"<x><y/><![CDATA[<]]></x>"]];

	[l appendObject: [OFSet setWithObjects: @"foo", @"foo", @"bar", nil]];
	[l appendObject:
	    [OFCountedSet setWithObjects: @"foo", @"foo", @"bar", nil]];

	[d setObject: @"list" forKey: l];

	data = [OFData dataWithItems: "0123456789:;<ABCDEFGHJIKLMNOPQRSTUVWXYZ"
			       count: 39];
	[d setObject: @"data" forKey: data];





	TEST(@"-[stringBySerializing]",
	    (s = d.stringBySerializing) && [s isEqual:
	    [OFString stringWithContentsOfFile: @"serialization.xml"]])

	TEST(@"-[objectByDeserializing]", [s.objectByDeserializing isEqual: d])


	objc_autoreleasePoolPop(pool);
}
@end







|





|
|
|

|
>

|
|
|
|
|

|
|

|
|
|
|

>
|
|


|



|

>
>
>
>

|


|
>




13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
 * 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: [OFURL URLWithString: @"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 stringWithContentsOfFile: @"serialization.xml"]])

	TEST(@"-[objectByDeserializing]",
	    [string.objectByDeserializing isEqual: dict])

	objc_autoreleasePoolPop(pool);
}
@end

Modified tests/OFSetTests.m from [04cbdfa860] to [d85d2c2bce].

17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

#import "TestsAppDelegate.h"

#import "OFSet.h"
#import "OFMapTableSet.h"
#import "OFMutableMapTableSet.h"

static OFString *module = nil;

@interface SimpleSet: OFSet
{
	OFMutableSet *_set;
}
@end








|







17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

#import "TestsAppDelegate.h"

#import "OFSet.h"
#import "OFMapTableSet.h"
#import "OFMutableMapTableSet.h"

static OFString *module;

@interface SimpleSet: OFSet
{
	OFMutableSet *_set;
}
@end

Renamed and modified tests/SocketTests.m [da7b4aa12b] to tests/OFSocketTests.m [bd6253505c].

48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
	a.sockaddr.in6.sin6_addr.s6_addr[10] = a5 >> 8;		\
	a.sockaddr.in6.sin6_addr.s6_addr[11] = a5 & 0xFF;	\
	a.sockaddr.in6.sin6_addr.s6_addr[12] = a6 >> 8;		\
	a.sockaddr.in6.sin6_addr.s6_addr[13] = a6 & 0xFF;	\
	a.sockaddr.in6.sin6_addr.s6_addr[14] = a7 >> 8;		\
	a.sockaddr.in6.sin6_addr.s6_addr[15] = a7 & 0xFF;

static OFString *module = @"Socket";

@implementation TestsAppDelegate (SocketTests)
- (void)socketTests
{
	void *pool = objc_autoreleasePoolPush();
	OFSocketAddress addr;

	TEST(@"Parsing an IPv4",
	    R(addr = OFSocketAddressParseIP(@"127.0.0.1", 1234)) &&







|

|







48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
	a.sockaddr.in6.sin6_addr.s6_addr[10] = a5 >> 8;		\
	a.sockaddr.in6.sin6_addr.s6_addr[11] = a5 & 0xFF;	\
	a.sockaddr.in6.sin6_addr.s6_addr[12] = a6 >> 8;		\
	a.sockaddr.in6.sin6_addr.s6_addr[13] = a6 & 0xFF;	\
	a.sockaddr.in6.sin6_addr.s6_addr[14] = a7 >> 8;		\
	a.sockaddr.in6.sin6_addr.s6_addr[15] = a7 & 0xFF;

static OFString *const module = @"OFSocket";

@implementation TestsAppDelegate (OFSocketTests)
- (void)socketTests
{
	void *pool = objc_autoreleasePoolPush();
	OFSocketAddress addr;

	TEST(@"Parsing an IPv4",
	    R(addr = OFSocketAddressParseIP(@"127.0.0.1", 1234)) &&

Modified tests/OFStreamTests.m from [ad2f2ab750] to [641e91bbf2].

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

#include "config.h"

#import "TestsAppDelegate.h"

static OFString *module = @"OFStream";

@interface StreamTester: OFStream
{
	int state;
}
@end

@implementation StreamTester
- (bool)lowlevelIsAtEndOfStream
{
	return (state > 1);
}

- (size_t)lowlevelReadIntoBuffer: (void *)buffer length: (size_t)size
{







|

|





|







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

#include "config.h"

#import "TestsAppDelegate.h"

static OFString *const module = @"OFStream";

@interface StreamTest: OFStream
{
	int state;
}
@end

@implementation StreamTest
- (bool)lowlevelIsAtEndOfStream
{
	return (state > 1);
}

- (size_t)lowlevelReadIntoBuffer: (void *)buffer length: (size_t)size
{
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74



75
76
77
78
79
80
81
82
83
@end

@implementation TestsAppDelegate (OFStreamTests)
- (void)streamTests
{
	void *pool = objc_autoreleasePoolPush();
	size_t pageSize = [OFSystemInfo pageSize];
	StreamTester *t = [[[StreamTester alloc] init] autorelease];
	OFString *str;
	char *cstr;

	cstr = OFAllocMemory(pageSize - 2, 1);
	memset(cstr, 'X', pageSize - 3);
	cstr[pageSize - 3] = '\0';




	TEST(@"-[readLine]", [[t readLine] isEqual: @"foo"] &&
	    [(str = [t readLine]) length] == pageSize - 3 &&
	    !strcmp(str.UTF8String, cstr))

	OFFreeMemory(cstr);

	objc_autoreleasePoolPop(pool);
}
@end







|
|
|

|
|
|

>
>
>
|
|
|

|




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

@implementation TestsAppDelegate (OFStreamTests)
- (void)streamTests
{
	void *pool = objc_autoreleasePoolPush();
	size_t pageSize = [OFSystemInfo pageSize];
	StreamTest *test = [[[StreamTest alloc] init] autorelease];
	OFString *string;
	char *cString;

	cString = OFAllocMemory(pageSize - 2, 1);
	memset(cString, 'X', pageSize - 3);
	cString[pageSize - 3] = '\0';

	TEST(@"-[readLine] #1", [[test readLine] isEqual: @"foo"])

	string = [test readLine];
	TEST(@"-[readLine] #2", string != nil &&
	    string.length == pageSize - 3 &&
	    !strcmp(string.UTF8String, cString))

	OFFreeMemory(cString);

	objc_autoreleasePoolPop(pool);
}
@end

Modified tests/OFStringTests.m from [40fec06275] to [33be156318].

25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#import "OFMutableUTF8String.h"
#import "OFUTF8String.h"

#ifndef INFINITY
# define INFINITY __builtin_inf()
#endif

static OFString *module = nil;
static OFString *whitespace[] = {
	@" \r \t\n\t \tasd  \t \t\t\r\n",
	@" \t\t  \t\t  \t \t"
};
static OFUnichar ucstr[] = {
	0xFEFF, 'f', 0xF6, 0xF6, 'b', 0xE4, 'r', 0x1F03A, 0
};
static OFUnichar sucstr[] = {
	0xFFFE0000, 0x66000000, 0xF6000000, 0xF6000000, 0x62000000, 0xE4000000,
	0x72000000, 0x3AF00100, 0
};
static uint16_t utf16str[] = {
	0xFEFF, 'f', 0xF6, 0xF6, 'b', 0xE4, 'r', 0xD83C, 0xDC3A, 0
};
static uint16_t sutf16str[] = {
	0xFFFE, 0x6600, 0xF600, 0xF600, 0x6200, 0xE400, 0x7200, 0x3CD8, 0x3ADC,
	0
};

@interface SimpleString: OFString
{
	OFMutableString *_string;







|
|



|


|



|


|







25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#import "OFMutableUTF8String.h"
#import "OFUTF8String.h"

#ifndef INFINITY
# define INFINITY __builtin_inf()
#endif

static OFString *module;
static OFString *const whitespace[] = {
	@" \r \t\n\t \tasd  \t \t\t\r\n",
	@" \t\t  \t\t  \t \t"
};
static const OFUnichar unicharString[] = {
	0xFEFF, 'f', 0xF6, 0xF6, 'b', 0xE4, 'r', 0x1F03A, 0
};
static const OFUnichar swappedUnicharString[] = {
	0xFFFE0000, 0x66000000, 0xF6000000, 0xF6000000, 0x62000000, 0xE4000000,
	0x72000000, 0x3AF00100, 0
};
static const OFChar16 char16String[] = {
	0xFEFF, 'f', 0xF6, 0xF6, 'b', 0xE4, 'r', 0xD83C, 0xDC3A, 0
};
static const OFChar16 swappedChar16String[] = {
	0xFFFE, 0x6600, 0xF600, 0xF600, 0x6200, 0xE400, 0x7200, 0x3CD8, 0x3ADC,
	0
};

@interface SimpleString: OFString
{
	OFMutableString *_string;
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
@end

@implementation TestsAppDelegate (OFStringTests)
- (void)stringTestsWithClass: (Class)stringClass
		mutableClass: (Class)mutableStringClass
{
	void *pool = objc_autoreleasePoolPush();
	OFMutableString *s[3];
	OFString *is;
	OFArray *a;
	size_t i;
	const OFUnichar *ua;
	const uint16_t *u16a;
	OFCharacterSet *cs;
	EntityHandler *h;
#ifdef OF_HAVE_BLOCKS
	__block int j;
	__block bool ok;
#endif

#define C(s) ((OFString *)[stringClass stringWithString: s])

	s[0] = [mutableStringClass stringWithString: @"täs€"];
	s[1] = [mutableStringClass string];
	s[2] = [[s[0] copy] autorelease];

	TEST(@"-[isEqual:]", [s[0] isEqual: s[2]] &&
	    ![s[0] isEqual: [[[OFObject alloc] init] autorelease]])

	TEST(@"-[compare:]", [s[0] compare: s[2]] == OFOrderedSame &&

	    [s[0] compare: @""] != OFOrderedSame &&
	    [C(@"") compare: @"a"] == OFOrderedAscending &&
	    [C(@"a") compare: @"b"] == OFOrderedAscending &&
	    [C(@"cd") compare: @"bc"] == OFOrderedDescending &&
	    [C(@"ä") compare: @"ö"] == OFOrderedAscending &&
	    [C(@"€") compare: @"ß"] == OFOrderedDescending &&
	    [C(@"aa") compare: @"z"] == OFOrderedAscending)








|
|
|

|
|
|
|







|
|
|

|
|

|
>
|







209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
@end

@implementation TestsAppDelegate (OFStringTests)
- (void)stringTestsWithClass: (Class)stringClass
		mutableClass: (Class)mutableStringClass
{
	void *pool = objc_autoreleasePoolPush();
	OFMutableString *mutableString1, *mutableString2, *mutableString3;
	OFString *string;
	OFArray *array;
	size_t i;
	const OFUnichar *characters;
	const uint16_t *UTF16Characters;
	OFCharacterSet *characterSet;
	EntityHandler *entityHandler;
#ifdef OF_HAVE_BLOCKS
	__block int j;
	__block bool ok;
#endif

#define C(s) ((OFString *)[stringClass stringWithString: s])

	mutableString1 = [mutableStringClass stringWithString: @"täs€"];
	mutableString2 = [mutableStringClass string];
	mutableString3 = [[mutableString1 copy] autorelease];

	TEST(@"-[isEqual:]", [mutableString1 isEqual: mutableString3] &&
	    ![mutableString1 isEqual: [[[OFObject alloc] init] autorelease]])

	TEST(@"-[compare:]",
	    [mutableString1 compare: mutableString3] == OFOrderedSame &&
	    [mutableString1 compare: @""] != OFOrderedSame &&
	    [C(@"") compare: @"a"] == OFOrderedAscending &&
	    [C(@"a") compare: @"b"] == OFOrderedAscending &&
	    [C(@"cd") compare: @"bc"] == OFOrderedDescending &&
	    [C(@"ä") compare: @"ö"] == OFOrderedAscending &&
	    [C(@"€") compare: @"ß"] == OFOrderedDescending &&
	    [C(@"aa") compare: @"z"] == OFOrderedAscending)

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
	    [C(@"AA") caseInsensitiveCompare: @"z"] == OFOrderedAscending &&
	    [[stringClass stringWithUTF8String: "ABC"] caseInsensitiveCompare:
	    [stringClass stringWithUTF8String: "AbD"]] ==
	    [C(@"abc") compare: @"abd"])
#endif

	TEST(@"-[hash] is the same if -[isEqual:] is true",
	    s[0].hash == s[2].hash)

	TEST(@"-[description]", [s[0].description isEqual: s[0]])


	TEST(@"-[appendString:] and -[appendUTF8String:]",
	    R([s[1] appendUTF8String: "1𝄞"]) && R([s[1] appendString: @"3"]) &&


	    R([s[0] appendString: s[1]]) && [s[0] isEqual: @"täs€1𝄞3"])

	TEST(@"-[appendCharacters:length:]",
	    R([s[1] appendCharacters: ucstr + 6 length: 2]) &&
	   [s[1] isEqual: @"1𝄞3r🀺"])

	TEST(@"-[length]", s[0].length == 7)
	TEST(@"-[UTF8StringLength]", s[0].UTF8StringLength == 13)
	TEST(@"-[hash]", s[0].hash == 0x705583C0)

	TEST(@"-[characterAtIndex:]",
	    [s[0] characterAtIndex: 0] == 't' &&
	    [s[0] characterAtIndex: 1] == 0xE4 &&
	    [s[0] characterAtIndex: 3] == 0x20AC &&
	    [s[0] characterAtIndex: 5] == 0x1D11E)

	EXPECT_EXCEPTION(@"Detect out of range in -[characterAtIndex:]",
	    OFOutOfRangeException, [s[0] characterAtIndex: 7])

	TEST(@"-[reverse]", R([s[0] reverse]) && [s[0] isEqual: @"3𝄞1€sät"])


	s[1] = [mutableStringClass stringWithString: @"abc"];

#ifdef OF_HAVE_UNICODE_TABLES
	TEST(@"-[uppercase]", R([s[0] uppercase]) &&
	    [s[0] isEqual: @"3𝄞1€SÄT"] &&
	    R([s[1] uppercase]) && [s[1] isEqual: @"ABC"])

	TEST(@"-[lowercase]", R([s[0] lowercase]) &&
	    [s[0] isEqual: @"3𝄞1€sät"] &&
	    R([s[1] lowercase]) && [s[1] isEqual: @"abc"])

	TEST(@"-[uppercaseString]",
	    [[s[0] uppercaseString] isEqual: @"3𝄞1€SÄT"])

	TEST(@"-[lowercaseString]", R([s[0] uppercase]) &&
	    [[s[0] lowercaseString] isEqual: @"3𝄞1€sät"])

	TEST(@"-[capitalizedString]", [C(@"džbla tdžst TDŽST").capitalizedString
	    isEqual: @"Džbla Tdžst Tdžst"])
#else
	TEST(@"-[uppercase]", R([s[0] uppercase]) &&
	    [s[0] isEqual: @"3𝄞1€SäT"] &&
	    R([s[1] uppercase]) && [s[1] isEqual: @"ABC"])

	TEST(@"-[lowercase]", R([s[0] lowercase]) &&
	    [s[0] isEqual: @"3𝄞1€sät"] &&
	    R([s[1] lowercase]) && [s[1] isEqual: @"abc"])

	TEST(@"-[uppercaseString]", [s[0].uppercaseString isEqual: @"3𝄞1€SäT"])


	TEST(@"-[lowercaseString]", R([s[0] uppercase]) &&

	    [s[0].lowercaseString isEqual: @"3𝄞1€sät"])

	TEST(@"-[capitalizedString]", [C(@"džbla tdžst TDŽST").capitalizedString
	    isEqual: @"džbla Tdžst TDŽst"])
#endif

	TEST(@"+[stringWithUTF8String:length:]",
	    (s[0] = [mutableStringClass stringWithUTF8String: "\xEF\xBB\xBF"
							      "foobar"
						      length: 6]) &&
	    [s[0] isEqual: @"foo"])

	TEST(@"+[stringWithUTF16String:]",
	    (is = [stringClass stringWithUTF16String: utf16str]) &&
	    [is isEqual: @"fööbär🀺"] &&
	    (is = [stringClass stringWithUTF16String: sutf16str]) &&
	    [is isEqual: @"fööbär🀺"])

	TEST(@"+[stringWithUTF32String:]",
	    (is = [stringClass stringWithUTF32String: ucstr]) &&
	    [is isEqual: @"fööbär🀺"] &&
	    (is = [stringClass stringWithUTF32String: sucstr]) &&
	    [is isEqual: @"fööbär🀺"])

#ifdef OF_HAVE_FILES
	TEST(@"+[stringWithContentsOfFile:encoding]", (is = [stringClass
	    stringWithContentsOfFile: @"testfile.txt"
			    encoding: OFStringEncodingISO8859_1]) &&
	    [is isEqual: @"testäöü"])

	TEST(@"+[stringWithContentsOfURL:encoding]", (is = [stringClass
	    stringWithContentsOfURL: [OFURL fileURLWithPath: @"testfile.txt"]
			   encoding: OFStringEncodingISO8859_1]) &&
	    [is isEqual: @"testäöü"])
#endif

	TEST(@"-[appendUTFString:length:]",
	    R([s[0] appendUTF8String: "\xEF\xBB\xBF" "barqux" length: 6]) &&

	    [s[0] isEqual: @"foobar"])

	EXPECT_EXCEPTION(@"Detection of invalid UTF-8 encoding #1",
	    OFInvalidEncodingException,
	    [stringClass stringWithUTF8String: "\xE0\x80"])
	EXPECT_EXCEPTION(@"Detection of invalid UTF-8 encoding #2",
	    OFInvalidEncodingException,
	    [stringClass stringWithUTF8String: "\xF0\x80\x80\xC0"])







|

|
>


|
>
>
|


|
|

|
|
|


|
|
|
|


|

|
>

|


|
|
|

|
|
|


|

|
|




|
|
|

|
|
|

|
>

|
>
|






|
|
|
|


|
|
|
|


|
|
|
|


|


|

|


|



|
>
|







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
	    [C(@"AA") caseInsensitiveCompare: @"z"] == OFOrderedAscending &&
	    [[stringClass stringWithUTF8String: "ABC"] caseInsensitiveCompare:
	    [stringClass stringWithUTF8String: "AbD"]] ==
	    [C(@"abc") compare: @"abd"])
#endif

	TEST(@"-[hash] is the same if -[isEqual:] is true",
	    mutableString1.hash == mutableString3.hash)

	TEST(@"-[description]",
	    [mutableString1.description isEqual: mutableString1])

	TEST(@"-[appendString:] and -[appendUTF8String:]",
	    R([mutableString2 appendUTF8String: "1𝄞"]) &&
	    R([mutableString2 appendString: @"3"]) &&
	    R([mutableString1 appendString: mutableString2]) &&
	    [mutableString1 isEqual: @"täs€1𝄞3"])

	TEST(@"-[appendCharacters:length:]",
	    R([mutableString2 appendCharacters: unicharString + 6 length: 2]) &&
	    [mutableString2 isEqual: @"1𝄞3r🀺"])

	TEST(@"-[length]", mutableString1.length == 7)
	TEST(@"-[UTF8StringLength]", mutableString1.UTF8StringLength == 13)
	TEST(@"-[hash]", mutableString1.hash == 0x705583C0)

	TEST(@"-[characterAtIndex:]",
	    [mutableString1 characterAtIndex: 0] == 't' &&
	    [mutableString1 characterAtIndex: 1] == 0xE4 &&
	    [mutableString1 characterAtIndex: 3] == 0x20AC &&
	    [mutableString1 characterAtIndex: 5] == 0x1D11E)

	EXPECT_EXCEPTION(@"Detect out of range in -[characterAtIndex:]",
	    OFOutOfRangeException, [mutableString1 characterAtIndex: 7])

	TEST(@"-[reverse]",
	    R([mutableString1 reverse]) && [mutableString1 isEqual: @"3𝄞1€sät"])

	mutableString2 = [mutableStringClass stringWithString: @"abc"];

#ifdef OF_HAVE_UNICODE_TABLES
	TEST(@"-[uppercase]", R([mutableString1 uppercase]) &&
	    [mutableString1 isEqual: @"3𝄞1€SÄT"] &&
	    R([mutableString2 uppercase]) && [mutableString2 isEqual: @"ABC"])

	TEST(@"-[lowercase]", R([mutableString1 lowercase]) &&
	    [mutableString1 isEqual: @"3𝄞1€sät"] &&
	    R([mutableString2 lowercase]) && [mutableString2 isEqual: @"abc"])

	TEST(@"-[uppercaseString]",
	    [[mutableString1 uppercaseString] isEqual: @"3𝄞1€SÄT"])

	TEST(@"-[lowercaseString]", R([mutableString1 uppercase]) &&
	    [[mutableString1 lowercaseString] isEqual: @"3𝄞1€sät"])

	TEST(@"-[capitalizedString]", [C(@"džbla tdžst TDŽST").capitalizedString
	    isEqual: @"Džbla Tdžst Tdžst"])
#else
	TEST(@"-[uppercase]", R([mutableString1 uppercase]) &&
	    [mutableString1 isEqual: @"3𝄞1€SäT"] &&
	    R([mutableString2 uppercase]) && [mutableString2 isEqual: @"ABC"])

	TEST(@"-[lowercase]", R([mutableString1 lowercase]) &&
	    [mutableString1 isEqual: @"3𝄞1€sät"] &&
	    R([mutableString2 lowercase]) && [mutableString2 isEqual: @"abc"])

	TEST(@"-[uppercaseString]",
	    [mutableString1.uppercaseString isEqual: @"3𝄞1€SäT"])

	TEST(@"-[lowercaseString]",
	    R([mutableString1 uppercase]) &&
	    [mutableString1.lowercaseString isEqual: @"3𝄞1€sät"])

	TEST(@"-[capitalizedString]", [C(@"džbla tdžst TDŽST").capitalizedString
	    isEqual: @"džbla Tdžst TDŽst"])
#endif

	TEST(@"+[stringWithUTF8String:length:]",
	    (mutableString1 = [mutableStringClass
	    stringWithUTF8String: "\xEF\xBB\xBF" "foobar"
			  length: 6]) &&
	    [mutableString1 isEqual: @"foo"])

	TEST(@"+[stringWithUTF16String:]",
	    (string = [stringClass stringWithUTF16String: char16String]) &&
	    [string isEqual: @"fööbär🀺"] &&
	    (string = [stringClass stringWithUTF16String:
	    swappedChar16String]) && [string isEqual: @"fööbär🀺"])

	TEST(@"+[stringWithUTF32String:]",
	    (string = [stringClass stringWithUTF32String: unicharString]) &&
	    [string isEqual: @"fööbär🀺"] &&
	    (string = [stringClass stringWithUTF32String:
	    swappedUnicharString]) && [string isEqual: @"fööbär🀺"])

#ifdef OF_HAVE_FILES
	TEST(@"+[stringWithContentsOfFile:encoding]", (string = [stringClass
	    stringWithContentsOfFile: @"testfile.txt"
			    encoding: OFStringEncodingISO8859_1]) &&
	    [string isEqual: @"testäöü"])

	TEST(@"+[stringWithContentsOfURL:encoding]", (string = [stringClass
	    stringWithContentsOfURL: [OFURL fileURLWithPath: @"testfile.txt"]
			   encoding: OFStringEncodingISO8859_1]) &&
	    [string isEqual: @"testäöü"])
#endif

	TEST(@"-[appendUTFString:length:]",
	    R([mutableString1 appendUTF8String: "\xEF\xBB\xBF" "barqux"
					length: 6]) &&
	    [mutableString1 isEqual: @"foobar"])

	EXPECT_EXCEPTION(@"Detection of invalid UTF-8 encoding #1",
	    OFInvalidEncodingException,
	    [stringClass stringWithUTF8String: "\xE0\x80"])
	EXPECT_EXCEPTION(@"Detection of invalid UTF-8 encoding #2",
	    OFInvalidEncodingException,
	    [stringClass stringWithUTF8String: "\xF0\x80\x80\xC0"])
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
#ifdef HAVE_CODEPAGE_437
	TEST(@"Lossy conversion of Unicode to Codepage 437",
	    !strcmp([C(@"T€st strîng ░▒▓") lossyCStringWithEncoding:
	    OFStringEncodingCodepage437], "T?st str\x8Cng \xB0\xB1\xB2"))
#endif

	TEST(@"+[stringWithFormat:]",
	    [(s[0] = [mutableStringClass stringWithFormat: @"%@:%d", @"test",

							   123])
	    isEqual: @"test:123"])

	TEST(@"-[appendFormat:]",
	    R(([s[0] appendFormat: @"%02X", 15])) &&
	    [s[0] isEqual: @"test:1230F"])

	TEST(@"-[rangeOfString:]",
	    [C(@"𝄞öö") rangeOfString: @"öö"].location == 1 &&
	    [C(@"𝄞öö") rangeOfString: @"ö"].location == 1 &&
	    [C(@"𝄞öö") rangeOfString: @"𝄞"].location == 0 &&
	    [C(@"𝄞öö") rangeOfString: @"x"].location == OFNotFound &&
	    [C(@"𝄞öö") rangeOfString: @"öö"
	    options: OFStringSearchBackwards].location == 1 &&
	    [C(@"𝄞öö") rangeOfString: @"ö"
	    options: OFStringSearchBackwards].location == 2 &&
	    [C(@"𝄞öö") rangeOfString: @"𝄞"
	    options: OFStringSearchBackwards].location == 0 &&
	    [C(@"𝄞öö") rangeOfString: @"x"
	    options: OFStringSearchBackwards].location == OFNotFound)

	EXPECT_EXCEPTION(
	    @"Detect out of range in -[rangeOfString:options:range:]",
	    OFOutOfRangeException,
	    [C(@"𝄞öö") rangeOfString: @"ö" options: 0 range: OFRangeMake(3, 1)])


	cs = [OFCharacterSet characterSetWithCharactersInString: @"cđ"];
	TEST(@"-[indexOfCharacterFromSet:]",
	     [C(@"abcđabcđe") indexOfCharacterFromSet: cs] == 2 &&
	     [C(@"abcđabcđë")
	     indexOfCharacterFromSet: cs
			     options: OFStringSearchBackwards] == 7 &&
	     [C(@"abcđabcđë")
	     indexOfCharacterFromSet: cs
			     options: 0
			       range: OFRangeMake(4, 4)] == 6 &&
	     [C(@"abcđabcđëf")
	     indexOfCharacterFromSet: cs
			     options: 0
			       range: OFRangeMake(8, 2)] == OFNotFound)

	EXPECT_EXCEPTION(
	    @"Detect out of range in -[indexOfCharacterFromSet:options:range:]",
	    OFOutOfRangeException,
	    [C(@"𝄞öö") indexOfCharacterFromSet: cs
				       options: 0
					 range: OFRangeMake(3, 1)])

	TEST(@"-[substringWithRange:]",
	    [[C(@"𝄞öö") substringWithRange: OFRangeMake(1, 1)] isEqual: @"ö"] &&
	    [[C(@"𝄞öö") substringWithRange: OFRangeMake(3, 0)] isEqual: @""])








|
>
|



|
|




















>
|

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




|







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
#ifdef HAVE_CODEPAGE_437
	TEST(@"Lossy conversion of Unicode to Codepage 437",
	    !strcmp([C(@"T€st strîng ░▒▓") lossyCStringWithEncoding:
	    OFStringEncodingCodepage437], "T?st str\x8Cng \xB0\xB1\xB2"))
#endif

	TEST(@"+[stringWithFormat:]",
	    [(mutableString1 = [mutableStringClass stringWithFormat: @"%@:%d",
								     @"test",
								     123])
	    isEqual: @"test:123"])

	TEST(@"-[appendFormat:]",
	    R(([mutableString1 appendFormat: @"%02X", 15])) &&
	    [mutableString1 isEqual: @"test:1230F"])

	TEST(@"-[rangeOfString:]",
	    [C(@"𝄞öö") rangeOfString: @"öö"].location == 1 &&
	    [C(@"𝄞öö") rangeOfString: @"ö"].location == 1 &&
	    [C(@"𝄞öö") rangeOfString: @"𝄞"].location == 0 &&
	    [C(@"𝄞öö") rangeOfString: @"x"].location == OFNotFound &&
	    [C(@"𝄞öö") rangeOfString: @"öö"
	    options: OFStringSearchBackwards].location == 1 &&
	    [C(@"𝄞öö") rangeOfString: @"ö"
	    options: OFStringSearchBackwards].location == 2 &&
	    [C(@"𝄞öö") rangeOfString: @"𝄞"
	    options: OFStringSearchBackwards].location == 0 &&
	    [C(@"𝄞öö") rangeOfString: @"x"
	    options: OFStringSearchBackwards].location == OFNotFound)

	EXPECT_EXCEPTION(
	    @"Detect out of range in -[rangeOfString:options:range:]",
	    OFOutOfRangeException,
	    [C(@"𝄞öö") rangeOfString: @"ö" options: 0 range: OFRangeMake(3, 1)])

	characterSet =
	    [OFCharacterSet characterSetWithCharactersInString: @"cđ"];
	TEST(@"-[indexOfCharacterFromSet:]",
	    [C(@"abcđabcđe") indexOfCharacterFromSet: characterSet] == 2 &&
	    [C(@"abcđabcđë")
	    indexOfCharacterFromSet: characterSet
			    options: OFStringSearchBackwards] == 7 &&
	    [C(@"abcđabcđë") indexOfCharacterFromSet: characterSet

					     options: 0
					       range: OFRangeMake(4, 4)] == 6 &&
	    [C(@"abcđabcđëf")
	    indexOfCharacterFromSet: characterSet
			    options: 0
			      range: OFRangeMake(8, 2)] == OFNotFound)

	EXPECT_EXCEPTION(
	    @"Detect out of range in -[indexOfCharacterFromSet:options:range:]",
	    OFOutOfRangeException,
	    [C(@"𝄞öö") indexOfCharacterFromSet: characterSet
				       options: 0
					 range: OFRangeMake(3, 1)])

	TEST(@"-[substringWithRange:]",
	    [[C(@"𝄞öö") substringWithRange: OFRangeMake(1, 1)] isEqual: @"ö"] &&
	    [[C(@"𝄞öö") substringWithRange: OFRangeMake(3, 0)] isEqual: @""])

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
	    !C(@"foo/bar").absolutePath && !C(@"foo").absolutePath)
# else
	TEST(@"-[isAbsolutePath]",
	    C(@"/foo").absolutePath && C(@"/foo/bar").absolutePath &&
	    !C(@"foo/bar").absolutePath && !C(@"foo").absolutePath)
# endif

	s[0] = [mutableStringClass stringWithString: @"foo"];
# if defined(OF_WINDOWS) || defined(OF_MSDOS)
	[s[0] appendString: @"\\"];
# else
	[s[0] appendString: @"/"];
# endif
	[s[0] appendString: @"bar"];
	s[1] = [mutableStringClass stringWithString: s[0]];
# if defined(OF_WINDOWS) || defined(OF_MSDOS)
	[s[1] appendString: @"\\"];
# else
	[s[1] appendString: @"/"];
# endif
	is = [stringClass stringWithString: s[1]];
	[s[1] appendString: @"baz"];
	TEST(@"-[stringByAppendingPathComponent:]",
	    [[s[0] stringByAppendingPathComponent: @"baz"] isEqual: s[1]] &&

	    [[is stringByAppendingPathComponent: @"baz"] isEqual: s[1]])

#endif

	TEST(@"-[hasPrefix:]", [C(@"foobar") hasPrefix: @"foo"] &&
	    ![C(@"foobar") hasPrefix: @"foobar0"])

	TEST(@"-[hasSuffix:]", [C(@"foobar") hasSuffix: @"bar"] &&
	    ![C(@"foobar") hasSuffix: @"foobar0"])

	i = 0;
	TEST(@"-[componentsSeparatedByString:]",
	    (a = [C(@"fooXXbarXXXXbazXXXX")
	    componentsSeparatedByString: @"XX"]) &&
	    [[a objectAtIndex: i++] isEqual: @"foo"] &&
	    [[a objectAtIndex: i++] isEqual: @"bar"] &&
	    [[a objectAtIndex: i++] isEqual: @""] &&
	    [[a objectAtIndex: i++] isEqual: @"baz"] &&
	    [[a objectAtIndex: i++] isEqual: @""] &&
	    [[a objectAtIndex: i++] isEqual: @""] &&
	    a.count == i &&
	    (a = [C(@"foo") componentsSeparatedByString: @""]) &&
	    [[a objectAtIndex: 0] isEqual: @"foo"] &&
	    a.count == 1)

	i = 0;
	TEST(@"-[componentsSeparatedByString:options:]",
	    (a = [C(@"fooXXbarXXXXbazXXXX")
	    componentsSeparatedByString: @"XX"
				options: OFStringSkipEmptyComponents]) &&
	    [[a objectAtIndex: i++] isEqual: @"foo"] &&
	    [[a objectAtIndex: i++] isEqual: @"bar"] &&
	    [[a objectAtIndex: i++] isEqual: @"baz"] &&
	    a.count == i)


	cs = [OFCharacterSet characterSetWithCharactersInString: @"XYZ"];

	i = 0;
	TEST(@"-[componentsSeparatedByCharactersInSet:]",
	    (a = [C(@"fooXYbarXYZXbazXYXZx")
	    componentsSeparatedByCharactersInSet: cs]) &&
	    [[a objectAtIndex: i++] isEqual: @"foo"] &&
	    [[a objectAtIndex: i++] isEqual: @""] &&
	    [[a objectAtIndex: i++] isEqual: @"bar"] &&
	    [[a objectAtIndex: i++] isEqual: @""] &&
	    [[a objectAtIndex: i++] isEqual: @""] &&
	    [[a objectAtIndex: i++] isEqual: @""] &&
	    [[a objectAtIndex: i++] isEqual: @"baz"] &&
	    [[a objectAtIndex: i++] isEqual: @""] &&
	    [[a objectAtIndex: i++] isEqual: @""] &&
	    [[a objectAtIndex: i++] isEqual: @""] &&
	    [[a objectAtIndex: i++] isEqual: @"x"] &&
	    a.count == i)

	i = 0;
	TEST(@"-[componentsSeparatedByCharactersInSet:options:]",
	    (a = [C(@"fooXYbarXYZXbazXYXZ")
	    componentsSeparatedByCharactersInSet: cs
	    options: OFStringSkipEmptyComponents]) &&
	    [[a objectAtIndex: i++] isEqual: @"foo"] &&
	    [[a objectAtIndex: i++] isEqual: @"bar"] &&
	    [[a objectAtIndex: i++] isEqual: @"baz"] &&
	    a.count == i)

#ifdef OF_HAVE_FILES
# if defined(OF_WINDOWS)
	TEST(@"+[pathWithComponents:]",
	    [[stringClass pathWithComponents: [OFArray arrayWithObjects:
	    @"foo", @"bar", @"baz", nil]] isEqual: @"foo\\bar\\baz"] &&
	    [[stringClass pathWithComponents: [OFArray arrayWithObjects:







|

|

|

|
|

|

|

|
|

|
>
|
>










|

|
|
|
|
|
|
|
|
|
|



|


|
|
|
|

>
|



|
|
|
|
|
|
|
|
|
|
|
|
|
|



|
|

|
|
|
|







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
	    !C(@"foo/bar").absolutePath && !C(@"foo").absolutePath)
# else
	TEST(@"-[isAbsolutePath]",
	    C(@"/foo").absolutePath && C(@"/foo/bar").absolutePath &&
	    !C(@"foo/bar").absolutePath && !C(@"foo").absolutePath)
# endif

	mutableString1 = [mutableStringClass stringWithString: @"foo"];
# if defined(OF_WINDOWS) || defined(OF_MSDOS)
	[mutableString1 appendString: @"\\"];
# else
	[mutableString1 appendString: @"/"];
# endif
	[mutableString1 appendString: @"bar"];
	mutableString2 = [mutableStringClass stringWithString: mutableString1];
# if defined(OF_WINDOWS) || defined(OF_MSDOS)
	[mutableString2 appendString: @"\\"];
# else
	[mutableString2 appendString: @"/"];
# endif
	string = [stringClass stringWithString: mutableString2];
	[mutableString2 appendString: @"baz"];
	TEST(@"-[stringByAppendingPathComponent:]",
	    [[mutableString1 stringByAppendingPathComponent: @"baz"]
	    isEqual: mutableString2] &&
	    [[string stringByAppendingPathComponent: @"baz"]
	    isEqual: mutableString2])
#endif

	TEST(@"-[hasPrefix:]", [C(@"foobar") hasPrefix: @"foo"] &&
	    ![C(@"foobar") hasPrefix: @"foobar0"])

	TEST(@"-[hasSuffix:]", [C(@"foobar") hasSuffix: @"bar"] &&
	    ![C(@"foobar") hasSuffix: @"foobar0"])

	i = 0;
	TEST(@"-[componentsSeparatedByString:]",
	    (array = [C(@"fooXXbarXXXXbazXXXX")
	    componentsSeparatedByString: @"XX"]) &&
	    [[array objectAtIndex: i++] isEqual: @"foo"] &&
	    [[array objectAtIndex: i++] isEqual: @"bar"] &&
	    [[array objectAtIndex: i++] isEqual: @""] &&
	    [[array objectAtIndex: i++] isEqual: @"baz"] &&
	    [[array objectAtIndex: i++] isEqual: @""] &&
	    [[array objectAtIndex: i++] isEqual: @""] &&
	    array.count == i &&
	    (array = [C(@"foo") componentsSeparatedByString: @""]) &&
	    [[array objectAtIndex: 0] isEqual: @"foo"] &&
	    array.count == 1)

	i = 0;
	TEST(@"-[componentsSeparatedByString:options:]",
	    (array = [C(@"fooXXbarXXXXbazXXXX")
	    componentsSeparatedByString: @"XX"
				options: OFStringSkipEmptyComponents]) &&
	    [[array objectAtIndex: i++] isEqual: @"foo"] &&
	    [[array objectAtIndex: i++] isEqual: @"bar"] &&
	    [[array objectAtIndex: i++] isEqual: @"baz"] &&
	    array.count == i)

	characterSet =
	    [OFCharacterSet characterSetWithCharactersInString: @"XYZ"];

	i = 0;
	TEST(@"-[componentsSeparatedByCharactersInSet:]",
	    (array = [C(@"fooXYbarXYZXbazXYXZx")
	    componentsSeparatedByCharactersInSet: characterSet]) &&
	    [[array objectAtIndex: i++] isEqual: @"foo"] &&
	    [[array objectAtIndex: i++] isEqual: @""] &&
	    [[array objectAtIndex: i++] isEqual: @"bar"] &&
	    [[array objectAtIndex: i++] isEqual: @""] &&
	    [[array objectAtIndex: i++] isEqual: @""] &&
	    [[array objectAtIndex: i++] isEqual: @""] &&
	    [[array objectAtIndex: i++] isEqual: @"baz"] &&
	    [[array objectAtIndex: i++] isEqual: @""] &&
	    [[array objectAtIndex: i++] isEqual: @""] &&
	    [[array objectAtIndex: i++] isEqual: @""] &&
	    [[array objectAtIndex: i++] isEqual: @"x"] &&
	    array.count == i)

	i = 0;
	TEST(@"-[componentsSeparatedByCharactersInSet:options:]",
	    (array = [C(@"fooXYbarXYZXbazXYXZ")
	    componentsSeparatedByCharactersInSet: characterSet
	    options: OFStringSkipEmptyComponents]) &&
	    [[array objectAtIndex: i++] isEqual: @"foo"] &&
	    [[array objectAtIndex: i++] isEqual: @"bar"] &&
	    [[array objectAtIndex: i++] isEqual: @"baz"] &&
	    array.count == i)

#ifdef OF_HAVE_FILES
# if defined(OF_WINDOWS)
	TEST(@"+[pathWithComponents:]",
	    [[stringClass pathWithComponents: [OFArray arrayWithObjects:
	    @"foo", @"bar", @"baz", nil]] isEqual: @"foo\\bar\\baz"] &&
	    [[stringClass pathWithComponents: [OFArray arrayWithObjects:
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
	    [[stringClass pathWithComponents: [OFArray arrayWithObjects:
	    @"foo", nil]] isEqual: @"foo"])
# endif

# if defined(OF_WINDOWS)
	TEST(@"-[pathComponents]",
	    /* c:/tmp */
	    (a = C(@"c:/tmp").pathComponents) && a.count == 2 &&
	    [[a objectAtIndex: 0] isEqual: @"c:/"] &&
	    [[a objectAtIndex: 1] isEqual: @"tmp"] &&
	    /* c:\tmp\ */
	    (a = C(@"c:\\tmp\\").pathComponents) && a.count == 2 &&
	    [[a objectAtIndex: 0] isEqual: @"c:\\"] &&
	    [[a objectAtIndex: 1] isEqual: @"tmp"] &&
	    /* c:\ */
	    (a = C(@"c:\\").pathComponents) && a.count == 1 &&
	    [[a objectAtIndex: 0] isEqual: @"c:\\"] &&
	    /* c:/ */
	    (a = C(@"c:/").pathComponents) && a.count == 1 &&
	    [[a objectAtIndex: 0] isEqual: @"c:/"] &&
	    /* c: */
	    (a = C(@"c:").pathComponents) && a.count == 1 &&
	    [[a objectAtIndex: 0] isEqual: @"c:"] &&
	    /* foo\bar */
	    (a = C(@"foo\\bar").pathComponents) && a.count == 2 &&
	    [[a objectAtIndex: 0] isEqual: @"foo"] &&
	    [[a objectAtIndex: 1] isEqual: @"bar"] &&
	    /* foo\bar/baz/ */
	    (a = C(@"foo\\bar/baz/").pathComponents) && a.count == 3 &&
	    [[a objectAtIndex: 0] isEqual: @"foo"] &&
	    [[a objectAtIndex: 1] isEqual: @"bar"] &&
	    [[a objectAtIndex: 2] isEqual: @"baz"] &&
	    /* foo\/ */
	    (a = C(@"foo\\/").pathComponents) && a.count == 1 &&
	    [[a objectAtIndex: 0] isEqual: @"foo"] &&
	    /* \\foo\bar */
	    (a = C(@"\\\\foo\\bar").pathComponents) && a.count == 3 &&
	    [[a objectAtIndex: 0] isEqual: @"\\\\"] &&
	    [[a objectAtIndex: 1] isEqual: @"foo"] &&
	    [[a objectAtIndex: 2] isEqual: @"bar"] &&
	    C(@"").pathComponents.count == 0)
# elif defined(OF_MSDOS)
	TEST(@"-[pathComponents]",
	    /* c:/tmp */
	    (a = C(@"c:/tmp").pathComponents) && a.count == 2 &&
	    [[a objectAtIndex: 0] isEqual: @"c:/"] &&
	    [[a objectAtIndex: 1] isEqual: @"tmp"] &&
	    /* c:\tmp\ */
	    (a = C(@"c:\\tmp\\").pathComponents) && a.count == 2 &&
	    [[a objectAtIndex: 0] isEqual: @"c:\\"] &&
	    [[a objectAtIndex: 1] isEqual: @"tmp"] &&
	    /* c:\ */
	    (a = C(@"c:\\").pathComponents) && a.count == 1 &&
	    [[a objectAtIndex: 0] isEqual: @"c:\\"] &&
	    /* c:/ */
	    (a = C(@"c:/").pathComponents) && a.count == 1 &&
	    [[a objectAtIndex: 0] isEqual: @"c:/"] &&
	    /* c: */
	    (a = C(@"c:").pathComponents) && a.count == 1 &&
	    [[a objectAtIndex: 0] isEqual: @"c:"] &&
	    /* foo\bar */
	    (a = C(@"foo\\bar").pathComponents) && a.count == 2 &&
	    [[a objectAtIndex: 0] isEqual: @"foo"] &&
	    [[a objectAtIndex: 1] isEqual: @"bar"] &&
	    /* foo\bar/baz/ */
	    (a = C(@"foo\\bar/baz/").pathComponents) && a.count == 3 &&
	    [[a objectAtIndex: 0] isEqual: @"foo"] &&
	    [[a objectAtIndex: 1] isEqual: @"bar"] &&
	    [[a objectAtIndex: 2] isEqual: @"baz"] &&
	    /* foo\/ */
	    (a = C(@"foo\\/").pathComponents) && a.count == 1 &&
	    [[a objectAtIndex: 0] isEqual: @"foo"] &&
	    C(@"").pathComponents.count == 0)
# elif defined(OF_AMIGAOS)
	TEST(@"-[pathComponents]",
	    /* dh0:tmp */
	    (a = C(@"dh0:tmp").pathComponents) && a.count == 2 &&
	    [[a objectAtIndex: 0] isEqual: @"dh0:"] &&
	    [[a objectAtIndex: 1] isEqual: @"tmp"] &&
	    /* dh0:tmp/ */
	    (a = C(@"dh0:tmp/").pathComponents) && a.count == 2 &&
	    [[a objectAtIndex: 0] isEqual: @"dh0:"] &&
	    [[a objectAtIndex: 1] isEqual: @"tmp"] &&
	    /* dh0: */
	    (a = C(@"dh0:/").pathComponents) && a.count == 2 &&
	    [[a objectAtIndex: 0] isEqual: @"dh0:"] &&
	    [[a objectAtIndex: 1] isEqual: @"/"] &&
	    /* foo/bar */
	    (a = C(@"foo/bar").pathComponents) && a.count == 2 &&
	    [[a objectAtIndex: 0] isEqual: @"foo"] &&
	    [[a objectAtIndex: 1] isEqual: @"bar"] &&
	    /* foo/bar/baz/ */
	    (a = C(@"foo/bar/baz/").pathComponents) && a.count == 3 &&
	    [[a objectAtIndex: 0] isEqual: @"foo"] &&
	    [[a objectAtIndex: 1] isEqual: @"bar"] &&
	    [[a objectAtIndex: 2] isEqual: @"baz"] &&
	    /* foo// */
	    (a = C(@"foo//").pathComponents) && a.count == 2 &&
	    [[a objectAtIndex: 0] isEqual: @"foo"] &&
	    [[a objectAtIndex: 1] isEqual: @"/"] &&
	    C(@"").pathComponents.count == 0)
# elif defined(OF_NINTENDO_3DS) || defined(OF_WII)
	TEST(@"-[pathComponents]",
	    /* sdmc:/tmp */
	    (a = C(@"sdmc:/tmp").pathComponents) && a.count == 2 &&
	    [[a objectAtIndex: 0] isEqual: @"sdmc:"] &&
	    [[a objectAtIndex: 1] isEqual: @"tmp"] &&
	    /* sdmc:/ */
	    (a = C(@"sdmc:/").pathComponents) && a.count == 1 &&
	    [[a objectAtIndex: 0] isEqual: @"sdmc:"] &&
	    /* foo/bar */
	    (a = C(@"foo/bar").pathComponents) && a.count == 2 &&
	    [[a objectAtIndex: 0] isEqual: @"foo"] &&
	    [[a objectAtIndex: 1] isEqual: @"bar"] &&
	    /* foo/bar/baz/ */
	    (a = C(@"foo/bar/baz/").pathComponents) && a.count == 3 &&
	    [[a objectAtIndex: 0] isEqual: @"foo"] &&
	    [[a objectAtIndex: 1] isEqual: @"bar"] &&
	    [[a objectAtIndex: 2] isEqual: @"baz"] &&
	    /* foo// */
	    (a = C(@"foo//").pathComponents) && a.count == 1 &&
	    [[a objectAtIndex: 0] isEqual: @"foo"] &&
	    C(@"").pathComponents.count == 0)
# else
	TEST(@"-[pathComponents]",
	    /* /tmp */
	    (a = C(@"/tmp").pathComponents) && a.count == 2 &&
	    [[a objectAtIndex: 0] isEqual: @"/"] &&
	    [[a objectAtIndex: 1] isEqual: @"tmp"] &&
	    /* /tmp/ */
	    (a = C(@"/tmp/").pathComponents) && a.count == 2 &&
	    [[a objectAtIndex: 0] isEqual: @"/"] &&
	    [[a objectAtIndex: 1] isEqual: @"tmp"] &&
	    /* / */
	    (a = C(@"/").pathComponents) && a.count == 1 &&
	    [[a objectAtIndex: 0] isEqual: @"/"] &&
	    /* foo/bar */
	    (a = C(@"foo/bar").pathComponents) && a.count == 2 &&
	    [[a objectAtIndex: 0] isEqual: @"foo"] &&
	    [[a objectAtIndex: 1] isEqual: @"bar"] &&
	    /* foo/bar/baz/ */
	    (a = C(@"foo/bar/baz/").pathComponents) && a.count == 3 &&
	    [[a objectAtIndex: 0] isEqual: @"foo"] &&
	    [[a objectAtIndex: 1] isEqual: @"bar"] &&
	    [[a objectAtIndex: 2] isEqual: @"baz"] &&
	    /* foo// */
	    (a = C(@"foo//").pathComponents) && a.count == 1 &&
	    [[a objectAtIndex: 0] isEqual: @"foo"] &&
	    C(@"").pathComponents.count == 0)
# endif

# if defined(OF_WINDOWS)
	TEST(@"-[lastPathComponent]",
	    [C(@"c:/tmp").lastPathComponent isEqual: @"tmp"] &&
	    [C(@"c:\\tmp\\").lastPathComponent isEqual: @"tmp"] &&







|
|
|

|
|
|

|
|

|
|

|
|

|
|
|

|
|
|
|

|
|

|
|
|
|




|
|
|

|
|
|

|
|

|
|

|
|

|
|
|

|
|
|
|

|
|




|
|
|

|
|
|

|
|
|

|
|
|

|
|
|
|

|
|
|




|
|
|

|
|

|
|
|

|
|
|
|

|
|




|
|
|

|
|
|

|
|

|
|
|

|
|
|
|

|
|







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
	    [[stringClass pathWithComponents: [OFArray arrayWithObjects:
	    @"foo", nil]] isEqual: @"foo"])
# endif

# if defined(OF_WINDOWS)
	TEST(@"-[pathComponents]",
	    /* c:/tmp */
	    (array = C(@"c:/tmp").pathComponents) && array.count == 2 &&
	    [[array objectAtIndex: 0] isEqual: @"c:/"] &&
	    [[array objectAtIndex: 1] isEqual: @"tmp"] &&
	    /* c:\tmp\ */
	    (array = C(@"c:\\tmp\\").pathComponents) && array.count == 2 &&
	    [[array objectAtIndex: 0] isEqual: @"c:\\"] &&
	    [[array objectAtIndex: 1] isEqual: @"tmp"] &&
	    /* c:\ */
	    (array = C(@"c:\\").pathComponents) && array.count == 1 &&
	    [[array objectAtIndex: 0] isEqual: @"c:\\"] &&
	    /* c:/ */
	    (array = C(@"c:/").pathComponents) && array.count == 1 &&
	    [[array objectAtIndex: 0] isEqual: @"c:/"] &&
	    /* c: */
	    (array = C(@"c:").pathComponents) && array.count == 1 &&
	    [[array objectAtIndex: 0] isEqual: @"c:"] &&
	    /* foo\bar */
	    (array = C(@"foo\\bar").pathComponents) && array.count == 2 &&
	    [[array objectAtIndex: 0] isEqual: @"foo"] &&
	    [[array objectAtIndex: 1] isEqual: @"bar"] &&
	    /* foo\bar/baz/ */
	    (array = C(@"foo\\bar/baz/").pathComponents) && array.count == 3 &&
	    [[array objectAtIndex: 0] isEqual: @"foo"] &&
	    [[array objectAtIndex: 1] isEqual: @"bar"] &&
	    [[array objectAtIndex: 2] isEqual: @"baz"] &&
	    /* foo\/ */
	    (array = C(@"foo\\/").pathComponents) && array.count == 1 &&
	    [[array objectAtIndex: 0] isEqual: @"foo"] &&
	    /* \\foo\bar */
	    (array = C(@"\\\\foo\\bar").pathComponents) && array.count == 3 &&
	    [[array objectAtIndex: 0] isEqual: @"\\\\"] &&
	    [[array objectAtIndex: 1] isEqual: @"foo"] &&
	    [[array objectAtIndex: 2] isEqual: @"bar"] &&
	    C(@"").pathComponents.count == 0)
# elif defined(OF_MSDOS)
	TEST(@"-[pathComponents]",
	    /* c:/tmp */
	    (array = C(@"c:/tmp").pathComponents) && array.count == 2 &&
	    [[array objectAtIndex: 0] isEqual: @"c:/"] &&
	    [[array objectAtIndex: 1] isEqual: @"tmp"] &&
	    /* c:\tmp\ */
	    (array = C(@"c:\\tmp\\").pathComponents) && array.count == 2 &&
	    [[array objectAtIndex: 0] isEqual: @"c:\\"] &&
	    [[array objectAtIndex: 1] isEqual: @"tmp"] &&
	    /* c:\ */
	    (array = C(@"c:\\").pathComponents) && array.count == 1 &&
	    [[array objectAtIndex: 0] isEqual: @"c:\\"] &&
	    /* c:/ */
	    (array = C(@"c:/").pathComponents) && array.count == 1 &&
	    [[array objectAtIndex: 0] isEqual: @"c:/"] &&
	    /* c: */
	    (array = C(@"c:").pathComponents) && array.count == 1 &&
	    [[array objectAtIndex: 0] isEqual: @"c:"] &&
	    /* foo\bar */
	    (array = C(@"foo\\bar").pathComponents) && array.count == 2 &&
	    [[array objectAtIndex: 0] isEqual: @"foo"] &&
	    [[array objectAtIndex: 1] isEqual: @"bar"] &&
	    /* foo\bar/baz/ */
	    (array = C(@"foo\\bar/baz/").pathComponents) && array.count == 3 &&
	    [[array objectAtIndex: 0] isEqual: @"foo"] &&
	    [[array objectAtIndex: 1] isEqual: @"bar"] &&
	    [[array objectAtIndex: 2] isEqual: @"baz"] &&
	    /* foo\/ */
	    (array = C(@"foo\\/").pathComponents) && array.count == 1 &&
	    [[array objectAtIndex: 0] isEqual: @"foo"] &&
	    C(@"").pathComponents.count == 0)
# elif defined(OF_AMIGAOS)
	TEST(@"-[pathComponents]",
	    /* dh0:tmp */
	    (array = C(@"dh0:tmp").pathComponents) && array.count == 2 &&
	    [[array objectAtIndex: 0] isEqual: @"dh0:"] &&
	    [[array objectAtIndex: 1] isEqual: @"tmp"] &&
	    /* dh0:tmp/ */
	    (array = C(@"dh0:tmp/").pathComponents) && array.count == 2 &&
	    [[array objectAtIndex: 0] isEqual: @"dh0:"] &&
	    [[array objectAtIndex: 1] isEqual: @"tmp"] &&
	    /* dh0: */
	    (array = C(@"dh0:/").pathComponents) && array.count == 2 &&
	    [[array objectAtIndex: 0] isEqual: @"dh0:"] &&
	    [[array objectAtIndex: 1] isEqual: @"/"] &&
	    /* foo/bar */
	    (array = C(@"foo/bar").pathComponents) && array.count == 2 &&
	    [[array objectAtIndex: 0] isEqual: @"foo"] &&
	    [[array objectAtIndex: 1] isEqual: @"bar"] &&
	    /* foo/bar/baz/ */
	    (array = C(@"foo/bar/baz/").pathComponents) && array.count == 3 &&
	    [[array objectAtIndex: 0] isEqual: @"foo"] &&
	    [[array objectAtIndex: 1] isEqual: @"bar"] &&
	    [[array objectAtIndex: 2] isEqual: @"baz"] &&
	    /* foo// */
	    (array = C(@"foo//").pathComponents) && array.count == 2 &&
	    [[array objectAtIndex: 0] isEqual: @"foo"] &&
	    [[array objectAtIndex: 1] isEqual: @"/"] &&
	    C(@"").pathComponents.count == 0)
# elif defined(OF_NINTENDO_3DS) || defined(OF_WII)
	TEST(@"-[pathComponents]",
	    /* sdmc:/tmp */
	    (array = C(@"sdmc:/tmp").pathComponents) && array.count == 2 &&
	    [[array objectAtIndex: 0] isEqual: @"sdmc:"] &&
	    [[array objectAtIndex: 1] isEqual: @"tmp"] &&
	    /* sdmc:/ */
	    (array = C(@"sdmc:/").pathComponents) && array.count == 1 &&
	    [[array objectAtIndex: 0] isEqual: @"sdmc:"] &&
	    /* foo/bar */
	    (array = C(@"foo/bar").pathComponents) && array.count == 2 &&
	    [[array objectAtIndex: 0] isEqual: @"foo"] &&
	    [[array objectAtIndex: 1] isEqual: @"bar"] &&
	    /* foo/bar/baz/ */
	    (array = C(@"foo/bar/baz/").pathComponents) && array.count == 3 &&
	    [[array objectAtIndex: 0] isEqual: @"foo"] &&
	    [[array objectAtIndex: 1] isEqual: @"bar"] &&
	    [[array objectAtIndex: 2] isEqual: @"baz"] &&
	    /* foo// */
	    (array = C(@"foo//").pathComponents) && array.count == 1 &&
	    [[array objectAtIndex: 0] isEqual: @"foo"] &&
	    C(@"").pathComponents.count == 0)
# else
	TEST(@"-[pathComponents]",
	    /* /tmp */
	    (array = C(@"/tmp").pathComponents) && array.count == 2 &&
	    [[array objectAtIndex: 0] isEqual: @"/"] &&
	    [[array objectAtIndex: 1] isEqual: @"tmp"] &&
	    /* /tmp/ */
	    (array = C(@"/tmp/").pathComponents) && array.count == 2 &&
	    [[array objectAtIndex: 0] isEqual: @"/"] &&
	    [[array objectAtIndex: 1] isEqual: @"tmp"] &&
	    /* / */
	    (array = C(@"/").pathComponents) && array.count == 1 &&
	    [[array objectAtIndex: 0] isEqual: @"/"] &&
	    /* foo/bar */
	    (array = C(@"foo/bar").pathComponents) && array.count == 2 &&
	    [[array objectAtIndex: 0] isEqual: @"foo"] &&
	    [[array objectAtIndex: 1] isEqual: @"bar"] &&
	    /* foo/bar/baz/ */
	    (array = C(@"foo/bar/baz/").pathComponents) && array.count == 3 &&
	    [[array objectAtIndex: 0] isEqual: @"foo"] &&
	    [[array objectAtIndex: 1] isEqual: @"bar"] &&
	    [[array objectAtIndex: 2] isEqual: @"baz"] &&
	    /* foo// */
	    (array = C(@"foo//").pathComponents) && array.count == 1 &&
	    [[array objectAtIndex: 0] isEqual: @"foo"] &&
	    C(@"").pathComponents.count == 0)
# endif

# if defined(OF_WINDOWS)
	TEST(@"-[lastPathComponent]",
	    [C(@"c:/tmp").lastPathComponent isEqual: @"tmp"] &&
	    [C(@"c:\\tmp\\").lastPathComponent isEqual: @"tmp"] &&
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

	EXPECT_EXCEPTION(@"Detect out of range in -[unsignedLongLongValue]",
	    OFOutOfRangeException,
	    [C(@"0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF"
	       @"0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF")
	    unsignedLongLongValueWithBase: 16])

	TEST(@"-[characters]", (ua = C(@"fööbär🀺").characters) &&
	    !memcmp(ua, ucstr + 1, sizeof(ucstr) - 8))

#ifdef OF_BIG_ENDIAN
# define SWAPPED_BYTE_ORDER OFByteOrderLittleEndian
#else
# define SWAPPED_BYTE_ORDER OFByteOrderBigEndian
#endif
	TEST(@"-[UTF16String]", (u16a = C(@"fööbär🀺").UTF16String) &&

	    !memcmp(u16a, utf16str + 1, OFUTF16StringLength(utf16str) * 2) &&
	    (u16a = [C(@"fööbär🀺")
	    UTF16StringWithByteOrder: SWAPPED_BYTE_ORDER]) &&

	    !memcmp(u16a, sutf16str + 1, OFUTF16StringLength(sutf16str) * 2))

	TEST(@"-[UTF16StringLength]", C(@"fööbär🀺").UTF16StringLength == 8)

	TEST(@"-[UTF32String]", (ua = C(@"fööbär🀺").UTF32String) &&

	    !memcmp(ua, ucstr + 1, OFUTF32StringLength(ucstr) * 4) &&
	    (ua = [C(@"fööbär🀺") UTF32StringWithByteOrder:
	    SWAPPED_BYTE_ORDER]) &&

	    !memcmp(ua, sucstr + 1, OFUTF32StringLength(sucstr) * 4))
#undef SWAPPED_BYTE_ORDER

	TEST(@"-[stringByMD5Hashing]", [C(@"asdfoobar").stringByMD5Hashing
	    isEqual: @"184dce2ec49b5422c7cfd8728864db4c"])

	TEST(@"-[stringByRIPEMD160Hashing]",
	    [C(@"asdfoobar").stringByRIPEMD160Hashing
	    isEqual: @"021d773b0fac06eb6755ca6aa58a580c980f7f13"])







|
|


|

|

|
>
|
|
|
>
|



|
>
|
|
|
>
|
|







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

	EXPECT_EXCEPTION(@"Detect out of range in -[unsignedLongLongValue]",
	    OFOutOfRangeException,
	    [C(@"0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF"
	       @"0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF")
	    unsignedLongLongValueWithBase: 16])

	TEST(@"-[characters]", (characters = C(@"fööbär🀺").characters) &&
	    !memcmp(characters, unicharString + 1, sizeof(unicharString) - 8))

#ifdef OF_BIG_ENDIAN
# define swappedByteOrder OFByteOrderLittleEndian
#else
# define swappedByteOrder OFByteOrderBigEndian
#endif
	TEST(@"-[UTF16String]", (UTF16Characters = C(@"fööbär🀺").UTF16String) &&
	    !memcmp(UTF16Characters, char16String + 1,
	    OFUTF16StringLength(char16String) * 2) &&
	    (UTF16Characters = [C(@"fööbär🀺")
	    UTF16StringWithByteOrder: swappedByteOrder]) &&
	    !memcmp(UTF16Characters, swappedChar16String + 1,
	    OFUTF16StringLength(swappedChar16String) * 2))

	TEST(@"-[UTF16StringLength]", C(@"fööbär🀺").UTF16StringLength == 8)

	TEST(@"-[UTF32String]", (characters = C(@"fööbär🀺").UTF32String) &&
	    !memcmp(characters, unicharString + 1,
	    OFUTF32StringLength(unicharString) * 4) &&
	    (characters = [C(@"fööbär🀺") UTF32StringWithByteOrder:
	    swappedByteOrder]) &&
	    !memcmp(characters, swappedUnicharString + 1,
	    OFUTF32StringLength(swappedUnicharString) * 4))
#undef swappedByteOrder

	TEST(@"-[stringByMD5Hashing]", [C(@"asdfoobar").stringByMD5Hashing
	    isEqual: @"184dce2ec49b5422c7cfd8728864db4c"])

	TEST(@"-[stringByRIPEMD160Hashing]",
	    [C(@"asdfoobar").stringByRIPEMD160Hashing
	    isEqual: @"021d773b0fac06eb6755ca6aa58a580c980f7f13"])
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
		     @"279e5addf8be854044bca0cece073fce28eec7d9"])

	TEST(@"-[stringBySHA512Hashing]", [C(@"asdfoobar").stringBySHA512Hashing
	    isEqual: @"0464c427da158b02161bb44a3090bbfc594611ef6a53603640454b56"
		     @"412a9247c3579a329e53a5dc74676b106755e3394f9454a2d4227324"
		     @"2615d32f80437d61"])


	cs = [OFCharacterSet characterSetWithCharactersInString: @"abfo'_~$🍏"];
	TEST(@"-[stringByURLEncodingWithAllowedCharacters:]",
	    [[C(@"foo\"ba'_~$]🍏🍌") stringByURLEncodingWithAllowedCharacters:
	    cs] isEqual: @"foo%22ba'_~$%5D🍏%F0%9F%8D%8C"])

	TEST(@"-[stringByURLDecoding]",
	    [C(@"foo%20bar%22+%24%F0%9F%8D%8C").stringByURLDecoding
	    isEqual: @"foo bar\"+$🍌"])

	TEST(@"-[insertString:atIndex:]",

	    (s[0] = [mutableStringClass stringWithString: @"𝄞öööbä€"]) &&
	    R([s[0] insertString: @"äöü" atIndex: 3]) &&
	    [s[0] isEqual: @"𝄞ööäöüöbä€"])

	EXPECT_EXCEPTION(@"Detect invalid format in -[stringByURLDecoding] "
	    @"#1", OFInvalidFormatException,
	    [C(@"foo%xbar") stringByURLDecoding])
	EXPECT_EXCEPTION(@"Detect invalid encoding in -[stringByURLDecoding] "
	    @"#2", OFInvalidEncodingException,
	    [C(@"foo%FFbar") stringByURLDecoding])

	TEST(@"-[setCharacter:atIndex:]",

	    (s[0] = [mutableStringClass stringWithString: @"abäde"]) &&
	    R([s[0] setCharacter: 0xF6 atIndex: 2]) &&
	    [s[0] isEqual: @"aböde"] &&
	    R([s[0] setCharacter: 'c' atIndex: 2]) &&
	    [s[0] isEqual: @"abcde"] &&
	    R([s[0] setCharacter: 0x20AC atIndex: 3]) &&
	    [s[0] isEqual: @"abc€e"] &&
	    R([s[0] setCharacter: 'x' atIndex: 1]) && [s[0] isEqual: @"axc€e"])


	TEST(@"-[deleteCharactersInRange:]",

	    (s[0] = [mutableStringClass stringWithString: @"𝄞öööbä€"]) &&
	    R([s[0] deleteCharactersInRange: OFRangeMake(1, 3)]) &&
	    [s[0] isEqual: @"𝄞bä€"] &&
	    R([s[0] deleteCharactersInRange: OFRangeMake(0, 4)]) &&
	    [s[0] isEqual: @""])

	TEST(@"-[replaceCharactersInRange:withString:]",

	    (s[0] = [mutableStringClass stringWithString: @"𝄞öööbä€"]) &&
	    R([s[0] replaceCharactersInRange: OFRangeMake(1, 3)
				  withString: @"äöüß"]) &&
	    [s[0] isEqual: @"𝄞äöüßbä€"] &&
	    R([s[0] replaceCharactersInRange: OFRangeMake(4, 2)
				  withString: @"b"]) &&
	    [s[0] isEqual: @"𝄞äöübä€"] &&
	    R([s[0] replaceCharactersInRange: OFRangeMake(0, 7)
				  withString: @""]) &&
	    [s[0] isEqual: @""])

	EXPECT_EXCEPTION(@"Detect OoR in -[deleteCharactersInRange:] #1",
	    OFOutOfRangeException,
	    {
		s[0] = [mutableStringClass stringWithString: @"𝄞öö"];
		[s[0] deleteCharactersInRange: OFRangeMake(2, 2)];
	    })

	EXPECT_EXCEPTION(@"Detect OoR in -[deleteCharactersInRange:] #2",
	    OFOutOfRangeException,
	    [s[0] deleteCharactersInRange: OFRangeMake(4, 0)])

	EXPECT_EXCEPTION(@"Detect OoR in "
	    @"-[replaceCharactersInRange:withString:] #1",
	    OFOutOfRangeException,
	    [s[0] replaceCharactersInRange: OFRangeMake(2, 2) withString: @""])


	EXPECT_EXCEPTION(@"Detect OoR in "
	    @"-[replaceCharactersInRange:withString:] #2",
	    OFOutOfRangeException,
	    [s[0] replaceCharactersInRange: OFRangeMake(4, 0) withString: @""])


	TEST(@"-[replaceOccurrencesOfString:withString:]",
	    (s[0] = [mutableStringClass stringWithString:
	    @"asd fo asd fofo asd"]) &&
	    R([s[0] replaceOccurrencesOfString: @"fo" withString: @"foo"]) &&

	    [s[0] isEqual: @"asd foo asd foofoo asd"] &&
	    (s[0] = [mutableStringClass stringWithString: @"XX"]) &&
	    R([s[0] replaceOccurrencesOfString: @"X" withString: @"XX"]) &&

	    [s[0] isEqual: @"XXXX"])

	TEST(@"-[replaceOccurrencesOfString:withString:options:range:]",
	    (s[0] = [mutableStringClass stringWithString:
	    @"foofoobarfoobarfoo"]) &&
	    R([s[0] replaceOccurrencesOfString: @"oo"
				    withString: @"óò"
				       options: 0
					 range: OFRangeMake(2, 15)]) &&
	    [s[0] isEqual: @"foofóòbarfóòbarfoo"])

	TEST(@"-[deleteLeadingWhitespaces]",

	    (s[0] = [mutableStringClass stringWithString: whitespace[0]]) &&
	    R([s[0] deleteLeadingWhitespaces]) &&
	    [s[0] isEqual: @"asd  \t \t\t\r\n"] &&

	    (s[0] = [mutableStringClass stringWithString: whitespace[1]]) &&
	    R([s[0] deleteLeadingWhitespaces]) && [s[0] isEqual: @""])


	TEST(@"-[deleteTrailingWhitespaces]",

	    (s[0] = [mutableStringClass stringWithString: whitespace[0]]) &&
	    R([s[0] deleteTrailingWhitespaces]) &&
	    [s[0] isEqual: @" \r \t\n\t \tasd"] &&

	    (s[0] = [mutableStringClass stringWithString: whitespace[1]]) &&
	    R([s[0] deleteTrailingWhitespaces]) && [s[0] isEqual: @""])


	TEST(@"-[deleteEnclosingWhitespaces]",

	    (s[0] = [mutableStringClass stringWithString: whitespace[0]]) &&
	    R([s[0] deleteEnclosingWhitespaces]) && [s[0] isEqual: @"asd"] &&


	    (s[0] = [mutableStringClass stringWithString: whitespace[1]]) &&
	    R([s[0] deleteEnclosingWhitespaces]) && [s[0] 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]",
	    (is = C(@"<hello> &world'\"!&").stringByXMLEscaping) &&
	    [is isEqual: @"&lt;hello&gt; &amp;world&apos;&quot;!&amp;"])

	TEST(@"-[stringByXMLUnescaping]",
	    [is.stringByXMLUnescaping isEqual: @"<hello> &world'\"!&"] &&
	    [C(@"&#x79;").stringByXMLUnescaping isEqual: @"y"] &&
	    [C(@"&#xe4;").stringByXMLUnescaping isEqual: @"ä"] &&
	    [C(@"&#8364;").stringByXMLUnescaping isEqual: @"€"] &&
	    [C(@"&#x1D11E;").stringByXMLUnescaping isEqual: @"𝄞"])

	EXPECT_EXCEPTION(@"Detect unknown entities in -[stringByXMLUnescaping]",
	    OFUnknownXMLEntityException, [C(@"&foo;") stringByXMLUnescaping])







>
|


|






>
|
|
|









>
|
|
|
|
|
|
|
|
>


>
|
|
|
|
|


>
|
|
|
|
|
|
|
|
|
|




|
|




|




|
>




|
>


|

|
>
|
|
|
>
|


|
|
|
|
|
|
|


>
|
|
|
>
|
|
>


>
|
|
|
>
|
|
>


>
|
|
>
>
|
|
>












|
|


|







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
		     @"279e5addf8be854044bca0cece073fce28eec7d9"])

	TEST(@"-[stringBySHA512Hashing]", [C(@"asdfoobar").stringBySHA512Hashing
	    isEqual: @"0464c427da158b02161bb44a3090bbfc594611ef6a53603640454b56"
		     @"412a9247c3579a329e53a5dc74676b106755e3394f9454a2d4227324"
		     @"2615d32f80437d61"])

	characterSet =
	    [OFCharacterSet characterSetWithCharactersInString: @"abfo'_~$🍏"];
	TEST(@"-[stringByURLEncodingWithAllowedCharacters:]",
	    [[C(@"foo\"ba'_~$]🍏🍌") stringByURLEncodingWithAllowedCharacters:
	    characterSet] isEqual: @"foo%22ba'_~$%5D🍏%F0%9F%8D%8C"])

	TEST(@"-[stringByURLDecoding]",
	    [C(@"foo%20bar%22+%24%F0%9F%8D%8C").stringByURLDecoding
	    isEqual: @"foo bar\"+$🍌"])

	TEST(@"-[insertString:atIndex:]",
	    (mutableString1 = [mutableStringClass
	    stringWithString: @"𝄞öööbä€"]) &&
	    R([mutableString1 insertString: @"äöü" atIndex: 3]) &&
	    [mutableString1 isEqual: @"𝄞ööäöüöbä€"])

	EXPECT_EXCEPTION(@"Detect invalid format in -[stringByURLDecoding] "
	    @"#1", OFInvalidFormatException,
	    [C(@"foo%xbar") stringByURLDecoding])
	EXPECT_EXCEPTION(@"Detect invalid encoding in -[stringByURLDecoding] "
	    @"#2", OFInvalidEncodingException,
	    [C(@"foo%FFbar") stringByURLDecoding])

	TEST(@"-[setCharacter:atIndex:]",
	    (mutableString1 = [mutableStringClass
	    stringWithString: @"abäde"]) &&
	    R([mutableString1 setCharacter: 0xF6 atIndex: 2]) &&
	    [mutableString1 isEqual: @"aböde"] &&
	    R([mutableString1 setCharacter: 'c' atIndex: 2]) &&
	    [mutableString1 isEqual: @"abcde"] &&
	    R([mutableString1 setCharacter: 0x20AC atIndex: 3]) &&
	    [mutableString1 isEqual: @"abc€e"] &&
	    R([mutableString1 setCharacter: 'x' atIndex: 1]) &&
	    [mutableString1 isEqual: @"axc€e"])

	TEST(@"-[deleteCharactersInRange:]",
	    (mutableString1 = [mutableStringClass
	    stringWithString: @"𝄞öööbä€"]) &&
	    R([mutableString1 deleteCharactersInRange: OFRangeMake(1, 3)]) &&
	    [mutableString1 isEqual: @"𝄞bä€"] &&
	    R([mutableString1 deleteCharactersInRange: OFRangeMake(0, 4)]) &&
	    [mutableString1 isEqual: @""])

	TEST(@"-[replaceCharactersInRange:withString:]",
	    (mutableString1 = [mutableStringClass
	    stringWithString: @"𝄞öööbä€"]) &&
	    R([mutableString1 replaceCharactersInRange: OFRangeMake(1, 3)
					    withString: @"äöüß"]) &&
	    [mutableString1 isEqual: @"𝄞äöüßbä€"] &&
	    R([mutableString1 replaceCharactersInRange: OFRangeMake(4, 2)
					    withString: @"b"]) &&
	    [mutableString1 isEqual: @"𝄞äöübä€"] &&
	    R([mutableString1 replaceCharactersInRange: OFRangeMake(0, 7)
					    withString: @""]) &&
	    [mutableString1 isEqual: @""])

	EXPECT_EXCEPTION(@"Detect OoR in -[deleteCharactersInRange:] #1",
	    OFOutOfRangeException,
	    {
		mutableString1 = [mutableStringClass stringWithString: @"𝄞öö"];
		[mutableString1 deleteCharactersInRange: OFRangeMake(2, 2)];
	    })

	EXPECT_EXCEPTION(@"Detect OoR in -[deleteCharactersInRange:] #2",
	    OFOutOfRangeException,
	    [mutableString1 deleteCharactersInRange: OFRangeMake(4, 0)])

	EXPECT_EXCEPTION(@"Detect OoR in "
	    @"-[replaceCharactersInRange:withString:] #1",
	    OFOutOfRangeException,
	    [mutableString1 replaceCharactersInRange: OFRangeMake(2, 2)
					  withString: @""])

	EXPECT_EXCEPTION(@"Detect OoR in "
	    @"-[replaceCharactersInRange:withString:] #2",
	    OFOutOfRangeException,
	    [mutableString1 replaceCharactersInRange: OFRangeMake(4, 0)
					  withString: @""])

	TEST(@"-[replaceOccurrencesOfString:withString:]",
	    (mutableString1 = [mutableStringClass stringWithString:
	    @"asd fo asd fofo asd"]) &&
	    R([mutableString1 replaceOccurrencesOfString: @"fo"
					      withString: @"foo"]) &&
	    [mutableString1 isEqual: @"asd foo asd foofoo asd"] &&
	    (mutableString1 = [mutableStringClass stringWithString: @"XX"]) &&
	    R([mutableString1 replaceOccurrencesOfString: @"X"
					      withString: @"XX"]) &&
	    [mutableString1 isEqual: @"XXXX"])

	TEST(@"-[replaceOccurrencesOfString:withString:options:range:]",
	    (mutableString1 = [mutableStringClass stringWithString:
	    @"foofoobarfoobarfoo"]) && R([mutableString1
	    replaceOccurrencesOfString: @"oo"
			    withString: @"óò"
			       options: 0
				 range: OFRangeMake(2, 15)]) &&
	    [mutableString1 isEqual: @"foofóòbarfóòbarfoo"])

	TEST(@"-[deleteLeadingWhitespaces]",
	    (mutableString1 = [mutableStringClass
	    stringWithString: whitespace[0]]) &&
	    R([mutableString1 deleteLeadingWhitespaces]) &&
	    [mutableString1 isEqual: @"asd  \t \t\t\r\n"] &&
	    (mutableString1 = [mutableStringClass
	    stringWithString: whitespace[1]]) &&
	    R([mutableString1 deleteLeadingWhitespaces]) &&
	    [mutableString1 isEqual: @""])

	TEST(@"-[deleteTrailingWhitespaces]",
	    (mutableString1 = [mutableStringClass
	    stringWithString: whitespace[0]]) &&
	    R([mutableString1 deleteTrailingWhitespaces]) &&
	    [mutableString1 isEqual: @" \r \t\n\t \tasd"] &&
	    (mutableString1 = [mutableStringClass
	    stringWithString: whitespace[1]]) &&
	    R([mutableString1 deleteTrailingWhitespaces]) &&
	    [mutableString1 isEqual: @""])

	TEST(@"-[deleteEnclosingWhitespaces]",
	    (mutableString1 = [mutableStringClass
	    stringWithString: whitespace[0]]) &&
	    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"] &&
	    [C(@"&#xe4;").stringByXMLUnescaping isEqual: @"ä"] &&
	    [C(@"&#8364;").stringByXMLUnescaping isEqual: @"€"] &&
	    [C(@"&#x1D11E;").stringByXMLUnescaping isEqual: @"𝄞"])

	EXPECT_EXCEPTION(@"Detect unknown entities in -[stringByXMLUnescaping]",
	    OFUnknownXMLEntityException, [C(@"&foo;") stringByXMLUnescaping])
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
	EXPECT_EXCEPTION(@"Detect invalid entities in -[stringByXMLUnescaping] "
	    @"#4", OFInvalidFormatException, [C(@"&#g;") stringByXMLUnescaping])
	EXPECT_EXCEPTION(@"Detect invalid entities in -[stringByXMLUnescaping] "
	    @"#5", OFInvalidFormatException,
	    [C(@"&#xg;") stringByXMLUnescaping])

	TEST(@"-[stringByXMLUnescapingWithDelegate:]",
	    (h = [[[EntityHandler alloc] init] autorelease]) &&
	    [[C(@"x&foo;y") stringByXMLUnescapingWithDelegate: h]
	    isEqual: @"xbary"])

#ifdef OF_HAVE_BLOCKS
	TEST(@"-[stringByXMLUnescapingWithBlock:]",
	    [[C(@"x&foo;y") stringByXMLUnescapingWithBlock:
	        ^ OFString *(OFString *str, OFString *entity) {
		    if ([entity isEqual: @"foo"])
			    return @"bar";

		    return nil;
	    }] isEqual: @"xbary"])

	j = 0;







|
|





|







1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
	EXPECT_EXCEPTION(@"Detect invalid entities in -[stringByXMLUnescaping] "
	    @"#4", OFInvalidFormatException, [C(@"&#g;") stringByXMLUnescaping])
	EXPECT_EXCEPTION(@"Detect invalid entities in -[stringByXMLUnescaping] "
	    @"#5", OFInvalidFormatException,
	    [C(@"&#xg;") stringByXMLUnescaping])

	TEST(@"-[stringByXMLUnescapingWithDelegate:]",
	    (entityHandler = [[[EntityHandler alloc] init] autorelease]) &&
	    [[C(@"x&foo;y") stringByXMLUnescapingWithDelegate: entityHandler]
	    isEqual: @"xbary"])

#ifdef OF_HAVE_BLOCKS
	TEST(@"-[stringByXMLUnescapingWithBlock:]",
	    [[C(@"x&foo;y") stringByXMLUnescapingWithBlock:
		^ OFString *(OFString *str, OFString *entity) {
		    if ([entity isEqual: @"foo"])
			    return @"bar";

		    return nil;
	    }] isEqual: @"xbary"])

	j = 0;

Modified tests/OFTCPSocketTests.m from [dfc17ad706] to [e9219b696c].

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

#include "config.h"

#include <string.h>

#import "TestsAppDelegate.h"

static OFString *module = @"OFTCPSocket";

@implementation TestsAppDelegate (OFTCPSocketTests)
- (void)TCPSocketTests
{
	void *pool = objc_autoreleasePoolPush();
	OFTCPSocket *server, *client = nil, *accepted;
	uint16_t port;
	char buf[6];

	TEST(@"+[socket]", (server = [OFTCPSocket socket]) &&
	    (client = [OFTCPSocket socket]))

	TEST(@"-[bindToHost:port:]",
	    (port = [server bindToHost: @"127.0.0.1" port: 0]))








|







|







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

#include "config.h"

#include <string.h>

#import "TestsAppDelegate.h"

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

45
46
47
48
49
50
51
52
53
54
55
56
57
	TEST(@"-[remoteAddress]",
	    [OFSocketAddressString(accepted.remoteAddress)
	    isEqual: @"127.0.0.1"])

	TEST(@"-[writeString:]", [client writeString: @"Hello!"])

	TEST(@"-[readIntoBuffer:length:]",
	    [accepted readIntoBuffer: buf length: 6] &&
	    !memcmp(buf, "Hello!", 6))

	objc_autoreleasePoolPop(pool);
}
@end







|
|




45
46
47
48
49
50
51
52
53
54
55
56
57
	TEST(@"-[remoteAddress]",
	    [OFSocketAddressString(accepted.remoteAddress)
	    isEqual: @"127.0.0.1"])

	TEST(@"-[writeString:]", [client writeString: @"Hello!"])

	TEST(@"-[readIntoBuffer:length:]",
	    [accepted readIntoBuffer: buffer length: 6] &&
	    !memcmp(buffer, "Hello!", 6))

	objc_autoreleasePoolPop(pool);
}
@end

Modified tests/OFThreadTests.m from [61a0609ec2] to [6e125a20af].

13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28


29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
 * file.
 */

#include "config.h"

#import "TestsAppDelegate.h"

static OFString *module = @"OFThread";

@interface TestThread: OFThread
@end

@implementation TestThread
- (id)main
{
	[[OFThread threadDictionary] setObject: @"bar" forKey: @"foo"];



	return @"success";
}
@end

@implementation TestsAppDelegate (OFThreadTests)
- (void)threadTests
{
	void *pool = objc_autoreleasePoolPush();
	TestThread *t;
	OFMutableDictionary *d;

	TEST(@"+[thread]", (t = [TestThread thread]))

	TEST(@"-[start]", R([t start]))

	TEST(@"-[join]", [[t join] isEqual: @"success"])

	TEST(@"-[threadDictionary]", (d = [OFThread threadDictionary]) &&
	    [d objectForKey: @"foo"] == nil)

	objc_autoreleasePoolPop(pool);
}
@end







|








>
>









|
<

|

|

|

|
|




13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40

41
42
43
44
45
46
47
48
49
50
51
52
53
 * file.
 */

#include "config.h"

#import "TestsAppDelegate.h"

static OFString *const module = @"OFThread";

@interface TestThread: OFThread
@end

@implementation TestThread
- (id)main
{
	[[OFThread threadDictionary] setObject: @"bar" forKey: @"foo"];
	OFEnsure([[[OFThread threadDictionary]
	    objectForKey: @"foo"] isEqual: @"bar"]);

	return @"success";
}
@end

@implementation TestsAppDelegate (OFThreadTests)
- (void)threadTests
{
	void *pool = objc_autoreleasePoolPush();
	TestThread *thread;


	TEST(@"+[thread]", (thread = [TestThread thread]))

	TEST(@"-[start]", R([thread start]))

	TEST(@"-[join]", [[thread join] isEqual: @"success"])

	TEST(@"-[threadDictionary]",
	    [[OFThread threadDictionary] objectForKey: @"foo"] == nil)

	objc_autoreleasePoolPop(pool);
}
@end

Modified tests/OFUDPSocketTests.m from [c440a7c2a6] to [6d7b4e4936].

15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

#include "config.h"

#include <string.h>

#import "TestsAppDelegate.h"

static OFString *module = @"OFUDPSocket";

@implementation TestsAppDelegate (OFUDPSocketTests)
- (void)UDPSocketTests
{
	void *pool = objc_autoreleasePoolPush();
	OFUDPSocket *sock;
	uint16_t port1;







|







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

#include "config.h"

#include <string.h>

#import "TestsAppDelegate.h"

static OFString *const module = @"OFUDPSocket";

@implementation TestsAppDelegate (OFUDPSocketTests)
- (void)UDPSocketTests
{
	void *pool = objc_autoreleasePoolPush();
	OFUDPSocket *sock;
	uint16_t port1;

Modified tests/OFURLTests.m from [a23bc7aa5e] to [641ece2b4e].

13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
 * file.
 */

#include "config.h"

#import "TestsAppDelegate.h"

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

@implementation TestsAppDelegate (OFURLTests)
- (void)URLTests
{
	void *pool = objc_autoreleasePoolPush();
	OFURL *u1, *u2, *u3, *u4, *u5, *u6, *u7;
	OFMutableURL *mu;

	TEST(@"+[URLWithString:]",
	    R(u1 = [OFURL URLWithString: url_str]) &&
	    R(u2 = [OFURL URLWithString: @"http://foo:80"]) &&
	    R(u3 = [OFURL URLWithString: @"http://bar/"]) &&
	    R(u4 = [OFURL URLWithString: @"file:///etc/passwd"]) &&
	    R(u5 = [OFURL URLWithString: @"http://foo/bar/qux/foo%2fbar"]) &&
	    R(u6 = [OFURL URLWithString: @"https://[12:34::56:abcd]/"]) &&
	    R(u7 = [OFURL URLWithString: @"https://[12:34::56:abcd]:234/"]))

	EXPECT_EXCEPTION(@"+[URLWithString:] fails with invalid characters #1",
	    OFInvalidFormatException,
	    [OFURL URLWithString: @"ht,tp://foo"])

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







|
|






|
|


|
|
|
|
|
|
|







13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
 * file.
 */

#include "config.h"

#import "TestsAppDelegate.h"

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

@implementation TestsAppDelegate (OFURLTests)
- (void)URLTests
{
	void *pool = objc_autoreleasePoolPush();
	OFURL *URL1, *URL2, *URL3, *URL4, *URL5, *URL6, *URL7;
	OFMutableURL *mutableURL;

	TEST(@"+[URLWithString:]",
	    R(URL1 = [OFURL URLWithString: URLString]) &&
	    R(URL2 = [OFURL URLWithString: @"http://foo:80"]) &&
	    R(URL3 = [OFURL URLWithString: @"http://bar/"]) &&
	    R(URL4 = [OFURL URLWithString: @"file:///etc/passwd"]) &&
	    R(URL5 = [OFURL URLWithString: @"http://foo/bar/qux/foo%2fbar"]) &&
	    R(URL6 = [OFURL URLWithString: @"https://[12:34::56:abcd]/"]) &&
	    R(URL7 = [OFURL URLWithString: @"https://[12:34::56:abcd]:234/"]))

	EXPECT_EXCEPTION(@"+[URLWithString:] fails with invalid characters #1",
	    OFInvalidFormatException,
	    [OFURL URLWithString: @"ht,tp://foo"])

	EXPECT_EXCEPTION(@"+[URLWithString:] fails with invalid characters #2",
	    OFInvalidFormatException,
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
	    [OFURL URLWithString: @"https://[f]:/"])

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

	TEST(@"+[URLWithString:relativeToURL:]",
	    [[[OFURL URLWithString: @"/foo" relativeToURL: u1] string] isEqual:
	    @"ht%3atp://us%3Aer:p%40w@ho%3Ast:1234/foo"] &&
	    [[[OFURL URLWithString: @"foo/bar?q"
		     relativeToURL: [OFURL URLWithString: @"http://h/qux/quux"]]
	    string] isEqual: @"http://h/qux/foo/bar?q"] &&
	    [[[OFURL URLWithString: @"foo/bar"
		     relativeToURL: [OFURL URLWithString: @"http://h/qux/?x"]]
	    string] isEqual: @"http://h/qux/foo/bar"] &&
	    [[[OFURL URLWithString: @"http://foo/?q"
		     relativeToURL: u1] string] isEqual: @"http://foo/?q"] &&
	    [[[OFURL URLWithString: @"foo"
		     relativeToURL: [OFURL URLWithString: @"http://foo/bar"]]
	    string] isEqual: @"http://foo/foo"] &&
	    [[[OFURL URLWithString: @"foo"
		     relativeToURL: [OFURL URLWithString: @"http://foo"]]
	    string] isEqual: @"http://foo/foo"])

	EXPECT_EXCEPTION(
	    @"+[URLWithString:relativeToURL:] fails with invalid characters #1",
	    OFInvalidFormatException,
	    [OFURL URLWithString: @"`" relativeToURL: u1])

	EXPECT_EXCEPTION(
	    @"+[URLWithString:relativeToURL:] fails with invalid characters #2",
	    OFInvalidFormatException,
	    [OFURL URLWithString: @"/`" relativeToURL: u1])

	EXPECT_EXCEPTION(
	    @"+[URLWithString:relativeToURL:] fails with invalid characters #3",
	    OFInvalidFormatException,
	    [OFURL URLWithString: @"?`" relativeToURL: u1])

	EXPECT_EXCEPTION(
	    @"+[URLWithString:relativeToURL:] fails with invalid characters #4",
	    OFInvalidFormatException,
	    [OFURL URLWithString: @"#`" relativeToURL: u1])

#ifdef OF_HAVE_FILES
	TEST(@"+[fileURLWithPath:]",
	    [[[OFURL fileURLWithPath: @"testfile.txt"] fileSystemRepresentation]
	    isEqual: [[OFFileManager defaultManager].currentDirectoryPath
	    stringByAppendingPathComponent: @"testfile.txt"]])








|
|







|










|




|




|




|







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
	    [OFURL URLWithString: @"https://[f]:/"])

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

	TEST(@"+[URLWithString:relativeToURL:]",
	    [[[OFURL URLWithString: @"/foo" relativeToURL: URL1] string]
	    isEqual: @"ht%3atp://us%3Aer:p%40w@ho%3Ast:1234/foo"] &&
	    [[[OFURL URLWithString: @"foo/bar?q"
		     relativeToURL: [OFURL URLWithString: @"http://h/qux/quux"]]
	    string] isEqual: @"http://h/qux/foo/bar?q"] &&
	    [[[OFURL URLWithString: @"foo/bar"
		     relativeToURL: [OFURL URLWithString: @"http://h/qux/?x"]]
	    string] isEqual: @"http://h/qux/foo/bar"] &&
	    [[[OFURL URLWithString: @"http://foo/?q"
		     relativeToURL: URL1] string] isEqual: @"http://foo/?q"] &&
	    [[[OFURL URLWithString: @"foo"
		     relativeToURL: [OFURL URLWithString: @"http://foo/bar"]]
	    string] isEqual: @"http://foo/foo"] &&
	    [[[OFURL URLWithString: @"foo"
		     relativeToURL: [OFURL URLWithString: @"http://foo"]]
	    string] isEqual: @"http://foo/foo"])

	EXPECT_EXCEPTION(
	    @"+[URLWithString:relativeToURL:] fails with invalid characters #1",
	    OFInvalidFormatException,
	    [OFURL URLWithString: @"`" relativeToURL: URL1])

	EXPECT_EXCEPTION(
	    @"+[URLWithString:relativeToURL:] fails with invalid characters #2",
	    OFInvalidFormatException,
	    [OFURL URLWithString: @"/`" relativeToURL: URL1])

	EXPECT_EXCEPTION(
	    @"+[URLWithString:relativeToURL:] fails with invalid characters #3",
	    OFInvalidFormatException,
	    [OFURL URLWithString: @"?`" relativeToURL: URL1])

	EXPECT_EXCEPTION(
	    @"+[URLWithString:relativeToURL:] fails with invalid characters #4",
	    OFInvalidFormatException,
	    [OFURL URLWithString: @"#`" relativeToURL: URL1])

#ifdef OF_HAVE_FILES
	TEST(@"+[fileURLWithPath:]",
	    [[[OFURL fileURLWithPath: @"testfile.txt"] fileSystemRepresentation]
	    isEqual: [[OFFileManager defaultManager].currentDirectoryPath
	    stringByAppendingPathComponent: @"testfile.txt"]])

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
	    [tmp.host isEqual: @"test"] && [tmp.path isEqual: @"/"] &&
	    [tmp.string isEqual: @"file://test/"] &&
	    [tmp.fileSystemRepresentation isEqual: @"\\\\test"])
# endif
#endif

	TEST(@"-[string]",
	    [u1.string isEqual: url_str] &&
	    [u2.string isEqual: @"http://foo:80"] &&
	    [u3.string isEqual: @"http://bar/"] &&
	    [u4.string isEqual: @"file:///etc/passwd"])

	TEST(@"-[scheme]",
	    [u1.scheme isEqual: @"ht:tp"] && [u4.scheme isEqual: @"file"])

	TEST(@"-[user]", [u1.user isEqual: @"us:er"] && u4.user == nil)
	TEST(@"-[password]",
	    [u1.password isEqual: @"p@w"] && u4.password == nil)
	TEST(@"-[host]", [u1.host isEqual: @"ho:st"] &&
	    [u6.host isEqual: @"12:34::56:abcd"] &&
	    [u7.host isEqual: @"12:34::56:abcd"])
	TEST(@"-[port]", u1.port.unsignedShortValue == 1234 &&
	    [u4 port] == nil && u7.port.unsignedShortValue == 234)
	TEST(@"-[path]",

	    [u1.path isEqual: @"/pa?th"] && [u4.path isEqual: @"/etc/passwd"])
	TEST(@"-[pathComponents]",
	    [u1.pathComponents isEqual:
	    [OFArray arrayWithObjects: @"/", @"pa?th", nil]] &&
	    [u4.pathComponents isEqual:
	    [OFArray arrayWithObjects: @"/", @"etc", @"passwd", nil]] &&
	    [u5.pathComponents isEqual:
	    [OFArray arrayWithObjects: @"/", @"bar", @"qux", @"foo/bar", nil]])
	TEST(@"-[lastPathComponent]",
	    [[[OFURL URLWithString: @"http://host/foo//bar/baz"]
	    lastPathComponent] isEqual: @"baz"] &&
	    [[[OFURL URLWithString: @"http://host/foo//bar/baz/"]
	    lastPathComponent] isEqual: @"baz"] &&
	    [[[OFURL URLWithString: @"http://host/foo/"]
	    lastPathComponent] isEqual: @"foo"] &&
	    [[[OFURL URLWithString: @"http://host/"]
	    lastPathComponent] isEqual: @"/"] &&
	    [u5.lastPathComponent isEqual: @"foo/bar"])
	TEST(@"-[query]",
	    [u1.query isEqual: @"que#ry=1&f&oo=b=ar"] && u4.query == nil)
	TEST(@"-[queryDictionary]",
	    [u1.queryDictionary isEqual:
	    [OFDictionary dictionaryWithKeysAndObjects:
	    @"que#ry", @"1", @"f&oo", @"b=ar", nil]]);
	TEST(@"-[fragment]",
	    [u1.fragment isEqual: @"frag#ment"] && u4.fragment == nil)

	TEST(@"-[copy]", R(u4 = [[u1 copy] autorelease]))

	TEST(@"-[isEqual:]", [u1 isEqual: u4] && ![u2 isEqual: u3] &&
	    [[OFURL URLWithString: @"HTTP://bar/"] isEqual: u3])

	TEST(@"-[hash:]", u1.hash == u4.hash && u2.hash != u3.hash)

	EXPECT_EXCEPTION(@"Detection of invalid format",
	    OFInvalidFormatException, [OFURL URLWithString: @"http"])

	mu = [OFMutableURL URL];

	TEST(@"-[setScheme:]",

	    (mu.scheme = @"ht:tp") && [mu.URLEncodedScheme isEqual: @"ht%3Atp"])

	TEST(@"-[setURLEncodedScheme:]",
	    (mu.URLEncodedScheme = @"ht%3Atp") && [mu.scheme isEqual: @"ht:tp"])


	EXPECT_EXCEPTION(
	    @"-[setURLEncodedScheme:] with invalid characters fails",
	    OFInvalidFormatException, mu.URLEncodedScheme = @"~")

	TEST(@"-[setHost:]",

	    (mu.host = @"ho:st") && [mu.URLEncodedHost isEqual: @"ho%3Ast"] &&
	    (mu.host = @"12:34:ab") &&
	    [mu.URLEncodedHost isEqual: @"[12:34:ab]"] &&
	    (mu.host = @"12:34:aB") &&
	    [mu.URLEncodedHost isEqual: @"[12:34:aB]"] &&
	    (mu.host = @"12:34:g") &&
	    [mu.URLEncodedHost isEqual: @"12%3A34%3Ag"])

	TEST(@"-[setURLEncodedHost:]",
	    (mu.URLEncodedHost = @"ho%3Ast") && [mu.host isEqual: @"ho:st"] &&

	    (mu.URLEncodedHost = @"[12:34]") && [mu.host isEqual: @"12:34"] &&

	    (mu.URLEncodedHost = @"[12::ab]") && [mu.host isEqual: @"12::ab"])


	EXPECT_EXCEPTION(@"-[setURLEncodedHost:] with invalid characters fails"
	    " #1", OFInvalidFormatException, mu.URLEncodedHost = @"/")

	EXPECT_EXCEPTION(@"-[setURLEncodedHost:] with invalid characters fails"
	    " #2", OFInvalidFormatException, mu.URLEncodedHost = @"[12:34")


	EXPECT_EXCEPTION(@"-[setURLEncodedHost:] with invalid characters fails"
	    " #3", OFInvalidFormatException, mu.URLEncodedHost = @"[a::g]")


	TEST(@"-[setUser:]",

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

	TEST(@"-[setURLEncodedUser:]",
	    (mu.URLEncodedUser = @"us%3Aer") && [mu.user isEqual: @"us:er"])


	EXPECT_EXCEPTION(@"-[setURLEncodedUser:] with invalid characters fails",
	    OFInvalidFormatException, mu.URLEncodedHost = @"/")

	TEST(@"-[setPassword:]",
	    (mu.password = @"pass:word") &&
	    [mu.URLEncodedPassword isEqual: @"pass%3Aword"])

	TEST(@"-[setURLEncodedPassword:]",
	    (mu.URLEncodedPassword = @"pass%3Aword") &&
	    [mu.password isEqual: @"pass:word"])

	EXPECT_EXCEPTION(
	    @"-[setURLEncodedPassword:] with invalid characters fails",
	    OFInvalidFormatException, mu.URLEncodedPassword = @"/")

	TEST(@"-[setPath:]",

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

	TEST(@"-[setURLEncodedPath:]",
	    (mu.URLEncodedPath = @"pa/th@%3F") && [mu.path isEqual: @"pa/th@?"])


	EXPECT_EXCEPTION(@"-[setURLEncodedPath:] with invalid characters fails",
	    OFInvalidFormatException, mu.URLEncodedPath = @"?")

	TEST(@"-[setQuery:]",
	    (mu.query = @"que/ry?#") &&
	    [mu.URLEncodedQuery isEqual: @"que/ry?%23"])

	TEST(@"-[setURLEncodedQuery:]",
	    (mu.URLEncodedQuery = @"que/ry?%23") &&
	    [mu.query isEqual: @"que/ry?#"])

	EXPECT_EXCEPTION(
	    @"-[setURLEncodedQuery:] with invalid characters fails",
	    OFInvalidFormatException, mu.URLEncodedQuery = @"`")

	TEST(@"-[setQueryDictionary:]",

	    (mu.queryDictionary = [OFDictionary dictionaryWithKeysAndObjects:
	    @"foo&bar", @"baz=qux", @"f=oobar", @"b&azqux", nil]) &&
	    [mu.URLEncodedQuery isEqual:
	    @"foo%26bar=baz%3Dqux&f%3Doobar=b%26azqux"])

	TEST(@"-[setFragment:]",
	    (mu.fragment = @"frag/ment?#") &&
	    [mu.URLEncodedFragment isEqual: @"frag/ment?%23"])

	TEST(@"-[setURLEncodedFragment:]",
	    (mu.URLEncodedFragment = @"frag/ment?%23") &&
	    [mu.fragment isEqual: @"frag/ment?#"])

	EXPECT_EXCEPTION(
	    @"-[setURLEncodedFragment:] with invalid characters fails",
	    OFInvalidFormatException, mu.URLEncodedFragment = @"`")

	TEST(@"-[URLByAppendingPathComponent:isDirectory:]",
	    [[[OFURL URLWithString: @"file:///foo/bar"]
	    URLByAppendingPathComponent: @"qux" isDirectory: false] isEqual:
	    [OFURL URLWithString: @"file:///foo/bar/qux"]] &&
	    [[[OFURL URLWithString: @"file:///foo/bar/"]
	    URLByAppendingPathComponent: @"qux" isDirectory: false] isEqual:







|
|
|
|


|

|

|
|
|
|
|
|

>
|

|

|

|










|

|

|



|

|

|
|

|




|


>
|


|
>



|


>
|
|
|
|
|
|
|


|
>
|
>
|
>


|


|
>


|
>


>
|


|
>


|


|
|


|
|



|


>
|


|
>


|


|
|


|
|



|


>
|

|



|
|


|
|



|







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
	    [tmp.host isEqual: @"test"] && [tmp.path isEqual: @"/"] &&
	    [tmp.string isEqual: @"file://test/"] &&
	    [tmp.fileSystemRepresentation isEqual: @"\\\\test"])
# endif
#endif

	TEST(@"-[string]",
	    [URL1.string isEqual: URLString] &&
	    [URL2.string isEqual: @"http://foo:80"] &&
	    [URL3.string isEqual: @"http://bar/"] &&
	    [URL4.string isEqual: @"file:///etc/passwd"])

	TEST(@"-[scheme]",
	    [URL1.scheme isEqual: @"ht:tp"] && [URL4.scheme isEqual: @"file"])

	TEST(@"-[user]", [URL1.user isEqual: @"us:er"] && URL4.user == nil)
	TEST(@"-[password]",
	    [URL1.password isEqual: @"p@w"] && URL4.password == nil)
	TEST(@"-[host]", [URL1.host isEqual: @"ho:st"] &&
	    [URL6.host isEqual: @"12:34::56:abcd"] &&
	    [URL7.host isEqual: @"12:34::56:abcd"])
	TEST(@"-[port]", URL1.port.unsignedShortValue == 1234 &&
	    [URL4 port] == nil && URL7.port.unsignedShortValue == 234)
	TEST(@"-[path]",
	    [URL1.path isEqual: @"/pa?th"] &&
	    [URL4.path isEqual: @"/etc/passwd"])
	TEST(@"-[pathComponents]",
	    [URL1.pathComponents isEqual:
	    [OFArray arrayWithObjects: @"/", @"pa?th", nil]] &&
	    [URL4.pathComponents isEqual:
	    [OFArray arrayWithObjects: @"/", @"etc", @"passwd", nil]] &&
	    [URL5.pathComponents isEqual:
	    [OFArray arrayWithObjects: @"/", @"bar", @"qux", @"foo/bar", nil]])
	TEST(@"-[lastPathComponent]",
	    [[[OFURL URLWithString: @"http://host/foo//bar/baz"]
	    lastPathComponent] isEqual: @"baz"] &&
	    [[[OFURL URLWithString: @"http://host/foo//bar/baz/"]
	    lastPathComponent] isEqual: @"baz"] &&
	    [[[OFURL URLWithString: @"http://host/foo/"]
	    lastPathComponent] isEqual: @"foo"] &&
	    [[[OFURL URLWithString: @"http://host/"]
	    lastPathComponent] isEqual: @"/"] &&
	    [URL5.lastPathComponent isEqual: @"foo/bar"])
	TEST(@"-[query]",
	    [URL1.query isEqual: @"que#ry=1&f&oo=b=ar"] && URL4.query == nil)
	TEST(@"-[queryDictionary]",
	    [URL1.queryDictionary isEqual:
	    [OFDictionary dictionaryWithKeysAndObjects:
	    @"que#ry", @"1", @"f&oo", @"b=ar", nil]]);
	TEST(@"-[fragment]",
	    [URL1.fragment isEqual: @"frag#ment"] && URL4.fragment == nil)

	TEST(@"-[copy]", R(URL4 = [[URL1 copy] autorelease]))

	TEST(@"-[isEqual:]", [URL1 isEqual: URL4] && ![URL2 isEqual: URL3] &&
	    [[OFURL URLWithString: @"HTTP://bar/"] isEqual: URL3])

	TEST(@"-[hash:]", URL1.hash == URL4.hash && URL2.hash != URL3.hash)

	EXPECT_EXCEPTION(@"Detection of invalid format",
	    OFInvalidFormatException, [OFURL URLWithString: @"http"])

	mutableURL = [OFMutableURL URL];

	TEST(@"-[setScheme:]",
	    (mutableURL.scheme = @"ht:tp") &&
	    [mutableURL.URLEncodedScheme isEqual: @"ht%3Atp"])

	TEST(@"-[setURLEncodedScheme:]",
	    (mutableURL.URLEncodedScheme = @"ht%3Atp") &&
	    [mutableURL.scheme isEqual: @"ht:tp"])

	EXPECT_EXCEPTION(
	    @"-[setURLEncodedScheme:] with invalid characters fails",
	    OFInvalidFormatException, mutableURL.URLEncodedScheme = @"~")

	TEST(@"-[setHost:]",
	    (mutableURL.host = @"ho:st") &&
	    [mutableURL.URLEncodedHost isEqual: @"ho%3Ast"] &&
	    (mutableURL.host = @"12:34:ab") &&
	    [mutableURL.URLEncodedHost isEqual: @"[12:34:ab]"] &&
	    (mutableURL.host = @"12:34:aB") &&
	    [mutableURL.URLEncodedHost isEqual: @"[12:34:aB]"] &&
	    (mutableURL.host = @"12:34:g") &&
	    [mutableURL.URLEncodedHost isEqual: @"12%3A34%3Ag"])

	TEST(@"-[setURLEncodedHost:]",
	    (mutableURL.URLEncodedHost = @"ho%3Ast") &&
	    [mutableURL.host isEqual: @"ho:st"] &&
	    (mutableURL.URLEncodedHost = @"[12:34]") &&
	    [mutableURL.host isEqual: @"12:34"] &&
	    (mutableURL.URLEncodedHost = @"[12::ab]") &&
	    [mutableURL.host isEqual: @"12::ab"])

	EXPECT_EXCEPTION(@"-[setURLEncodedHost:] with invalid characters fails"
	    " #1", OFInvalidFormatException, mutableURL.URLEncodedHost = @"/")

	EXPECT_EXCEPTION(@"-[setURLEncodedHost:] with invalid characters fails"
	    " #2", OFInvalidFormatException,
	    mutableURL.URLEncodedHost = @"[12:34")

	EXPECT_EXCEPTION(@"-[setURLEncodedHost:] with invalid characters fails"
	    " #3", OFInvalidFormatException,
	    mutableURL.URLEncodedHost = @"[a::g]")

	TEST(@"-[setUser:]",
	    (mutableURL.user = @"us:er") &&
	    [mutableURL.URLEncodedUser isEqual: @"us%3Aer"])

	TEST(@"-[setURLEncodedUser:]",
	    (mutableURL.URLEncodedUser = @"us%3Aer") &&
	    [mutableURL.user isEqual: @"us:er"])

	EXPECT_EXCEPTION(@"-[setURLEncodedUser:] with invalid characters fails",
	    OFInvalidFormatException, mutableURL.URLEncodedHost = @"/")

	TEST(@"-[setPassword:]",
	    (mutableURL.password = @"pass:word") &&
	    [mutableURL.URLEncodedPassword isEqual: @"pass%3Aword"])

	TEST(@"-[setURLEncodedPassword:]",
	    (mutableURL.URLEncodedPassword = @"pass%3Aword") &&
	    [mutableURL.password isEqual: @"pass:word"])

	EXPECT_EXCEPTION(
	    @"-[setURLEncodedPassword:] with invalid characters fails",
	    OFInvalidFormatException, mutableURL.URLEncodedPassword = @"/")

	TEST(@"-[setPath:]",
	    (mutableURL.path = @"pa/th@?") &&
	    [mutableURL.URLEncodedPath isEqual: @"pa/th@%3F"])

	TEST(@"-[setURLEncodedPath:]",
	    (mutableURL.URLEncodedPath = @"pa/th@%3F") &&
	    [mutableURL.path isEqual: @"pa/th@?"])

	EXPECT_EXCEPTION(@"-[setURLEncodedPath:] with invalid characters fails",
	    OFInvalidFormatException, mutableURL.URLEncodedPath = @"?")

	TEST(@"-[setQuery:]",
	    (mutableURL.query = @"que/ry?#") &&
	    [mutableURL.URLEncodedQuery isEqual: @"que/ry?%23"])

	TEST(@"-[setURLEncodedQuery:]",
	    (mutableURL.URLEncodedQuery = @"que/ry?%23") &&
	    [mutableURL.query isEqual: @"que/ry?#"])

	EXPECT_EXCEPTION(
	    @"-[setURLEncodedQuery:] with invalid characters fails",
	    OFInvalidFormatException, mutableURL.URLEncodedQuery = @"`")

	TEST(@"-[setQueryDictionary:]",
	    (mutableURL.queryDictionary =
	    [OFDictionary dictionaryWithKeysAndObjects:
	    @"foo&bar", @"baz=qux", @"f=oobar", @"b&azqux", nil]) &&
	    [mutableURL.URLEncodedQuery isEqual:
	    @"foo%26bar=baz%3Dqux&f%3Doobar=b%26azqux"])

	TEST(@"-[setFragment:]",
	    (mutableURL.fragment = @"frag/ment?#") &&
	    [mutableURL.URLEncodedFragment isEqual: @"frag/ment?%23"])

	TEST(@"-[setURLEncodedFragment:]",
	    (mutableURL.URLEncodedFragment = @"frag/ment?%23") &&
	    [mutableURL.fragment isEqual: @"frag/ment?#"])

	EXPECT_EXCEPTION(
	    @"-[setURLEncodedFragment:] with invalid characters fails",
	    OFInvalidFormatException, mutableURL.URLEncodedFragment = @"`")

	TEST(@"-[URLByAppendingPathComponent:isDirectory:]",
	    [[[OFURL URLWithString: @"file:///foo/bar"]
	    URLByAppendingPathComponent: @"qux" isDirectory: false] isEqual:
	    [OFURL URLWithString: @"file:///foo/bar/qux"]] &&
	    [[[OFURL URLWithString: @"file:///foo/bar/"]
	    URLByAppendingPathComponent: @"qux" isDirectory: false] isEqual:

Modified tests/OFValueTests.m from [f7da5ac296] to [f0ec7ac363].

15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

#include "config.h"

#include <string.h>

#import "TestsAppDelegate.h"

static OFString *module = @"OFValue";

@implementation TestsAppDelegate (OFValueTests)
- (void)valueTests
{
	void *pool = objc_autoreleasePoolPush();
	OFRange range = OFRangeMake(1, 64), range2;
	OFPoint point = OFPointMake(1.5f, 3.0f), point2;







|







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

#include "config.h"

#include <string.h>

#import "TestsAppDelegate.h"

static OFString *const module = @"OFValue";

@implementation TestsAppDelegate (OFValueTests)
- (void)valueTests
{
	void *pool = objc_autoreleasePoolPush();
	OFRange range = OFRangeMake(1, 64), range2;
	OFPoint point = OFPointMake(1.5f, 3.0f), point2;

Modified tests/OFWindowsRegistryKeyTests.m from [5df411ba49] to [b3eba3a2d6].

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

#include "config.h"

#import "TestsAppDelegate.h"

static OFString *module = @"OFWindowsRegistryKey";

@implementation TestsAppDelegate (OFWindowsRegistryKeyTests)
- (void)windowsRegistryKeyTests
{
	void *pool = objc_autoreleasePoolPush();
	OFData *data = [OFData dataWithItems: "abcdef" count: 6];
	OFWindowsRegistryKey *softwareKey, *ObjFWKey;
	DWORD type;

	TEST(@"+[OFWindowsRegistryKey classesRootKey]",
	    [OFWindowsRegistryKey classesRootKey])

	TEST(@"+[OFWindowsRegistryKey currentConfigKey]",
	    [OFWindowsRegistryKey currentConfigKey])







|






|







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

#include "config.h"

#import "TestsAppDelegate.h"

static OFString *const module = @"OFWindowsRegistryKey";

@implementation TestsAppDelegate (OFWindowsRegistryKeyTests)
- (void)windowsRegistryKeyTests
{
	void *pool = objc_autoreleasePoolPush();
	OFData *data = [OFData dataWithItems: "abcdef" count: 6];
	OFWindowsRegistryKey *softwareKey, *objFWKey;
	DWORD type;

	TEST(@"+[OFWindowsRegistryKey classesRootKey]",
	    [OFWindowsRegistryKey classesRootKey])

	TEST(@"+[OFWindowsRegistryKey currentConfigKey]",
	    [OFWindowsRegistryKey currentConfigKey])
47
48
49
50
51
52
53
54
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
		   openSubkeyAtPath: @"Software"
	    securityAndAccessRights: KEY_ALL_ACCESS]) &&
	    [[OFWindowsRegistryKey currentUserKey]
		   openSubkeyAtPath: @"nonexistent"
	    securityAndAccessRights: KEY_ALL_ACCESS] == nil)

	TEST(@"-[createSubkeyAtPath:securityAndAccessRights:]",
	    (ObjFWKey = [softwareKey createSubkeyAtPath: @"ObjFW"
				securityAndAccessRights: KEY_ALL_ACCESS]))

	TEST(@"-[setData:forValueNamed:type:]",
	    R([ObjFWKey setData: data forValueNamed: @"data" type: REG_BINARY]))

	TEST(@"-[dataForValueNamed:subkeyPath:flags:type:]",
	    [[ObjFWKey dataForValueNamed: @"data" type: &type] isEqual: data] &&
	    type == REG_BINARY)

	TEST(@"-[setString:forValueNamed:type:]",
	    R([ObjFWKey setString: @"foobar" forValueNamed: @"string"]) &&
	    R([ObjFWKey setString: @"%PATH%;foo"
		    forValueNamed: @"expand"
			     type: REG_EXPAND_SZ]))

	TEST(@"-[stringForValue:subkeyPath:]",
	    [[ObjFWKey stringForValueNamed: @"string"] isEqual: @"foobar"] &&
	    [[ObjFWKey stringForValueNamed: @"expand" type: &type]
	    isEqual: @"%PATH%;foo"] &&
	    type == REG_EXPAND_SZ)

	TEST(@"-[deleteValueNamed:]", R([ObjFWKey deleteValueNamed: @"data"]))

	TEST(@"-[deleteSubkeyAtPath:]",
	    R([softwareKey deleteSubkeyAtPath: @"ObjFW"]))

	objc_autoreleasePoolPop(pool);
}
@end







|



|


|



|
|




|
|



|







47
48
49
50
51
52
53
54
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
		   openSubkeyAtPath: @"Software"
	    securityAndAccessRights: KEY_ALL_ACCESS]) &&
	    [[OFWindowsRegistryKey currentUserKey]
		   openSubkeyAtPath: @"nonexistent"
	    securityAndAccessRights: KEY_ALL_ACCESS] == nil)

	TEST(@"-[createSubkeyAtPath:securityAndAccessRights:]",
	    (objFWKey = [softwareKey createSubkeyAtPath: @"ObjFW"
				securityAndAccessRights: KEY_ALL_ACCESS]))

	TEST(@"-[setData:forValueNamed:type:]",
	    R([objFWKey setData: data forValueNamed: @"data" type: REG_BINARY]))

	TEST(@"-[dataForValueNamed:subkeyPath:flags:type:]",
	    [[objFWKey dataForValueNamed: @"data" type: &type] isEqual: data] &&
	    type == REG_BINARY)

	TEST(@"-[setString:forValueNamed:type:]",
	    R([objFWKey setString: @"foobar" forValueNamed: @"string"]) &&
	    R([objFWKey setString: @"%PATH%;foo"
		    forValueNamed: @"expand"
			     type: REG_EXPAND_SZ]))

	TEST(@"-[stringForValue:subkeyPath:]",
	    [[objFWKey stringForValueNamed: @"string"] isEqual: @"foobar"] &&
	    [[objFWKey stringForValueNamed: @"expand" type: &type]
	    isEqual: @"%PATH%;foo"] &&
	    type == REG_EXPAND_SZ)

	TEST(@"-[deleteValueNamed:]", R([objFWKey deleteValueNamed: @"data"]))

	TEST(@"-[deleteSubkeyAtPath:]",
	    R([softwareKey deleteSubkeyAtPath: @"ObjFW"]))

	objc_autoreleasePoolPop(pool);
}
@end

Modified tests/OFXMLElementBuilderTests.m from [47b293e0e2] to [1ae510b9c5].

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

#include "config.h"

#import "TestsAppDelegate.h"

static OFString *module = @"OFXMLElementBuilder";
static OFXMLNode *nodes[2];
static size_t i = 0;

@implementation TestsAppDelegate (OFXMLElementBuilderTests)
- (void)elementBuilder: (OFXMLElementBuilder *)builder
       didBuildElement: (OFXMLElement *)element
{







|







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

#include "config.h"

#import "TestsAppDelegate.h"

static OFString *const module = @"OFXMLElementBuilder";
static OFXMLNode *nodes[2];
static size_t i = 0;

@implementation TestsAppDelegate (OFXMLElementBuilderTests)
- (void)elementBuilder: (OFXMLElementBuilder *)builder
       didBuildElement: (OFXMLElement *)element
{
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
	OFEnsure(i == 1);
	nodes[i++] = [node retain];
}

- (void)XMLElementBuilderTests
{
	void *pool = objc_autoreleasePoolPush();
	OFXMLParser *p = [OFXMLParser parser];
	OFXMLElementBuilder *builder = [OFXMLElementBuilder builder];
	OFString *str = @"<foo>bar<![CDATA[f<oo]]>baz<qux/>"
	    " <qux xmlns:qux='urn:qux'><?asd?><qux:bar/><x qux:y='z'/></qux>"
	    "</foo>";

	p.delegate = builder;
	builder.delegate = self;

	TEST(@"Building elements from parsed XML",
	    R([p parseString: str]) &&
	    nodes[0] != nil && [nodes[0].XMLString isEqual: str] &&
	    R([p parseString: @"<!--foo-->"]) &&
	    nodes[1] != nil && [nodes[1].XMLString isEqual: @"<!--foo-->"] &&
	    i == 2)

	[nodes[0] release];
	[nodes[1] release];
	objc_autoreleasePoolPop(pool);
}
@end







|

|



|



|
|
|








35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
	OFEnsure(i == 1);
	nodes[i++] = [node retain];
}

- (void)XMLElementBuilderTests
{
	void *pool = objc_autoreleasePoolPush();
	OFXMLParser *parser = [OFXMLParser parser];
	OFXMLElementBuilder *builder = [OFXMLElementBuilder builder];
	OFString *string = @"<foo>bar<![CDATA[f<oo]]>baz<qux/>"
	    " <qux xmlns:qux='urn:qux'><?asd?><qux:bar/><x qux:y='z'/></qux>"
	    "</foo>";

	parser.delegate = builder;
	builder.delegate = self;

	TEST(@"Building elements from parsed XML",
	    R([parser parseString: string]) &&
	    nodes[0] != nil && [nodes[0].XMLString isEqual: string] &&
	    R([parser parseString: @"<!--foo-->"]) &&
	    nodes[1] != nil && [nodes[1].XMLString isEqual: @"<!--foo-->"] &&
	    i == 2)

	[nodes[0] release];
	[nodes[1] release];
	objc_autoreleasePoolPop(pool);
}
@end

Modified tests/OFXMLNodeTests.m from [c231b8bd5e] to [3a041e8eb3].

13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28


29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
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
 * file.
 */

#include "config.h"

#import "TestsAppDelegate.h"

static OFString *module = @"OFXMLNode";

@implementation TestsAppDelegate (OFXMLNodeTests)
- (void)XMLNodeTests
{
	void *pool = objc_autoreleasePoolPush();
	id nodes[4];
	OFArray *a;



	TEST(@"+[elementWithName:]",
	    (nodes[0] = [OFXMLElement elementWithName: @"foo"]) &&
	    [[nodes[0] XMLString] isEqual: @"<foo/>"])

	TEST(@"+[elementWithName:stringValue:]",
	    (nodes[1] = [OFXMLElement elementWithName: @"foo"
					  stringValue: @"b&ar"]) &&
	    [[nodes[1] XMLString] isEqual: @"<foo>b&amp;ar</foo>"])

	TEST(@"+[elementWithName:namespace:]",
	    (nodes[2] = [OFXMLElement elementWithName: @"foo"
					    namespace: @"urn:objfw:test"]) &&
	    R([nodes[2] addAttributeWithName: @"test" stringValue: @"test"]) &&
	    R([nodes[2] setPrefix: @"objfw-test"
		     forNamespace: @"urn:objfw:test"]) &&
	    [[nodes[2] XMLString] isEqual: @"<objfw-test:foo test='test'/>"] &&
	    (nodes[3] = [OFXMLElement elementWithName: @"foo"
					    namespace: @"urn:objfw:test"]) &&
	    R([nodes[3] addAttributeWithName: @"test" stringValue: @"test"]) &&
	    [[nodes[3] XMLString] isEqual:
	    @"<foo xmlns='urn:objfw:test' test='test'/>"])

	TEST(@"+[elementWithName:namespace:stringValue:]",
	    (nodes[3] = [OFXMLElement elementWithName: @"foo"
					    namespace: @"urn:objfw:test"
					  stringValue: @"x"]) &&
	    R([nodes[3] setPrefix: @"objfw-test"
		     forNamespace: @"urn:objfw:test"]) &&
	    [[nodes[3] XMLString] isEqual:
	    @"<objfw-test:foo>x</objfw-test:foo>"])

	TEST(@"+[charactersWithString:]",
	    (nodes[3] = [OFXMLCharacters charactersWithString: @"<foo>"]) &&
	    [[nodes[3] XMLString] isEqual: @"&lt;foo&gt;"])

	TEST(@"+[CDATAWithString:]",
	    (nodes[3] = [OFXMLCDATA CDATAWithString: @"<foo>"]) &&
	    [[nodes[3] XMLString] isEqual: @"<![CDATA[<foo>]]>"]);

	TEST(@"+[commentWithText:]",
	    (nodes[3] = [OFXMLComment commentWithText: @" comment "]) &&
	    [[nodes[3] XMLString] isEqual: @"<!-- comment -->"])

	module = @"OFXMLElement";

	TEST(@"-[addAttributeWithName:stringValue:]",
	    R([nodes[0] addAttributeWithName: @"foo" stringValue: @"b&ar"]) &&
	    [[nodes[0] XMLString] isEqual: @"<foo foo='b&amp;ar'/>"] &&
	    R([nodes[1] addAttributeWithName: @"foo" stringValue: @"b&ar"]) &&
	    [[nodes[1] XMLString] isEqual:
	    @"<foo foo='b&amp;ar'>b&amp;ar</foo>"])

	TEST(@"-[setPrefix:forNamespace:]",
	    R([nodes[1] setPrefix: @"objfw-test"
		     forNamespace: @"urn:objfw:test"]))

	TEST(@"-[addAttributeWithName:namespace:stringValue:]",
	    R([nodes[1] addAttributeWithName: @"foo"
				   namespace: @"urn:objfw:test"
				 stringValue: @"bar"]) &&
	    R([nodes[1] addAttributeWithName: @"foo"
				   namespace: @"urn:objfw:test"
				 stringValue: @"ignored"]) &&
	    [[nodes[1] XMLString] isEqual:
	    @"<foo foo='b&amp;ar' objfw-test:foo='bar'>b&amp;ar</foo>"])

	TEST(@"-[removeAttributeForName:namespace:]",
	    R([nodes[1] removeAttributeForName: @"foo"]) &&
	    [[nodes[1] XMLString] isEqual:
	    @"<foo objfw-test:foo='bar'>b&amp;ar</foo>"] &&
	    R([nodes[1] removeAttributeForName: @"foo"
				     namespace: @"urn:objfw:test"]) &&
	    [[nodes[1] XMLString] isEqual: @"<foo>b&amp;ar</foo>"])

	TEST(@"-[addChild:]",
	    R([nodes[0] addChild: [OFXMLElement elementWithName: @"bar"]]) &&
	    [[nodes[0] XMLString] isEqual:
	    @"<foo foo='b&amp;ar'><bar/></foo>"] &&
	    R([nodes[2] addChild: [OFXMLElement elementWithName: @"bar"
		       namespace: @"urn:objfw:test"]]) &&
	    [[nodes[2] XMLString] isEqual:
	    @"<objfw-test:foo test='test'><objfw-test:bar/></objfw-test:foo>"])

	TEST(@"+[elementWithXMLString:] and -[stringValue]",
	    [[[OFXMLElement elementWithXMLString:
	    @"<?xml version='1.0' encoding='UTF-8'?>\r\n<x>foo<![CDATA[bar]]>"
	    @"<y>b<!-- fooo -->az</y>qux</x>"] stringValue]
	    isEqual: @"foobarbazqux"])

	TEST(@"-[elementsForName:namespace:]",
	    (a = [nodes[2] elementsForName: @"bar"
				 namespace: @"urn:objfw:test"]) &&
	    a.count == 1 && [[[a firstObject] XMLString] isEqual:
	    @"<bar xmlns='urn:objfw:test'/>"])

	TEST(@"-[isEqual:]",
	    [[OFXMLElement elementWithXMLString: @"<foo bar='asd'/>"] isEqual:
	    [OFXMLElement elementWithXMLString: @"<foo bar='asd'></foo>"]] &&
	    [[OFXMLElement elementWithXMLString: @"<x><y/></x>"] isEqual:
	    [OFXMLElement elementWithXMLString: @"<x><y></y></x>"]])







|





|
|

>
>

|
|


|
|
|


|
|
|
|
|
|
|
|
|
|



|
|
|
|
|
<
|


|
|


|
|


|
|




|
|
|
<
|


|
|


|
|
|
|
|
|
|



|
|

|
|
|


|
|

|
|
|









|
|
|







13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
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
 * file.
 */

#include "config.h"

#import "TestsAppDelegate.h"

static OFString *module;

@implementation TestsAppDelegate (OFXMLNodeTests)
- (void)XMLNodeTests
{
	void *pool = objc_autoreleasePoolPush();
	id node1, node2, node3, node4;
	OFArray *array;

	module = @"OFXMLNode";

	TEST(@"+[elementWithName:]",
	    (node1 = [OFXMLElement elementWithName: @"foo"]) &&
	    [[node1 XMLString] isEqual: @"<foo/>"])

	TEST(@"+[elementWithName:stringValue:]",
	    (node2 = [OFXMLElement elementWithName: @"foo"
				       stringValue: @"b&ar"]) &&
	    [[node2 XMLString] isEqual: @"<foo>b&amp;ar</foo>"])

	TEST(@"+[elementWithName:namespace:]",
	    (node3 = [OFXMLElement elementWithName: @"foo"
					 namespace: @"urn:objfw:test"]) &&
	    R([node3 addAttributeWithName: @"test" stringValue: @"test"]) &&
	    R([node3 setPrefix: @"objfw-test"
		  forNamespace: @"urn:objfw:test"]) &&
	    [[node3 XMLString] isEqual: @"<objfw-test:foo test='test'/>"] &&
	    (node4 = [OFXMLElement elementWithName: @"foo"
					 namespace: @"urn:objfw:test"]) &&
	    R([node4 addAttributeWithName: @"test" stringValue: @"test"]) &&
	    [[node4 XMLString] isEqual:
	    @"<foo xmlns='urn:objfw:test' test='test'/>"])

	TEST(@"+[elementWithName:namespace:stringValue:]",
	    (node4 = [OFXMLElement elementWithName: @"foo"
					 namespace: @"urn:objfw:test"
				       stringValue: @"x"]) &&
	    R([node4 setPrefix: @"objfw-test"
		  forNamespace: @"urn:objfw:test"]) &&

	    [[node4 XMLString] isEqual: @"<objfw-test:foo>x</objfw-test:foo>"])

	TEST(@"+[charactersWithString:]",
	    (node4 = [OFXMLCharacters charactersWithString: @"<foo>"]) &&
	    [[node4 XMLString] isEqual: @"&lt;foo&gt;"])

	TEST(@"+[CDATAWithString:]",
	    (node4 = [OFXMLCDATA CDATAWithString: @"<foo>"]) &&
	    [[node4 XMLString] isEqual: @"<![CDATA[<foo>]]>"]);

	TEST(@"+[commentWithText:]",
	    (node4 = [OFXMLComment commentWithText: @" comment "]) &&
	    [[node4 XMLString] isEqual: @"<!-- comment -->"])

	module = @"OFXMLElement";

	TEST(@"-[addAttributeWithName:stringValue:]",
	    R([node1 addAttributeWithName: @"foo" stringValue: @"b&ar"]) &&
	    [[node1 XMLString] isEqual: @"<foo foo='b&amp;ar'/>"] &&
	    R([node2 addAttributeWithName: @"foo" stringValue: @"b&ar"]) &&

	    [[node2 XMLString] isEqual: @"<foo foo='b&amp;ar'>b&amp;ar</foo>"])

	TEST(@"-[setPrefix:forNamespace:]",
	    R([node2 setPrefix: @"objfw-test"
		  forNamespace: @"urn:objfw:test"]))

	TEST(@"-[addAttributeWithName:namespace:stringValue:]",
	    R([node2 addAttributeWithName: @"foo"
				namespace: @"urn:objfw:test"
			      stringValue: @"bar"]) &&
	    R([node2 addAttributeWithName: @"foo"
				namespace: @"urn:objfw:test"
			      stringValue: @"ignored"]) &&
	    [[node2 XMLString] isEqual:
	    @"<foo foo='b&amp;ar' objfw-test:foo='bar'>b&amp;ar</foo>"])

	TEST(@"-[removeAttributeForName:namespace:]",
	    R([node2 removeAttributeForName: @"foo"]) &&
	    [[node2 XMLString] isEqual:
	    @"<foo objfw-test:foo='bar'>b&amp;ar</foo>"] &&
	    R([node2 removeAttributeForName: @"foo"
				  namespace: @"urn:objfw:test"]) &&
	    [[node2 XMLString] isEqual: @"<foo>b&amp;ar</foo>"])

	TEST(@"-[addChild:]",
	    R([node1 addChild: [OFXMLElement elementWithName: @"bar"]]) &&
	    [[node1 XMLString] isEqual:
	    @"<foo foo='b&amp;ar'><bar/></foo>"] &&
	    R([node3 addChild: [OFXMLElement elementWithName: @"bar"
		    namespace: @"urn:objfw:test"]]) &&
	    [[node3 XMLString] isEqual:
	    @"<objfw-test:foo test='test'><objfw-test:bar/></objfw-test:foo>"])

	TEST(@"+[elementWithXMLString:] and -[stringValue]",
	    [[[OFXMLElement elementWithXMLString:
	    @"<?xml version='1.0' encoding='UTF-8'?>\r\n<x>foo<![CDATA[bar]]>"
	    @"<y>b<!-- fooo -->az</y>qux</x>"] stringValue]
	    isEqual: @"foobarbazqux"])

	TEST(@"-[elementsForName:namespace:]",
	    (array = [node3 elementsForName: @"bar"
				  namespace: @"urn:objfw:test"]) &&
	    array.count == 1 && [[array.firstObject XMLString] isEqual:
	    @"<bar xmlns='urn:objfw:test'/>"])

	TEST(@"-[isEqual:]",
	    [[OFXMLElement elementWithXMLString: @"<foo bar='asd'/>"] isEqual:
	    [OFXMLElement elementWithXMLString: @"<foo bar='asd'></foo>"]] &&
	    [[OFXMLElement elementWithXMLString: @"<x><y/></x>"] isEqual:
	    [OFXMLElement elementWithXMLString: @"<x><y></y></x>"]])

Modified tests/OFXMLParserTests.m from [20f4783b1c] to [3eb25f939e].

16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51

52
53
54
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
#include "config.h"

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

#import "TestsAppDelegate.h"

static OFString *module = @"OFXMLParser";
static int i = 0;

enum event_type {
	PROCESSING_INSTRUCTION,
	TAG_OPEN,
	TAG_CLOSE,
	STRING,
	CDATA,
	COMMENT
};

@implementation TestsAppDelegate (OFXMLParser)
-   (void)parser: (OFXMLParser *)parser
  didCreateEvent: (enum event_type)type
	    name: (OFString *)name
	  prefix: (OFString *)prefix
       namespace: (OFString *)ns
      attributes: (OFArray *)attrs
	  string: (OFString *)string
{
	OFString *msg;

	i++;
	msg = [OFString stringWithFormat: @"Parsing part #%d", i];

	switch (i) {
	case 1:
		TEST(msg, type == PROCESSING_INSTRUCTION &&

		    [name isEqual: @"xml"] &&
		    [string isEqual: @"version='1.0'"])
		break;
	case 2:
		TEST(msg, type == PROCESSING_INSTRUCTION &&

		    [name isEqual: @"p?i"] && string == nil)
		break;
	case 3:

		TEST(msg, type == TAG_OPEN && [name isEqual: @"root"] &&
		    prefix == nil && ns == nil && attrs.count == 0)
		break;
	case 4:

		TEST(msg, type == STRING && [string isEqual: @"\n\n "])
		break;
	case 5:

		TEST(msg, type == CDATA && [string isEqual: @"f<]]]oo]"] &&
		    parser.lineNumber == 3)
		break;
	case 6:

		TEST(msg, type == TAG_OPEN && [name isEqual: @"bar"] &&
		    prefix == nil && ns == nil && attrs == nil)
		break;
	case 7:

		TEST(msg, type == TAG_CLOSE && [name isEqual: @"bar"] &&
		    prefix == nil && ns == nil && attrs == nil)
		break;
	case 8:

		TEST(msg, type == STRING && [string isEqual: @"\n "])
		break;
	case 9:

		TEST(msg, type == TAG_OPEN && [name isEqual: @"foobar"] &&

		    prefix == nil && [ns isEqual: @"urn:objfw:test:foobar"] &&
		    attrs.count == 1 &&
		    /* xmlns attr */
		    [[[attrs objectAtIndex: 0] name] isEqual: @"xmlns"] &&
		    [[attrs objectAtIndex: 0] namespace] == nil &&
		    [[[attrs objectAtIndex: 0] stringValue] isEqual:
		    @"urn:objfw:test:foobar"])
		break;
	case 10:

		TEST(msg, type == STRING && [string isEqual: @"\n  "])
		break;
	case 11:

		TEST(msg, type == TAG_OPEN && [name isEqual: @"qux"] &&

		    prefix == nil && [ns isEqual: @"urn:objfw:test:foobar"] &&
		    attrs.count == 1 &&
		    /* xmlns:foo attr */
		    [[[attrs objectAtIndex: 0] name] isEqual: @"foo"] &&
		    [[[attrs objectAtIndex: 0] namespace] isEqual:
		    @"http://www.w3.org/2000/xmlns/"] &&
		    [[[attrs objectAtIndex: 0] stringValue] isEqual:
		    @"urn:objfw:test:foo"])
		break;
	case 12:

		TEST(msg, type == STRING && [string isEqual: @"\n   "])
		break;
	case 13:

		TEST(msg, type == TAG_OPEN && [name isEqual: @"bla"] &&
		    [prefix isEqual: @"foo"] &&
		    [ns isEqual: @"urn:objfw:test:foo"] &&
		    attrs.count == 2 &&
		    /* foo:bla attr */
		    [[[attrs objectAtIndex: 0] name] isEqual: @"bla"] &&
		    [[[attrs objectAtIndex: 0] namespace] isEqual:
		    @"urn:objfw:test:foo"] &&
		    [[[attrs objectAtIndex: 0] stringValue] isEqual: @"bla"] &&
		    /* blafoo attr */
		    [[[attrs objectAtIndex: 1] name] isEqual: @"blafoo"] &&
		    [[attrs objectAtIndex: 1] namespace] == nil &&
		    [[[attrs objectAtIndex: 1] stringValue] isEqual: @"foo"])
		break;
	case 14:

		TEST(msg, type == STRING && [string isEqual: @"\n    "])
		break;
	case 15:

		TEST(msg, type == TAG_OPEN && [name isEqual: @"blup"] &&

		    prefix == nil && [ns isEqual: @"urn:objfw:test:foobar"] &&
		    attrs.count == 2 &&
		    /* foo:qux attr */
		    [[[attrs objectAtIndex: 0] name] isEqual: @"qux"] &&
		    [[[attrs objectAtIndex: 0] namespace] isEqual:
		    @"urn:objfw:test:foo"] &&
		    [[[attrs objectAtIndex: 0] stringValue] isEqual: @"asd"] &&
		    /* quxqux attr */
		    [[[attrs objectAtIndex: 1] name] isEqual: @"quxqux"] &&
		    [[attrs objectAtIndex: 1] namespace] == nil &&
		    [[[attrs objectAtIndex: 1] stringValue] isEqual: @"test"])
		break;
	case 16:

		TEST(msg, type == TAG_CLOSE && [name isEqual: @"blup"] &&

		    prefix == nil && [ns isEqual: @"urn:objfw:test:foobar"])
		break;
	case 17:

		TEST(msg, type == STRING && [string isEqual: @"\n    "])
		break;
	case 18:

		TEST(msg, type == TAG_OPEN && [name isEqual: @"bla"] &&
		    [prefix isEqual: @"bla"] &&
		    [ns isEqual: @"urn:objfw:test:bla"] && attrs.count == 3 &&

		    /* xmlns:bla attr */
		    [[[attrs objectAtIndex: 0] name] isEqual: @"bla"] &&
		    [[[attrs objectAtIndex: 0] namespace] isEqual:
		    @"http://www.w3.org/2000/xmlns/"] &&
		    [[[attrs objectAtIndex: 0] stringValue] isEqual:
		    @"urn:objfw:test:bla"] &&
		    /* qux attr */
		    [[[attrs objectAtIndex: 1] name] isEqual: @"qux"] &&
		    [[attrs objectAtIndex: 1] namespace] == nil &&
		    [[[attrs objectAtIndex: 1] stringValue] isEqual: @"qux"] &&
		    /* bla:foo attr */
		    [[[attrs objectAtIndex: 2] name] isEqual: @"foo"] &&
		    [[[attrs objectAtIndex: 2] namespace] isEqual:
		    @"urn:objfw:test:bla"] &&
		    [[[attrs objectAtIndex: 2] stringValue] isEqual: @"blafoo"])
		break;
	case 19:

		TEST(msg, type == TAG_CLOSE && [name isEqual: @"bla"] &&
		    [prefix isEqual: @"bla"] &&
		    [ns isEqual: @"urn:objfw:test:bla"])
		break;
	case 20:

		TEST(msg, type == STRING && [string isEqual: @"\n    "])
		break;
	case 21:

		TEST(msg, type == TAG_OPEN && [name isEqual: @"abc"] &&

		    prefix == nil && [ns isEqual: @"urn:objfw:test:abc"] &&
		    attrs.count == 3 &&
		    /* xmlns attr */
		    [[[attrs objectAtIndex: 0] name] isEqual: @"xmlns"] &&
		    [[attrs objectAtIndex: 0] namespace] == nil &&
		    [[[attrs objectAtIndex: 0] stringValue] isEqual:
		    @"urn:objfw:test:abc"] &&
		    /* abc attr */
		    [[[attrs objectAtIndex: 1] name] isEqual: @"abc"] &&
		    [[attrs objectAtIndex: 1] namespace] == nil &&
		    [[[attrs objectAtIndex: 1] stringValue] isEqual: @"abc"] &&
		    /* foo:abc attr */
		    [[[attrs objectAtIndex: 2] name] isEqual: @"abc"] &&
		    [[[attrs objectAtIndex: 2] namespace] isEqual:
		    @"urn:objfw:test:foo"] &&
		    [[[attrs objectAtIndex: 2] stringValue] isEqual: @"abc"])
		break;
	case 22:

		TEST(msg, type == TAG_CLOSE && [name isEqual: @"abc"] &&
		    prefix == nil && [ns isEqual: @"urn:objfw:test:abc"])
		break;
	case 23:

		TEST(msg, type == STRING && [string isEqual: @"\n   "])
		break;
	case 24:

		TEST(msg, type == TAG_CLOSE && [name isEqual: @"bla"] &&
		    [prefix isEqual: @"foo"] &&
		    [ns isEqual: @"urn:objfw:test:foo"])
		break;
	case 25:

		TEST(msg, type == STRING && [string isEqual: @"\n   "])
		break;
	case 26:

		TEST(msg, type == COMMENT && [string isEqual: @" commänt "])
		break;
	case 27:

		TEST(msg, type == STRING && [string isEqual: @"\n  "])
		break;
	case 28:

		TEST(msg, type == TAG_CLOSE && [name isEqual: @"qux"] &&

		    prefix == nil && [ns isEqual: @"urn:objfw:test:foobar"])
		break;
	case 29:

		TEST(msg, type == STRING && [string isEqual: @"\n "])
		break;
	case 30:

		TEST(msg, type == TAG_CLOSE && [name isEqual: @"foobar"] &&

		    prefix == nil && [ns isEqual: @"urn:objfw:test:foobar"])
		break;
	case 31:

		TEST(msg, type == STRING && [string isEqual: @"\n"])
		break;
	case 32:

		TEST(msg, type == TAG_CLOSE && [name isEqual: @"root"] &&
		    prefix == nil && ns == nil);
		break;
	}
}

-			  (void)parser: (OFXMLParser *)parser
  foundProcessingInstructionWithTarget: (OFString *)target
				  data: (OFString *)data
{
	[self	    parser: parser
	    didCreateEvent: PROCESSING_INSTRUCTION
		      name: target
		    prefix: nil
		 namespace: nil
		attributes: nil
		    string: data];
}

-    (void)parser: (OFXMLParser *)parser
  didStartElement: (OFString *)name
	   prefix: (OFString *)prefix
	namespace: (OFString *)ns
       attributes: (OFArray *)attrs
{
	[self	    parser: parser
	    didCreateEvent: TAG_OPEN
		      name: name
		    prefix: prefix
		 namespace: ns
		attributes: attrs
		    string: nil];
}

-  (void)parser: (OFXMLParser *)parser
  didEndElement: (OFString *)name
	 prefix: (OFString *)prefix
      namespace: (OFString *)ns
{
	[self	    parser: parser
	    didCreateEvent: TAG_CLOSE
		      name: name
		    prefix: prefix
		 namespace: ns
		attributes: nil
		    string: nil];
}

- (void)parser: (OFXMLParser *)parser foundCharacters: (OFString *)string
{
	[self	    parser: parser
	    didCreateEvent: STRING
		      name: nil
		    prefix: nil
		 namespace: nil
		attributes: nil
		    string: string];
}

- (void)parser: (OFXMLParser *)parser foundCDATA: (OFString *)cdata
{
	[self	    parser: parser
	    didCreateEvent: CDATA
		      name: nil
		    prefix: nil
		 namespace: nil
		attributes: nil
		    string: cdata];
}

- (void)parser: (OFXMLParser *)parser foundComment: (OFString *)comment
{
	[self	    parser: parser
	    didCreateEvent: COMMENT
		      name: nil
		    prefix: nil
		 namespace: nil
		attributes: nil
		    string: comment];
}

-      (OFString *)parser: (OFXMLParser *)parser
  foundUnknownEntityNamed: (OFString *)entity
{
	if ([entity isEqual: @"foo"])
		return @"foobar";

	return nil;
}

- (void)XMLParserTests
{
	void *pool = objc_autoreleasePoolPush();
	const char *str = "\xEF\xBB\xBF<?xml version='1.0'?><?p?i?>"
	    "<!DOCTYPE foo><root>\r\r"
	    " <![CDATA[f<]]]oo]]]><bar/>\n"
	    " <foobar xmlns='urn:objfw:test:foobar'>\r\n"
	    "  <qux xmlns:foo='urn:objfw:test:foo'>\n"
	    "   <foo:bla foo:bla = '&#x62;&#x6c;&#x61;' blafoo='foo'>\n"
	    "    <blup foo:qux='asd' quxqux='test'/>\n"
	    "    <bla:bla\r\rxmlns:bla\r=\t\"urn:objfw:test:bla\" qux='qux'\r\n"
	    "     bla:foo='blafoo'/>\n"
	    "    <abc xmlns='urn:objfw:test:abc' abc='abc' foo:abc='abc'/>\n"
	    "   </foo:bla>\n"
	    "   <!-- commänt -->\n"
	    "  </qux>\n"
	    " </foobar>\n"
	    "</root>";
	OFXMLParser *parser;
	size_t j, len;

	TEST(@"+[parser]", (parser = [OFXMLParser parser]))

	TEST(@"-[setDelegate:]", (parser.delegate = self))

	/* Simulate a stream where we only get chunks */
	len = strlen(str);

	for (j = 0; j < len; j+= 2) {
		if (parser.hasFinishedParsing)
			abort();

		if (j + 2 > len)
			[parser parseBuffer: str + j length: 1];
		else
			[parser parseBuffer: str + j length: 2];
	}

	TEST(@"Checking if everything was parsed",
	    i == 32 && parser.lineNumber == 18)

	TEST(@"-[hasFinishedParsing]", parser.hasFinishedParsing)








|


|
|
|
|
|
|
|




|


|



|


|



|
>




|
>



>
|
|


>
|


>
|



>
|
|


>
|
|


>
|


>
|
>
|








>
|


>
|
>
|









>
|


>
|

|












>
|


>
|
>
|












>
|
>
|


>
|


>
|

|
>

















>
|

|


>
|


>
|
>
|

















>
|
|


>
|


>
|

|


>
|


>
|


>
|


>
|
>
|


>
|


>
|
>
|


>
|


>
|
|









|










|



|


|







|


|


|







|







|


|




|





|



















|















|






|

|



|
|

|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
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
#include "config.h"

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

#import "TestsAppDelegate.h"

static OFString *const module = @"OFXMLParser";
static int i = 0;

enum EventType {
	eventTypeProcessingInstruction,
	eventTypeTagOpen,
	eventTypeTagClose,
	eventTypeString,
	eventTypeCDATA,
	eventTypeComment
};

@implementation TestsAppDelegate (OFXMLParser)
-   (void)parser: (OFXMLParser *)parser
  didCreateEvent: (enum EventType)type
	    name: (OFString *)name
	  prefix: (OFString *)prefix
       namespace: (OFString *)namespace
      attributes: (OFArray *)attrs
	  string: (OFString *)string
{
	OFString *message;

	i++;
	message = [OFString stringWithFormat: @"Parsing part #%d", i];

	switch (i) {
	case 1:
		TEST(message,
		    type == eventTypeProcessingInstruction &&
		    [name isEqual: @"xml"] &&
		    [string isEqual: @"version='1.0'"])
		break;
	case 2:
		TEST(message,
		    type == eventTypeProcessingInstruction &&
		    [name isEqual: @"p?i"] && string == nil)
		break;
	case 3:
		TEST(message,
		    type == eventTypeTagOpen && [name isEqual: @"root"] &&
		    prefix == nil && namespace == nil && attrs.count == 0)
		break;
	case 4:
		TEST(message,
		    type == eventTypeString && [string isEqual: @"\n\n "])
		break;
	case 5:
		TEST(message,
		    type == eventTypeCDATA && [string isEqual: @"f<]]]oo]"] &&
		    parser.lineNumber == 3)
		break;
	case 6:
		TEST(message,
		    type == eventTypeTagOpen && [name isEqual: @"bar"] &&
		    prefix == nil && namespace == nil && attrs == nil)
		break;
	case 7:
		TEST(message,
		    type == eventTypeTagClose && [name isEqual: @"bar"] &&
		    prefix == nil && namespace == nil && attrs == nil)
		break;
	case 8:
		TEST(message,
		    type == eventTypeString && [string isEqual: @"\n "])
		break;
	case 9:
		TEST(message,
		    type == eventTypeTagOpen && [name isEqual: @"foobar"] &&
		    prefix == nil &&
		    [namespace isEqual: @"urn:objfw:test:foobar"] &&
		    attrs.count == 1 &&
		    /* xmlns attr */
		    [[[attrs objectAtIndex: 0] name] isEqual: @"xmlns"] &&
		    [[attrs objectAtIndex: 0] namespace] == nil &&
		    [[[attrs objectAtIndex: 0] stringValue] isEqual:
		    @"urn:objfw:test:foobar"])
		break;
	case 10:
		TEST(message,
		    type == eventTypeString && [string isEqual: @"\n  "])
		break;
	case 11:
		TEST(message,
		    type == eventTypeTagOpen && [name isEqual: @"qux"] &&
		    prefix == nil &&
		    [namespace isEqual: @"urn:objfw:test:foobar"] &&
		    attrs.count == 1 &&
		    /* xmlns:foo attr */
		    [[[attrs objectAtIndex: 0] name] isEqual: @"foo"] &&
		    [[[attrs objectAtIndex: 0] namespace] isEqual:
		    @"http://www.w3.org/2000/xmlns/"] &&
		    [[[attrs objectAtIndex: 0] stringValue] isEqual:
		    @"urn:objfw:test:foo"])
		break;
	case 12:
		TEST(message,
		    type == eventTypeString && [string isEqual: @"\n   "])
		break;
	case 13:
		TEST(message,
		    type == eventTypeTagOpen && [name isEqual: @"bla"] &&
		    [prefix isEqual: @"foo"] &&
		    [namespace isEqual: @"urn:objfw:test:foo"] &&
		    attrs.count == 2 &&
		    /* foo:bla attr */
		    [[[attrs objectAtIndex: 0] name] isEqual: @"bla"] &&
		    [[[attrs objectAtIndex: 0] namespace] isEqual:
		    @"urn:objfw:test:foo"] &&
		    [[[attrs objectAtIndex: 0] stringValue] isEqual: @"bla"] &&
		    /* blafoo attr */
		    [[[attrs objectAtIndex: 1] name] isEqual: @"blafoo"] &&
		    [[attrs objectAtIndex: 1] namespace] == nil &&
		    [[[attrs objectAtIndex: 1] stringValue] isEqual: @"foo"])
		break;
	case 14:
		TEST(message,
		    type == eventTypeString && [string isEqual: @"\n    "])
		break;
	case 15:
		TEST(message,
		    type == eventTypeTagOpen && [name isEqual: @"blup"] &&
		    prefix == nil &&
		    [namespace isEqual: @"urn:objfw:test:foobar"] &&
		    attrs.count == 2 &&
		    /* foo:qux attr */
		    [[[attrs objectAtIndex: 0] name] isEqual: @"qux"] &&
		    [[[attrs objectAtIndex: 0] namespace] isEqual:
		    @"urn:objfw:test:foo"] &&
		    [[[attrs objectAtIndex: 0] stringValue] isEqual: @"asd"] &&
		    /* quxqux attr */
		    [[[attrs objectAtIndex: 1] name] isEqual: @"quxqux"] &&
		    [[attrs objectAtIndex: 1] namespace] == nil &&
		    [[[attrs objectAtIndex: 1] stringValue] isEqual: @"test"])
		break;
	case 16:
		TEST(message,
		    type == eventTypeTagClose && [name isEqual: @"blup"] &&
		    prefix == nil &&
		    [namespace isEqual: @"urn:objfw:test:foobar"])
		break;
	case 17:
		TEST(message,
		    type == eventTypeString && [string isEqual: @"\n    "])
		break;
	case 18:
		TEST(message,
		    type == eventTypeTagOpen && [name isEqual: @"bla"] &&
		    [prefix isEqual: @"bla"] &&
		    [namespace isEqual: @"urn:objfw:test:bla"] &&
		    attrs.count == 3 &&
		    /* xmlns:bla attr */
		    [[[attrs objectAtIndex: 0] name] isEqual: @"bla"] &&
		    [[[attrs objectAtIndex: 0] namespace] isEqual:
		    @"http://www.w3.org/2000/xmlns/"] &&
		    [[[attrs objectAtIndex: 0] stringValue] isEqual:
		    @"urn:objfw:test:bla"] &&
		    /* qux attr */
		    [[[attrs objectAtIndex: 1] name] isEqual: @"qux"] &&
		    [[attrs objectAtIndex: 1] namespace] == nil &&
		    [[[attrs objectAtIndex: 1] stringValue] isEqual: @"qux"] &&
		    /* bla:foo attr */
		    [[[attrs objectAtIndex: 2] name] isEqual: @"foo"] &&
		    [[[attrs objectAtIndex: 2] namespace] isEqual:
		    @"urn:objfw:test:bla"] &&
		    [[[attrs objectAtIndex: 2] stringValue] isEqual: @"blafoo"])
		break;
	case 19:
		TEST(message,
		    type == eventTypeTagClose && [name isEqual: @"bla"] &&
		    [prefix isEqual: @"bla"] &&
		    [namespace isEqual: @"urn:objfw:test:bla"])
		break;
	case 20:
		TEST(message,
		    type == eventTypeString && [string isEqual: @"\n    "])
		break;
	case 21:
		TEST(message,
		    type == eventTypeTagOpen && [name isEqual: @"abc"] &&
		    prefix == nil &&
		    [namespace isEqual: @"urn:objfw:test:abc"] &&
		    attrs.count == 3 &&
		    /* xmlns attr */
		    [[[attrs objectAtIndex: 0] name] isEqual: @"xmlns"] &&
		    [[attrs objectAtIndex: 0] namespace] == nil &&
		    [[[attrs objectAtIndex: 0] stringValue] isEqual:
		    @"urn:objfw:test:abc"] &&
		    /* abc attr */
		    [[[attrs objectAtIndex: 1] name] isEqual: @"abc"] &&
		    [[attrs objectAtIndex: 1] namespace] == nil &&
		    [[[attrs objectAtIndex: 1] stringValue] isEqual: @"abc"] &&
		    /* foo:abc attr */
		    [[[attrs objectAtIndex: 2] name] isEqual: @"abc"] &&
		    [[[attrs objectAtIndex: 2] namespace] isEqual:
		    @"urn:objfw:test:foo"] &&
		    [[[attrs objectAtIndex: 2] stringValue] isEqual: @"abc"])
		break;
	case 22:
		TEST(message,
		    type == eventTypeTagClose && [name isEqual: @"abc"] &&
		    prefix == nil && [namespace isEqual: @"urn:objfw:test:abc"])
		break;
	case 23:
		TEST(message,
		    type == eventTypeString && [string isEqual: @"\n   "])
		break;
	case 24:
		TEST(message,
		    type == eventTypeTagClose && [name isEqual: @"bla"] &&
		    [prefix isEqual: @"foo"] &&
		    [namespace isEqual: @"urn:objfw:test:foo"])
		break;
	case 25:
		TEST(message,
		    type == eventTypeString && [string isEqual: @"\n   "])
		break;
	case 26:
		TEST(message,
		    type == eventTypeComment && [string isEqual: @" commänt "])
		break;
	case 27:
		TEST(message,
		    type == eventTypeString && [string isEqual: @"\n  "])
		break;
	case 28:
		TEST(message,
		    type == eventTypeTagClose && [name isEqual: @"qux"] &&
		    prefix == nil &&
		    [namespace isEqual: @"urn:objfw:test:foobar"])
		break;
	case 29:
		TEST(message,
		    type == eventTypeString && [string isEqual: @"\n "])
		break;
	case 30:
		TEST(message,
		    type == eventTypeTagClose && [name isEqual: @"foobar"] &&
		    prefix == nil &&
		    [namespace isEqual: @"urn:objfw:test:foobar"])
		break;
	case 31:
		TEST(message,
		    type == eventTypeString && [string isEqual: @"\n"])
		break;
	case 32:
		TEST(message,
		    type == eventTypeTagClose && [name isEqual: @"root"] &&
		    prefix == nil && namespace == nil);
		break;
	}
}

-			  (void)parser: (OFXMLParser *)parser
  foundProcessingInstructionWithTarget: (OFString *)target
				  data: (OFString *)data
{
	[self	    parser: parser
	    didCreateEvent: eventTypeProcessingInstruction
		      name: target
		    prefix: nil
		 namespace: nil
		attributes: nil
		    string: data];
}

-    (void)parser: (OFXMLParser *)parser
  didStartElement: (OFString *)name
	   prefix: (OFString *)prefix
	namespace: (OFString *)namespace
       attributes: (OFArray *)attrs
{
	[self	    parser: parser
	    didCreateEvent: eventTypeTagOpen
		      name: name
		    prefix: prefix
		 namespace: namespace
		attributes: attrs
		    string: nil];
}

-  (void)parser: (OFXMLParser *)parser
  didEndElement: (OFString *)name
	 prefix: (OFString *)prefix
      namespace: (OFString *)namespace
{
	[self	    parser: parser
	    didCreateEvent: eventTypeTagClose
		      name: name
		    prefix: prefix
		 namespace: namespace
		attributes: nil
		    string: nil];
}

- (void)parser: (OFXMLParser *)parser foundCharacters: (OFString *)string
{
	[self	    parser: parser
	    didCreateEvent: eventTypeString
		      name: nil
		    prefix: nil
		 namespace: nil
		attributes: nil
		    string: string];
}

- (void)parser: (OFXMLParser *)parser foundCDATA: (OFString *)CDATA
{
	[self	    parser: parser
	    didCreateEvent: eventTypeCDATA
		      name: nil
		    prefix: nil
		 namespace: nil
		attributes: nil
		    string: CDATA];
}

- (void)parser: (OFXMLParser *)parser foundComment: (OFString *)comment
{
	[self	    parser: parser
	    didCreateEvent: eventTypeComment
		      name: nil
		    prefix: nil
		 namespace: nil
		attributes: nil
		    string: comment];
}

-      (OFString *)parser: (OFXMLParser *)parser
  foundUnknownEntityNamed: (OFString *)entity
{
	if ([entity isEqual: @"foo"])
		return @"foobar";

	return nil;
}

- (void)XMLParserTests
{
	void *pool = objc_autoreleasePoolPush();
	const char *string = "\xEF\xBB\xBF<?xml version='1.0'?><?p?i?>"
	    "<!DOCTYPE foo><root>\r\r"
	    " <![CDATA[f<]]]oo]]]><bar/>\n"
	    " <foobar xmlns='urn:objfw:test:foobar'>\r\n"
	    "  <qux xmlns:foo='urn:objfw:test:foo'>\n"
	    "   <foo:bla foo:bla = '&#x62;&#x6c;&#x61;' blafoo='foo'>\n"
	    "    <blup foo:qux='asd' quxqux='test'/>\n"
	    "    <bla:bla\r\rxmlns:bla\r=\t\"urn:objfw:test:bla\" qux='qux'\r\n"
	    "     bla:foo='blafoo'/>\n"
	    "    <abc xmlns='urn:objfw:test:abc' abc='abc' foo:abc='abc'/>\n"
	    "   </foo:bla>\n"
	    "   <!-- commänt -->\n"
	    "  </qux>\n"
	    " </foobar>\n"
	    "</root>";
	OFXMLParser *parser;
	size_t j, length;

	TEST(@"+[parser]", (parser = [OFXMLParser parser]))

	TEST(@"-[setDelegate:]", (parser.delegate = self))

	/* Simulate a stream where we only get chunks */
	length = strlen(string);

	for (j = 0; j < length; j+= 2) {
		if (parser.hasFinishedParsing)
			abort();

		if (j + 2 > length)
			[parser parseBuffer: string + j length: 1];
		else
			[parser parseBuffer: string + j length: 2];
	}

	TEST(@"Checking if everything was parsed",
	    i == 32 && parser.lineNumber == 18)

	TEST(@"-[hasFinishedParsing]", parser.hasFinishedParsing)

Modified tests/RuntimeARCTests.m from [17d2d82f60] to [b48c97e0ac].

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

#include "config.h"

#import "TestsAppDelegate.h"

static OFString *module = @"Runtime (ARC)";

@interface RuntimeARCTest: OFObject
@end

@implementation RuntimeARCTest
- (instancetype)init
{







|







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

#include "config.h"

#import "TestsAppDelegate.h"

static OFString *const module = @"Runtime (ARC)";

@interface RuntimeARCTest: OFObject
@end

@implementation RuntimeARCTest
- (instancetype)init
{

Modified tests/RuntimeTests.m from [60799e33cc] to [20a13fa2e0].

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

#include "config.h"

#import "TestsAppDelegate.h"

static OFString *module = @"Runtime";

@interface OFObject (SuperTest)
- (id)superTest;
@end

@interface RuntimeTest: OFObject
{







|







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

#include "config.h"

#import "TestsAppDelegate.h"

static OFString *const module = @"Runtime";

@interface OFObject (SuperTest)
- (id)superTest;
@end

@interface RuntimeTest: OFObject
{
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
}
@end

@implementation TestsAppDelegate (RuntimeTests)
- (void)runtimeTests
{
	void *pool = objc_autoreleasePoolPush();
	RuntimeTest *rt = [[[RuntimeTest alloc] init] autorelease];
	OFString *t, *foo;
#ifdef OF_OBJFW_RUNTIME
	int cid1, cid2;
	uintmax_t value;
	id object;
#endif

	EXPECT_EXCEPTION(@"Calling a non-existent method via super",
	    OFNotImplementedException, [rt superTest])

	TEST(@"Calling a method via a super with self == nil",
	    [rt nilSuperTest] == nil)

	t = [OFMutableString stringWithString: @"foo"];
	foo = @"foo";

	[rt setFoo: t];
	TEST(@"copy, nonatomic properties", [rt.foo isEqual: foo] &&
	    rt.foo != foo && rt.foo.retainCount == 1)

	rt.bar = t;
	TEST(@"retain, atomic properties", rt.bar == t && t.retainCount == 3)


#ifdef OF_OBJFW_RUNTIME
	if (sizeof(uintptr_t) == 8)
		value = 0xDEADBEEFDEADBEF;
	else if (sizeof(uintptr_t) == 4)
		value = 0xDEADBEF;
	else
		abort();

	TEST(@"Tagged pointers",
	    (cid1 = objc_registerTaggedPointerClass([OFString class])) != -1 &&
	    (cid2 = objc_registerTaggedPointerClass([OFNumber class])) != -1 &&

	    (object = objc_createTaggedPointer(cid2, (uintptr_t)value)) &&
	    object_getClass(object) == [OFNumber class] &&
	    [object class] == [OFNumber class] &&
	    object_getTaggedPointerValue(object) == value &&
	    objc_createTaggedPointer(cid2, UINTPTR_MAX >> 4) != nil &&
	    objc_createTaggedPointer(cid2, (UINTPTR_MAX >> 4) + 1) == nil)
#endif

	objc_autoreleasePoolPop(pool);
}
@end







|
|

|





|


|

|


|
|
|

|
|
>










|
|
>
|



|
|





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
}
@end

@implementation TestsAppDelegate (RuntimeTests)
- (void)runtimeTests
{
	void *pool = objc_autoreleasePoolPush();
	RuntimeTest *test = [[[RuntimeTest alloc] init] autorelease];
	OFString *string, *foo;
#ifdef OF_OBJFW_RUNTIME
	int classID;
	uintmax_t value;
	id object;
#endif

	EXPECT_EXCEPTION(@"Calling a non-existent method via super",
	    OFNotImplementedException, [test superTest])

	TEST(@"Calling a method via a super with self == nil",
	    [test nilSuperTest] == nil)

	string = [OFMutableString stringWithString: @"foo"];
	foo = @"foo";

	test.foo = string;
	TEST(@"copy, nonatomic properties", [test.foo isEqual: foo] &&
	    test.foo != foo && test.foo.retainCount == 1)

	test.bar = string;
	TEST(@"retain, atomic properties",
	    test.bar == string && string.retainCount == 3)

#ifdef OF_OBJFW_RUNTIME
	if (sizeof(uintptr_t) == 8)
		value = 0xDEADBEEFDEADBEF;
	else if (sizeof(uintptr_t) == 4)
		value = 0xDEADBEF;
	else
		abort();

	TEST(@"Tagged pointers",
	    objc_registerTaggedPointerClass([OFString class]) != -1 &&
	    (classID = objc_registerTaggedPointerClass([OFNumber class])) !=
	    -1 &&
	    (object = objc_createTaggedPointer(classID, (uintptr_t)value)) &&
	    object_getClass(object) == [OFNumber class] &&
	    [object class] == [OFNumber class] &&
	    object_getTaggedPointerValue(object) == value &&
	    objc_createTaggedPointer(classID, UINTPTR_MAX >> 4) != nil &&
	    objc_createTaggedPointer(classID, (UINTPTR_MAX >> 4) + 1) == nil)
#endif

	objc_autoreleasePoolPop(pool);
}
@end

Modified tests/TestsAppDelegate.h from [2fa9306569] to [36680e2682].

142
143
144
145
146
147
148




149
150
151
152
153
154
155
@interface TestsAppDelegate (OFNumberTests)
- (void)numberTests;
@end

@interface TestsAppDelegate (OFObjectTests)
- (void)objectTests;
@end





@interface TestsAppDelegate (OFPropertyListTests)
- (void)propertyListTests;
@end

@interface TestsAppDelegate (OFPluginTests)
- (void)pluginTests;







>
>
>
>







142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
@interface TestsAppDelegate (OFNumberTests)
- (void)numberTests;
@end

@interface TestsAppDelegate (OFObjectTests)
- (void)objectTests;
@end

@interface TestsAppDelegate (OFPBKDF2Tests)
- (void)PBKDF2Tests;
@end

@interface TestsAppDelegate (OFPropertyListTests)
- (void)propertyListTests;
@end

@interface TestsAppDelegate (OFPluginTests)
- (void)pluginTests;
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
- (void)runtimeARCTests;
@end

@interface TestsAppDelegate (OFRIPEMD160HashTests)
- (void)RIPEMD160HashTests;
@end

@interface TestsAppDelegate (ScryptTests)
- (void)scryptTests;
@end

@interface TestsAppDelegate (OFSHA1HashTests)
- (void)SHA1HashTests;
@end








|







167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
- (void)runtimeARCTests;
@end

@interface TestsAppDelegate (OFRIPEMD160HashTests)
- (void)RIPEMD160HashTests;
@end

@interface TestsAppDelegate (OFScryptTests)
- (void)scryptTests;
@end

@interface TestsAppDelegate (OFSHA1HashTests)
- (void)SHA1HashTests;
@end

210
211
212
213
214
215
216




217
218
219
220
221
222
223
@interface TestsAppDelegate (OFSystemInfoTests)
- (void)systemInfoTests;
@end

@interface TestsAppDelegate (OFHMACTests)
- (void)HMACTests;
@end





@interface TestsAppDelegate (OFStreamTests)
- (void)streamTests;
@end

@interface TestsAppDelegate (OFStringTests)
- (void)stringTests;







>
>
>
>







214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
@interface TestsAppDelegate (OFSystemInfoTests)
- (void)systemInfoTests;
@end

@interface TestsAppDelegate (OFHMACTests)
- (void)HMACTests;
@end

@interface TestsAppDelegate (OFSocketTests)
- (void)socketTests;
@end

@interface TestsAppDelegate (OFStreamTests)
- (void)streamTests;
@end

@interface TestsAppDelegate (OFStringTests)
- (void)stringTests;
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
- (void)XMLNodeTests;
@end

@interface TestsAppDelegate (OFXMLParserTests)
    <OFXMLParserDelegate, OFXMLElementBuilderDelegate>
- (void)XMLParserTests;
@end

@interface TestsAppDelegate (PBKDF2Tests)
- (void)PBKDF2Tests;
@end

@interface TestsAppDelegate (SocketTests)
- (void)socketTests;
@end







<
<
<
<
<
<
<
<
263
264
265
266
267
268
269








- (void)XMLNodeTests;
@end

@interface TestsAppDelegate (OFXMLParserTests)
    <OFXMLParserDelegate, OFXMLElementBuilderDelegate>
- (void)XMLParserTests;
@end








Modified tests/TestsAppDelegate.m from [0b419cd689] to [1130ab2e6c].

47
48
49
50
51
52
53


54
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
#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_PSP
static int
exit_cb(int arg1, int arg2, void *arg)
{
	sceKernelExitGame();

	return 0;
}

static int
callback_thread(SceSize args, void *argp)
{
	sceKernelRegisterExitCallback(
	    sceKernelCreateCallback("Exit Callback", exit_cb, NULL));
	sceKernelSleepThreadCB();

	return 0;
}
#endif

int
main(int argc, char *argv[])
{
#ifdef OF_PSP
	int tid;
#endif

#if defined(OF_OBJFW_RUNTIME) && !defined(OF_WINDOWS) && !defined(OF_AMIGAOS)
	/*
	 * This does not work on Win32 if ObjFW is built as a DLL.
	 *
	 * On AmigaOS, some destructors need to be able to send messages.
	 * Calling objc_exit() via atexit() would result in the runtime being
	 * destructed before for the destructors ran.
	 */
	atexit(objc_exit);
#endif

	/* We need deterministic hashes for tests */
	OFHashSeed = 0;

#ifdef OF_WII
	GXRModeObj *rmode;







>
>


|







|


|


















|


|







47
48
49
50
51
52
53
54
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
#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

extern unsigned long OFHashSeed;

#ifdef OF_PSP
static int
exitCallback(int arg1, int arg2, void *arg)
{
	sceKernelExitGame();

	return 0;
}

static int
threadCallback(SceSize args, void *argp)
{
	sceKernelRegisterExitCallback(
	    sceKernelCreateCallback("Exit Callback", exitCallback, NULL));
	sceKernelSleepThreadCB();

	return 0;
}
#endif

int
main(int argc, char *argv[])
{
#ifdef OF_PSP
	int tid;
#endif

#if defined(OF_OBJFW_RUNTIME) && !defined(OF_WINDOWS) && !defined(OF_AMIGAOS)
	/*
	 * This does not work on Win32 if ObjFW is built as a DLL.
	 *
	 * On AmigaOS, some destructors need to be able to send messages.
	 * Calling objc_deinit() via atexit() would result in the runtime being
	 * destructed before for the destructors ran.
	 */
	atexit(objc_deinit);
#endif

	/* We need deterministic hashes for tests */
	OFHashSeed = 0;

#ifdef OF_WII
	GXRModeObj *rmode;
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130

#ifdef OF_PSP
	pspDebugScreenInit();

	sceCtrlSetSamplingCycle(0);
	sceCtrlSetSamplingMode(PSP_CTRL_MODE_DIGITAL);

	if ((tid = sceKernelCreateThread("update_thread", callback_thread,
	    0x11, 0xFA0, 0, 0)) >= 0)
		sceKernelStartThread(tid, 0, 0);
#endif

#ifdef OF_NINTENDO_DS
	consoleDemoInit();
#endif







|







118
119
120
121
122
123
124
125
126
127
128
129
130
131
132

#ifdef OF_PSP
	pspDebugScreenInit();

	sceCtrlSetSamplingCycle(0);
	sceCtrlSetSamplingMode(PSP_CTRL_MODE_DIGITAL);

	if ((tid = sceKernelCreateThread("update_thread", threadCallback,
	    0x11, 0xFA0, 0, 0)) >= 0)
		sceKernelStartThread(tid, 0, 0);
#endif

#ifdef OF_NINTENDO_DS
	consoleDemoInit();
#endif
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
	}
#else
	return OFApplicationMain(&argc, &argv, [[TestsAppDelegate alloc] init]);
#endif
}

@implementation TestsAppDelegate
- (void)outputTesting: (OFString *)test
	     inModule: (OFString *)module
{
	if (OFStdOut.hasTerminal) {
		[OFStdOut setForegroundColor: [OFColor yellow]];
		[OFStdOut writeFormat: @"[%@] %@: testing...", module, test];
	} else
		[OFStdOut writeFormat: @"[%@] %@: ", module, test];
}

- (void)outputSuccess: (OFString *)test
	     inModule: (OFString *)module
{
	if (OFStdOut.hasTerminal) {
		[OFStdOut setForegroundColor: [OFColor lime]];
		[OFStdOut eraseLine];
		[OFStdOut writeFormat: @"\r[%@] %@: ok\n", module, test];
	} else
		[OFStdOut writeLine: @"ok"];
}

- (void)outputFailure: (OFString *)test
	     inModule: (OFString *)module
{
	if (OFStdOut.hasTerminal) {
		[OFStdOut setForegroundColor: [OFColor red]];
		[OFStdOut eraseLine];
		[OFStdOut writeFormat: @"\r[%@] %@: failed\n", module, test];

#ifdef OF_WII







|
<








|
<









|
<







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
	return OFApplicationMain(&argc, &argv, [[TestsAppDelegate alloc] init]);
#endif
}

@implementation TestsAppDelegate
- (void)outputTesting: (OFString *)test inModule: (OFString *)module

{
	if (OFStdOut.hasTerminal) {
		[OFStdOut setForegroundColor: [OFColor yellow]];
		[OFStdOut writeFormat: @"[%@] %@: testing...", module, test];
	} else
		[OFStdOut writeFormat: @"[%@] %@: ", module, test];
}

- (void)outputSuccess: (OFString *)test inModule: (OFString *)module

{
	if (OFStdOut.hasTerminal) {
		[OFStdOut setForegroundColor: [OFColor lime]];
		[OFStdOut eraseLine];
		[OFStdOut writeFormat: @"\r[%@] %@: ok\n", module, test];
	} else
		[OFStdOut writeLine: @"ok"];
}

- (void)outputFailure: (OFString *)test inModule: (OFString *)module

{
	if (OFStdOut.hasTerminal) {
		[OFStdOut setForegroundColor: [OFColor red]];
		[OFStdOut eraseLine];
		[OFStdOut writeFormat: @"\r[%@] %@: failed\n", module, test];

#ifdef OF_WII

Modified tests/objc_sync/Makefile from [050b215f54] to [0df383ed25].

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

17
18
19
20
21
22
23
24
25
26
27
28

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

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

59
60
61

62
63
64
65
66


67
include ../../extra.mk

PROG_NOINST = objc_sync${PROG_SUFFIX}
SRCS = test.m

include ../../buildsys.mk

post-all: ${RUN_TESTS}

.PHONY: run
run:
	rm -f libobjfw.so.${OBJFW_LIB_MAJOR}
	rm -f libobjfw.so.${OBJFW_LIB_MAJOR_MINOR}
	rm -f objfw.dll libobjfw.${OBJFW_LIB_MAJOR}.dylib
	rm -f libobjfwrt.so.${OBJFWRT_LIB_MAJOR}
	rm -f libobjfwrt.so.${OBJFWRT_LIB_MAJOR_MINOR}

	rm -f objfwrt.dll 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.dll; then \
		${LN_S} ../../src/objfw.dll objfw.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.dll; then \
		${LN_S} ../../src/runtime/objfwrt.dll objfwrt.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 objfw.so.${OBJFW_LIB_MAJOR_MINOR} objfw.dll; \

	rm -f libobjfw.${OBJFW_LIB_MAJOR}.dylib; \
	rm -f libobjfwrt.so.${OBJFWRT_LIB_MAJOR}; \
	rm -f objfwrt.so.${OBJFWRT_LIB_MAJOR_MINOR} objfwrt.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}







<
<




|


>
|









|
|
>













|
|
>














|
>


|
>




|
>
>

1
2
3
4
5
6
7


8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
include ../../extra.mk

PROG_NOINST = objc_sync${PROG_SUFFIX}
SRCS = test.m

include ../../buildsys.mk



.PHONY: run
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}; \
	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_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}

Modified tests/plugin/TestPlugin.m from [c395596363] to [37c0de4e88].

24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
{
	Class class = objc_getClass("TestPlugin");

	if (class == Nil)
		/*
		 * musl has broken dlclose(): Instead of calling the destructor
		 * on dlclose(), they call it on exit(). This of course means
		 * that our tests might have already called objc_exit() and the
		 * class is already gone.
		 */
		return;

	objc_unregister_class(class);
}
#endif

@implementation TestPlugin
- (int)test: (int)num
{
	return num * 2;







|
|



|







24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
{
	Class class = objc_getClass("TestPlugin");

	if (class == Nil)
		/*
		 * musl has broken dlclose(): Instead of calling the destructor
		 * on dlclose(), they call it on exit(). This of course means
                 * that our tests might have already called objc_deinit() and
                 * the class is already gone.
		 */
		return;

	objc_unregisterClass(class);
}
#endif

@implementation TestPlugin
- (int)test: (int)num
{
	return num * 2;

Modified tests/serialization.xml from [c1b84078b7] to [1df911f605].

1
2
3






4
5
6
7
8
9
10
<?xml version='1.0' encoding='UTF-8'?>
<serialization xmlns='https://objfw.nil.im/serialization' version='1'>
  <OFMutableDictionary>






    <key>
      <OFString>Blub</OFString>
    </key>
    <object>
      <OFString>B&quot;la</OFString>
    </object>
    <key>



>
>
>
>
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?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>

Modified tests/terminal/Makefile from [58c564f0ae] to [e8770b0b9b].

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

17
18
19
20
21
22
23
24
25
26
27
28

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

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

59
60
61

62
63
64
65
66


67
include ../../extra.mk

PROG_NOINST = terminal_tests${PROG_SUFFIX}
SRCS = TerminalTests.m

include ../../buildsys.mk

post-all: ${RUN_TESTS}

.PHONY: run
run:
	rm -f libobjfw.so.${OBJFW_LIB_MAJOR}
	rm -f libobjfw.so.${OBJFW_LIB_MAJOR_MINOR}
	rm -f objfw.dll libobjfw.${OBJFW_LIB_MAJOR}.dylib
	rm -f libobjfwrt.so.${OBJFWRT_LIB_MAJOR}
	rm -f libobjfwrt.so.${OBJFWRT_LIB_MAJOR_MINOR}

	rm -f objfwrt.dll 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.dll; then \
		${LN_S} ../../src/objfw.dll objfw.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.dll; then \
		${LN_S} ../../src/runtime/objfwrt.dll objfwrt.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 objfw.so.${OBJFW_LIB_MAJOR_MINOR} objfw.dll; \

	rm -f libobjfw.${OBJFW_LIB_MAJOR}.dylib; \
	rm -f libobjfwrt.so.${OBJFWRT_LIB_MAJOR}; \
	rm -f objfwrt.so.${OBJFWRT_LIB_MAJOR_MINOR} objfwrt.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}







<
<




|


>
|









|
|
>













|
|
>














|
>


|
>




|
>
>

1
2
3
4
5
6
7


8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
include ../../extra.mk

PROG_NOINST = terminal_tests${PROG_SUFFIX}
SRCS = TerminalTests.m

include ../../buildsys.mk



.PHONY: run
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}; \
	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_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}

Modified utils/ofarc/LHAArchive.m from [051184aa1d] to [9257c8729a].

478
479
480
481
482
483
484
485
486





487
488
489
490
491
492
493
		    attributes.fileOwnerAccountID];
		entry.GID = [OFNumber numberWithUnsignedLong:
		    attributes.fileGroupOwnerAccountID];
		entry.owner = attributes.fileOwnerAccountName;
		entry.group = attributes.fileGroupOwnerAccountName;
#endif

		if ([type isEqual: OFFileTypeDirectory])
			entry.compressionMethod = @"-lhd-";






		output = [_archive streamForWritingEntry: entry];

		if ([type isEqual: OFFileTypeRegular]) {
			unsigned long long written = 0;
			unsigned long long size = attributes.fileSize;
			int8_t percent = -1, newPercent;







|

>
>
>
>
>







478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
		    attributes.fileOwnerAccountID];
		entry.GID = [OFNumber numberWithUnsignedLong:
		    attributes.fileGroupOwnerAccountID];
		entry.owner = attributes.fileOwnerAccountName;
		entry.group = attributes.fileGroupOwnerAccountName;
#endif

		if ([type isEqual: OFFileTypeDirectory]) {
			entry.compressionMethod = @"-lhd-";

			if (![entry.fileName hasSuffix: @"/"])
				entry.fileName = [entry.fileName
				    stringByAppendingString: @"/"];
		}

		output = [_archive streamForWritingEntry: entry];

		if ([type isEqual: OFFileTypeRegular]) {
			unsigned long long written = 0;
			unsigned long long size = attributes.fileSize;
			int8_t percent = -1, newPercent;

Modified utils/ofarc/OFArc.m from [84fac1d63f] to [905433948f].

140
141
142
143
144
145
146





















147
148
149
150
151
152
153
writingNotSupported(OFString *type)
{
	[OFStdErr writeLine: OF_LOCALIZED(
	    @"writing_not_supported",
	    @"Writing archives of type %[type] is not (yet) supported!",
	    @"type", type)];
}






















@implementation OFArc
- (void)applicationDidFinishLaunching
{
	OFString *outputDir, *encodingString, *type;
	const OFOptionsParserOption options[] = {
		{ 'a', @"append", 0, NULL, NULL },







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







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
writingNotSupported(OFString *type)
{
	[OFStdErr writeLine: OF_LOCALIZED(
	    @"writing_not_supported",
	    @"Writing archives of type %[type] is not (yet) supported!",
	    @"type", type)];
}

static void
addFiles(id <Archive> archive, OFArray OF_GENERIC(OFString *) *files)
{
	OFMutableArray *expandedFiles =
	    [OFMutableArray arrayWithCapacity: files.count];
	OFFileManager *fileManager = [OFFileManager defaultManager];

	for (OFString *file in files) {
		OFFileAttributes attributes =
		    [fileManager attributesOfItemAtPath: file];

		if ([attributes.fileType isEqual: OFFileTypeDirectory])
			[expandedFiles addObjectsFromArray: 
			    [fileManager subpathsOfDirectoryAtPath: file]];
		else
			[expandedFiles addObject: file];
	}

	[archive addFiles: expandedFiles];
}

@implementation OFArc
- (void)applicationDidFinishLaunching
{
	OFString *outputDir, *encodingString, *type;
	const OFOptionsParserOption options[] = {
		{ 'a', @"append", 0, NULL, NULL },
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346

		archive = [self
		    openArchiveWithPath: remainingArguments.firstObject
				   type: type
				   mode: mode
			       encoding: encoding];

		[archive addFiles: files];
		break;
	case 'l':
		if (remainingArguments.count != 1)
			help(OFStdErr, false, 1);

#ifdef OF_HAVE_SANDBOX
		if (![remainingArguments.firstObject isEqual: @"-"])







|







353
354
355
356
357
358
359
360
361
362
363
364
365
366
367

		archive = [self
		    openArchiveWithPath: remainingArguments.firstObject
				   type: type
				   mode: mode
			       encoding: encoding];

		addFiles(archive, files);
		break;
	case 'l':
		if (remainingArguments.count != 1)
			help(OFStdErr, false, 1);

#ifdef OF_HAVE_SANDBOX
		if (![remainingArguments.firstObject isEqual: @"-"])

Modified utils/ofhash/OFHash.m from [976db374f8] to [1dccaed4eb].

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

OF_APPLICATION_DELEGATE(OFHash)

static void
help(void)
{
	[OFStdErr writeLine: OF_LOCALIZED(@"usage",
	    @"Usage: %[prog] [--md5|--ripemd160|--sha1|--sha224|--sha256|"
	    @"--sha384|--sha512] file1 [file2 ...]",
	    @"prog", [OFApplication programName])];

	[OFApplication terminateWithStatus: 1];
}

static void
printHash(OFString *algo, OFString *path, id <OFCryptographicHash> hash)







|
|







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

OF_APPLICATION_DELEGATE(OFHash)

static void
help(void)
{
	[OFStdErr writeLine: OF_LOCALIZED(@"usage",
	    @"Usage: %[prog] [--md5] [--ripemd160] [--sha1] [--sha224] "
	    @"[--sha256] [--sha384] [--sha512] file1 [file2 ...]",
	    @"prog", [OFApplication programName])];

	[OFApplication terminateWithStatus: 1];
}

static void
printHash(OFString *algo, OFString *path, id <OFCryptographicHash> hash)

Modified utils/ofhash/lang/de.json from [775fc52ec2] to [e3d21e1de1].

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
{
    "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/ofhttp/OFHTTP.m from [c136ae289f] to [cd70aeb710].

528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
	}

#ifdef OF_HAVE_SANDBOX
	if (outputPath != nil)
		[sandbox unveilPath: outputPath
			permissions: (_continue ? @"rwc" : @"wc")];
	else
		[sandbox unveilPath: [[OFFileManger defaultManager]
					 currentDirectoryPath]
			permissions: (_continue ? @"rwc" : @"wc")];

	/* In case we use ObjOpenSSL for https later */
	[sandbox unveilPath: @"/etc/ssl" permissions: @"r"];

	sandbox.allowsUnveil = false;







|







528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
	}

#ifdef OF_HAVE_SANDBOX
	if (outputPath != nil)
		[sandbox unveilPath: outputPath
			permissions: (_continue ? @"rwc" : @"wc")];
	else
		[sandbox unveilPath: [[OFFileManager defaultManager]
					 currentDirectoryPath]
			permissions: (_continue ? @"rwc" : @"wc")];

	/* In case we use ObjOpenSSL for https later */
	[sandbox unveilPath: @"/etc/ssl" permissions: @"r"];

	sandbox.allowsUnveil = false;

Modified utils/ofhttp/ProgressBar.m from [5cde87eb26] to [55b889a4e0].

21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#import "OFStdIOStream.h"
#import "OFTimer.h"
#import "OFLocale.h"

#import "ProgressBar.h"

static const float oneKibibyte = 1024;
static const float oneMebibyte = 1024 * oneKibibyte;
static const float oneGibibyte = 1024 * oneMebibyte;

static const OFTimeInterval updateInterval = 0.1;

#ifndef HAVE_TRUNCF
# define truncf(x) trunc(x)
#endif








|
|







21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#import "OFStdIOStream.h"
#import "OFTimer.h"
#import "OFLocale.h"

#import "ProgressBar.h"

static const float oneKibibyte = 1024;
static const float oneMebibyte = 1024 * 1024;
static const float oneGibibyte = 1024 * 1024 * 1024;

static const OFTimeInterval updateInterval = 0.1;

#ifndef HAVE_TRUNCF
# define truncf(x) trunc(x)
#endif