Index: .fossil-settings/clean-glob ================================================================== --- .fossil-settings/clean-glob +++ .fossil-settings/clean-glob @@ -30,21 +30,27 @@ src/bridge/Info.plist src/libobjfw.* src/objfw-defs.h src/runtime/Info.plist src/runtime/libobjfwrt.* +src/tls/Info.plist tests/DerivedData tests/EBOOT.PBP tests/Info.plist tests/PARAM.SFO tests/objc_sync/objc_sync tests/plugin/Info.plist +tests/serialization_xml.m tests/terminal/terminal_tests +tests/testfile_bin.m +tests/testfile_ini.m tests/tests tests/tests.3dsx tests/tests.arm9 tests/tests.nds +tests/tests.nro +tests/tests.rpx utils/objfw-config utils/ofarc/ofarc utils/ofdns/ofdns utils/ofhash/ofhash utils/ofhttp/ofhttp Index: .fossil-settings/ignore-glob ================================================================== --- .fossil-settings/ignore-glob +++ .fossil-settings/ignore-glob @@ -32,24 +32,30 @@ src/bridge/Info.plist src/libobjfw.* src/objfw-defs.h src/runtime/Info.plist src/runtime/libobjfwrt.* +src/tls/Info.plist tests/DerivedData tests/EBOOT.PBP tests/Info.plist tests/PARAM.SFO tests/iOS.xcodeproj/*.pbxuser tests/iOS.xcodeproj/project.xcworkspace tests/iOS.xcodeproj/xcuserdata tests/objc_sync/objc_sync tests/plugin/Info.plist +tests/serialization_xml.m tests/terminal/terminal_tests +tests/testfile_bin.m +tests/testfile_ini.m tests/tests tests/tests.3dsx tests/tests.arm9 tests/tests.nds +tests/tests.nro +tests/tests.rpx utils/objfw-config utils/ofarc/ofarc utils/ofdns/ofdns utils/ofhash/ofhash utils/ofhttp/ofhttp Index: .github/workflows/amiga-gcc.yml ================================================================== --- .github/workflows/amiga-gcc.yml +++ .github/workflows/amiga-gcc.yml @@ -1,9 +1,9 @@ name: amiga-gcc on: [push, pull_request] jobs: - tests: + build: runs-on: ubuntu-latest strategy: matrix: configure_flags: - Index: .github/workflows/ios.yml ================================================================== --- .github/workflows/ios.yml +++ .github/workflows/ios.yml @@ -1,9 +1,9 @@ name: ios on: [push, pull_request] jobs: - tests: + build: runs-on: macos-latest strategy: matrix: arch: - arm64 ADDED .github/workflows/morphos.yml Index: .github/workflows/morphos.yml ================================================================== --- .github/workflows/morphos.yml +++ .github/workflows/morphos.yml @@ -0,0 +1,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)" Index: .github/workflows/nintendo-3ds.yml ================================================================== --- .github/workflows/nintendo-3ds.yml +++ .github/workflows/nintendo-3ds.yml @@ -1,9 +1,9 @@ name: nintendo-3ds on: [push, pull_request] jobs: - tests: + build: runs-on: ubuntu-latest steps: - name: Install dependencies run: docker pull devkitpro/devkitarm - uses: actions/checkout@v2 Index: .github/workflows/nintendo-ds.yml ================================================================== --- .github/workflows/nintendo-ds.yml +++ .github/workflows/nintendo-ds.yml @@ -1,9 +1,9 @@ name: nintendo-ds on: [push, pull_request] jobs: - tests: + build: runs-on: ubuntu-latest steps: - name: Install dependencies run: docker pull devkitpro/devkitarm - uses: actions/checkout@v2 ADDED .github/workflows/nintendo-switch.yml Index: .github/workflows/nintendo-switch.yml ================================================================== --- .github/workflows/nintendo-switch.yml +++ .github/workflows/nintendo-switch.yml @@ -0,0 +1,35 @@ +name: nintendo-switch +on: [push, pull_request] +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Install dependencies + run: docker pull devkitpro/devkita64 + - uses: actions/checkout@v2 + - name: autogen.sh + run: ./autogen.sh + - name: configure + run: | + docker run \ + -e DEVKITPRO=/opt/devkitpro \ + -e PATH="/opt/devkitpro/devkitA64/bin:$PATH" \ + -v "$PWD:/objfw" \ + devkitpro/devkita64 \ + sh -c 'cd /objfw && ./configure --host=aarch64-none-elf --with-nintendo-switch' + - name: make + run: | + docker run \ + -e DEVKITPRO=/opt/devkitpro \ + -e PATH="/opt/devkitpro/devkitA64/bin:$PATH" \ + -v "$PWD:/objfw" \ + devkitpro/devkita64 \ + sh -c "cd /objfw && make -j$(nproc)" + - name: make install + run: | + docker run \ + -e DEVKITPRO=/opt/devkitpro \ + -e PATH="/opt/devkitpro/devkitA64/bin:$PATH" \ + -v "$PWD:/objfw" \ + devkitpro/devkita64 \ + sh -c "cd /objfw && make -j$(nproc)" Index: .github/workflows/ubuntu-18.04-32bit.yml ================================================================== --- .github/workflows/ubuntu-18.04-32bit.yml +++ .github/workflows/ubuntu-18.04-32bit.yml @@ -4,26 +4,28 @@ 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 + - --without-tls + - --without-tls --enable-seluid24 + - --without-tls --disable-compiler-tls + - --without-tls --disable-threads + - --without-tls --disable-threads --disable-sockets + - --without-tls --disable-threads --disable-files + - --without-tls --disable-threads --disable-sockets --disable-files + - --without-tls --disable-sockets + - --without-tls --disable-sockets --disable-files + - --without-tls --disable-files + - --without-tls --disable-shared + - --without-tls --disable-shared --enable-seluid24 + - --without-tls --disable-compiler-tls --disable-threads steps: - name: Install dependencies - run: sudo apt install gcc-multilib + run: | + sudo apt-get update + sudo apt-get install gcc-multilib - uses: actions/checkout@v2 - name: autogen.sh run: ./autogen.sh - name: configure run: ./configure OBJC="clang -m32" ${{ matrix.configure_flags }} Index: .github/workflows/ubuntu-18.04-gcc-32bit.yml ================================================================== --- .github/workflows/ubuntu-18.04-gcc-32bit.yml +++ .github/workflows/ubuntu-18.04-gcc-32bit.yml @@ -4,26 +4,28 @@ 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 + - --without-tls + - --without-tls --enable-seluid24 + - --without-tls --disable-compiler-tls + - --without-tls --disable-threads + - --without-tls --disable-threads --disable-sockets + - --without-tls --disable-threads --disable-files + - --without-tls --disable-threads --disable-sockets --disable-files + - --without-tls --disable-sockets + - --without-tls --disable-sockets --disable-files + - --without-tls --disable-files + - --without-tls --disable-shared + - --without-tls --disable-shared --enable-seluid24 + - --without-tls --disable-compiler-tls --disable-threads steps: - name: Install dependencies - run: sudo apt install gcc-multilib gobjc + run: | + sudo apt-get update + sudo apt-get install gcc-multilib gobjc - uses: actions/checkout@v2 - name: autogen.sh run: ./autogen.sh - name: configure run: ./configure OBJC="gcc -m32" ${{ matrix.configure_flags }} Index: .github/workflows/ubuntu-18.04-gcc.yml ================================================================== --- .github/workflows/ubuntu-18.04-gcc.yml +++ .github/workflows/ubuntu-18.04-gcc.yml @@ -17,13 +17,17 @@ - --disable-sockets --disable-files - --disable-files - --disable-shared - --disable-shared --enable-seluid24 - --disable-compiler-tls --disable-threads + - --with-tls=gnutls + - --with-tls=gnutls --disable-shared steps: - name: Install dependencies - run: sudo apt install gobjc + run: | + sudo apt-get update + sudo apt-get install gobjc libssl-dev gnutls-dev - uses: actions/checkout@v2 - name: autogen.sh run: ./autogen.sh - name: configure run: ./configure OBJC="gcc" ${{ matrix.configure_flags }} Index: .github/workflows/ubuntu-18.04.yml ================================================================== --- .github/workflows/ubuntu-18.04.yml +++ .github/workflows/ubuntu-18.04.yml @@ -17,11 +17,17 @@ - --disable-sockets --disable-files - --disable-files - --disable-shared - --disable-shared --enable-seluid24 - --disable-compiler-tls --disable-threads + - --with-tls=gnutls + - --with-tls=gnutls --disable-shared steps: + - name: Install dependencies + run: | + sudo apt-get update + sudo apt-get install libssl-dev gnutls-dev - uses: actions/checkout@v2 - name: autogen.sh run: ./autogen.sh - name: configure run: ./configure ${{ matrix.configure_flags }} Index: .github/workflows/ubuntu-20.04-32bit.yml ================================================================== --- .github/workflows/ubuntu-20.04-32bit.yml +++ .github/workflows/ubuntu-20.04-32bit.yml @@ -4,26 +4,28 @@ 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 + - --without-tls + - --without-tls --enable-seluid24 + - --without-tls --disable-compiler-tls + - --without-tls --disable-threads + - --without-tls --disable-threads --disable-sockets + - --without-tls --disable-threads --disable-files + - --without-tls --disable-threads --disable-sockets --disable-files + - --without-tls --disable-sockets + - --without-tls --disable-sockets --disable-files + - --without-tls --disable-files + - --without-tls --disable-shared + - --without-tls --disable-shared --enable-seluid24 + - --without-tls --disable-compiler-tls --disable-threads steps: - name: Install dependencies - run: sudo apt install gcc-multilib + run: | + sudo apt-get update + sudo apt-get install gcc-multilib - uses: actions/checkout@v2 - name: autogen.sh run: ./autogen.sh - name: configure run: ./configure OBJC="clang -m32" ${{ matrix.configure_flags }} Index: .github/workflows/ubuntu-20.04-gcc-32bit.yml ================================================================== --- .github/workflows/ubuntu-20.04-gcc-32bit.yml +++ .github/workflows/ubuntu-20.04-gcc-32bit.yml @@ -4,26 +4,28 @@ 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 + - --without-tls + - --without-tls --enable-seluid24 + - --without-tls --disable-compiler-tls + - --without-tls --disable-threads + - --without-tls --disable-threads --disable-sockets + - --without-tls --disable-threads --disable-files + - --without-tls --disable-threads --disable-sockets --disable-files + - --without-tls --disable-sockets + - --without-tls --disable-sockets --disable-files + - --without-tls --disable-files + - --without-tls --disable-shared + - --without-tls --disable-shared --enable-seluid24 + - --without-tls --disable-compiler-tls --disable-threads steps: - name: Install dependencies - run: sudo apt install gcc-multilib gobjc + run: | + sudo apt-get update + sudo apt-get install gcc-multilib gobjc - uses: actions/checkout@v2 - name: autogen.sh run: ./autogen.sh - name: configure run: ./configure OBJC="gcc -m32" ${{ matrix.configure_flags }} Index: .github/workflows/ubuntu-20.04-gcc.yml ================================================================== --- .github/workflows/ubuntu-20.04-gcc.yml +++ .github/workflows/ubuntu-20.04-gcc.yml @@ -17,13 +17,17 @@ - --disable-sockets --disable-files - --disable-files - --disable-shared - --disable-shared --enable-seluid24 - --disable-compiler-tls --disable-threads + - --with-tls=gnutls + - --with-tls=gnutls --disable-shared steps: - name: Install dependencies - run: sudo apt install gobjc + run: | + sudo apt-get update + sudo apt-get install gobjc libssl-dev gnutls-dev - uses: actions/checkout@v2 - name: autogen.sh run: ./autogen.sh - name: configure run: ./configure OBJC="gcc" ${{ matrix.configure_flags }} Index: .github/workflows/ubuntu-20.04.yml ================================================================== --- .github/workflows/ubuntu-20.04.yml +++ .github/workflows/ubuntu-20.04.yml @@ -17,11 +17,17 @@ - --disable-sockets --disable-files - --disable-files - --disable-shared - --disable-shared --enable-seluid24 - --disable-compiler-tls --disable-threads + - --with-tls=gnutls + - --with-tls=gnutls --disable-shared steps: + - name: Install dependencies + run: | + sudo apt-get update + sudo apt-get install libssl-dev gnutls-dev - uses: actions/checkout@v2 - name: autogen.sh run: ./autogen.sh - name: configure run: ./configure ${{ matrix.configure_flags }} ADDED .github/workflows/wii-u.yml Index: .github/workflows/wii-u.yml ================================================================== --- .github/workflows/wii-u.yml +++ .github/workflows/wii-u.yml @@ -0,0 +1,35 @@ +name: wii-u +on: [push, pull_request] +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Install dependencies + run: docker pull devkitpro/devkitppc + - uses: actions/checkout@v2 + - name: autogen.sh + run: ./autogen.sh + - name: configure + run: | + docker run \ + -e DEVKITPRO=/opt/devkitpro \ + -e PATH="/opt/devkitpro/devkitPPC/bin:$PATH" \ + -v "$PWD:/objfw" \ + devkitpro/devkitppc \ + sh -c 'cd /objfw && ./configure --host=powerpc-eabi --with-wii-u' + - 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)" Index: .github/workflows/wii.yml ================================================================== --- .github/workflows/wii.yml +++ .github/workflows/wii.yml @@ -1,9 +1,9 @@ name: wii on: [push, pull_request] jobs: - tests: + build: runs-on: ubuntu-latest steps: - name: Install dependencies run: docker pull devkitpro/devkitppc - uses: actions/checkout@v2 Index: .gitignore ================================================================== --- .gitignore +++ .gitignore @@ -32,24 +32,30 @@ src/bridge/Info.plist src/libobjfw.* src/objfw-defs.h src/runtime/Info.plist src/runtime/libobjfwrt.* +src/tls/Info.plist tests/DerivedData tests/EBOOT.PBP tests/Info.plist tests/PARAM.SFO tests/iOS.xcodeproj/*.pbxuser tests/iOS.xcodeproj/project.xcworkspace tests/iOS.xcodeproj/xcuserdata tests/objc_sync/objc_sync tests/plugin/Info.plist +tests/serialization_xml.m tests/terminal/terminal_tests +tests/testfile_bin.m +tests/testfile_ini.m tests/tests tests/tests.3dsx tests/tests.arm9 tests/tests.nds +tests/tests.nro +tests/tests.rpx utils/objfw-config utils/ofarc/ofarc utils/ofdns/ofdns utils/ofhash/ofhash utils/ofhttp/ofhttp Index: Doxyfile ================================================================== --- Doxyfile +++ Doxyfile @@ -1,15 +1,18 @@ PROJECT_NAME = "ObjFW" OUTPUT_DIRECTORY = docs/ INPUT = src src/exceptions src/runtime FILE_PATTERNS = *.h *.m HTML_OUTPUT = . +HAVE_DOT = NO GENERATE_LATEX = NO HIDE_UNDOC_CLASSES = YES HIDE_UNDOC_MEMBERS = YES TYPEDEF_HIDES_STRUCT = YES PREDEFINED = __OBJC__ \ + _Nonnull \ + _Nullable \ DOXYGEN \ OF_BOXABLE \ OF_CONSUMED \ OF_DESIGNATED_INITIALIZER \ OF_GENERIC(...)= \ Index: PLATFORMS.md ================================================================== --- PLATFORMS.md +++ PLATFORMS.md @@ -103,10 +103,20 @@ * OS Versions: 10.5, 10.7-10.15, Darling * Architectures: PowerPC, PowerPC64, x86, x86_64 * Compilers: Clang 3.1-10.0, Apple GCC 4.0.1 & 4.2.1 * Runtimes: Apple, ObjFW + +MiNT +---- + + * OS Versions: FreeMiNT 1.19 + * Architectures: m68k + * Runtimes: ObjFW + * Compilers: GCC 4.6.4 (MiNT 20130415) + * Limitations: No shared libraries, no threads + MorphOS ------- * OS Versions: 3.14 @@ -142,10 +152,20 @@ * Compilers: GCC 4.8.2 (devkitARM release 42) * Runtimes: ObjFW * Limitations: No threads, no sockets * Notes: File support requires an argv-compatible launcher (such as HBMenu) + +Nintendo Switch +--------------- + + * OS Versions: yuzu 1093 + * Architectures: AArch64 + * Compilers: GCC 12.1.0 (devkitA64 release 19) + * Runtimes: ObjFW + * Limitations: No sockets, no shared libraries, not tested on real hardware + OpenBSD ------- * OS Versions: 5.2-6.7 @@ -189,20 +209,32 @@ * Architectures: PowerPC * Compilers: GCC 4.6.3 (devkitPPC release 26) * Runtimes: ObjFW * Limitations: No threads + +Wii U +----- + + * OS Versions: Cemu 12.26.2f + * Architectures: PowerPC + * Compilers: gcc version 12.1.0 (devkitPPC release 41) + * Runtimes: ObjFW + * Limitations: No files, no threads, no sockets, no shared libraries, not + tested on real hardware + Windows ------- - * OS Versions: 98 SE, NT 4.0, XP (x86), 7 (x64), 8 (x64), 8.1 (x64), 10, + * OS Versions: 98 SE, NT 4.0, XP (x86), 7 (x64), 8 (x64), 8.1 (x64), 10, 11, Wine (x86 & x64) - * Architectures: x86, x86_64 + * Architectures: x86, x86_64, AArch64 * Compilers: GCC 5.3.0 & 6.2.0 from msys2 (x86 & x64), Clang 3.9.0 from msys2 (x86), - Clang 10.0 from msys2 (x86 & x86_64) + Clang 10.0 from msys2 (x86 & x86_64), + Clang 14.0.4 from msys2 (AArch64) * Runtimes: ObjFW Others ------ Index: README.md ================================================================== --- README.md +++ README.md @@ -30,10 +30,12 @@ * [Amiga](#amiga) * [Writing your first application with ObjFW](#first-app) * [Documentation](#documentation) * [Bugs and feature requests](#bugs) * [Support and community](#support) + * [Donating](#donating) + * [Thanks](#thanks) * [Commercial use](#commercial-use)

What is ObjFW?

@@ -122,10 +124,16 @@ In order to verify the signature of the currently checked out checkin, you can use: $ fossil artifact current | gpg --verify + Please note that not all checkins are signed, as the signing key only resides + on trusted systems. This means that checkins I perform on e.g. Windows are + unsigned. However, usually it should not take long until there is another + signed checkin. Alternatively, you can go back until the last signed checkin + and review changes from there on. +

Git

To clone the Git repository, use the following: $ git clone https://github.com/ObjFW/ObjFW @@ -137,11 +145,12 @@ To install ObjFW, just run the following commands: $ ./configure $ make - $ make install + $ 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 @@ -149,27 +158,33 @@

macOS and iOS

Building as a framework

When building for macOS or iOS, everything is built as a `.framework` by - default if `--disable-shared` has not been specified to `configure`. + default if `--disable-shared` has not been specified to `./configure`. The + frameworks will end up in `$PREFIX/Library/Frameworks`. - To build for iOS, use something like this: + To build for macOS, just follow the + regular instructions above. + + To build for iOS, follow the regular instructions, but instead of + `./configure` do something like this: $ clang="clang -isysroot $(xcrun --sdk iphoneos --show-sdk-path)" $ export OBJC="$clang -arch armv7 -arch arm64" $ export OBJCPP="$clang -arch armv7 -E" $ export IPHONEOS_DEPLOYMENT_TARGET="9.0" $ ./configure --prefix=/usr/local/ios --host=arm64-apple-darwin - To build for the iOS simulator, use something like this: + To build for the iOS simulator, follow the regular instructions, but instead + of `./configure` use something like this: $ clang="clang -isysroot $(xcrun --sdk iphonesimulator --show-sdk-path)" - $ export OBJC="$clang -arch i386 -arch x86_64" - $ export OBJCPP="$clang -arch i386 -E" + $ export OBJC="$clang -arch arm64 -arch x86_64" + $ export OBJCPP="$clang -arch arm64 -E" $ export IPHONEOS_DEPLOYMENT_TARGET="9.0" - $ ./configure --prefix=/usr/local/iossim --host=x86_64-apple-darwin + $ ./configure --prefix=/usr/local/iossim --host=arm64-apple-darwin

Using the macOS or iOS framework in Xcode

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`: @@ -354,12 +369,27 @@ * A [Gitter room](https://gitter.im/ObjFW/ObjFW), bridged to the Matrix room above Please don't hesitate to join any or all of those! + +

Donating

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

Thanks

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

Commercial use

If for whatever reason neither the terms of the QPL nor those of the GPL work for you, a proprietary license for ObjFW including support is available upon request. Just write a mail to js@nil.im and we can find a reasonable solution for both parties. Index: build-aux/m4/buildsys.m4 ================================================================== --- build-aux/m4/buildsys.m4 +++ build-aux/m4/buildsys.m4 @@ -20,17 +20,17 @@ 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]) + AC_ARG_ENABLE(rpath, + AS_HELP_STRING([--disable-rpath], [do not use rpath])) + case "$build_os" in darwin*) case "$host_os" in darwin*) AC_SUBST(BUILD_AND_HOST_ARE_DARWIN, yes) @@ -203,20 +203,21 @@ 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='-shared -Wl,--export-all-symbols' LIB_LDFLAGS_INSTALL_NAME='' LIB_PREFIX='' LIB_SUFFIX='${LIB_MAJOR}.dll' + LINK_LIB='&& ${LN_S} $$out lib$${out%${LIB_SUFFIX}}.dll.a' PLUGIN_CFLAGS='' - PLUGIN_LDFLAGS='-shared' + PLUGIN_LDFLAGS='-shared -Wl,--export-all-symbols' PLUGIN_SUFFIX='.dll' LINK_PLUGIN='${LD} -o $$out ${PLUGIN_OBJS} ${PLUGIN_OBJS_EXTRA} ${PLUGIN_LDFLAGS} ${LDFLAGS} ${LIBS}' - INSTALL_LIB='&& ${MKDIR_P} ${DESTDIR}${bindir} && ${INSTALL} -m 755 $$i ${DESTDIR}${bindir}/$$i && ${INSTALL} -m 755 lib$${i%${LIB_SUFFIX}}.a ${DESTDIR}${libdir}/lib$${i%${LIB_SUFFIX}}.a' - UNINSTALL_LIB='&& rm -f ${DESTDIR}${bindir}/$$i ${DESTDIR}${libdir}/lib$$i.a' + INSTALL_LIB='&& ${MKDIR_P} ${DESTDIR}${bindir} && ${INSTALL} -m 755 $$i ${DESTDIR}${bindir}/$$i && ${INSTALL} -m 755 lib$${i%${LIB_SUFFIX}}.dll.a ${DESTDIR}${libdir}/lib$${i%${LIB_SUFFIX}}.dll.a' + UNINSTALL_LIB='&& rm -f ${DESTDIR}${bindir}/$$i ${DESTDIR}${libdir}/lib$${i%${LIB_SUFFIX}}.dll.a' 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*) ADDED build-aux/m4/pkg.m4 Index: build-aux/m4/pkg.m4 ================================================================== --- build-aux/m4/pkg.m4 +++ build-aux/m4/pkg.m4 @@ -0,0 +1,343 @@ +# pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*- +# serial 11 (pkg-config-0.29.1) + +dnl Copyright © 2004 Scott James Remnant . +dnl Copyright © 2012-2015 Dan Nicholson +dnl +dnl This program is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2 of the License, or +dnl (at your option) any later version. +dnl +dnl This program is distributed in the hope that it will be useful, but +dnl WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +dnl General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with this program; if not, write to the Free Software +dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +dnl 02111-1307, USA. +dnl +dnl As a special exception to the GNU General Public License, if you +dnl distribute this file as part of a program that contains a +dnl configuration script generated by Autoconf, you may include it under +dnl the same distribution terms that you use for the rest of that +dnl program. + +dnl PKG_PREREQ(MIN-VERSION) +dnl ----------------------- +dnl Since: 0.29 +dnl +dnl Verify that the version of the pkg-config macros are at least +dnl MIN-VERSION. Unlike PKG_PROG_PKG_CONFIG, which checks the user's +dnl installed version of pkg-config, this checks the developer's version +dnl of pkg.m4 when generating configure. +dnl +dnl To ensure that this macro is defined, also add: +dnl m4_ifndef([PKG_PREREQ], +dnl [m4_fatal([must install pkg-config 0.29 or later before running autoconf/autogen])]) +dnl +dnl See the "Since" comment for each macro you use to see what version +dnl of the macros you require. +m4_defun([PKG_PREREQ], +[m4_define([PKG_MACROS_VERSION], [0.29.1]) +m4_if(m4_version_compare(PKG_MACROS_VERSION, [$1]), -1, + [m4_fatal([pkg.m4 version $1 or higher is required but ]PKG_MACROS_VERSION[ found])]) +])dnl PKG_PREREQ + +dnl PKG_PROG_PKG_CONFIG([MIN-VERSION]) +dnl ---------------------------------- +dnl Since: 0.16 +dnl +dnl Search for the pkg-config tool and set the PKG_CONFIG variable to +dnl first found in the path. Checks that the version of pkg-config found +dnl is at least MIN-VERSION. If MIN-VERSION is not specified, 0.9.0 is +dnl used since that's the first version where most current features of +dnl pkg-config existed. +AC_DEFUN([PKG_PROG_PKG_CONFIG], +[m4_pattern_forbid([^_?PKG_[A-Z_]+$]) +m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$]) +m4_pattern_allow([^PKG_CONFIG_(DISABLE_UNINSTALLED|TOP_BUILD_DIR|DEBUG_SPEW)$]) +AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility]) +AC_ARG_VAR([PKG_CONFIG_PATH], [directories to add to pkg-config's search path]) +AC_ARG_VAR([PKG_CONFIG_LIBDIR], [path overriding pkg-config's built-in search path]) + +if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then + AC_PATH_TOOL([PKG_CONFIG], [pkg-config]) +fi +if test -n "$PKG_CONFIG"; then + _pkg_min_version=m4_default([$1], [0.9.0]) + AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version]) + if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + PKG_CONFIG="" + fi +fi[]dnl +])dnl PKG_PROG_PKG_CONFIG + +dnl PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +dnl ------------------------------------------------------------------- +dnl Since: 0.18 +dnl +dnl Check to see whether a particular set of modules exists. Similar to +dnl PKG_CHECK_MODULES(), but does not set variables or print errors. +dnl +dnl Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG]) +dnl only at the first occurence in configure.ac, so if the first place +dnl it's called might be skipped (such as if it is within an "if", you +dnl have to call PKG_CHECK_EXISTS manually +AC_DEFUN([PKG_CHECK_EXISTS], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +if test -n "$PKG_CONFIG" && \ + AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then + m4_default([$2], [:]) +m4_ifvaln([$3], [else + $3])dnl +fi]) + +dnl _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES]) +dnl --------------------------------------------- +dnl Internal wrapper calling pkg-config via PKG_CONFIG and setting +dnl pkg_failed based on the result. +m4_define([_PKG_CONFIG], +[if test -n "$$1"; then + pkg_cv_[]$1="$$1" + elif test -n "$PKG_CONFIG"; then + PKG_CHECK_EXISTS([$3], + [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes ], + [pkg_failed=yes]) + else + pkg_failed=untried +fi[]dnl +])dnl _PKG_CONFIG + +dnl _PKG_SHORT_ERRORS_SUPPORTED +dnl --------------------------- +dnl Internal check to see if pkg-config supports short errors. +AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG]) +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi[]dnl +])dnl _PKG_SHORT_ERRORS_SUPPORTED + + +dnl PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], +dnl [ACTION-IF-NOT-FOUND]) +dnl -------------------------------------------------------------- +dnl Since: 0.4.0 +dnl +dnl Note that if there is a possibility the first call to +dnl PKG_CHECK_MODULES might not happen, you should be sure to include an +dnl explicit call to PKG_PROG_PKG_CONFIG in your configure.ac +AC_DEFUN([PKG_CHECK_MODULES], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl +AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl + +pkg_failed=no +AC_MSG_CHECKING([for $1]) + +_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2]) +_PKG_CONFIG([$1][_LIBS], [libs], [$2]) + +m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS +and $1[]_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details.]) + +if test $pkg_failed = yes; then + AC_MSG_RESULT([no]) + _PKG_SHORT_ERRORS_SUPPORTED + if test $_pkg_short_errors_supported = yes; then + $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1` + else + $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD + + m4_default([$4], [AC_MSG_ERROR( +[Package requirements ($2) were not met: + +$$1_PKG_ERRORS + +Consider adjusting the PKG_CONFIG_PATH environment variable if you +installed software in a non-standard prefix. + +_PKG_TEXT])[]dnl + ]) +elif test $pkg_failed = untried; then + AC_MSG_RESULT([no]) + m4_default([$4], [AC_MSG_FAILURE( +[The pkg-config script could not be found or is too old. Make sure it +is in your PATH or set the PKG_CONFIG environment variable to the full +path to pkg-config. + +_PKG_TEXT + +To get pkg-config, see .])[]dnl + ]) +else + $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS + $1[]_LIBS=$pkg_cv_[]$1[]_LIBS + AC_MSG_RESULT([yes]) + $3 +fi[]dnl +])dnl PKG_CHECK_MODULES + + +dnl PKG_CHECK_MODULES_STATIC(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], +dnl [ACTION-IF-NOT-FOUND]) +dnl --------------------------------------------------------------------- +dnl Since: 0.29 +dnl +dnl Checks for existence of MODULES and gathers its build flags with +dnl static libraries enabled. Sets VARIABLE-PREFIX_CFLAGS from --cflags +dnl and VARIABLE-PREFIX_LIBS from --libs. +dnl +dnl Note that if there is a possibility the first call to +dnl PKG_CHECK_MODULES_STATIC might not happen, you should be sure to +dnl include an explicit call to PKG_PROG_PKG_CONFIG in your +dnl configure.ac. +AC_DEFUN([PKG_CHECK_MODULES_STATIC], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +_save_PKG_CONFIG=$PKG_CONFIG +PKG_CONFIG="$PKG_CONFIG --static" +PKG_CHECK_MODULES($@) +PKG_CONFIG=$_save_PKG_CONFIG[]dnl +])dnl PKG_CHECK_MODULES_STATIC + + +dnl PKG_INSTALLDIR([DIRECTORY]) +dnl ------------------------- +dnl Since: 0.27 +dnl +dnl Substitutes the variable pkgconfigdir as the location where a module +dnl should install pkg-config .pc files. By default the directory is +dnl $libdir/pkgconfig, but the default can be changed by passing +dnl DIRECTORY. The user can override through the --with-pkgconfigdir +dnl parameter. +AC_DEFUN([PKG_INSTALLDIR], +[m4_pushdef([pkg_default], [m4_default([$1], ['${libdir}/pkgconfig'])]) +m4_pushdef([pkg_description], + [pkg-config installation directory @<:@]pkg_default[@:>@]) +AC_ARG_WITH([pkgconfigdir], + [AS_HELP_STRING([--with-pkgconfigdir], pkg_description)],, + [with_pkgconfigdir=]pkg_default) +AC_SUBST([pkgconfigdir], [$with_pkgconfigdir]) +m4_popdef([pkg_default]) +m4_popdef([pkg_description]) +])dnl PKG_INSTALLDIR + + +dnl PKG_NOARCH_INSTALLDIR([DIRECTORY]) +dnl -------------------------------- +dnl Since: 0.27 +dnl +dnl Substitutes the variable noarch_pkgconfigdir as the location where a +dnl module should install arch-independent pkg-config .pc files. By +dnl default the directory is $datadir/pkgconfig, but the default can be +dnl changed by passing DIRECTORY. The user can override through the +dnl --with-noarch-pkgconfigdir parameter. +AC_DEFUN([PKG_NOARCH_INSTALLDIR], +[m4_pushdef([pkg_default], [m4_default([$1], ['${datadir}/pkgconfig'])]) +m4_pushdef([pkg_description], + [pkg-config arch-independent installation directory @<:@]pkg_default[@:>@]) +AC_ARG_WITH([noarch-pkgconfigdir], + [AS_HELP_STRING([--with-noarch-pkgconfigdir], pkg_description)],, + [with_noarch_pkgconfigdir=]pkg_default) +AC_SUBST([noarch_pkgconfigdir], [$with_noarch_pkgconfigdir]) +m4_popdef([pkg_default]) +m4_popdef([pkg_description]) +])dnl PKG_NOARCH_INSTALLDIR + + +dnl PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE, +dnl [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +dnl ------------------------------------------- +dnl Since: 0.28 +dnl +dnl Retrieves the value of the pkg-config variable for the given module. +AC_DEFUN([PKG_CHECK_VAR], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl + +_PKG_CONFIG([$1], [variable="][$3]["], [$2]) +AS_VAR_COPY([$1], [pkg_cv_][$1]) + +AS_VAR_IF([$1], [""], [$5], [$4])dnl +])dnl PKG_CHECK_VAR + +dnl PKG_WITH_MODULES(VARIABLE-PREFIX, MODULES, +dnl [ACTION-IF-FOUND],[ACTION-IF-NOT-FOUND], +dnl [DESCRIPTION], [DEFAULT]) +dnl ------------------------------------------ +dnl +dnl Prepare a "--with-" configure option using the lowercase +dnl [VARIABLE-PREFIX] name, merging the behaviour of AC_ARG_WITH and +dnl PKG_CHECK_MODULES in a single macro. +AC_DEFUN([PKG_WITH_MODULES], +[ +m4_pushdef([with_arg], m4_tolower([$1])) + +m4_pushdef([description], + [m4_default([$5], [build with ]with_arg[ support])]) + +m4_pushdef([def_arg], [m4_default([$6], [auto])]) +m4_pushdef([def_action_if_found], [AS_TR_SH([with_]with_arg)=yes]) +m4_pushdef([def_action_if_not_found], [AS_TR_SH([with_]with_arg)=no]) + +m4_case(def_arg, + [yes],[m4_pushdef([with_without], [--without-]with_arg)], + [m4_pushdef([with_without],[--with-]with_arg)]) + +AC_ARG_WITH(with_arg, + AS_HELP_STRING(with_without, description[ @<:@default=]def_arg[@:>@]),, + [AS_TR_SH([with_]with_arg)=def_arg]) + +AS_CASE([$AS_TR_SH([with_]with_arg)], + [yes],[PKG_CHECK_MODULES([$1],[$2],$3,$4)], + [auto],[PKG_CHECK_MODULES([$1],[$2], + [m4_n([def_action_if_found]) $3], + [m4_n([def_action_if_not_found]) $4])]) + +m4_popdef([with_arg]) +m4_popdef([description]) +m4_popdef([def_arg]) + +])dnl PKG_WITH_MODULES + +dnl PKG_HAVE_WITH_MODULES(VARIABLE-PREFIX, MODULES, +dnl [DESCRIPTION], [DEFAULT]) +dnl ----------------------------------------------- +dnl +dnl Convenience macro to trigger AM_CONDITIONAL after PKG_WITH_MODULES +dnl check._[VARIABLE-PREFIX] is exported as make variable. +AC_DEFUN([PKG_HAVE_WITH_MODULES], +[ +PKG_WITH_MODULES([$1],[$2],,,[$3],[$4]) + +AM_CONDITIONAL([HAVE_][$1], + [test "$AS_TR_SH([with_]m4_tolower([$1]))" = "yes"]) +])dnl PKG_HAVE_WITH_MODULES + +dnl PKG_HAVE_DEFINE_WITH_MODULES(VARIABLE-PREFIX, MODULES, +dnl [DESCRIPTION], [DEFAULT]) +dnl ------------------------------------------------------ +dnl +dnl Convenience macro to run AM_CONDITIONAL and AC_DEFINE after +dnl PKG_WITH_MODULES check. HAVE_[VARIABLE-PREFIX] is exported as make +dnl and preprocessor variable. +AC_DEFUN([PKG_HAVE_DEFINE_WITH_MODULES], +[ +PKG_HAVE_WITH_MODULES([$1],[$2],[$3],[$4]) + +AS_IF([test "$AS_TR_SH([with_]m4_tolower([$1]))" = "yes"], + [AC_DEFINE([HAVE_][$1], 1, [Enable ]m4_tolower([$1])[ support])]) +])dnl PKG_HAVE_DEFINE_WITH_MODULES Index: configure.ac ================================================================== --- configure.ac +++ configure.ac @@ -44,10 +44,11 @@ LDFLAGS="$LDFLAGS -noixemul" LIBS="$LIBS -ldebug" enable_files="yes" # Required for reading ENV: enable_shared="no" + with_tls="no" supports_amiga_lib="yes" AS_IF([test x"$enable_amiga_lib" != x"no"], [ AC_SUBST(OBJFW_AMIGA_LIB, 'objfw${OBJFW_LIB_MAJOR}.library') AC_SUBST(OBJFWRT_AMIGA_LIB, @@ -65,10 +66,11 @@ powerpc-*-amigaos*) CPPFLAGS="$CPPFLAGS -D__USE_INLINE__" enable_files="yes" # Required for reading ENV: enable_shared="no" + with_tls="no" AC_SUBST(LIBBASES_M, libbases.m) ;; *-morphos*) AS_IF([test x"$OBJCFLAGS" = x""], [OBJCFLAGS="-O2 -g"]) @@ -139,10 +141,15 @@ dnl also used for .S files. OBJCFLAGS="$OBJCFLAGS -include inttypes.h" dnl We need -latomic for GCC's atomics to work. LIBS="$LIBS -latomic" ;; +*-*-mint*) + enable_shared="no" + enable_threads="no" # TODO + with_tls="no" + ;; esac AS_IF([test x"$host_os" = x"msdosdjgpp" -a x"$build_os" = x"msdosdjgpp"], [ dnl Hack to make configure find these on DOS. : ${AR:=ar.exe} @@ -177,18 +184,43 @@ flags="-mrvl -mcpu=750 -meabi -mhard-float" OBJCFLAGS="$OBJCFLAGS $flags" OBJFW_OBJCFLAGS="$OBJFW_OBJCFLAGS $flags" CPPFLAGS="$CPPFLAGS -DGEKKO -I$DEVKITPRO/libogc/include" + OBJFW_CPPFLAGS="$OBJFW_CPPFLAGS -DGEKKO -I\$DEVKITPRO/libogc/include" LDFLAGS="$LDFLAGS -mrvl -mcpu=750 -meabi -mhard-float" LIBS="$LIBS -L$DEVKITPRO/libogc/lib/wii -lfat -logc" TESTS_LIBS="$TESTS_LIBS -lwiiuse -lbte" enable_shared="no" enable_threads="no" # TODO + with_tls="no" AC_DEFINE(OF_WII, 1, [Whether we are compiling for Wii]) - OBJFW_CPPFLAGS="$OBJFW_CPPFLAGS -DGEKKO -I\$DEVKITPRO/libogc/include" + AC_SUBST(MAP_LDFLAGS, ['-Wl,-Map,$@.map']) +]) + +AC_ARG_WITH(wii-u, + AS_HELP_STRING([--with-wii-u], [build for Wii U])) +AS_IF([test x"$with_wii_u" = x"yes"], [ + AS_IF([test x"$DEVKITPRO" = x""], [ + AC_MSG_ERROR([DEVKITPRO is not set! Please set DEVKITPRO.]) + ]) + + flags="-mcpu=750 -meabi -mhard-float" + OBJCFLAGS="$OBJCFLAGS $flags" + OBJFW_OBJCFLAGS="$OBJFW_OBJCFLAGS $flags" + CPPFLAGS="-isystem $DEVKITPRO/wut/include -D__WIIU__ -D__WUT__" + OBJFW_CPPFLAGS="$OBJFW_CPPFLAGS -isystem \$DEVKITPRO/wut/include" + OBJFW_CPPFLAGS="$OBJFW_CPPFLAGS -D__WIIU__ -D__WUT__" + LDFLAGS="-specs=$DEVKITPRO/wut/share/wut.specs" + LIBS="-L$DEVKITPRO/wut/lib -L$DEVKITPRO/wut/lib/stubs -lwut" + enable_files="no" # TODO + enable_shared="no" # TODO + enable_threads="no" # TODO + enable_sockets="no" # TODO + + AC_DEFINE(OF_WII_U, 1, [Whether we are compiling for Wii U]) AC_SUBST(MAP_LDFLAGS, ['-Wl,-Map,$@.map']) ]) AC_ARG_WITH(nds, AS_HELP_STRING([--with-nds], [build for Nintendo DS])) @@ -199,20 +231,20 @@ flags="-march=armv5te -mtune=arm946e-s -mthumb -mthumb-interwork" OBJCFLAGS="$OBJCFLAGS $flags" OBJFW_OBJCFLAGS="$OBJFW_OBJCFLAGS $flags" CPPFLAGS="$CPPFLAGS -DARM9 -I$DEVKITPRO/libnds/include" + OBJFW_CPPFLAGS="$OBJFW_CPPFLAGS -DARM9 -I\$DEVKITPRO/libnds/include" ASFLAGS="$ASFLAGS -march=armv5te" LDFLAGS="$LDFLAGS -specs=ds_arm9.specs" LIBS="$LIBS -L$DEVKITPRO/libnds/lib -lfilesystem -lfat -lnds9" enable_shared="no" enable_threads="no" # TODO enable_sockets="no" # TODO check_pedantic="no" AC_DEFINE(OF_NINTENDO_DS, 1, [Whether we are compiling for Nintendo DS]) - OBJFW_CPPFLAGS="$OBJFW_CPPFLAGS -DARM9 -I\$DEVKITPRO/libnds/include" AC_SUBST(MAP_LDFLAGS, ['-Wl,-Map,$@.map']) ]) AC_ARG_WITH(3ds, AS_HELP_STRING([--with-3ds], [build for Nintendo 3DS])) @@ -224,23 +256,48 @@ flags="-march=armv6k -mtune=mpcore -mfloat-abi=hard -mtp=soft" flags="$flags -mword-relocations" OBJCFLAGS="$OBJCFLAGS $flags" OBJFW_OBJCFLAGS="$OBJFW_OBJCFLAGS $flags" CPPFLAGS="$CPPFLAGS -DARM11 -I$DEVKITPRO/libctru/include" + OBJFW_CPPFLAGS="$OBJFW_CPPFLAGS -DARM11 -I\$DEVKITPRO/libctru/include" ASFLAGS="$ASFLAGS -march=armv6k" LDFLAGS="$LDFLAGS -specs=3dsx.specs -march=armv6k -mtune=mpcore" LDFLAGS="$LDFLAGS -mfloat-abi=hard -mtp=soft -mword-relocations" LIBS="$LIBS -L$DEVKITPRO/libctru/lib -lctru" enable_shared="no" enable_threads="no" # TODO + with_tls="no" check_pedantic="no" AC_DEFINE(OF_NINTENDO_3DS, 1, [Whether we are compiling for Nintendo 3DS]) - OBJFW_CPPFLAGS="$OBJFW_CPPFLAGS -DARM11 -I\$DEVKITPRO/libctru/include" AC_SUBST(MAP_LDFLAGS, ['-Wl,-Map,$@.map']) ]) + +AC_ARG_WITH(nintendo-switch, + AS_HELP_STRING([--with-nintendo-switch], [build for Nintendo Switch])) +AS_IF([test x"$with_nintendo_switch" = x"yes"], [ + AS_IF([test x"$DEVKITPRO" = x""], [ + AC_MSG_ERROR([DEVKITPRO is not set! Please set DEVKITPRO.]) + ]) + + flags="-march=armv8-a+crc+crypto -mtune=cortex-a57 -mtp=soft -fPIE" + OBJCFLAGS="$OBJCFLAGS $flags" + OBJFW_OBJCFLAGS="$OBJFW_OBJCFLAGS $flags" + CPPFLAGS="$CPPFLAGS -D__SWITCH__ -I$DEVKITPRO/libnx/include" + OBJFW_CPPFLAGS="$OBJFW_CPPFLAGS -D__SWITCH__ -I$DEVKITPRO/libnx/include" + ASFLAGS="$ASFLAGS $flags" + LDFLAGS="$LDFLAGS -specs=$DEVKITPRO/libnx/switch.specs $flags" + LIBS="$LIBS -L$DEVKITPRO/libnx/lib -lnx" + enable_shared="no" + enable_threads="yes" + enable_sockets="no" # TODO + check_pedantic="no" + + AC_DEFINE(OF_NINTENDO_SWITCH, 1, + [Whether we are compiling for Nintendo Switch]) +]) CPP="$OBJCPP" CPPFLAGS="$CPPFLAGS $OBJCPPFLAGS -DOF_COMPILING_OBJFW" flags="-fexceptions -fobjc-exceptions -funwind-tables" flags="$flags -fconstant-string-class=OFConstantString" @@ -434,11 +491,11 @@ AC_MSG_CHECKING(whether we need -D_GNU_SOURCE) AC_EGREP_CPP(egrep_cpp_yes, [ #include #if defined(__GLIBC__) || defined(__MINGW32__) || \ - defined(__NEWLIB__) || defined(__MORPHOS__) + defined(__NEWLIB__) || defined(__MORPHOS__) || defined(__MINT__) egrep_cpp_yes #endif ], [ AC_MSG_RESULT(yes) CPPFLAGS="-D_GNU_SOURCE $CPPFLAGS" @@ -648,10 +705,13 @@ OBJCFLAGS="$old_OBJCFLAGS" ;; esac case "$host_os" in +mint*) + dnl _Unwind_Backtrace crashes on MiNT + ;; hpux*) dnl _Unwind_Backtrace() returns complete garbage on HP-UX. ;; *) AC_CHECK_FUNCS(_Unwind_Backtrace) @@ -837,10 +897,14 @@ AC_CHECK_FUNCS(strtof truncf) AC_CHECK_FUNC(asprintf, [ case "$host" in + *-*-mint*) + dnl asprintf is not in headers + have_asprintf="no" + ;; *-*-mingw*) dnl asprintf from MinGW is broken on older Windows versions have_asprintf="no" ;; *-psp-*) @@ -1351,10 +1415,13 @@ AC_CHECK_HEADER(netinet/tcp.h, [ AC_DEFINE(OF_HAVE_NETINET_TCP_H, 1, [Whether we have netinet/tcp.h]) ]) AC_CHECK_HEADERS([arpa/inet.h netdb.h]) + AC_CHECK_HEADER(sys/un.h, [ + AC_DEFINE(OF_HAVE_SYS_UN_H, 1, [Whether we have sys/un.h]) + ]) AC_CHECK_HEADER(netipx/ipx.h, [ AC_DEFINE(OF_HAVE_NETIPX_IPX_H, 1, [Whether we have netipx/ipx.h]) ]) @@ -1407,10 +1474,44 @@ # endif # include # include #endif ]) + + AC_CHECK_HEADERS(afunix.h, [ + AC_DEFINE(OF_HAVE_AFUNIX_H, 1, [Whether we have afunix.h]) + ], [], [ + #ifdef _WIN32 + # include + #endif + ]) + AC_CHECK_MEMBER(struct sockaddr_un.sun_path, [ + AC_DEFINE(OF_HAVE_UNIX_SOCKETS, 1, + [Whether we have UNIX sockets]) + AC_SUBST(USE_SRCS_UNIX_SOCKETS, '${SRCS_UNIX_SOCKETS}') + ], [], [ + #ifdef OF_HAVE_SYS_TYPES_H + # include + #endif + #ifdef OF_HAVE_SYS_UN_H + # include + #endif + #ifdef _WIN32 + # include + #endif + #ifdef HAVE_AFUNIX_H + # include + #endif + + #ifdef __morphos__ + # error MorphOS has the struct but does not support it + #endif + + #ifdef __MINT__ + # error Gives invalid argument at runtime + #endif + ]) AC_CHECK_MEMBER(struct sockaddr_ipx.sipx_network, [], [ AC_CHECK_MEMBER(struct sockaddr_ipx.sa_netnum, [], [], [ #ifdef _WIN32 typedef int BOOL; @@ -1524,18 +1625,124 @@ AC_SUBST(OF_SELECT_KERNEL_EVENT_OBSERVER_M, "OFSelectKernelEventObserver.m") ]) ;; esac + + AC_ARG_WITH(tls, + AS_HELP_STRING([--with-tls], [ + enable TLS support using the specified library + (yes, openssl, gnutls, securetransport or no)])) + AS_IF([test x"$with_tls" = x""], [with_tls="yes"]) + tls_support="no" + + AS_IF([test x"$with_tls" = x"securetransport" \ + -o x"$with_tls" = x"yes"], [ + AC_CHECK_HEADERS(Security/SecureTransport.h, [ + old_LIBS="$LIBS" + LIBS="-framework Security -framework Foundation $LIBS" + + AC_CHECK_FUNC(SSLHandshake, [ + AC_DEFINE(HAVE_SECURE_TRANSPORT, 1, + [Whether we have Secure Transport]) + + tls_support="Secure Transport" + TLS_LIBS="-framework Foundation $TLS_LIBS" + TLS_LIBS="-framework Security $TLS_LIBS" + + AC_SUBST(OF_SECURE_TRANSPORT_TLS_STREAM_M, + "OFSecureTransportTLSStream.m") + + AC_CHECK_FUNCS(SSLCreateContext) + ], []) + + LIBS="$old_LIBS" + ]) + ]) + + AS_IF([test x"$with_tls" = x"openssl" \ + -o \( x"$with_tls" = x"yes" -a x"$tls_support" = x"no" \)], [ + case "$host_os" in + morphos*) + ssl="ssl_shared" + crypto="crypto_shared" + ;; + *) + ssl="ssl" + crypto="crypto" + ;; + esac + + AC_CHECK_LIB($ssl, SSL_set1_host, [ + AC_CHECK_HEADER(openssl/ssl.h, [ + AC_DEFINE(HAVE_OPENSSL, 1, + [Whether we have OpenSSL]) + + tls_support="OpenSSL" + TLS_LIBS="-l$ssl -l$crypto $TLS_LIBS" + + AC_SUBST(OF_OPENSSL_TLS_STREAM_M, + "OFOpenSSLTLSStream.m") + ]) + ], [], [-l$crypto]) + ]) + + AS_IF([test x"$with_tls" = x"gnutls" \ + -o \( x"$with_tls" = x"yes" -a x"$tls_support" = x"no" \)], [ + PKG_CHECK_MODULES(gnutls, [gnutls >= 3.5.0], [ + AC_DEFINE(HAVE_GNUTLS, 1, [Whether we have GnuTLS]) + + tls_support="GnuTLS" + TLS_CPPFLAGS="$gnutls_CFLAGS $TLS_CPPFLAGS" + TLS_LIBS="$gnutls_LIBS $TLS_LIBS" + + AC_SUBST(OF_GNUTLS_TLS_STREAM_M, "OFGnuTLSTLSStream.m") + ], [ + dnl Disable default action-if-not-found, which exits + dnl configure with an error. + : + ]) + ]) + + AS_IF([test x"$tls_support" != x"no"], [ + AC_SUBST(TLS, "tls") + AC_SUBST(TLS_CPPFLAGS) + AC_SUBST(TLS_LIBS) + AC_DEFINE(HAVE_TLS_SUPPORT, 1, + [Whether we have an implementation for TLS]) + AC_CONFIG_FILES(src/tls/Info.plist) + + OFHTTP_LIBS="-lobjfwtls $TLS_LIBS $OFHTTP_LIBS" + + AS_IF([test x"$enable_shared" != x"no"], [ + AC_SUBST(OBJFWTLS_SHARED_LIB, + "${LIB_PREFIX}objfwtls${LIB_SUFFIX}") + ]) + AS_IF([test x"$enable_static" = x"yes" \ + -o x"$enable_shared" = x"no"], [ + AC_SUBST(OBJFWTLS_STATIC_LIB, "libobjfwtls.a") + ]) + AS_IF([test x"$build_framework" = x"yes"], [ + AC_SUBST(OBJFWTLS_FRAMEWORK, "ObjFWTLS.framework") + ]) + ]) + + AS_IF([test x"$with_tls" != x"no" -a x"$tls_support" = x"no"], [ + AC_MSG_ERROR(m4_normalize([ + No TLS implementation was found. Please install OpenSSL, + GnuTLS or use --without-tls. + ])) + ]) AS_IF([test x"$enable_threads" != x"no"], [ AC_SUBST(OF_HTTP_CLIENT_TESTS_M, "OFHTTPClientTests.m") ]) AC_SUBST(OFDNS, "ofdns") AS_IF([test x"$enable_files" != x"no"], [ AC_SUBST(OFHTTP, "ofhttp") + AC_SUBST(OFHTTP_LIBS) ]) ]) AC_DEFUN([CHECK_BUILTIN_BSWAP], [ AC_MSG_CHECKING(for __builtin_bswap$1) @@ -1571,10 +1778,13 @@ egrep_cpp_yes #endif ], [ AC_MSG_RESULT(yes) have_subprocesses="yes" + + AC_CHECK_FUNCS(posix_spawnp) + AC_CHECK_HEADERS(spawn.h) ], [ AC_MSG_RESULT(no) have_subprocesses="no" ]) ;; Index: extra.mk.in ================================================================== --- extra.mk.in +++ extra.mk.in @@ -16,10 +16,14 @@ OBJFWBRIDGE_SHARED_LIB = @OBJFWBRIDGE_SHARED_LIB@ OBJFWBRIDGE_STATIC_LIB = @OBJFWBRIDGE_STATIC_LIB@ OBJFWBRIDGE_FRAMEWORK = @OBJFWBRIDGE_FRAMEWORK@ +OBJFWTLS_SHARED_LIB = @OBJFWTLS_SHARED_LIB@ +OBJFWTLS_STATIC_LIB = @OBJFWTLS_STATIC_LIB@ +OBJFWTLS_FRAMEWORK = @OBJFWTLS_FRAMEWORK@ + BIN_PREFIX = @BIN_PREFIX@ BRIDGE = @BRIDGE@ CVINCLUDE_INLINE_H = @CVINCLUDE_INLINE_H@ ENCODINGS_A = @ENCODINGS_A@ ENCODINGS_AMIGALIB_A = @ENCODINGS_AMIGALIB_A@ @@ -46,15 +50,19 @@ OBJFW_LIBS = @OBJFW_LIBS@ OFARC = @OFARC@ OFDNS = @OFDNS@ OFHASH = @OFHASH@ OFHTTP = @OFHTTP@ +OFHTTP_LIBS = @OFHTTP_LIBS@ OF_BLOCK_TESTS_M = @OF_BLOCK_TESTS_M@ OF_EPOLL_KERNEL_EVENT_OBSERVER_M = @OF_EPOLL_KERNEL_EVENT_OBSERVER_M@ +OF_GNUTLS_TLS_STREAM_M = @OF_GNUTLS_TLS_STREAM_M@ OF_HTTP_CLIENT_TESTS_M = @OF_HTTP_CLIENT_TESTS_M@ OF_KQUEUE_KERNEL_EVENT_OBSERVER_M = @OF_KQUEUE_KERNEL_EVENT_OBSERVER_M@ +OF_OPENSSL_TLS_STREAM_M = @OF_OPENSSL_TLS_STREAM_M@ OF_POLL_KERNEL_EVENT_OBSERVER_M = @OF_POLL_KERNEL_EVENT_OBSERVER_M@ +OF_SECURE_TRANSPORT_TLS_STREAM_M = @OF_SECURE_TRANSPORT_TLS_STREAM_M@ OF_SELECT_KERNEL_EVENT_OBSERVER_M = @OF_SELECT_KERNEL_EVENT_OBSERVER_M@ OF_SUBPROCESS_M = @OF_SUBPROCESS_M@ REEXPORT_RUNTIME = @REEXPORT_RUNTIME@ REEXPORT_RUNTIME_FRAMEWORK = @REEXPORT_RUNTIME_FRAMEWORK@ RUNTIME = @RUNTIME@ @@ -68,14 +76,18 @@ SFD_FILE = @SFD_FILE@ TESTPLUGIN = @TESTPLUGIN@ TESTPLUGIN_LIBS = @TESTPLUGIN_LIBS@ TESTS_LIBS = @TESTS_LIBS@ TESTS_STATIC_LIB = @TESTS_STATIC_LIB@ +TLS = @TLS@ +TLS_CPPFLAGS = @TLS_CPPFLAGS@ +TLS_LIBS = @TLS_LIBS@ UNICODE_M = @UNICODE_M@ USE_INCLUDES_ATOMIC = @USE_INCLUDES_ATOMIC@ USE_SRCS_FILES = @USE_SRCS_FILES@ USE_SRCS_IPX = @USE_SRCS_IPX@ USE_SRCS_PLUGINS = @USE_SRCS_PLUGINS@ USE_SRCS_SOCKETS = @USE_SRCS_SOCKETS@ USE_SRCS_THREADS = @USE_SRCS_THREADS@ +USE_SRCS_UNIX_SOCKETS = @USE_SRCS_UNIX_SOCKETS@ USE_SRCS_WINDOWS = @USE_SRCS_WINDOWS@ WRAPPER = @WRAPPER@ Index: generators/library/FuncArrayGenerator.h ================================================================== --- generators/library/FuncArrayGenerator.h +++ generators/library/FuncArrayGenerator.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: generators/library/FuncArrayGenerator.m ================================================================== --- generators/library/FuncArrayGenerator.m +++ generators/library/FuncArrayGenerator.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: generators/library/GlueGenerator.h ================================================================== --- generators/library/GlueGenerator.h +++ generators/library/GlueGenerator.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: generators/library/GlueGenerator.m ================================================================== --- generators/library/GlueGenerator.m +++ generators/library/GlueGenerator.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: generators/library/LibraryGenerator.m ================================================================== --- generators/library/LibraryGenerator.m +++ generators/library/LibraryGenerator.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -44,15 +44,23 @@ OFURL *glueURL = [sourcesURL URLByAppendingPathComponent: @"amiga-glue.m"]; OFURL *funcArrayURL = [sourcesURL URLByAppendingPathComponent: @"amiga-funcarray.inc"]; OFXMLElement *library = [OFXMLElement elementWithStream: - [OFFile fileWithURL: libraryURL mode: @"r"]]; - OFFile *linkLib = [OFFile fileWithURL: linkLibURL mode: @"w"]; - OFFile *glueHeader = [OFFile fileWithURL: glueHeaderURL mode: @"w"]; - OFFile *glue = [OFFile fileWithURL: glueURL mode: @"w"]; - OFFile *funcArray = [OFFile fileWithURL: funcArrayURL mode: @"w"]; + [OFFile fileWithPath: libraryURL.fileSystemRepresentation + mode: @"r"]]; + OFFile *linkLib = + [OFFile fileWithPath: linkLibURL.fileSystemRepresentation + mode: @"w"]; + OFFile *glueHeader = + [OFFile fileWithPath: glueHeaderURL.fileSystemRepresentation + mode: @"w"]; + OFFile *glue = + [OFFile fileWithPath: glueURL.fileSystemRepresentation mode: @"w"]; + OFFile *funcArray = + [OFFile fileWithPath: funcArrayURL.fileSystemRepresentation + mode: @"w"]; LinkLibGenerator *linkLibGenerator = [[[LinkLibGenerator alloc] initWithLibrary: library implementation: linkLib] autorelease]; GlueGenerator *glueGenerator = [[[GlueGenerator alloc] initWithLibrary: library Index: generators/library/LinkLibGenerator.h ================================================================== --- generators/library/LinkLibGenerator.h +++ generators/library/LinkLibGenerator.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: generators/library/LinkLibGenerator.m ================================================================== --- generators/library/LinkLibGenerator.m +++ generators/library/LinkLibGenerator.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: generators/library/copyright.h ================================================================== --- generators/library/copyright.h +++ generators/library/copyright.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -15,11 +15,11 @@ #import "OFString.h" #define COPYRIGHT \ @"/*\n" \ - @" * Copyright (c) 2008-2021 Jonathan Schleifer \n" \ + @" * Copyright (c) 2008-2022 Jonathan Schleifer \n" \ @" *\n" \ @" * All rights reserved.\n" \ @" *\n" \ @" * This file is part of ObjFW. It may be distributed under the terms " \ @"of the\n" \ Index: generators/unicode/TableGenerator.h ================================================================== --- generators/unicode/TableGenerator.h +++ generators/unicode/TableGenerator.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: generators/unicode/TableGenerator.m ================================================================== --- generators/unicode/TableGenerator.m +++ generators/unicode/TableGenerator.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -53,12 +53,12 @@ _titlecaseTableSize = SIZE_MAX; _caseFoldingTableSize = SIZE_MAX; _decompositionTableSize = SIZE_MAX; _decompositionCompatTableSize = SIZE_MAX; } @catch (id e) { - @throw e; [self release]; + @throw e; } return self; } Index: generators/unicode/copyright.h ================================================================== --- generators/unicode/copyright.h +++ generators/unicode/copyright.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -15,11 +15,11 @@ #import "OFString.h" #define COPYRIGHT \ @"/*\n" \ - @" * Copyright (c) 2008-2021 Jonathan Schleifer \n" \ + @" * Copyright (c) 2008-2022 Jonathan Schleifer \n" \ @" *\n" \ @" * All rights reserved.\n" \ @" *\n" \ @" * This file is part of ObjFW. It may be distributed under the terms " \ @"of the\n" \ Index: objfw.spec ================================================================== --- objfw.spec +++ objfw.spec @@ -1,15 +1,19 @@ %global libobjfw_major 0 %global libobjfw_minor 0 %global libobjfwrt_major 0 %global libobjfwrt_minor 0 +%global libobjfwtls_major 0 +%global libobjfwtls_minor 0 %if 0%{?suse_version} %global libobjfw_pkgname libobjfw%{libobjfw_major} %global libobjfwrt_pkgname libobjfwrt%{libobjfwrt_major} +%global libobjfwtls_pkgname libobjfwtls%{libobjfwtls_major} %else %global libobjfw_pkgname libobjfw %global libobjfwrt_pkgname libobjfwrt +%global libobjfwtls_pkgname libobjfwtls %endif Name: objfw Version: 1.1dev Release: 1%{?dist} @@ -26,10 +30,11 @@ BuildRequires: autoconf BuildRequires: automake BuildRequires: clang BuildRequires: make +BuildRequires: pkgconfig(openssl) 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} @@ -58,31 +63,46 @@ %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} +Summary: Header files, libraries and tools for %{libobjfw_pkgname} Requires: %{libobjfw_pkgname}%{_isa} = %{version}-%{release} Requires: %{libobjfwrt_pkgname}-devel = %{version}-%{release} %description -n %{libobjfw_pkgname}-devel -The %{libobjfw_pkgname}-devel package contains the header files and tools to -develop programs using ObjFW. +The %{libobjfw_pkgname}-devel package contains the header files, libraries and +tools to develop programs using ObjFW. %package -n %{libobjfwrt_pkgname} Summary: ObjFW Objective-C runtime library %description -n %{libobjfwrt_pkgname} The %{libobjfwrt_pkgname} package contains ObjFW's Objective-C runtime library. %package -n %{libobjfwrt_pkgname}-devel -Summary: Header files for %{libobjfwrt_pkgname} +Summary: Header files and libraries for %{libobjfwrt_pkgname} Requires: %{libobjfwrt_pkgname}%{_isa} = %{version}-%{release} %description -n %{libobjfwrt_pkgname}-devel -The %{libobjfwrt_pkgname}-devel package contains header files for ObjFW's -Objective-C runtime library. +The %{libobjfwrt_pkgname}-devel package contains header files and libraries for +ObjFW's Objective-C runtime library. + +%package -n %{libobjfwtls_pkgname} +Summary: TLS support for ObjFW +Requires: openssl%{_isa} >= 1.1.1 + +%description -n %{libobjfwtls_pkgname} +The %{libobjfwtls_pkgname} package contains TLS support for ObjFW + +%package -n %{libobjfwtls_pkgname}-devel +Summary: Header files and libraries for %{libobjfwtls_pkgname} +Requires: %{libobjfwtls_pkgname}%{_isa} = %{version}-%{release} + +%description -n %{libobjfwtls_pkgname}-devel +The %{libobjfwtls_pkgname}-devel package contains header files and libraries +for TLS support for ObjFW. %package -n ofarc Summary: Utility for handling ZIP, Tar and LHA archives Requires: %{libobjfw_pkgname}%{_isa} = %{version}-%{release} Requires: %{libobjfwrt_pkgname}%{_isa} = %{version}-%{release} @@ -113,10 +133,11 @@ %package -n ofhttp Summary: Command line downloader for HTTP(S) Requires: %{libobjfw_pkgname}%{_isa} = %{version}-%{release} Requires: %{libobjfwrt_pkgname}%{_isa} = %{version}-%{release} +Requires: %{libobjfwtls_pkgname}%{_isa} = %{version}-%{release} %description -n ofhttp ofhttp is a command line downloader for HTTP and HTTPS (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 @@ -125,11 +146,11 @@ %prep %autosetup ./autogen.sh %build -%configure --disable-rpath +%configure OBJC=clang --disable-rpath %make_build %install %make_install @@ -155,221 +176,12 @@ %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 +%dir %{_includedir}/ObjFW +%{_includedir}/ObjFW %{_bindir}/objfw-compile %{_bindir}/objfw-config %{_bindir}/objfw-new %license LICENSE.QPL %license LICENSE.GPLv3 @@ -384,10 +196,24 @@ %files -n %{libobjfwrt_pkgname}-devel %{_libdir}/libobjfwrt.so %{_includedir}/ObjFWRT/ObjFWRT.h %license LICENSE.QPL +%license LICENSE.GPLv3 +%license LICENSE.GPLv2 + +%files -n %{libobjfwtls_pkgname} +%{_libdir}/libobjfwtls.so.%{libobjfwtls_major} +%{_libdir}/libobjfwtls.so.%{libobjfwtls_major}.%{libobjfwtls_minor}.0 +%license LICENSE.QPL +%license LICENSE.GPLv3 +%license LICENSE.GPLv2 + +%files -n %{libobjfwtls_pkgname}-devel +%{_libdir}/libobjfwtls.so +%{_includedir}/ObjFWTLS/ObjFWTLS.h +%license LICENSE.QPL %license LICENSE.GPLv3 %license LICENSE.GPLv2 %files -n ofarc %{_bindir}/ofarc Index: src/Makefile ================================================================== --- src/Makefile +++ src/Makefile @@ -1,9 +1,9 @@ include ../extra.mk SUBDIRS = ${RUNTIME} exceptions encodings forwarding -SUBDIRS_AFTER = ${LINKLIB} ${BRIDGE} +SUBDIRS_AFTER = ${LINKLIB} ${BRIDGE} ${TLS} CLEAN = amiga-end.amigalib.dep \ amiga-end.amigalib.o \ amiga-glue.amigalib.dep \ amiga-glue.amigalib.o \ amiga-library-functable.inc \ @@ -17,40 +17,40 @@ FRAMEWORK = ${OBJFW_FRAMEWORK} AMIGA_LIB = ${OBJFW_AMIGA_LIB} LIB_MAJOR = ${OBJFW_LIB_MAJOR} LIB_MINOR = ${OBJFW_LIB_MINOR} -SRCS = OFASPrintF.m \ - OFApplication.m \ +SRCS = OFApplication.m \ OFArray.m \ - OFBase64.m \ OFBlock.m \ - OFCRC16.m \ - OFCRC32.m \ OFCharacterSet.m \ OFColor.m \ OFConstantString.m \ OFCountedSet.m \ OFData.m \ OFData+CryptographicHashing.m \ OFData+MessagePackParsing.m \ OFDate.m \ OFDictionary.m \ + OFEmbeddedFileURLHandler.m \ OFEnumerator.m \ OFFileManager.m \ OFGZIPStream.m \ OFHMAC.m \ - OFHuffmanTree.m \ + OFINICategory.m \ + OFINIFile.m \ + OFINIFileSettings.m \ OFInflate64Stream.m \ OFInflateStream.m \ OFInvocation.m \ OFLHAArchive.m \ OFLHAArchiveEntry.m \ OFList.m \ OFLocale.m \ OFMD5Hash.m \ OFMapTable.m \ + OFMemoryStream.m \ OFMessagePackExtension.m \ OFMethodSignature.m \ OFMutableArray.m \ OFMutableData.m \ OFMutableDictionary.m \ @@ -60,10 +60,12 @@ OFMutableString.m \ OFMutableTarArchiveEntry.m \ OFMutableTriple.m \ OFMutableURL.m \ OFMutableZIPArchiveEntry.m \ + OFNotification.m \ + OFNotificationCenter.m \ OFNull.m \ OFNumber.m \ OFObject.m \ OFObject+KeyValueCoding.m \ OFObject+Serialization.m \ @@ -85,29 +87,30 @@ OFSeekableStream.m \ OFSerialization.m \ OFSet.m \ OFSortedList.m \ OFStdIOStream.m \ - OFStrPTime.m \ OFStream.m \ OFString.m \ OFString+CryptographicHashing.m \ OFString+JSONParsing.m \ OFString+PropertyListParsing.m \ OFString+Serialization.m \ OFString+URLEncoding.m \ OFString+XMLEscaping.m \ OFString+XMLUnescaping.m \ - ${OF_SUBUPROCESS_M} \ + ${OF_SUBPROCESS_M} \ + OFSettings.m \ OFSystemInfo.m \ 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 \ @@ -123,17 +126,11 @@ ${USE_SRCS_PLUGINS} \ ${USE_SRCS_SOCKETS} \ ${USE_SRCS_THREADS} \ ${USE_SRCS_WINDOWS} SRCS_FILES = OFFile.m \ - OFINICategory.m \ - OFINIFile.m \ - OFSettings.m \ OFString+PathAdditions.m -SRCS_IPX = OFIPXSocket.m \ - OFSPXSocket.m \ - OFSPXStreamSocket.m SRCS_PLUGINS = OFPlugin.m SRCS_SOCKETS = OFDNSQuery.m \ OFDNSResolver.m \ OFDNSResourceRecord.m \ OFDNSResponse.m \ @@ -146,20 +143,26 @@ OFHTTPServer.m \ OFSequencedPacketSocket.m \ OFSocket.m \ OFStreamSocket.m \ OFTCPSocket.m \ + OFTLSStream.m \ OFUDPSocket.m \ - ${USE_SRCS_IPX} + ${USE_SRCS_IPX} \ + ${USE_SRCS_UNIX_SOCKETS} +SRCS_IPX = OFIPXSocket.m \ + OFSPXSocket.m \ + OFSPXStreamSocket.m +SRCS_UNIX_SOCKETS = OFUNIXDatagramSocket.m \ + OFUNIXStreamSocket.m SRCS_THREADS = OFCondition.m \ OFMutex.m \ OFPlainCondition.m \ OFPlainMutex.m \ OFPlainThread.m \ OFRecursiveMutex.m \ - OFTLSKey.m \ - OFThreadPool.m + OFTLSKey.m SRCS_WINDOWS = OFWin32ConsoleStdIOStream.m \ OFWindowsRegistryKey.m INCLUDES_ATOMIC = OFAtomic.h \ platform/GCC4/OFAtomic.h \ @@ -173,22 +176,26 @@ OFJSONRepresentation.h \ OFKernelEventObserver.h \ OFKeyValueCoding.h \ OFLocking.h \ OFMessagePackRepresentation.h \ - OFTLSSocket.h \ ObjFW.h \ macros.h \ objfw-defs.h \ platform.h \ ${USE_INCLUDES_ATOMIC} -SRCS += OFAdjacentArray.m \ +SRCS += OFASPrintF.m \ + OFAdjacentArray.m \ OFAdjacentSubarray.m \ + OFBase64.m \ OFBitSetCharacterSet.m \ OFBytesValue.m \ + OFCRC16.m \ + OFCRC32.m \ OFCountedMapTableSet.m \ + OFHuffmanTree.m \ OFInvertedCharacterSet.m \ OFLHADecompressingStream.m \ OFMapTableDictionary.m \ OFMapTableSet.m \ OFMutableAdjacentArray.m \ @@ -201,24 +208,24 @@ OFRangeCharacterSet.m \ OFRangeValue.m \ OFRectValue.m \ OFSandbox.m \ OFSizeValue.m \ + OFStrPTime.m \ OFSubarray.m \ OFUTF8String.m \ ${LIBBASES_M} \ ${RUNTIME_AUTORELEASE_M} \ ${RUNTIME_INSTANCE_M} \ ${UNICODE_M} -SRCS_FILES += OFFileURLHandler.m \ - OFINIFileSettings.m +SRCS_FILES += OFFileURLHandler.m SRCS_SOCKETS += OFDNSResolverSettings.m \ + ${OF_EPOLL_KERNEL_EVENT_OBSERVER_M} \ OFHTTPURLHandler.m \ OFHostAddressResolver.m \ OFIPSocketAsyncConnector.m \ OFKernelEventObserver.m \ - ${OF_EPOLL_KERNEL_EVENT_OBSERVER_M} \ ${OF_KQUEUE_KERNEL_EVENT_OBSERVER_M} \ ${OF_POLL_KERNEL_EVENT_OBSERVER_M} \ ${OF_SELECT_KERNEL_EVENT_OBSERVER_M} \ OFTCPSocketSOCKS5Connector.m Index: src/OFASPrintF.h ================================================================== --- src/OFASPrintF.h +++ src/OFASPrintF.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFASPrintF.m ================================================================== --- src/OFASPrintF.m +++ src/OFASPrintF.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFAdjacentArray.h ================================================================== --- src/OFAdjacentArray.h +++ src/OFAdjacentArray.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFAdjacentArray.m ================================================================== --- src/OFAdjacentArray.m +++ src/OFAdjacentArray.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFAdjacentSubarray.h ================================================================== --- src/OFAdjacentSubarray.h +++ src/OFAdjacentSubarray.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFAdjacentSubarray.m ================================================================== --- src/OFAdjacentSubarray.m +++ src/OFAdjacentSubarray.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFApplication.h ================================================================== --- src/OFApplication.h +++ src/OFApplication.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -14,10 +14,11 @@ */ #include #import "OFObject.h" +#import "OFNotification.h" OF_ASSUME_NONNULL_BEGIN /** @file */ @@ -26,10 +27,15 @@ @class OFMutableArray OF_GENERIC(ObjectType); @class OFMutableDictionary OF_GENERIC(KeyType, ObjectType); @class OFSandbox; @class OFString; +/** + * @brief A notification that will be sent when the application will terminate. + */ +extern const OFNotificationName OFApplicationWillTerminateNotification; + /** * @brief Specify the class to be used as the application delegate. * * An instance of this class will be created and act as the application * delegate. @@ -143,10 +149,14 @@ * @brief A class which represents the application as an object. * * In order to create a new OFApplication, you should create a class conforming * to the optional @ref OFApplicationDelegate protocol and put * `OF_APPLICATION_DELEGATE(NameOfYourClass)` in the .m file of that class. + * + * When the application is about to be terminated, + * @ref OFApplicationDelegate#applicationWillTerminate will be called on the + * delegate and an @ref OFApplicationWillTerminateNotification will be sent. */ OF_SUBCLASSING_RESTRICTED @interface OFApplication: OFObject { OFString *_programName; Index: src/OFApplication.m ================================================================== --- src/OFApplication.m +++ src/OFApplication.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -30,10 +30,11 @@ #ifdef OF_AMIGAOS # import "OFFile.h" # import "OFFileManager.h" #endif #import "OFLocale.h" +#import "OFNotificationCenter.h" #import "OFPair.h" #import "OFRunLoop+Private.h" #import "OFRunLoop.h" #import "OFSandbox.h" #import "OFString.h" @@ -73,21 +74,30 @@ OF_DIRECT_MEMBERS @interface OFApplication () - (instancetype)of_init OF_METHOD_FAMILY(init); - (void)of_setArgumentCount: (int *)argc andArgumentValues: (char **[])argv; #ifdef OF_WINDOWS -- (void)of_setArgumentCount: (int)argc andWideArgumentValues: (wchar_t *[])argv; +- (void)of_setArgumentCount: (int *)argc + andArgumentValues: (char **[])argv + andWideArgumentCount: (int)wargc + andWideArgumentValues: (wchar_t *[])wargv; #endif - (void)of_run; @end +const OFNotificationName OFApplicationWillTerminateNotification = + @"OFApplicationWillTerminateNotification"; static OFApplication *app = nil; static void atexitHandler(void) { id delegate = app.delegate; + + [[OFNotificationCenter defaultCenter] + postNotificationName: OFApplicationWillTerminateNotification + object: app]; if ([delegate respondsToSelector: @selector(applicationWillTerminate)]) [delegate applicationWillTerminate]; [delegate release]; @@ -111,11 +121,14 @@ app = [[OFApplication alloc] of_init]; #ifdef OF_WINDOWS if ([OFSystemInfo isWindowsNT]) { __wgetmainargs(&wargc, &wargv, &wenvp, _CRT_glob, &si); - [app of_setArgumentCount: wargc andWideArgumentValues: wargv]; + [app of_setArgumentCount: argc + andArgumentValues: argv + andWideArgumentCount: wargc + andWideArgumentValues: wargv]; } else #endif [app of_setArgumentCount: argc andArgumentValues: argv]; app.delegate = delegate; @@ -460,11 +473,11 @@ [_environment release]; [super dealloc]; } -- (void)of_setArgumentCount: (int *)argc andArgumentValues: (char ***)argv +- (void)of_setArgumentCount: (int *)argc andArgumentValues: (char **[])argv { void *pool = objc_autoreleasePoolPush(); OFMutableArray *arguments; OFStringEncoding encoding; @@ -493,22 +506,28 @@ objc_autoreleasePoolPop(pool); } #ifdef OF_WINDOWS -- (void)of_setArgumentCount: (int)argc andWideArgumentValues: (wchar_t **)argv +- (void)of_setArgumentCount: (int *)argc + andArgumentValues: (char **[])argv + andWideArgumentCount: (int)wargc + andWideArgumentValues: (wchar_t *[])wargv { void *pool = objc_autoreleasePoolPush(); OFMutableArray *arguments; - if (argc > 0) { - _programName = [[OFString alloc] initWithUTF16String: argv[0]]; + _argc = argc; + _argv = argv; + + if (wargc > 0) { + _programName = [[OFString alloc] initWithUTF16String: wargv[0]]; arguments = [[OFMutableArray alloc] init]; - for (int i = 1; i < argc; i++) + for (int i = 1; i < wargc; i++) [arguments addObject: - [OFString stringWithUTF16String: argv[i]]]; + [OFString stringWithUTF16String: wargv[i]]]; [arguments makeImmutable]; _arguments = arguments; } Index: src/OFArray+Private.h ================================================================== --- src/OFArray+Private.h +++ src/OFArray+Private.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFArray.h ================================================================== --- src/OFArray.h +++ src/OFArray.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -180,13 +180,12 @@ * * @param objects A C array of objects * @param count The length of the C array * @return A new autoreleased OFArray */ -+ (instancetype) - arrayWithObjects: (ObjectType const _Nonnull *_Nonnull)objects - count: (size_t)count; ++ (instancetype)arrayWithObjects: (ObjectType const _Nonnull *_Nonnull)objects + count: (size_t)count; /** * @brief Initializes an OFArray with the specified object. * * @param object An object @@ -435,18 +434,10 @@ * @return A new array with the objects from the specified array added */ - (OFArray OF_GENERIC(ObjectType) *)arrayByAddingObjectsFromArray: (OFArray OF_GENERIC(ObjectType) *)array; -/** - * @brief Creates a new array with the specified object removed. - * - * @param object The object to remove - * @return A new array with the specified object removed - */ -- (OFArray OF_GENERIC(ObjectType) *)arrayByRemovingObject: (ObjectType)object; - #ifdef OF_HAVE_BLOCKS /** * @brief Executes a block for each object. * * @param block The block to execute for each object Index: src/OFArray.m ================================================================== --- src/OFArray.m +++ src/OFArray.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -813,18 +813,10 @@ [ret makeImmutable]; return ret; } -- (OFArray *)arrayByRemovingObject: (id)object -{ - OFMutableArray *ret = [[self mutableCopy] autorelease]; - [ret removeObject: object]; - [ret makeImmutable]; - return ret; -} - #ifdef OF_HAVE_BLOCKS - (OFArray *)mappedArrayUsingBlock: (OFArrayMapBlock)block { OFArray *ret; size_t count = self.count; Index: src/OFAtomic.h ================================================================== --- src/OFAtomic.h +++ src/OFAtomic.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFBase64.h ================================================================== --- src/OFBase64.h +++ src/OFBase64.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFBase64.m ================================================================== --- src/OFBase64.m +++ src/OFBase64.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFBitSetCharacterSet.h ================================================================== --- src/OFBitSetCharacterSet.h +++ src/OFBitSetCharacterSet.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFBitSetCharacterSet.m ================================================================== --- src/OFBitSetCharacterSet.m +++ src/OFBitSetCharacterSet.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFBlock.h ================================================================== --- src/OFBlock.h +++ src/OFBlock.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFBlock.m ================================================================== --- src/OFBlock.m +++ src/OFBlock.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFBytesValue.h ================================================================== --- src/OFBytesValue.h +++ src/OFBytesValue.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFBytesValue.m ================================================================== --- src/OFBytesValue.m +++ src/OFBytesValue.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFCRC16.h ================================================================== --- src/OFCRC16.h +++ src/OFCRC16.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFCRC16.m ================================================================== --- src/OFCRC16.m +++ src/OFCRC16.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFCRC32.h ================================================================== --- src/OFCRC32.h +++ src/OFCRC32.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFCRC32.m ================================================================== --- src/OFCRC32.m +++ src/OFCRC32.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFCharacterSet.h ================================================================== --- src/OFCharacterSet.h +++ src/OFCharacterSet.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFCharacterSet.m ================================================================== --- src/OFCharacterSet.m +++ src/OFCharacterSet.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFCollection.h ================================================================== --- src/OFCollection.h +++ src/OFCollection.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFColor.h ================================================================== --- src/OFColor.h +++ src/OFColor.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFColor.m ================================================================== --- src/OFColor.m +++ src/OFColor.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFCondition.h ================================================================== --- src/OFCondition.h +++ src/OFCondition.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFCondition.m ================================================================== --- src/OFCondition.m +++ src/OFCondition.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFConstantString.h ================================================================== --- src/OFConstantString.h +++ src/OFConstantString.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFConstantString.m ================================================================== --- src/OFConstantString.m +++ src/OFConstantString.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -347,10 +347,16 @@ - (OFString *)stringByAppendingPathComponent: (OFString *)component { [self finishInitialization]; return [self stringByAppendingPathComponent: component]; } + +- (OFString *)stringByAppendingPathExtension: (OFString *)extension +{ + [self finishInitialization]; + return [self stringByAppendingPathExtension: extension]; +} - (OFString *)stringByPrependingString: (OFString *)string { [self finishInitialization]; return [self stringByPrependingString: string]; Index: src/OFCountedMapTableSet.h ================================================================== --- src/OFCountedMapTableSet.h +++ src/OFCountedMapTableSet.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFCountedMapTableSet.m ================================================================== --- src/OFCountedMapTableSet.m +++ src/OFCountedMapTableSet.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -41,11 +41,11 @@ @try { void *pool = objc_autoreleasePoolPush(); if ([set isKindOfClass: [OFCountedSet class]]) { - OFCountedSet *countedSet = (OFCountedSet *)countedSet; + OFCountedSet *countedSet = (OFCountedSet *)set; for (id object in countedSet) { size_t count = [countedSet countForObject: object]; Index: src/OFCountedSet.h ================================================================== --- src/OFCountedSet.h +++ src/OFCountedSet.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFCountedSet.m ================================================================== --- src/OFCountedSet.m +++ src/OFCountedSet.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFCryptographicHash.h ================================================================== --- src/OFCryptographicHash.h +++ src/OFCryptographicHash.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -98,10 +98,15 @@ * @param buffer The buffer which should be included into the calculation * @param length The length of the buffer */ - (void)updateWithBuffer: (const void *)buffer length: (size_t)length; +/** + * @brief Performs the final calculation of the cryptographic hash. + */ +- (void)calculate; + /** * @brief Resets all state so that a new hash can be calculated. * * @warning This invalidates any pointer previously returned by @ref digest. If * you are still interested in the previous digest, you need to memcpy Index: src/OFDNSQuery.h ================================================================== --- src/OFDNSQuery.h +++ src/OFDNSQuery.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFDNSQuery.m ================================================================== --- src/OFDNSQuery.m +++ src/OFDNSQuery.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFDNSResolver.h ================================================================== --- src/OFDNSResolver.h +++ src/OFDNSResolver.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFDNSResolver.m ================================================================== --- src/OFDNSResolver.m +++ src/OFDNSResolver.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -37,10 +37,11 @@ #import "OFDNSQueryFailedException.h" #import "OFInitializationFailedException.h" #import "OFInvalidArgumentException.h" #import "OFInvalidFormatException.h" #import "OFInvalidServerReplyException.h" +#import "OFNotImplementedException.h" #import "OFOutOfRangeException.h" #import "OFTruncatedDataException.h" #ifndef SOCK_DNS # define SOCK_DNS 0 @@ -745,11 +746,15 @@ OFSocketAddressParseIPv6(@"::", 0); _IPv6Socket = [[OFUDPSocket alloc] init]; [_IPv6Socket of_bindToAddress: &address extraType: SOCK_DNS]; - _IPv6Socket.canBlock = false; + @try { + _IPv6Socket.canBlock = false; + } @catch (OFNotImplementedException *e) { + /* Can't do anything about it... */ + } _IPv6Socket.delegate = self; } sock = _IPv6Socket; break; @@ -760,11 +765,15 @@ OFSocketAddressParseIPv4(@"0.0.0.0", 0); _IPv4Socket = [[OFUDPSocket alloc] init]; [_IPv4Socket of_bindToAddress: &address extraType: SOCK_DNS]; - _IPv4Socket.canBlock = false; + @try { + _IPv4Socket.canBlock = false; + } @catch (OFNotImplementedException *e) { + /* Can't do anything about it... */ + } _IPv4Socket.delegate = self; } sock = _IPv4Socket; break; Index: src/OFDNSResolverSettings.h ================================================================== --- src/OFDNSResolverSettings.h +++ src/OFDNSResolverSettings.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFDNSResolverSettings.m ================================================================== --- src/OFDNSResolverSettings.m +++ src/OFDNSResolverSettings.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -64,10 +64,14 @@ # define RESOLV_CONF_PATH @"AmiTCP:db/resolv.conf" #else # define HOSTS_PATH @"/etc/hosts" # define RESOLV_CONF_PATH @"/etc/resolv.conf" #endif + +#ifndef HOST_NAME_MAX +# define HOST_NAME_MAX 255 +#endif #ifndef OF_WII static OFString * domainFromHostname(OFString *hostname) { @@ -100,13 +104,13 @@ #if !defined(OF_WII) && !defined(OF_MORPHOS) static OFString * obtainHostname(void) { - char hostname[256]; + char hostname[HOST_NAME_MAX + 1]; - if (gethostname(hostname, 256) != 0) + if (gethostname(hostname, HOST_NAME_MAX + 1) != 0) return nil; return [OFString stringWithCString: hostname encoding: [OFLocale encoding]]; } Index: src/OFDNSResourceRecord.h ================================================================== --- src/OFDNSResourceRecord.h +++ src/OFDNSResourceRecord.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFDNSResourceRecord.m ================================================================== --- src/OFDNSResourceRecord.m +++ src/OFDNSResourceRecord.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFDNSResponse.h ================================================================== --- src/OFDNSResponse.h +++ src/OFDNSResponse.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFDNSResponse.m ================================================================== --- src/OFDNSResponse.m +++ src/OFDNSResponse.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -54,11 +54,11 @@ } return self; } -- (instancetype)init OF_UNAVAILABLE +- (instancetype)init { OF_INVALID_INIT_METHOD } - (void)dealloc Index: src/OFData+CryptographicHashing.h ================================================================== --- src/OFData+CryptographicHashing.h +++ src/OFData+CryptographicHashing.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFData+CryptographicHashing.m ================================================================== --- src/OFData+CryptographicHashing.m +++ src/OFData+CryptographicHashing.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -39,10 +39,11 @@ const unsigned char *digest; char cString[digestSize * 2]; [hash updateWithBuffer: self->_items length: self->_count * self->_itemSize]; + [hash calculate]; digest = hash.digest; for (size_t i = 0; i < digestSize; i++) { uint8_t high, low; Index: src/OFData+MessagePackParsing.h ================================================================== --- src/OFData+MessagePackParsing.h +++ src/OFData+MessagePackParsing.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFData+MessagePackParsing.m ================================================================== --- src/OFData+MessagePackParsing.m +++ src/OFData+MessagePackParsing.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFData.h ================================================================== --- src/OFData.h +++ src/OFData.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -43,15 +43,15 @@ * for OFData with item size 1. */ @interface OFData: OFObject { - unsigned char *_items; + unsigned char *_Nullable _items; size_t _count, _itemSize; bool _freeWhenDone; @private - OFData *_parentData; + OFData *_Nullable _parentData; OF_RESERVE_IVARS(OFData, 4) } /** * @brief The size of a single item in the OFData in bytes. @@ -66,11 +66,12 @@ /** * @brief All elements of the OFData as a C array. * * @warning The pointer is only valid until the OFData is changed! */ -@property (readonly, nonatomic) const void *items OF_RETURNS_INNER_POINTER; +@property OF_NULLABLE_PROPERTY (readonly, nonatomic) const void *items + OF_RETURNS_INNER_POINTER; /** * @brief The first item of the OFData or `NULL`. */ @property OF_NULLABLE_PROPERTY (readonly, nonatomic) const void *firstItem @@ -173,13 +174,13 @@ */ + (instancetype)dataWithContentsOfURL: (OFURL *)URL; /** * @brief Creates a new OFData with an item size of 1, containing the data of - * the string representation. + * the hex string representation. * - * @param string The string representation of the data + * @param string The hex string representation of the data * @return A new autoreleased OFData */ + (instancetype)dataWithStringRepresentation: (OFString *)string; /** @@ -190,21 +191,21 @@ * @return A new autoreleased OFData */ + (instancetype)dataWithBase64EncodedString: (OFString *)string; /** - * @brief Initialized an already allocated OFData with the specified `count` + * @brief Initializes an already allocated OFData with the specified `count` * items of size 1. * * @param items The items to store in the OFData * @param count The number of items * @return An initialized OFData */ - (instancetype)initWithItems: (const void *)items count: (size_t)count; /** - * @brief Initialized an already allocated OFData with the specified `count` + * @brief Initializes an already allocated OFData with the specified `count` * items of the specified size. * * @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 @@ -272,13 +273,13 @@ */ - (instancetype)initWithContentsOfURL: (OFURL *)URL; /** * @brief Initializes an already allocated OFData with an item size of 1, - * containing the data of the string representation. + * containing the data of the hex string representation. * - * @param string The string representation of the data + * @param string The hex string representation of the data * @return A new autoreleased OFData */ - (instancetype)initWithStringRepresentation: (OFString *)string; /** Index: src/OFData.m ================================================================== --- src/OFData.m +++ src/OFData.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFDatagramSocket.h ================================================================== --- src/OFDatagramSocket.h +++ src/OFDatagramSocket.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -39,18 +39,15 @@ const OFSocketAddress *_Nonnull sender, id _Nullable exception); /** * @brief A block which is called when a packet has been sent. * - * @param data The data which was sent - * @param receiver The receiver for the packet * @param exception An exception which occurred while reading or `nil` on * success * @return The data to repeat the send with or nil if it should not repeat */ typedef OFData *_Nullable (^OFDatagramSocketAsyncSendDataBlock)( - OFData *_Nonnull data, const OFSocketAddress *_Nonnull receiver, id _Nullable exception); #endif /** * @protocol OFDatagramSocketDelegate OFDatagramSocket.h \ Index: src/OFDatagramSocket.m ================================================================== --- src/OFDatagramSocket.m +++ src/OFDatagramSocket.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -175,35 +175,40 @@ sender->length = (socklen_t)sizeof(sender->sockaddr); #ifndef OF_WINDOWS if ((ret = recvfrom(_socket, buffer, length, 0, - &sender->sockaddr.sockaddr, &sender->length)) < 0) + (struct sockaddr *)&sender->sockaddr, &sender->length)) < 0) @throw [OFReadFailedException exceptionWithObject: self requestedLength: length errNo: OFSocketErrNo()]; #else if (length > INT_MAX) @throw [OFOutOfRangeException exception]; if ((ret = recvfrom(_socket, buffer, (int)length, 0, - &sender->sockaddr.sockaddr, &sender->length)) < 0) + (struct sockaddr *)&sender->sockaddr, &sender->length)) < 0) @throw [OFReadFailedException exceptionWithObject: self requestedLength: length errNo: OFSocketErrNo()]; #endif - switch (sender->sockaddr.sockaddr.sa_family) { + switch (((struct sockaddr *)&sender->sockaddr)->sa_family) { case AF_INET: sender->family = OFSocketAddressFamilyIPv4; break; #ifdef OF_HAVE_IPV6 case AF_INET6: sender->family = OFSocketAddressFamilyIPv6; break; +#endif +#ifdef OF_HAVE_UNIX_SOCKETS + case AF_UNIX: + sender->family = OFSocketAddressFamilyUNIX; + break; #endif #ifdef OF_HAVE_IPX case AF_IPX: sender->family = OFSocketAddressFamilyIPX; break; @@ -274,12 +279,11 @@ if (length > SSIZE_MAX) @throw [OFOutOfRangeException exception]; if ((bytesWritten = sendto(_socket, (void *)buffer, length, 0, - (struct sockaddr *)&receiver->sockaddr.sockaddr, - receiver->length)) < 0) + (struct sockaddr *)&receiver->sockaddr, receiver->length)) < 0) @throw [OFWriteFailedException exceptionWithObject: self requestedLength: length bytesWritten: 0 errNo: OFSocketErrNo()]; @@ -288,11 +292,11 @@ if (length > INT_MAX) @throw [OFOutOfRangeException exception]; if ((bytesWritten = sendto(_socket, buffer, (int)length, 0, - &receiver->sockaddr.sockaddr, receiver->length)) < 0) + (struct sockaddr *)&receiver->sockaddr, receiver->length)) < 0) @throw [OFWriteFailedException exceptionWithObject: self requestedLength: length bytesWritten: 0 errNo: OFSocketErrNo()]; Index: src/OFDate.h ================================================================== --- src/OFDate.h +++ src/OFDate.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFDate.m ================================================================== --- src/OFDate.m +++ src/OFDate.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -39,12 +39,12 @@ #import "OFInvalidArgumentException.h" #import "OFInvalidFormatException.h" #import "OFOutOfMemoryException.h" #import "OFOutOfRangeException.h" -#ifdef OF_AMIGAOS_M68K -/* amiga-gcc does not have trunc() */ +#if defined(OF_AMIGAOS_M68K) || defined(OF_MINT) +/* amiga-gcc and freemint-gcc do not have trunc() */ # define trunc(x) ((int64_t)(x)) #endif @interface OFDate () + (instancetype)of_alloc; Index: src/OFDictionary.h ================================================================== --- src/OFDictionary.h +++ src/OFDictionary.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -32,12 +32,36 @@ OF_ASSUME_NONNULL_BEGIN @class OFArray OF_GENERIC(ObjectType); #ifdef OF_HAVE_BLOCKS +/** + * @brief A block for enumerating an OFDictionary. + * + * @param key The current key + * @param object The object for the current key + * @param stop A pointer to a variable that can be set to true to stop the + * enumeration. + */ typedef void (^OFDictionaryEnumerationBlock)(id key, id object, bool *stop); + +/** + * @brief A block for filtering an OFDictionary. + * + * @param key The key to inspect + * @param object The object for the key to inspect + * @return Whether the object should be in the filtered dictionary. + */ typedef bool (^OFDictionaryFilterBlock)(id key, id object); + +/** + * @brief A block for mapping keys to objects in an OFDictionary. + * + * @param key The key to map + * @param object The current object for the key + * @return The object to map the key to + */ typedef id _Nonnull (^OFDictionaryMapBlock)(id key, id object); #endif /** * @class OFDictionary OFDictionary.h ObjFW/OFDictionary.h @@ -104,13 +128,12 @@ * * @param keys An array of keys * @param objects An array of objects * @return A new autoreleased OFDictionary */ -+ (instancetype) - dictionaryWithObjects: (OFArray OF_GENERIC(ObjectType) *)objects - forKeys: (OFArray OF_GENERIC(KeyType) *)keys; ++ (instancetype)dictionaryWithObjects: (OFArray OF_GENERIC(ObjectType) *)objects + forKeys: (OFArray OF_GENERIC(KeyType) *)keys; /** * @brief Creates a new OFDictionary with the specified keys and objects. * * @param keys An array of keys Index: src/OFDictionary.m ================================================================== --- src/OFDictionary.m +++ src/OFDictionary.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in ADDED src/OFEmbeddedFileURLHandler.h Index: src/OFEmbeddedFileURLHandler.h ================================================================== --- src/OFEmbeddedFileURLHandler.h +++ src/OFEmbeddedFileURLHandler.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2008-2022 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either 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 "OFURLHandler.h" + +OF_ASSUME_NONNULL_BEGIN + +@interface OFEmbeddedFileURLHandler: OFURLHandler +@end + +OF_ASSUME_NONNULL_END ADDED src/OFEmbeddedFileURLHandler.m Index: src/OFEmbeddedFileURLHandler.m ================================================================== --- src/OFEmbeddedFileURLHandler.m +++ src/OFEmbeddedFileURLHandler.m @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2008-2022 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 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 +#include +#include + +#import "OFEmbeddedFileURLHandler.h" +#import "OFMemoryStream.h" +#import "OFURL.h" + +#import "OFInvalidArgumentException.h" +#import "OFOpenItemFailedException.h" + +#ifdef OF_HAVE_THREADS +# import "OFOnce.h" +# import "OFPlainMutex.h" +#endif + +struct EmbeddedFile { + const char *name; + const uint8_t *bytes; + size_t size; +} *embeddedFiles = NULL; +size_t numEmbeddedFiles = 0; +#ifdef OF_HAVE_THREADS +static OFPlainMutex mutex; + +static void +init(void) +{ + OFEnsure(OFPlainMutexNew(&mutex) == 0); +} +#endif + +void +OFRegisterEmbeddedFile(const char *name, const uint8_t *bytes, size_t size) +{ +#ifdef OF_HAVE_THREADS + static OFOnceControl onceControl = OFOnceControlInitValue; + OFOnce(&onceControl, init); + + OFEnsure(OFPlainMutexLock(&mutex) == 0); +#endif + + embeddedFiles = realloc(embeddedFiles, + sizeof(*embeddedFiles) * (numEmbeddedFiles + 1)); + OFEnsure(embeddedFiles != NULL); + + embeddedFiles[numEmbeddedFiles].name = name; + embeddedFiles[numEmbeddedFiles].bytes = bytes; + embeddedFiles[numEmbeddedFiles].size = size; + numEmbeddedFiles++; + +#ifdef OF_HAVE_THREADS + OFEnsure(OFPlainMutexUnlock(&mutex) == 0); +#endif +} + +@implementation OFEmbeddedFileURLHandler +- (OFStream *)openItemAtURL: (OFURL *)URL mode: (OFString *)mode +{ + const char *path; + + if (![URL.scheme isEqual: @"objfw-embedded"] || URL.host != nil || + URL.port != nil || URL.user != nil || URL.password != nil || + URL.query != nil || URL.fragment != nil) + @throw [OFInvalidArgumentException exception]; + + if (![mode isEqual: @"r"]) + @throw [OFOpenItemFailedException exceptionWithURL: URL + mode: mode + errNo: EROFS]; + + if ((path = URL.path.UTF8String) == NULL) { + @throw [OFInvalidArgumentException exception]; + } + +#ifdef OF_HAVE_THREADS + OFEnsure(OFPlainMutexLock(&mutex) == 0); + @try { +#endif + for (size_t i = 0; i < numEmbeddedFiles; i++) { + if (strcmp(embeddedFiles[i].name, path) != 0) + continue; + + return [OFMemoryStream + streamWithMemoryAddress: (void *) + embeddedFiles[i].bytes + size: embeddedFiles[i].size + writable: false]; + } +#ifdef OF_HAVE_THREADS + } @finally { + OFEnsure(OFPlainMutexUnlock(&mutex) == 0); + } +#endif + + @throw [OFOpenItemFailedException exceptionWithURL: URL + mode: mode + errNo: ENOENT]; +} +@end Index: src/OFEnumerator.h ================================================================== --- src/OFEnumerator.h +++ src/OFEnumerator.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -48,12 +48,10 @@ /** * @struct OFFastEnumerationState OFEnumerator.h ObjFW/OFEnumerator.h * * @brief State information for fast enumerations. */ -#define OFFastEnumerationState NSFastEnumerationState -#ifndef NSINTEGER_DEFINED typedef struct { /** Arbitrary state information for the enumeration */ unsigned long state; /** Pointer to a C array of objects to return */ id __unsafe_unretained _Nullable *_Nullable itemsPtr; @@ -60,10 +58,12 @@ /** Arbitrary state information to detect mutations */ unsigned long *_Nullable mutationsPtr; /** Additional arbitrary state information */ unsigned long extra[5]; } OFFastEnumerationState; +#ifndef NSINTEGER_DEFINED +typedef OFFastEnumerationState NSFastEnumerationState; #endif /** * @protocol OFFastEnumeration OFEnumerator.h ObjFW/OFEnumerator.h * Index: src/OFEnumerator.m ================================================================== --- src/OFEnumerator.m +++ src/OFEnumerator.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFEpollKernelEventObserver.h ================================================================== --- src/OFEpollKernelEventObserver.h +++ src/OFEpollKernelEventObserver.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFEpollKernelEventObserver.m ================================================================== --- src/OFEpollKernelEventObserver.m +++ src/OFEpollKernelEventObserver.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFFile.h ================================================================== --- src/OFFile.h +++ src/OFFile.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -63,30 +63,10 @@ * `a+` | Read-write, create or append * @return A new autoreleased OFFile */ + (instancetype)fileWithPath: (OFString *)path mode: (OFString *)mode; -/** - * @brief Creates a new OFFile with the specified URL and mode. - * - * @param URL The URL to the file to open - * @param mode The mode in which the file should be opened.@n - * Possible modes are: - * Mode | Description - * ---------------|------------------------------------- - * `r` | Read-only - * `r+` | Read-write - * `w` | Write-only, create or truncate - * `wx` | Write-only, create or fail, exclusive - * `w+` | Read-write, create or truncate - * `w+x` | Read-write, create or fail, exclusive - * `a` | Write-only, create or append - * `a+` | Read-write, create or append - * @return A new autoreleased OFFile - */ -+ (instancetype)fileWithURL: (OFURL *)URL mode: (OFString *)mode; - /** * @brief Creates a new OFFile with the specified native file handle. * * @param handle A native file handle. If OF_FILE_HANDLE_IS_FD is defined, this * is a file descriptor. The handle is closed when the OFFile @@ -93,12 +73,10 @@ * object is deallocated! * @return A new autoreleased OFFile */ + (instancetype)fileWithHandle: (OFFileHandle)handle; -- (instancetype)init OF_UNAVAILABLE; - /** * @brief Initializes an already allocated OFFile. * * @param path The path to the file to open as a string * @param mode The mode in which the file should be opened.@n @@ -122,38 +100,16 @@ - (instancetype)initWithPath: (OFString *)path mode: (OFString *)mode; /** * @brief Initializes an already allocated OFFile. * - * @param URL The URL to the file to open - * @param mode The mode in which the file should be opened.@n - * Possible modes are: - * Mode | Description - * ---------------|------------------------------------- - * `r` | read-only - * `rb` | read-only, binary - * `r+` | read-write - * `rb+` or `r+b` | read-write, binary - * `w` | write-only, create, truncate - * `wb` | write-only, create, truncate, binary - * `w` | read-write, create, truncate - * `wb+` or `w+b` | read-write, create, truncate, binary - * `a` | write-only, create, append - * `ab` | write-only, create, append, binary - * `a+` | read-write, create, append - * `ab+` or `a+b` | read-write, create, append, binary - * @return An initialized OFFile - */ -- (instancetype)initWithURL: (OFURL *)URL mode: (OFString *)mode; - -/** - * @brief Initializes an already allocated OFFile. - * * @param handle A native file handle. If OF_FILE_HANDLE_IS_FD is defined, this * is a file descriptor. The handle is closed when the OFFile * object is deallocated! * @return An initialized OFFile */ - (instancetype)initWithHandle: (OFFileHandle)handle OF_DESIGNATED_INITIALIZER; + +- (instancetype)init OF_UNAVAILABLE; @end OF_ASSUME_NONNULL_END Index: src/OFFile.m ================================================================== --- src/OFFile.m +++ src/OFFile.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -46,10 +46,15 @@ #import "OFWriteFailedException.h" #ifdef OF_WINDOWS # include #endif + +#ifdef OF_AMIGAOS +# include +# include +#endif #ifdef OF_WII # include #endif @@ -56,13 +61,14 @@ #ifdef OF_NINTENDO_DS # include # include #endif -#ifdef OF_AMIGAOS -# include -# include +#ifdef OF_NINTENDO_SWITCH +# define id nx_id +# include +# undef id #endif #ifndef O_BINARY # define O_BINARY 0 #endif @@ -182,32 +188,31 @@ #ifdef OF_NINTENDO_DS if (!nitroFSInit(NULL)) @throw [OFInitializationFailedException exceptionWithClass: self]; #endif + +#ifdef OF_NINTENDO_SWITCH + if (R_SUCCEEDED(romfsInit())) + /* + * Errors are intentionally ignored, as it's possible we just + * have no romfs. + */ + atexit((void (*)(void))romfsExit); +#endif } + (instancetype)fileWithPath: (OFString *)path mode: (OFString *)mode { return [[[self alloc] initWithPath: path mode: mode] autorelease]; } -+ (instancetype)fileWithURL: (OFURL *)URL mode: (OFString *)mode -{ - return [[[self alloc] initWithURL: URL mode: mode] autorelease]; -} - + (instancetype)fileWithHandle: (OFFileHandle)handle { return [[[self alloc] initWithHandle: handle] autorelease]; } -- (instancetype)init -{ - OF_INVALID_INIT_METHOD -} - - (instancetype)initWithPath: (OFString *)path mode: (OFString *)mode { OFFileHandle handle; @try { @@ -327,37 +332,23 @@ } return self; } -- (instancetype)initWithURL: (OFURL *)URL mode: (OFString *)mode -{ - void *pool = objc_autoreleasePoolPush(); - OFString *fileSystemRepresentation; - - @try { - fileSystemRepresentation = URL.fileSystemRepresentation; - } @catch (id e) { - [self release]; - @throw e; - } - - self = [self initWithPath: fileSystemRepresentation mode: mode]; - - objc_autoreleasePoolPop(pool); - - return self; -} - - (instancetype)initWithHandle: (OFFileHandle)handle { self = [super init]; _handle = handle; return self; } + +- (instancetype)init +{ + OF_INVALID_INIT_METHOD +} - (bool)lowlevelIsAtEndOfStream { if (_handle == OFInvalidFileHandle) @throw [OFNotOpenException exceptionWithObject: self]; Index: src/OFFileManager.h ================================================================== --- src/OFFileManager.h +++ src/OFFileManager.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFFileManager.m ================================================================== --- src/OFFileManager.m +++ src/OFFileManager.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -65,10 +65,14 @@ #ifdef OF_AMIGAOS # include # include #endif + +#ifdef OF_MINT +# include +#endif @interface OFDefaultFileManager: OFFileManager @end #ifdef OF_AMIGAOS4 Index: src/OFFileManagerConstants.inc ================================================================== --- src/OFFileManagerConstants.inc +++ src/OFFileManagerConstants.inc @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFFileURLHandler.h ================================================================== --- src/OFFileURLHandler.h +++ src/OFFileURLHandler.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFFileURLHandler.m ================================================================== --- src/OFFileURLHandler.m +++ src/OFFileURLHandler.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFGZIPStream.h ================================================================== --- src/OFGZIPStream.h +++ src/OFGZIPStream.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFGZIPStream.m ================================================================== --- src/OFGZIPStream.m +++ src/OFGZIPStream.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFHMAC.h ================================================================== --- src/OFHMAC.h +++ src/OFHMAC.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -101,10 +101,15 @@ * @param buffer The buffer which should be included into the calculation * @param length The length of the buffer */ - (void)updateWithBuffer: (const void *)buffer length: (size_t)length; +/** + * @brief Performs the final calculation of the HMAC. + */ +- (void)calculate; + /** * @brief Resets the HMAC so that it can be calculated for a new message. * * @note This does not reset the key so that a new HMAC with the same key can * be calculated efficiently. If you want to reset both, use Index: src/OFHMAC.m ================================================================== --- src/OFHMAC.m +++ src/OFHMAC.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -17,10 +17,11 @@ #import "OFHMAC.h" #import "OFSecureData.h" #import "OFHashAlreadyCalculatedException.h" +#import "OFHashNotCalculatedException.h" #import "OFInvalidArgumentException.h" @implementation OFHMAC @synthesize hashClass = _hashClass; @synthesize allowsSwappableMemory = _allowsSwappableMemory; @@ -82,10 +83,11 @@ if (length > blockSize) { id hash = [_hashClass hashWithAllowsSwappableMemory: _allowsSwappableMemory]; [hash updateWithBuffer: key length: length]; + [hash calculate]; length = hash.digestSize; if OF_UNLIKELY (length > blockSize) length = blockSize; @@ -138,21 +140,30 @@ exceptionWithObject: self]; [_innerHash updateWithBuffer: buffer length: length]; } -- (const unsigned char *)digest +- (void)calculate { + if (_calculated) + @throw [OFHashAlreadyCalculatedException + exceptionWithObject: self]; + if (_outerHash == nil || _innerHash == nil) @throw [OFInvalidArgumentException exception]; - if (_calculated) - return _outerHash.digest; - + [_innerHash calculate]; [_outerHash updateWithBuffer: _innerHash.digest length: _innerHash.digestSize]; + [_outerHash calculate]; _calculated = true; +} + +- (const unsigned char *)digest +{ + if (!_calculated) + @throw [OFHashNotCalculatedException exceptionWithObject: self]; return _outerHash.digest; } - (size_t)digestSize Index: src/OFHTTPClient.h ================================================================== --- src/OFHTTPClient.h +++ src/OFHTTPClient.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -25,10 +25,11 @@ @class OFHTTPClient; @class OFHTTPRequest; @class OFHTTPResponse; @class OFStream; @class OFTCPSocket; +@class OFTLSStream; @class OFURL; /** * @protocol OFHTTPClientDelegate OFHTTPClient.h ObjFW/OFHTTPClient.h * @@ -48,24 +49,36 @@ response: (nullable OFHTTPResponse *)response exception: (nullable id)exception; @optional /** - * @brief A callback which is called when an OFHTTPClient creates a socket. - * - * This is useful if the connection is using HTTPS and the server requires a - * client certificate. This callback can then be used to tell the TLS socket - * about the certificate. Another use case is to tell the socket about a SOCKS5 - * proxy it should use for this connection. - * - * @param client The OFHTTPClient that created a socket - * @param socket The socket created by the OFHTTPClient - * @param request The request for which the socket was created - */ -- (void)client: (OFHTTPClient *)client - didCreateSocket: (OFTCPSocket *)socket - request: (OFHTTPRequest *)request; + * @brief A callback which is called when an OFHTTPClient creates a TCP socket. + * + * This can be used to tell the socket about a SOCKS5 proxy it should use for + * this connection. + * + * @param client The OFHTTPClient that created a TCP socket + * @param TCPSocket The socket created by the OFHTTPClient + * @param request The request for which the TCP socket was created + */ +- (void)client: (OFHTTPClient *)client + didCreateTCPSocket: (OFTCPSocket *)TCPSocket + request: (OFHTTPRequest *)request; + +/** + * @brief A callback which is called when an OFHTTPClient creates a TLS stream. + * + * This can be used to tell the TLS stream about a client certificate it should + * use before performing the TLS handshake. + * + * @param client The OFHTTPClient that created a TLS stream + * @param TLSStream The TLS stream created by the OFHTTPClient + * @param request The request for which the TLS stream was created + */ +- (void)client: (OFHTTPClient *)client + didCreateTLSStream: (OFTLSStream *)TLSStream + request: (OFHTTPRequest *)request; /** * @brief A callback which is called when an OFHTTPClient wants to send the * body for a request. * @@ -134,11 +147,11 @@ #ifdef OF_HTTPCLIENT_M @public #endif OFObject *_Nullable _delegate; bool _allowsInsecureRedirects, _inProgress; - OFTCPSocket *_Nullable _socket; + OFStream *_Nullable _stream; OFURL *_Nullable _lastURL; bool _lastWasHEAD; OFHTTPResponse *_Nullable _lastResponse; } Index: src/OFHTTPClient.m ================================================================== --- src/OFHTTPClient.m +++ src/OFHTTPClient.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -26,13 +26,13 @@ #import "OFHTTPRequest.h" #import "OFHTTPResponse.h" #import "OFKernelEventObserver.h" #import "OFNumber.h" #import "OFRunLoop.h" -#import "OFSocket+Private.h" #import "OFString.h" #import "OFTCPSocket.h" +#import "OFTLSStream.h" #import "OFURL.h" #import "OFAlreadyConnectedException.h" #import "OFHTTPRequestFailedException.h" #import "OFInvalidArgumentException.h" @@ -49,11 +49,12 @@ #import "OFWriteFailedException.h" static const unsigned int defaultRedirects = 10; OF_DIRECT_MEMBERS -@interface OFHTTPClientRequestHandler: OFObject +@interface OFHTTPClientRequestHandler: OFObject { @public OFHTTPClient *_client; OFHTTPRequest *_request; unsigned int _redirects; @@ -72,32 +73,32 @@ OF_DIRECT_MEMBERS @interface OFHTTPClientRequestBodyStream: OFStream { OFHTTPClientRequestHandler *_handler; - OFTCPSocket *_socket; + OFStream *_stream; bool _chunked; unsigned long long _toWrite; bool _atEndOfStream; } - (instancetype)initWithHandler: (OFHTTPClientRequestHandler *)handler - socket: (OFTCPSocket *)sock; + stream: (OFStream *)stream; @end OF_DIRECT_MEMBERS @interface OFHTTPClientResponse: OFHTTPResponse { - OFTCPSocket *_socket; + OFStream *_stream; bool _hasContentLength, _chunked, _keepAlive; bool _atEndOfStream, _setAtEndOfStream; long long _toRead; } @property (nonatomic, setter=of_setKeepAlive:) bool of_keepAlive; -- (instancetype)initWithSocket: (OFTCPSocket *)sock; +- (instancetype)initWithStream: (OFStream *)stream; @end OF_DIRECT_MEMBERS @interface OFHTTPClientSyncPerformer: OFObject { @@ -293,20 +294,20 @@ didPerformRequest: _request response: nil exception: exception]; } -- (void)createResponseWithSocketOrThrow: (OFTCPSocket *)sock +- (void)createResponseWithStreamOrThrow: (OFStream *)stream { OFURL *URL = _request.URL; OFHTTPClientResponse *response; OFString *connectionHeader; bool keepAlive; OFString *location; id exception; - response = [[[OFHTTPClientResponse alloc] initWithSocket: sock] + response = [[[OFHTTPClientResponse alloc] initWithStream: stream] autorelease]; response.protocolVersionString = _version; response.statusCode = _status; response.headers = _serverHeaders; @@ -325,11 +326,11 @@ } if (keepAlive) { response.of_keepAlive = true; - _client->_socket = [sock retain]; + _client->_stream = [stream retain]; _client->_lastURL = [URL copy]; _client->_lastWasHEAD = (_request.method == OFHTTPRequestMethodHead); _client->_lastResponse = [response retain]; } @@ -429,14 +430,14 @@ withObject: response withObject: exception afterDelay: 0]; } -- (void)createResponseWithSocket: (OFTCPSocket *)sock +- (void)createResponseWithStream: (OFStream *)stream { @try { - [self createResponseWithSocketOrThrow: sock]; + [self createResponseWithStreamOrThrow: stream]; } @catch (id e) { [self raiseException: e]; } } @@ -471,11 +472,11 @@ _status = (short)status; return true; } -- (bool)handleServerHeader: (OFString *)line socket: (OFTCPSocket *)sock +- (bool)handleServerHeader: (OFString *)line stream: (OFStream *)stream { OFString *key, *value, *old; const char *lineC, *tmp; char *keyC; @@ -490,14 +491,14 @@ [_client->_delegate client: _client didReceiveHeaders: _serverHeaders statusCode: _status request: _request]; - sock.delegate = nil; + stream.delegate = nil; - [self performSelector: @selector(createResponseWithSocket:) - withObject: sock + [self performSelector: @selector(createResponseWithStream:) + withObject: stream afterDelay: 0]; return false; } @@ -532,11 +533,11 @@ [_serverHeaders setObject: value forKey: key]; return true; } -- (bool)stream: (OFStream *)sock +- (bool)stream: (OFStream *)stream didReadLine: (OFString *)line exception: (id)exception { bool ret; @@ -552,12 +553,11 @@ @try { if (_firstLine) { _firstLine = false; ret = [self handleFirstLine: line]; } else - ret = [self handleServerHeader: line - socket: (OFTCPSocket *)sock]; + ret = [self handleServerHeader: line stream: stream]; } @catch (id e) { [self raiseException: e]; ret = false; } @@ -594,12 +594,11 @@ if (chunked || [headers objectForKey: @"Content-Length"] != nil) { stream.delegate = nil; OFStream *requestBody = [[[OFHTTPClientRequestBodyStream alloc] - initWithHandler: self - socket: (OFTCPSocket *)stream] autorelease]; + initWithHandler: self stream: stream] autorelease]; if ([_client->_delegate respondsToSelector: @selector(client:wantsRequestBody:request:)]) [_client->_delegate client: _client wantsRequestBody: requestBody @@ -608,23 +607,23 @@ [stream asyncReadLine]; return nil; } -- (void)handleSocket: (OFTCPSocket *)sock +- (void)handleStream: (OFStream *)stream { /* * As a work around for a bug with split packets in lighttpd when using * HTTPS, we construct the complete request in a buffer string and then * send it all at once. * - * We do not use the socket's write buffer in case we need to resend + * We do not use the streams's write buffer in case we need to resend * the entire request (e.g. in case a keep-alive connection timed out). */ @try { - [sock asyncWriteString: constructRequestString(_request)]; + [stream asyncWriteString: constructRequestString(_request)]; } @catch (id e) { [self raiseException: e]; return; } } @@ -632,58 +631,95 @@ - (void)socket: (OFTCPSocket *)sock didConnectToHost: (OFString *)host port: (uint16_t)port exception: (id)exception { - sock.delegate = self; + if (exception != nil) { + [self raiseException: exception]; + return; + } + sock.canBlock = false; + + if ([_client->_delegate respondsToSelector: + @selector(client:didCreateTCPSocket:request:)]) + [_client->_delegate client: _client + didCreateTCPSocket: sock + request: _request]; + + if ([_request.URL.scheme caseInsensitiveCompare: @"https"] == + OFOrderedSame) { + OFTLSStream *stream; + @try { + stream = [OFTLSStream streamWithStream: sock]; + } @catch (OFNotImplementedException *e) { + [self raiseException: + [OFUnsupportedProtocolException + exceptionWithURL: _request.URL]]; + return; + } + + if ([_client->_delegate respondsToSelector: + @selector(client:didCreateTLSStream:request:)]) + [_client->_delegate client: _client + didCreateTLSStream: stream + request: _request]; + + stream.delegate = self; + [stream asyncPerformClientHandshakeWithHost: _request.URL.host]; + } else { + sock.delegate = self; + [self performSelector: @selector(handleStream:) + withObject: sock + afterDelay: 0]; + } +} + +- (void)stream: (OFTLSStream *)stream + didPerformClientHandshakeWithHost: (OFString *)host + exception: (id)exception +{ if (exception != nil) { [self raiseException: exception]; return; } - if ([_client->_delegate respondsToSelector: - @selector(client:didCreateSocket:request:)]) - [_client->_delegate client: _client - didCreateSocket: sock - request: _request]; - - [self performSelector: @selector(handleSocket:) - withObject: sock + [self performSelector: @selector(handleStream:) + withObject: stream afterDelay: 0]; } - (void)start { OFURL *URL = _request.URL; - OFTCPSocket *sock; + OFStream *stream; /* Can we reuse the last socket? */ - if (_client->_socket != nil && !_client->_socket.atEndOfStream && + if (_client->_stream != nil && !_client->_stream.atEndOfStream && [_client->_lastURL.scheme isEqual: URL.scheme] && [_client->_lastURL.host isEqual: URL.host] && (_client->_lastURL.port == URL.port || [_client->_lastURL.port isEqual: URL.port]) && (_client->_lastWasHEAD || _client->_lastResponse.atEndOfStream)) { /* - * Set _socket to nil, so that in case of an error it won't be - * reused. If everything is successful, we set _socket again + * Set _stream to nil, so that in case of an error it won't be + * reused. If everything is successful, we set _stream again * at the end. */ - sock = [_client->_socket autorelease]; - _client->_socket = nil; + stream = [_client->_stream autorelease]; + _client->_stream = nil; [_client->_lastURL release]; _client->_lastURL = nil; [_client->_lastResponse release]; _client->_lastResponse = nil; - sock.delegate = self; + stream.delegate = self; - [self performSelector: @selector(handleSocket:) - withObject: sock + [self performSelector: @selector(handleStream:) + withObject: stream afterDelay: 0]; } else [self closeAndReconnect]; } @@ -694,23 +730,18 @@ OFTCPSocket *sock; uint16_t port; OFNumber *URLPort; [_client close]; + + sock = [OFTCPSocket socket]; if ([URL.scheme caseInsensitiveCompare: @"https"] == - OFOrderedSame) { - if (OFTLSSocketClass == Nil) - @throw [OFUnsupportedProtocolException - exceptionWithURL: URL]; - - sock = [[[OFTLSSocketClass alloc] init] autorelease]; + OFOrderedSame) port = 443; - } else { - sock = [OFTCPSocket socket]; + else port = 80; - } URLPort = URL.port; if (URLPort != nil) port = URLPort.unsignedShortValue; @@ -722,20 +753,20 @@ } @end @implementation OFHTTPClientRequestBodyStream - (instancetype)initWithHandler: (OFHTTPClientRequestHandler *)handler - socket: (OFTCPSocket *)sock + stream: (OFStream *)stream { self = [super init]; @try { OFDictionary OF_GENERIC(OFString *, OFString *) *headers; OFString *transferEncoding, *contentLengthString; _handler = [handler retain]; - _socket = [sock retain]; + _stream = [stream retain]; headers = _handler->_request.headers; transferEncoding = [headers objectForKey: @"Transfer-Encoding"]; _chunked = [transferEncoding isEqual: @"chunked"]; @@ -757,25 +788,23 @@ return self; } - (void)dealloc { - if (_socket != nil) + if (_stream != nil) [self close]; [_handler release]; [super dealloc]; } -- (size_t)lowlevelWriteBuffer: (const void *)buffer - length: (size_t)length +- (size_t)lowlevelWriteBuffer: (const void *)buffer length: (size_t)length { - size_t requestedLength = length; - size_t ret; + /* TODO: Use non-blocking writes */ - if (_socket == nil) + if (_stream == nil) @throw [OFNotOpenException exceptionWithObject: self]; /* * We must not send a chunk of size 0, as that would end the body. We * always ignore writing 0 bytes to still allow writing 0 bytes after @@ -783,90 +812,80 @@ */ if (length == 0) return 0; if (_atEndOfStream) - @throw [OFWriteFailedException - exceptionWithObject: self - requestedLength: requestedLength - bytesWritten: 0 - errNo: 0]; + @throw [OFWriteFailedException exceptionWithObject: self + requestedLength: length + bytesWritten: 0 + errNo: ENOTCONN]; if (_chunked) - [_socket writeFormat: @"%zX\r\n", length]; + [_stream writeFormat: @"%zX\r\n", length]; else if (length > _toWrite) - length = (size_t)_toWrite; + @throw [OFOutOfRangeException exception]; - ret = [_socket writeBuffer: buffer length: length]; + [_stream writeBuffer: buffer length: length]; if (_chunked) - [_socket writeString: @"\r\n"]; - - if (ret > length) - @throw [OFOutOfRangeException exception]; + [_stream writeString: @"\r\n"]; if (!_chunked) { - _toWrite -= ret; + _toWrite -= length; if (_toWrite == 0) _atEndOfStream = true; } - if (requestedLength > length) - @throw [OFWriteFailedException - exceptionWithObject: self - requestedLength: requestedLength - bytesWritten: ret - errNo: 0]; - - return ret; + return length; } - (bool)lowlevelIsAtEndOfStream { return _atEndOfStream; } - (void)close { - if (_socket == nil) + if (_stream == nil) @throw [OFNotOpenException exceptionWithObject: self]; if (_chunked) - [_socket writeString: @"0\r\n\r\n"]; + [_stream writeString: @"0\r\n\r\n"]; else if (_toWrite > 0) @throw [OFTruncatedDataException exception]; - _socket.delegate = _handler; - [_socket asyncReadLine]; + _stream.delegate = _handler; + [_stream asyncReadLine]; - [_socket release]; - _socket = nil; + [_stream release]; + _stream = nil; [super close]; } - (int)fileDescriptorForWriting { - return _socket.fileDescriptorForWriting; + return ((OFStream *)_stream) + .fileDescriptorForWriting; } @end @implementation OFHTTPClientResponse @synthesize of_keepAlive = _keepAlive; -- (instancetype)initWithSocket: (OFTCPSocket *)sock +- (instancetype)initWithStream: (OFStream *)stream { self = [super init]; - _socket = [sock retain]; + _stream = [stream retain]; return self; } - (void)dealloc { - if (_socket != nil) + if (_stream != nil) [self close]; [super dealloc]; } @@ -900,30 +919,30 @@ } } - (size_t)lowlevelReadIntoBuffer: (void *)buffer length: (size_t)length { - if (_socket == nil) + if (_stream == nil) @throw [OFNotOpenException exceptionWithObject: self]; if (_atEndOfStream) return 0; if (!_hasContentLength && !_chunked) - return [_socket readIntoBuffer: buffer length: length]; + return [_stream readIntoBuffer: buffer length: length]; - if (_socket.atEndOfStream) + if (_stream.atEndOfStream) @throw [OFTruncatedDataException exception]; /* Content-Length */ if (!_chunked) { size_t ret; if (length > (unsigned long long)_toRead) length = (size_t)_toRead; - ret = [_socket readIntoBuffer: buffer length: length]; + ret = [_stream readIntoBuffer: buffer length: length]; if (ret > length) @throw [OFOutOfRangeException exception]; _toRead -= ret; @@ -935,11 +954,11 @@ /* Chunked */ if (_toRead == -2) { char tmp[2]; - switch ([_socket readIntoBuffer: tmp length: 2]) { + switch ([_stream readIntoBuffer: tmp length: 2]) { case 2: _toRead++; if (tmp[1] != '\n') @throw [OFInvalidServerReplyException exception]; @@ -955,11 +974,11 @@ return 0; } else if (_toRead == -1) { char tmp; - if ([_socket readIntoBuffer: &tmp length: 1] == 1) { + if ([_stream readIntoBuffer: &tmp length: 1] == 1) { _toRead++; if (tmp != '\n') @throw [OFInvalidServerReplyException exception]; } @@ -970,11 +989,11 @@ return 0; } else if (_toRead > 0) { if (length > (unsigned long long)_toRead) length = (size_t)_toRead; - length = [_socket readIntoBuffer: buffer length: length]; + length = [_stream readIntoBuffer: buffer length: length]; _toRead -= length; if (_toRead == 0) _toRead = -2; @@ -983,11 +1002,11 @@ void *pool = objc_autoreleasePoolPush(); OFString *line; size_t pos; @try { - line = [_socket tryReadLine]; + line = [_stream tryReadLine]; } @catch (OFInvalidEncodingException *e) { @throw [OFInvalidServerReplyException exception]; } if (line == nil) @@ -997,14 +1016,14 @@ if (pos != OFNotFound) line = [line substringToIndex: pos]; if (line.length < 1) { /* - * We have read the empty string because the socket is + * We have read the empty string because the stream is * at end of stream. */ - if (_socket.atEndOfStream && pos == OFNotFound) + if (_stream.atEndOfStream && pos == OFNotFound) @throw [OFTruncatedDataException exception]; else @throw [OFInvalidServerReplyException exception]; } @@ -1035,41 +1054,42 @@ - (bool)lowlevelIsAtEndOfStream { if (_atEndOfStream) return true; - if (_socket == nil) + if (_stream == nil) @throw [OFNotOpenException exceptionWithObject: self]; if (!_hasContentLength && !_chunked) - return _socket.atEndOfStream; + return _stream.atEndOfStream; return _atEndOfStream; } - (int)fileDescriptorForReading { - if (_socket == nil) + if (_stream == nil) return -1; - return _socket.fileDescriptorForReading; + return ((OFStream *)_stream) + .fileDescriptorForReading; } - (bool)hasDataInReadBuffer { - return (super.hasDataInReadBuffer || _socket.hasDataInReadBuffer); + return (super.hasDataInReadBuffer || _stream.hasDataInReadBuffer); } - (void)close { - if (_socket == nil) + if (_stream == nil) @throw [OFNotOpenException exceptionWithObject: self]; _atEndOfStream = false; - [_socket release]; - _socket = nil; + [_stream release]; + _stream = nil; [super close]; } @end @@ -1132,19 +1152,30 @@ didPerformRequest: request response: response exception: nil]; } -- (void)client: (OFHTTPClient *)client - didCreateSocket: (OFTCPSocket *)sock - request: (OFHTTPRequest *)request +- (void)client: (OFHTTPClient *)client + didCreateTCPSocket: (OFTCPSocket *)TCPSocket + request: (OFHTTPRequest *)request +{ + if ([_delegate respondsToSelector: + @selector(client:didCreateTCPSocket:request:)]) + [_delegate client: client + didCreateTCPSocket: TCPSocket + request: request]; +} + +- (void)client: (OFHTTPClient *)client + didCreateTLSStream: (OFTLSStream *)TLSStream + request: (OFHTTPRequest *)request { if ([_delegate respondsToSelector: - @selector(client:didCreateSocket:request:)]) - [_delegate client: client - didCreateSocket: sock - request: request]; + @selector(client:didCreateTLSStream:request:)]) + [_delegate client: client + didCreateTLSStream: TLSStream + request: request]; } - (void)client: (OFHTTPClient *)client wantsRequestBody: (OFStream *)body request: (OFHTTPRequest *)request @@ -1255,15 +1286,15 @@ objc_autoreleasePoolPop(pool); } - (void)close { - [_socket release]; - _socket = nil; + [_stream release]; + _stream = nil; [_lastURL release]; _lastURL = nil; [_lastResponse release]; _lastResponse = nil; } @end Index: src/OFHTTPCookie.h ================================================================== --- src/OFHTTPCookie.h +++ src/OFHTTPCookie.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFHTTPCookie.m ================================================================== --- src/OFHTTPCookie.m +++ src/OFHTTPCookie.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFHTTPCookieManager.h ================================================================== --- src/OFHTTPCookieManager.h +++ src/OFHTTPCookieManager.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFHTTPCookieManager.m ================================================================== --- src/OFHTTPCookieManager.m +++ src/OFHTTPCookieManager.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFHTTPRequest.h ================================================================== --- src/OFHTTPRequest.h +++ src/OFHTTPRequest.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -107,17 +107,10 @@ * * @note The setter creates a copy of the remote address. */ @property OF_NULLABLE_PROPERTY (nonatomic) const OFSocketAddress *remoteAddress; -/** - * @brief Creates a new OFHTTPRequest. - * - * @return A new, autoreleased OFHTTPRequest - */ -+ (instancetype)request; - /** * @brief Creates a new OFHTTPRequest with the specified URL. * * @param URL The URL for the request * @return A new, autoreleased OFHTTPRequest @@ -129,10 +122,12 @@ * * @param URL The URL for the request * @return An initialized OFHTTPRequest */ - (instancetype)initWithURL: (OFURL *)URL; + +- (instancetype)init OF_UNAVAILABLE; @end #ifdef __cplusplus extern "C" { #endif Index: src/OFHTTPRequest.m ================================================================== --- src/OFHTTPRequest.m +++ src/OFHTTPRequest.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -78,44 +78,36 @@ } @implementation OFHTTPRequest @synthesize URL = _URL, method = _method, headers = _headers; -+ (instancetype)request -{ - return [[[self alloc] init] autorelease]; -} - + (instancetype)requestWithURL: (OFURL *)URL { return [[[self alloc] initWithURL: URL] autorelease]; } -- (instancetype)init +- (instancetype)initWithURL: (OFURL *)URL { self = [super init]; - _method = OFHTTPRequestMethodGet; - _protocolVersion.major = 1; - _protocolVersion.minor = 1; - - return self; -} - -- (instancetype)initWithURL: (OFURL *)URL -{ - self = [self init]; - @try { _URL = [URL copy]; + _method = OFHTTPRequestMethodGet; + _protocolVersion.major = 1; + _protocolVersion.minor = 1; } @catch (id e) { [self release]; @throw e; } return self; } + +- (instancetype)init +{ + OF_INVALID_INIT_METHOD +} - (void)dealloc { [_URL release]; [_headers release]; @@ -139,16 +131,15 @@ return NULL; } - (id)copy { - OFHTTPRequest *copy = [[OFHTTPRequest alloc] init]; + OFHTTPRequest *copy = [[OFHTTPRequest alloc] initWithURL: _URL]; @try { copy->_method = _method; copy->_protocolVersion = _protocolVersion; - copy.URL = _URL; copy.headers = _headers; copy.remoteAddress = self.remoteAddress; } @catch (id e) { [copy release]; @throw e; Index: src/OFHTTPResponse.h ================================================================== --- src/OFHTTPResponse.h +++ src/OFHTTPResponse.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -22,11 +22,11 @@ @class OFArray OF_GENERIC(ObjectType); /** * @class OFHTTPResponse OFHTTPResponse.h ObjFW/OFHTTPResponse.h * - * @brief A class for representing an HTTP request reply as a stream. + * @brief A class for representing an HTTP request response as a stream. */ @interface OFHTTPResponse: OFStream { OFHTTPRequestProtocolVersion _protocolVersion; short _statusCode; @@ -33,42 +33,45 @@ OFDictionary OF_GENERIC(OFString *, OFString *) *_headers; OF_RESERVE_IVARS(OFHTTPResponse, 4) } /** - * @brief The protocol version of the HTTP request reply. + * @brief The protocol version of the HTTP request response. */ @property (nonatomic) OFHTTPRequestProtocolVersion protocolVersion; /** - * @brief The protocol version of the HTTP request reply as a string. + * @brief The protocol version of the HTTP request response as a string. */ @property (copy, nonatomic) OFString *protocolVersionString; /** - * @brief The status code of the reply to the HTTP request. + * @brief The status code of the response to the HTTP request. */ @property (nonatomic) short statusCode; /** - * @brief The headers of the reply to the HTTP request. + * @brief The headers of the response to the HTTP request. */ @property (copy, nonatomic) OFDictionary OF_GENERIC(OFString *, OFString *) *headers; /** - * @brief The reply as a string, trying to detect the encoding. + * @brief Read the response as a string, trying to detect the encoding and + * falling back to the specified encoding if not detectable. + * + * @return The response as a string */ -@property (readonly, nonatomic) OFString *string; +- (OFString *)readString; /** - * @brief Returns the reply as a string, trying to detect the encoding and + * @brief Rread the response as a string, trying to detect the encoding and * falling back to the specified encoding if not detectable. * - * @return The reply as a string + * @return The response as a string */ -- (OFString *)stringWithEncoding: (OFStringEncoding)encoding; +- (OFString *)readStringWithEncoding: (OFStringEncoding)encoding; @end #ifdef __cplusplus extern "C" { #endif Index: src/OFHTTPResponse.m ================================================================== --- src/OFHTTPResponse.m +++ src/OFHTTPResponse.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -294,16 +294,16 @@ return [OFString stringWithFormat: @"%hhu.%hhu", _protocolVersion.major, _protocolVersion.minor]; } -- (OFString *)string +- (OFString *)readString { - return [self stringWithEncoding: OFStringEncodingAutodetect]; + return [self readStringWithEncoding: OFStringEncodingAutodetect]; } -- (OFString *)stringWithEncoding: (OFStringEncoding)encoding +- (OFString *)readStringWithEncoding: (OFStringEncoding)encoding { void *pool = objc_autoreleasePoolPush(); OFString *contentType, *contentLengthString, *ret; OFData *data; Index: src/OFHTTPServer.h ================================================================== --- src/OFHTTPServer.h +++ src/OFHTTPServer.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -62,11 +62,12 @@ */ - (bool)server: (OFHTTPServer *)server didReceiveExceptionOnListeningSocket: (id)exception; /** - * @brief This method is called when a client socket encountered an exception. + * @brief This method is called when a socket for a client encountered an + * exception. * * This can happen when the OFHTTPServer tries to properly close the * connection. If no headers have been sent yet, it will send headers, and if * chunked transfer encoding was used, it will send a chunk of size 0. However, * if the other end already closed the connection before that, this will raise @@ -91,13 +92,10 @@ OF_SUBCLASSING_RESTRICTED @interface OFHTTPServer: OFObject { OFString *_Nullable _host; uint16_t _port; - bool _usesTLS; - OFString *_Nullable _certificateFile, *_Nullable _privateKeyFile; - const char *_Nullable _privateKeyPassphrase; id _Nullable _delegate; OFString *_Nullable _name; OFTCPSocket *_Nullable _listeningSocket; #ifdef OF_HAVE_THREADS size_t _numberOfThreads, _nextThreadIndex; @@ -119,46 +117,10 @@ * Setting this after @ref start has been called raises an * @ref OFAlreadyConnectedException. */ @property (nonatomic) uint16_t port; -/** - * @brief Whether the HTTP server uses TLS. - * - * Setting this after @ref start has been called raises an - * @ref OFAlreadyConnectedException. - */ -@property (nonatomic) bool usesTLS; - -/** - * @brief The path to the X.509 certificate file to use for TLS. - * - * Setting this after @ref start has been called raises an - * @ref OFAlreadyConnectedException. - */ -@property OF_NULLABLE_PROPERTY (copy, nonatomic) OFString *certificateFile; - -/** - * @brief The path to the PKCS#8 private key file to use for TLS. - * - * Setting this after @ref start has been called raises an - * @ref OFAlreadyConnectedException. - */ -@property OF_NULLABLE_PROPERTY (copy, nonatomic) OFString *privateKeyFile; - -/** - * @brief The passphrase to decrypt the PKCS#8 private key file for TLS. - * - * @warning You have to ensure that this is in secure memory protected from - * swapping! This is also the reason why this is not an OFString. - * - * Setting this after @ref start has been called raises an - * @ref OFAlreadyConnectedException. - */ -@property OF_NULLABLE_PROPERTY (assign, nonatomic) - const char *privateKeyPassphrase; - /** * @brief The delegate for the HTTP server. */ @property OF_NULLABLE_PROPERTY (assign, nonatomic) id delegate; Index: src/OFHTTPServer.m ================================================================== --- src/OFHTTPServer.m +++ src/OFHTTPServer.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -13,10 +13,11 @@ * file. */ #include "config.h" +#include #include #include #import "OFHTTPServer.h" #import "OFArray.h" @@ -26,11 +27,10 @@ #import "OFHTTPRequest.h" #import "OFHTTPResponse.h" #import "OFNumber.h" #import "OFSocket+Private.h" #import "OFTCPSocket.h" -#import "OFTLSSocket.h" #import "OFThread.h" #import "OFTimer.h" #import "OFURL.h" #import "OFAlreadyConnectedException.h" @@ -226,12 +226,22 @@ @throw [OFNotOpenException exceptionWithObject: self]; if (!_headersSent) [self of_sendHeaders]; - if (!_chunked) - return [_socket writeBuffer: buffer length: length]; + if (!_chunked) { + @try { + [_socket writeBuffer: buffer length: length]; + } @catch (OFWriteFailedException *e) { + if (e.errNo == EWOULDBLOCK || e.errNo == EAGAIN) + return e.bytesWritten; + + @throw e; + } + + return length; + } pool = objc_autoreleasePoolPush(); [_socket writeString: [OFString stringWithFormat: @"%zX\r\n", length]]; objc_autoreleasePoolPop(pool); @@ -526,20 +536,27 @@ URL.scheme = @"http"; URL.host = _host; if (_port != 80) URL.port = [OFNumber numberWithUnsignedShort: _port]; - if ((pos = [_path rangeOfString: @"?"].location) != OFNotFound) { - OFString *path, *query; - - path = [_path substringToIndex: pos]; - query = [_path substringFromIndex: pos + 1]; - - URL.URLEncodedPath = path; - URL.URLEncodedQuery = query; - } else - URL.URLEncodedPath = _path; + @try { + if ((pos = [_path rangeOfString: @"?"].location) != + OFNotFound) { + OFString *path, *query; + + path = [_path substringToIndex: pos]; + query = [_path substringFromIndex: pos + 1]; + + URL.URLEncodedPath = path; + URL.URLEncodedQuery = query; + } else + URL.URLEncodedPath = _path; + } @catch (OFInvalidFormatException *e) { + objc_autoreleasePoolPop(pool); + [self sendErrorAndClose: 400]; + return; + } [URL makeImmutable]; request = [OFHTTPRequest requestWithURL: URL]; request.method = _method; @@ -809,70 +826,10 @@ - (uint16_t)port { return _port; } -- (void)setUsesTLS: (bool)usesTLS -{ - if (_listeningSocket != nil) - @throw [OFAlreadyConnectedException exception]; - - _usesTLS = usesTLS; -} - -- (bool)usesTLS -{ - return _usesTLS; -} - -- (void)setCertificateFile: (OFString *)certificateFile -{ - OFString *old; - - if (_listeningSocket != nil) - @throw [OFAlreadyConnectedException exception]; - - old = _certificateFile; - _certificateFile = [certificateFile copy]; - [old release]; -} - -- (OFString *)certificateFile -{ - return _certificateFile; -} - -- (void)setPrivateKeyFile: (OFString *)privateKeyFile -{ - OFString *old; - - if (_listeningSocket != nil) - @throw [OFAlreadyConnectedException exception]; - - old = _privateKeyFile; - _privateKeyFile = [privateKeyFile copy]; - [old release]; -} - -- (OFString *)privateKeyFile -{ - return _privateKeyFile; -} - -- (void)setPrivateKeyPassphrase: (const char *)privateKeyPassphrase -{ - if (_listeningSocket != nil) - @throw [OFAlreadyConnectedException exception]; - - _privateKeyPassphrase = privateKeyPassphrase; -} - -- (const char *)privateKeyPassphrase -{ - return _privateKeyPassphrase; -} - #ifdef OF_HAVE_THREADS - (void)setNumberOfThreads: (size_t)numberOfThreads { if (numberOfThreads == 0) @throw [OFInvalidArgumentException exception]; @@ -897,25 +854,11 @@ @throw [OFInvalidArgumentException exception]; if (_listeningSocket != nil) @throw [OFAlreadyConnectedException exception]; - if (_usesTLS) { - OFTCPSocket *TLSSocket; - - if (OFTLSSocketClass == Nil) - @throw [OFUnsupportedProtocolException exception]; - - TLSSocket = [[OFTLSSocketClass alloc] init]; - _listeningSocket = TLSSocket; - - TLSSocket.certificateFile = _certificateFile; - TLSSocket.privateKeyFile = _privateKeyFile; - TLSSocket.privateKeyPassphrase = _privateKeyPassphrase; - } else - _listeningSocket = [[OFTCPSocket alloc] init]; - + _listeningSocket = [[OFTCPSocket alloc] init]; _port = [_listeningSocket bindToHost: _host port: _port]; [_listeningSocket listen]; #ifdef OF_HAVE_THREADS if (_numberOfThreads > 1) { Index: src/OFHTTPURLHandler.h ================================================================== --- src/OFHTTPURLHandler.h +++ src/OFHTTPURLHandler.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFHTTPURLHandler.m ================================================================== --- src/OFHTTPURLHandler.m +++ src/OFHTTPURLHandler.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFHostAddressResolver.h ================================================================== --- src/OFHostAddressResolver.h +++ src/OFHostAddressResolver.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFHostAddressResolver.m ================================================================== --- src/OFHostAddressResolver.m +++ src/OFHostAddressResolver.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFHuffmanTree.h ================================================================== --- src/OFHuffmanTree.h +++ src/OFHuffmanTree.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFHuffmanTree.m ================================================================== --- src/OFHuffmanTree.m +++ src/OFHuffmanTree.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFINICategory+Private.h ================================================================== --- src/OFINICategory+Private.h +++ src/OFINICategory+Private.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFINICategory.h ================================================================== --- src/OFINICategory.h +++ src/OFINICategory.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFINICategory.m ================================================================== --- src/OFINICategory.m +++ src/OFINICategory.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFINIFile.h ================================================================== --- src/OFINIFile.h +++ src/OFINIFile.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -18,10 +18,11 @@ #import "OFINICategory.h" OF_ASSUME_NONNULL_BEGIN @class OFMutableArray OF_GENERIC(ObjectType); +@class OFURL; /** * @class OFINIFile OFINIFile.h ObjFW/OFINIFile.h * * @brief A class for reading, creating and modifying INI files. @@ -38,51 +39,50 @@ @property (readonly, nonatomic) OFArray OF_GENERIC(OFINICategory *) *categories; /** * @brief Creates a new OFINIFile with the contents of the specified file. * - * @param path The path to the file whose contents the OFINIFile should contain + * @param URL The URL to the file whose contents the OFINIFile should contain * * @return A new, autoreleased OFINIFile with the contents of the specified file */ -+ (instancetype)fileWithPath: (OFString *)path; ++ (instancetype)fileWithURL: (OFURL *)URL; /** * @brief Creates a new OFINIFile with the contents of the specified file in * the specified encoding. * - * @param path The path to the file whose contents the OFINIFile should contain + * @param URL The URL to the file whose contents the OFINIFile should contain * @param encoding The encoding of the specified file * * @return A new, autoreleased OFINIFile with the contents of the specified file */ -+ (instancetype)fileWithPath: (OFString *)path - encoding: (OFStringEncoding)encoding; ++ (instancetype)fileWithURL: (OFURL *)URL encoding: (OFStringEncoding)encoding; - (instancetype)init OF_UNAVAILABLE; /** * @brief Initializes an already allocated OFINIFile with the contents of the * specified file. * - * @param path The path to the file whose contents the OFINIFile should contain + * @param URL The URL to the file whose contents the OFINIFile should contain * * @return An initialized OFINIFile with the contents of the specified file */ -- (instancetype)initWithPath: (OFString *)path; +- (instancetype)initWithURL: (OFURL *)URL; /** * @brief Initializes an already allocated OFINIFile with the contents of the * specified file in the specified encoding. * - * @param path The path to the file whose contents the OFINIFile should contain + * @param URL The URL to the file whose contents the OFINIFile should contain * @param encoding The encoding of the specified file * * @return An initialized OFINIFile with the contents of the specified file */ -- (instancetype)initWithPath: (OFString *)path - encoding: (OFStringEncoding)encoding +- (instancetype)initWithURL: (OFURL *)URL + encoding: (OFStringEncoding)encoding OF_DESIGNATED_INITIALIZER; /** * @brief Returns an @ref OFINICategory for the category with the specified * name. @@ -95,20 +95,20 @@ - (OFINICategory *)categoryForName: (OFString *)name; /** * @brief Writes the contents of the OFINIFile to a file. * - * @param path The path of the file to write to + * @param URL The URL of the file to write to */ -- (void)writeToFile: (OFString *)path; +- (void)writeToURL: (OFURL *)URL; /** * @brief Writes the contents of the OFINIFile to a file in the specified * encoding. * - * @param path The path of the file to write to + * @param URL The URL of the file to write to * @param encoding The encoding to use */ -- (void)writeToFile: (OFString *)path encoding: (OFStringEncoding)encoding; +- (void)writeToURL: (OFURL *)URL encoding: (OFStringEncoding)encoding; @end OF_ASSUME_NONNULL_END Index: src/OFINIFile.m ================================================================== --- src/OFINIFile.m +++ src/OFINIFile.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -17,21 +17,23 @@ #include #import "OFINIFile.h" #import "OFArray.h" -#import "OFString.h" -#import "OFFile.h" +#import "OFINICategory+Private.h" #import "OFINICategory.h" -#import "OFINICategory+Private.h" +#import "OFStream.h" +#import "OFString.h" +#import "OFURL.h" +#import "OFURLHandler.h" #import "OFInvalidFormatException.h" #import "OFOpenItemFailedException.h" OF_DIRECT_MEMBERS @interface OFINIFile () -- (void)of_parseFile: (OFString *)path encoding: (OFStringEncoding)encoding; +- (void)of_parseURL: (OFURL *)URL encoding: (OFStringEncoding)encoding; @end static bool isWhitespaceLine(OFString *line) { @@ -46,41 +48,38 @@ } @implementation OFINIFile @synthesize categories = _categories; -+ (instancetype)fileWithPath: (OFString *)path ++ (instancetype)fileWithURL: (OFURL *)URL { - return [[[self alloc] initWithPath: path] autorelease]; + return [[[self alloc] initWithURL: URL] autorelease]; } -+ (instancetype)fileWithPath: (OFString *)path - encoding: (OFStringEncoding)encoding ++ (instancetype)fileWithURL: (OFURL *)URL encoding: (OFStringEncoding)encoding { - return [[[self alloc] initWithPath: path - encoding: encoding] autorelease]; + return [[[self alloc] initWithURL: URL encoding: encoding] autorelease]; } - (instancetype)init { OF_INVALID_INIT_METHOD } -- (instancetype)initWithPath: (OFString *)path +- (instancetype)initWithURL: (OFURL *)URL { - return [self initWithPath: path encoding: OFStringEncodingUTF8]; + return [self initWithURL: URL encoding: OFStringEncodingAutodetect]; } -- (instancetype)initWithPath: (OFString *)path - encoding: (OFStringEncoding)encoding +- (instancetype)initWithURL: (OFURL *)URL encoding: (OFStringEncoding)encoding { self = [super init]; @try { _categories = [[OFMutableArray alloc] init]; - [self of_parseFile: path encoding: encoding]; + [self of_parseURL: URL encoding: encoding]; } @catch (id e) { [self release]; @throw e; } @@ -109,19 +108,20 @@ objc_autoreleasePoolPop(pool); return category; } -- (void)of_parseFile: (OFString *)path encoding: (OFStringEncoding)encoding +- (void)of_parseURL: (OFURL *)URL encoding: (OFStringEncoding)encoding { void *pool = objc_autoreleasePoolPush(); - OFFile *file; + OFStream *file; OFINICategory *category = nil; OFString *line; @try { - file = [OFFile fileWithPath: path mode: @"r"]; + file = [[OFURLHandler handlerForURL: URL] openItemAtURL: URL + mode: @"r"]; } @catch (OFOpenItemFailedException *e) { /* Handle missing file like an empty file */ if (e.errNo == ENOENT) return; @@ -152,19 +152,21 @@ } objc_autoreleasePoolPop(pool); } -- (void)writeToFile: (OFString *)path +- (void)writeToURL: (OFURL *)URL { - [self writeToFile: path encoding: OFStringEncodingUTF8]; + [self writeToURL: URL encoding: OFStringEncodingUTF8]; } -- (void)writeToFile: (OFString *)path encoding: (OFStringEncoding)encoding +- (void)writeToURL: (OFURL *)URL encoding: (OFStringEncoding)encoding { void *pool = objc_autoreleasePoolPush(); - OFFile *file = [OFFile fileWithPath: path mode: @"w"]; + OFStream *file = [[OFURLHandler handlerForURL: URL] + openItemAtURL: URL + mode: @"w"]; bool first = true; for (OFINICategory *category in _categories) if ([category of_writeToStream: file encoding: encoding Index: src/OFINIFileSettings.h ================================================================== --- src/OFINIFileSettings.h +++ src/OFINIFileSettings.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -15,16 +15,17 @@ #import "OFSettings.h" OF_ASSUME_NONNULL_BEGIN -@class OFString; @class OFINIFile; +@class OFString; +@class OFURL; @interface OFINIFileSettings: OFSettings { - OFString *_filePath; + OFURL *_fileURL; OFINIFile *_INIFile; } @end OF_ASSUME_NONNULL_END Index: src/OFINIFileSettings.m ================================================================== --- src/OFINIFileSettings.m +++ src/OFINIFileSettings.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -14,14 +14,15 @@ */ #include "config.h" #import "OFINIFileSettings.h" -#import "OFString.h" #import "OFArray.h" #import "OFINIFile.h" +#import "OFString.h" #import "OFSystemInfo.h" +#import "OFURL.h" @implementation OFINIFileSettings - (instancetype)initWithApplicationName: (OFString *)applicationName { self = [super initWithApplicationName: applicationName]; @@ -29,13 +30,13 @@ @try { void *pool = objc_autoreleasePoolPush(); OFString *fileName; fileName = [applicationName stringByAppendingString: @".ini"]; - _filePath = [[[OFSystemInfo userConfigPath] - stringByAppendingPathComponent: fileName] copy]; - _INIFile = [[OFINIFile alloc] initWithPath: _filePath]; + _fileURL = [[[OFSystemInfo userConfigURL] + URLByAppendingPathComponent: fileName] copy]; + _INIFile = [[OFINIFile alloc] initWithURL: _fileURL]; objc_autoreleasePoolPop(pool); } @catch (id e) { [self release]; @throw e; @@ -44,11 +45,11 @@ return self; } - (void)dealloc { - [_filePath release]; + [_fileURL release]; [_INIFile release]; [super dealloc]; } @@ -240,8 +241,8 @@ objc_autoreleasePoolPop(pool); } - (void)save { - [_INIFile writeToFile: _filePath]; + [_INIFile writeToURL: _fileURL]; } @end Index: src/OFIPSocketAsyncConnector.h ================================================================== --- src/OFIPSocketAsyncConnector.h +++ src/OFIPSocketAsyncConnector.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFIPSocketAsyncConnector.m ================================================================== --- src/OFIPSocketAsyncConnector.m +++ src/OFIPSocketAsyncConnector.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -74,11 +74,11 @@ OFEnsure(0); } else { #endif if ([_delegate respondsToSelector: @selector(socket:didConnectToHost:port:exception:)]) - [_delegate socket: _socket + [_delegate socket: _socket didConnectToHost: _host port: _port exception: _exception]; #ifdef OF_HAVE_BLOCKS } Index: src/OFIPXSocket.h ================================================================== --- src/OFIPXSocket.h +++ src/OFIPXSocket.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFIPXSocket.m ================================================================== --- src/OFIPXSocket.m +++ src/OFIPXSocket.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -41,19 +41,19 @@ #endif if (_socket != OFInvalidSocketHandle) @throw [OFAlreadyConnectedException exceptionWithSocket: self]; - address = OFSocketAddressMakeIPX(zeroNode, 0, port); + address = OFSocketAddressMakeIPX(0, zeroNode, port); #ifdef OF_WINDOWS protocol = NSPROTO_IPX + packetType; #else _packetType = address.sockaddr.ipx.sipx_type = packetType; #endif - if ((_socket = socket(address.sockaddr.sockaddr.sa_family, + if ((_socket = socket(address.sockaddr.ipx.sipx_family, SOCK_DGRAM | SOCK_CLOEXEC, protocol)) == OFInvalidSocketHandle) @throw [OFBindFailedException exceptionWithPort: port packetType: packetType socket: self @@ -64,11 +64,12 @@ #if SOCK_CLOEXEC == 0 && defined(HAVE_FCNTL_H) && defined(FD_CLOEXEC) if ((flags = fcntl(_socket, F_GETFD, 0)) != -1) fcntl(_socket, F_SETFD, flags | FD_CLOEXEC); #endif - if (bind(_socket, &address.sockaddr.sockaddr, address.length) != 0) { + if (bind(_socket, (struct sockaddr *)&address.sockaddr, + address.length) != 0) { int errNo = OFSocketErrNo(); closesocket(_socket); _socket = OFInvalidSocketHandle; @@ -80,11 +81,11 @@ memset(&address, 0, sizeof(address)); address.family = OFSocketAddressFamilyIPX; address.length = (socklen_t)sizeof(address.sockaddr); - if (OFGetSockName(_socket, &address.sockaddr.sockaddr, + if (OFGetSockName(_socket, (struct sockaddr *)&address.sockaddr, &address.length) != 0) { int errNo = OFSocketErrNo(); closesocket(_socket); _socket = OFInvalidSocketHandle; @@ -93,11 +94,11 @@ packetType: packetType socket: self errNo: errNo]; } - if (address.sockaddr.sockaddr.sa_family != AF_IPX) { + if (address.sockaddr.ipx.sipx_family != AF_IPX) { closesocket(_socket); _socket = OFInvalidSocketHandle; @throw [OFBindFailedException exceptionWithPort: port packetType: packetType Index: src/OFInflate64Stream.h ================================================================== --- src/OFInflate64Stream.h +++ src/OFInflate64Stream.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -12,11 +12,10 @@ * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this * file. */ #import "OFStream.h" -#import "OFHuffmanTree.h" #import "OFKernelEventObserver.h" OF_ASSUME_NONNULL_BEGIN #define OFInflate64StreamBufferSize 4096 @@ -49,23 +48,23 @@ } uncompressedHeader; struct { uint16_t position, length; } uncompressed; struct { - OFHuffmanTree _Nullable litLenTree; - OFHuffmanTree _Nullable distTree; - OFHuffmanTree _Nullable codeLenTree; - OFHuffmanTree _Nullable treeIter; + struct _OFHuffmanTree *_Nullable litLenTree; + struct _OFHuffmanTree *_Nullable distTree; + struct _OFHuffmanTree *_Nullable codeLenTree; + struct _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; + struct _OFHuffmanTree *_Nullable litLenTree; + struct _OFHuffmanTree *_Nullable distTree; + struct _OFHuffmanTree *_Nullable treeIter; int state; uint16_t value, length, distance, extraBits; } huffman; } _context; bool _inLastBlock, _atEndOfStream; Index: src/OFInflate64Stream.m ================================================================== --- src/OFInflate64Stream.m +++ src/OFInflate64Stream.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFInflateStream.h ================================================================== --- src/OFInflateStream.h +++ src/OFInflateStream.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -12,11 +12,10 @@ * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this * file. */ #import "OFStream.h" -#import "OFHuffmanTree.h" #import "OFKernelEventObserver.h" OF_ASSUME_NONNULL_BEGIN #define OFInflateStreamBufferSize 4096 @@ -49,23 +48,23 @@ } uncompressedHeader; struct { uint16_t position, length; } uncompressed; struct { - OFHuffmanTree _Nullable litLenTree; - OFHuffmanTree _Nullable distTree; - OFHuffmanTree _Nullable codeLenTree; - OFHuffmanTree _Nullable treeIter; + struct _OFHuffmanTree *_Nullable litLenTree; + struct _OFHuffmanTree *_Nullable distTree; + struct _OFHuffmanTree *_Nullable codeLenTree; + struct _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; + struct _OFHuffmanTree *_Nullable litLenTree; + struct _OFHuffmanTree *_Nullable distTree; + struct _OFHuffmanTree *_Nullable treeIter; int state; uint16_t value, length, distance, extraBits; } huffman; } _context; bool _inLastBlock, _atEndOfStream; Index: src/OFInflateStream.m ================================================================== --- src/OFInflateStream.m +++ src/OFInflateStream.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFInvertedCharacterSet.h ================================================================== --- src/OFInvertedCharacterSet.h +++ src/OFInvertedCharacterSet.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFInvertedCharacterSet.m ================================================================== --- src/OFInvertedCharacterSet.m +++ src/OFInvertedCharacterSet.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFInvocation.h ================================================================== --- src/OFInvocation.h +++ src/OFInvocation.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFInvocation.m ================================================================== --- src/OFInvocation.m +++ src/OFInvocation.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFJSONRepresentation.h ================================================================== --- src/OFJSONRepresentation.h +++ src/OFJSONRepresentation.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFKernelEventObserver.h ================================================================== --- src/OFKernelEventObserver.h +++ src/OFKernelEventObserver.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFKernelEventObserver.m ================================================================== --- src/OFKernelEventObserver.m +++ src/OFKernelEventObserver.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFKeyValueCoding.h ================================================================== --- src/OFKeyValueCoding.h +++ src/OFKeyValueCoding.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFKqueueKernelEventObserver.h ================================================================== --- src/OFKqueueKernelEventObserver.h +++ src/OFKqueueKernelEventObserver.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFKqueueKernelEventObserver.m ================================================================== --- src/OFKqueueKernelEventObserver.m +++ src/OFKqueueKernelEventObserver.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFLHAArchive.h ================================================================== --- src/OFLHAArchive.h +++ src/OFLHAArchive.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFLHAArchive.m ================================================================== --- src/OFLHAArchive.m +++ src/OFLHAArchive.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -12,10 +12,12 @@ * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this * file. */ #include "config.h" + +#include #import "OFLHAArchive.h" #import "OFLHAArchiveEntry.h" #import "OFLHAArchiveEntry+Private.h" #import "OFCRC16.h" @@ -471,32 +473,34 @@ [super dealloc]; } - (size_t)lowlevelWriteBuffer: (const void *)buffer length: (size_t)length { - uint32_t bytesWritten; - if (_stream == nil) @throw [OFNotOpenException exceptionWithObject: self]; if (UINT32_MAX - _bytesWritten < length) @throw [OFOutOfRangeException exception]; @try { - bytesWritten = (uint32_t)[_stream writeBuffer: buffer - length: length]; + [_stream writeBuffer: buffer length: length]; } @catch (OFWriteFailedException *e) { - _bytesWritten += e.bytesWritten; + OFEnsure(e.bytesWritten <= length); + + _bytesWritten += (uint32_t)e.bytesWritten; _CRC16 = OFCRC16(_CRC16, buffer, e.bytesWritten); + + if (e.errNo == EWOULDBLOCK || e.errNo == EAGAIN) + return e.bytesWritten; @throw e; } - _bytesWritten += (uint32_t)bytesWritten; - _CRC16 = OFCRC16(_CRC16, buffer, bytesWritten); + _bytesWritten += (uint32_t)length; + _CRC16 = OFCRC16(_CRC16, buffer, length); - return bytesWritten; + return length; } - (bool)lowlevelIsAtEndOfStream { if (_stream == nil) Index: src/OFLHAArchiveEntry+Private.h ================================================================== --- src/OFLHAArchiveEntry+Private.h +++ src/OFLHAArchiveEntry+Private.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFLHAArchiveEntry.h ================================================================== --- src/OFLHAArchiveEntry.h +++ src/OFLHAArchiveEntry.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFLHAArchiveEntry.m ================================================================== --- src/OFLHAArchiveEntry.m +++ src/OFLHAArchiveEntry.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFLHADecompressingStream.h ================================================================== --- src/OFLHADecompressingStream.h +++ src/OFLHADecompressingStream.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFLHADecompressingStream.m ================================================================== --- src/OFLHADecompressingStream.m +++ src/OFLHADecompressingStream.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFList.h ================================================================== --- src/OFList.h +++ src/OFList.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFList.m ================================================================== --- src/OFList.m +++ src/OFList.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFLocale.h ================================================================== --- src/OFLocale.h +++ src/OFLocale.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -150,11 +150,11 @@ * * @warning This sets the locale via `setlocale()`! * * @warning You should never call this yourself, except if you do not use * @ref OFApplication. In this case, you need to allocate exactly one - * instance of OFLocale, which will be come the current locale, and + * instance of OFLocale, which will become the current locale, and * call this method. */ - (instancetype)init; #ifdef OF_HAVE_FILES Index: src/OFLocale.m ================================================================== --- src/OFLocale.m +++ src/OFLocale.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFLocking.h ================================================================== --- src/OFLocking.h +++ src/OFLocking.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFMD5Hash.h ================================================================== --- src/OFMD5Hash.h +++ src/OFMD5Hash.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFMD5Hash.m ================================================================== --- src/OFMD5Hash.m +++ src/OFMD5Hash.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -19,10 +19,11 @@ #import "OFMD5Hash.h" #import "OFSecureData.h" #import "OFHashAlreadyCalculatedException.h" +#import "OFHashNotCalculatedException.h" #import "OFOutOfRangeException.h" static const size_t digestSize = 16; static const size_t blockSize = 64; @@ -242,12 +243,21 @@ } } - (const unsigned char *)digest { + if (!_calculated) + @throw [OFHashNotCalculatedException exceptionWithObject: self]; + + return (const unsigned char *)_iVars->state; +} + +- (void)calculate +{ if (_calculated) - return (const unsigned char *)_iVars->state; + @throw [OFHashAlreadyCalculatedException + exceptionWithObject: self]; _iVars->buffer.bytes[_iVars->bufferLength] = 0x80; OFZeroMemory(_iVars->buffer.bytes + _iVars->bufferLength + 1, 64 - _iVars->bufferLength - 1); @@ -263,12 +273,10 @@ processBlock(_iVars->state, _iVars->buffer.words); OFZeroMemory(&_iVars->buffer, sizeof(_iVars->buffer)); byteSwapVectorIfBE(_iVars->state, 4); _calculated = true; - - return (const unsigned char *)_iVars->state; } - (void)reset { [self of_resetState]; Index: src/OFMapTable+Private.h ================================================================== --- src/OFMapTable+Private.h +++ src/OFMapTable+Private.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFMapTable.h ================================================================== --- src/OFMapTable.h +++ src/OFMapTable.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -71,11 +71,11 @@ OF_SUBCLASSING_RESTRICTED @interface OFMapTable: OFObject { OFMapTableFunctions _keyFunctions, _objectFunctions; struct OFMapTableBucket *_Nonnull *_Nullable _buckets; - unsigned long _count, _capacity; + uint32_t _count, _capacity; unsigned char _rotate; unsigned long _mutations; } /** @@ -233,12 +233,12 @@ */ @interface OFMapTableEnumerator: OFObject { OFMapTable *_mapTable; struct OFMapTableBucket *_Nonnull *_Nullable _buckets; - unsigned long _capacity, _mutations, *_Nullable _mutationsPtr; - unsigned long _position; + uint32_t _capacity; + unsigned long _mutations, *_Nullable _mutationsPtr, _position; } - (instancetype)init OF_UNAVAILABLE; /** Index: src/OFMapTable.m ================================================================== --- src/OFMapTable.m +++ src/OFMapTable.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -26,17 +26,17 @@ #import "OFEnumerationMutationException.h" #import "OFInvalidArgumentException.h" #import "OFOutOfRangeException.h" -extern unsigned long OFHashSeed; +extern uint32_t OFHashSeed; -static const unsigned long minCapacity = 16; +static const uint32_t minCapacity = 16; struct OFMapTableBucket { void *key, *object; - unsigned long hash; + uint32_t hash; }; static struct OFMapTableBucket deletedBucket = { 0 }; static void * defaultRetain(void *object) @@ -63,11 +63,11 @@ OF_DIRECT_MEMBERS @interface OFMapTableEnumerator () - (instancetype)of_initWithMapTable: (OFMapTable *)mapTable buckets: (struct OFMapTableBucket **)buckets - capacity: (unsigned long)capacity + capacity: (uint32_t)capacity mutationsPointer: (unsigned long *)mutationsPtr OF_METHOD_FAMILY(init); @end @interface OFMapTableKeyEnumerator: OFMapTableEnumerator @@ -134,23 +134,23 @@ SET_DEFAULT(_objectFunctions.hash, defaultHash); SET_DEFAULT(_objectFunctions.equal, defaultEqual); #undef SET_DEFAULT - if (capacity > ULONG_MAX / sizeof(*_buckets) || - capacity > ULONG_MAX / 8) + if (capacity > UINT32_MAX / sizeof(*_buckets) || + capacity > UINT32_MAX / 8) @throw [OFOutOfRangeException exception]; for (_capacity = 1; _capacity < capacity;) { - if (_capacity > ULONG_MAX / 2) + if (_capacity > UINT32_MAX / 2) @throw [OFOutOfRangeException exception]; _capacity *= 2; } if (capacity * 8 / _capacity >= 6) - if (_capacity <= ULONG_MAX / 2) + if (_capacity <= UINT32_MAX / 2) _capacity *= 2; if (_capacity < minCapacity) _capacity = minCapacity; @@ -166,11 +166,11 @@ return self; } - (void)dealloc { - for (unsigned long i = 0; i < _capacity; i++) { + for (uint32_t i = 0; i < _capacity; i++) { if (_buckets[i] != NULL && _buckets[i] != &deletedBucket) { _keyFunctions.release(_buckets[i]->key); _objectFunctions.release(_buckets[i]->object); OFFreeMemory(_buckets[i]); @@ -181,23 +181,23 @@ [super dealloc]; } static void -resizeForCount(OFMapTable *self, unsigned long count) +resizeForCount(OFMapTable *self, uint32_t count) { - unsigned long fullness, capacity; + uint32_t fullness, capacity; struct OFMapTableBucket **buckets; - if (count > ULONG_MAX / sizeof(*self->_buckets) || - count > ULONG_MAX / 8) + if (count > UINT32_MAX / sizeof(*self->_buckets) || + count > UINT32_MAX / 8) @throw [OFOutOfRangeException exception]; fullness = count * 8 / self->_capacity; if (fullness >= 6) { - if (self->_capacity > ULONG_MAX / 2) + if (self->_capacity > UINT32_MAX / 2) return; capacity = self->_capacity * 2; } else if (fullness <= 1) capacity = self->_capacity / 2; @@ -212,14 +212,14 @@ capacity < minCapacity) return; buckets = OFAllocZeroedMemory(capacity, sizeof(*buckets)); - for (unsigned long i = 0; i < self->_capacity; i++) { + for (uint32_t i = 0; i < self->_capacity; i++) { if (self->_buckets[i] != NULL && self->_buckets[i] != &deletedBucket) { - unsigned long j, last; + uint32_t j, last; last = capacity; for (j = self->_buckets[i]->hash & (capacity - 1); j < last && buckets[j] != NULL; j++); @@ -243,14 +243,13 @@ self->_buckets = buckets; self->_capacity = capacity; } static void -setObject(OFMapTable *restrict self, void *key, void *object, - unsigned long hash) +setObject(OFMapTable *restrict self, void *key, void *object, uint32_t hash) { - unsigned long i, last; + uint32_t i, last; void *old; if (key == NULL || object == NULL) @throw [OFInvalidArgumentException exception]; @@ -351,11 +350,11 @@ if (mapTable->_count != _count || mapTable->_keyFunctions.equal != _keyFunctions.equal || mapTable->_objectFunctions.equal != _objectFunctions.equal) return false; - for (unsigned long i = 0; i < _capacity; i++) { + for (uint32_t i = 0; i < _capacity; i++) { if (_buckets[i] != NULL && _buckets[i] != &deletedBucket) { void *objectIter = [mapTable objectForKey: _buckets[i]->key]; if (!_objectFunctions.equal(objectIter, @@ -387,11 +386,11 @@ initWithKeyFunctions: _keyFunctions objectFunctions: _objectFunctions capacity: _capacity]; @try { - for (unsigned long i = 0; i < _capacity; i++) + for (uint32_t i = 0; i < _capacity; i++) if (_buckets[i] != NULL && _buckets[i] != &deletedBucket) setObject(copy, _buckets[i]->key, _buckets[i]->object, OFRotateRight(_buckets[i]->hash, _rotate)); @@ -408,16 +407,16 @@ return _count; } - (void *)objectForKey: (void *)key { - unsigned long i, hash, last; + uint32_t i, hash, last; if (key == NULL) @throw [OFInvalidArgumentException exception]; - hash = OFRotateLeft(_keyFunctions.hash(key), _rotate); + hash = OFRotateLeft((uint32_t)_keyFunctions.hash(key), _rotate); last = _capacity; for (i = hash & (_capacity - 1); i < last && _buckets[i] != NULL; i++) { if (_buckets[i] == &deletedBucket) continue; @@ -443,21 +442,21 @@ return NULL; } - (void)setObject: (void *)object forKey: (void *)key { - setObject(self, key, object,_keyFunctions.hash(key)); + setObject(self, key, object, (uint32_t)_keyFunctions.hash(key)); } - (void)removeObjectForKey: (void *)key { - unsigned long i, hash, last; + uint32_t i, hash, last; if (key == NULL) @throw [OFInvalidArgumentException exception]; - hash = OFRotateLeft(_keyFunctions.hash(key), _rotate); + hash = OFRotateLeft((uint32_t)_keyFunctions.hash(key), _rotate); last = _capacity; for (i = hash & (_capacity - 1); i < last && _buckets[i] != NULL; i++) { if (_buckets[i] == &deletedBucket) continue; @@ -504,11 +503,11 @@ } } - (void)removeAllObjects { - for (unsigned long i = 0; i < _capacity; i++) { + for (uint32_t i = 0; i < _capacity; i++) { if (_buckets[i] != NULL) { if (_buckets[i] == &deletedBucket) { _buckets[i] = NULL; continue; } @@ -536,11 +535,11 @@ - (bool)containsObject: (void *)object { if (object == NULL || _count == 0) return false; - for (unsigned long i = 0; i < _capacity; i++) + for (uint32_t i = 0; i < _capacity; i++) if (_buckets[i] != NULL && _buckets[i] != &deletedBucket) if (_objectFunctions.equal(_buckets[i]->object, object)) return true; return false; @@ -549,11 +548,11 @@ - (bool)containsObjectIdenticalTo: (void *)object { if (object == NULL || _count == 0) return false; - for (unsigned long i = 0; i < _capacity; i++) + for (uint32_t i = 0; i < _capacity; i++) if (_buckets[i] != NULL && _buckets[i] != &deletedBucket) if (_buckets[i]->object == object) return true; return false; @@ -651,11 +650,11 @@ OF_INVALID_INIT_METHOD } - (instancetype)of_initWithMapTable: (OFMapTable *)mapTable buckets: (struct OFMapTableBucket **)buckets - capacity: (unsigned long)capacity + capacity: (uint32_t)capacity mutationsPointer: (unsigned long *)mutationsPtr { self = [super init]; _mapTable = [mapTable retain]; Index: src/OFMapTableDictionary.h ================================================================== --- src/OFMapTableDictionary.h +++ src/OFMapTableDictionary.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFMapTableDictionary.m ================================================================== --- src/OFMapTableDictionary.m +++ src/OFMapTableDictionary.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFMapTableSet.h ================================================================== --- src/OFMapTableSet.h +++ src/OFMapTableSet.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFMapTableSet.m ================================================================== --- src/OFMapTableSet.m +++ src/OFMapTableSet.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in ADDED src/OFMemoryStream.h Index: src/OFMemoryStream.h ================================================================== --- src/OFMemoryStream.h +++ src/OFMemoryStream.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2008-2022 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either 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 "OFSeekableStream.h" + +OF_ASSUME_NONNULL_BEGIN + +/** + * @class OFMemoryStream OFMemoryStream.h ObjFW/OFMemoryStream.h + * + * @brief A seekable stream for reading from and writing to memory. + */ +OF_SUBCLASSING_RESTRICTED +@interface OFMemoryStream: OFSeekableStream +{ + char *_address; + size_t _size, _position; + bool _writable; +} + +/** + * @brief Creates a new OFMemoryStream with the specified memory. + * + * @warning The memory is not copied, so it is your responsibility that the + * specified memory stays alive for as long as the OFMemoryStream does! + * + * @param address The memory address for the stream + * @param size The size of the memory at the specified address + * @param writable Whether writes to memory should be allowed + * @return A new autoreleased OFMemoryStream + */ ++ (instancetype)streamWithMemoryAddress: (void *)address + size: (size_t)size + writable: (bool)writable; + +- (instancetype)init OF_UNAVAILABLE; + +/** + * @brief Initializes an already allocated OFMemoryStream with the specified + * memory. + * + * @warning The memory is not copied, so it is your responsibility that the + * specified memory stays alive for as long as the OFMemoryStream does! + * + * @param address The memory address for the stream + * @param size The size of the memory at the specified address + * @param writable Whether writes to memory should be allowed + * @return An initialized OFMemoryStream + */ +- (instancetype)initWithMemoryAddress: (void *)address + size: (size_t)size + writable: (bool)writable; +@end + +OF_ASSUME_NONNULL_END ADDED src/OFMemoryStream.m Index: src/OFMemoryStream.m ================================================================== --- src/OFMemoryStream.m +++ src/OFMemoryStream.m @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2008-2022 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 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 + +#import "OFMemoryStream.h" + +#import "OFInvalidArgumentException.h" +#import "OFOutOfRangeException.h" +#import "OFWriteFailedException.h" +#import "OFSeekFailedException.h" + +@implementation OFMemoryStream ++ (instancetype)streamWithMemoryAddress: (void *)address + size: (size_t)size + writable: (bool)writable +{ + return [[[self alloc] initWithMemoryAddress: address + size: size + writable: writable] autorelease]; +} + +- (instancetype)init +{ + OF_INVALID_INIT_METHOD +} + +- (instancetype)initWithMemoryAddress: (void *)address + size: (size_t)size + writable: (bool)writable +{ + self = [super init]; + + @try { + if (size > SSIZE_MAX || (ssize_t)size != (OFFileOffset)size) + @throw [OFOutOfRangeException exception]; + + _address = address; + _size = size; + _writable = writable; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (size_t)lowlevelReadIntoBuffer: (void *)buffer length: (size_t)length +{ + if (SIZE_MAX - _position < length || _position + length > _size) + length = _size - _position; + + memcpy(buffer, _address + _position, length); + _position += length; + + return length; +} + +- (size_t)lowlevelWriteBuffer: (const void *)buffer length: (size_t)length +{ + size_t bytesWritten = length; + + if (!_writable) + @throw [OFWriteFailedException exceptionWithObject: self + requestedLength: length + bytesWritten: 0 + errNo: EBADF]; + + if (SIZE_MAX - _position < length || _position + length > _size) + bytesWritten = _size - _position; + + memcpy(_address + _position, buffer, bytesWritten); + _position += bytesWritten; + + if (bytesWritten != length) + @throw [OFWriteFailedException exceptionWithObject: self + requestedLength: length + bytesWritten: bytesWritten + errNo: EFBIG]; + + return bytesWritten; +} + +- (bool)lowlevelIsAtEndOfStream +{ + return (_position == _size); +} + +- (OFFileOffset)lowlevelSeekToOffset: (OFFileOffset)offset whence: (int)whence +{ + OFFileOffset new; + + switch (whence) { + case SEEK_SET: + new = offset; + break; + case SEEK_CUR: + new = (OFFileOffset)_position + offset; + break; + case SEEK_END: + new = (OFFileOffset)_size + offset; + break; + default: + @throw [OFInvalidArgumentException exception]; + } + + if (new < 0 || new > (OFFileOffset)_size) + @throw [OFSeekFailedException exceptionWithStream: self + offset: offset + whence: whence + errNo: EINVAL]; + + return (_position = (size_t)new); +} +@end Index: src/OFMessagePackExtension.h ================================================================== --- src/OFMessagePackExtension.h +++ src/OFMessagePackExtension.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFMessagePackExtension.m ================================================================== --- src/OFMessagePackExtension.m +++ src/OFMessagePackExtension.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFMessagePackRepresentation.h ================================================================== --- src/OFMessagePackRepresentation.h +++ src/OFMessagePackRepresentation.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFMethodSignature.h ================================================================== --- src/OFMethodSignature.h +++ src/OFMethodSignature.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFMethodSignature.m ================================================================== --- src/OFMethodSignature.m +++ src/OFMethodSignature.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFMutableAdjacentArray.h ================================================================== --- src/OFMutableAdjacentArray.h +++ src/OFMutableAdjacentArray.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFMutableAdjacentArray.m ================================================================== --- src/OFMutableAdjacentArray.m +++ src/OFMutableAdjacentArray.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -105,12 +105,10 @@ for (size_t i = 0; i < count; i++) { if ([objects[i] isEqual: oldObject]) { [newObject retain]; [objects[i] release]; objects[i] = newObject; - - return; } } } - (void)replaceObjectAtIndex: (size_t)idx withObject: (id)object @@ -164,18 +162,21 @@ objects = _array.items; count = _array.count; for (size_t i = 0; i < count; i++) { if ([objects[i] isEqual: object]) { - object = objects[i]; + id tmp = objects[i]; [_array removeItemAtIndex: i]; _mutations++; - [object release]; + [tmp release]; - return; + objects = _array.items; + i--; + count--; + continue; } } } - (void)removeObjectIdenticalTo: (id)object @@ -194,11 +195,14 @@ [_array removeItemAtIndex: i]; _mutations++; [object release]; - return; + objects = _array.items; + i--; + count--; + continue; } } } - (void)removeObjectAtIndex: (size_t)idx Index: src/OFMutableArray.h ================================================================== --- src/OFMutableArray.h +++ src/OFMutableArray.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -92,11 +92,11 @@ */ - (void)insertObjectsFromArray: (OFArray OF_GENERIC(ObjectType) *)array atIndex: (size_t)index; /** - * @brief Replaces the first object equivalent to the specified object with the + * @brief Replaces all objects equivalent to the specified object with the * other specified object. * * @param oldObject The object to replace * @param newObject The replacement object */ @@ -131,18 +131,18 @@ */ - (void)replaceObjectIdenticalTo: (ObjectType)oldObject withObject: (ObjectType)newObject; /** - * @brief Removes the first object equivalent to the specified object. + * @brief Removes all objects equivalent to the specified object. * * @param object The object to remove */ - (void)removeObject: (ObjectType)object; /** - * @brief Removes the first object that has the same address as the specified + * @brief Removes all objects that have the same address as the specified * object. * * @param object The object to remove */ - (void)removeObjectIdenticalTo: (ObjectType)object; @@ -153,11 +153,11 @@ * @param index The index of the object to remove */ - (void)removeObjectAtIndex: (size_t)index; /** - * @brief Removes the object in the specified range. + * @brief Removes the objects in the specified range. * * @param range The range of the objects to remove */ - (void)removeObjectsInRange: (OFRange)range; Index: src/OFMutableArray.m ================================================================== --- src/OFMutableArray.m +++ src/OFMutableArray.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -293,16 +293,13 @@ if (oldObject == nil || newObject == nil) @throw [OFInvalidArgumentException exception]; count = self.count; - for (size_t i = 0; i < count; i++) { - if ([[self objectAtIndex: i] isEqual: oldObject]) { + for (size_t i = 0; i < count; i++) + if ([[self objectAtIndex: i] isEqual: oldObject]) [self replaceObjectAtIndex: i withObject: newObject]; - return; - } - } } - (void)replaceObjectIdenticalTo: (id)oldObject withObject: (id)newObject { size_t count; @@ -337,11 +334,13 @@ for (size_t i = 0; i < count; i++) { if ([[self objectAtIndex: i] isEqual: object]) { [self removeObjectAtIndex: i]; - return; + i--; + count--; + continue; } } } - (void)removeObjectIdenticalTo: (id)object @@ -355,11 +354,13 @@ for (size_t i = 0; i < count; i++) { if ([self objectAtIndex: i] == object) { [self removeObjectAtIndex: i]; - return; + i--; + count--; + continue; } } } - (void)removeObjectsInRange: (OFRange)range Index: src/OFMutableData.h ================================================================== --- src/OFMutableData.h +++ src/OFMutableData.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -37,11 +37,12 @@ * @warning The pointer is only valid until the OFMutableData is changed! * * Modifying the returned array directly is allowed and will change the contents * of the data. */ -@property (readonly, nonatomic) void *mutableItems OF_RETURNS_INNER_POINTER; +@property OF_NULLABLE_PROPERTY (readonly, nonatomic) void *mutableItems + OF_RETURNS_INNER_POINTER; /** * @brief The first item of the OFMutableData or `NULL`. */ @property OF_NULLABLE_PROPERTY (readonly, nonatomic) void *mutableFirstItem Index: src/OFMutableData.m ================================================================== --- src/OFMutableData.m +++ src/OFMutableData.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFMutableDictionary.h ================================================================== --- src/OFMutableDictionary.h +++ src/OFMutableDictionary.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFMutableDictionary.m ================================================================== --- src/OFMutableDictionary.m +++ src/OFMutableDictionary.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFMutableLHAArchiveEntry.h ================================================================== --- src/OFMutableLHAArchiveEntry.h +++ src/OFMutableLHAArchiveEntry.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFMutableLHAArchiveEntry.m ================================================================== --- src/OFMutableLHAArchiveEntry.m +++ src/OFMutableLHAArchiveEntry.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFMutableMapTableDictionary.h ================================================================== --- src/OFMutableMapTableDictionary.h +++ src/OFMutableMapTableDictionary.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFMutableMapTableDictionary.m ================================================================== --- src/OFMutableMapTableDictionary.m +++ src/OFMutableMapTableDictionary.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFMutableMapTableSet.h ================================================================== --- src/OFMutableMapTableSet.h +++ src/OFMutableMapTableSet.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFMutableMapTableSet.m ================================================================== --- src/OFMutableMapTableSet.m +++ src/OFMutableMapTableSet.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFMutablePair.h ================================================================== --- src/OFMutablePair.h +++ src/OFMutablePair.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFMutablePair.m ================================================================== --- src/OFMutablePair.m +++ src/OFMutablePair.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFMutableSet.h ================================================================== --- src/OFMutableSet.h +++ src/OFMutableSet.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFMutableSet.m ================================================================== --- src/OFMutableSet.m +++ src/OFMutableSet.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFMutableString.h ================================================================== --- src/OFMutableString.h +++ src/OFMutableString.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFMutableString.m ================================================================== --- src/OFMutableString.m +++ src/OFMutableString.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFMutableTarArchiveEntry.h ================================================================== --- src/OFMutableTarArchiveEntry.h +++ src/OFMutableTarArchiveEntry.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFMutableTarArchiveEntry.m ================================================================== --- src/OFMutableTarArchiveEntry.m +++ src/OFMutableTarArchiveEntry.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFMutableTriple.h ================================================================== --- src/OFMutableTriple.h +++ src/OFMutableTriple.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFMutableTriple.m ================================================================== --- src/OFMutableTriple.m +++ src/OFMutableTriple.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFMutableURL.h ================================================================== --- src/OFMutableURL.h +++ src/OFMutableURL.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -129,12 +129,12 @@ * * For example, a query like `key1=value1&key2=value2` would correspond to the * following dictionary: * * @{ - * @"key1": "value1", - * @"key2": "value2" + * @"key1": @"value1", + * @"key2": @"value2" * } */ @property OF_NULLABLE_PROPERTY (readwrite, copy, nonatomic) OFDictionary OF_GENERIC(OFString *, OFString *) *queryDictionary; @@ -175,11 +175,11 @@ */ - (void)appendPathComponent: (OFString *)component isDirectory: (bool)isDirectory; /** - * @brief Resolves relative sub paths. + * @brief Resolves relative subpaths. */ - (void)standardizePath; /** * @brief Converts the mutable URL to an immutable URL. Index: src/OFMutableURL.m ================================================================== --- src/OFMutableURL.m +++ src/OFMutableURL.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFMutableUTF8String.h ================================================================== --- src/OFMutableUTF8String.h +++ src/OFMutableUTF8String.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFMutableUTF8String.m ================================================================== --- src/OFMutableUTF8String.m +++ src/OFMutableUTF8String.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFMutableZIPArchiveEntry.h ================================================================== --- src/OFMutableZIPArchiveEntry.h +++ src/OFMutableZIPArchiveEntry.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFMutableZIPArchiveEntry.m ================================================================== --- src/OFMutableZIPArchiveEntry.m +++ src/OFMutableZIPArchiveEntry.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFMutex.h ================================================================== --- src/OFMutex.h +++ src/OFMutex.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFMutex.m ================================================================== --- src/OFMutex.m +++ src/OFMutex.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFNonretainedObjectValue.h ================================================================== --- src/OFNonretainedObjectValue.h +++ src/OFNonretainedObjectValue.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFNonretainedObjectValue.m ================================================================== --- src/OFNonretainedObjectValue.m +++ src/OFNonretainedObjectValue.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in ADDED src/OFNotification.h Index: src/OFNotification.h ================================================================== --- src/OFNotification.h +++ src/OFNotification.h @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2008-2022 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#import "OFObject.h" + +OF_ASSUME_NONNULL_BEGIN + +/** @file */ + +@class OFConstantString; +@class OFDictionary OF_GENERIC(KeyType, ObjectType); + +/** + * @brief A name for a notification. + */ +typedef OFConstantString *OFNotificationName; + +/** + * @class OFNotification OFNotification.h ObjFW/OFNotification.h + * + * @brief A class to represent a notification for or from + * @ref OFNotificationCenter. + */ +OF_SUBCLASSING_RESTRICTED +@interface OFNotification: OFObject +{ + OFNotificationName _name; + id _Nullable _object; + OFDictionary *_Nullable _userInfo; +} + +/** + * @brief The name of the notification. + */ +@property (readonly, nonatomic) OFNotificationName name; + +/** + * @brief The object of the notification. This is commonly the sender of the + * notification. + */ +@property OF_NULLABLE_PROPERTY (readonly, nonatomic) id object; + +/** + * @brief Additional information about the notification. + */ +@property OF_NULLABLE_PROPERTY (readonly, nonatomic) OFDictionary *userInfo; + +/** + * @brief Creates a new notification with the specified name and object. + * + * @param name The name for the notification + * @param object The object for the notification. This is commonly the sender + * of the notification. + * @return A new, autoreleased OFNotification + */ ++ (instancetype)notificationWithName: (OFNotificationName)name + object: (nullable id)object; + +/** + * @brief Creates a new notification with the specified name, object and + * additional information. + * + * @param name The name for the notification + * @param object The object for the notification. This is commonly the sender + * of the notification. + * @param userInfo Additional information for the notification + * @return A new, autoreleased OFNotification + */ ++ (instancetype)notificationWithName: (OFNotificationName)name + object: (nullable id)object + userInfo: (nullable OFDictionary *)userInfo; + +/** + * @brief Initializes an already allocated notification with the specified + * name and object. + * + * @param name The name for the notification + * @param object The object for the notification. This is commonly the sender + * of the notification. + * @return An initialized OFNotification + */ +- (instancetype)initWithName: (OFNotificationName)name + object: (nullable id)object; + +/** + * @brief Initializes an already allocated notification with the specified + * name, object and additional information. + * + * @param name The name for the notification + * @param object The object for the notification. This is commonly the sender + * of the notification. + * @param userInfo Additional information for the notification + * @return An initialized OFNotification + */ +- (instancetype)initWithName: (OFNotificationName)name + object: (nullable id)object + userInfo: (nullable OFDictionary *)userInfo + OF_DESIGNATED_INITIALIZER; + +- (instancetype)init OF_UNAVAILABLE; +@end + +OF_ASSUME_NONNULL_END ADDED src/OFNotification.m Index: src/OFNotification.m ================================================================== --- src/OFNotification.m +++ src/OFNotification.m @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2008-2022 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 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 "OFNotification.h" +#import "OFDictionary.h" +#import "OFString.h" + +@implementation OFNotification +@synthesize name = _name, object = _object, userInfo = _userInfo; + ++ (instancetype)notificationWithName: (OFNotificationName)name + object: (id)object +{ + return [[[self alloc] initWithName: name object: object] autorelease]; +} + ++ (instancetype)notificationWithName: (OFNotificationName)name + object: (id)object + userInfo: (OFDictionary *)userInfo +{ + return [[[self alloc] initWithName: name + object: object + userInfo: userInfo] autorelease]; +} + +- (instancetype)initWithName: (OFNotificationName)name object: (id)object +{ + return [self initWithName: name object: object userInfo: nil]; +} + +- (instancetype)initWithName: (OFNotificationName)name + object: (id)object + userInfo: (OFDictionary *)userInfo +{ + self = [super init]; + + @try { + _name = [name copy]; + _object = [object retain]; + _userInfo = [userInfo copy]; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (instancetype)init +{ + OF_INVALID_INIT_METHOD +} + +- (void)dealloc +{ + [_name release]; + [_object release]; + [_userInfo release]; + + [super dealloc]; +} + +- (id)copy +{ + return [self retain]; +} +@end ADDED src/OFNotificationCenter.h Index: src/OFNotificationCenter.h ================================================================== --- src/OFNotificationCenter.h +++ src/OFNotificationCenter.h @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2008-2022 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either 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 "OFNotification.h" + +OF_ASSUME_NONNULL_BEGIN + +@class OFMutableDictionary OF_GENERIC(KeyType, ObjectType); +#ifdef OF_HAVE_THREADS +@class OFMutex; +#endif +@class OFNotificationCenterHandle; + +#ifdef OF_HAVE_BLOCKS +/** + * @brief A block which is called when a notification has been posted. + * + * @param notification The notification that has been posted + */ +typedef void (^OFNotificationCenterBlock)(OFNotification *notification); +#endif + +/** + * @class OFNotificationCenter OFNotificationCenter.h \ + * ObjFW/OFNotificationCenter.h + * + * @brief A class to send and register for notifications. + */ +@interface OFNotificationCenter: OFObject +{ +#ifdef OF_HAVE_THREADS + OFMutex *_mutex; +#endif + OFMutableDictionary *_handles; + OF_RESERVE_IVARS(OFNotificationCenter, 4) +} + +#ifdef OF_HAVE_CLASS_PROPERTIES +@property (class, readonly, nonatomic) OFNotificationCenter *defaultCenter; +#endif + +/** + * @brief Returns the default notification center. + */ ++ (OFNotificationCenter *)defaultCenter; + +/** + * @brief Adds an observer for the specified notification and object. + * + * @param observer The object that should receive notifications + * @param selector The selector to call on the observer on notifications. The + * method must take exactly one object of type @ref + * OFNotification. + * @param name The name of the notification to observe + * @param object The object that should be sending the notification, or `nil` + * if the object should be ignored to determine what + * notifications to deliver + */ +- (void)addObserver: (id)observer + selector: (SEL)selector + name: (OFNotificationName)name + object: (nullable id)object; + +/** + * @brief Removes an observer. All parameters must match those used with + * @ref addObserver:selector:name:object:. + * + * @param observer The observer that was specified when adding the observer + * @param selector The selector that was specified when adding the observer + * @param name The name that was specified when adding the observer + * @param object The object that was specified when adding the observer + */ +- (void)removeObserver: (id)observer + selector: (SEL)selector + name: (OFNotificationName)name + object: (nullable id)object; + +#ifdef OF_HAVE_BLOCKS +/** + * @brief Adds an observer for the specified notification and object. + * + * To remove the observer again, use @ref removeObserver:. + * + * @param name The name of the notification to observe + * @param object The object that should be sending the notification, or `nil` + * if the object should be ignored to determine what + * notifications to deliver + * @param block The block to handle notifications + * @return An opaque object to remove the observer again + */ +- (OFNotificationCenterHandle *) + addObserverForName: (OFNotificationName)name + object: (nullable id)object + usingBlock: (OFNotificationCenterBlock)block; + +/** + * @brief Removes an observer. The specified observer must be one returned by + * @ref addObserver:selector:name:object:. + * + * @param observer The object that was returned when adding the observer + */ +- (void)removeObserver: (OFNotificationCenterHandle *)observer; +#endif + +/** + * @brief Posts the specified notification. + * + * @param notification The notification to post + */ +- (void)postNotification: (OFNotification *)notification; + +/** + * @brief Posts a notification with the specified name and object. + * + * @param name The name for the notification + * @param object The object for the notification + */ +- (void)postNotificationName: (OFNotificationName)name + object: (nullable id)object; + +/** + * @brief Posts a notification with the specified name, object and additional + * information. + * + * @param name The name for the notification + * @param object The object for the notification + * @param userInfo Additional information for the notification + */ +- (void)postNotificationName: (OFNotificationName)name + object: (nullable id)object + userInfo: (nullable OFDictionary *)userInfo; +@end + +OF_ASSUME_NONNULL_END ADDED src/OFNotificationCenter.m Index: src/OFNotificationCenter.m ================================================================== --- src/OFNotificationCenter.m +++ src/OFNotificationCenter.m @@ -0,0 +1,397 @@ +/* + * Copyright (c) 2008-2022 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 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 "OFNotificationCenter.h" +#import "OFArray.h" +#import "OFDictionary.h" +#ifdef OF_HAVE_THREADS +# import "OFMutex.h" +#endif +#import "OFSet.h" +#import "OFString.h" + +#import "OFInvalidArgumentException.h" + +@interface OFDefaultNotificationCenter: OFNotificationCenter +@end + +@interface OFNotificationCenterHandle: OFObject +{ +@public + OFNotificationName _name; + id _observer; + SEL _selector; + unsigned long _selectorHash; +#ifdef OF_HAVE_BLOCKS + OFNotificationCenterBlock _block; +#endif + id _object; +} + +- (instancetype)initWithName: (OFNotificationName)name + observer: (id)observer + selector: (SEL)selector + object: (id)object; +#ifdef OF_HAVE_BLOCKS +- (instancetype)initWithName: (OFNotificationName)name + object: (id)object + block: (OFNotificationCenterBlock)block; +#endif +@end + +static OFNotificationCenter *defaultCenter; + +@implementation OFNotificationCenterHandle +- (instancetype)initWithName: (OFNotificationName)name + observer: (id)observer + selector: (SEL)selector + object: (id)object +{ + self = [super init]; + + @try { + void *pool = objc_autoreleasePoolPush(); + + _name = [name copy]; + _observer = [observer retain]; + _selector = selector; + _object = [object retain]; + + _selectorHash = [[OFString stringWithUTF8String: + sel_getName(_selector)] hash]; + + objc_autoreleasePoolPop(pool); + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +#ifdef OF_HAVE_BLOCKS +- (instancetype)initWithName: (OFNotificationName)name + object: (id)object + block: (OFNotificationCenterBlock)block +{ + self = [super init]; + + @try { + _name = [name copy]; + _object = [object retain]; + _block = [block copy]; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} +#endif + +- (void)dealloc +{ + [_name release]; + [_observer release]; + [_object release]; +#ifdef OF_HAVE_BLOCKS + [_block release]; +#endif + + [super dealloc]; +} + +- (bool)isEqual: (OFNotificationCenterHandle *)handle +{ + if (![handle isKindOfClass: [OFNotificationCenterHandle class]]) + return false; + + if (![handle->_name isEqual: _name]) + return false; + + if (handle->_observer != _observer && + ![handle->_observer isEqual: _observer]) + return false; + + if (handle->_selector != _selector && + !sel_isEqual(handle->_selector, _selector)) + return false; + +#ifdef OF_HAVE_BLOCKS + if (handle->_block != _block) + return false; +#endif + + if (handle->_object != _object && ![handle->_object isEqual: _object]) + return false; + + return true; +} + +- (unsigned long)hash +{ + unsigned long hash; + + OFHashInit(&hash); + + OFHashAddHash(&hash, _name.hash); + OFHashAddHash(&hash, [_observer hash]); + OFHashAddHash(&hash, _selectorHash); +#ifdef OF_HAVE_BLOCKS + if (_block != NULL) + OFHashAddHash(&hash, (unsigned long)(uintptr_t)_block); +#endif + OFHashAddHash(&hash, [_object hash]); + + OFHashFinalize(&hash); + + return hash; +} +@end + +@implementation OFNotificationCenter ++ (void)initialize +{ + if (self != [OFNotificationCenter class]) + return; + + defaultCenter = [[OFDefaultNotificationCenter alloc] init]; +} + ++ (OFNotificationCenter *)defaultCenter +{ + return defaultCenter; +} + +- (instancetype)init +{ + self = [super init]; + + @try { +#ifdef OF_HAVE_THREADS + _mutex = [[OFMutex alloc] init]; +#endif + _handles = [[OFMutableDictionary alloc] init]; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (void)dealloc +{ +#ifdef OF_HAVE_THREADS + [_mutex release]; +#endif + [_handles release]; + + [super dealloc]; +} + +- (void)of_addObserver: (OFNotificationCenterHandle *)handle +{ +#ifdef OF_HAVE_THREADS + [_mutex lock]; + @try { +#endif + OFMutableSet *handlesForName = + [_handles objectForKey: handle->_name]; + + if (handlesForName == nil) { + handlesForName = [OFMutableSet set]; + [_handles setObject: handlesForName + forKey: handle->_name]; + } + + [handlesForName addObject: handle]; +#ifdef OF_HAVE_THREADS + } @finally { + [_mutex unlock]; + } +#endif +} + +- (void)addObserver: (id)observer + selector: (SEL)selector + name: (OFNotificationName)name + object: (id)object +{ + void *pool = objc_autoreleasePoolPush(); + + [self of_addObserver: + [[[OFNotificationCenterHandle alloc] initWithName: name + observer: observer + selector: selector + object: object] + autorelease]]; + + objc_autoreleasePoolPop(pool); +} + +#ifdef OF_HAVE_BLOCKS +- (OFNotificationCenterHandle *) + addObserverForName: (OFNotificationName)name + object: (id)object + usingBlock: (OFNotificationCenterBlock)block +{ + void *pool = objc_autoreleasePoolPush(); + OFNotificationCenterHandle *handle = + [[[OFNotificationCenterHandle alloc] initWithName: name + object: object + block: block] + autorelease]; + + [self of_addObserver: handle]; + + [handle retain]; + + objc_autoreleasePoolPop(pool); + + return [handle autorelease]; +} +#endif + +- (void)removeObserver: (OFNotificationCenterHandle *)handle +{ + void *pool = objc_autoreleasePoolPush(); + + /* {} required to avoid -Wmisleading-indentation false positive. */ + if (![handle isKindOfClass: [OFNotificationCenterHandle class]]) { + @throw [OFInvalidArgumentException exception]; + } + +#ifdef OF_HAVE_THREADS + [_mutex lock]; + @try { +#endif + OFNotificationName name = [[handle->_name copy] autorelease]; + OFMutableSet *handlesForName = [_handles objectForKey: name]; + + [handlesForName removeObject: handle]; + + if (handlesForName.count == 0) + [_handles removeObjectForKey: name]; +#ifdef OF_HAVE_THREADS + } @finally { + [_mutex unlock]; + } +#endif + + objc_autoreleasePoolPop(pool); +} + +- (void)removeObserver: (id)observer + selector: (SEL)selector + name: (OFNotificationName)name + object: (id)object +{ + void *pool = objc_autoreleasePoolPush(); + + [self removeObserver: + [[[OFNotificationCenterHandle alloc] initWithName: name + observer: observer + selector: selector + object: object] + autorelease]]; + + objc_autoreleasePoolPop(pool); +} + +- (void)postNotification: (OFNotification *)notification +{ + void *pool = objc_autoreleasePoolPush(); + OFMutableArray *matchedHandles = [OFMutableArray array]; + +#ifdef OF_HAVE_THREADS + [_mutex lock]; + @try { +#endif + for (OFNotificationCenterHandle *handle in + [_handles objectForKey: notification.name]) + if (handle->_object == nil || + handle->_object == notification.object) + [matchedHandles addObject: handle]; +#ifdef OF_HAVE_THREADS + } @finally { + [_mutex unlock]; + } +#endif + + for (OFNotificationCenterHandle *handle in matchedHandles) { +#ifdef OF_HAVE_BLOCKS + if (handle->_block != NULL) + handle->_block(notification); + else { +#endif + void (*callback)(id, SEL, OFNotification *) = + (void (*)(id, SEL, OFNotification *)) + [handle->_observer methodForSelector: + handle->_selector]; + + callback(handle->_observer, handle->_selector, + notification); +#ifdef OF_HAVE_BLOCKS + } +#endif + } + + objc_autoreleasePoolPop(pool); +} + +- (void)postNotificationName: (OFNotificationName)name + object: (nullable id)object +{ + [self postNotificationName: name object: object userInfo: nil]; +} + +- (void)postNotificationName: (OFNotificationName)name + object: (nullable id)object + userInfo: (nullable OFDictionary *)userInfo +{ + void *pool = objc_autoreleasePoolPush(); + + [self postNotification: + [OFNotification notificationWithName: name + object: object + userInfo: userInfo]]; + + objc_autoreleasePoolPop(pool); +} +@end + +@implementation OFDefaultNotificationCenter +- (instancetype)autorelease +{ + return self; +} + +- (instancetype)retain +{ + return self; +} + +- (void)release +{ +} + +- (unsigned int)retainCount +{ + return OFMaxRetainCount; +} +@end Index: src/OFNull.h ================================================================== --- src/OFNull.h +++ src/OFNull.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFNull.m ================================================================== --- src/OFNull.m +++ src/OFNull.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFNumber.h ================================================================== --- src/OFNumber.h +++ src/OFNumber.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -122,20 +122,18 @@ /** * @brief The OFNumber as a string. */ @property (readonly, nonatomic) OFString *stringValue; -#ifdef OF_HAVE_UNAVAILABLE + (instancetype)valueWithBytes: (const void *)bytes objCType: (const char *)objCType OF_UNAVAILABLE; + (instancetype)valueWithPointer: (const void *)pointer OF_UNAVAILABLE; + (instancetype)valueWithNonretainedObject: (id)object OF_UNAVAILABLE; + (instancetype)valueWithRange: (OFRange)range OF_UNAVAILABLE; + (instancetype)valueWithPoint: (OFPoint)point OF_UNAVAILABLE; + (instancetype)valueWithSize: (OFSize)size OF_UNAVAILABLE; + (instancetype)valueWithRect: (OFRect)rect OF_UNAVAILABLE; -#endif /** * @brief Creates a new OFNumber with the specified `bool`. * * @param value The `bool` value which the OFNumber should contain @@ -238,14 +236,12 @@ * @return A new autoreleased OFNumber */ + (instancetype)numberWithDouble: (double)value; - (instancetype)init OF_UNAVAILABLE; -#ifdef OF_HAVE_UNAVAILABLE - (instancetype)initWithBytes: (const void *)bytes objCType: (const char *)objCType OF_UNAVAILABLE; -#endif /** * @brief Initializes an already allocated OFNumber with the specified `bool`. * * @param value The `bool` value which the OFNumber should contain Index: src/OFNumber.m ================================================================== --- src/OFNumber.m +++ src/OFNumber.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -509,10 +509,46 @@ if (self == [OFNumber class]) return (id)&placeholder; return [super alloc]; } + ++ (instancetype)valueWithBytes: (const void *)bytes + objCType: (const char *)objCType +{ + OF_UNRECOGNIZED_SELECTOR +} + ++ (instancetype)valueWithPointer: (const void *)pointer +{ + OF_UNRECOGNIZED_SELECTOR +} + ++ (instancetype)valueWithNonretainedObject: (id)object +{ + OF_UNRECOGNIZED_SELECTOR +} + ++ (instancetype)valueWithRange: (OFRange)range +{ + OF_UNRECOGNIZED_SELECTOR +} + ++ (instancetype)valueWithPoint: (OFPoint)point +{ + OF_UNRECOGNIZED_SELECTOR +} + ++ (instancetype)valueWithSize: (OFSize)size +{ + OF_UNRECOGNIZED_SELECTOR +} + ++ (instancetype)valueWithRect: (OFRect)rect +{ + OF_UNRECOGNIZED_SELECTOR +} + (instancetype)numberWithBool: (bool)value { return [[[self alloc] initWithBool: value] autorelease]; } @@ -577,10 +613,16 @@ return [[[self alloc] initWithDouble: value] autorelease]; } - (instancetype)init { + OF_INVALID_INIT_METHOD +} + +- (instancetype)initWithBytes: (const void *)bytes + objCType: (const char *)objCType +{ OF_INVALID_INIT_METHOD } - (instancetype)initWithBool: (bool)value { Index: src/OFObject+KeyValueCoding.h ================================================================== --- src/OFObject+KeyValueCoding.h +++ src/OFObject+KeyValueCoding.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFObject+KeyValueCoding.m ================================================================== --- src/OFObject+KeyValueCoding.m +++ src/OFObject+KeyValueCoding.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFObject+Serialization.h ================================================================== --- src/OFObject+Serialization.h +++ src/OFObject+Serialization.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFObject+Serialization.m ================================================================== --- src/OFObject+Serialization.m +++ src/OFObject+Serialization.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFObject.h ================================================================== --- src/OFObject.h +++ src/OFObject.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFObject.m ================================================================== --- src/OFObject.m +++ src/OFObject.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -16,10 +16,11 @@ #include "config.h" #include #include #include +#include "unistd_wrapper.h" #include #ifdef OF_APPLE_RUNTIME # include @@ -46,11 +47,10 @@ #import "OFAllocFailedException.h" #import "OFEnumerationMutationException.h" #import "OFInitializationFailedException.h" #import "OFInvalidArgumentException.h" -#import "OFMemoryNotPartOfObjectException.h" #import "OFNotImplementedException.h" #import "OFOutOfMemoryException.h" #import "OFOutOfRangeException.h" #if defined(OF_APPLE_RUNTIME) && __OBJC2__ @@ -141,12 +141,14 @@ } void * OFResizeMemory(void *pointer, size_t count, size_t size) { - if OF_UNLIKELY (count == 0 || size == 0) + if OF_UNLIKELY (count == 0 || size == 0) { + free(pointer); return NULL; + } if OF_UNLIKELY (count > SIZE_MAX / size) @throw [OFOutOfRangeException exception]; if OF_UNLIKELY ((pointer = realloc(pointer, count * size)) == NULL) Index: src/OFOnce.h ================================================================== --- src/OFOnce.h +++ src/OFOnce.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -35,16 +35,16 @@ #ifdef __cplusplus extern "C" { #endif /** - * @brief A method to call a function only once in a thread-safe manner. + * @brief Executes the specified function exactly once in the application's + * lifetime, even in a multi-threaded environment. * - * @param control The once control. This needs to be set to - * OFOnceControlInitValue at compile time. - * @param func The function to call only once + * @param control An OFOnceControl. This should be a static variable + * preinitialized to `OFOnceControlInitValue`. + * @param function The function to execute once */ -extern void OFOnce(OFOnceControl *_Nonnull control, - OFOnceFunction _Nonnull func); +extern void OFOnce(OFOnceControl *control, void (*function)(void)); #ifdef __cplusplus } #endif Index: src/OFOnce.m ================================================================== --- src/OFOnce.m +++ src/OFOnce.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -26,26 +26,26 @@ #ifdef OF_AMIGAOS # include #endif void -OFOnce(OFOnceControl *control, void (*func)(void)) +OFOnce(OFOnceControl *control, void (*function)(void)) { #if !defined(OF_HAVE_THREADS) if (*control == 0) { - func(); + function(); *control = 1; } #elif defined(OF_HAVE_PTHREADS) - pthread_once(control, func); + pthread_once(control, function); #elif defined(OF_HAVE_ATOMIC_OPS) /* Avoid atomic operations in case it's already done. */ if (*control == 2) return; if (OFAtomicIntCompareAndSwap(control, 0, 1)) { - func(); + function(); OFMemoryBarrier(); OFAtomicIntIncrease(control); } else @@ -73,12 +73,12 @@ } Permit(); if (run) { - func(); + function(); *control = 2; } #else # error No OFOnce available #endif } Index: src/OFOptionsParser.h ================================================================== --- src/OFOptionsParser.h +++ src/OFOptionsParser.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFOptionsParser.m ================================================================== --- src/OFOptionsParser.m +++ src/OFOptionsParser.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFPBKDF2.h ================================================================== --- src/OFPBKDF2.h +++ src/OFPBKDF2.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFPBKDF2.m ================================================================== --- src/OFPBKDF2.m +++ src/OFPBKDF2.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -71,17 +71,19 @@ memcpy(extendedSaltItems + param.saltLength, &i, 4); [param.HMAC reset]; [param.HMAC updateWithBuffer: extendedSaltItems length: param.saltLength + 4]; + [param.HMAC calculate]; memcpy(bufferItems, param.HMAC.digest, digestSize); memcpy(digestItems, param.HMAC.digest, digestSize); for (size_t j = 1; j < param.iterations; j++) { [param.HMAC reset]; [param.HMAC updateWithBuffer: digestItems length: digestSize]; + [param.HMAC calculate]; memcpy(digestItems, param.HMAC.digest, digestSize); for (size_t k = 0; k < digestSize; k++) bufferItems[k] ^= digestItems[k]; Index: src/OFPair.h ================================================================== --- src/OFPair.h +++ src/OFPair.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFPair.m ================================================================== --- src/OFPair.m +++ src/OFPair.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFPlainCondition.h ================================================================== --- src/OFPlainCondition.h +++ src/OFPlainCondition.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFPlainCondition.m ================================================================== --- src/OFPlainCondition.m +++ src/OFPlainCondition.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFPlainMutex.h ================================================================== --- src/OFPlainMutex.h +++ src/OFPlainMutex.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFPlainMutex.m ================================================================== --- src/OFPlainMutex.m +++ src/OFPlainMutex.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFPlainThread.h ================================================================== --- src/OFPlainThread.h +++ src/OFPlainThread.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFPlainThread.m ================================================================== --- src/OFPlainThread.m +++ src/OFPlainThread.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFPlugin.h ================================================================== --- src/OFPlugin.h +++ src/OFPlugin.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -18,58 +18,64 @@ @class OFString; #ifndef OF_WINDOWS # include typedef void *OFPluginHandle; - -typedef enum { - OFDLOpenFlagLazy = RTLD_LAZY, - OFDLOpenFlagNow = RTLD_NOW -} OFDLOpenFlags; #else # include 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. + * @brief A class representing a loaded plugin (shared library). * - * 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. */ +OF_SUBCLASSING_RESTRICTED @interface OFPlugin: OFObject { - OFPluginHandle _pluginHandle; - OF_RESERVE_IVARS(OFPlugin, 4) + OFPluginHandle _handle; } /** - * @brief Loads a plugin from a file. - * - * @param path Path to the plugin file. The suffix is appended automatically. - * @return The loaded plugin - */ -+ (OF_KINDOF(OFPlugin *))pluginWithPath: (OFString *)path; -@end - -#ifdef __cplusplus -extern "C" { -#endif -extern OFPluginHandle OFDLOpen(OFString *path, OFDLOpenFlags flags); -extern void *OFDLSym(OFPluginHandle handle, const char *symbol); -extern OFString *_Nullable OFDLError(void); -extern void OFDLClose(OFPluginHandle handle); -#ifdef __cplusplus -} -#endif + * @brief Returns the plugin path for a plugin with the specified name. + * + * E.g. on ELF systems, it appends .so, while on macOS and iOS, it creates the + * appropriate plugin path. This can also be prefixed by a directory. + * + * @param name The name to return the plugin path for + * @return The plugin path + */ ++ (OFString *)pathForName: (OFString *)name; + +/** + * @brief Creates a new OFPlugin by loading the plugin with the specified path. + * + * @param path The path to the plugin file. The suffix is appended + * automatically. + * @return An new, autoreleased OFPlugin + */ ++ (instancetype)pluginWithPath: (OFString *)path; + +/** + * @brief Initializes an already allocated OFPlugin by loading the plugin with + * the specified path. + * + * @param path The path to the plugin file. The suffix is appended + * automatically. + * @return An initialized OFPlugin + */ +- (instancetype)initWithPath: (OFString *)path; + +/** + * @brief Returns the address for the specified symbol, or `nil` if not found. + * + * @param symbol The symbol to return the address for + * @return The address for the speccified symbol, or `nil` if not found + */ +- (nullable void *)addressForSymbol: (OFString *)symbol; +@end OF_ASSUME_NONNULL_END Index: src/OFPlugin.m ================================================================== --- src/OFPlugin.m +++ src/OFPlugin.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -28,116 +28,90 @@ #import "OFSystemInfo.h" #import "OFInitializationFailedException.h" #import "OFLoadPluginFailedException.h" -typedef OFPlugin *(*PluginInit)(void); - -OFPluginHandle -OFDLOpen(OFString *path, OFDLOpenFlags flags) -{ -#ifndef OF_WINDOWS - return dlopen([path cStringWithEncoding: [OFLocale encoding]], flags); -#else - if (path == nil) - return GetModuleHandle(NULL); - - if ([OFSystemInfo isWindowsNT]) - return LoadLibraryW(path.UTF16String); - else - return LoadLibraryA( - [path cStringWithEncoding: [OFLocale encoding]]); -#endif -} - -void * -OFDLSym(OFPluginHandle handle, const char *symbol) -{ -#ifndef OF_WINDOWS - return dlsym(handle, symbol); -#else - return (void *)(uintptr_t)GetProcAddress(handle, symbol); -#endif -} - -void -OFDLClose(OFPluginHandle handle) -{ -#ifndef OF_WINDOWS - dlclose(handle); -#else - FreeLibrary(handle); -#endif -} - -OFString * -OFDLError(void) -{ -#ifndef OF_WINDOWS - return [OFString stringWithCString: dlerror() - encoding: [OFLocale encoding]]; -#else - return nil; -#endif -} - -@implementation OFPlugin -+ (id)pluginWithPath: (OFString *)path -{ - void *pool = objc_autoreleasePoolPush(); - OFPluginHandle handle; - PluginInit initPlugin; - OFPlugin *plugin; - -#if defined(OF_MACOS) - path = [path stringByAppendingFormat: @".bundle/Contents/MacOS/%@", - path.lastPathComponent]; -#elif defined(OF_IOS) - path = [path stringByAppendingFormat: @".bundle/%@", - path.lastPathComponent]; -#else - path = [path stringByAppendingString: @PLUGIN_SUFFIX]; -#endif - - if ((handle = OFDLOpen(path, OFDLOpenFlagLazy)) == NULL) - @throw [OFLoadPluginFailedException - exceptionWithPath: path - error: OFDLError()]; - - objc_autoreleasePoolPop(pool); - - initPlugin = (PluginInit)(uintptr_t)OFDLSym(handle, "OFPluginInit"); - if (initPlugin == (PluginInit)0 || (plugin = initPlugin()) == nil) { - OFDLClose(handle); - @throw [OFInitializationFailedException - exceptionWithClass: self]; - } - - plugin->_pluginHandle = handle; - return plugin; -} - -- (instancetype)init -{ - if ([self isMemberOfClass: [OFPlugin class]]) { - @try { - [self doesNotRecognizeSelector: _cmd]; - } @catch (id e) { - [self release]; - @throw e; - } - - abort(); - } - - return [super init]; +#ifndef RTLD_LAZY +# define RTLD_LAZY 0 +#endif + +@implementation OFPlugin ++ (instancetype)pluginWithPath: (OFString *)path +{ + return [[[self alloc] initWithPath: path] autorelease]; +} + ++ (OFString *)pathForName: (OFString *)name +{ +#if defined(OF_MACOS) + return [name stringByAppendingFormat: @".bundle/Contents/MacOS/%@", + name.lastPathComponent]; +#elif defined(OF_IOS) + return [name stringByAppendingFormat: @".bundle/%@", + name.lastPathComponent]; +#else + return [name stringByAppendingString: @PLUGIN_SUFFIX]; +#endif +} + +- (instancetype)initWithPath: (OFString *)path +{ + self = [super init]; + + @try { + void *pool = objc_autoreleasePoolPush(); + +#ifndef OF_WINDOWS + _handle = dlopen( + [path cStringWithEncoding: [OFLocale encoding]], RTLD_LAZY); +#else + if ([OFSystemInfo isWindowsNT]) + _handle = LoadLibraryW(path.UTF16String); + else + _handle = LoadLibraryA( + [path cStringWithEncoding: [OFLocale encoding]]); +#endif + + if (_handle == NULL) { +#ifndef OF_WINDOWS + OFString *error = [OFString + stringWithCString: dlerror() + encoding: [OFLocale encoding]]; +#else + OFString *error = nil; +#endif + @throw [OFLoadPluginFailedException + exceptionWithPath: path + error: error]; + } + + objc_autoreleasePoolPop(pool); + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (void *)addressForSymbol: (OFString *)symbol +{ +#ifndef OF_WINDOWS + return dlsym(_handle, + [symbol cStringWithEncoding: [OFLocale encoding]]); +#else + return (void *)(uintptr_t)GetProcAddress(_handle, + [symbol cStringWithEncoding: [OFLocale encoding]]); +#endif } - (void)dealloc { - OFPluginHandle h = _pluginHandle; +#ifndef OF_WINDOWS + dlclose(_handle); +#else + FreeLibrary(_handle); +#endif [super dealloc]; - - OFDLClose(h); } @end Index: src/OFPointValue.h ================================================================== --- src/OFPointValue.h +++ src/OFPointValue.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFPointValue.m ================================================================== --- src/OFPointValue.m +++ src/OFPointValue.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFPointerValue.h ================================================================== --- src/OFPointerValue.h +++ src/OFPointerValue.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFPointerValue.m ================================================================== --- src/OFPointerValue.m +++ src/OFPointerValue.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFPollKernelEventObserver.h ================================================================== --- src/OFPollKernelEventObserver.h +++ src/OFPollKernelEventObserver.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFPollKernelEventObserver.m ================================================================== --- src/OFPollKernelEventObserver.m +++ src/OFPollKernelEventObserver.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFRIPEMD160Hash.h ================================================================== --- src/OFRIPEMD160Hash.h +++ src/OFRIPEMD160Hash.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFRIPEMD160Hash.m ================================================================== --- src/OFRIPEMD160Hash.m +++ src/OFRIPEMD160Hash.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -19,10 +19,11 @@ #import "OFRIPEMD160Hash.h" #import "OFSecureData.h" #import "OFHashAlreadyCalculatedException.h" +#import "OFHashNotCalculatedException.h" #import "OFOutOfRangeException.h" static const size_t digestSize = 20; static const size_t blockSize = 64; @@ -256,12 +257,21 @@ } } - (const unsigned char *)digest { + if (!_calculated) + @throw [OFHashNotCalculatedException exceptionWithObject: self]; + + return (const unsigned char *)_iVars->state; +} + +- (void)calculate +{ if (_calculated) - return (const unsigned char *)_iVars->state; + @throw [OFHashAlreadyCalculatedException + exceptionWithObject: self]; _iVars->buffer.bytes[_iVars->bufferLength] = 0x80; OFZeroMemory(_iVars->buffer.bytes + _iVars->bufferLength + 1, 64 - _iVars->bufferLength - 1); @@ -277,12 +287,10 @@ processBlock(_iVars->state, _iVars->buffer.words); OFZeroMemory(&_iVars->buffer, sizeof(_iVars->buffer)); byteSwapVectorIfBE(_iVars->state, 5); _calculated = true; - - return (const unsigned char *)_iVars->state; } - (void)reset { [self of_resetState]; Index: src/OFRangeCharacterSet.h ================================================================== --- src/OFRangeCharacterSet.h +++ src/OFRangeCharacterSet.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFRangeCharacterSet.m ================================================================== --- src/OFRangeCharacterSet.m +++ src/OFRangeCharacterSet.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFRangeValue.h ================================================================== --- src/OFRangeValue.h +++ src/OFRangeValue.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFRangeValue.m ================================================================== --- src/OFRangeValue.m +++ src/OFRangeValue.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFRectValue.h ================================================================== --- src/OFRectValue.h +++ src/OFRectValue.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFRectValue.m ================================================================== --- src/OFRectValue.m +++ src/OFRectValue.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFRecursiveMutex.h ================================================================== --- src/OFRecursiveMutex.h +++ src/OFRecursiveMutex.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFRecursiveMutex.m ================================================================== --- src/OFRecursiveMutex.m +++ src/OFRecursiveMutex.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFRunLoop+Private.h ================================================================== --- src/OFRunLoop+Private.h +++ src/OFRunLoop+Private.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFRunLoop.h ================================================================== --- src/OFRunLoop.h +++ src/OFRunLoop.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFRunLoop.m ================================================================== --- src/OFRunLoop.m +++ src/OFRunLoop.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -40,10 +40,11 @@ #import "OFTimer.h" #import "OFTimer+Private.h" #import "OFDate.h" #import "OFObserveFailedException.h" +#import "OFWriteFailedException.h" #include "OFRunLoopConstants.inc" static OFRunLoop *mainRunLoop = nil; @@ -567,26 +568,31 @@ size_t dataLength = _data.count * _data.itemSize; OFData *newData, *oldData; @try { const char *dataItems = _data.items; + length = dataLength - _writtenLength; + [object writeBuffer: dataItems + _writtenLength length: length]; + } @catch (OFWriteFailedException *e) { + length = e.bytesWritten; - length = [object writeBuffer: dataItems + _writtenLength - length: dataLength - _writtenLength]; + if (e.errNo != EWOULDBLOCK && e.errNo != EAGAIN) + exception = e; } @catch (id e) { length = 0; exception = e; } _writtenLength += length; + OFEnsure(_writtenLength <= dataLength); if (_writtenLength != dataLength && exception == nil) return true; # ifdef OF_HAVE_BLOCKS if (_block != NULL) { - newData = _block(_data, _writtenLength, exception); + newData = _block(_writtenLength, exception); if (newData == nil) return false; oldData = _data; @@ -639,26 +645,31 @@ size_t cStringLength = [_string cStringLengthWithEncoding: _encoding]; OFString *newString, *oldString; @try { const char *cString = [_string cStringWithEncoding: _encoding]; + length = cStringLength - _writtenLength; + [object writeBuffer: cString + _writtenLength length: length]; + } @catch (OFWriteFailedException *e) { + length = e.bytesWritten; - length = [object writeBuffer: cString + _writtenLength - length: cStringLength - _writtenLength]; + if (e.errNo != EWOULDBLOCK && e.errNo != EAGAIN) + exception = e; } @catch (id e) { length = 0; exception = e; } _writtenLength += length; + OFEnsure(_writtenLength <= cStringLength); if (_writtenLength != cStringLength && exception == nil) return true; # ifdef OF_HAVE_BLOCKS if (_block != NULL) { - newString = _block(_string, _writtenLength, exception); + newString = _block(_writtenLength, exception); if (newString == nil) return false; oldString = _string; @@ -848,11 +859,11 @@ exception = e; } # ifdef OF_HAVE_BLOCKS if (_block != NULL) { - newData = _block(_data, &_receiver, exception); + newData = _block(exception); if (newData == nil) return false; oldData = _data; @@ -949,11 +960,11 @@ exception = e; } # ifdef OF_HAVE_BLOCKS if (_block != NULL) { - newData = _block(_data, exception); + newData = _block(exception); if (newData == nil) return false; oldData = _data; @@ -1414,17 +1425,14 @@ - (void)of_removeTimer: (OFTimer *)timer forMode: (OFRunLoopMode)mode { OFRunLoopState *state = stateForMode(self, mode, false); - if (state == nil) + /* {} required to avoid -Wmisleading-indentation false positive. */ + 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 @@ -1438,12 +1446,10 @@ #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 { Index: src/OFRunLoopConstants.inc ================================================================== --- src/OFRunLoopConstants.inc +++ src/OFRunLoopConstants.inc @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFSHA1Hash.h ================================================================== --- src/OFSHA1Hash.h +++ src/OFSHA1Hash.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFSHA1Hash.m ================================================================== --- src/OFSHA1Hash.m +++ src/OFSHA1Hash.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -19,10 +19,11 @@ #import "OFSHA1Hash.h" #import "OFSecureData.h" #import "OFHashAlreadyCalculatedException.h" +#import "OFHashNotCalculatedException.h" #import "OFOutOfRangeException.h" static const size_t digestSize = 20; static const size_t blockSize = 64; @@ -216,12 +217,21 @@ } } - (const unsigned char *)digest { + if (!_calculated) + @throw [OFHashNotCalculatedException exceptionWithObject: self]; + + return (const unsigned char *)_iVars->state; +} + +- (void)calculate +{ if (_calculated) - return (const unsigned char *)_iVars->state; + @throw [OFHashAlreadyCalculatedException + exceptionWithObject: self]; _iVars->buffer.bytes[_iVars->bufferLength] = 0x80; OFZeroMemory(_iVars->buffer.bytes + _iVars->bufferLength + 1, 64 - _iVars->bufferLength - 1); @@ -237,12 +247,10 @@ processBlock(_iVars->state, _iVars->buffer.words); OFZeroMemory(&_iVars->buffer, sizeof(_iVars->buffer)); byteSwapVectorIfLE(_iVars->state, 5); _calculated = true; - - return (const unsigned char *)_iVars->state; } - (void)reset { [self of_resetState]; Index: src/OFSHA224Hash.h ================================================================== --- src/OFSHA224Hash.h +++ src/OFSHA224Hash.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFSHA224Hash.m ================================================================== --- src/OFSHA224Hash.m +++ src/OFSHA224Hash.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFSHA224Or256Hash.h ================================================================== --- src/OFSHA224Or256Hash.h +++ src/OFSHA224Or256Hash.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFSHA224Or256Hash.m ================================================================== --- src/OFSHA224Or256Hash.m +++ src/OFSHA224Or256Hash.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -20,10 +20,11 @@ #import "OFSHA224Or256Hash.h" #import "OFSecureData.h" #import "OFHashAlreadyCalculatedException.h" +#import "OFHashNotCalculatedException.h" #import "OFOutOfRangeException.h" static const size_t blockSize = 64; @interface OFSHA224Or256Hash () @@ -232,12 +233,21 @@ } } - (const unsigned char *)digest { + if (!_calculated) + @throw [OFHashNotCalculatedException exceptionWithObject: self]; + + return (const unsigned char *)_iVars->state; +} + +- (void)calculate +{ if (_calculated) - return (const unsigned char *)_iVars->state; + @throw [OFHashAlreadyCalculatedException + exceptionWithObject: self]; _iVars->buffer.bytes[_iVars->bufferLength] = 0x80; OFZeroMemory(_iVars->buffer.bytes + _iVars->bufferLength + 1, 64 - _iVars->bufferLength - 1); @@ -253,12 +263,10 @@ processBlock(_iVars->state, _iVars->buffer.words); OFZeroMemory(&_iVars->buffer, sizeof(_iVars->buffer)); byteSwapVectorIfLE(_iVars->state, 8); _calculated = true; - - return (const unsigned char *)_iVars->state; } - (void)reset { [self of_resetState]; Index: src/OFSHA256Hash.h ================================================================== --- src/OFSHA256Hash.h +++ src/OFSHA256Hash.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFSHA256Hash.m ================================================================== --- src/OFSHA256Hash.m +++ src/OFSHA256Hash.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFSHA384Hash.h ================================================================== --- src/OFSHA384Hash.h +++ src/OFSHA384Hash.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFSHA384Hash.m ================================================================== --- src/OFSHA384Hash.m +++ src/OFSHA384Hash.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFSHA384Or512Hash.h ================================================================== --- src/OFSHA384Or512Hash.h +++ src/OFSHA384Or512Hash.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFSHA384Or512Hash.m ================================================================== --- src/OFSHA384Or512Hash.m +++ src/OFSHA384Or512Hash.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -20,10 +20,11 @@ #import "OFSHA384Or512Hash.h" #import "OFSecureData.h" #import "OFHashAlreadyCalculatedException.h" +#import "OFHashNotCalculatedException.h" #import "OFOutOfRangeException.h" static const size_t blockSize = 128; @interface OFSHA384Or512Hash () @@ -245,12 +246,21 @@ } } - (const unsigned char *)digest { + if (!_calculated) + @throw [OFHashNotCalculatedException exceptionWithObject: self]; + + return (const unsigned char *)_iVars->state; +} + +- (void)calculate +{ if (_calculated) - return (const unsigned char *)_iVars->state; + @throw [OFHashAlreadyCalculatedException + exceptionWithObject: self]; _iVars->buffer.bytes[_iVars->bufferLength] = 0x80; OFZeroMemory(_iVars->buffer.bytes + _iVars->bufferLength + 1, 128 - _iVars->bufferLength - 1); @@ -264,12 +274,10 @@ processBlock(_iVars->state, _iVars->buffer.words); OFZeroMemory(&_iVars->buffer, sizeof(_iVars->buffer)); byteSwapVectorIfLE(_iVars->state, 8); _calculated = true; - - return (const unsigned char *)_iVars->state; } - (void)reset { [self of_resetState]; Index: src/OFSHA512Hash.h ================================================================== --- src/OFSHA512Hash.h +++ src/OFSHA512Hash.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFSHA512Hash.m ================================================================== --- src/OFSHA512Hash.m +++ src/OFSHA512Hash.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFSPXSocket.h ================================================================== --- src/OFSPXSocket.h +++ src/OFSPXSocket.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -42,21 +42,21 @@ @optional /** * @brief A method which is called when a socket connected. * * @param socket The socket which connected - * @param node The node the socket connected to * @param network The network of the node the socket connected to + * @param node The node the socket connected to * @param port The port of the node to which the socket connected * @param exception An exception that occurred while connecting, or nil on * success */ -- (void)socket: (OFSPXSocket *)socket - didConnectToNode: (unsigned char [_Nonnull IPX_NODE_LEN])node - network: (uint32_t)network - port: (uint16_t)port - exception: (nullable id)exception; +- (void)socket: (OFSPXSocket *)socket + didConnectToNetwork: (uint32_t)network + node: (unsigned char [_Nonnull IPX_NODE_LEN])node + port: (uint16_t)port + exception: (nullable id)exception; @end /** * @class OFSPXSocket OFSPXSocket.h ObjFW/OFSPXSocket.h * @@ -83,44 +83,44 @@ id delegate; /** * @brief Connect the OFSPXSocket to the specified destination. * - * @param node The node to connect to - * @param network The network on which the node to connect to is - * @param port The port (sometimes also called socket number) on the node to - * connect to - */ -- (void)connectToNode: (unsigned char [_Nonnull IPX_NODE_LEN])node - network: (uint32_t)network - port: (uint16_t)port; - -/** - * @brief Asynchronously connect the OFSPXSocket to the specified destination. - * - * @param node The node to connect to - * @param network The network on which the node to connect to is - * @param port The port (sometimes also called socket number) on the node to - * connect to - */ -- (void)asyncConnectToNode: (unsigned char [_Nonnull IPX_NODE_LEN])node - network: (uint32_t)network - port: (uint16_t)port; - -/** - * @brief Asynchronously connect the OFSPXSocket to the specified destination. - * - * @param node The node to connect to - * @param network The network on which the node to connect to is - * @param port The port (sometimes also called socket number) on the node to - * connect to - * @param runLoopMode The run loop mode in which to perform the async connect - */ -- (void)asyncConnectToNode: (unsigned char [_Nonnull IPX_NODE_LEN])node - network: (uint32_t)network - port: (uint16_t)port - runLoopMode: (OFRunLoopMode)runLoopMode; + * @param network The network on which the node to connect to is + * @param node The node to connect to + * @param port The port (sometimes also called socket number) on the node to + * connect to + */ +- (void)connectToNetwork: (uint32_t)network + node: (unsigned char [_Nonnull IPX_NODE_LEN])node + port: (uint16_t)port; + +/** + * @brief Asynchronously connect the OFSPXSocket to the specified destination. + * + * @param network The network on which the node to connect to is + * @param node The node to connect to + * @param port The port (sometimes also called socket number) on the node to + * connect to + */ +- (void)asyncConnectToNetwork: (uint32_t)network + node: (unsigned char [_Nonnull IPX_NODE_LEN])node + port: (uint16_t)port; + +/** + * @brief Asynchronously connect the OFSPXSocket to the specified destination. + * + * @param network The network on which the node to connect to is + * @param node The node to connect to + * @param port The port (sometimes also called socket number) on the node to + * connect to + * @param runLoopMode The run loop mode in which to perform the async connect + */ +- (void)asyncConnectToNetwork: (uint32_t)network + node: (unsigned char [_Nonnull IPX_NODE_LEN])node + port: (uint16_t)port + runLoopMode: (OFRunLoopMode)runLoopMode; #ifdef OF_HAVE_BLOCKS /** * @brief Asynchronously connect the OFSPXSocket to the specified destination. * @@ -128,14 +128,14 @@ * @param network The network on which the node to connect to is * @param port The port (sometimes also called socket number) on the node to * connect to * @param block The block to execute once the connection has been established */ -- (void)asyncConnectToNode: (unsigned char [_Nonnull IPX_NODE_LEN])node - network: (uint32_t)network - port: (uint16_t)port - block: (OFSPXSocketAsyncConnectBlock)block; +- (void)asyncConnectToNetwork: (uint32_t)network + node: (unsigned char [_Nonnull IPX_NODE_LEN])node + port: (uint16_t)port + block: (OFSPXSocketAsyncConnectBlock)block; /** * @brief Asynchronously connect the OFSPXSocket to the specified destination. * * @param node The node to connect to @@ -143,15 +143,15 @@ * @param port The port (sometimes also called socket number) on the node to * connect to * @param runLoopMode The run loop mode in which to perform the async connect * @param block The block to execute once the connection has been established */ -- (void)asyncConnectToNode: (unsigned char [_Nonnull IPX_NODE_LEN])node - network: (uint32_t)network - port: (uint16_t)port - runLoopMode: (OFRunLoopMode)runLoopMode - block: (OFSPXSocketAsyncConnectBlock)block; +- (void)asyncConnectToNetwork: (uint32_t)network + node: (unsigned char [_Nonnull IPX_NODE_LEN])node + port: (uint16_t)port + runLoopMode: (OFRunLoopMode)runLoopMode + block: (OFSPXSocketAsyncConnectBlock)block; #endif /** * @brief Bind the socket to the specified network, node and port. * Index: src/OFSPXSocket.m ================================================================== --- src/OFSPXSocket.m +++ src/OFSPXSocket.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -44,21 +44,21 @@ OF_DIRECT_MEMBERS @interface OFSPXSocketAsyncConnectDelegate: OFObject { OFSPXSocket *_socket; - unsigned char _node[IPX_NODE_LEN]; uint32_t _network; + unsigned char _node[IPX_NODE_LEN]; uint16_t _port; #ifdef OF_HAVE_BLOCKS OFSPXSocketAsyncConnectBlock _block; #endif } - (instancetype)initWithSocket: (OFSPXSocket *)socket - node: (unsigned char [IPX_NODE_LEN])node network: (uint32_t)network + node: (unsigned char [IPX_NODE_LEN])node port: (uint16_t)port #ifdef OF_HAVE_BLOCKS block: (OFSPXSocketAsyncConnectBlock)block #endif ; @@ -65,23 +65,23 @@ - (void)startWithRunLoopMode: (OFRunLoopMode)runLoopMode; @end @implementation OFSPXSocketAsyncConnectDelegate - (instancetype)initWithSocket: (OFSPXSocket *)sock - node: (unsigned char [IPX_NODE_LEN])node network: (uint32_t)network + node: (unsigned char [IPX_NODE_LEN])node port: (uint16_t)port #ifdef OF_HAVE_BLOCKS block: (OFSPXSocketAsyncConnectBlock)block #endif { self = [super init]; @try { _socket = [sock retain]; - memcpy(_node, node, IPX_NODE_LEN); _network = network; + memcpy(_node, node, IPX_NODE_LEN); _port = port; #ifdef OF_HAVE_BLOCKS _block = [block copy]; #endif } @catch (id e) { @@ -103,11 +103,11 @@ } - (void)startWithRunLoopMode: (OFRunLoopMode)runLoopMode { OFSocketAddress address = - OFSocketAddressMakeIPX(_node, _network, _port); + OFSocketAddressMakeIPX(_network, _node, _port); id exception = nil; int errNo; if (![_socket of_createSocketForAddress: &address errNo: &errNo]) { exception = [self of_connectionFailedExceptionForErrNo: errNo]; @@ -151,28 +151,28 @@ if (_block != NULL) _block(exception); else { #endif if ([delegate respondsToSelector: - @selector(socket:didConnectToNode:network:port:exception:)]) - [delegate socket: _socket - didConnectToNode: _node - network: _network - port: _port - exception: exception]; + @selector(socket:didConnectToNetwork:node:port:exception:)]) + [delegate socket: _socket + didConnectToNetwork: _network + node: _node + port: _port + exception: exception]; #ifdef OF_HAVE_BLOCKS } #endif } - (id)of_connectionFailedExceptionForErrNo: (int)errNo { - return [OFConnectionFailedException exceptionWithNode: _node - network: _network - port: _port - socket: _socket - errNo: errNo]; + return [OFConnectionFailedException exceptionWithNetwork: _network + node: _node + port: _port + socket: _socket + errNo: errNo]; } @end @implementation OFSPXSocket @dynamic delegate; @@ -206,11 +206,11 @@ errNo: (int *)errNo { if (_socket == OFInvalidSocketHandle) @throw [OFNotOpenException exceptionWithObject: self]; - if (connect(_socket, &address->sockaddr.sockaddr, + if (connect(_socket, (struct sockaddr *)&address->sockaddr, address->length) != 0) { *errNo = OFSocketErrNo(); return false; } @@ -221,58 +221,58 @@ { closesocket(_socket); _socket = OFInvalidSocketHandle; } -- (void)connectToNode: (unsigned char [_Nonnull IPX_NODE_LEN])node - network: (uint32_t)network - port: (uint16_t)port +- (void)connectToNetwork: (uint32_t)network + node: (unsigned char [_Nonnull IPX_NODE_LEN])node + port: (uint16_t)port { - OFSocketAddress address = OFSocketAddressMakeIPX(node, network, port); + OFSocketAddress address = OFSocketAddressMakeIPX(network, node, port); int errNo; if (![self of_createSocketForAddress: &address errNo: &errNo]) @throw [OFConnectionFailedException - exceptionWithNode: node - network: network - port: port - socket: self - errNo: errNo]; + exceptionWithNetwork: network + node: node + port: port + socket: self + errNo: errNo]; if (![self of_connectSocketToAddress: &address errNo: &errNo]) { [self of_closeSocket]; @throw [OFConnectionFailedException - exceptionWithNode: node - network: network - port: port - socket: self - errNo: errNo]; - } -} - -- (void)asyncConnectToNode: (unsigned char [_Nonnull IPX_NODE_LEN])node - network: (uint32_t)network - port: (uint16_t)port -{ - [self asyncConnectToNode: node - network: network - port: port - runLoopMode: OFDefaultRunLoopMode]; -} - -- (void)asyncConnectToNode: (unsigned char [_Nonnull IPX_NODE_LEN])node - network: (uint32_t)network - port: (uint16_t)port - runLoopMode: (OFRunLoopMode)runLoopMode + exceptionWithNetwork: network + node: node + port: port + socket: self + errNo: errNo]; + } +} + +- (void)asyncConnectToNetwork: (uint32_t)network + node: (unsigned char [_Nonnull IPX_NODE_LEN])node + port: (uint16_t)port +{ + [self asyncConnectToNetwork: network + node: node + port: port + runLoopMode: OFDefaultRunLoopMode]; +} + +- (void)asyncConnectToNetwork: (uint32_t)network + node: (unsigned char [_Nonnull IPX_NODE_LEN])node + port: (uint16_t)port + runLoopMode: (OFRunLoopMode)runLoopMode { void *pool = objc_autoreleasePoolPush(); [[[[OFSPXSocketAsyncConnectDelegate alloc] initWithSocket: self - node: node network: network + node: node port: port #ifdef OF_HAVE_BLOCKS block: NULL #endif ] autorelease] startWithRunLoopMode: runLoopMode]; @@ -279,34 +279,34 @@ objc_autoreleasePoolPop(pool); } #ifdef OF_HAVE_BLOCKS -- (void)asyncConnectToNode: (unsigned char [_Nonnull IPX_NODE_LEN])node - network: (uint32_t)network - port: (uint16_t)port - block: (OFSPXSocketAsyncConnectBlock)block -{ - [self asyncConnectToNode: node - network: network - port: port - runLoopMode: OFDefaultRunLoopMode - block: block]; -} - -- (void)asyncConnectToNode: (unsigned char [_Nonnull IPX_NODE_LEN])node - network: (uint32_t)network - port: (uint16_t)port - runLoopMode: (OFRunLoopMode)runLoopMode - block: (OFSPXSocketAsyncConnectBlock)block +- (void)asyncConnectToNetwork: (uint32_t)network + node: (unsigned char [_Nonnull IPX_NODE_LEN])node + port: (uint16_t)port + block: (OFSPXSocketAsyncConnectBlock)block +{ + [self asyncConnectToNetwork: network + node: node + port: port + runLoopMode: OFDefaultRunLoopMode + block: block]; +} + +- (void)asyncConnectToNetwork: (uint32_t)network + node: (unsigned char [_Nonnull IPX_NODE_LEN])node + port: (uint16_t)port + runLoopMode: (OFRunLoopMode)runLoopMode + block: (OFSPXSocketAsyncConnectBlock)block { void *pool = objc_autoreleasePoolPush(); [[[[OFSPXSocketAsyncConnectDelegate alloc] initWithSocket: self - node: node network: network + node: node port: port block: block ] autorelease] startWithRunLoopMode: runLoopMode]; objc_autoreleasePoolPop(pool); @@ -322,13 +322,13 @@ #endif if (_socket != OFInvalidSocketHandle) @throw [OFAlreadyConnectedException exceptionWithSocket: self]; - address = OFSocketAddressMakeIPX(zeroNode, 0, port); + address = OFSocketAddressMakeIPX(0, zeroNode, port); - if ((_socket = socket(address.sockaddr.sockaddr.sa_family, + if ((_socket = socket(address.sockaddr.ipx.sipx_family, SOCK_SEQPACKET | SOCK_CLOEXEC, NSPROTO_SPX)) == OFInvalidSocketHandle) @throw [OFBindFailedException exceptionWithPort: port packetType: SPXPacketType @@ -340,11 +340,12 @@ #if SOCK_CLOEXEC == 0 && defined(HAVE_FCNTL_H) && defined(FD_CLOEXEC) if ((flags = fcntl(_socket, F_GETFD, 0)) != -1) fcntl(_socket, F_SETFD, flags | FD_CLOEXEC); #endif - if (bind(_socket, &address.sockaddr.sockaddr, address.length) != 0) { + if (bind(_socket, (struct sockaddr *)&address.sockaddr, + address.length) != 0) { int errNo = OFSocketErrNo(); closesocket(_socket); _socket = OFInvalidSocketHandle; @@ -356,11 +357,11 @@ memset(&address, 0, sizeof(address)); address.family = OFSocketAddressFamilyIPX; address.length = (socklen_t)sizeof(address.sockaddr); - if (OFGetSockName(_socket, &address.sockaddr.sockaddr, + if (OFGetSockName(_socket, (struct sockaddr *)&address.sockaddr, &address.length) != 0) { int errNo = OFSocketErrNo(); closesocket(_socket); _socket = OFInvalidSocketHandle; @@ -369,11 +370,11 @@ packetType: SPXPacketType socket: self errNo: errNo]; } - if (address.sockaddr.sockaddr.sa_family != AF_IPX) { + if (address.sockaddr.ipx.sipx_family != AF_IPX) { closesocket(_socket); _socket = OFInvalidSocketHandle; @throw [OFBindFailedException exceptionWithPort: port packetType: SPXPacketType Index: src/OFSPXStreamSocket.h ================================================================== --- src/OFSPXStreamSocket.h +++ src/OFSPXStreamSocket.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -43,21 +43,21 @@ @optional /** * @brief A method which is called when a socket connected. * * @param socket The socket which connected - * @param node The node the socket connected to * @param network The network of the node the socket connected to + * @param node The node the socket connected to * @param port The port of the node to which the socket connected * @param exception An exception that occurred while connecting, or nil on * success */ -- (void)socket: (OFSPXStreamSocket *)socket - didConnectToNode: (unsigned char [_Nonnull IPX_NODE_LEN])node - network: (uint32_t)network - port: (uint16_t)port - exception: (nullable id)exception; +- (void)socket: (OFSPXStreamSocket *)socket + didConnectToNetwork: (uint32_t)network + node: (unsigned char [_Nonnull IPX_NODE_LEN])node + port: (uint16_t)port + exception: (nullable id)exception; @end /** * @class OFSPXStreamSocket OFSPXStreamSocket.h ObjFW/OFSPXStreamSocket.h * @@ -84,79 +84,79 @@ id delegate; /** * @brief Connect the OFSPXStreamSocket to the specified destination. * - * @param node The node to connect to - * @param network The network on which the node to connect to is - * @param port The port (sometimes also called socket number) on the node to - * connect to - */ -- (void)connectToNode: (unsigned char [_Nonnull IPX_NODE_LEN])node - network: (uint32_t)network - port: (uint16_t)port; - -/** - * @brief Asynchronously connect the OFSPXStreamSocket to the specified - * destination. - * - * @param node The node to connect to - * @param network The network on which the node to connect to is - * @param port The port (sometimes also called socket number) on the node to - * connect to - */ -- (void)asyncConnectToNode: (unsigned char [_Nonnull IPX_NODE_LEN])node - network: (uint32_t)network - port: (uint16_t)port; - -/** - * @brief Asynchronously connect the OFSPXStreamSocket to the specified - * destination. - * - * @param node The node to connect to - * @param network The network on which the node to connect to is - * @param port The port (sometimes also called socket number) on the node to - * connect to - * @param runLoopMode The run loop mode in which to perform the async connect - */ -- (void)asyncConnectToNode: (unsigned char [_Nonnull IPX_NODE_LEN])node - network: (uint32_t)network - port: (uint16_t)port - runLoopMode: (OFRunLoopMode)runLoopMode; + * @param network The network on which the node to connect to is + * @param node The node to connect to + * @param port The port (sometimes also called socket number) on the node to + * connect to + */ +- (void)connectToNetwork: (uint32_t)network + node: (unsigned char [_Nonnull IPX_NODE_LEN])node + port: (uint16_t)port; + +/** + * @brief Asynchronously connect the OFSPXStreamSocket to the specified + * destination. + * + * @param network The network on which the node to connect to is + * @param node The node to connect to + * @param port The port (sometimes also called socket number) on the node to + * connect to + */ +- (void)asyncConnectToNetwork: (uint32_t)network + node: (unsigned char [_Nonnull IPX_NODE_LEN])node + port: (uint16_t)port; + +/** + * @brief Asynchronously connect the OFSPXStreamSocket to the specified + * destination. + * + * @param network The network on which the node to connect to is + * @param node The node to connect to + * @param port The port (sometimes also called socket number) on the node to + * connect to + * @param runLoopMode The run loop mode in which to perform the async connect + */ +- (void)asyncConnectToNetwork: (uint32_t)network + node: (unsigned char [_Nonnull IPX_NODE_LEN])node + port: (uint16_t)port + runLoopMode: (OFRunLoopMode)runLoopMode; #ifdef OF_HAVE_BLOCKS /** * @brief Asynchronously connect the OFSPXStreamSocket to the specified * destination. * - * @param node The node to connect to * @param network The network on which the node to connect to is + * @param node The node to connect to * @param port The port (sometimes also called socket number) on the node to * connect to * @param block The block to execute once the connection has been established */ -- (void)asyncConnectToNode: (unsigned char [_Nonnull IPX_NODE_LEN])node - network: (uint32_t)network - port: (uint16_t)port - block: (OFSPXStreamSocketAsyncConnectBlock)block; +- (void)asyncConnectToNetwork: (uint32_t)network + node: (unsigned char [_Nonnull IPX_NODE_LEN])node + port: (uint16_t)port + block: (OFSPXStreamSocketAsyncConnectBlock)block; /** * @brief Asynchronously connect the OFSPXStreamSocket to the specified * destination. * - * @param node The node to connect to * @param network The network on which the node to connect to is + * @param node The node to connect to * @param port The port (sometimes also called socket number) on the node to * connect to * @param runLoopMode The run loop mode in which to perform the async connect * @param block The block to execute once the connection has been established */ -- (void)asyncConnectToNode: (unsigned char [_Nonnull IPX_NODE_LEN])node - network: (uint32_t)network - port: (uint16_t)port - runLoopMode: (OFRunLoopMode)runLoopMode - block: (OFSPXStreamSocketAsyncConnectBlock)block; +- (void)asyncConnectToNetwork: (uint32_t)network + node: (unsigned char [_Nonnull IPX_NODE_LEN])node + port: (uint16_t)port + runLoopMode: (OFRunLoopMode)runLoopMode + block: (OFSPXStreamSocketAsyncConnectBlock)block; #endif /** * @brief Bind the socket to the specified network, node and port. * Index: src/OFSPXStreamSocket.m ================================================================== --- src/OFSPXStreamSocket.m +++ src/OFSPXStreamSocket.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -45,21 +45,21 @@ OF_DIRECT_MEMBERS @interface OFSPXStreamSocketAsyncConnectDelegate: OFObject { OFSPXStreamSocket *_socket; - unsigned char _node[IPX_NODE_LEN]; uint32_t _network; + unsigned char _node[IPX_NODE_LEN]; uint16_t _port; #ifdef OF_HAVE_BLOCKS OFSPXStreamSocketAsyncConnectBlock _block; #endif } - (instancetype)initWithSocket: (OFSPXStreamSocket *)socket - node: (unsigned char [IPX_NODE_LEN])node network: (uint32_t)network + node: (unsigned char [IPX_NODE_LEN])node port: (uint16_t)port #ifdef OF_HAVE_BLOCKS block: (OFSPXStreamSocketAsyncConnectBlock)block #endif ; @@ -66,23 +66,23 @@ - (void)startWithRunLoopMode: (OFRunLoopMode)runLoopMode; @end @implementation OFSPXStreamSocketAsyncConnectDelegate - (instancetype)initWithSocket: (OFSPXStreamSocket *)sock - node: (unsigned char [IPX_NODE_LEN])node network: (uint32_t)network + node: (unsigned char [IPX_NODE_LEN])node port: (uint16_t)port #ifdef OF_HAVE_BLOCKS block: (OFSPXStreamSocketAsyncConnectBlock)block #endif { self = [super init]; @try { _socket = [sock retain]; - memcpy(_node, node, IPX_NODE_LEN); _network = network; + memcpy(_node, node, IPX_NODE_LEN); _port = port; #ifdef OF_HAVE_BLOCKS _block = [block copy]; #endif } @catch (id e) { @@ -104,11 +104,11 @@ } - (void)startWithRunLoopMode: (OFRunLoopMode)runLoopMode { OFSocketAddress address = - OFSocketAddressMakeIPX(_node, _network, _port); + OFSocketAddressMakeIPX(_network, _node, _port); id exception = nil; int errNo; if (![_socket of_createSocketForAddress: &address errNo: &errNo]) { exception = [self of_connectionFailedExceptionForErrNo: errNo]; @@ -153,28 +153,28 @@ if (_block != NULL) _block(exception); else { #endif if ([delegate respondsToSelector: - @selector(socket:didConnectToNode:network:port:exception:)]) - [delegate socket: _socket - didConnectToNode: _node - network: _network - port: _port - exception: exception]; + @selector(socket:didConnectToNetwork:node:port:exception:)]) + [delegate socket: _socket + didConnectToNetwork: _network + node: _node + port: _port + exception: exception]; #ifdef OF_HAVE_BLOCKS } #endif } - (id)of_connectionFailedExceptionForErrNo: (int)errNo { - return [OFConnectionFailedException exceptionWithNode: _node - network: _network - port: _port - socket: _socket - errNo: errNo]; + return [OFConnectionFailedException exceptionWithNetwork: _network + node: _node + port: _port + socket: _socket + errNo: errNo]; } @end @implementation OFSPXStreamSocket @dynamic delegate; @@ -208,11 +208,11 @@ errNo: (int *)errNo { if (_socket == OFInvalidSocketHandle) @throw [OFNotOpenException exceptionWithObject: self]; - if (connect(_socket, &address->sockaddr.sockaddr, + if (connect(_socket, (struct sockaddr *)&address->sockaddr, address->length) != 0) { *errNo = OFSocketErrNo(); return false; } @@ -223,58 +223,58 @@ { closesocket(_socket); _socket = OFInvalidSocketHandle; } -- (void)connectToNode: (unsigned char [_Nonnull IPX_NODE_LEN])node - network: (uint32_t)network - port: (uint16_t)port +- (void)connectToNetwork: (uint32_t)network + node: (unsigned char [_Nonnull IPX_NODE_LEN])node + port: (uint16_t)port { - OFSocketAddress address = OFSocketAddressMakeIPX(node, network, port); + OFSocketAddress address = OFSocketAddressMakeIPX(network, node, port); int errNo; if (![self of_createSocketForAddress: &address errNo: &errNo]) @throw [OFConnectionFailedException - exceptionWithNode: node - network: network - port: port - socket: self - errNo: errNo]; + exceptionWithNetwork: network + node: node + port: port + socket: self + errNo: errNo]; if (![self of_connectSocketToAddress: &address errNo: &errNo]) { [self of_closeSocket]; @throw [OFConnectionFailedException - exceptionWithNode: node - network: network - port: port - socket: self - errNo: errNo]; - } -} - -- (void)asyncConnectToNode: (unsigned char [_Nonnull IPX_NODE_LEN])node - network: (uint32_t)network - port: (uint16_t)port -{ - [self asyncConnectToNode: node - network: network - port: port - runLoopMode: OFDefaultRunLoopMode]; -} - -- (void)asyncConnectToNode: (unsigned char [_Nonnull IPX_NODE_LEN])node - network: (uint32_t)network - port: (uint16_t)port - runLoopMode: (OFRunLoopMode)runLoopMode + exceptionWithNetwork: network + node: node + port: port + socket: self + errNo: errNo]; + } +} + +- (void)asyncConnectToNetwork: (uint32_t)network + node: (unsigned char [_Nonnull IPX_NODE_LEN])node + port: (uint16_t)port +{ + [self asyncConnectToNetwork: network + node: node + port: port + runLoopMode: OFDefaultRunLoopMode]; +} + +- (void)asyncConnectToNetwork: (uint32_t)network + node: (unsigned char [_Nonnull IPX_NODE_LEN])node + port: (uint16_t)port + runLoopMode: (OFRunLoopMode)runLoopMode { void *pool = objc_autoreleasePoolPush(); [[[[OFSPXStreamSocketAsyncConnectDelegate alloc] initWithSocket: self - node: node network: network + node: node port: port #ifdef OF_HAVE_BLOCKS block: NULL #endif ] autorelease] startWithRunLoopMode: runLoopMode]; @@ -281,34 +281,34 @@ objc_autoreleasePoolPop(pool); } #ifdef OF_HAVE_BLOCKS -- (void)asyncConnectToNode: (unsigned char [_Nonnull IPX_NODE_LEN])node - network: (uint32_t)network - port: (uint16_t)port - block: (OFSPXStreamSocketAsyncConnectBlock)block -{ - [self asyncConnectToNode: node - network: network - port: port - runLoopMode: OFDefaultRunLoopMode - block: block]; -} - -- (void)asyncConnectToNode: (unsigned char [_Nonnull IPX_NODE_LEN])node - network: (uint32_t)network - port: (uint16_t)port - runLoopMode: (OFRunLoopMode)runLoopMode - block: (OFSPXStreamSocketAsyncConnectBlock)block +- (void)asyncConnectToNetwork: (uint32_t)network + node: (unsigned char [_Nonnull IPX_NODE_LEN])node + port: (uint16_t)port + block: (OFSPXStreamSocketAsyncConnectBlock)block +{ + [self asyncConnectToNetwork: network + node: node + port: port + runLoopMode: OFDefaultRunLoopMode + block: block]; +} + +- (void)asyncConnectToNetwork: (uint32_t)network + node: (unsigned char [_Nonnull IPX_NODE_LEN])node + port: (uint16_t)port + runLoopMode: (OFRunLoopMode)runLoopMode + block: (OFSPXStreamSocketAsyncConnectBlock)block { void *pool = objc_autoreleasePoolPush(); [[[[OFSPXStreamSocketAsyncConnectDelegate alloc] initWithSocket: self - node: node network: network + node: node port: port block: block ] autorelease] startWithRunLoopMode: runLoopMode]; objc_autoreleasePoolPop(pool); @@ -324,13 +324,13 @@ #endif if (_socket != OFInvalidSocketHandle) @throw [OFAlreadyConnectedException exceptionWithSocket: self]; - address = OFSocketAddressMakeIPX(zeroNode, 0, port); + address = OFSocketAddressMakeIPX(0, zeroNode, port); - if ((_socket = socket(address.sockaddr.sockaddr.sa_family, + if ((_socket = socket(address.sockaddr.ipx.sipx_family, SOCK_STREAM | SOCK_CLOEXEC, NSPROTO_SPX)) == OFInvalidSocketHandle) @throw [OFBindFailedException exceptionWithPort: port packetType: SPXPacketType socket: self @@ -341,11 +341,12 @@ #if SOCK_CLOEXEC == 0 && defined(HAVE_FCNTL_H) && defined(FD_CLOEXEC) if ((flags = fcntl(_socket, F_GETFD, 0)) != -1) fcntl(_socket, F_SETFD, flags | FD_CLOEXEC); #endif - if (bind(_socket, &address.sockaddr.sockaddr, address.length) != 0) { + if (bind(_socket, (struct sockaddr *)&address.sockaddr, + address.length) != 0) { int errNo = OFSocketErrNo(); closesocket(_socket); _socket = OFInvalidSocketHandle; @@ -357,11 +358,11 @@ memset(&address, 0, sizeof(address)); address.family = OFSocketAddressFamilyIPX; address.length = (socklen_t)sizeof(address.sockaddr); - if (OFGetSockName(_socket, &address.sockaddr.sockaddr, + if (OFGetSockName(_socket, (struct sockaddr *)&address.sockaddr, &address.length) != 0) { int errNo = OFSocketErrNo(); closesocket(_socket); _socket = OFInvalidSocketHandle; @@ -370,11 +371,11 @@ packetType: SPXPacketType socket: self errNo: errNo]; } - if (address.sockaddr.sockaddr.sa_family != AF_IPX) { + if (address.sockaddr.ipx.sipx_family != AF_IPX) { closesocket(_socket); _socket = OFInvalidSocketHandle; @throw [OFBindFailedException exceptionWithPort: port packetType: SPXPacketType Index: src/OFSandbox.h ================================================================== --- src/OFSandbox.h +++ src/OFSandbox.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFSandbox.m ================================================================== --- src/OFSandbox.m +++ src/OFSandbox.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFScrypt.h ================================================================== --- src/OFScrypt.h +++ src/OFScrypt.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFScrypt.m ================================================================== --- src/OFScrypt.m +++ src/OFScrypt.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFSecureData.h ================================================================== --- src/OFSecureData.h +++ src/OFSecureData.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFSecureData.m ================================================================== --- src/OFSecureData.m +++ src/OFSecureData.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFSeekableStream.h ================================================================== --- src/OFSeekableStream.h +++ src/OFSeekableStream.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFSeekableStream.m ================================================================== --- src/OFSeekableStream.m +++ src/OFSeekableStream.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFSelectKernelEventObserver.h ================================================================== --- src/OFSelectKernelEventObserver.h +++ src/OFSelectKernelEventObserver.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFSelectKernelEventObserver.m ================================================================== --- src/OFSelectKernelEventObserver.m +++ src/OFSelectKernelEventObserver.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFSequencedPacketSocket+Private.h ================================================================== --- src/OFSequencedPacketSocket+Private.h +++ src/OFSequencedPacketSocket+Private.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFSequencedPacketSocket.h ================================================================== --- src/OFSequencedPacketSocket.h +++ src/OFSequencedPacketSocket.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -38,17 +38,16 @@ id _Nullable exception); /** * @brief A block which is called when a packet has been sent. * - * @param data The data which was sent * @param exception An exception which occurred while reading or `nil` on * success * @return The data to repeat the send with or nil if it should not repeat */ typedef OFData *_Nullable (^OFSequencedPacketSocketAsyncSendDataBlock)( - OFData *_Nonnull data, id _Nullable exception); + id _Nullable exception); /** * @brief A block which is called when the socket accepted a connection. * * @param acceptedSocket The socket which has been accepted Index: src/OFSequencedPacketSocket.m ================================================================== --- src/OFSequencedPacketSocket.m +++ src/OFSequencedPacketSocket.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -329,27 +329,27 @@ client->_remoteAddress.length = (socklen_t)sizeof(client->_remoteAddress.sockaddr); #if defined(HAVE_PACCEPT) && defined(SOCK_CLOEXEC) if ((client->_socket = paccept(_socket, - &client->_remoteAddress.sockaddr.sockaddr, + (struct sockaddr *)&client->_remoteAddress.sockaddr, &client->_remoteAddress.length, NULL, SOCK_CLOEXEC)) == OFInvalidSocketHandle) @throw [OFAcceptFailedException exceptionWithSocket: self errNo: OFSocketErrNo()]; #elif defined(HAVE_ACCEPT4) && defined(SOCK_CLOEXEC) if ((client->_socket = accept4(_socket, - &client->_remoteAddress.sockaddr.sockaddr, + (struct sockaddr *)&client->_remoteAddress.sockaddr, &client->_remoteAddress.length, SOCK_CLOEXEC)) == OFInvalidSocketHandle) @throw [OFAcceptFailedException exceptionWithSocket: self errNo: OFSocketErrNo()]; #else if ((client->_socket = accept(_socket, - &client->_remoteAddress.sockaddr.sockaddr, + (struct sockaddr *)&client->_remoteAddress.sockaddr, &client->_remoteAddress.length)) == OFInvalidSocketHandle) @throw [OFAcceptFailedException exceptionWithSocket: self errNo: OFSocketErrNo()]; @@ -360,11 +360,12 @@ #endif assert(client->_remoteAddress.length <= (socklen_t)sizeof(client->_remoteAddress.sockaddr)); - switch (client->_remoteAddress.sockaddr.sockaddr.sa_family) { + switch (((struct sockaddr *)&client->_remoteAddress.sockaddr) + ->sa_family) { case AF_INET: client->_remoteAddress.family = OFSocketAddressFamilyIPv4; break; #ifdef OF_HAVE_IPV6 case AF_INET6: Index: src/OFSerialization.h ================================================================== --- src/OFSerialization.h +++ src/OFSerialization.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -15,10 +15,11 @@ #import "OFObject.h" OF_ASSUME_NONNULL_BEGIN +@class OFConstantString; @class OFXMLElement; /** * @protocol OFSerialization OFSerialization.h ObjFW/OFSerialization.h * @@ -40,11 +41,11 @@ @end #ifdef __cplusplus extern "C" { #endif -extern OFString *const OFSerializationNS; +extern OFConstantString *const OFSerializationNS; #ifdef __cplusplus } #endif OF_ASSUME_NONNULL_END Index: src/OFSerialization.m ================================================================== --- src/OFSerialization.m +++ src/OFSerialization.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -14,6 +14,7 @@ */ #import "OFSerialization.h" #import "OFString.h" -OFString *const OFSerializationNS = @"https://objfw.nil.im/serialization"; +OFConstantString *const OFSerializationNS = + @"https://objfw.nil.im/serialization"; Index: src/OFSet.h ================================================================== --- src/OFSet.h +++ src/OFSet.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -140,20 +140,10 @@ * @param firstObject The first object for the set * @return An initialized set with the specified objects */ - (instancetype)initWithObjects: (ObjectType)firstObject, ... OF_SENTINEL; -/** - * @brief Initializes an already allocated set with the specified objects. - * - * @param objects An array of objects for the set - * @param count The number of objects in the specified array - * @return An initialized set with the specified objects - */ -- (instancetype)initWithObjects: (ObjectType const _Nonnull *_Nonnull)objects - count: (size_t)count; - /** * @brief Initializes an already allocated set with the specified object and * va_list. * * @param firstObject The first object for the set @@ -161,10 +151,20 @@ * @return An initialized set with the specified object and va_list */ - (instancetype)initWithObject: (ObjectType)firstObject arguments: (va_list)arguments; +/** + * @brief Initializes an already allocated set with the specified objects. + * + * @param objects An array of objects for the set + * @param count The number of objects in the specified array + * @return An initialized set with the specified objects + */ +- (instancetype)initWithObjects: (ObjectType const _Nonnull *_Nonnull)objects + count: (size_t)count; + /** * @brief Returns an OFEnumerator to enumerate through all objects of the set. * * @return An OFEnumerator to enumerate through all objects of the set */ @@ -184,35 +184,17 @@ * @return Whether the receiver and the specified set have at least one object * in common */ - (bool)intersectsSet: (OFSet OF_GENERIC(ObjectType) *)set; -/** - * @brief Creates a new set which contains the objects which are in the - * receiver, but not in the specified set. - * - * @param set The set whose objects will not be in the new set - */ -- (OFSet OF_GENERIC(ObjectType) *)setBySubtractingSet: - (OFSet OF_GENERIC(ObjectType) *)set; - -/** - * @brief Creates a new set by creating the intersection of the receiver and - * the specified set. - * - * @param set The set to intersect with - */ -- (OFSet OF_GENERIC(ObjectType) *)setByIntersectingWithSet: - (OFSet OF_GENERIC(ObjectType) *)set; - /** * @brief Creates a new set by creating the union of the receiver and the * specified set. * * @param set The set to create the union with */ -- (OFSet OF_GENERIC(ObjectType) *)setByAddingSet: +- (OFSet OF_GENERIC(ObjectType) *)setByAddingObjectsFromSet: (OFSet OF_GENERIC(ObjectType) *)set; /** * @brief Checks whether the set contains an object equal to the specified * object. Index: src/OFSet.m ================================================================== --- src/OFSet.m +++ src/OFSet.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -385,27 +385,11 @@ objc_autoreleasePoolPop(pool); return [element autorelease]; } -- (OFSet *)setBySubtractingSet: (OFSet *)set -{ - OFMutableSet *new = [[self mutableCopy] autorelease]; - [new minusSet: set]; - [new makeImmutable]; - return new; -} - -- (OFSet *)setByIntersectingWithSet: (OFSet *)set -{ - OFMutableSet *new = [[self mutableCopy] autorelease]; - [new intersectSet: set]; - [new makeImmutable]; - return new; -} - -- (OFSet *)setByAddingSet: (OFSet *)set +- (OFSet *)setByAddingObjectsFromSet: (OFSet *)set { OFMutableSet *new = [[self mutableCopy] autorelease]; [new unionSet: set]; [new makeImmutable]; return new; Index: src/OFSettings.h ================================================================== --- src/OFSettings.h +++ src/OFSettings.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFSettings.m ================================================================== --- src/OFSettings.m +++ src/OFSettings.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -46,12 +46,12 @@ self = [super init]; @try { _applicationName = [applicationName copy]; } @catch (id e) { - @throw e; [self release]; + @throw e; } return self; } Index: src/OFSizeValue.h ================================================================== --- src/OFSizeValue.h +++ src/OFSizeValue.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFSizeValue.m ================================================================== --- src/OFSizeValue.m +++ src/OFSizeValue.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFSocket+Private.h ================================================================== --- src/OFSocket+Private.h +++ src/OFSocket+Private.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFSocket.h ================================================================== --- src/OFSocket.h +++ src/OFSocket.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -36,10 +36,16 @@ # include #endif #ifdef OF_HAVE_NETIPX_IPX_H # include #endif +#ifdef OF_HAVE_SYS_UN_H +# include +#endif +#ifdef OF_HAVE_AFUNIX_H +# include +#endif #ifdef OF_WINDOWS # include # include # ifdef OF_HAVE_IPX @@ -66,10 +72,14 @@ static const OFSocketHandle OFInvalidSocketHandle = -1; #else typedef SOCKET OFSocketHandle; static const OFSocketHandle OFInvalidSocketHandle = INVALID_SOCKET; #endif + +#ifdef OF_WINDOWS +typedef short sa_family_t; +#endif #ifdef OF_WII typedef u8 sa_family_t; #endif @@ -87,10 +97,12 @@ OFSocketAddressFamilyUnknown, /** IPv4 */ OFSocketAddressFamilyIPv4, /** IPv6 */ OFSocketAddressFamilyIPv6, + /** UNIX */ + OFSocketAddressFamilyUNIX, /** IPX */ OFSocketAddressFamilyIPX, /** Any address family */ OFSocketAddressFamilyAny = 255 } OFSocketAddressFamily; @@ -104,10 +116,17 @@ uint8_t s6_addr[16]; } sin6_addr; uint32_t sin6_scope_id; }; #endif + +#if !defined(OF_HAVE_UNIX_SOCKETS) && !defined(OF_MORPHOS) && !defined(OF_MINT) +struct sockaddr_un { + sa_family_t sun_family; + char sun_path[108]; +}; +#endif #ifndef OF_HAVE_IPX # define IPX_NODE_LEN 6 struct sockaddr_ipx { sa_family_t sipx_family; @@ -129,22 +148,19 @@ * @struct OFSocketAddress OFSocket.h ObjFW/OFSocket.h * * @brief A struct which represents a host / port pair for a socket. */ typedef struct OF_BOXABLE { + OFSocketAddressFamily family; /* - * 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. + * We can't use struct sockaddr as it can contain variable length + * arrays. */ - OFSocketAddressFamily family; union { - struct sockaddr sockaddr; struct sockaddr_in in; struct sockaddr_in6 in6; + struct sockaddr_un un; struct sockaddr_ipx ipx; } sockaddr; socklen_t length; } OFSocketAddress; @@ -178,19 +194,27 @@ * @return The parsed IPv6 and port as an OFSocketAddress */ extern OFSocketAddress OFSocketAddressParseIPv6(OFString *IP, uint16_t port); /** - * @brief Creates an IPX address for the specified network, node and port. + * @brief Creates a UNIX socket address from the specified path. * - * @param node The node in the IPX network + * @param path The path of the UNIX socket + * @return A UNIX socket address with the specified path + */ +extern OFSocketAddress OFSocketAddressMakeUNIX(OFString *path); + +/** + * @brief Creates an IPX address for the specified node, network and port. + * * @param network The IPX network + * @param node The node in the IPX network * @param port The IPX port (sometimes called socket number) on the node + * @return An IPX socket address with the specified node, network and port. */ -extern OFSocketAddress OFSocketAddressMakeIPX( - const unsigned char node[_Nonnull IPX_NODE_LEN], uint32_t network, - uint16_t port); +extern OFSocketAddress OFSocketAddressMakeIPX(uint32_t network, + const unsigned char node[_Nonnull IPX_NODE_LEN], uint16_t port); /** * @brief Compares two OFSocketAddress for equality. * * @param address1 The address to compare with the second address @@ -235,10 +259,19 @@ * @param address The address on which to get the port * @return The port of the address */ extern uint16_t OFSocketAddressPort(const OFSocketAddress *_Nonnull address); +/** + * @brief Gets the UNIX socket path of the specified @ref OFSocketAddress. + * + * @param address The address on which to get the UNIX socket path + * @return The UNIX socket path + */ +extern OFString *_Nullable OFSocketAddressUNIXPath( + const OFSocketAddress *_Nonnull address); + /** * @brief Sets the IPX network of the specified @ref OFSocketAddress. * * @param address The address on which to set the IPX network * @param network The IPX network to set on the address Index: src/OFSocket.m ================================================================== --- src/OFSocket.m +++ src/OFSocket.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -43,10 +43,11 @@ #import "OFException.h" /* For some E* -> WSAE* defines */ #import "OFInitializationFailedException.h" #import "OFInvalidArgumentException.h" #import "OFInvalidFormatException.h" #import "OFLockFailedException.h" +#import "OFOutOfRangeException.h" #import "OFUnlockFailedException.h" #ifdef OF_AMIGAOS # include #endif @@ -53,10 +54,16 @@ #ifdef OF_NINTENDO_3DS # include <3ds/types.h> # include <3ds/services/soc.h> #endif + +#ifdef OF_NINTENDO_SWITCH +# define id nx_id +# include +# undef id +#endif #if defined(OF_HAVE_THREADS) && (!defined(OF_AMIGAOS) || defined(OF_MORPHOS)) static OFMutex *mutex; static void @@ -127,20 +134,20 @@ if (socInit(ctx, 0x100000) != 0) return; atexit((void (*)(void))socExit); +# elif defined(OF_NINTENDO_SWITCH) + if (R_FAILED(socketInitializeDefault())) + return; + + atexit(socketExit); # endif # if defined(OF_HAVE_THREADS) && (!defined(OF_AMIGAOS) || defined(OF_MORPHOS)) mutex = [[OFMutex alloc] init]; atexit(releaseMutex); - -# ifdef OF_WII - if (OFSpinlockNew(&spinlock) != 0) - return; -# endif # endif initSuccessful = true; } @@ -512,11 +519,40 @@ return ret; } OFSocketAddress -OFSocketAddressMakeIPX(const unsigned char node[IPX_NODE_LEN], uint32_t network, +OFSocketAddressMakeUNIX(OFString *path) +{ + void *pool = objc_autoreleasePoolPush(); + OFStringEncoding encoding = [OFLocale encoding]; + size_t length = [path cStringLengthWithEncoding: encoding]; + OFSocketAddress ret; + + if (length > sizeof(ret.sockaddr.un.sun_path)) + @throw [OFOutOfRangeException exception]; + + memset(&ret, '\0', sizeof(ret)); + ret.family = OFSocketAddressFamilyUNIX; + ret.length = (socklen_t) + (offsetof(struct sockaddr_un, sun_path) + length); + +#ifdef AF_UNIX + ret.sockaddr.un.sun_family = AF_UNIX; +#else + ret.sockaddr.un.sun_family = AF_UNSPEC; +#endif + memcpy(ret.sockaddr.un.sun_path, + [path cStringWithEncoding: encoding], length); + + objc_autoreleasePoolPop(pool); + + return ret; +} + +OFSocketAddress +OFSocketAddressMakeIPX(uint32_t network, const unsigned char node[IPX_NODE_LEN], uint16_t port) { OFSocketAddress ret; memset(&ret, '\0', sizeof(ret)); @@ -526,14 +562,14 @@ #ifdef AF_IPX ret.sockaddr.ipx.sipx_family = AF_IPX; #else ret.sockaddr.ipx.sipx_family = AF_UNSPEC; #endif - memcpy(ret.sockaddr.ipx.sipx_node, node, IPX_NODE_LEN); network = OFToBigEndian32(network); memcpy(&ret.sockaddr.ipx.sipx_network, &network, sizeof(ret.sockaddr.ipx.sipx_network)); + memcpy(ret.sockaddr.ipx.sipx_node, node, IPX_NODE_LEN); ret.sockaddr.ipx.sipx_port = OFToBigEndian16(port); return ret; } @@ -542,10 +578,13 @@ const OFSocketAddress *address2) { const struct sockaddr_in *addrIn1, *addrIn2; const struct sockaddr_in6 *addrIn6_1, *addrIn6_2; const struct sockaddr_ipx *addrIPX1, *addrIPX2; + void *pool; + OFString *path1, *path2; + bool ret; if (address1->family != address2->family) return false; switch (address1->family) { @@ -565,11 +604,11 @@ if (addrIn1->sin_port != addrIn2->sin_port) return false; if (addrIn1->sin_addr.s_addr != addrIn2->sin_addr.s_addr) return false; - break; + return true; case OFSocketAddressFamilyIPv6: if (address1->length < (socklen_t)sizeof(struct sockaddr_in6) || address2->length < (socklen_t)sizeof(struct sockaddr_in6)) @throw [OFInvalidArgumentException exception]; @@ -581,11 +620,28 @@ if (memcmp(addrIn6_1->sin6_addr.s6_addr, addrIn6_2->sin6_addr.s6_addr, sizeof(addrIn6_1->sin6_addr.s6_addr)) != 0) return false; - break; + return true; + case OFSocketAddressFamilyUNIX: + pool = objc_autoreleasePoolPush(); + + path1 = OFSocketAddressUNIXPath(address1); + path2 = OFSocketAddressUNIXPath(address2); + + if (path1 == nil || path2 == nil) { + objc_autoreleasePoolPop(pool); + + return false; + } + + ret = [path1 isEqual: path2]; + + objc_autoreleasePoolPop(pool); + + return ret; case OFSocketAddressFamilyIPX: if (address1->length < (socklen_t)sizeof(struct sockaddr_ipx) || address2->length < (socklen_t)sizeof(struct sockaddr_ipx)) @throw [OFInvalidArgumentException exception]; @@ -599,16 +655,14 @@ return false; if (memcmp(addrIPX1->sipx_node, addrIPX2->sipx_node, IPX_NODE_LEN) != 0) return false; - break; + return true; default: @throw [OFInvalidArgumentException exception]; } - - return true; } unsigned long OFSocketAddressHash(const OFSocketAddress *address) { @@ -646,10 +700,19 @@ i < sizeof(address->sockaddr.in6.sin6_addr.s6_addr); i++) OFHashAdd(&hash, address->sockaddr.in6.sin6_addr.s6_addr[i]); break; + case OFSocketAddressFamilyUNIX:; + void *pool = objc_autoreleasePoolPush(); + OFString *path = OFSocketAddressUNIXPath(address); + + hash = path.hash; + + objc_autoreleasePoolPop(pool); + + return hash; case OFSocketAddressFamilyIPX:; unsigned char network[ sizeof(address->sockaddr.ipx.sipx_network)]; if (address->length < (socklen_t)sizeof(struct sockaddr_ipx)) @@ -801,10 +864,32 @@ return OFFromBigEndian16(address->sockaddr.ipx.sipx_port); default: @throw [OFInvalidArgumentException exception]; } } + +OFString * +OFSocketAddressUNIXPath(const OFSocketAddress *_Nonnull address) +{ + socklen_t length; + + if (address->family != OFSocketAddressFamilyUNIX) + @throw [OFInvalidArgumentException exception]; + + length = address->length - offsetof(struct sockaddr_un, sun_path); + + for (socklen_t i = 0; i < length; i++) + if (address->sockaddr.un.sun_path[i] == 0) + length = i; + + if (length <= 0) + return nil; + + return [OFString stringWithCString: address->sockaddr.un.sun_path + encoding: [OFLocale encoding] + length: length]; +} void OFSocketAddressSetIPXNetwork(OFSocketAddress *address, uint32_t network) { if (address->family != OFSocketAddressFamilyIPX) Index: src/OFSortedList.h ================================================================== --- src/OFSortedList.h +++ src/OFSortedList.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFSortedList.m ================================================================== --- src/OFSortedList.m +++ src/OFSortedList.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFStdIOStream+Private.h ================================================================== --- src/OFStdIOStream+Private.h +++ src/OFStdIOStream+Private.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -17,14 +17,16 @@ OF_ASSUME_NONNULL_BEGIN OF_DIRECT_MEMBERS @interface OFStdIOStream () -#ifndef OF_AMIGAOS -- (instancetype)of_initWithFileDescriptor: (int)fd OF_METHOD_FAMILY(init); -#else +#if defined(OF_AMIGAOS) - (instancetype)of_initWithHandle: (BPTR)handle closable: (bool)closable OF_METHOD_FAMILY(init); +#elif defined(OF_WII_U) +- (instancetype)of_init OF_METHOD_FAMILY(init); +#else +- (instancetype)of_initWithFileDescriptor: (int)fd OF_METHOD_FAMILY(init); #endif @end OF_ASSUME_NONNULL_END Index: src/OFStdIOStream.h ================================================================== --- src/OFStdIOStream.h +++ src/OFStdIOStream.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -36,19 +36,19 @@ */ #ifdef OF_STDIO_STREAM_WIN32_CONSOLE_H OF_SUBCLASSING_RESTRICTED #endif @interface OFStdIOStream: OFStream -#if !defined(OF_WINDOWS) && !defined(OF_AMIGAOS) +#if !defined(OF_WINDOWS) && !defined(OF_AMIGAOS) && !defined(OF_WII_U) #endif { -#ifndef OF_AMIGAOS - int _fd; -#else +#if defined(OF_AMIGAOS) BPTR _handle; bool _closable; +#elif !defined(OF_WII_U) + int _fd; #endif bool _atEndOfStream; } /** Index: src/OFStdIOStream.m ================================================================== --- src/OFStdIOStream.m +++ src/OFStdIOStream.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -49,10 +49,16 @@ #ifdef OF_AMIGAOS # include # include # undef HAVE_ISATTY #endif + +#ifdef OF_WII_U +# define BOOL WUT_BOOL +# include +# undef BOOL +#endif /* References for static linking */ #ifdef OF_WINDOWS void _reference_to_OFWin32ConsoleStdIOStream(void) @@ -132,11 +138,11 @@ date.microsecond / 1000, me, getpid(), msg]; objc_autoreleasePoolPop(pool); } -#ifdef HAVE_ISATTY +#if defined(HAVE_ISATTY) && !defined(OF_WII_U) static int colorToANSI(OFColor *color) { if ([color isEqual: [OFColor black]]) return 30; @@ -180,22 +186,11 @@ + (void)load { if (self != [OFStdIOStream class]) return; -# ifndef OF_AMIGAOS - int fd; - - if ((fd = fileno(stdin)) >= 0) - OFStdIn = [[OFStdIOStream alloc] of_initWithFileDescriptor: fd]; - if ((fd = fileno(stdout)) >= 0) - OFStdOut = [[OFStdIOStream alloc] - of_initWithFileDescriptor: fd]; - if ((fd = fileno(stderr)) >= 0) - OFStdErr = [[OFStdIOStream alloc] - of_initWithFileDescriptor: fd]; -# else +# if defined(OF_AMIGAOS) BPTR input, output, error; bool inputClosable = false, outputClosable = false, errorClosable = false; input = Input(); @@ -221,69 +216,112 @@ closable: inputClosable]; OFStdOut = [[OFStdIOStream alloc] of_initWithHandle: output closable: outputClosable]; OFStdErr = [[OFStdIOStream alloc] of_initWithHandle: error closable: errorClosable]; +# elif defined(OF_WII_U) + OFStdOut = [[OFStdIOStream alloc] of_init]; + OFStdErr = [[OFStdIOStream alloc] of_init]; +# else + int fd; + + if ((fd = fileno(stdin)) >= 0) + OFStdIn = [[OFStdIOStream alloc] of_initWithFileDescriptor: fd]; + if ((fd = fileno(stdout)) >= 0) + OFStdOut = [[OFStdIOStream alloc] + of_initWithFileDescriptor: fd]; + if ((fd = fileno(stderr)) >= 0) + OFStdErr = [[OFStdIOStream alloc] + of_initWithFileDescriptor: fd]; # endif } #endif - (instancetype)init { OF_INVALID_INIT_METHOD } -#ifndef OF_AMIGAOS -- (instancetype)of_initWithFileDescriptor: (int)fd -{ - self = [super init]; - - _fd = fd; - - return self; -} -#else +#if defined(OF_AMIGAOS) - (instancetype)of_initWithHandle: (BPTR)handle closable: (bool)closable { self = [super init]; _handle = handle; _closable = closable; return self; } +#elif defined(OF_WII_U) +- (instancetype)of_init +{ + return [super init]; +} +#else +- (instancetype)of_initWithFileDescriptor: (int)fd +{ + self = [super init]; + + _fd = fd; + + return self; +} #endif - (void)dealloc { -#ifndef OF_AMIGAOS - if (_fd != -1) -#else +#if defined(OF_AMIGAOS) if (_handle != 0) -#endif + [self close]; +#elif !defined(OF_WII_U) + if (_fd != -1) [self close]; +#endif [super dealloc]; } - (bool)lowlevelIsAtEndOfStream { -#ifndef OF_AMIGAOS - if (_fd == -1) -#else +#if defined(OF_AMIGAOS) if (_handle == 0) -#endif + @throw [OFNotOpenException exceptionWithObject: self]; +#elif !defined(OF_WII_U) + if (_fd == -1) @throw [OFNotOpenException exceptionWithObject: self]; +#endif return _atEndOfStream; } - (size_t)lowlevelReadIntoBuffer: (void *)buffer length: (size_t)length { +#if defined(OF_AMIGAOS) + ssize_t ret; + + if (_handle == 0) + @throw [OFNotOpenException exceptionWithObject: self]; + + if (length > LONG_MAX) + @throw [OFOutOfRangeException exception]; + + if ((ret = Read(_handle, buffer, length)) < 0) + @throw [OFReadFailedException exceptionWithObject: self + requestedLength: length + errNo: EIO]; + + if (ret == 0) + _atEndOfStream = true; + + return ret; +#elif defined(OF_WII_U) + @throw [OFReadFailedException exceptionWithObject: self + requestedLength: length + errNo: EOPNOTSUPP]; +#else ssize_t ret; -#ifndef OF_AMIGAOS if (_fd == -1) @throw [OFNotOpenException exceptionWithObject: self]; # ifndef OF_WINDOWS if ((ret = read(_fd, buffer, length)) < 0) @@ -297,32 +335,41 @@ if ((ret = read(_fd, buffer, (unsigned int)length)) < 0) @throw [OFReadFailedException exceptionWithObject: self requestedLength: length errNo: errno]; # endif -#else - if (_handle == 0) - @throw [OFNotOpenException exceptionWithObject: self]; - - if (length > LONG_MAX) - @throw [OFOutOfRangeException exception]; - - if ((ret = Read(_handle, buffer, length)) < 0) - @throw [OFReadFailedException exceptionWithObject: self - requestedLength: length - errNo: EIO]; -#endif if (ret == 0) _atEndOfStream = true; return ret; +#endif } - (size_t)lowlevelWriteBuffer: (const void *)buffer length: (size_t)length { -#ifndef OF_AMIGAOS +#if defined(OF_AMIGAOS) + LONG bytesWritten; + + if (_handle == 0) + @throw [OFNotOpenException exceptionWithObject: self]; + + if (length > SSIZE_MAX) + @throw [OFOutOfRangeException exception]; + + if ((bytesWritten = Write(_handle, (void *)buffer, length)) < 0) + @throw [OFWriteFailedException exceptionWithObject: self + requestedLength: length + bytesWritten: 0 + errNo: EIO]; + + return (size_t)bytesWritten; +#elif defined(OF_WII_U) + OSConsoleWrite(buffer, length); + + return length; +#else if (_fd == -1) @throw [OFNotOpenException exceptionWithObject: self]; # ifndef OF_WINDOWS ssize_t bytesWritten; @@ -345,30 +392,16 @@ @throw [OFWriteFailedException exceptionWithObject: self requestedLength: length bytesWritten: 0 errNo: errno]; # endif -#else - LONG bytesWritten; - - if (_handle == 0) - @throw [OFNotOpenException exceptionWithObject: self]; - - if (length > SSIZE_MAX) - @throw [OFOutOfRangeException exception]; - - if ((bytesWritten = Write(_handle, (void *)buffer, length)) < 0) - @throw [OFWriteFailedException exceptionWithObject: self - requestedLength: length - bytesWritten: 0 - errNo: EIO]; -#endif return (size_t)bytesWritten; +#endif } -#if !defined(OF_WINDOWS) && !defined(OF_AMIGAOS) +#if !defined(OF_WINDOWS) && !defined(OF_AMIGAOS) && !defined(OF_WII_U) - (int)fileDescriptorForReading { return _fd; } @@ -378,24 +411,24 @@ } #endif - (void)close { -#ifndef OF_AMIGAOS - if (_fd == -1) - @throw [OFNotOpenException exceptionWithObject: self]; - - close(_fd); - _fd = -1; -#else +#if defined(OF_AMIGAOS) if (_handle == 0) @throw [OFNotOpenException exceptionWithObject: self]; if (_closable) Close(_handle); _handle = 0; +#elif !defined(OF_WII_U) + if (_fd == -1) + @throw [OFNotOpenException exceptionWithObject: self]; + + close(_fd); + _fd = -1; #endif [super close]; } @@ -418,20 +451,21 @@ return OFMaxRetainCount; } - (bool)hasTerminal { -#ifdef HAVE_ISATTY +#if defined(HAVE_ISATTY) && !defined(OF_WII_U) return isatty(_fd); #else return false; #endif } - (int)columns { -#if defined(HAVE_SYS_IOCTL_H) && defined(TIOCGWINSZ) && !defined(OF_AMIGAOS) +#if defined(HAVE_SYS_IOCTL_H) && defined(TIOCGWINSZ) && \ + !defined(OF_AMIGAOS) && !defined(OF_WII_U) struct winsize ws; if (ioctl(_fd, TIOCGWINSZ, &ws) != 0) return -1; @@ -441,11 +475,12 @@ #endif } - (int)rows { -#if defined(HAVE_SYS_IOCTL_H) && defined(TIOCGWINSZ) && !defined(OF_AMIGAOS) +#if defined(HAVE_SYS_IOCTL_H) && defined(TIOCGWINSZ) && \ + !defined(OF_AMIGAOS) && !defined(OF_WII_U) struct winsize ws; if (ioctl(_fd, TIOCGWINSZ, &ws) != 0) return -1; @@ -455,11 +490,11 @@ #endif } - (void)setForegroundColor: (OFColor *)color { -#ifdef HAVE_ISATTY +#if defined(HAVE_ISATTY) && !defined(OF_WII_U) int code; if (!isatty(_fd)) return; @@ -470,11 +505,11 @@ #endif } - (void)setBackgroundColor: (OFColor *)color { -#ifdef HAVE_ISATTY +#if defined(HAVE_ISATTY) && !defined(OF_WII_U) int code; if (!isatty(_fd)) return; @@ -485,41 +520,41 @@ #endif } - (void)reset { -#ifdef HAVE_ISATTY +#if defined(HAVE_ISATTY) && !defined(OF_WII_U) if (!isatty(_fd)) return; [self writeString: @"\033[0m"]; #endif } - (void)clear { -#ifdef HAVE_ISATTY +#if defined(HAVE_ISATTY) && !defined(OF_WII_U) if (!isatty(_fd)) return; [self writeString: @"\033[2J"]; #endif } - (void)eraseLine { -#ifdef HAVE_ISATTY +#if defined(HAVE_ISATTY) && !defined(OF_WII_U) if (!isatty(_fd)) return; [self writeString: @"\033[2K"]; #endif } - (void)setCursorColumn: (unsigned int)column { -#ifdef HAVE_ISATTY +#if defined(HAVE_ISATTY) && !defined(OF_WII_U) if (!isatty(_fd)) return; [self writeFormat: @"\033[%uG", column + 1]; #endif @@ -528,11 +563,11 @@ - (void)setCursorPosition: (OFPoint)position { if (position.x < 0 || position.y < 0) @throw [OFInvalidArgumentException exception]; -#ifdef HAVE_ISATTY +#if defined(HAVE_ISATTY) && !defined(OF_WII_U) if (!isatty(_fd)) return; [self writeFormat: @"\033[%u;%uH", (unsigned)position.y + 1, (unsigned)position.x + 1]; @@ -539,11 +574,11 @@ #endif } - (void)setRelativeCursorPosition: (OFPoint)position { -#ifdef HAVE_ISATTY +#if defined(HAVE_ISATTY) && !defined(OF_WII_U) if (!isatty(_fd)) return; if (position.x > 0) [self writeFormat: @"\033[%uC", (unsigned)position.x]; Index: src/OFStrPTime.h ================================================================== --- src/OFStrPTime.h +++ src/OFStrPTime.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFStrPTime.m ================================================================== --- src/OFStrPTime.m +++ src/OFStrPTime.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFStream+Private.h ================================================================== --- src/OFStream+Private.h +++ src/OFStream+Private.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFStream.h ================================================================== --- src/OFStream.h +++ src/OFStream.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -63,35 +63,33 @@ /** * @brief A block which is called when data was written asynchronously to a * stream. * - * @param data The data which was written to the stream * @param bytesWritten The number of bytes which have been written. This * matches the length of the specified data on the * asynchronous write if no exception was encountered. * @param exception An exception which occurred while writing or `nil` on * success * @return The data to repeat the write with or nil if it should not repeat */ -typedef OFData *_Nullable (^OFStreamAsyncWriteDataBlock)(OFData *_Nonnull data, - size_t bytesWritten, id _Nullable exception); +typedef OFData *_Nullable (^OFStreamAsyncWriteDataBlock)(size_t bytesWritten, + id _Nullable exception); /** * @brief A block which is called when a string was written asynchronously to a * stream. * - * @param string The string which was written to the stream * @param bytesWritten The number of bytes which have been written. This * matches the length of the specified data on the * asynchronous write if no exception was encountered. * @param exception An exception which occurred while writing or `nil` on * success * @return The string to repeat the write with or nil if it should not repeat */ typedef OFString *_Nullable (^OFStreamAsyncWriteStringBlock)( - OFString *_Nonnull string, size_t bytesWritten, id _Nullable exception); + size_t bytesWritten, id _Nullable exception); #endif /** * @protocol OFStreamDelegate OFStream.h ObjFW/OFStream.h * @@ -526,83 +524,10 @@ * * @return A double from the stream in the native endianess */ - (double)readBigEndianDouble; -/** - * @brief Reads the specified number of uint16_ts from the stream which are - * encoded in big endian. - * - * @warning Only call this when you know that enough data is available! - * Otherwise you will get an exception! - * - * @param buffer A buffer of sufficient size to store the specified number of - * uint16_ts - * @param count The number of uint16_ts to read - * @return The number of bytes read - */ -- (size_t)readBigEndianInt16sIntoBuffer: (uint16_t *)buffer - count: (size_t)count; - -/** - * @brief Reads the specified number of uint32_ts from the stream which are - * encoded in big endian. - * - * @warning Only call this when you know that enough data is available! - * Otherwise you will get an exception! - * - * @param buffer A buffer of sufficient size to store the specified number of - * uint32_ts - * @param count The number of uint32_ts to read - * @return The number of bytes read - */ -- (size_t)readBigEndianInt32sIntoBuffer: (uint32_t *)buffer - count: (size_t)count; - -/** - * @brief Reads the specified number of uint64_ts from the stream which are - * encoded in big endian. - * - * @warning Only call this when you know that enough data is available! - * Otherwise you will get an exception! - * - * @param buffer A buffer of sufficient size to store the specified number of - * uint64_ts - * @param count The number of uint64_ts to read - * @return The number of bytes read - */ -- (size_t)readBigEndianInt64sIntoBuffer: (uint64_t *)buffer - count: (size_t)count; - -/** - * @brief Reads the specified number of floats from the stream which are encoded - * in big endian. - * - * @warning Only call this when you know that enough data is available! - * Otherwise you will get an exception! - * - * @param buffer A buffer of sufficient size to store the specified number of - * floats - * @param count The number of floats to read - * @return The number of bytes read - */ -- (size_t)readBigEndianFloatsIntoBuffer: (float *)buffer count: (size_t)count; - -/** - * @brief Reads the specified number of doubles from the stream which are - * encoded in big endian. - * - * @warning Only call this when you know that enough data is available! - * Otherwise you will get an exception! - * - * @param buffer A buffer of sufficient size to store the specified number of - * doubles - * @param count The number of doubles to read - * @return The number of bytes read - */ -- (size_t)readBigEndianDoublesIntoBuffer: (double *)buffer count: (size_t)count; - /** * @brief Reads a uint16_t from the stream which is encoded in little endian. * * @warning Only call this when you know that enough data is available! * Otherwise you will get an exception! @@ -649,85 +574,10 @@ * * @return A double from the stream in the native endianess */ - (double)readLittleEndianDouble; -/** - * @brief Reads the specified number of uint16_ts from the stream which are - * encoded in little endian. - * - * @warning Only call this when you know that enough data is available! - * Otherwise you will get an exception! - * - * @param buffer A buffer of sufficient size to store the specified number of - * uint16_ts - * @param count The number of uint16_ts to read - * @return The number of bytes read - */ -- (size_t)readLittleEndianInt16sIntoBuffer: (uint16_t *)buffer - count: (size_t)count; - -/** - * @brief Reads the specified number of uint32_ts from the stream which are - * encoded in little endian. - * - * @warning Only call this when you know that enough data is available! - * Otherwise you will get an exception! - * - * @param buffer A buffer of sufficient size to store the specified number of - * uint32_ts - * @param count The number of uint32_ts to read - * @return The number of bytes read - */ -- (size_t)readLittleEndianInt32sIntoBuffer: (uint32_t *)buffer - count: (size_t)count; - -/** - * @brief Reads the specified number of uint64_ts from the stream which are - * encoded in little endian. - * - * @warning Only call this when you know that enough data is available! - * Otherwise you will get an exception! - * - * @param buffer A buffer of sufficient size to store the specified number of - * uint64_ts - * @param count The number of uint64_ts to read - * @return The number of bytes read - */ -- (size_t)readLittleEndianInt64sIntoBuffer: (uint64_t *)buffer - count: (size_t)count; - -/** - * @brief Reads the specified number of floats from the stream which are - * encoded in little endian. - * - * @warning Only call this when you know that enough data is available! - * Otherwise you will get an exception! - * - * @param buffer A buffer of sufficient size to store the specified number of - * floats - * @param count The number of floats to read - * @return The number of bytes read - */ -- (size_t)readLittleEndianFloatsIntoBuffer: (float *)buffer - count: (size_t)count; - -/** - * @brief Reads the specified number of doubles from the stream which are - * encoded in little endian. - * - * @warning Only call this when you know that enough data is available! - * Otherwise you will get an exception! - * - * @param buffer A buffer of sufficient size to store the specified number of - * doubles - * @param count The number of doubles to read - * @return The number of bytes read - */ -- (size_t)readLittleEndianDoublesIntoBuffer: (double *)buffer - count: (size_t)count; - /** * @brief Reads the specified number of items with an item size of 1 from the * stream and returns them as OFData. * * @warning Only call this when you know that enough data is available! @@ -965,22 +815,31 @@ - (nullable OFString *)tryReadTillDelimiter: (OFString *)delimiter encoding: (OFStringEncoding)encoding; /** * @brief Writes everything in the write buffer to the stream. + * + * @return Whether the write buffer was flushed entirely. On non-blocking + * sockets, this can return `false` if flushing the write buffer in its + * entirety would block. */ -- (void)flushWriteBuffer; +- (bool)flushWriteBuffer; /** * @brief Writes from a buffer into the stream. + * + * In non-blocking mode, if less than the specified length could be written, an + * @ref OFWriteFailedException is thrown with @ref OFWriteFailedException#errNo + * being set to `EWOULDBLOCK` or `EAGAIN` (you need to check for both, as they + * are not the same on some systems) and + * @ref OFWriteFailedException#bytesWritten being set to the number of bytes + * that were written, if any. * * @param buffer The buffer from which the data is written into the stream * @param length The length of the data that should be written - * @return The number of bytes written. This can only differ from the specified - * length in non-blocking mode. */ -- (size_t)writeBuffer: (const void *)buffer length: (size_t)length; +- (void)writeBuffer: (const void *)buffer length: (size_t)length; #ifdef OF_HAVE_SOCKETS /** * @brief Asynchronously writes data into the stream. * @@ -1129,265 +988,181 @@ #endif /** * @brief Writes a uint8_t into the stream. * + * In non-blocking mode, the behavior is the same as @ref writeBuffer:length:. + * * @param int8 A uint8_t */ - (void)writeInt8: (uint8_t)int8; /** * @brief Writes a uint16_t into the stream, encoded in big endian. + * + * In non-blocking mode, the behavior is the same as @ref writeBuffer:length:. * * @param int16 A uint16_t */ - (void)writeBigEndianInt16: (uint16_t)int16; /** * @brief Writes a uint32_t into the stream, encoded in big endian. * + * In non-blocking mode, the behavior is the same as @ref writeBuffer:length:. + * * @param int32 A uint32_t */ - (void)writeBigEndianInt32: (uint32_t)int32; /** * @brief Writes a uint64_t into the stream, encoded in big endian. * + * In non-blocking mode, the behavior is the same as @ref writeBuffer:length:. + * * @param int64 A uint64_t */ - (void)writeBigEndianInt64: (uint64_t)int64; /** * @brief Writes a float into the stream, encoded in big endian. + * + * In non-blocking mode, the behavior is the same as @ref writeBuffer:length:. * * @param float_ A float */ - (void)writeBigEndianFloat: (float)float_; /** * @brief Writes a double into the stream, encoded in big endian. * + * In non-blocking mode, the behavior is the same as @ref writeBuffer:length:. + * * @param double_ A double */ - (void)writeBigEndianDouble: (double)double_; -/** - * @brief Writes the specified number of uint16_ts into the stream, encoded in - * big endian. - * - * @param buffer The buffer from which the data is written to the stream after - * it has been byte swapped if necessary - * @param count The number of uint16_ts to write - * @return The number of bytes written to the stream - */ -- (size_t)writeBigEndianInt16s: (const uint16_t *)buffer count: (size_t)count; - -/** - * @brief Writes the specified number of uint32_ts into the stream, encoded in - * big endian. - * - * @param buffer The buffer from which the data is written to the stream after - * it has been byte swapped if necessary - * @param count The number of uint32_ts to write - * @return The number of bytes written to the stream - */ -- (size_t)writeBigEndianInt32s: (const uint32_t *)buffer count: (size_t)count; - -/** - * @brief Writes the specified number of uint64_ts into the stream, encoded in - * big endian. - * - * @param buffer The buffer from which the data is written to the stream after - * it has been byte swapped if necessary - * @param count The number of uint64_ts to write - * @return The number of bytes written to the stream - */ -- (size_t)writeBigEndianInt64s: (const uint64_t *)buffer count: (size_t)count; - -/** - * @brief Writes the specified number of floats into the stream, encoded in big - * endian. - * - * @param buffer The buffer from which the data is written to the stream after - * it has been byte swapped if necessary - * @param count The number of floats to write - * @return The number of bytes written to the stream - */ -- (size_t)writeBigEndianFloats: (const float *)buffer count: (size_t)count; - -/** - * @brief Writes the specified number of doubles into the stream, encoded in - * big endian. - * - * @param buffer The buffer from which the data is written to the stream after - * it has been byte swapped if necessary - * @param count The number of doubles to write - * @return The number of bytes written to the stream - */ -- (size_t)writeBigEndianDoubles: (const double *)buffer count: (size_t)count; - /** * @brief Writes a uint16_t into the stream, encoded in little endian. + * + * In non-blocking mode, the behavior is the same as @ref writeBuffer:length:. * * @param int16 A uint16_t */ - (void)writeLittleEndianInt16: (uint16_t)int16; /** * @brief Writes a uint32_t into the stream, encoded in little endian. * + * In non-blocking mode, the behavior is the same as @ref writeBuffer:length:. + * * @param int32 A uint32_t */ - (void)writeLittleEndianInt32: (uint32_t)int32; /** * @brief Writes a uint64_t into the stream, encoded in little endian. * + * In non-blocking mode, the behavior is the same as @ref writeBuffer:length:. + * * @param int64 A uint64_t */ - (void)writeLittleEndianInt64: (uint64_t)int64; /** * @brief Writes a float into the stream, encoded in little endian. + * + * In non-blocking mode, the behavior is the same as @ref writeBuffer:length:. * * @param float_ A float */ - (void)writeLittleEndianFloat: (float)float_; /** * @brief Writes a double into the stream, encoded in little endian. * + * In non-blocking mode, the behavior is the same as @ref writeBuffer:length:. + * * @param double_ A double */ - (void)writeLittleEndianDouble: (double)double_; -/** - * @brief Writes the specified number of uint16_ts into the stream, encoded in - * little endian. - * - * @param buffer The buffer from which the data is written to the stream after - * it has been byte swapped if necessary - * @param count The number of uint16_ts to write - * @return The number of bytes written to the stream - */ -- (size_t)writeLittleEndianInt16s: (const uint16_t *)buffer - count: (size_t)count; - -/** - * @brief Writes the specified number of uint32_ts into the stream, encoded in - * little endian. - * - * @param count The number of uint32_ts to write - * @param buffer The buffer from which the data is written to the stream after - * it has been byte swapped if necessary - * @return The number of bytes written to the stream - */ -- (size_t)writeLittleEndianInt32s: (const uint32_t *)buffer - count: (size_t)count; - -/** - * @brief Writes the specified number of uint64_ts into the stream, encoded in - * little endian. - * - * @param buffer The buffer from which the data is written to the stream after - * it has been byte swapped if necessary - * @param count The number of uint64_ts to write - * @return The number of bytes written to the stream - */ -- (size_t)writeLittleEndianInt64s: (const uint64_t *)buffer - count: (size_t)count; - -/** - * @brief Writes the specified number of floats into the stream, encoded in - * little endian. - * - * @param buffer The buffer from which the data is written to the stream after - * it has been byte swapped if necessary - * @param count The number of floats to write - * @return The number of bytes written to the stream - */ -- (size_t)writeLittleEndianFloats: (const float *)buffer count: (size_t)count; - -/** - * @brief Writes the specified number of doubles into the stream, encoded in - * little endian. - * - * @param buffer The buffer from which the data is written to the stream after - * it has been byte swapped if necessary - * @param count The number of doubles to write - * @return The number of bytes written to the stream - */ -- (size_t)writeLittleEndianDoubles: (const double *)buffer count: (size_t)count; - /** * @brief Writes OFData into the stream. + * + * In non-blocking mode, the behavior is the same as @ref writeBuffer:length:. * * @param data The OFData to write into the stream - * @return The number of bytes written */ -- (size_t)writeData: (OFData *)data; +- (void)writeData: (OFData *)data; /** * @brief Writes a string into the stream, without the trailing zero. * + * In non-blocking mode, the behavior is the same as @ref writeBuffer:length:. + * * @param string The string from which the data is written to the stream - * @return The number of bytes written */ -- (size_t)writeString: (OFString *)string; +- (void)writeString: (OFString *)string; /** * @brief Writes a string into the stream in the specified encoding, without * the trailing zero. * + * In non-blocking mode, the behavior is the same as @ref writeBuffer:length:. + * * @param string The string from which the data is written to the stream * @param encoding The encoding in which to write the string to the stream - * @return The number of bytes written */ -- (size_t)writeString: (OFString *)string encoding: (OFStringEncoding)encoding; +- (void)writeString: (OFString *)string encoding: (OFStringEncoding)encoding; /** * @brief Writes a string into the stream with a trailing newline. * + * In non-blocking mode, the behavior is the same as @ref writeBuffer:length:. + * * @param string The string from which the data is written to the stream - * @return The number of bytes written */ -- (size_t)writeLine: (OFString *)string; +- (void)writeLine: (OFString *)string; /** * @brief Writes a string into the stream in the specified encoding with a * trailing newline. * + * In non-blocking mode, the behavior is the same as @ref writeBuffer:length:. + * * @param string The string from which the data is written to the stream * @param encoding The encoding in which to write the string to the stream - * @return The number of bytes written + */ +- (void)writeLine: (OFString *)string encoding: (OFStringEncoding)encoding; + +/** + * @brief Writes a formatted string into the stream. + * + * See printf for the format syntax. As an addition, `%@` is available as + * format specifier for objects, `%C` for `OFUnichar` and `%S` for + * `const OFUnichar *`. + * + * In non-blocking mode, the behavior is the same as @ref writeBuffer:length:. + * + * @param format A string used as format */ -- (size_t)writeLine: (OFString *)string encoding: (OFStringEncoding)encoding; +- (void)writeFormat: (OFConstantString *)format, ...; /** * @brief Writes a formatted string into the stream. * * See printf for the format syntax. As an addition, `%@` is available as * format specifier for objects, `%C` for `OFUnichar` and `%S` for * `const OFUnichar *`. * - * @param format A string used as format - * @return The number of bytes written - */ -- (size_t)writeFormat: (OFConstantString *)format, ...; - -/** - * @brief Writes a formatted string into the stream. - * - * See printf for the format syntax. As an addition, `%@` is available as - * format specifier for objects, `%C` for `OFUnichar` and `%S` for - * `const OFUnichar *`. + * In non-blocking mode, the behavior is the same as @ref writeBuffer:length:. * * @param format A string used as format * @param arguments The arguments used in the format string - * @return The number of bytes written */ -- (size_t)writeFormat: (OFConstantString *)format arguments: (va_list)arguments; +- (void)writeFormat: (OFConstantString *)format arguments: (va_list)arguments; #ifdef OF_HAVE_SOCKETS /** * @brief Cancels all pending asynchronous requests on the stream. */ Index: src/OFStream.m ================================================================== --- src/OFStream.m +++ src/OFStream.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -337,105 +337,10 @@ double ret; [self readIntoBuffer: (char *)&ret exactLength: 8]; return OFFromBigEndianDouble(ret); } -- (size_t)readBigEndianInt16sIntoBuffer: (uint16_t *)buffer count: (size_t)count -{ - size_t size; - - if OF_UNLIKELY (count > SIZE_MAX / sizeof(uint16_t)) - @throw [OFOutOfRangeException exception]; - - size = count * sizeof(uint16_t); - - [self readIntoBuffer: buffer exactLength: size]; - -#ifndef OF_BIG_ENDIAN - for (size_t i = 0; i < count; i++) - buffer[i] = OFByteSwap16(buffer[i]); -#endif - - return size; -} - -- (size_t)readBigEndianInt32sIntoBuffer: (uint32_t *)buffer count: (size_t)count -{ - size_t size; - - if OF_UNLIKELY (count > SIZE_MAX / sizeof(uint32_t)) - @throw [OFOutOfRangeException exception]; - - size = count * sizeof(uint32_t); - - [self readIntoBuffer: buffer exactLength: size]; - -#ifndef OF_BIG_ENDIAN - for (size_t i = 0; i < count; i++) - buffer[i] = OFByteSwap32(buffer[i]); -#endif - - return size; -} - -- (size_t)readBigEndianInt64sIntoBuffer: (uint64_t *)buffer count: (size_t)count -{ - size_t size; - - if OF_UNLIKELY (count > SIZE_MAX / sizeof(uint64_t)) - @throw [OFOutOfRangeException exception]; - - size = count * sizeof(uint64_t); - - [self readIntoBuffer: buffer exactLength: size]; - -#ifndef OF_BIG_ENDIAN - for (size_t i = 0; i < count; i++) - buffer[i] = OFByteSwap64(buffer[i]); -#endif - - return size; -} - -- (size_t)readBigEndianFloatsIntoBuffer: (float *)buffer count: (size_t)count -{ - size_t size; - - if OF_UNLIKELY (count > SIZE_MAX / sizeof(float)) - @throw [OFOutOfRangeException exception]; - - size = count * sizeof(float); - - [self readIntoBuffer: buffer exactLength: size]; - -#ifndef OF_FLOAT_BIG_ENDIAN - for (size_t i = 0; i < count; i++) - buffer[i] = OFByteSwapFloat(buffer[i]); -#endif - - return size; -} - -- (size_t)readBigEndianDoublesIntoBuffer: (double *)buffer count: (size_t)count -{ - size_t size; - - if OF_UNLIKELY (count > SIZE_MAX / sizeof(double)) - @throw [OFOutOfRangeException exception]; - - size = count * sizeof(double); - - [self readIntoBuffer: buffer exactLength: size]; - -#ifndef OF_FLOAT_BIG_ENDIAN - for (size_t i = 0; i < count; i++) - buffer[i] = OFByteSwapDouble(buffer[i]); -#endif - - return size; -} - - (uint16_t)readLittleEndianInt16 { uint16_t ret; [self readIntoBuffer: (char *)&ret exactLength: 2]; return OFFromLittleEndian16(ret); @@ -467,110 +372,10 @@ double ret; [self readIntoBuffer: (char *)&ret exactLength: 8]; return OFFromLittleEndianDouble(ret); } -- (size_t)readLittleEndianInt16sIntoBuffer: (uint16_t *)buffer - count: (size_t)count -{ - size_t size; - - if OF_UNLIKELY (count > SIZE_MAX / sizeof(uint16_t)) - @throw [OFOutOfRangeException exception]; - - size = count * sizeof(uint16_t); - - [self readIntoBuffer: buffer exactLength: size]; - -#ifdef OF_BIG_ENDIAN - for (size_t i = 0; i < count; i++) - buffer[i] = OFByteSwap16(buffer[i]); -#endif - - return size; -} - -- (size_t)readLittleEndianInt32sIntoBuffer: (uint32_t *)buffer - count: (size_t)count -{ - size_t size; - - if OF_UNLIKELY (count > SIZE_MAX / sizeof(uint32_t)) - @throw [OFOutOfRangeException exception]; - - size = count * sizeof(uint32_t); - - [self readIntoBuffer: buffer exactLength: size]; - -#ifdef OF_BIG_ENDIAN - for (size_t i = 0; i < count; i++) - buffer[i] = OFByteSwap32(buffer[i]); -#endif - - return size; -} - -- (size_t)readLittleEndianInt64sIntoBuffer: (uint64_t *)buffer - count: (size_t)count -{ - size_t size; - - if OF_UNLIKELY (count > SIZE_MAX / sizeof(uint64_t)) - @throw [OFOutOfRangeException exception]; - - size = count * sizeof(uint64_t); - - [self readIntoBuffer: buffer exactLength: size]; - -#ifdef OF_BIG_ENDIAN - for (size_t i = 0; i < count; i++) - buffer[i] = OFByteSwap64(buffer[i]); -#endif - - return size; -} - -- (size_t)readLittleEndianFloatsIntoBuffer: (float *)buffer - count: (size_t)count -{ - size_t size; - - if OF_UNLIKELY (count > SIZE_MAX / sizeof(float)) - @throw [OFOutOfRangeException exception]; - - size = count * sizeof(float); - - [self readIntoBuffer: buffer exactLength: size]; - -#ifdef OF_FLOAT_BIG_ENDIAN - for (size_t i = 0; i < count; i++) - buffer[i] = OFByteSwapFloat(buffer[i]); -#endif - - return size; -} - -- (size_t)readLittleEndianDoublesIntoBuffer: (double *)buffer - count: (size_t)count -{ - size_t size; - - if OF_UNLIKELY (count > SIZE_MAX / sizeof(double)) - @throw [OFOutOfRangeException exception]; - - size = count * sizeof(double); - - [self readIntoBuffer: buffer exactLength: size]; - -#ifdef OF_FLOAT_BIG_ENDIAN - for (size_t i = 0; i < count; i++) - buffer[i] = OFByteSwapDouble(buffer[i]); -#endif - - return size; -} - - (OFData *)readDataWithCount: (size_t)count { return [self readDataWithItemSize: 1 count: count]; } @@ -1054,44 +859,66 @@ { return [self tryReadTillDelimiter: delimiter encoding: OFStringEncodingUTF8]; } -- (void)flushWriteBuffer +- (bool)flushWriteBuffer { + size_t bytesWritten; + if (_writeBuffer == NULL) - return; + return true; - [self lowlevelWriteBuffer: _writeBuffer length: _writeBufferLength]; + bytesWritten = [self lowlevelWriteBuffer: _writeBuffer + length: _writeBufferLength]; - OFFreeMemory(_writeBuffer); - _writeBuffer = NULL; - _writeBufferLength = 0; + if (bytesWritten == 0) + return false; + + if (bytesWritten == _writeBufferLength) { + OFFreeMemory(_writeBuffer); + _writeBuffer = NULL; + _writeBufferLength = 0; + + return true; + } + + OFEnsure(bytesWritten <= _writeBufferLength); + + memmove(_writeBuffer, _writeBuffer + bytesWritten, + _writeBufferLength - bytesWritten); + _writeBufferLength -= bytesWritten; + @try { + _writeBuffer = OFResizeMemory(_writeBuffer, + _writeBufferLength, 1); + } @catch (OFOutOfMemoryException *e) { + /* We don't care, as we only made it smaller. */ + } + + return false; } -- (size_t)writeBuffer: (const void *)buffer - length: (size_t)length +- (void)writeBuffer: (const void *)buffer length: (size_t)length { if (!_buffersWrites) { size_t bytesWritten = [self lowlevelWriteBuffer: buffer length: length]; - if (_canBlock && bytesWritten < length) + if (bytesWritten < length) @throw [OFWriteFailedException exceptionWithObject: self requestedLength: length bytesWritten: bytesWritten errNo: 0]; - - return bytesWritten; } else { + if (SIZE_MAX - _writeBufferLength < length) + @throw [OFOutOfRangeException exception]; + _writeBuffer = OFResizeMemory(_writeBuffer, _writeBufferLength + length, 1); memcpy(_writeBuffer + _writeBufferLength, buffer, length); _writeBufferLength += length; - - return length; } } #ifdef OF_HAVE_SOCKETS - (void)asyncWriteData: (OFData *)data @@ -1237,145 +1064,10 @@ { double_ = OFToBigEndianDouble(double_); [self writeBuffer: (char *)&double_ length: 8]; } -- (size_t)writeBigEndianInt16s: (const uint16_t *)buffer count: (size_t)count -{ - size_t size; - - if OF_UNLIKELY (count > SIZE_MAX / sizeof(uint16_t)) - @throw [OFOutOfRangeException exception]; - - size = count * sizeof(uint16_t); - -#ifdef OF_BIG_ENDIAN - [self writeBuffer: buffer length: size]; -#else - uint16_t *tmp = OFAllocMemory(count, sizeof(uint16_t)); - - @try { - for (size_t i = 0; i < count; i++) - tmp[i] = OFByteSwap16(buffer[i]); - - [self writeBuffer: tmp length: size]; - } @finally { - OFFreeMemory(tmp); - } -#endif - - return size; -} - -- (size_t)writeBigEndianInt32s: (const uint32_t *)buffer count: (size_t)count -{ - size_t size; - - if OF_UNLIKELY (count > SIZE_MAX / sizeof(uint32_t)) - @throw [OFOutOfRangeException exception]; - - size = count * sizeof(uint32_t); - -#ifdef OF_BIG_ENDIAN - [self writeBuffer: buffer length: size]; -#else - uint32_t *tmp = OFAllocMemory(count, sizeof(uint32_t)); - - @try { - for (size_t i = 0; i < count; i++) - tmp[i] = OFByteSwap32(buffer[i]); - - [self writeBuffer: tmp length: size]; - } @finally { - OFFreeMemory(tmp); - } -#endif - - return size; -} - -- (size_t)writeBigEndianInt64s: (const uint64_t *)buffer count: (size_t)count -{ - size_t size; - - if OF_UNLIKELY (count > SIZE_MAX / sizeof(uint64_t)) - @throw [OFOutOfRangeException exception]; - - size = count * sizeof(uint64_t); - -#ifdef OF_BIG_ENDIAN - [self writeBuffer: buffer length: size]; -#else - uint64_t *tmp = OFAllocMemory(count, sizeof(uint64_t)); - - @try { - for (size_t i = 0; i < count; i++) - tmp[i] = OFByteSwap64(buffer[i]); - - [self writeBuffer: tmp length: size]; - } @finally { - OFFreeMemory(tmp); - } -#endif - - return size; -} - -- (size_t)writeBigEndianFloats: (const float *)buffer count: (size_t)count -{ - size_t size; - - if OF_UNLIKELY (count > SIZE_MAX / sizeof(float)) - @throw [OFOutOfRangeException exception]; - - size = count * sizeof(float); - -#ifdef OF_FLOAT_BIG_ENDIAN - [self writeBuffer: buffer length: size]; -#else - float *tmp = OFAllocMemory(count, sizeof(float)); - - @try { - for (size_t i = 0; i < count; i++) - tmp[i] = OFByteSwapFloat(buffer[i]); - - [self writeBuffer: tmp length: size]; - } @finally { - OFFreeMemory(tmp); - } -#endif - - return size; -} - -- (size_t)writeBigEndianDoubles: (const double *)buffer count: (size_t)count -{ - size_t size; - - if OF_UNLIKELY (count > SIZE_MAX / sizeof(double)) - @throw [OFOutOfRangeException exception]; - - size = count * sizeof(double); - -#ifdef OF_FLOAT_BIG_ENDIAN - [self writeBuffer: buffer length: size]; -#else - double *tmp = OFAllocMemory(count, sizeof(double)); - - @try { - for (size_t i = 0; i < count; i++) - tmp[i] = OFByteSwapDouble(buffer[i]); - - [self writeBuffer: tmp length: size]; - } @finally { - OFFreeMemory(tmp); - } -#endif - - return size; -} - - (void)writeLittleEndianInt16: (uint16_t)int16 { int16 = OFToLittleEndian16(int16); [self writeBuffer: (char *)&int16 length: 2]; } @@ -1402,146 +1094,11 @@ { double_ = OFToLittleEndianDouble(double_); [self writeBuffer: (char *)&double_ length: 8]; } -- (size_t)writeLittleEndianInt16s: (const uint16_t *)buffer count: (size_t)count -{ - size_t size; - - if OF_UNLIKELY (count > SIZE_MAX / sizeof(uint16_t)) - @throw [OFOutOfRangeException exception]; - - size = count * sizeof(uint16_t); - -#ifndef OF_BIG_ENDIAN - [self writeBuffer: buffer length: size]; -#else - uint16_t *tmp = OFAllocMemory(count, sizeof(uint16_t)); - - @try { - for (size_t i = 0; i < count; i++) - tmp[i] = OFByteSwap16(buffer[i]); - - [self writeBuffer: tmp length: size]; - } @finally { - OFFreeMemory(tmp); - } -#endif - - return size; -} - -- (size_t)writeLittleEndianInt32s: (const uint32_t *)buffer count: (size_t)count -{ - size_t size; - - if OF_UNLIKELY (count > SIZE_MAX / sizeof(uint32_t)) - @throw [OFOutOfRangeException exception]; - - size = count * sizeof(uint32_t); - -#ifndef OF_BIG_ENDIAN - [self writeBuffer: buffer length: size]; -#else - uint32_t *tmp = OFAllocMemory(count, sizeof(uint32_t)); - - @try { - for (size_t i = 0; i < count; i++) - tmp[i] = OFByteSwap32(buffer[i]); - - [self writeBuffer: tmp length: size]; - } @finally { - OFFreeMemory(tmp); - } -#endif - - return size; -} - -- (size_t)writeLittleEndianInt64s: (const uint64_t *)buffer count: (size_t)count -{ - size_t size; - - if OF_UNLIKELY (count > SIZE_MAX / sizeof(uint64_t)) - @throw [OFOutOfRangeException exception]; - - size = count * sizeof(uint64_t); - -#ifndef OF_BIG_ENDIAN - [self writeBuffer: buffer length: size]; -#else - uint64_t *tmp = OFAllocMemory(count, sizeof(uint64_t)); - - @try { - for (size_t i = 0; i < count; i++) - tmp[i] = OFByteSwap64(buffer[i]); - - [self writeBuffer: tmp length: size]; - } @finally { - OFFreeMemory(tmp); - } -#endif - - return size; -} - -- (size_t)writeLittleEndianFloats: (const float *)buffer count: (size_t)count -{ - size_t size; - - if OF_UNLIKELY (count > SIZE_MAX / sizeof(float)) - @throw [OFOutOfRangeException exception]; - - size = count * sizeof(float); - -#ifndef OF_FLOAT_BIG_ENDIAN - [self writeBuffer: buffer length: size]; -#else - float *tmp = OFAllocMemory(count, sizeof(float)); - - @try { - for (size_t i = 0; i < count; i++) - tmp[i] = OFByteSwapFloat(buffer[i]); - - [self writeBuffer: tmp length: size]; - } @finally { - OFFreeMemory(tmp); - } -#endif - - return size; -} - -- (size_t)writeLittleEndianDoubles: (const double *)buffer count: (size_t)count -{ - size_t size; - - if OF_UNLIKELY (count > SIZE_MAX / sizeof(double)) - @throw [OFOutOfRangeException exception]; - - size = count * sizeof(double); - -#ifndef OF_FLOAT_BIG_ENDIAN - [self writeBuffer: buffer length: size]; -#else - double *tmp = OFAllocMemory(count, sizeof(double)); - - @try { - for (size_t i = 0; i < count; i++) - tmp[i] = OFByteSwapDouble(buffer[i]); - - [self writeBuffer: tmp length: size]; - } @finally { - OFFreeMemory(tmp); - } -#endif - - return size; -} - -- (size_t)writeData: (OFData *)data +- (void)writeData: (OFData *)data { void *pool; size_t length; if (data == nil) @@ -1551,20 +1108,18 @@ length = data.count * data.itemSize; [self writeBuffer: data.items length: length]; objc_autoreleasePoolPop(pool); +} - return length; +- (void)writeString: (OFString *)string +{ + [self writeString: string encoding: OFStringEncodingUTF8]; } -- (size_t)writeString: (OFString *)string -{ - return [self writeString: string encoding: OFStringEncodingUTF8]; -} - -- (size_t)writeString: (OFString *)string encoding: (OFStringEncoding)encoding +- (void)writeString: (OFString *)string encoding: (OFStringEncoding)encoding { void *pool; size_t length; if (string == nil) @@ -1575,20 +1130,18 @@ [self writeBuffer: [string cStringWithEncoding: encoding] length: length]; objc_autoreleasePoolPop(pool); +} - return length; +- (void)writeLine: (OFString *)string +{ + [self writeLine: string encoding: OFStringEncodingUTF8]; } -- (size_t)writeLine: (OFString *)string -{ - return [self writeLine: string encoding: OFStringEncodingUTF8]; -} - -- (size_t)writeLine: (OFString *)string encoding: (OFStringEncoding)encoding +- (void)writeLine: (OFString *)string encoding: (OFStringEncoding)encoding { size_t stringLength = [string cStringLengthWithEncoding: encoding]; char *buffer; buffer = OFAllocMemory(stringLength + 1, 1); @@ -1600,27 +1153,22 @@ [self writeBuffer: buffer length: stringLength + 1]; } @finally { OFFreeMemory(buffer); } - - return stringLength + 1; } -- (size_t)writeFormat: (OFConstantString *)format, ... +- (void)writeFormat: (OFConstantString *)format, ... { va_list arguments; - size_t ret; va_start(arguments, format); - ret = [self writeFormat: format arguments: arguments]; + [self writeFormat: format arguments: arguments]; va_end(arguments); - - return ret; } -- (size_t)writeFormat: (OFConstantString *)format arguments: (va_list)arguments +- (void)writeFormat: (OFConstantString *)format arguments: (va_list)arguments { char *UTF8String; int length; if (format == nil) @@ -1633,12 +1181,10 @@ @try { [self writeBuffer: UTF8String length: length]; } @finally { free(UTF8String); } - - return length; } - (bool)hasDataInReadBuffer { return (_readBufferLength > 0); Index: src/OFStreamSocket+Private.h ================================================================== --- src/OFStreamSocket+Private.h +++ src/OFStreamSocket+Private.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFStreamSocket.h ================================================================== --- src/OFStreamSocket.h +++ src/OFStreamSocket.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFStreamSocket.m ================================================================== --- src/OFStreamSocket.m +++ src/OFStreamSocket.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -253,27 +253,27 @@ client->_remoteAddress.length = (socklen_t)sizeof(client->_remoteAddress.sockaddr); #if defined(HAVE_PACCEPT) && defined(SOCK_CLOEXEC) if ((client->_socket = paccept(_socket, - &client->_remoteAddress.sockaddr.sockaddr, + (struct sockaddr *)&client->_remoteAddress.sockaddr, &client->_remoteAddress.length, NULL, SOCK_CLOEXEC)) == OFInvalidSocketHandle) @throw [OFAcceptFailedException exceptionWithSocket: self errNo: OFSocketErrNo()]; #elif defined(HAVE_ACCEPT4) && defined(SOCK_CLOEXEC) if ((client->_socket = accept4(_socket, - &client->_remoteAddress.sockaddr.sockaddr, + (struct sockaddr * )&client->_remoteAddress.sockaddr, &client->_remoteAddress.length, SOCK_CLOEXEC)) == OFInvalidSocketHandle) @throw [OFAcceptFailedException exceptionWithSocket: self errNo: OFSocketErrNo()]; #else if ((client->_socket = accept(_socket, - &client->_remoteAddress.sockaddr.sockaddr, + (struct sockaddr *)&client->_remoteAddress.sockaddr, &client->_remoteAddress.length)) == OFInvalidSocketHandle) @throw [OFAcceptFailedException exceptionWithSocket: self errNo: OFSocketErrNo()]; @@ -284,18 +284,24 @@ #endif assert(client->_remoteAddress.length <= (socklen_t)sizeof(client->_remoteAddress.sockaddr)); - switch (client->_remoteAddress.sockaddr.sockaddr.sa_family) { + switch (((struct sockaddr *)&client->_remoteAddress.sockaddr) + ->sa_family) { case AF_INET: client->_remoteAddress.family = OFSocketAddressFamilyIPv4; break; #ifdef OF_HAVE_IPV6 case AF_INET6: client->_remoteAddress.family = OFSocketAddressFamilyIPv6; break; +#endif +#ifdef OF_HAVE_UNIX_SOCKETS + case AF_UNIX: + client->_remoteAddress.family = OFSocketAddressFamilyUNIX; + break; #endif #ifdef OF_HAVE_IPX case AF_IPX: client->_remoteAddress.family = OFSocketAddressFamilyIPX; break; Index: src/OFString+CryptographicHashing.h ================================================================== --- src/OFString+CryptographicHashing.h +++ src/OFString+CryptographicHashing.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFString+CryptographicHashing.m ================================================================== --- src/OFString+CryptographicHashing.m +++ src/OFString+CryptographicHashing.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -37,10 +37,11 @@ size_t digestSize = [class digestSize]; const unsigned char *digest; char cString[digestSize * 2]; [hash updateWithBuffer: self.UTF8String length: self.UTF8StringLength]; + [hash calculate]; digest = hash.digest; for (size_t i = 0; i < digestSize; i++) { uint8_t high, low; Index: src/OFString+JSONParsing.h ================================================================== --- src/OFString+JSONParsing.h +++ src/OFString+JSONParsing.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFString+JSONParsing.m ================================================================== --- src/OFString+JSONParsing.m +++ src/OFString+JSONParsing.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFString+PathAdditions.h ================================================================== --- src/OFString+PathAdditions.h +++ src/OFString+PathAdditions.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -75,14 +75,22 @@ * @param component The path component to append * @return A new, autoreleased OFString with the path component appended */ - (OFString *)stringByAppendingPathComponent: (OFString *)component; +/** + * @brief Creates a new string by appending a path extension. + * + * @param extension The extension to append + * @return A new, autoreleased OFString with the path extension appended + */ +- (OFString *)stringByAppendingPathExtension: (OFString *)extension; + - (bool)of_isDirectoryPath; - (OFString *)of_pathToURLPathWithURLEncodedHost: (OFString *__autoreleasing _Nullable *_Nonnull)URLEncodedHost; - (OFString *)of_URLPathToPathWithURLEncodedHost: (nullable OFString *)URLEncodedHost; - (OFString *)of_pathComponentToURLPathComponent; @end OF_ASSUME_NONNULL_END Index: src/OFString+PathAdditions.m ================================================================== --- src/OFString+PathAdditions.m +++ src/OFString+PathAdditions.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -15,14 +15,15 @@ #include "config.h" #include "platform.h" -#if defined(OF_WINDOWS) || defined(OF_MSDOS) +#if defined(OF_WINDOWS) || defined(OF_MSDOS) || defined(OF_MINT) # import "platform/Windows/OFString+PathAdditions.m" #elif defined(OF_AMIGAOS) # import "platform/AmigaOS/OFString+PathAdditions.m" -#elif defined(OF_NINTENDO_3DS) || defined(OF_WII) +#elif defined(OF_NINTENDO_3DS) || defined(OF_WII) || \ + defined(OF_NINTENDO_SWITCH) # import "platform/libfat/OFString+PathAdditions.m" #else # import "platform/POSIX/OFString+PathAdditions.m" #endif Index: src/OFString+PropertyListParsing.h ================================================================== --- src/OFString+PropertyListParsing.h +++ src/OFString+PropertyListParsing.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFString+PropertyListParsing.m ================================================================== --- src/OFString+PropertyListParsing.m +++ src/OFString+PropertyListParsing.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFString+Serialization.h ================================================================== --- src/OFString+Serialization.h +++ src/OFString+Serialization.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFString+Serialization.m ================================================================== --- src/OFString+Serialization.m +++ src/OFString+Serialization.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFString+URLEncoding.h ================================================================== --- src/OFString+URLEncoding.h +++ src/OFString+URLEncoding.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFString+URLEncoding.m ================================================================== --- src/OFString+URLEncoding.m +++ src/OFString+URLEncoding.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFString+XMLEscaping.h ================================================================== --- src/OFString+XMLEscaping.h +++ src/OFString+XMLEscaping.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFString+XMLEscaping.m ================================================================== --- src/OFString+XMLEscaping.m +++ src/OFString+XMLEscaping.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFString+XMLUnescaping.h ================================================================== --- src/OFString+XMLUnescaping.h +++ src/OFString+XMLUnescaping.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFString+XMLUnescaping.m ================================================================== --- src/OFString+XMLUnescaping.m +++ src/OFString+XMLUnescaping.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFString.h ================================================================== --- src/OFString.h +++ src/OFString.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFString.m ================================================================== --- src/OFString.m +++ src/OFString.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -1082,10 +1082,14 @@ data = [OFData dataWithContentsOfURL: URL]; } @catch (id e) { [self release]; @throw e; } + + /* FIXME: Detect encoding where we can. */ + if (encoding == OFStringEncodingAutodetect) + encoding = OFStringEncodingUTF8; self = [self initWithCString: data.items encoding: encoding length: data.count * data.itemSize]; Index: src/OFSubarray.h ================================================================== --- src/OFSubarray.h +++ src/OFSubarray.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFSubarray.m ================================================================== --- src/OFSubarray.m +++ src/OFSubarray.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFSubprocess.h ================================================================== --- src/OFSubprocess.h +++ src/OFSubprocess.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -78,11 +78,11 @@ * search path specified in PATH is used. * @param arguments The arguments to pass to the program, or `nil` * @return A new, autoreleased OFSubprocess. */ + (instancetype) - subProcessWithProgram: (OFString *)program + subprocessWithProgram: (OFString *)program arguments: (nullable OFArray OF_GENERIC(OFString *) *)arguments; /** * @brief Creates a new OFSubprocess with the specified program, program name * and arguments and invokes the program. Index: src/OFSubprocess.m ================================================================== --- src/OFSubprocess.m +++ src/OFSubprocess.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFSystemInfo.h ================================================================== --- src/OFSystemInfo.h +++ src/OFSystemInfo.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -16,10 +16,12 @@ #import "OFObject.h" #import "OFString.h" OF_ASSUME_NONNULL_BEGIN +@class OFURL; + /** * @class OFSystemInfo OFSystemInfo.h ObjFW/OFSystemInfo.h * * @brief A class for querying information about the system. */ @@ -27,19 +29,18 @@ @interface OFSystemInfo: OFObject #ifdef OF_HAVE_CLASS_PROPERTIES @property (class, readonly, nonatomic) size_t pageSize; @property (class, readonly, nonatomic) size_t numberOfCPUs; @property (class, readonly, nonatomic) OFString *ObjFWVersion; -@property (class, readonly, nonatomic) unsigned int ObjFWVersionMajor; -@property (class, readonly, nonatomic) unsigned int ObjFWVersionMinor; +@property (class, readonly, nonatomic) unsigned short ObjFWVersionMajor; +@property (class, readonly, nonatomic) unsigned short ObjFWVersionMinor; @property (class, readonly, nullable, nonatomic) OFString *operatingSystemName; @property (class, readonly, nullable, nonatomic) OFString *operatingSystemVersion; -# ifdef OF_HAVE_FILES -@property (class, readonly, nullable, nonatomic) OFString *userDataPath; -@property (class, readonly, nullable, nonatomic) OFString *userConfigPath; -# endif +@property (class, readonly, nullable, nonatomic) OFURL *userDataURL; +@property (class, readonly, nullable, nonatomic) OFURL *userConfigURL; +@property (class, readonly, nullable, nonatomic) OFURL *temporaryDirectoryURL; @property (class, readonly, nullable, nonatomic) OFString *CPUVendor; @property (class, readonly, nullable, nonatomic) OFString *CPUModel; # if defined(OF_X86_64) || defined(OF_X86) || defined(DOXYGEN) @property (class, readonly, nonatomic) bool supportsMMX; @property (class, readonly, nonatomic) bool supportsSSE; @@ -87,18 +88,18 @@ /** * @brief The major version of ObjFW. * * @return The major version of ObjFW */ -+ (unsigned int)ObjFWVersionMajor; ++ (unsigned short)ObjFWVersionMajor; /** * @brief The minor version of ObjFW. * * @return The minor version of ObjFW */ -+ (unsigned int)ObjFWVersionMinor; ++ (unsigned short)ObjFWVersionMinor; /** * @brief Returns the name of the operating system the application is running * on. * @@ -112,11 +113,10 @@ * * @return The version of the operating system the application is running on */ + (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 @@ -124,11 +124,11 @@ * 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; ++ (nullable OFURL *)userDataURL; /** * @brief Returns the path where user configuration for the application can be * stored. * @@ -139,11 +139,11 @@ * 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; ++ (nullable OFURL *)userConfigURL; /** * @brief Returns a path where temporary files for can be stored. * * If possible, returns a temporary directory for the user, otherwise returns a @@ -157,12 +157,11 @@ * 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 ++ (nullable OFURL *)temporaryDirectoryURL; /** * @brief Returns the vendor of the CPU. * * If the vendor could not be determined, `nil` is returned instead. Index: src/OFSystemInfo.m ================================================================== --- src/OFSystemInfo.m +++ src/OFSystemInfo.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -24,31 +24,39 @@ #include "platform.h" #ifdef HAVE_SYS_UTSNAME_H # include #endif -#if defined(OF_MACOS) || defined(OF_NETBSD) +#if defined(OF_MACOS) || defined(OF_IOS) || defined(OF_NETBSD) # include #endif + +#ifdef OF_AMIGAOS +# include +# include +#endif #if defined(OF_AMIGAOS4) # include -# include #elif defined(OF_MORPHOS) # include -# include +#endif + +#ifdef OF_NINTENDO_SWITCH +# define id nx_id +# import +# undef nx_id #endif #import "OFSystemInfo.h" #import "OFApplication.h" #import "OFArray.h" #import "OFDictionary.h" #import "OFLocale.h" #import "OFOnce.h" #import "OFString.h" - -#import "OFNotImplementedException.h" +#import "OFURL.h" #if defined(OF_MACOS) || defined(OF_IOS) # ifdef HAVE_SYSDIR_H # include # endif @@ -212,16 +220,14 @@ 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_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; @@ -232,10 +238,22 @@ operatingSystemVersion = [[OFString alloc] initWithCString: utsname.release encoding: [OFLocale encoding]]; #endif } + +#ifdef OF_NINTENDO_SWITCH +static OFURL *tmpFSURL = nil; + +static void +mountTmpFS(void) +{ + if (R_SUCCEEDED(fsdevMountTemporaryStorage("tmpfs"))) + tmpFSURL = [[OFURL alloc] initFileURLWithPath: @"tmpfs:/" + isDirectory: true]; +} +#endif #if defined(OF_X86_64) || defined(OF_X86) static OF_INLINE struct X86Regs OF_CONST_FUNC x86CPUID(uint32_t eax, uint32_t ecx) { @@ -318,16 +336,16 @@ + (OFString *)ObjFWVersion { return @PACKAGE_VERSION; } -+ (unsigned int)ObjFWVersionMajor ++ (unsigned short)ObjFWVersionMajor { return OBJFW_VERSION_MAJOR; } -+ (unsigned int)ObjFWVersionMinor ++ (unsigned short)ObjFWVersionMinor { return OBJFW_VERSION_MINOR; } + (OFString *)operatingSystemName @@ -344,13 +362,13 @@ OFOnce(&onceControl, initOperatingSystemVersion); return operatingSystemVersion; } -#ifdef OF_HAVE_FILES -+ (OFString *)userDataPath ++ (OFURL *)userDataURL { +#ifdef OF_HAVE_FILES # if defined(OF_MACOS) || defined(OF_IOS) char pathC[PATH_MAX]; OFMutableString *path; # ifdef HAVE_SYSDIR_START_SEARCH_PATH_ENUMERATION @@ -359,23 +377,19 @@ 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 - exceptionWithSelector: _cmd - object: self]; + return nil; } else { # endif NSSearchPathEnumerationState state; state = NSStartSearchPathEnumeration( NSApplicationSupportDirectory, NSUserDomainMask); if (NSGetNextSearchPathEnumeration(state, pathC) == 0) - @throw [OFNotImplementedException - exceptionWithSelector: _cmd - object: self]; + return nil; # ifdef HAVE_SYSDIR_START_SEARCH_PATH_ENUMERATION } # endif path = [OFMutableString stringWithUTF8String: pathC]; @@ -382,67 +396,69 @@ if ([path hasPrefix: @"~"]) { OFDictionary *env = [OFApplication environment]; OFString *home; if ((home = [env objectForKey: @"HOME"]) == nil) - @throw [OFNotImplementedException - exceptionWithSelector: _cmd - object: self]; + return nil; [path deleteCharactersInRange: OFRangeMake(0, 1)]; [path prependString: home]; } [path makeImmutable]; - return path; + return [OFURL fileURLWithPath: path isDirectory: true]; # elif defined(OF_WINDOWS) OFDictionary *env = [OFApplication environment]; OFString *appData; if ((appData = [env objectForKey: @"APPDATA"]) == nil) - @throw [OFNotImplementedException exceptionWithSelector: _cmd - object: self]; + return nil; - return appData; + return [OFURL fileURLWithPath: appData isDirectory: true]; # elif defined(OF_HAIKU) char pathC[PATH_MAX]; if (find_directory(B_USER_SETTINGS_DIRECTORY, 0, false, pathC, PATH_MAX) != B_OK) - @throw [OFNotImplementedException exceptionWithSelector: _cmd - object: self]; + return nil; - return [OFString stringWithUTF8String: pathC]; + return [OFURL fileURLWithPath: [OFString stringWithUTF8String: pathC] + isDirectory: true]; # elif defined(OF_AMIGAOS) - return @"PROGDIR:"; + return [OFURL fileURLWithPath: @"PROGDIR:" isDirectory: true]; # else OFDictionary *env = [OFApplication environment]; OFString *var; + OFURL *URL; void *pool; if ((var = [env objectForKey: @"XDG_DATA_HOME"]) != nil && var.length > 0) - return var; + return [OFURL fileURLWithPath: var isDirectory: true]; if ((var = [env objectForKey: @"HOME"]) == nil) - @throw [OFNotImplementedException exceptionWithSelector: _cmd - object: self]; + return nil; pool = objc_autoreleasePoolPush(); - var = [[OFString pathWithComponents: [OFArray arrayWithObjects: - var, @".local", @"share", nil]] retain]; + var = [OFString pathWithComponents: [OFArray arrayWithObjects: + var, @".local", @"share", nil]]; + URL = [[OFURL alloc] initFileURLWithPath: var isDirectory: true]; objc_autoreleasePoolPop(pool); - return [var autorelease]; + return [URL autorelease]; # endif +#else + return nil; +#endif } -+ (OFString *)userConfigPath ++ (OFURL *)userConfigURL { +#ifdef OF_HAVE_FILES # if defined(OF_MACOS) || defined(OF_IOS) char pathC[PATH_MAX]; OFMutableString *path; # ifdef HAVE_SYSDIR_START_SEARCH_PATH_ENUMERATION @@ -450,23 +466,19 @@ 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 - object: self]; + return nil; } else { # endif NSSearchPathEnumerationState state; state = NSStartSearchPathEnumeration(NSLibraryDirectory, NSUserDomainMask); if (NSGetNextSearchPathEnumeration(state, pathC) == 0) - @throw [OFNotImplementedException - exceptionWithSelector: _cmd - object: self]; + return nil; # ifdef HAVE_SYSDIR_START_SEARCH_PATH_ENUMERATION } # endif path = [OFMutableString stringWithUTF8String: pathC]; @@ -473,109 +485,134 @@ if ([path hasPrefix: @"~"]) { OFDictionary *env = [OFApplication environment]; OFString *home; if ((home = [env objectForKey: @"HOME"]) == nil) - @throw [OFNotImplementedException - exceptionWithSelector: _cmd - object: self]; + return nil; [path deleteCharactersInRange: OFRangeMake(0, 1)]; [path prependString: home]; } [path appendString: @"/Preferences"]; [path makeImmutable]; - return path; + return [OFURL fileURLWithPath: path isDirectory: true]; # elif defined(OF_WINDOWS) OFDictionary *env = [OFApplication environment]; OFString *appData; if ((appData = [env objectForKey: @"APPDATA"]) == nil) - @throw [OFNotImplementedException exceptionWithSelector: _cmd - object: self]; + return nil; - return appData; + return [OFURL fileURLWithPath: appData isDirectory: true]; # elif defined(OF_HAIKU) char pathC[PATH_MAX]; if (find_directory(B_USER_SETTINGS_DIRECTORY, 0, false, pathC, PATH_MAX) != B_OK) - @throw [OFNotImplementedException exceptionWithSelector: _cmd - object: self]; + return nil; - return [OFString stringWithUTF8String: pathC]; + return [OFURL fileURLWithPath: [OFString stringWithUTF8String: pathC] + isDirectory: true]; # elif defined(OF_AMIGAOS) - return @"PROGDIR:"; + return [OFURL fileURLWithPath: @"PROGDIR:" isDirectory: true]; # else OFDictionary *env = [OFApplication environment]; OFString *var; if ((var = [env objectForKey: @"XDG_CONFIG_HOME"]) != nil && var.length > 0) - return var; + return [OFURL fileURLWithPath: var isDirectory: true]; if ((var = [env objectForKey: @"HOME"]) == nil) - @throw [OFNotImplementedException exceptionWithSelector: _cmd - object: self]; + return nil; + + var = [var stringByAppendingPathComponent: @".config"]; - return [var stringByAppendingPathComponent: @".config"]; + return [OFURL fileURLWithPath: var isDirectory: true]; # endif +#else + return nil; +#endif } -+ (OFString *)temporaryDirectoryPath ++ (OFURL *)temporaryDirectoryURL { +#ifdef OF_HAVE_FILES # if defined(OF_MACOS) || defined(OF_IOS) char buffer[PATH_MAX]; size_t length; + OFString *path; if ((length = confstr(_CS_DARWIN_USER_TEMP_DIR, buffer, PATH_MAX)) == 0) - return @"/tmp"; + return [OFURL fileURLWithPath: @"/tmp" isDirectory: true]; - return [OFString stringWithCString: buffer + path = [OFString stringWithCString: buffer encoding: [OFLocale encoding] length: length - 1]; + + return [OFURL fileURLWithPath: path isDirectory: true]; # elif defined(OF_WINDOWS) + OFString *path; + if ([self isWindowsNT]) { wchar_t buffer[PATH_MAX]; if (!GetTempPathW(PATH_MAX, buffer)) return nil; - return [OFString stringWithUTF16String: buffer]; + path = [OFString stringWithUTF16String: buffer]; } else { char buffer[PATH_MAX]; if (!GetTempPathA(PATH_MAX, buffer)) return nil; - return [OFString stringWithCString: buffer + path = [OFString stringWithCString: buffer encoding: [OFLocale encoding]]; } + + return [OFURL fileURLWithPath: path isDirectory: true]; # elif defined(OF_HAIKU) char pathC[PATH_MAX]; if (find_directory(B_SYSTEM_TEMP_DIRECTORY, 0, false, pathC, PATH_MAX) != B_OK) - @throw [OFNotImplementedException exceptionWithSelector: _cmd - object: self]; + return nil; - return [OFString stringWithUTF8String: pathC]; + return [OFURL fileURLWithPath: [OFString stringWithUTF8String: pathC] + isDirectory: true]; # elif defined(OF_AMIGAOS) - return @"T:"; + return [OFURL fileURLWithPath: @"T:" isDirectory: true]; +# elif defined(OF_MSDOS) + OFString *path = [[OFApplication environment] objectForKey: @"TEMP"]; + + if (path == nil) + return nil; + + return [OFURL fileURLWithPath: path isDirectory: true]; +# elif defined(OF_MINT) + return [OFURL fileURLWithPath: @"u:\\tmp" isDirectory: true]; +# elif defined(OF_NINTENDO_SWITCH) + static OFOnceControl onceControl = OFOnceControlInitValue; + OFOnce(&onceControl, mountTmpFS); + + return tmpFSURL; # else OFString *path = [[OFApplication environment] objectForKey: @"XDG_RUNTIME_DIR"]; if (path != nil) - return path; + return [OFURL fileURLWithPath: path]; - return @"/tmp"; + return [OFURL fileURLWithPath: @"/tmp"]; # endif -} +#else + return nil; #endif +} + (OFString *)CPUVendor { #if (defined(OF_X86_64) || defined(OF_X86)) && defined(__GNUC__) struct X86Regs regs = x86CPUID(0, 0); @@ -589,33 +626,49 @@ 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 { #if (defined(OF_X86_64) || defined(OF_X86)) && defined(__GNUC__) + struct X86Regs regs = x86CPUID(0x80000000, 0); uint32_t buffer[12]; size_t i; + if (regs.eax < 0x80000004) + return nil; + i = 0; for (uint32_t eax = 0x80000002; eax <= 0x80000004; eax++) { - struct X86Regs regs = x86CPUID(eax, 0); - + regs = x86CPUID(eax, 0); buffer[i++] = regs.eax; buffer[i++] = regs.ebx; buffer[i++] = regs.ecx; buffer[i++] = regs.edx; } return [OFString stringWithCString: (char *)buffer encoding: OFStringEncodingASCII]; +#elif defined(OF_MACOS) || defined(OF_IOS) + char buffer[128]; + size_t length = sizeof(buffer); + + if (sysctlbyname("machdep.cpu.brand_string", &buffer, &length, + NULL, 0) != 0) + return nil; + + return [OFString stringWithCString: buffer + encoding: [OFLocale encoding] + length: length]; #elif defined(OF_AMIGAOS4) CONST_STRPTR model, version; GetCPUInfoTags(GCIT_ModelString, &model, GCIT_VersionString, &version, TAG_END); @@ -623,10 +676,23 @@ 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 } Index: src/OFTCPSocket.h ================================================================== --- src/OFTCPSocket.h +++ src/OFTCPSocket.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -144,27 +144,27 @@ * @return The port to use as a SOCKS5 proxy when creating a new socket */ + (uint16_t)SOCKS5Port; /** - * @brief Connect the OFTCPSocket to the specified destination. + * @brief Connects the OFTCPSocket to the specified destination. * * @param host The host to connect to * @param port The port on the host to connect to */ - (void)connectToHost: (OFString *)host port: (uint16_t)port; /** - * @brief Asynchronously connect the OFTCPSocket to the specified destination. + * @brief Asynchronously connects the OFTCPSocket to the specified destination. * * @param host The host to connect to * @param port The port on the host to connect to */ - (void)asyncConnectToHost: (OFString *)host port: (uint16_t)port; /** - * @brief Asynchronously connect the OFTCPSocket to the specified destination. + * @brief Asynchronously connects the OFTCPSocket to the specified destination. * * @param host The host to connect to * @param port The port on the host to connect to * @param runLoopMode The run loop mode in which to perform the async connect */ @@ -172,11 +172,11 @@ port: (uint16_t)port runLoopMode: (OFRunLoopMode)runLoopMode; #ifdef OF_HAVE_BLOCKS /** - * @brief Asynchronously connect the OFTCPSocket to the specified destination. + * @brief Asynchronously connects the OFTCPSocket to the specified destination. * * @param host The host to connect to * @param port The port on the host to connect to * @param block The block to execute once the connection has been established */ @@ -183,11 +183,11 @@ - (void)asyncConnectToHost: (OFString *)host port: (uint16_t)port block: (OFTCPSocketAsyncConnectBlock)block; /** - * @brief Asynchronously connect the OFTCPSocket to the specified destination. + * @brief Asynchronously connects the OFTCPSocket to the specified destination. * * @param host The host to connect to * @param port The port on the host to connect to * @param runLoopMode The run loop mode in which to perform the async connect * @param block The block to execute once the connection has been established @@ -197,11 +197,11 @@ runLoopMode: (OFRunLoopMode)runLoopMode block: (OFTCPSocketAsyncConnectBlock)block; #endif /** - * @brief Bind the socket to the specified host and port. + * @brief Binds the socket to the specified host and port. * * @param host The host to bind to. Use `@"0.0.0.0"` for IPv4 or `@"::"` for * IPv6 to bind to all. * @param port The port to bind to. If the port is 0, an unused port will be * chosen, which can be obtained using the return value. @@ -208,14 +208,6 @@ * @return The port the socket was bound to */ - (uint16_t)bindToHost: (OFString *)host port: (uint16_t)port; @end -#ifdef __cplusplus -extern "C" { -#endif -extern Class _Nullable OFTLSSocketClass; -#ifdef __cplusplus -} -#endif - OF_ASSUME_NONNULL_END Index: src/OFTCPSocket.m ================================================================== --- src/OFTCPSocket.m +++ src/OFTCPSocket.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -51,12 +51,10 @@ #import "OFSetOptionFailedException.h" static const OFRunLoopMode connectRunLoopMode = @"OFTCPSocketConnectRunLoopMode"; -Class OFTLSSocketClass = Nil; - static OFString *defaultSOCKS5Host = nil; static uint16_t defaultSOCKS5Port = 1080; @interface OFTCPSocket () @end @@ -143,11 +141,12 @@ #endif if (_socket != OFInvalidSocketHandle) @throw [OFAlreadyConnectedException exceptionWithSocket: self]; - if ((_socket = socket(address->sockaddr.sockaddr.sa_family, + if ((_socket = socket( + ((struct sockaddr *)&address->sockaddr)->sa_family, SOCK_STREAM | SOCK_CLOEXEC, 0)) == OFInvalidSocketHandle) { *errNo = OFSocketErrNo(); return false; } @@ -164,11 +163,11 @@ { if (_socket == OFInvalidSocketHandle) @throw [OFNotOpenException exceptionWithObject: self]; /* Cast needed for AmigaOS, where the argument is declared non-const */ - if (connect(_socket, (struct sockaddr *)&address->sockaddr.sockaddr, + if (connect(_socket, (struct sockaddr *)&address->sockaddr, address->length) != 0) { *errNo = OFSocketErrNo(); return false; } @@ -187,26 +186,26 @@ id delegate = _delegate; OFTCPSocketConnectDelegate *connectDelegate = [[[OFTCPSocketConnectDelegate alloc] init] autorelease]; OFRunLoop *runLoop = [OFRunLoop currentRunLoop]; - self.delegate = connectDelegate; + _delegate = connectDelegate; [self asyncConnectToHost: host port: port runLoopMode: connectRunLoopMode]; while (!connectDelegate->_done) [runLoop runMode: connectRunLoopMode beforeDate: nil]; /* Cleanup */ [runLoop runMode: connectRunLoopMode beforeDate: [OFDate date]]; + + _delegate = delegate; if (connectDelegate->_exception != nil) @throw connectDelegate->_exception; - self.delegate = delegate; - objc_autoreleasePoolPop(pool); } - (void)asyncConnectToHost: (OFString *)host port: (uint16_t)port { @@ -318,11 +317,12 @@ addressFamily: OFSocketAddressFamilyAny]; address = *(OFSocketAddress *)[socketAddresses itemAtIndex: 0]; OFSocketAddressSetPort(&address, port); - if ((_socket = socket(address.sockaddr.sockaddr.sa_family, + if ((_socket = socket( + ((struct sockaddr *)&address.sockaddr)->sa_family, SOCK_STREAM | SOCK_CLOEXEC, 0)) == OFInvalidSocketHandle) @throw [OFBindFailedException exceptionWithHost: host port: port socket: self @@ -339,11 +339,11 @@ (char *)&one, (socklen_t)sizeof(one)); #if defined(OF_HPUX) || defined(OF_WII) || defined(OF_NINTENDO_3DS) if (port != 0) { #endif - if (bind(_socket, &address.sockaddr.sockaddr, + if (bind(_socket, (struct sockaddr *)&address.sockaddr, address.length) != 0) { int errNo = OFSocketErrNo(); closesocket(_socket); _socket = OFInvalidSocketHandle; @@ -362,11 +362,12 @@ while (rnd < 1024) rnd = (uint16_t)rand(); OFSocketAddressSetPort(&address, rnd); - if ((ret = bind(_socket, &address.sockaddr.sockaddr, + if ((ret = bind(_socket, + (struct sockaddr *)&address.sockaddr, address.length)) == 0) { port = rnd; break; } @@ -393,11 +394,11 @@ #if !defined(OF_HPUX) && !defined(OF_WII) && !defined(OF_NINTENDO_3DS) memset(&address, 0, sizeof(address)); address.length = (socklen_t)sizeof(address.sockaddr); - if (OFGetSockName(_socket, &address.sockaddr.sockaddr, + if (OFGetSockName(_socket, (struct sockaddr *)&address.sockaddr, &address.length) != 0) { int errNo = OFSocketErrNo(); closesocket(_socket); _socket = OFInvalidSocketHandle; @@ -406,17 +407,18 @@ port: port socket: self errNo: errNo]; } - if (address.sockaddr.sockaddr.sa_family == AF_INET) + switch (((struct sockaddr *)&address.sockaddr)->sa_family) { + case AF_INET: return OFFromBigEndian16(address.sockaddr.in.sin_port); # ifdef OF_HAVE_IPV6 - else if (address.sockaddr.sockaddr.sa_family == AF_INET6) + case AF_INET6: return OFFromBigEndian16(address.sockaddr.in6.sin6_port); # endif - else { + default: closesocket(_socket); _socket = OFInvalidSocketHandle; @throw [OFBindFailedException exceptionWithHost: host port: port Index: src/OFTCPSocketSOCKS5Connector.h ================================================================== --- src/OFTCPSocketSOCKS5Connector.h +++ src/OFTCPSocketSOCKS5Connector.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFTCPSocketSOCKS5Connector.m ================================================================== --- src/OFTCPSocketSOCKS5Connector.m +++ src/OFTCPSocketSOCKS5Connector.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFTLSKey.h ================================================================== --- src/OFTLSKey.h +++ src/OFTLSKey.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFTLSKey.m ================================================================== --- src/OFTLSKey.m +++ src/OFTLSKey.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in DELETED src/OFTLSSocket.h Index: src/OFTLSSocket.h ================================================================== --- src/OFTLSSocket.h +++ src/OFTLSSocket.h @@ -1,184 +0,0 @@ -/* - * Copyright (c) 2008-2021 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#import "OFObject.h" - -OF_ASSUME_NONNULL_BEGIN - -@class OFString; -@class OFDictionary OF_GENERIC(KeyType, ObjectType); -@protocol OFTLSSocket; - -/** - * @protocol OFTLSSocketDelegate OFTLSSocket.h ObjFW/OFTLSSocket.h - * - * @brief A delegate for classes implementing the OFTLSSocket protocol. - */ -@protocol OFTLSSocketDelegate -@optional -/** - * @brief This callback is called when the TLS socket wants to know if it - * should accept the received certificate. - * - * @note This is only used to verify certain fields of a certificate to allow - * for protocol specific verification. The certificate chain is verified - * using the specified CAs, or the system's CAs if no CAs have been - * specified. - * - * @param socket The socket which wants to know if it should accept the received - * certificate - * @param certificate A dictionary with the fields of the received certificate - * @return Whether the TLS socket should accept the received certificate chain - */ -- (bool)socket: (id )socket - shouldAcceptCertificate: (OFDictionary *)certificate; -@end - -/** - * @protocol OFTLSSocket OFTLSSocket.h ObjFW/OFTLSSocket.h - * - * @brief A protocol that should be implemented by 3rd-party libraries - * implementing TLS. - */ -@protocol OFTLSSocket -/** - * @brief The delegate for the TLS socket. - */ -@property OF_NULLABLE_PROPERTY (assign, nonatomic) - id delegate; - -/** - * @brief The path to the X.509 certificate file to use. - */ -@property OF_NULLABLE_PROPERTY (copy, nonatomic) OFString *certificateFile; - -/** - * @brief The path to the PKCS#8 private key file to use. - */ -@property OF_NULLABLE_PROPERTY (copy, nonatomic) OFString *privateKeyFile; - -/** - * @brief The passphrase to decrypt the PKCS#8 private key file. - * - * @warning You have to ensure that this is in secure memory protected from - * swapping! This is also the reason why this is not an OFString. - */ -@property OF_NULLABLE_PROPERTY (assign, nonatomic) - const char *privateKeyPassphrase; - -/** - * @brief Whether certificates are verified. - * - * The default is enabled. - */ -@property (nonatomic) bool verifiesCertificates; - -/** - * @brief Initializes the TLS socket with the specified TCP socket as its - * underlying socket. - * - * @param socket The TCP socket to use as underlying socket - */ -- (instancetype)initWithSocket: (OFTCPSocket *)socket; - -/** - * @brief Initiates the TLS handshake. - * - * @note This is only useful if you used @ref initWithSocket: to start TLS on - * a TCP socket which is already connected! - * - * @param host The host to expect for certificate verification. - * May be `nil` if certificate verification is disabled. - */ -- (void)startTLSWithExpectedHost: (nullable OFString *)host; - -/** - * @brief Sets the path to the X.509 certificate file to use for the specified - * SNI host. - * - * @param SNIHost The SNI host for which the path of the X.509 certificate file - * should be set - * - * @param certificateFile The path to the X.509 certificate file - */ -- (void)setCertificateFile: (OFString *)certificateFile - forSNIHost: (OFString *)SNIHost; - -/** - * @brief Returns the path of the X.509 certificate file used by the TLS socket - * for the specified SNI host. - * - * @param SNIHost The SNI host for which the path of the X.509 certificate file - * should be returned - * - * @return The path of the X.509 certificate file used by the TLS socket for - * the specified SNI host - */ -- (nullable OFString *)certificateFileForSNIHost: (OFString *)SNIHost; - -/** - * @brief Sets the path to the PKCS#8 private key file to use for the specified - * SNI host. - * - * @param privateKeyFile The path to the PKCS#8 private key file - * @param SNIHost The SNI host for which the path to the PKCS#8 private key - * file should be set - */ -- (void)setPrivateKeyFile: (OFString *)privateKeyFile - forSNIHost: (OFString *)SNIHost; - -/** - * @brief Returns the path of the PKCS#8 private key file used by the TLS - * socket for the specified SNI host. - * - * @param SNIHost The SNI host for which the path of the PKCS#8 private key - * file should be returned - * - * @return The path of the PKCS#8 private key file used by the TLS socket for - * the specified SNI host - */ -- (nullable OFString *)privateKeyFileForSNIHost: (OFString *)SNIHost; - -/** - * @brief Sets the passphrase to decrypt the PKCS#8 private key file for the - * specified SNI host. - * - * @warning You have to ensure that this is in secure memory protected from - * swapping! This is also the reason why this is not an OFString. - * - * @param privateKeyPassphrase The passphrase to decrypt the PKCS#8 private - * key file for the specified SNI host - * @param SNIHost The SNI host for which the passphrase to decrypt the PKCS#8 - * private key file should be set - */ -- (void)setPrivateKeyPassphrase: (const char *)privateKeyPassphrase - forSNIHost: (OFString *)SNIHost; - -/** - * @brief Returns the passphrase to decrypt the PKCS#8 private key file for the - * specified SNI host. - * - * @warning You should not copy this to insecure memory which is swappable! - * - * @param SNIHost The SNI host for which the passphrase to decrypt the PKCS#8 - * private key file should be returned - * - * @return The passphrase to decrypt the PKCS#8 private key file for the - * specified SNI host - */ -- (nullable const char *)privateKeyPassphraseForSNIHost: (OFString *)SNIHost; -@end - -OF_ASSUME_NONNULL_END ADDED src/OFTLSStream.h Index: src/OFTLSStream.h ================================================================== --- src/OFTLSStream.h +++ src/OFTLSStream.h @@ -0,0 +1,176 @@ +/* + * Copyright (c) 2008-2022 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#import "OFStream.h" +#import "OFRunLoop.h" + +OF_ASSUME_NONNULL_BEGIN + +/** @file */ + +@class OFTLSStream; + +/** + * @brief An enum representing an error of an OFTLSStream. + */ +typedef enum { + /** @brief An unknown error. */ + OFTLSStreamErrorCodeUnknown, + /** @brief Initialization of the TLS context failed. */ + OFTLSStreamErrorCodeInitializationFailed +} OFTLSStreamErrorCode; + +/** + * @protocol OFTLSStreamDelegate OFTLSStream.h ObjFW/OFTLSStream.h + * + * A delegate for OFTLSStream. + */ +@protocol OFTLSStreamDelegate +/** + * @brief A method which is called when a TLS stream performed the client + * handshake. + * + * @param stream The TLS stream which performed the handshake + * @param host The host for which the handshake was performed + * @param exception An exception that occurred during the handshake, or nil on + * success + */ +- (void)stream: (OFTLSStream *)stream + didPerformClientHandshakeWithHost: (OFString *)host + exception: (nullable id)exception; +@end + +/** + * @class OFTLSStream OFTLSStream.h ObjFW/OFTLSStream.h + * + * @brief A class that provides Transport Layer Security on top of a stream. + * + * This class is a class cluster and returns a suitable OFTLSStream subclass, + * if available. + * + * Subclasses need to override @ref lowlevelReadIntoBuffer:length:, + * @ref lowlevelWriteBuffer:length: and + * @ref asyncPerformClientHandshakeWithHost:runLoopMode:. The method + * @ref hasDataInReadBuffer should be overridden to return `true` if the TLS + * stream has cached unprocessed data internally, while returning + * `self.underlyingStream.hasDataInReadBuffer` if it does not have any + * unprocessed data. In order to get access to the underlying stream, + * @ref underlyingStream can be used. + */ +@interface OFTLSStream: OFStream +{ + OFStream + *_underlyingStream; + bool _verifiesCertificates; + OF_RESERVE_IVARS(OFTLSStream, 4) +} + +/** + * @brief The underlying stream. + */ +@property (readonly, nonatomic) OFStream *underlyingStream; + +/** + * @brief The delegate for asynchronous operations on the stream. + * + * @note The delegate is retained for as long as asynchronous operations are + * still ongoing. + */ +@property OF_NULLABLE_PROPERTY (assign, nonatomic) + id delegate; + +/** + * @brief Whether certificates are verified. Default is true. + */ +@property (nonatomic) bool verifiesCertificates; + +- (instancetype)init OF_UNAVAILABLE; + +/** + * @brief Creates a new TLS stream with the specified stream as its underlying + * stream. + * + * @param stream The stream to use as underlying stream. Must not be closed + * before the TLS stream is closed. + * @return A new, autoreleased TLS stream + */ ++ (instancetype)streamWithStream: (OFStream *)stream; + +/** + * @brief Initializes the TLS stream with the specified stream as its + * underlying stream. + * + * @param stream The stream to use as underlying stream. Must not be closed + * before the TLS stream is closed. + * @return An initialized TLS stream + */ +- (instancetype)initWithStream: (OFStream *)stream + OF_DESIGNATED_INITIALIZER; + +/** + * @brief Asynchronously performs the TLS client handshake for the specified + * host and calls the delegate afterwards. + * + * @param host The host to perform the handshake with + */ +- (void)asyncPerformClientHandshakeWithHost: (OFString *)host; + +/** + * @brief Asynchronously performs the TLS client handshake for the specified + * host and calls the delegate afterwards. + * + * @param host The host to perform the handshake with + * @param runLoopMode The run loop mode in which to perform the async handshake + */ +- (void)asyncPerformClientHandshakeWithHost: (OFString *)host + runLoopMode: (OFRunLoopMode)runLoopMode; + +/** + * @brief Performs the TLS client handshake for the specified host. + * + * @param host The host to perform the handshake with + */ +- (void)performClientHandshakeWithHost: (OFString *)host; +@end + +#ifdef __cplusplus +extern "C" { +#endif +/** + * @brief The implementation for OFTLSStream to use. + * + * This can be set to a class that is always used for OFTLSStream. This is + * useful to either force a specific implementation or use one that ObjFW does + * not know about. + */ +extern Class OFTLSStreamImplementation; + +/** + * @brief Returns a string description for the TLS stream error code. + * + * @param errorCode The error code to return the description for + * @return A string description for the TLS stream error code + */ +extern OFString *OFTLSStreamErrorCodeDescription( + OFTLSStreamErrorCode errorCode); +#ifdef __cplusplus +} +#endif + +OF_ASSUME_NONNULL_END ADDED src/OFTLSStream.m Index: src/OFTLSStream.m ================================================================== --- src/OFTLSStream.m +++ src/OFTLSStream.m @@ -0,0 +1,202 @@ +/* + * Copyright (c) 2008-2022 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 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 "OFTLSStream.h" +#import "OFDate.h" + +#import "OFNotImplementedException.h" +#import "OFTLSHandshakeFailedException.h" + +@interface OFTLSStreamHandshakeDelegate: OFObject +{ +@public + bool _done; + id _exception; +} +@end + +Class OFTLSStreamImplementation = Nil; +static const OFRunLoopMode handshakeRunLoopMode = + @"OFTLSStreamHandshakeRunLoopMode"; + +/* + * References to exceptions. This is needed because they are only used by + * subclasses that are in a different library. + */ +void +_references_to_exceptions_of_OFTLSStream(void) +{ + _OFTLSHandshakeFailedException_reference = 1; +} + +OFString * +OFTLSStreamErrorCodeDescription(OFTLSStreamErrorCode errorCode) +{ + switch (errorCode) { + case OFTLSStreamErrorCodeInitializationFailed: + return @"Initialization of TLS context failed"; + default: + return @"Unknown error"; + } +} + +@implementation OFTLSStreamHandshakeDelegate +- (void)dealloc +{ + [_exception release]; + + [super dealloc]; +} + +- (void)stream: (OFTLSStream *)stream + didPerformClientHandshakeWithHost: (OFString *)host + exception: (id)exception +{ + _done = true; + _exception = [exception retain]; +} +@end + +@implementation OFTLSStream +@synthesize underlyingStream = _underlyingStream; +@dynamic delegate; +@synthesize verifiesCertificates = _verifiesCertificates; + ++ (instancetype)alloc +{ + if (self == [OFTLSStream class]) { + if (OFTLSStreamImplementation != Nil) + return [OFTLSStreamImplementation alloc]; + + @throw [OFNotImplementedException exceptionWithSelector: _cmd + object: self]; + } + + return [super alloc]; +} + ++ (instancetype)streamWithStream: (OFStream *)stream +{ + return [[[self alloc] initWithStream: stream] autorelease]; +} + +- (instancetype)init +{ + OF_INVALID_INIT_METHOD +} + +- (instancetype)initWithStream: (OFStream *)stream +{ + self = [super init]; + + @try { + _underlyingStream = [stream retain]; + _verifiesCertificates = true; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (void)dealloc +{ + [_underlyingStream release]; + + [super dealloc]; +} + +- (void)close +{ + [_underlyingStream release]; + _underlyingStream = nil; + + [super close]; +} + +- (size_t)lowlevelReadIntoBuffer: (void *)buffer length: (size_t)length +{ + OF_UNRECOGNIZED_SELECTOR +} + +- (size_t)lowlevelWriteBuffer: (const void *)buffer length: (size_t)length +{ + OF_UNRECOGNIZED_SELECTOR +} + +- (bool)hasDataInReadBuffer +{ + return (super.hasDataInReadBuffer || + _underlyingStream.hasDataInReadBuffer); +} + +- (bool)lowlevelIsAtEndOfStream +{ + return _underlyingStream.atEndOfStream; +} + +- (int)fileDescriptorForReading +{ + return _underlyingStream.fileDescriptorForReading; +} + +- (int)fileDescriptorForWriting +{ + return _underlyingStream.fileDescriptorForWriting; +} + +- (void)asyncPerformClientHandshakeWithHost: (OFString *)host +{ + [self asyncPerformClientHandshakeWithHost: host + runLoopMode: OFDefaultRunLoopMode]; +} + +- (void)asyncPerformClientHandshakeWithHost: (OFString *)host + runLoopMode: (OFRunLoopMode)runLoopMode +{ + OF_UNRECOGNIZED_SELECTOR +} + +- (void)performClientHandshakeWithHost: (OFString *)host +{ + void *pool = objc_autoreleasePoolPush(); + id delegate = _delegate; + OFTLSStreamHandshakeDelegate *handshakeDelegate = + [[[OFTLSStreamHandshakeDelegate alloc] init] autorelease]; + OFRunLoop *runLoop = [OFRunLoop currentRunLoop]; + + _delegate = handshakeDelegate; + [self asyncPerformClientHandshakeWithHost: host + runLoopMode: handshakeRunLoopMode]; + + while (!handshakeDelegate->_done) + [runLoop runMode: handshakeRunLoopMode beforeDate: nil]; + + /* Cleanup */ + [runLoop runMode: handshakeRunLoopMode beforeDate: [OFDate date]]; + + _delegate = delegate; + + if (handshakeDelegate->_exception != nil) + @throw handshakeDelegate->_exception; + + objc_autoreleasePoolPop(pool); +} +@end Index: src/OFTarArchive.h ================================================================== --- src/OFTarArchive.h +++ src/OFTarArchive.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFTarArchive.m ================================================================== --- src/OFTarArchive.m +++ src/OFTarArchive.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -12,10 +12,12 @@ * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this * file. */ #include "config.h" + +#include #import "OFTarArchive.h" #import "OFTarArchiveEntry.h" #import "OFTarArchiveEntry+Private.h" #import "OFDate.h" @@ -427,29 +429,32 @@ [super dealloc]; } - (size_t)lowlevelWriteBuffer: (const void *)buffer length: (size_t)length { - size_t bytesWritten; - if (_stream == nil) @throw [OFNotOpenException exceptionWithObject: self]; if ((uint64_t)length > _toWrite) @throw [OFOutOfRangeException exception]; @try { - bytesWritten = [_stream writeBuffer: buffer - length: length]; + [_stream writeBuffer: buffer length: length]; } @catch (OFWriteFailedException *e) { + OFEnsure(e.bytesWritten <= length); + _toWrite -= e.bytesWritten; + + if (e.errNo == EWOULDBLOCK || e.errNo == EAGAIN) + return e.bytesWritten; + @throw e; } - _toWrite -= bytesWritten; + _toWrite -= length; - return bytesWritten; + return length; } - (bool)lowlevelIsAtEndOfStream { if (_stream == nil) Index: src/OFTarArchiveEntry+Private.h ================================================================== --- src/OFTarArchiveEntry+Private.h +++ src/OFTarArchiveEntry+Private.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFTarArchiveEntry.h ================================================================== --- src/OFTarArchiveEntry.h +++ src/OFTarArchiveEntry.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFTarArchiveEntry.m ================================================================== --- src/OFTarArchiveEntry.m +++ src/OFTarArchiveEntry.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFThread+Private.h ================================================================== --- src/OFThread+Private.h +++ src/OFThread+Private.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFThread.h ================================================================== --- src/OFThread.h +++ src/OFThread.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFThread.m ================================================================== --- src/OFThread.m +++ src/OFThread.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -77,10 +77,15 @@ #ifdef OF_HAVE_THREADS # import "OFThreadJoinFailedException.h" # import "OFThreadStartFailedException.h" # import "OFThreadStillRunningException.h" #endif + +#ifdef OF_MINT +/* freemint-gcc does not have trunc() */ +# define trunc(x) ((int64_t)(x)) +#endif #if defined(OF_HAVE_THREADS) # import "OFTLSKey.h" # if defined(OF_AMIGAOS) && defined(OF_HAVE_SOCKETS) # import "OFSocket.h" DELETED src/OFThreadPool.h Index: src/OFThreadPool.h ================================================================== --- src/OFThreadPool.h +++ src/OFThreadPool.h @@ -1,116 +0,0 @@ -/* - * Copyright (c) 2008-2021 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#import "OFObject.h" - -OF_ASSUME_NONNULL_BEGIN - -/** @file */ - -#ifdef OF_HAVE_BLOCKS -/** - * @brief A block for a job which should be executed in a thread pool. - */ -typedef void (^OFThreadPoolBlock)(void); -#endif - -@class OFCondition; -@class OFList OF_GENERIC(ObjectType); -@class OFMutableArray OF_GENERIC(ObjectType); -@class OFThreadPoolJob; - -/** - * @class OFThreadPool OFThreadPool.h ObjFW/OFThreadPool.h - * - * @brief A class providing a pool of reusable threads. - * - * @note When the thread pool is released, all threads will terminate after - * they finish the job they are currently processing. - */ -OF_SUBCLASSING_RESTRICTED -@interface OFThreadPool: OFObject -{ - size_t _size; - OFMutableArray *_threads; - volatile int _count; -#ifdef OF_THREAD_POOL_M -@public -#endif - OFList *_queue; - OFCondition *_queueCondition; - volatile int _doneCount; - OFCondition *_countCondition; -} - -/** - * @brief The size of the thread pool. - */ -@property (readonly, nonatomic) size_t size; - -/** - * @brief Returns a new thread pool with one thread for each core in the system. - * - * @warning If for some reason the number of cores in the system could not be - * determined, the pool will only have one thread! - * - * @return A new thread pool with one thread for each core in the system - */ -+ (instancetype)threadPool; - -/** - * @brief Returns a new thread pool with the specified number of threads. - * - * @param size The number of threads for the pool - * @return A new thread pool with the specified number of threads - */ -+ (instancetype)threadPoolWithSize: (size_t)size; - -/** - * @brief Initializes an already allocated OFThreadPool with the specified - * number of threads. - * - * @param size The number of threads for the pool - * @return An initialized OFThreadPool with the specified number of threads - */ -- (instancetype)initWithSize: (size_t)size OF_DESIGNATED_INITIALIZER; - -/** - * @brief Execute the specified selector on the specified target with the - * specified object as soon as a thread is ready. - * - * @param target The target on which to perform the selector - * @param selector The selector to perform on the target - * @param object The object with which the selector is performed on the target - */ -- (void)dispatchWithTarget: (id)target - selector: (SEL)selector - object: (nullable id)object; - -#ifdef OF_HAVE_BLOCKS -/** - * @brief Executes the specified block as soon as a thread is ready. - * - * @param block The block to execute - */ -- (void)dispatchWithBlock: (OFThreadPoolBlock)block; -#endif - -/** - * @brief Waits until all jobs are done. - */ -- (void)waitUntilDone; -@end - -OF_ASSUME_NONNULL_END DELETED src/OFThreadPool.m Index: src/OFThreadPool.m ================================================================== --- src/OFThreadPool.m +++ src/OFThreadPool.m @@ -1,360 +0,0 @@ -/* - * Copyright (c) 2008-2021 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#include "config.h" - -#define OF_THREAD_POOL_M - -#import "OFThreadPool.h" -#import "OFArray.h" -#import "OFList.h" -#import "OFThread.h" -#import "OFCondition.h" -#import "OFSystemInfo.h" - -OF_DIRECT_MEMBERS -@interface OFThreadPoolJob: OFObject -{ - id _target; - SEL _selector; - id _object; -#ifdef OF_HAVE_BLOCKS - OFThreadPoolBlock _block; -#endif -} - -- (instancetype)initWithTarget: (id)target - selector: (SEL)selector - object: (id)object; -#ifdef OF_HAVE_BLOCKS -- (instancetype)initWithBlock: (OFThreadPoolBlock)block; -#endif -- (void)perform; -@end - -@implementation OFThreadPoolJob -- (instancetype)initWithTarget: (id)target - selector: (SEL)selector - object: (id)object -{ - self = [super init]; - - @try { - _target = [target retain]; - _selector = selector; - _object = [object retain]; - } @catch (id e) { - [self release]; - @throw e; - } - - return self; -} - -#ifdef OF_HAVE_BLOCKS -- (instancetype)initWithBlock: (OFThreadPoolBlock)block -{ - self = [super init]; - - @try { - _block = [block copy]; - } @catch (id e) { - [self release]; - @throw e; - } - - return self; -} -#endif - -- (void)dealloc -{ - [_target release]; - [_object release]; -#ifdef OF_HAVE_BLOCKS - [_block release]; -#endif - - [super dealloc]; -} - -- (void)perform -{ -#ifdef OF_HAVE_BLOCKS - if (_block != NULL) - _block(); - else -#endif - [_target performSelector: _selector withObject: _object]; -} -@end - -OF_DIRECT_MEMBERS -@interface OFThreadPoolThread: OFThread -{ - OFList *_queue; - OFCondition *_queueCondition, *_countCondition; -@public - volatile bool _terminate; - volatile int *_doneCount; -} - -+ (instancetype)threadWithThreadPool: (OFThreadPool *)threadPool; -- (instancetype)initWithThreadPool: (OFThreadPool *)threadPool; -@end - -@implementation OFThreadPoolThread -+ (instancetype)threadWithThreadPool: (OFThreadPool *)threadPool -{ - return [[(OFThreadPoolThread *)[self alloc] - initWithThreadPool: threadPool] autorelease]; -} - -- (instancetype)initWithThreadPool: (OFThreadPool *)threadPool -{ - self = [super init]; - - @try { - _queue = [threadPool->_queue retain]; - _queueCondition = [threadPool->_queueCondition retain]; - _countCondition = [threadPool->_countCondition retain]; - _doneCount = &threadPool->_doneCount; - } @catch (id e) { - [self release]; - @throw e; - } - - return self; -} - -- (void)dealloc -{ - [_queue release]; - [_queueCondition release]; - [_countCondition release]; - - [super dealloc]; -} - -- (id)main -{ - void *pool; - - if (_terminate) - return nil; - - pool = objc_autoreleasePoolPush(); - - for (;;) { - OFThreadPoolJob *job; - - [_queueCondition lock]; - @try { - OFListItem listItem; - - if (_terminate) { - objc_autoreleasePoolPop(pool); - return nil; - } - - listItem = _queue.firstListItem; - - while (listItem == NULL) { - [_queueCondition wait]; - - if (_terminate) { - objc_autoreleasePoolPop(pool); - return nil; - } - - listItem = _queue.firstListItem; - } - - job = [[OFListItemObject(listItem) retain] autorelease]; - [_queue removeListItem: listItem]; - } @finally { - [_queueCondition unlock]; - } - - if (_terminate) { - objc_autoreleasePoolPop(pool); - return nil; - } - - [job perform]; - - if (_terminate) { - objc_autoreleasePoolPop(pool); - return nil; - } - - objc_autoreleasePoolPop(pool); - pool = objc_autoreleasePoolPush(); - - [_countCondition lock]; - @try { - if (_terminate) { - objc_autoreleasePoolPop(pool); - return nil; - } - - (*_doneCount)++; - - [_countCondition signal]; - } @finally { - [_countCondition unlock]; - } - } -} -@end - -@implementation OFThreadPool -+ (instancetype)threadPool -{ - return [[[self alloc] init] autorelease]; -} - -+ (instancetype)threadPoolWithSize: (size_t)size -{ - return [[[self alloc] initWithSize: size] autorelease]; -} - -- (instancetype)init -{ - return [self initWithSize: [OFSystemInfo numberOfCPUs]]; -} - -- (instancetype)initWithSize: (size_t)size -{ - self = [super init]; - - @try { - _size = size; - _threads = [[OFMutableArray alloc] init]; - _queue = [[OFList alloc] init]; - _queueCondition = [[OFCondition alloc] init]; - _countCondition = [[OFCondition alloc] init]; - - for (size_t i = 0; i < size; i++) { - void *pool = objc_autoreleasePoolPush(); - - OFThreadPoolThread *thread = - [OFThreadPoolThread threadWithThreadPool: self]; - - [_threads addObject: thread]; - - objc_autoreleasePoolPop(pool); - } - - /* - * We need to start the threads in a separate loop to make sure - * _threads is not modified anymore to prevent a race condition. - */ - for (size_t i = 0; i < size; i++) - [[_threads objectAtIndex: i] start]; - } @catch (id e) { - [self release]; - @throw e; - } - - return self; -} - -- (void)dealloc -{ - [_queueCondition lock]; - @try { - [_countCondition lock]; - @try { - for (OFThreadPoolThread *thread in _threads) - thread->_terminate = true; - } @finally { - [_countCondition unlock]; - } - - [_queueCondition broadcast]; - } @finally { - [_queueCondition unlock]; - } - - [_threads release]; - [_queue release]; - [_queueCondition release]; - [_countCondition release]; - - [super dealloc]; -} - -- (void)of_dispatchJob: (OFThreadPoolJob *)job OF_DIRECT -{ - [_countCondition lock]; - _count++; - [_countCondition unlock]; - - [_queueCondition lock]; - @try { - [_queue appendObject: job]; - [_queueCondition signal]; - } @finally { - [_queueCondition unlock]; - } -} - -- (void)waitUntilDone -{ - for (;;) { - [_countCondition lock]; - @try { - if (_doneCount == _count) - return; - - [_countCondition wait]; - } @finally { - [_countCondition unlock]; - } - } -} - -- (void)dispatchWithTarget: (id)target - selector: (SEL)selector - object: (id)object -{ - OFThreadPoolJob *job = [[OFThreadPoolJob alloc] initWithTarget: target - selector: selector - object: object]; - @try { - [self of_dispatchJob: job]; - } @finally { - [job release]; - } -} - -#ifdef OF_HAVE_BLOCKS -- (void)dispatchWithBlock: (OFThreadPoolBlock)block -{ - OFThreadPoolJob *job = [[OFThreadPoolJob alloc] initWithBlock: block]; - @try { - [self of_dispatchJob: job]; - } @finally { - [job release]; - } -} -#endif - -- (size_t)size -{ - return _size; -} -@end Index: src/OFTimer+Private.h ================================================================== --- src/OFTimer+Private.h +++ src/OFTimer+Private.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFTimer.h ================================================================== --- src/OFTimer.h +++ src/OFTimer.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFTimer.m ================================================================== --- src/OFTimer.m +++ src/OFTimer.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -679,20 +679,45 @@ @"\tBlock: %@\n" @"\tValid: %s\n" @">", self.class, _fireDate, _interval, (_repeats ? "yes" : "no"), _block, (_valid ? "yes" : "no")]; - else + else { #endif - return [OFString stringWithFormat: + void *pool = objc_autoreleasePoolPush(); + OFString *objects = @"", *ret; + + if (_arguments >= 1) + objects = [objects stringByAppendingFormat: + @"\tObject: %@\n", _object1]; + if (_arguments >= 2) + objects = [objects stringByAppendingFormat: + @"\tObject: %@\n", _object2]; + if (_arguments >= 3) + objects = [objects stringByAppendingFormat: + @"\tObject: %@\n", _object3]; + if (_arguments >= 4) + objects = [objects stringByAppendingFormat: + @"\tObject: %@\n", _object4]; + + ret = [[OFString alloc] initWithFormat: @"<%@:\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")]; + _target, sel_getName(_selector), objects, + (_valid ? "yes" : "no")]; + + objc_autoreleasePoolPop(pool); + + return [ret autorelease]; +#ifdef OF_HAVE_BLOCKS + } +#endif } @end Index: src/OFTriple.h ================================================================== --- src/OFTriple.h +++ src/OFTriple.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFTriple.m ================================================================== --- src/OFTriple.m +++ src/OFTriple.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFUDPSocket+Private.h ================================================================== --- src/OFUDPSocket+Private.h +++ src/OFUDPSocket+Private.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFUDPSocket.h ================================================================== --- src/OFUDPSocket.h +++ src/OFUDPSocket.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFUDPSocket.m ================================================================== --- src/OFUDPSocket.m +++ src/OFUDPSocket.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -47,11 +47,12 @@ uint16_t port; #if SOCK_CLOEXEC == 0 && defined(HAVE_FCNTL) && defined(FD_CLOEXEC) int flags; #endif - if ((_socket = socket(address->sockaddr.sockaddr.sa_family, + if ((_socket = socket( + ((struct sockaddr *)&address->sockaddr)->sa_family, SOCK_DGRAM | SOCK_CLOEXEC | extraType, 0)) == OFInvalidSocketHandle) @throw [OFBindFailedException exceptionWithHost: OFSocketAddressString(address) port: OFSocketAddressPort(address) socket: self @@ -67,11 +68,11 @@ #endif #if defined(OF_HPUX) || defined(OF_WII) || defined(OF_NINTENDO_3DS) if (OFSocketAddressPort(address) != 0) { #endif - if (bind(_socket, &address->sockaddr.sockaddr, + if (bind(_socket, (struct sockaddr *)&address->sockaddr, address->length) != 0) { int errNo = OFSocketErrNo(); closesocket(_socket); _socket = OFInvalidSocketHandle; @@ -91,11 +92,12 @@ while (rnd < 1024) rnd = (uint16_t)rand(); OFSocketAddressSetPort(address, rnd); - if ((ret = bind(_socket, &address->sockaddr.sockaddr, + if ((ret = bind(_socket, + (struct sockaddr *)&address->sockaddr, address->length)) == 0) break; if (OFSocketErrNo() != EADDRINUSE) { int errNo = OFSocketErrNo(); @@ -122,11 +124,11 @@ #if !defined(OF_HPUX) && !defined(OF_WII) && !defined(OF_NINTENDO_3DS) memset(address, 0, sizeof(*address)); address->length = (socklen_t)sizeof(address->sockaddr); - if (OFGetSockName(_socket, &address->sockaddr.sockaddr, + if (OFGetSockName(_socket, (struct sockaddr *)&address->sockaddr, &address->length) != 0) { int errNo = OFSocketErrNo(); closesocket(_socket); _socket = OFInvalidSocketHandle; @@ -136,17 +138,18 @@ port: OFSocketAddressPort(address) socket: self errNo: errNo]; } - if (address->sockaddr.sockaddr.sa_family == AF_INET) + switch (((struct sockaddr *)&address->sockaddr)->sa_family) { + case AF_INET: return OFFromBigEndian16(address->sockaddr.in.sin_port); # ifdef OF_HAVE_IPV6 - else if (address->sockaddr.sockaddr.sa_family == AF_INET6) + case AF_INET6: return OFFromBigEndian16(address->sockaddr.in6.sin6_port); # endif - else { + default: closesocket(_socket); _socket = OFInvalidSocketHandle; @throw [OFBindFailedException exceptionWithHost: OFSocketAddressString(address) ADDED src/OFUNIXDatagramSocket.h Index: src/OFUNIXDatagramSocket.h ================================================================== --- src/OFUNIXDatagramSocket.h +++ src/OFUNIXDatagramSocket.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2008-2022 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#import "OFDatagramSocket.h" + +OF_ASSUME_NONNULL_BEGIN + +@class OFString; + +/** + * @protocol OFUNIXDatagramSocketDelegate OFUNIXDatagramSocket.h \ + * ObjFW/OFUNIXDatagramSocket.h + * + * @brief A delegate for OFUNIXDatagramSocket. + */ +@protocol OFUNIXDatagramSocketDelegate +@end + +/** + * @class OFUNIXDatagramSocket OFUNIXDatagramSocket.h \ + * ObjFW/OFUNIXDatagramSocket.h + * + * @brief A class which provides methods to create and use UNIX datagram + * sockets. + * + * Addresses are of type @ref OFSocketAddress. You can use + * @ref OFSocketAddressMakeUNIX to create an address or + * @ref OFSocketAddressUNIXPath to get the socket path. + * + * @warning Even though the OFCopying protocol is implemented, it does *not* + * return an independent copy of the socket, but instead retains it. + * This is so that the socket can be used as a key for a dictionary, + * so context can be associated with a socket. Using a socket in more + * than one thread at the same time is not thread-safe, even if copy + * was called to create one "instance" for every thread! + */ +@interface OFUNIXDatagramSocket: OFDatagramSocket +{ + OF_RESERVE_IVARS(OFUNIXDatagramSocket, 4) +} + +/** + * @brief The delegate for asynchronous operations on the socket. + * + * @note The delegate is retained for as long as asynchronous operations are + * still ongoing. + */ +@property OF_NULLABLE_PROPERTY (assign, nonatomic) + id delegate; + +/** + * @brief Bind the socket to the specified path. + * + * @param path The path to bind to + * @return The address on which this socket can be reached + */ +- (OFSocketAddress)bindToPath: (OFString *)path; +@end + +OF_ASSUME_NONNULL_END ADDED src/OFUNIXDatagramSocket.m Index: src/OFUNIXDatagramSocket.m ================================================================== --- src/OFUNIXDatagramSocket.m +++ src/OFUNIXDatagramSocket.m @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2008-2022 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#include "config.h" + +#ifdef HAVE_FCNTL_H +# include +#endif + +#import "OFUNIXDatagramSocket.h" +#import "OFSocket.h" +#import "OFSocket+Private.h" +#import "OFString.h" + +#import "OFAlreadyConnectedException.h" +#import "OFBindFailedException.h" + +@implementation OFUNIXDatagramSocket +@dynamic delegate; + +- (OFSocketAddress)bindToPath: (OFString *)path +{ + OFSocketAddress address; +#if SOCK_CLOEXEC == 0 && defined(HAVE_FCNTL_H) && defined(FD_CLOEXEC) + int flags; +#endif + + if (_socket != OFInvalidSocketHandle) + @throw [OFAlreadyConnectedException exceptionWithSocket: self]; + + address = OFSocketAddressMakeUNIX(path); + + if ((_socket = socket(address.sockaddr.un.sun_family, + SOCK_DGRAM | SOCK_CLOEXEC, 0)) == OFInvalidSocketHandle) + @throw [OFBindFailedException + exceptionWithPath: path + socket: self + errNo: OFSocketErrNo()]; + + _canBlock = true; + +#if SOCK_CLOEXEC == 0 && defined(HAVE_FCNTL_H) && defined(FD_CLOEXEC) + if ((flags = fcntl(_socket, F_GETFD, 0)) != -1) + fcntl(_socket, F_SETFD, flags | FD_CLOEXEC); +#endif + + if (bind(_socket, (struct sockaddr *)&address.sockaddr, + address.length) != 0) { + int errNo = OFSocketErrNo(); + + closesocket(_socket); + _socket = OFInvalidSocketHandle; + + @throw [OFBindFailedException exceptionWithPath: path + socket: self + errNo: errNo]; + } + + return address; +} +@end ADDED src/OFUNIXStreamSocket.h Index: src/OFUNIXStreamSocket.h ================================================================== --- src/OFUNIXStreamSocket.h +++ src/OFUNIXStreamSocket.h @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2008-2022 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either 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 "OFStreamSocket.h" + +OF_ASSUME_NONNULL_BEGIN + +@class OFString; + +/** + * @protocol OFUNIXStreamSocketDelegate OFUNIXStreamSocket.h \ + * ObjFW/OFUNIXStreamSocket.h + * + * A delegate for OFUNIXStreamSocket. + */ +@protocol OFUNIXStreamSocketDelegate +@end + +/** + * @class OFUNIXStreamSocket OFUNIXStreamSocket.h ObjFW/OFUNIXStreamSocket.h + * + * @brief A class which provides methods to create and use UNIX stream sockets. + * + * To connect to a server, create a socket and connect it. + * To create a server, create a socket, bind it and listen on it. + */ +@interface OFUNIXStreamSocket: OFStreamSocket +{ + OF_RESERVE_IVARS(OFUNIXStreamSocket, 4) +} + +/** + * @brief The delegate for asynchronous operations on the socket. + * + * @note The delegate is retained for as long as asynchronous operations are + * still ongoing. + */ +@property OF_NULLABLE_PROPERTY (assign, nonatomic) + id delegate; + +/** + * @brief Connects the OFUNIXStreamSocket to the specified destination. + * + * @param path The path to connect to + */ +- (void)connectToPath: (OFString *)path; + +/** + * @brief Binds the socket to the specified host and port. + * + * @param path The path to bind to + */ +- (void)bindToPath: (OFString *)path; +@end + +OF_ASSUME_NONNULL_END ADDED src/OFUNIXStreamSocket.m Index: src/OFUNIXStreamSocket.m ================================================================== --- src/OFUNIXStreamSocket.m +++ src/OFUNIXStreamSocket.m @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2008-2022 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#include "config.h" + +#ifdef HAVE_FCNTL_H +# include +#endif + +#import "OFUNIXStreamSocket.h" +#import "OFSocket.h" +#import "OFSocket+Private.h" +#import "OFString.h" + +#import "OFAlreadyConnectedException.h" +#import "OFBindFailedException.h" +#import "OFConnectionFailedException.h" + +@implementation OFUNIXStreamSocket +@dynamic delegate; + +- (void)connectToPath: (OFString *)path +{ + OFSocketAddress address; +#if SOCK_CLOEXEC == 0 && defined(HAVE_FCNTL) && defined(FD_CLOEXEC) + int flags; +#endif + + if (_socket != OFInvalidSocketHandle) + @throw [OFAlreadyConnectedException exceptionWithSocket: self]; + + address = OFSocketAddressMakeUNIX(path); + + if ((_socket = socket(address.sockaddr.un.sun_family, + SOCK_STREAM | SOCK_CLOEXEC, 0)) == OFInvalidSocketHandle) + @throw [OFConnectionFailedException + exceptionWithPath: path + socket: self + errNo: OFSocketErrNo()]; + + _canBlock = true; + +#if SOCK_CLOEXEC == 0 && defined(HAVE_FCNTL) && defined(FD_CLOEXEC) + if ((flags = fcntl(_socket, F_GETFD, 0)) != -1) + fcntl(_socket, F_SETFD, flags | FD_CLOEXEC); +#endif + + if (connect(_socket, (struct sockaddr *)&address.sockaddr, + address.length) != 0) { + int errNo = OFSocketErrNo(); + + closesocket(_socket); + _socket = OFInvalidSocketHandle; + + @throw [OFConnectionFailedException exceptionWithPath: path + socket: self + errNo: errNo]; + } +} + +- (void)bindToPath: (OFString *)path +{ + OFSocketAddress address; +#if SOCK_CLOEXEC == 0 && defined(HAVE_FCNTL) && defined(FD_CLOEXEC) + int flags; +#endif + + if (_socket != OFInvalidSocketHandle) + @throw [OFAlreadyConnectedException exceptionWithSocket: self]; + + address = OFSocketAddressMakeUNIX(path); + + if ((_socket = socket(address.sockaddr.un.sun_family, + SOCK_STREAM | SOCK_CLOEXEC, 0)) == OFInvalidSocketHandle) + @throw [OFBindFailedException + exceptionWithPath: path + socket: self + errNo: OFSocketErrNo()]; + + _canBlock = true; + +#if SOCK_CLOEXEC == 0 && defined(HAVE_FCNTL) && defined(FD_CLOEXEC) + if ((flags = fcntl(_socket, F_GETFD, 0)) != -1) + fcntl(_socket, F_SETFD, flags | FD_CLOEXEC); +#endif + + if (bind(_socket, (struct sockaddr *)&address.sockaddr, + address.length) != 0) { + int errNo = OFSocketErrNo(); + + closesocket(_socket); + _socket = OFInvalidSocketHandle; + + @throw [OFBindFailedException exceptionWithPath: path + socket: self + errNo: errNo]; + } +} +@end Index: src/OFURL.h ================================================================== --- src/OFURL.h +++ src/OFURL.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -131,12 +131,12 @@ * * For example, a query like `key1=value1&key2=value2` would correspond to the * following dictionary: * * @{ - * @"key1": "value1", - * @"key2": "value2" + * @"key1": @"value1", + * @"key2": @"value2" * } */ @property OF_NULLABLE_PROPERTY (readonly, copy, nonatomic) OFDictionary OF_GENERIC(OFString *, OFString *) *queryDictionary; @@ -155,11 +155,11 @@ * @brief The URL as a string. */ @property (readonly, nonatomic) OFString *string; /** - * @brief The URL with relative sub paths resolved. + * @brief The URL with relative subpaths resolved. */ @property (readonly, nonatomic) OFURL *URLByStandardizingPath; #ifdef OF_HAVE_FILES /** Index: src/OFURL.m ================================================================== --- src/OFURL.m +++ src/OFURL.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -555,15 +555,21 @@ if (portString.unsignedLongLongValue > 65535) @throw [OFInvalidFormatException exception]; _port = [[OFNumber alloc] initWithUnsignedShort: portString.unsignedLongLongValue]; - } else + } else { _URLEncodedHost = [[OFString alloc] initWithUTF8String: UTF8String]; - if (!isIPv6Host) + if (_URLEncodedHost.length == 0) { + [_URLEncodedHost release]; + _URLEncodedHost = nil; + } + } + + if (_URLEncodedHost != nil && !isIPv6Host) OFURLVerifyIsEscaped(_URLEncodedHost, [OFCharacterSet URLHostAllowedCharacterSet]); if ((UTF8String = tmp) != NULL) { if ((tmp = strchr(UTF8String, '#')) != NULL) { @@ -594,17 +600,21 @@ * 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" +#if OF_GCC_VERSION >= 402 +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wpragmas" +# pragma GCC diagnostic ignored "-Wunknown-warning-option" +# pragma GCC diagnostic ignored "-Wstringop-overflow" +#endif UTF8String--; *UTF8String = '/'; -#pragma GCC diagnostic pop +#if OF_GCC_VERSION >= 402 +# pragma GCC diagnostic pop +#endif _URLEncodedPath = [[OFString alloc] initWithUTF8String: UTF8String]; OFURLVerifyIsEscaped(_URLEncodedPath, Index: src/OFURLHandler.h ================================================================== --- src/OFURLHandler.h +++ src/OFURLHandler.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFURLHandler.m ================================================================== --- src/OFURLHandler.m +++ src/OFURLHandler.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -22,10 +22,11 @@ #ifdef OF_HAVE_THREADS # import "OFMutex.h" #endif +#import "OFEmbeddedFileURLHandler.h" #ifdef OF_HAVE_FILES # import "OFFileURLHandler.h" #endif #if defined(OF_HAVE_SOCKETS) && defined(OF_HAVE_THREADS) # import "OFHTTPURLHandler.h" @@ -54,10 +55,12 @@ #ifdef OF_HAVE_THREADS mutex = [[OFMutex alloc] init]; atexit(releaseMutex); #endif + [self registerClass: [OFEmbeddedFileURLHandler class] + forScheme: @"objfw-embedded"]; #ifdef OF_HAVE_FILES [self registerClass: [OFFileURLHandler class] forScheme: @"file"]; #endif #if defined(OF_HAVE_SOCKETS) && defined(OF_HAVE_THREADS) [self registerClass: [OFHTTPURLHandler class] forScheme: @"http"]; Index: src/OFUTF8String+Private.h ================================================================== --- src/OFUTF8String+Private.h +++ src/OFUTF8String+Private.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFUTF8String.h ================================================================== --- src/OFUTF8String.h +++ src/OFUTF8String.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFUTF8String.m ================================================================== --- src/OFUTF8String.m +++ src/OFUTF8String.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in ADDED src/OFUUID.h Index: src/OFUUID.h ================================================================== --- src/OFUUID.h +++ src/OFUUID.h @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2008-2022 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either 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 +{ + 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 Index: src/OFUUID.m ================================================================== --- src/OFUUID.m +++ src/OFUUID.m @@ -0,0 +1,252 @@ +/* + * Copyright (c) 2008-2022 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 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 Index: src/OFValue.h ================================================================== --- src/OFValue.h +++ src/OFValue.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFValue.m ================================================================== --- src/OFValue.m +++ src/OFValue.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFWin32ConsoleStdIOStream.h ================================================================== --- src/OFWin32ConsoleStdIOStream.h +++ src/OFWin32ConsoleStdIOStream.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFWin32ConsoleStdIOStream.m ================================================================== --- src/OFWin32ConsoleStdIOStream.m +++ src/OFWin32ConsoleStdIOStream.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFWindowsRegistryKey.h ================================================================== --- src/OFWindowsRegistryKey.h +++ src/OFWindowsRegistryKey.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -74,30 +74,28 @@ * @brief Opens the subkey at the specified path. * * @param path The path of the subkey to open * @param securityAndAccessRights Please refer to the `RegOpenKeyEx()` * documentation for `samDesired` - * @return The subkey with the specified path, or nil if it does not exist + * @return The subkey with the specified path */ -- (nullable OFWindowsRegistryKey *) - openSubkeyAtPath: (OFString *)path - securityAndAccessRights: (REGSAM)securityAndAccessRights; +- (OFWindowsRegistryKey *)openSubkeyAtPath: (OFString *)path + securityAndAccessRights: (REGSAM)securityAndAccessRights; /** * @brief Opens the subkey at the specified path. * * @param path The path of the subkey to open * @param options Please refer to the `RegOpenKeyEx()` documentation for * `ulOptions`. Usually 0. * @param securityAndAccessRights Please refer to the `RegOpenKeyEx()` * documentation for `samDesired` - * @return The subkey with the specified path, or nil if it does not exist + * @return The subkey with the specified path */ -- (nullable OFWindowsRegistryKey *) - openSubkeyAtPath: (OFString *)path - options: (DWORD)options - securityAndAccessRights: (REGSAM)securityAndAccessRights; +- (OFWindowsRegistryKey *)openSubkeyAtPath: (OFString *)path + options: (DWORD)options + securityAndAccessRights: (REGSAM)securityAndAccessRights; /** * @brief Creates a subkey at the specified path or opens it if it already * exists. * @@ -190,10 +188,42 @@ */ - (void)setString: (nullable OFString *)string forValueNamed: (nullable OFString *)name type: (DWORD)type; +/** + * @brief Returns the DWORD for the specified value at the specified path. + * + * @param name The name of the value to return + * @return The DWORD for the specified value + */ +- (uint32_t)DWORDForValueNamed: (nullable OFString *)name; + +/** + * @brief Sets the DWORD for the specified value. + * + * @param dword The DWORD to set the value to + * @param name The name of the value to set + */ +- (void)setDWORD: (uint32_t)dword forValueNamed: (nullable OFString *)name; + +/** + * @brief Returns the QWORD for the specified value at the specified path. + * + * @param name The name of the value to return + * @return The QWORD for the specified value + */ +- (uint64_t)QWORDForValueNamed: (nullable OFString *)name; + +/** + * @brief Sets the QWORD for the specified value. + * + * @param qword The QWORD to set the value to + * @param name The name of the value to set + */ +- (void)setQWORD: (uint64_t)qword forValueNamed: (nullable OFString *)name; + /** * @brief Deletes the specified value. * * @param name The value to delete */ Index: src/OFWindowsRegistryKey.m ================================================================== --- src/OFWindowsRegistryKey.m +++ src/OFWindowsRegistryKey.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -29,10 +29,11 @@ #import "OFInvalidEncodingException.h" #import "OFInvalidFormatException.h" #import "OFOpenWindowsRegistryKeyFailedException.h" #import "OFOutOfRangeException.h" #import "OFSetWindowsRegistryValueFailedException.h" +#import "OFUndefinedKeyException.h" OF_DIRECT_MEMBERS @interface OFWindowsRegistryKey () - (instancetype)of_initWithHKey: (HKEY)hKey close: (bool)close; @end @@ -113,23 +114,17 @@ else status = RegOpenKeyExA(_hKey, [path cStringWithEncoding: [OFLocale encoding]], options, securityAndAccessRights, &subKey); - if (status != ERROR_SUCCESS) { - if (status == ERROR_FILE_NOT_FOUND) { - objc_autoreleasePoolPop(pool); - return nil; - } - + if (status != ERROR_SUCCESS) @throw [OFOpenWindowsRegistryKeyFailedException exceptionWithRegistryKey: self path: path options: options securityAndAccessRights: securityAndAccessRights status: status]; - } objc_autoreleasePoolPop(pool); return [[[OFWindowsRegistryKey alloc] of_initWithHKey: subKey close: true] @@ -362,10 +357,75 @@ [self setData: data forValueNamed: name type: type]; objc_autoreleasePoolPop(pool); } + +- (uint32_t)DWORDForValueNamed: (OFString *)name +{ + void *pool = objc_autoreleasePoolPush(); + DWORD type, ret; + OFData *data = [self dataForValueNamed: name type: &type]; + + if (data == nil) + @throw [OFUndefinedKeyException exceptionWithObject: self + key: name + value: nil]; + + if (type != REG_DWORD) + @throw [OFInvalidEncodingException exception]; + + if (data.count != sizeof(ret) || data.itemSize != 1) + @throw [OFInvalidFormatException exception]; + + memcpy(&ret, data.items, sizeof(ret)); + + objc_autoreleasePoolPop(pool); + + return ret; +} + +- (void)setDWORD: (uint32_t)dword forValueNamed: (OFString *)name +{ + void *pool = objc_autoreleasePoolPush(); + OFData *data = [OFData dataWithItems: &dword count: sizeof(dword)]; + [self setData: data forValueNamed: name type: REG_DWORD]; + objc_autoreleasePoolPop(pool); +} + +- (uint64_t)QWORDForValueNamed: (OFString *)name +{ + void *pool = objc_autoreleasePoolPush(); + DWORD type; + uint64_t ret; + OFData *data = [self dataForValueNamed: name type: &type]; + + if (data == nil) + @throw [OFUndefinedKeyException exceptionWithObject: self + key: name + value: nil]; + + if (type != REG_QWORD) + @throw [OFInvalidEncodingException exception]; + + if (data.count != sizeof(ret) || data.itemSize != 1) + @throw [OFInvalidFormatException exception]; + + memcpy(&ret, data.items, sizeof(ret)); + + objc_autoreleasePoolPop(pool); + + return ret; +} + +- (void)setQWORD: (uint64_t)qword forValueNamed: (OFString *)name +{ + void *pool = objc_autoreleasePoolPush(); + OFData *data = [OFData dataWithItems: &qword count: sizeof(qword)]; + [self setData: data forValueNamed: name type: REG_QWORD]; + objc_autoreleasePoolPop(pool); +} - (void)deleteValueNamed: (OFString *)name { void *pool = objc_autoreleasePoolPush(); LSTATUS status; Index: src/OFXMLAttribute.h ================================================================== --- src/OFXMLAttribute.h +++ src/OFXMLAttribute.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -44,11 +44,11 @@ */ #ifndef __cplusplus @property OF_NULLABLE_PROPERTY (readonly, nonatomic) OFString *namespace; #else @property OF_NULLABLE_PROPERTY (readonly, nonatomic, getter=namespace) - OFString *namespace_; + OFString *nameSpace; #endif /** * @brief Creates a new XML attribute. * @@ -61,16 +61,16 @@ /** * @brief Creates a new XML attribute. * * @param name The name of the attribute - * @param namespace_ The namespace of the attribute + * @param nameSpace The namespace of the attribute * @param stringValue The string value of the attribute * @return A new autoreleased OFXMLAttribute with the specified parameters */ + (instancetype)attributeWithName: (OFString *)name - namespace: (nullable OFString *)namespace_ + namespace: (nullable OFString *)nameSpace stringValue: (OFString *)stringValue; /** * @brief Initializes an already allocated OFXMLAttribute. * @@ -83,17 +83,17 @@ /** * @brief Initializes an already allocated OFXMLAttribute. * * @param name The name of the attribute - * @param namespace_ The namespace of the attribute + * @param nameSpace The namespace of the attribute * @param stringValue The string value of the attribute * @return An initialized OFXMLAttribute with the specified parameters */ - (instancetype)initWithName: (OFString *)name - namespace: (nullable OFString *)namespace_ + namespace: (nullable OFString *)nameSpace stringValue: (OFString *)stringValue; - (instancetype)initWithSerialization: (OFXMLElement *)element; @end OF_ASSUME_NONNULL_END Index: src/OFXMLAttribute.m ================================================================== --- src/OFXMLAttribute.m +++ src/OFXMLAttribute.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFXMLCDATA.h ================================================================== --- src/OFXMLCDATA.h +++ src/OFXMLCDATA.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFXMLCDATA.m ================================================================== --- src/OFXMLCDATA.m +++ src/OFXMLCDATA.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFXMLCharacters.h ================================================================== --- src/OFXMLCharacters.h +++ src/OFXMLCharacters.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFXMLCharacters.m ================================================================== --- src/OFXMLCharacters.m +++ src/OFXMLCharacters.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFXMLComment.h ================================================================== --- src/OFXMLComment.h +++ src/OFXMLComment.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFXMLComment.m ================================================================== --- src/OFXMLComment.m +++ src/OFXMLComment.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFXMLElement+Serialization.h ================================================================== --- src/OFXMLElement+Serialization.h +++ src/OFXMLElement+Serialization.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFXMLElement+Serialization.m ================================================================== --- src/OFXMLElement+Serialization.m +++ src/OFXMLElement+Serialization.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFXMLElement.h ================================================================== --- src/OFXMLElement.h +++ src/OFXMLElement.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -50,11 +50,11 @@ */ #ifndef __cplusplus @property OF_NULLABLE_PROPERTY (copy, nonatomic) OFString *namespace; #else @property OF_NULLABLE_PROPERTY (copy, nonatomic, - getter=namespace, setter=setNamespace:) OFString *namespace_; + getter=namespace, setter=setNamespace:) OFString *nameSpace; #endif /** * @brief The default namespace for the element to be used if there is no * parent. @@ -99,29 +99,29 @@ /** * @brief Creates a new XML element with the specified name and namespace. * * @param name The name for the element - * @param namespace_ The namespace for the element + * @param nameSpace The namespace for the element * @return A new autoreleased OFXMLElement with the specified element name and * namespace */ + (instancetype)elementWithName: (OFString *)name - namespace: (nullable OFString *)namespace_; + namespace: (nullable OFString *)nameSpace; /** * @brief Creates a new XML element with the specified name, namespace and * string value. * * @param name The name for the element - * @param namespace_ The namespace for the element + * @param nameSpace The namespace for the element * @param stringValue The value for the element * @return A new autoreleased OFXMLElement with the specified element name, * namespace and value */ + (instancetype)elementWithName: (OFString *)name - namespace: (nullable OFString *)namespace_ + namespace: (nullable OFString *)nameSpace stringValue: (nullable OFString *)stringValue; /** * @brief Creates a new element with the specified element. * @@ -173,29 +173,29 @@ /** * @brief Initializes an already allocated OFXMLElement with the specified name * and namespace. * * @param name The name for the element - * @param namespace_ The namespace for the element + * @param nameSpace The namespace for the element * @return An initialized OFXMLElement with the specified element name and * namespace */ - (instancetype)initWithName: (OFString *)name - namespace: (nullable OFString *)namespace_; + namespace: (nullable OFString *)nameSpace; /** * @brief Initializes an already allocated OFXMLElement with the specified name, * namespace and value. * * @param name The name for the element - * @param namespace_ The namespace for the element + * @param nameSpace The namespace for the element * @param stringValue The value for the element * @return An initialized OFXMLElement with the specified element name, * namespace and value */ - (instancetype)initWithName: (OFString *)name - namespace: (nullable OFString *)namespace_ + namespace: (nullable OFString *)nameSpace stringValue: (nullable OFString *)stringValue; /** * @brief Initializes an already allocated OFXMLElement with the specified * element. @@ -228,21 +228,21 @@ /** * @brief Sets a prefix for a namespace. * * @param prefix The prefix for the namespace - * @param namespace_ The namespace for which the prefix is set + * @param nameSpace The namespace for which the prefix is set */ -- (void)setPrefix: (OFString *)prefix forNamespace: (OFString *)namespace_; +- (void)setPrefix: (OFString *)prefix forNamespace: (OFString *)nameSpace; /** * @brief Binds a prefix for a namespace. * * @param prefix The prefix for the namespace - * @param namespace_ The namespace for which the prefix is bound + * @param nameSpace The namespace for which the prefix is bound */ -- (void)bindPrefix: (OFString *)prefix forNamespace: (OFString *)namespace_; +- (void)bindPrefix: (OFString *)prefix forNamespace: (OFString *)nameSpace; /** * @brief Adds the specified attribute. * * If an attribute with the same name and namespace already exists, it is not @@ -270,15 +270,15 @@ * * If an attribute with the same name and namespace already exists, it is not * added. * * @param name The name of the attribute - * @param namespace_ The namespace of the attribute + * @param nameSpace The namespace of the attribute * @param stringValue The value of the attribute */ - (void)addAttributeWithName: (OFString *)name - namespace: (nullable OFString *)namespace_ + namespace: (nullable OFString *)nameSpace stringValue: (OFString *)stringValue; /** * @brief Returns the attribute with the specified name. * Index: src/OFXMLElement.m ================================================================== --- src/OFXMLElement.m +++ src/OFXMLElement.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFXMLElementBuilder.h ================================================================== --- src/OFXMLElementBuilder.h +++ src/OFXMLElementBuilder.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -71,16 +71,16 @@ * an OFMalformedXMLException. * * @param builder The builder which did not expect the close tag * @param name The name of the close tag * @param prefix The prefix of the close tag - * @param namespace_ The namespace of the close tag + * @param nameSpace The namespace of the close tag */ - (void)elementBuilder: (OFXMLElementBuilder *)builder didNotExpectCloseTag: (OFString *)name prefix: (nullable OFString *)prefix - namespace: (nullable OFString *)namespace_; + namespace: (nullable OFString *)nameSpace; /** * @brief This callback is called when the XML parser for the element builder * found an unknown entity. * Index: src/OFXMLElementBuilder.m ================================================================== --- src/OFXMLElementBuilder.m +++ src/OFXMLElementBuilder.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFXMLNode+Private.h ================================================================== --- src/OFXMLNode+Private.h +++ src/OFXMLNode+Private.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFXMLNode.h ================================================================== --- src/OFXMLNode.h +++ src/OFXMLNode.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFXMLNode.m ================================================================== --- src/OFXMLNode.m +++ src/OFXMLNode.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFXMLParser.h ================================================================== --- src/OFXMLParser.h +++ src/OFXMLParser.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -162,11 +162,11 @@ @property (readonly, nonatomic) size_t lineNumber; /** * @brief Whether the XML parser has finished parsing. */ -@property (readonly, nonatomic) bool hasFinishedParsing; +@property (readonly, nonatomic, getter=hasFinishedParsing) bool finishedParsing; /** * @brief The depth limit for the XML parser. * * If the depth limit is exceeded, an OFMalformedXMLException is thrown. Index: src/OFXMLParser.m ================================================================== --- src/OFXMLParser.m +++ src/OFXMLParser.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFXMLProcessingInstruction.h ================================================================== --- src/OFXMLProcessingInstruction.h +++ src/OFXMLProcessingInstruction.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFXMLProcessingInstruction.m ================================================================== --- src/OFXMLProcessingInstruction.m +++ src/OFXMLProcessingInstruction.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFZIPArchive.h ================================================================== --- src/OFZIPArchive.h +++ src/OFZIPArchive.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFZIPArchive.m ================================================================== --- src/OFZIPArchive.m +++ src/OFZIPArchive.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -40,10 +40,11 @@ #import "OFOpenItemFailedException.h" #import "OFOutOfRangeException.h" #import "OFSeekFailedException.h" #import "OFTruncatedDataException.h" #import "OFUnsupportedVersionException.h" +#import "OFWriteFailedException.h" /* * FIXME: Current limitations: * - Split archives are not supported. * - Encrypted files cannot be read. @@ -432,10 +433,13 @@ void *pool = objc_autoreleasePoolPush(); OFZIPArchiveEntry *entry; OFZIPArchiveLocalFileHeader *localFileHeader; int64_t offset64; + if (_stream == nil) + @throw [OFNotOpenException exceptionWithObject: self]; + if (_mode != modeRead) @throw [OFInvalidArgumentException exception]; if ((entry = [_pathToEntryMap objectForKey: path]) == nil) @throw [OFOpenItemFailedException exceptionWithPath: path @@ -482,10 +486,13 @@ OFMutableZIPArchiveEntry *entry; OFString *fileName; OFData *extraField; uint16_t fileNameLength, extraFieldLength; + if (_stream == nil) + @throw [OFNotOpenException exceptionWithObject: self]; + if (_mode != modeWrite && _mode != modeAppend) @throw [OFInvalidArgumentException exception]; pool = objc_autoreleasePoolPush(); entry = [[entry_ mutableCopy] autorelease]; @@ -874,26 +881,36 @@ [super dealloc]; } - (size_t)lowlevelWriteBuffer: (const void *)buffer length: (size_t)length { - size_t bytesWritten; - #if SIZE_MAX >= INT64_MAX if (length > INT64_MAX) @throw [OFOutOfRangeException exception]; #endif if (INT64_MAX - _bytesWritten < (int64_t)length) @throw [OFOutOfRangeException exception]; - bytesWritten = [_stream writeBuffer: buffer length: length]; + @try { + [_stream writeBuffer: buffer length: length]; + } @catch (OFWriteFailedException *e) { + OFEnsure(e.bytesWritten <= length); + + _bytesWritten += (int64_t)e.bytesWritten; + _CRC32 = OFCRC32(_CRC32, buffer, e.bytesWritten); + + if (e.errNo == EWOULDBLOCK || e.errNo == EAGAIN) + return e.bytesWritten; + + @throw e; + } - _bytesWritten += (int64_t)bytesWritten; + _bytesWritten += (int64_t)length; _CRC32 = OFCRC32(_CRC32, buffer, length); - return bytesWritten; + return length; } - (void)close { if (_stream == nil) Index: src/OFZIPArchiveEntry+Private.h ================================================================== --- src/OFZIPArchiveEntry+Private.h +++ src/OFZIPArchiveEntry+Private.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFZIPArchiveEntry.h ================================================================== --- src/OFZIPArchiveEntry.h +++ src/OFZIPArchiveEntry.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFZIPArchiveEntry.m ================================================================== --- src/OFZIPArchiveEntry.m +++ src/OFZIPArchiveEntry.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/ObjFW.h ================================================================== --- src/ObjFW.h +++ src/ObjFW.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -43,15 +43,21 @@ #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 "OFNotification.h" +#import "OFNotificationCenter.h" + #import "OFStream.h" +#import "OFSeekableStream.h" +#import "OFMemoryStream.h" #import "OFStdIOStream.h" #import "OFInflateStream.h" #import "OFInflate64Stream.h" #import "OFGZIPStream.h" #import "OFLHAArchive.h" @@ -61,20 +67,20 @@ #import "OFZIPArchive.h" #import "OFZIPArchiveEntry.h" #import "OFFileManager.h" #ifdef OF_HAVE_FILES # import "OFFile.h" -# import "OFINIFile.h" -# import "OFSettings.h" #endif +#import "OFINIFile.h" +#import "OFSettings.h" #ifdef OF_HAVE_SOCKETS # import "OFStreamSocket.h" # import "OFDatagramSocket.h" # import "OFSequencedPacketSocket.h" # import "OFTCPSocket.h" # import "OFUDPSocket.h" -# import "OFTLSSocket.h" +# import "OFTLSStream.h" # import "OFKernelEventObserver.h" # import "OFDNSQuery.h" # import "OFDNSResourceRecord.h" # import "OFDNSResponse.h" # import "OFDNSResolver.h" @@ -81,10 +87,14 @@ # ifdef OF_HAVE_IPX # import "OFIPXSocket.h" # import "OFSPXSocket.h" # import "OFSPXStreamSocket.h" # endif +# ifdef OF_HAVE_UNIX_SOCKETS +# import "OFUNIXDatagramSocket.h" +# import "OFUNIXStreamSocket.h" +# endif #endif #ifdef OF_HAVE_SOCKETS # ifdef OF_HAVE_THREADS # import "OFHTTPClient.h" # endif @@ -171,10 +181,11 @@ #import "OFGetOptionFailedException.h" #ifdef OF_WINDOWS # import "OFGetWindowsRegistryValueFailedException.h" #endif #import "OFHashAlreadyCalculatedException.h" +#import "OFHashNotCalculatedException.h" #ifdef OF_HAVE_SOCKETS # import "OFHTTPRequestFailedException.h" #endif #import "OFInitializationFailedException.h" #import "OFInvalidArgumentException.h" @@ -189,11 +200,10 @@ #ifdef OF_HAVE_PLUGINS # import "OFLoadPluginFailedException.h" #endif #import "OFLockFailedException.h" #import "OFMalformedXMLException.h" -#import "OFMemoryNotPartOfObjectException.h" #import "OFMoveItemFailedException.h" #import "OFNotImplementedException.h" #import "OFNotOpenException.h" #ifdef OF_HAVE_SOCKETS # import "OFObserveFailedException.h" @@ -221,10 +231,13 @@ #ifdef OF_HAVE_THREADS # import "OFThreadJoinFailedException.h" # import "OFThreadStartFailedException.h" # import "OFThreadStillRunningException.h" #endif +#ifdef OF_HAVE_SOCKETS +# import "OFTLSHandshakeFailedException.h" +#endif #import "OFTruncatedDataException.h" #import "OFUnboundNamespaceException.h" #import "OFUnboundPrefixException.h" #import "OFUndefinedKeyException.h" #import "OFUnknownXMLEntityException.h" @@ -249,16 +262,9 @@ # import "OFPlainCondition.h" # import "OFPlainMutex.h" # import "OFPlainThread.h" # import "OFRecursiveMutex.h" # import "OFTLSKey.h" -# import "OFThreadPool.h" #endif -#import "OFASPrintF.h" -#import "OFBase64.h" -#import "OFCRC16.h" -#import "OFCRC32.h" -#import "OFHuffmanTree.h" #import "OFPBKDF2.h" #import "OFScrypt.h" -#import "OFStrPTime.h" Index: src/bridge/NSArray+OFObject.h ================================================================== --- src/bridge/NSArray+OFObject.h +++ src/bridge/NSArray+OFObject.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/bridge/NSArray+OFObject.m ================================================================== --- src/bridge/NSArray+OFObject.m +++ src/bridge/NSArray+OFObject.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/bridge/NSBridging.h ================================================================== --- src/bridge/NSBridging.h +++ src/bridge/NSBridging.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/bridge/NSDictionary+OFObject.h ================================================================== --- src/bridge/NSDictionary+OFObject.h +++ src/bridge/NSDictionary+OFObject.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/bridge/NSDictionary+OFObject.m ================================================================== --- src/bridge/NSDictionary+OFObject.m +++ src/bridge/NSDictionary+OFObject.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/bridge/NSEnumerator+OFObject.h ================================================================== --- src/bridge/NSEnumerator+OFObject.h +++ src/bridge/NSEnumerator+OFObject.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/bridge/NSEnumerator+OFObject.m ================================================================== --- src/bridge/NSEnumerator+OFObject.m +++ src/bridge/NSEnumerator+OFObject.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/bridge/NSNumber+OFObject.h ================================================================== --- src/bridge/NSNumber+OFObject.h +++ src/bridge/NSNumber+OFObject.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/bridge/NSNumber+OFObject.m ================================================================== --- src/bridge/NSNumber+OFObject.m +++ src/bridge/NSNumber+OFObject.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/bridge/NSOFArray.h ================================================================== --- src/bridge/NSOFArray.h +++ src/bridge/NSOFArray.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/bridge/NSOFArray.m ================================================================== --- src/bridge/NSOFArray.m +++ src/bridge/NSOFArray.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/bridge/NSOFDictionary.h ================================================================== --- src/bridge/NSOFDictionary.h +++ src/bridge/NSOFDictionary.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/bridge/NSOFDictionary.m ================================================================== --- src/bridge/NSOFDictionary.m +++ src/bridge/NSOFDictionary.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/bridge/NSOFEnumerator.h ================================================================== --- src/bridge/NSOFEnumerator.h +++ src/bridge/NSOFEnumerator.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/bridge/NSOFEnumerator.m ================================================================== --- src/bridge/NSOFEnumerator.m +++ src/bridge/NSOFEnumerator.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/bridge/NSOFSet.h ================================================================== --- src/bridge/NSOFSet.h +++ src/bridge/NSOFSet.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/bridge/NSOFSet.m ================================================================== --- src/bridge/NSOFSet.m +++ src/bridge/NSOFSet.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/bridge/NSSet+OFObject.h ================================================================== --- src/bridge/NSSet+OFObject.h +++ src/bridge/NSSet+OFObject.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/bridge/NSSet+OFObject.m ================================================================== --- src/bridge/NSSet+OFObject.m +++ src/bridge/NSSet+OFObject.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/bridge/NSString+OFObject.h ================================================================== --- src/bridge/NSString+OFObject.h +++ src/bridge/NSString+OFObject.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/bridge/NSString+OFObject.m ================================================================== --- src/bridge/NSString+OFObject.m +++ src/bridge/NSString+OFObject.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/bridge/OFArray+NSObject.h ================================================================== --- src/bridge/OFArray+NSObject.h +++ src/bridge/OFArray+NSObject.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/bridge/OFArray+NSObject.m ================================================================== --- src/bridge/OFArray+NSObject.m +++ src/bridge/OFArray+NSObject.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/bridge/OFBridging.h ================================================================== --- src/bridge/OFBridging.h +++ src/bridge/OFBridging.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/bridge/OFDictionary+NSObject.h ================================================================== --- src/bridge/OFDictionary+NSObject.h +++ src/bridge/OFDictionary+NSObject.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/bridge/OFDictionary+NSObject.m ================================================================== --- src/bridge/OFDictionary+NSObject.m +++ src/bridge/OFDictionary+NSObject.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/bridge/OFEnumerator+NSObject.h ================================================================== --- src/bridge/OFEnumerator+NSObject.h +++ src/bridge/OFEnumerator+NSObject.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/bridge/OFEnumerator+NSObject.m ================================================================== --- src/bridge/OFEnumerator+NSObject.m +++ src/bridge/OFEnumerator+NSObject.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/bridge/OFException+Swift.h ================================================================== --- src/bridge/OFException+Swift.h +++ src/bridge/OFException+Swift.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/bridge/OFException+Swift.m ================================================================== --- src/bridge/OFException+Swift.m +++ src/bridge/OFException+Swift.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/bridge/OFNSArray.h ================================================================== --- src/bridge/OFNSArray.h +++ src/bridge/OFNSArray.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/bridge/OFNSArray.m ================================================================== --- src/bridge/OFNSArray.m +++ src/bridge/OFNSArray.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/bridge/OFNSDictionary.h ================================================================== --- src/bridge/OFNSDictionary.h +++ src/bridge/OFNSDictionary.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/bridge/OFNSDictionary.m ================================================================== --- src/bridge/OFNSDictionary.m +++ src/bridge/OFNSDictionary.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/bridge/OFNSEnumerator.h ================================================================== --- src/bridge/OFNSEnumerator.h +++ src/bridge/OFNSEnumerator.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/bridge/OFNSEnumerator.m ================================================================== --- src/bridge/OFNSEnumerator.m +++ src/bridge/OFNSEnumerator.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/bridge/OFNSSet.h ================================================================== --- src/bridge/OFNSSet.h +++ src/bridge/OFNSSet.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/bridge/OFNSSet.m ================================================================== --- src/bridge/OFNSSet.m +++ src/bridge/OFNSSet.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/bridge/OFNumber+NSObject.h ================================================================== --- src/bridge/OFNumber+NSObject.h +++ src/bridge/OFNumber+NSObject.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/bridge/OFNumber+NSObject.m ================================================================== --- src/bridge/OFNumber+NSObject.m +++ src/bridge/OFNumber+NSObject.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/bridge/OFSet+NSObject.h ================================================================== --- src/bridge/OFSet+NSObject.h +++ src/bridge/OFSet+NSObject.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/bridge/OFSet+NSObject.m ================================================================== --- src/bridge/OFSet+NSObject.m +++ src/bridge/OFSet+NSObject.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/bridge/OFString+NSObject.h ================================================================== --- src/bridge/OFString+NSObject.h +++ src/bridge/OFString+NSObject.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/bridge/OFString+NSObject.m ================================================================== --- src/bridge/OFString+NSObject.m +++ src/bridge/OFString+NSObject.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/bridge/ObjFWBridge.h ================================================================== --- src/bridge/ObjFWBridge.h +++ src/bridge/ObjFWBridge.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/encodings/codepage-437.m ================================================================== --- src/encodings/codepage-437.m +++ src/encodings/codepage-437.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/encodings/codepage-850.m ================================================================== --- src/encodings/codepage-850.m +++ src/encodings/codepage-850.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/encodings/codepage-858.m ================================================================== --- src/encodings/codepage-858.m +++ src/encodings/codepage-858.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/encodings/common.h ================================================================== --- src/encodings/common.h +++ src/encodings/common.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/encodings/iso-8859-15.m ================================================================== --- src/encodings/iso-8859-15.m +++ src/encodings/iso-8859-15.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/encodings/iso-8859-2.m ================================================================== --- src/encodings/iso-8859-2.m +++ src/encodings/iso-8859-2.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/encodings/iso-8859-3.m ================================================================== --- src/encodings/iso-8859-3.m +++ src/encodings/iso-8859-3.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/encodings/koi8-r.m ================================================================== --- src/encodings/koi8-r.m +++ src/encodings/koi8-r.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/encodings/koi8-u.m ================================================================== --- src/encodings/koi8-u.m +++ src/encodings/koi8-u.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/encodings/mac-roman.m ================================================================== --- src/encodings/mac-roman.m +++ src/encodings/mac-roman.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/encodings/windows-1251.m ================================================================== --- src/encodings/windows-1251.m +++ src/encodings/windows-1251.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/encodings/windows-1252.m ================================================================== --- src/encodings/windows-1252.m +++ src/encodings/windows-1252.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/exceptions/Makefile ================================================================== --- src/exceptions/Makefile +++ src/exceptions/Makefile @@ -12,20 +12,20 @@ OFCreateSymbolicLinkFailedException.m \ OFEnumerationMutationException.m \ OFException.m \ OFGetOptionFailedException.m \ OFHashAlreadyCalculatedException.m \ + OFHashNotCalculatedException.m \ OFInitializationFailedException.m \ OFInvalidArgumentException.m \ OFInvalidEncodingException.m \ OFInvalidFormatException.m \ OFInvalidJSONException.m \ OFInvalidServerReplyException.m \ OFLinkFailedException.m \ OFLockFailedException.m \ OFMalformedXMLException.m \ - OFMemoryNotPartOfObjectException.m \ OFMoveItemFailedException.m \ OFNotImplementedException.m \ OFNotOpenException.m \ OFOpenItemFailedException.m \ OFOutOfMemoryException.m \ @@ -60,11 +60,12 @@ OFConnectionFailedException.m \ OFDNSQueryFailedException.m \ OFHTTPRequestFailedException.m \ OFListenFailedException.m \ OFObserveFailedException.m \ - OFResolveHostFailedException.m + OFResolveHostFailedException.m \ + OFTLSHandshakeFailedException.m SRCS_THREADS = OFConditionBroadcastFailedException.m \ OFConditionSignalFailedException.m \ OFConditionStillWaitingException.m \ OFConditionWaitFailedException.m \ OFThreadJoinFailedException.m \ Index: src/exceptions/OFAcceptFailedException.h ================================================================== --- src/exceptions/OFAcceptFailedException.h +++ src/exceptions/OFAcceptFailedException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/exceptions/OFAcceptFailedException.m ================================================================== --- src/exceptions/OFAcceptFailedException.m +++ src/exceptions/OFAcceptFailedException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/exceptions/OFAllocFailedException.h ================================================================== --- src/exceptions/OFAllocFailedException.h +++ src/exceptions/OFAllocFailedException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/exceptions/OFAllocFailedException.m ================================================================== --- src/exceptions/OFAllocFailedException.m +++ src/exceptions/OFAllocFailedException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/exceptions/OFAlreadyConnectedException.h ================================================================== --- src/exceptions/OFAlreadyConnectedException.h +++ src/exceptions/OFAlreadyConnectedException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/exceptions/OFAlreadyConnectedException.m ================================================================== --- src/exceptions/OFAlreadyConnectedException.m +++ src/exceptions/OFAlreadyConnectedException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/exceptions/OFBindFailedException.h ================================================================== --- src/exceptions/OFBindFailedException.h +++ src/exceptions/OFBindFailedException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -29,23 +29,25 @@ * * @brief An exception indicating that binding a socket failed. */ @interface OFBindFailedException: OFException { - id _socket; /* IP */ - OFString *_host; + OFString *_Nullable _host; uint16_t _port; /* IPX */ uint8_t _packetType; + /* UNIX socket */ + OFString *_Nullable _path; + id _socket; int _errNo; } /** * @brief The host on which binding failed. */ -@property (readonly, nonatomic) OFString *host; +@property OF_NULLABLE_PROPERTY (readonly, nonatomic) OFString *host; /** * @brief The port on which binding failed. */ @property (readonly, nonatomic) uint16_t port; @@ -53,10 +55,15 @@ /** * @brief The IPX packet type for which binding failed. */ @property (readonly, nonatomic) uint8_t packetType; +/** + * @brief The path on which binding failed. + */ +@property OF_NULLABLE_PROPERTY (readonly, nonatomic) OFString *path; + /** * @brief The socket which could not be bound. */ @property (readonly, nonatomic) id socket; @@ -63,12 +70,10 @@ /** * @brief The errno of the error that occurred. */ @property (readonly, nonatomic) int errNo; -+ (instancetype)exception OF_UNAVAILABLE; - /** * @brief Creates a new, autoreleased bind failed exception. * * @param host The host on which binding failed * @param port The port on which binding failed @@ -79,10 +84,12 @@ + (instancetype)exceptionWithHost: (OFString *)host port: (uint16_t)port socket: (id)socket errNo: (int)errNo; ++ (instancetype)exception OF_UNAVAILABLE; + /** * @brief Creates a new, autoreleased bind failed exception. * * @param port The IPX port to which binding failed * @param packetType The IPX packet type for which binding failed @@ -93,11 +100,21 @@ + (instancetype)exceptionWithPort: (uint16_t)port packetType: (uint8_t)packetType socket: (id)socket errNo: (int)errNo; -- (instancetype)init OF_UNAVAILABLE; +/** + * @brief Creates a new, autoreleased bind failed exception. + * + * @param path The path on which binding failed + * @param socket The socket which could not be bound + * @param errNo The errno of the error that occurred + * @return A new, autoreleased bind failed exception + */ ++ (instancetype)exceptionWithPath: (OFString *)path + socket: (id)socket + errNo: (int)errNo; /** * @brief Initializes an already allocated bind failed exception. * * @param host The host on which binding failed @@ -122,8 +139,21 @@ */ - (instancetype)initWithPort: (uint16_t)port packetType: (uint8_t)packetType socket: (id)socket errNo: (int)errNo; +/** + * @brief Initializes an already allocated bind failed exception. + * + * @param path The path on which binding failed + * @param socket The socket which could not be bound + * @param errNo The errno of the error that occurred + * @return An initialized bind failed exception + */ +- (instancetype)initWithPath: (OFString *)path + socket: (id)socket + errNo: (int)errNo; + +- (instancetype)init OF_UNAVAILABLE; @end OF_ASSUME_NONNULL_END Index: src/exceptions/OFBindFailedException.m ================================================================== --- src/exceptions/OFBindFailedException.m +++ src/exceptions/OFBindFailedException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -17,11 +17,11 @@ #import "OFBindFailedException.h" #import "OFString.h" @implementation OFBindFailedException -@synthesize host = _host, port = _port, packetType = _packetType; +@synthesize host = _host, port = _port, packetType = _packetType, path = _path; @synthesize socket = _socket, errNo = _errNo; + (instancetype)exception { OF_UNRECOGNIZED_SELECTOR @@ -46,10 +46,19 @@ return [[[self alloc] initWithPort: port packetType: packetType socket: sock errNo: errNo] autorelease]; } + ++ (instancetype)exceptionWithPath: (OFString *)path + socket: (id)sock + errNo: (int)errNo +{ + return [[[self alloc] initWithPath: path + socket: sock + errNo: errNo] autorelease]; +} - (instancetype)init { OF_INVALID_INIT_METHOD } @@ -91,22 +100,45 @@ @throw e; } return self; } + +- (instancetype)initWithPath: (OFString *)path + socket: (id)sock + errNo: (int)errNo +{ + self = [super init]; + + @try { + _path = [path copy]; + _socket = [sock retain]; + _errNo = errNo; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} - (void)dealloc { [_host release]; + [_path release]; [_socket release]; [super dealloc]; } - (OFString *)description { - if (_host != nil) + if (_path != nil) + return [OFString stringWithFormat: + @"Binding to path %@ failed in socket of type %@: %@", + _path, [_socket class], OFStrError(_errNo)]; + else if (_host != nil) return [OFString stringWithFormat: @"Binding to port %" @PRIu16 @" on host %@ failed in " @"socket of type %@: %@", _port, _host, [_socket class], OFStrError(_errNo)]; else Index: src/exceptions/OFChangeCurrentDirectoryPathFailedException.h ================================================================== --- src/exceptions/OFChangeCurrentDirectoryPathFailedException.h +++ src/exceptions/OFChangeCurrentDirectoryPathFailedException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -40,12 +40,10 @@ /** * @brief The errno of the error that occurred. */ @property (readonly, nonatomic) int errNo; -+ (instancetype)exception OF_UNAVAILABLE; - /** * @brief Creates a new, autoreleased change current directory path failed * exception. * * @param path The path of the directory to which the current path could not be @@ -53,11 +51,11 @@ * @param errNo The errno of the error that occurred * @return A new, autoreleased change current directory path failed exception */ + (instancetype)exceptionWithPath: (OFString *)path errNo: (int)errNo; -- (instancetype)init OF_UNAVAILABLE; ++ (instancetype)exception OF_UNAVAILABLE; /** * @brief Initializes an already allocated change directory failed exception. * * @param path The path of the directory to which the current path could not be @@ -65,8 +63,10 @@ * @param errNo The errno of the error that occurred * @return An initialized change current directory path failed exception */ - (instancetype)initWithPath: (OFString *)path errNo: (int)errNo OF_DESIGNATED_INITIALIZER; + +- (instancetype)init OF_UNAVAILABLE; @end OF_ASSUME_NONNULL_END Index: src/exceptions/OFChangeCurrentDirectoryPathFailedException.m ================================================================== --- src/exceptions/OFChangeCurrentDirectoryPathFailedException.m +++ src/exceptions/OFChangeCurrentDirectoryPathFailedException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -19,23 +19,18 @@ #import "OFString.h" @implementation OFChangeCurrentDirectoryPathFailedException @synthesize path = _path, errNo = _errNo; -+ (instancetype)exception -{ - OF_UNRECOGNIZED_SELECTOR -} - + (instancetype)exceptionWithPath: (OFString *)path errNo: (int)errNo { return [[[self alloc] initWithPath: path errNo: errNo] autorelease]; } -- (instancetype)init ++ (instancetype)exception { - OF_INVALID_INIT_METHOD + OF_UNRECOGNIZED_SELECTOR } - (instancetype)initWithPath: (OFString *)path errNo: (int)errNo { self = [super init]; @@ -48,10 +43,15 @@ @throw e; } return self; } + +- (instancetype)init +{ + OF_INVALID_INIT_METHOD +} - (void)dealloc { [_path release]; Index: src/exceptions/OFChecksumMismatchException.h ================================================================== --- src/exceptions/OFChecksumMismatchException.h +++ src/exceptions/OFChecksumMismatchException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/exceptions/OFChecksumMismatchException.m ================================================================== --- src/exceptions/OFChecksumMismatchException.m +++ src/exceptions/OFChecksumMismatchException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/exceptions/OFConditionBroadcastFailedException.h ================================================================== --- src/exceptions/OFConditionBroadcastFailedException.h +++ src/exceptions/OFConditionBroadcastFailedException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -37,11 +37,11 @@ } /** * @brief The condition which could not be broadcasted. */ -@property OF_NULLABLE_PROPERTY (readonly, nonatomic) OFCondition *condition; +@property (readonly, nonatomic) OFCondition *condition; /** * @brief The errno of the error that occurred. */ @property (readonly, nonatomic) int errNo; @@ -51,22 +51,24 @@ * * @param condition The condition which could not be broadcasted * @param errNo The errno of the error that occurred * @return A new, autoreleased condition broadcast failed exception */ -+ (instancetype)exceptionWithCondition: (nullable OFCondition *)condition ++ (instancetype)exceptionWithCondition: (OFCondition *)condition errNo: (int)errNo; + ++ (instancetype)exception OF_UNAVAILABLE; /** * @brief Initializes an already allocated condition broadcast failed exception. * * @param condition The condition which could not be broadcasted * @param errNo The errno of the error that occurred * @return An initialized condition broadcast failed exception */ -- (instancetype)initWithCondition: (nullable OFCondition *)condition +- (instancetype)initWithCondition: (OFCondition *)condition errNo: (int)errNo OF_DESIGNATED_INITIALIZER; - (instancetype)init OF_UNAVAILABLE; @end OF_ASSUME_NONNULL_END Index: src/exceptions/OFConditionBroadcastFailedException.m ================================================================== --- src/exceptions/OFConditionBroadcastFailedException.m +++ src/exceptions/OFConditionBroadcastFailedException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -28,10 +28,15 @@ errNo: (int)errNo { return [[[self alloc] initWithCondition: condition errNo: errNo] autorelease]; } + ++ (instancetype)exception +{ + OF_UNRECOGNIZED_SELECTOR +} - (instancetype)initWithCondition: (OFCondition *)condition errNo: (int)errNo { self = [super init]; Index: src/exceptions/OFConditionSignalFailedException.h ================================================================== --- src/exceptions/OFConditionSignalFailedException.h +++ src/exceptions/OFConditionSignalFailedException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -37,11 +37,11 @@ } /** * @brief The condition which could not be signaled. */ -@property OF_NULLABLE_PROPERTY (readonly, nonatomic) OFCondition *condition; +@property (readonly, nonatomic) OFCondition *condition; /** * @brief The errno of the error that occurred. */ @property (readonly, nonatomic) int errNo; @@ -51,22 +51,24 @@ * * @param condition The condition which could not be signaled * @param errNo The errno of the error that occurred * @return A new, autoreleased condition signal failed exception */ -+ (instancetype)exceptionWithCondition: (nullable OFCondition *)condition ++ (instancetype)exceptionWithCondition: (OFCondition *)condition errNo: (int)errNo; + ++ (instancetype)exception OF_UNAVAILABLE; /** * @brief Initializes an already allocated condition signal failed exception. * * @param condition The condition which could not be signaled * @param errNo The errno of the error that occurred * @return An initialized condition signal failed exception */ -- (instancetype)initWithCondition: (nullable OFCondition *)condition +- (instancetype)initWithCondition: (OFCondition *)condition errNo: (int)errNo OF_DESIGNATED_INITIALIZER; - (instancetype)init OF_UNAVAILABLE; @end OF_ASSUME_NONNULL_END Index: src/exceptions/OFConditionSignalFailedException.m ================================================================== --- src/exceptions/OFConditionSignalFailedException.m +++ src/exceptions/OFConditionSignalFailedException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -28,10 +28,15 @@ errNo: (int)errNo { return [[[self alloc] initWithCondition: condition errNo: errNo] autorelease]; } + ++ (instancetype)exception +{ + OF_UNRECOGNIZED_SELECTOR +} - (instancetype)initWithCondition: (OFCondition *)condition errNo: (int)errNo { self = [super init]; Index: src/exceptions/OFConditionStillWaitingException.h ================================================================== --- src/exceptions/OFConditionStillWaitingException.h +++ src/exceptions/OFConditionStillWaitingException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -37,26 +37,30 @@ } /** * @brief The condition for which is still being waited. */ -@property OF_NULLABLE_PROPERTY (readonly, nonatomic) OFCondition *condition; +@property (readonly, nonatomic) OFCondition *condition; /** * @brief Creates a new, autoreleased condition still waiting exception. * * @param condition The condition for which is still being waited * @return A new, autoreleased condition still waiting exception */ -+ (instancetype)exceptionWithCondition: (nullable OFCondition *)condition; ++ (instancetype)exceptionWithCondition: (OFCondition *)condition; + ++ (instancetype)exception OF_UNAVAILABLE; /** * @brief Initializes an already allocated condition still waiting exception. * * @param condition The condition for which is still being waited * @return An initialized condition still waiting exception */ -- (instancetype)initWithCondition: (nullable OFCondition *)condition +- (instancetype)initWithCondition: (OFCondition *)condition OF_DESIGNATED_INITIALIZER; + +- (instancetype)init OF_UNAVAILABLE; @end OF_ASSUME_NONNULL_END Index: src/exceptions/OFConditionStillWaitingException.m ================================================================== --- src/exceptions/OFConditionStillWaitingException.m +++ src/exceptions/OFConditionStillWaitingException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -25,13 +25,13 @@ + (instancetype)exceptionWithCondition: (OFCondition *)condition { return [[[self alloc] initWithCondition: condition] autorelease]; } -- (instancetype)init ++ (instancetype)exception { - return [self initWithCondition: nil]; + OF_UNRECOGNIZED_SELECTOR } - (instancetype)initWithCondition: (OFCondition *)condition { self = [super init]; @@ -38,10 +38,15 @@ _condition = [condition retain]; return self; } + +- (instancetype)init +{ + OF_INVALID_INIT_METHOD +} - (void)dealloc { [_condition release]; @@ -48,15 +53,11 @@ [super dealloc]; } - (OFString *)description { - if (_condition != nil) - return [OFString stringWithFormat: - @"Deallocation of a condition of type %@ was tried, even " - "though a thread was still waiting for it!", - _condition.class]; - else - return @"Deallocation of a condition was tried, even though a " - "thread was still waiting for it!"; + return [OFString stringWithFormat: + @"Deallocation of a condition of type %@ was tried, even though " + "a thread was still waiting for it!", + _condition.class]; } @end Index: src/exceptions/OFConditionWaitFailedException.h ================================================================== --- src/exceptions/OFConditionWaitFailedException.h +++ src/exceptions/OFConditionWaitFailedException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -37,11 +37,11 @@ } /** * @brief The condition for which could not be waited. */ -@property OF_NULLABLE_PROPERTY (readonly, nonatomic) OFCondition *condition; +@property (readonly, nonatomic) OFCondition *condition; /** * @brief The errno of the error that occurred. */ @property (readonly, nonatomic) int errNo; @@ -51,22 +51,24 @@ * * @param condition The condition for which could not be waited * @param errNo The errno of the error that occurred * @return A new, autoreleased condition wait failed exception */ -+ (instancetype)exceptionWithCondition: (nullable OFCondition *)condition ++ (instancetype)exceptionWithCondition: (OFCondition *)condition errNo: (int)errNo; + ++ (instancetype)exception OF_UNAVAILABLE; /** * @brief Initializes an already allocated condition wait failed exception. * * @param condition The condition for which could not be waited * @param errNo The errno of the error that occurred * @return An initialized condition wait failed exception */ -- (instancetype)initWithCondition: (nullable OFCondition *)condition +- (instancetype)initWithCondition: (OFCondition *)condition errNo: (int)errNo OF_DESIGNATED_INITIALIZER; - (instancetype)init OF_UNAVAILABLE; @end OF_ASSUME_NONNULL_END Index: src/exceptions/OFConditionWaitFailedException.m ================================================================== --- src/exceptions/OFConditionWaitFailedException.m +++ src/exceptions/OFConditionWaitFailedException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -28,10 +28,15 @@ errNo: (int)errNo { return [[[self alloc] initWithCondition: condition errNo: errNo] autorelease]; } + ++ (instancetype)exception +{ + OF_UNRECOGNIZED_SELECTOR +} - (instancetype)initWithCondition: (OFCondition *)condition errNo: (int)errNo { self = [super init]; Index: src/exceptions/OFConnectionFailedException.h ================================================================== --- src/exceptions/OFConnectionFailedException.h +++ src/exceptions/OFConnectionFailedException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -29,23 +29,19 @@ * * @brief An exception indicating that a connection could not be established. */ @interface OFConnectionFailedException: OFException { - id _socket; - OFString *_host; + OFString *_Nullable _host; uint16_t _port; - unsigned char _node[IPX_NODE_LEN]; + OFString *_Nullable _path; uint32_t _network; + unsigned char _node[IPX_NODE_LEN]; + id _socket; int _errNo; } -/** - * @brief The socket which could not connect. - */ -@property (readonly, nonatomic) id socket; - /** * @brief The host to which the connection failed. */ @property OF_NULLABLE_PROPERTY (readonly, nonatomic) OFString *host; @@ -53,57 +49,78 @@ * @brief The port on the host to which the connection failed. */ @property (readonly, nonatomic) uint16_t port; /** - * @brief The IPX node to which the connection failed. + * @brief The path to which the connection failed. */ -@property (readonly, nonatomic) unsigned char *node; +@property OF_NULLABLE_PROPERTY (readonly, nonatomic) OFString *path; /** * @brief The IPX network of the node to which the connection failed. */ @property (readonly, nonatomic) uint32_t network; +/** + * @brief The IPX node to which the connection failed. + */ +@property (readonly, nonatomic) unsigned char *node; + +/** + * @brief The socket which could not connect. + */ +@property (readonly, nonatomic) id socket; + /** * @brief The errno of the error that occurred. */ @property (readonly, nonatomic) int errNo; -+ (instancetype)exception OF_UNAVAILABLE; - /** * @brief Creates a new, autoreleased connection failed exception. * * @param host The host to which the connection failed * @param port The port on the host to which the connection failed * @param socket The socket which could not connect * @param errNo The errno of the error that occurred * @return A new, autoreleased connection failed exception */ -+ (instancetype)exceptionWithHost: (nullable OFString *)host ++ (instancetype)exceptionWithHost: (OFString *)host port: (uint16_t)port socket: (id)socket errNo: (int)errNo; /** * @brief Creates a new, autoreleased connection failed exception. * - * @param node The node to which the connection failed + * @param path The path to which the connection failed + * @param socket The socket which could not connect + * @param errNo The errno of the error that occurred + * @return A new, autoreleased connection failed exception + */ ++ (instancetype)exceptionWithPath: (OFString *)path + socket: (id)socket + errNo: (int)errNo; + +/** + * @brief Creates a new, autoreleased connection failed exception. + * * @param network The IPX network of the node to which the connection failed + * @param node The node to which the connection failed * @param port The port on the node to which the connection failed * @param socket The socket which could not connect * @param errNo The errno of the error that occurred * @return A new, autoreleased connection failed exception */ -+ (instancetype)exceptionWithNode: (unsigned char [_Nullable IPX_NODE_LEN])node - network: (uint32_t)network - port: (uint16_t)port - socket: (id)socket - errNo: (int)errNo; ++ (instancetype) + exceptionWithNetwork: (uint32_t)network + node: (unsigned char [_Nullable IPX_NODE_LEN])node + port: (uint16_t)port + socket: (id)socket + errNo: (int)errNo; -- (instancetype)init OF_UNAVAILABLE; ++ (instancetype)exception OF_UNAVAILABLE; /** * @brief Initializes an already allocated connection failed exception. * * @param host The host to which the connection failed @@ -110,28 +127,42 @@ * @param port The port on the host to which the connection failed * @param socket The socket which could not connect * @param errNo The errno of the error that occurred * @return An initialized connection failed exception */ -- (instancetype)initWithHost: (nullable OFString *)host +- (instancetype)initWithHost: (OFString *)host port: (uint16_t)port socket: (id)socket errNo: (int)errNo; /** * @brief Initializes an already allocated connection failed exception. * - * @param node The node to which the connection failed + * @param path The path to which the connection failed + * @param socket The socket which could not connect + * @param errNo The errno of the error that occurred + * @return An initialized connection failed exception + */ +- (instancetype)initWithPath: (OFString *)path + socket: (id)socket + errNo: (int)errNo; + +/** + * @brief Initializes an already allocated connection failed exception. + * * @param network The IPX network of the node to which the connection failed + * @param node The node to which the connection failed * @param port The port on the node to which the connection failed * @param socket The socket which could not connect * @param errNo The errno of the error that occurred * @return An initialized connection failed exception */ -- (instancetype)initWithNode: (unsigned char [_Nullable IPX_NODE_LEN])node - network: (uint32_t)network - port: (uint16_t)port - socket: (id)socket - errNo: (int)errNo; +- (instancetype)initWithNetwork: (uint32_t)network + node: (unsigned char [_Nullable IPX_NODE_LEN])node + port: (uint16_t)port + socket: (id)socket + errNo: (int)errNo; + +- (instancetype)init OF_UNAVAILABLE; @end OF_ASSUME_NONNULL_END Index: src/exceptions/OFConnectionFailedException.m ================================================================== --- src/exceptions/OFConnectionFailedException.m +++ src/exceptions/OFConnectionFailedException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -17,17 +17,12 @@ #import "OFConnectionFailedException.h" #import "OFString.h" @implementation OFConnectionFailedException -@synthesize host = _host, port = _port, network = _network, socket = _socket; -@synthesize errNo = _errNo; - -+ (instancetype)exception -{ - OF_UNRECOGNIZED_SELECTOR -} +@synthesize host = _host, port = _port, path = _path, network = _network; +@synthesize socket = _socket, errNo = _errNo; + (instancetype)exceptionWithHost: (OFString *)host port: (uint16_t)port socket: (id)sock errNo: (int)errNo @@ -36,26 +31,35 @@ port: port socket: sock errNo: errNo] autorelease]; } -+ (instancetype)exceptionWithNode: (unsigned char [IPX_NODE_LEN])node - network: (uint32_t)network - port: (uint16_t)port ++ (instancetype)exception +{ + OF_UNRECOGNIZED_SELECTOR +} + ++ (instancetype)exceptionWithPath: (OFString *)path socket: (id)sock errNo: (int)errNo { - return [[[self alloc] initWithNode: node - network: network - port: port + return [[[self alloc] initWithPath: path socket: sock errNo: errNo] autorelease]; } -- (instancetype)init ++ (instancetype)exceptionWithNetwork: (uint32_t)network + node: (unsigned char [IPX_NODE_LEN])node + port: (uint16_t)port + socket: (id)sock + errNo: (int)errNo { - OF_INVALID_INIT_METHOD + return [[[self alloc] initWithNetwork: network + node: node + port: port + socket: sock + errNo: errNo] autorelease]; } - (instancetype)initWithHost: (OFString *)host port: (uint16_t)port socket: (id)sock @@ -74,21 +78,39 @@ } return self; } -- (instancetype)initWithNode: (unsigned char [IPX_NODE_LEN])node - network: (uint32_t)network - port: (uint16_t)port +- (instancetype)initWithPath: (OFString *)path socket: (id)sock errNo: (int)errNo { self = [super init]; @try { - memcpy(_node, node, IPX_NODE_LEN); + _path = [path copy]; + _socket = [sock retain]; + _errNo = errNo; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (instancetype)initWithNetwork: (uint32_t)network + node: (unsigned char [IPX_NODE_LEN])node + port: (uint16_t)port + socket: (id)sock + errNo: (int)errNo +{ + self = [super init]; + + @try { _network = network; + memcpy(_node, node, IPX_NODE_LEN); _port = port; _socket = [sock retain]; _errNo = errNo; } @catch (id e) { [self release]; @@ -95,14 +117,20 @@ @throw e; } return self; } + +- (instancetype)init +{ + OF_INVALID_INIT_METHOD +} - (void)dealloc { [_host release]; + [_path release]; [_socket release]; [super dealloc]; } @@ -111,11 +139,16 @@ return _node; } - (OFString *)description { - if (_host != nil) + if (_path != nil) + return [OFString stringWithFormat: + @"A connection to %@ could not be established in socket of " + @"type %@: %@", + _path, [_socket class], OFStrError(_errNo)]; + else if (_host != nil) return [OFString stringWithFormat: @"A connection to %@ on port %" @PRIu16 @" could not be " @"established in socket of type %@: %@", _host, _port, [_socket class], OFStrError(_errNo)]; else if (memcmp(_node, "\0\0\0\0\0", IPX_NODE_LEN) == 0) Index: src/exceptions/OFCopyItemFailedException.h ================================================================== --- src/exceptions/OFCopyItemFailedException.h +++ src/exceptions/OFCopyItemFailedException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -30,49 +30,49 @@ OFURL *_sourceURL, *_destinationURL; int _errNo; } /** - * @brief The path of the source item. + * @brief The URL of the source item. */ @property (readonly, nonatomic) OFURL *sourceURL; /** - * @brief The destination path. + * @brief The destination URL. */ @property (readonly, nonatomic) OFURL *destinationURL; /** * @brief The errno of the error that occurred. */ @property (readonly, nonatomic) int errNo; -+ (instancetype)exception OF_UNAVAILABLE; - /** * @brief Creates a new, autoreleased copy item failed exception. * - * @param sourceURL The original path - * @param destinationURL The new path + * @param sourceURL The URL of the source item + * @param destinationURL The destination URL * @param errNo The errno of the error that occurred * @return A new, autoreleased copy item failed exception */ + (instancetype)exceptionWithSourceURL: (OFURL *)sourceURL destinationURL: (OFURL *)destinationURL errNo: (int)errNo; -- (instancetype)init OF_UNAVAILABLE; ++ (instancetype)exception OF_UNAVAILABLE; /** * @brief Initializes an already allocated copy item failed exception. * - * @param sourceURL The original path - * @param destinationURL The new path + * @param sourceURL The URL of the source item + * @param destinationURL The destination URL * @param errNo The errno of the error that occurred * @return An initialized copy item failed exception */ - (instancetype)initWithSourceURL: (OFURL *)sourceURL destinationURL: (OFURL *)destinationURL errNo: (int)errNo OF_DESIGNATED_INITIALIZER; + +- (instancetype)init OF_UNAVAILABLE; @end OF_ASSUME_NONNULL_END Index: src/exceptions/OFCopyItemFailedException.m ================================================================== --- src/exceptions/OFCopyItemFailedException.m +++ src/exceptions/OFCopyItemFailedException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/exceptions/OFCreateDirectoryFailedException.h ================================================================== --- src/exceptions/OFCreateDirectoryFailedException.h +++ src/exceptions/OFCreateDirectoryFailedException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -40,22 +40,20 @@ /** * @brief The errno of the error that occurred. */ @property (readonly, nonatomic) int errNo; -+ (instancetype)exception OF_UNAVAILABLE; - /** * @brief Creates a new, autoreleased create directory failed exception. * * @param URL The URL of the directory which could not be created * @param errNo The errno of the error that occurred * @return A new, autoreleased create directory failed exception */ + (instancetype)exceptionWithURL: (OFURL *)URL errNo: (int)errNo; -- (instancetype)init OF_UNAVAILABLE; ++ (instancetype)exception OF_UNAVAILABLE; /** * @brief Initializes an already allocated create directory failed exception. * * @param URL The URL of the directory which could not be created @@ -62,8 +60,10 @@ * @param errNo The errno of the error that occurred * @return An initialized create directory failed exception */ - (instancetype)initWithURL: (OFURL *)URL errNo: (int)errNo OF_DESIGNATED_INITIALIZER; + +- (instancetype)init OF_UNAVAILABLE; @end OF_ASSUME_NONNULL_END Index: src/exceptions/OFCreateDirectoryFailedException.m ================================================================== --- src/exceptions/OFCreateDirectoryFailedException.m +++ src/exceptions/OFCreateDirectoryFailedException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/exceptions/OFCreateSymbolicLinkFailedException.h ================================================================== --- src/exceptions/OFCreateSymbolicLinkFailedException.h +++ src/exceptions/OFCreateSymbolicLinkFailedException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -46,12 +46,10 @@ /** * @brief The errno of the error that occurred. */ @property (readonly, nonatomic) int errNo; -+ (instancetype)exception OF_UNAVAILABLE; - /** * @brief Creates a new, autoreleased create symbolic link failed exception. * * @param URL The URL where the symlink should have been created * @param target The target for the symbolic link @@ -60,11 +58,11 @@ */ + (instancetype)exceptionWithURL: (OFURL *)URL target: (OFString *)target errNo: (int)errNo; -- (instancetype)init OF_UNAVAILABLE; ++ (instancetype)exception OF_UNAVAILABLE; /** * @brief Initializes an already allocated create symbolic link failed * exception. * @@ -74,8 +72,10 @@ * @return An initialized create symbolic link failed exception */ - (instancetype)initWithURL: (OFURL *)URL target: (OFString *)target errNo: (int)errNo OF_DESIGNATED_INITIALIZER; + +- (instancetype)init OF_UNAVAILABLE; @end OF_ASSUME_NONNULL_END Index: src/exceptions/OFCreateSymbolicLinkFailedException.m ================================================================== --- src/exceptions/OFCreateSymbolicLinkFailedException.m +++ src/exceptions/OFCreateSymbolicLinkFailedException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/exceptions/OFCreateWindowsRegistryKeyFailedException.h ================================================================== --- src/exceptions/OFCreateWindowsRegistryKeyFailedException.h +++ src/exceptions/OFCreateWindowsRegistryKeyFailedException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/exceptions/OFCreateWindowsRegistryKeyFailedException.m ================================================================== --- src/exceptions/OFCreateWindowsRegistryKeyFailedException.m +++ src/exceptions/OFCreateWindowsRegistryKeyFailedException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/exceptions/OFDNSQueryFailedException.h ================================================================== --- src/exceptions/OFDNSQueryFailedException.h +++ src/exceptions/OFDNSQueryFailedException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -50,19 +50,23 @@ * @return A new, autoreleased address translation failed exception */ + (instancetype)exceptionWithQuery: (OFDNSQuery *)query errorCode: (OFDNSResolverErrorCode)errorCode; ++ (instancetype)exception OF_UNAVAILABLE; + /** * @brief Initializes an already allocated DNS query failed exception. * * @param query The query which could not be performed * @param errorCode The error from the resolver * @return An initialized address translation failed exception */ - (instancetype)initWithQuery: (OFDNSQuery *)query errorCode: (OFDNSResolverErrorCode)errorCode; + +- (instancetype)init OF_UNAVAILABLE; @end #ifdef __cplusplus extern "C" { #endif Index: src/exceptions/OFDNSQueryFailedException.m ================================================================== --- src/exceptions/OFDNSQueryFailedException.m +++ src/exceptions/OFDNSQueryFailedException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -56,10 +56,15 @@ errorCode: (OFDNSResolverErrorCode)errorCode { return [[[self alloc] initWithQuery: query errorCode: errorCode] autorelease]; } + ++ (instancetype)exception +{ + OF_UNRECOGNIZED_SELECTOR +} - (instancetype)initWithQuery: (OFDNSQuery *)query errorCode: (OFDNSResolverErrorCode)errorCode { self = [super init]; @@ -72,10 +77,15 @@ @throw e; } return self; } + +- (instancetype)init +{ + OF_INVALID_INIT_METHOD +} - (void)dealloc { [_query release]; Index: src/exceptions/OFDeleteWindowsRegistryKeyFailedException.h ================================================================== --- src/exceptions/OFDeleteWindowsRegistryKeyFailedException.h +++ src/exceptions/OFDeleteWindowsRegistryKeyFailedException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/exceptions/OFDeleteWindowsRegistryKeyFailedException.m ================================================================== --- src/exceptions/OFDeleteWindowsRegistryKeyFailedException.m +++ src/exceptions/OFDeleteWindowsRegistryKeyFailedException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/exceptions/OFDeleteWindowsRegistryValueFailedException.h ================================================================== --- src/exceptions/OFDeleteWindowsRegistryValueFailedException.h +++ src/exceptions/OFDeleteWindowsRegistryValueFailedException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/exceptions/OFDeleteWindowsRegistryValueFailedException.m ================================================================== --- src/exceptions/OFDeleteWindowsRegistryValueFailedException.m +++ src/exceptions/OFDeleteWindowsRegistryValueFailedException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/exceptions/OFEnumerationMutationException.h ================================================================== --- src/exceptions/OFEnumerationMutationException.h +++ src/exceptions/OFEnumerationMutationException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -33,27 +33,27 @@ /** * @brief The object which was mutated during enumeration. */ @property (readonly, nonatomic) id object; -+ (instancetype)exception OF_UNAVAILABLE; - /** * @brief Creates a new, autoreleased enumeration mutation exception. * * @param object The object which was mutated during enumeration * @return A new, autoreleased enumeration mutation exception */ + (instancetype)exceptionWithObject: (id)object; -- (instancetype)init OF_UNAVAILABLE; ++ (instancetype)exception OF_UNAVAILABLE; /** * @brief Initializes an already allocated enumeration mutation exception. * * @param object The object which was mutated during enumeration * @return An initialized enumeration mutation exception */ - (instancetype)initWithObject: (id)object OF_DESIGNATED_INITIALIZER; + +- (instancetype)init OF_UNAVAILABLE; @end OF_ASSUME_NONNULL_END Index: src/exceptions/OFEnumerationMutationException.m ================================================================== --- src/exceptions/OFEnumerationMutationException.m +++ src/exceptions/OFEnumerationMutationException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/exceptions/OFException.h ================================================================== --- src/exceptions/OFException.h +++ src/exceptions/OFException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -132,10 +132,14 @@ # endif # ifndef EWOULDBLOCK # define EWOULDBLOCK WSAEWOULDBLOCK # endif #endif + +#ifndef EWOULDBLOCK +# define EWOULDBLOCK EAGAIN +#endif /** * @class OFException OFException.h ObjFW/OFException.h * * @brief The base class for all exceptions in ObjFW Index: src/exceptions/OFException.m ================================================================== --- src/exceptions/OFException.m +++ src/exceptions/OFException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/exceptions/OFGetCurrentDirectoryPathFailedException.h ================================================================== --- src/exceptions/OFGetCurrentDirectoryPathFailedException.h +++ src/exceptions/OFGetCurrentDirectoryPathFailedException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -33,29 +33,29 @@ /** * @brief The errno of the error that occurred. */ @property (readonly, nonatomic) int errNo; -+ (instancetype)exception OF_UNAVAILABLE; - /** * @brief Creates a new, autoreleased get current directory path failed * exception. * * @param errNo The errno of the error that occurred * @return A new, autoreleased get current directory failed exception */ + (instancetype)exceptionWithErrNo: (int)errNo; -- (instancetype)init OF_UNAVAILABLE; ++ (instancetype)exception OF_UNAVAILABLE; /** * @brief Initializes an already allocated get current directory path failed * exception. * * @param errNo The errno of the error that occurred * @return An initialized get current directory path failed exception */ - (instancetype)initWithErrNo: (int)errNo OF_DESIGNATED_INITIALIZER; + +- (instancetype)init OF_UNAVAILABLE; @end OF_ASSUME_NONNULL_END Index: src/exceptions/OFGetCurrentDirectoryPathFailedException.m ================================================================== --- src/exceptions/OFGetCurrentDirectoryPathFailedException.m +++ src/exceptions/OFGetCurrentDirectoryPathFailedException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -19,23 +19,18 @@ #import "OFString.h" @implementation OFGetCurrentDirectoryPathFailedException @synthesize errNo = _errNo; -+ (instancetype)exception -{ - OF_UNRECOGNIZED_SELECTOR -} - + (instancetype)exceptionWithErrNo: (int)errNo { return [[[self alloc] initWithErrNo: errNo] autorelease]; } -- (instancetype)init ++ (instancetype)exception { - OF_INVALID_INIT_METHOD + OF_UNRECOGNIZED_SELECTOR } - (instancetype)initWithErrNo: (int)errNo { self = [super init]; @@ -42,13 +37,18 @@ _errNo = errNo; return self; } + +- (instancetype)init +{ + OF_INVALID_INIT_METHOD +} - (OFString *)description { return [OFString stringWithFormat: @"Getting the current directory path failed: %@", OFStrError(_errNo)]; } @end Index: src/exceptions/OFGetOptionFailedException.h ================================================================== --- src/exceptions/OFGetOptionFailedException.h +++ src/exceptions/OFGetOptionFailedException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -37,22 +37,20 @@ /** * @brief The errno of the error that occurred. */ @property (readonly, nonatomic) int errNo; -+ (instancetype)exception OF_UNAVAILABLE; - /** * @brief Creates a new, autoreleased get option failed exception. * * @param object The object for which the option could not be retrieved * @param errNo The errno of the error that occurred * @return A new, autoreleased get option failed exception */ + (instancetype)exceptionWithObject: (id)object errNo: (int)errNo; -- (instancetype)init OF_UNAVAILABLE; ++ (instancetype)exception OF_UNAVAILABLE; /** * @brief Initializes an already allocated get option failed exception. * * @param object The object for which the option could not be retrieved @@ -59,8 +57,10 @@ * @param errNo The errno of the error that occurred * @return An initialized get option failed exception */ - (instancetype)initWithObject: (id)object errNo: (int)errNo OF_DESIGNATED_INITIALIZER; + +- (instancetype)init OF_UNAVAILABLE; @end OF_ASSUME_NONNULL_END Index: src/exceptions/OFGetOptionFailedException.m ================================================================== --- src/exceptions/OFGetOptionFailedException.m +++ src/exceptions/OFGetOptionFailedException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/exceptions/OFGetWindowsRegistryValueFailedException.h ================================================================== --- src/exceptions/OFGetWindowsRegistryValueFailedException.h +++ src/exceptions/OFGetWindowsRegistryValueFailedException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -62,11 +62,11 @@ */ + (instancetype)exceptionWithRegistryKey: (OFWindowsRegistryKey *)registryKey valueName: (nullable OFString *)valueName status: (LSTATUS)status; -- (instancetype)init OF_UNAVAILABLE; ++ (instancetype)exception OF_UNAVAILABLE; /** * @brief Initializes an already allocated get Windows registry value failed * exception. * @@ -77,8 +77,10 @@ * @return An initialized get Windows registry value failed exception */ - (instancetype)initWithRegistryKey: (OFWindowsRegistryKey *)registryKey valueName: (nullable OFString *)valueName status: (LSTATUS)status OF_DESIGNATED_INITIALIZER; + +- (instancetype)init OF_UNAVAILABLE; @end OF_ASSUME_NONNULL_END Index: src/exceptions/OFGetWindowsRegistryValueFailedException.m ================================================================== --- src/exceptions/OFGetWindowsRegistryValueFailedException.m +++ src/exceptions/OFGetWindowsRegistryValueFailedException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -28,13 +28,13 @@ return [[[self alloc] initWithRegistryKey: registryKey valueName: valueName status: status] autorelease]; } -- (instancetype)init ++ (instancetype)exception { - OF_INVALID_INIT_METHOD + OF_UNRECOGNIZED_SELECTOR } - (instancetype)initWithRegistryKey: (OFWindowsRegistryKey *)registryKey valueName: (OFString *)valueName status: (LSTATUS)status @@ -50,10 +50,15 @@ @throw e; } return self; } + +- (instancetype)init +{ + OF_INVALID_INIT_METHOD +} - (void)dealloc { [_registryKey release]; [_valueName release]; Index: src/exceptions/OFHTTPRequestFailedException.h ================================================================== --- src/exceptions/OFHTTPRequestFailedException.h +++ src/exceptions/OFHTTPRequestFailedException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -45,12 +45,10 @@ /** * @brief The response for the failed HTTP request. */ @property (readonly, nonatomic) OFHTTPResponse *response; -+ (instancetype)exception OF_UNAVAILABLE; - /** * @brief Creates a new, autoreleased HTTP request failed exception. * * @param request The HTTP request which failed * @param response The response for the failed HTTP request @@ -57,11 +55,11 @@ * @return A new, autoreleased HTTP request failed exception */ + (instancetype)exceptionWithRequest: (OFHTTPRequest *)request response: (OFHTTPResponse *)response; -- (instancetype)init OF_UNAVAILABLE; ++ (instancetype)exception OF_UNAVAILABLE; /** * @brief Initializes an already allocated HTTP request failed exception. * * @param request The HTTP request which failed @@ -69,8 +67,10 @@ * @return A new HTTP request failed exception */ - (instancetype)initWithRequest: (OFHTTPRequest *)request response: (OFHTTPResponse *)response OF_DESIGNATED_INITIALIZER; + +- (instancetype)init OF_UNAVAILABLE; @end OF_ASSUME_NONNULL_END Index: src/exceptions/OFHTTPRequestFailedException.m ================================================================== --- src/exceptions/OFHTTPRequestFailedException.m +++ src/exceptions/OFHTTPRequestFailedException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -21,25 +21,20 @@ #import "OFHTTPResponse.h" @implementation OFHTTPRequestFailedException @synthesize request = _request, response = _response; -+ (instancetype)exception -{ - OF_UNRECOGNIZED_SELECTOR -} - + (instancetype)exceptionWithRequest: (OFHTTPRequest *)request response: (OFHTTPResponse *)response { return [[[self alloc] initWithRequest: request response: response] autorelease]; } -- (instancetype)init ++ (instancetype)exception { - OF_INVALID_INIT_METHOD + OF_UNRECOGNIZED_SELECTOR } - (instancetype)initWithRequest: (OFHTTPRequest *)request response: (OFHTTPResponse *)response { @@ -48,10 +43,15 @@ _request = [request retain]; _response = [response retain]; return self; } + +- (instancetype)init +{ + OF_INVALID_INIT_METHOD +} - (void)dealloc { [_request release]; [_response release]; Index: src/exceptions/OFHashAlreadyCalculatedException.h ================================================================== --- src/exceptions/OFHashAlreadyCalculatedException.h +++ src/exceptions/OFHashAlreadyCalculatedException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -32,27 +32,27 @@ /** * @brief The hash which has already been calculated. */ @property (readonly, nonatomic) id object; -+ (instancetype)exception OF_UNAVAILABLE; - /** * @brief Creates a new, autoreleased hash already calculated exception. * * @param object The hash which has already been calculated * @return A new, autoreleased hash already calculated exception */ + (instancetype)exceptionWithObject: (id)object; -- (instancetype)init OF_UNAVAILABLE; ++ (instancetype)exception OF_UNAVAILABLE; /** * @brief Initializes an already allocated hash already calculated exception. * * @param object The hash which has already been calculated * @return An initialized hash already calculated exception */ - (instancetype)initWithObject: (id)object OF_DESIGNATED_INITIALIZER; + +- (instancetype)init OF_UNAVAILABLE; @end OF_ASSUME_NONNULL_END Index: src/exceptions/OFHashAlreadyCalculatedException.m ================================================================== --- src/exceptions/OFHashAlreadyCalculatedException.m +++ src/exceptions/OFHashAlreadyCalculatedException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in ADDED src/exceptions/OFHashNotCalculatedException.h Index: src/exceptions/OFHashNotCalculatedException.h ================================================================== --- src/exceptions/OFHashNotCalculatedException.h +++ src/exceptions/OFHashNotCalculatedException.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2008-2022 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#import "OFException.h" + +OF_ASSUME_NONNULL_BEGIN + +/** + * @class OFHashNotCalculatedException OFHashNotCalculatedException.h \ + * ObjFW/OFHashNotCalculatedException.h + * + * @brief An exception indicating that the hash has not been calculated yet. + */ +@interface OFHashNotCalculatedException: OFException +{ + id _object; +} + +/** + * @brief The hash which has not been calculated yet. + */ +@property (readonly, nonatomic) id object; + +/** + * @brief Creates a new, autoreleased hash not calculated exception. + * + * @param object The hash which has not been calculated yet + * @return A new, autoreleased hash not calculated exception + */ ++ (instancetype)exceptionWithObject: (id)object; + ++ (instancetype)exception OF_UNAVAILABLE; + +/** + * @brief Initializes an already allocated hash not calculated exception. + * + * @param object The hash which has not been calculated yet + * @return An initialized hash not calculated exception + */ +- (instancetype)initWithObject: (id)object OF_DESIGNATED_INITIALIZER; + +- (instancetype)init OF_UNAVAILABLE; +@end + +OF_ASSUME_NONNULL_END ADDED src/exceptions/OFHashNotCalculatedException.m Index: src/exceptions/OFHashNotCalculatedException.m ================================================================== --- src/exceptions/OFHashNotCalculatedException.m +++ src/exceptions/OFHashNotCalculatedException.m @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2008-2022 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 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 "OFHashNotCalculatedException.h" +#import "OFString.h" + +@implementation OFHashNotCalculatedException +@synthesize object = _object; + ++ (instancetype)exception +{ + OF_UNRECOGNIZED_SELECTOR +} + ++ (instancetype)exceptionWithObject: (id)object +{ + return [[[self alloc] initWithObject: object] autorelease]; +} + +- (instancetype)init +{ + OF_INVALID_INIT_METHOD +} + +- (instancetype)initWithObject: (id)object +{ + self = [super init]; + + _object = [object retain]; + + return self; +} + +- (void)dealloc +{ + [_object release]; + + [super dealloc]; +} + +- (OFString *)description +{ + return [OFString stringWithFormat: + @"The hash of type %@ has not been calculated yet!", + [_object class]]; +} +@end Index: src/exceptions/OFInitializationFailedException.h ================================================================== --- src/exceptions/OFInitializationFailedException.h +++ src/exceptions/OFInitializationFailedException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/exceptions/OFInitializationFailedException.m ================================================================== --- src/exceptions/OFInitializationFailedException.m +++ src/exceptions/OFInitializationFailedException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/exceptions/OFInvalidArgumentException.h ================================================================== --- src/exceptions/OFInvalidArgumentException.h +++ src/exceptions/OFInvalidArgumentException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/exceptions/OFInvalidArgumentException.m ================================================================== --- src/exceptions/OFInvalidArgumentException.m +++ src/exceptions/OFInvalidArgumentException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/exceptions/OFInvalidEncodingException.h ================================================================== --- src/exceptions/OFInvalidEncodingException.h +++ src/exceptions/OFInvalidEncodingException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/exceptions/OFInvalidEncodingException.m ================================================================== --- src/exceptions/OFInvalidEncodingException.m +++ src/exceptions/OFInvalidEncodingException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/exceptions/OFInvalidFormatException.h ================================================================== --- src/exceptions/OFInvalidFormatException.h +++ src/exceptions/OFInvalidFormatException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/exceptions/OFInvalidFormatException.m ================================================================== --- src/exceptions/OFInvalidFormatException.m +++ src/exceptions/OFInvalidFormatException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/exceptions/OFInvalidJSONException.h ================================================================== --- src/exceptions/OFInvalidJSONException.h +++ src/exceptions/OFInvalidJSONException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -37,12 +37,10 @@ /** * @brief The line in which parsing the JSON representation failed. */ @property (readonly, nonatomic) size_t line; -+ (instancetype)exception OF_UNAVAILABLE; - /** * @brief Creates a new, autoreleased invalid JSON exception. * * @param string The string containing the invalid JSON representation * @param line The line in which the parsing error was encountered @@ -49,11 +47,11 @@ * @return A new, autoreleased invalid JSON exception */ + (instancetype)exceptionWithString: (nullable OFString *)string line: (size_t)line; -- (instancetype)init OF_UNAVAILABLE; ++ (instancetype)exception OF_UNAVAILABLE; /** * @brief Initializes an already allocated invalid JSON exception. * * @param string The string containing the invalid JSON representation @@ -60,8 +58,10 @@ * @param line The line in which the parsing error was encountered * @return An initialized invalid JSON exception */ - (instancetype)initWithString: (nullable OFString *)string line: (size_t)line OF_DESIGNATED_INITIALIZER; + +- (instancetype)init OF_UNAVAILABLE; @end OF_ASSUME_NONNULL_END Index: src/exceptions/OFInvalidJSONException.m ================================================================== --- src/exceptions/OFInvalidJSONException.m +++ src/exceptions/OFInvalidJSONException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/exceptions/OFInvalidServerReplyException.h ================================================================== --- src/exceptions/OFInvalidServerReplyException.h +++ src/exceptions/OFInvalidServerReplyException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/exceptions/OFInvalidServerReplyException.m ================================================================== --- src/exceptions/OFInvalidServerReplyException.m +++ src/exceptions/OFInvalidServerReplyException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/exceptions/OFLinkFailedException.h ================================================================== --- src/exceptions/OFLinkFailedException.h +++ src/exceptions/OFLinkFailedException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -44,12 +44,10 @@ /** * @brief The errno of the error that occurred. */ @property (readonly, nonatomic) int errNo; -+ (instancetype)exception OF_UNAVAILABLE; - /** * @brief Creates a new, autoreleased link failed exception. * * @param sourceURL The source for the link * @param destinationURL The destination for the link @@ -58,11 +56,11 @@ */ + (instancetype)exceptionWithSourceURL: (OFURL *)sourceURL destinationURL: (OFURL *)destinationURL errNo: (int)errNo; -- (instancetype)init OF_UNAVAILABLE; ++ (instancetype)exception OF_UNAVAILABLE; /** * @brief Initializes an already allocated link failed exception. * * @param sourceURL The source for the link @@ -71,8 +69,10 @@ * @return An initialized link failed exception */ - (instancetype)initWithSourceURL: (OFURL*)sourceURL destinationURL: (OFURL *)destinationURL errNo: (int)errNo OF_DESIGNATED_INITIALIZER; + +- (instancetype)init OF_UNAVAILABLE; @end OF_ASSUME_NONNULL_END Index: src/exceptions/OFLinkFailedException.m ================================================================== --- src/exceptions/OFLinkFailedException.m +++ src/exceptions/OFLinkFailedException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/exceptions/OFListenFailedException.h ================================================================== --- src/exceptions/OFListenFailedException.h +++ src/exceptions/OFListenFailedException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -46,12 +46,10 @@ /** * @brief The errno of the error that occurred. */ @property (readonly, nonatomic) int errNo; -+ (instancetype)exception OF_UNAVAILABLE; - /** * @brief Creates a new, autoreleased listen failed exception. * * @param socket The socket which failed to listen * @param backlog The requested size of the back log @@ -60,21 +58,23 @@ */ + (instancetype)exceptionWithSocket: (id)socket backlog: (int)backlog errNo: (int)errNo; -- (instancetype)init OF_UNAVAILABLE; ++ (instancetype)exception OF_UNAVAILABLE; /** - * @brief Initializes an already allocated listen failed exception + * @brief Initializes an already allocated listen failed exception. * * @param socket The socket which failed to listen * @param backlog The requested size of the back log * @param errNo The errno of the error that occurred * @return An initialized listen failed exception */ - (instancetype)initWithSocket: (id)socket backlog: (int)backlog errNo: (int)errNo OF_DESIGNATED_INITIALIZER; + +- (instancetype)init OF_UNAVAILABLE; @end OF_ASSUME_NONNULL_END Index: src/exceptions/OFListenFailedException.m ================================================================== --- src/exceptions/OFListenFailedException.m +++ src/exceptions/OFListenFailedException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/exceptions/OFLoadPluginFailedException.h ================================================================== --- src/exceptions/OFLoadPluginFailedException.h +++ src/exceptions/OFLoadPluginFailedException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -36,12 +36,10 @@ /** * @brief The error why the plugin could not be loaded, as a string */ @property OF_NULLABLE_PROPERTY (readonly, nonatomic) OFString *error; -+ (instancetype)exception OF_UNAVAILABLE; - /** * @brief Creates a new, autoreleased load plugin failed exception. * * @param path The path of the plugin which could not be loaded * @param error The error why the plugin could not be loaded, as a string @@ -48,11 +46,11 @@ * @return A new, autoreleased load plugin failed exception */ + (instancetype)exceptionWithPath: (OFString *)path error: (nullable OFString *)error; -- (instancetype)init OF_UNAVAILABLE; ++ (instancetype)exception OF_UNAVAILABLE; /** * @brief Initializes an already allocated load plugin failed exception. * * @param path The path of the plugin which could not be loaded @@ -60,8 +58,10 @@ * @return An initialized load plugin failed exception */ - (instancetype)initWithPath: (OFString *)path error: (nullable OFString *)error OF_DESIGNATED_INITIALIZER; + +- (instancetype)init OF_UNAVAILABLE; @end OF_ASSUME_NONNULL_END Index: src/exceptions/OFLoadPluginFailedException.m ================================================================== --- src/exceptions/OFLoadPluginFailedException.m +++ src/exceptions/OFLoadPluginFailedException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -19,23 +19,18 @@ #import "OFString.h" @implementation OFLoadPluginFailedException @synthesize path = _path, error = _error; -+ (instancetype)exception -{ - OF_UNRECOGNIZED_SELECTOR -} - + (instancetype)exceptionWithPath: (OFString *)path error: (OFString *)error { return [[[self alloc] initWithPath: path error: error] autorelease]; } -- (instancetype)init ++ (instancetype)exception { - OF_INVALID_INIT_METHOD + OF_UNRECOGNIZED_SELECTOR } - (instancetype)initWithPath: (OFString *)path error: (OFString *)error { self = [super init]; @@ -48,10 +43,15 @@ @throw e; } return self; } + +- (instancetype)init +{ + OF_INVALID_INIT_METHOD +} - (void)dealloc { [_path release]; [_error release]; Index: src/exceptions/OFLockFailedException.h ================================================================== --- src/exceptions/OFLockFailedException.h +++ src/exceptions/OFLockFailedException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -24,11 +24,11 @@ * * @brief An exception indicating that locking a lock failed. */ @interface OFLockFailedException: OFException { - id _lock; + id _Nullable _lock; int _errNo; } /** * @brief The lock which could not be locked. @@ -57,10 +57,8 @@ * @param errNo The errno of the error that occurred * @return An initialized lock failed exception */ - (instancetype)initWithLock: (nullable id )lock errNo: (int)errNo OF_DESIGNATED_INITIALIZER; - -- (instancetype)init OF_UNAVAILABLE; @end OF_ASSUME_NONNULL_END Index: src/exceptions/OFLockFailedException.m ================================================================== --- src/exceptions/OFLockFailedException.m +++ src/exceptions/OFLockFailedException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -36,24 +36,22 @@ _errNo = errNo; return self; } -- (instancetype)init -{ - OF_INVALID_INIT_METHOD -} - - (void)dealloc { [_lock release]; [super dealloc]; } - (OFString *)description { - return [OFString stringWithFormat: - @"A lock of type %@ could not be locked: %s", - [_lock class], strerror(_errNo)]; + if (_lock != nil) + return [OFString stringWithFormat: + @"A lock of type %@ could not be locked: %s", + [_lock class], strerror(_errNo)]; + else + return @"A lock could not be locked!"; } @end Index: src/exceptions/OFMalformedXMLException.h ================================================================== --- src/exceptions/OFMalformedXMLException.h +++ src/exceptions/OFMalformedXMLException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/exceptions/OFMalformedXMLException.m ================================================================== --- src/exceptions/OFMalformedXMLException.m +++ src/exceptions/OFMalformedXMLException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in DELETED src/exceptions/OFMemoryNotPartOfObjectException.h Index: src/exceptions/OFMemoryNotPartOfObjectException.h ================================================================== --- src/exceptions/OFMemoryNotPartOfObjectException.h +++ src/exceptions/OFMemoryNotPartOfObjectException.h @@ -1,68 +0,0 @@ -/* - * Copyright (c) 2008-2021 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#import "OFException.h" - -OF_ASSUME_NONNULL_BEGIN - -/** - * @class OFMemoryNotPartOfObjectException \ - * OFMemoryNotPartOfObjectException.h \ - * ObjFW/OFMemoryNotPartOfObjectException.h - * - * @brief An exception indicating the given memory is not part of the object. - */ -@interface OFMemoryNotPartOfObjectException: OFException -{ - void *_Nullable _pointer; - id _object; -} - -/** - * @brief A pointer to the memory which is not part of the object. - */ -@property OF_NULLABLE_PROPERTY (readonly, nonatomic) void *pointer; - -/** - * @brief The object which the memory is not part of. - */ -@property (readonly, nonatomic) id object; - -+ (instancetype)exception OF_UNAVAILABLE; - -/** - * @brief Creates a new, autoreleased memory not part of object exception. - * - * @param pointer A pointer to the memory that is not part of the object - * @param object The object which the memory is not part of - * @return A new, autoreleased memory not part of object exception - */ -+ (instancetype)exceptionWithPointer: (nullable void *)pointer - object: (id)object; - -- (instancetype)init OF_UNAVAILABLE; - -/** - * @brief Initializes an already allocated memory not part of object exception. - * - * @param pointer A pointer to the memory that is not part of the object - * @param object The object which the memory is not part of - * @return An initialized memory not part of object exception - */ -- (instancetype)initWithPointer: (nullable void *)pointer - object: (id)object OF_DESIGNATED_INITIALIZER; -@end - -OF_ASSUME_NONNULL_END DELETED src/exceptions/OFMemoryNotPartOfObjectException.m Index: src/exceptions/OFMemoryNotPartOfObjectException.m ================================================================== --- src/exceptions/OFMemoryNotPartOfObjectException.m +++ src/exceptions/OFMemoryNotPartOfObjectException.m @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2008-2021 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 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 "OFMemoryNotPartOfObjectException.h" -#import "OFString.h" - -@implementation OFMemoryNotPartOfObjectException -@synthesize pointer = _pointer, object = _object; - -+ (instancetype)exception -{ - OF_UNRECOGNIZED_SELECTOR -} - -+ (instancetype)exceptionWithPointer: (void *)pointer object: (id)object -{ - return [[[self alloc] initWithPointer: pointer - object: object] autorelease]; -} - -- (instancetype)init -{ - OF_INVALID_INIT_METHOD -} - -- (instancetype)initWithPointer: (void *)pointer object: (id)object -{ - self = [super init]; - - _pointer = pointer; - _object = [object retain]; - - return self; -} - -- (void)dealloc -{ - [_object release]; - - [super dealloc]; -} - -- (OFString *)description -{ - return [OFString stringWithFormat: - @"Deallocation or reallocation of memory not allocated as part of " - @"object of type %@ was attempted! It is also possible that there " - @"was an attempt to free the same memory twice.", - [_object class]]; -} -@end Index: src/exceptions/OFMoveItemFailedException.h ================================================================== --- src/exceptions/OFMoveItemFailedException.h +++ src/exceptions/OFMoveItemFailedException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -44,12 +44,10 @@ /** * @brief The errno of the error that occurred. */ @property (readonly, nonatomic) int errNo; -+ (instancetype)exception OF_UNAVAILABLE; - /** * @brief Creates a new, autoreleased move item failed exception. * * @param sourceURL The original URL * @param destinationURL The new URL @@ -58,11 +56,11 @@ */ + (instancetype)exceptionWithSourceURL: (OFURL *)sourceURL destinationURL: (OFURL *)destinationURL errNo: (int)errNo; -- (instancetype)init OF_UNAVAILABLE; ++ (instancetype)exception OF_UNAVAILABLE; /** * @brief Initializes an already allocated move item failed exception. * * @param sourceURL The original URL @@ -71,8 +69,10 @@ * @return An initialized move item failed exception */ - (instancetype)initWithSourceURL: (OFURL *)sourceURL destinationURL: (OFURL *)destinationURL errNo: (int)errNo OF_DESIGNATED_INITIALIZER; + +- (instancetype)init OF_UNAVAILABLE; @end OF_ASSUME_NONNULL_END Index: src/exceptions/OFMoveItemFailedException.m ================================================================== --- src/exceptions/OFMoveItemFailedException.m +++ src/exceptions/OFMoveItemFailedException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/exceptions/OFNotImplementedException.h ================================================================== --- src/exceptions/OFNotImplementedException.h +++ src/exceptions/OFNotImplementedException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -36,13 +36,11 @@ @property (readonly, nonatomic) SEL selector; /** * @brief The object which does not (fully) implement the selector. */ -@property (readonly, nonatomic) id object; - -+ (instancetype)exception OF_UNAVAILABLE; +@property OF_NULLABLE_PROPERTY (readonly, nonatomic) id object; /** * @brief Creates a new, autoreleased not implemented exception. * * @param selector The selector which is not or not fully implemented @@ -50,11 +48,11 @@ * @return A new, autoreleased not implemented exception */ + (instancetype)exceptionWithSelector: (SEL)selector object: (nullable id)object; -- (instancetype)init OF_UNAVAILABLE; ++ (instancetype)exception OF_UNAVAILABLE; /** * @brief Initializes an already allocated not implemented exception. * * @param selector The selector which is not or not fully implemented @@ -61,8 +59,10 @@ * @param object The object which does not (fully) implement the selector * @return An initialized not implemented exception */ - (instancetype)initWithSelector: (SEL)selector object: (nullable id)object OF_DESIGNATED_INITIALIZER; + +- (instancetype)init OF_UNAVAILABLE; @end OF_ASSUME_NONNULL_END Index: src/exceptions/OFNotImplementedException.m ================================================================== --- src/exceptions/OFNotImplementedException.m +++ src/exceptions/OFNotImplementedException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/exceptions/OFNotOpenException.h ================================================================== --- src/exceptions/OFNotOpenException.h +++ src/exceptions/OFNotOpenException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -30,27 +30,27 @@ /** * @brief The object which is not open, connected or bound. */ @property (readonly, nonatomic) id object; -+ (instancetype)exception OF_UNAVAILABLE; - /** * @brief Creates a new, autoreleased not open exception. * * @param object The object which is not open, connected or bound * @return A new, autoreleased not open exception */ + (instancetype)exceptionWithObject: (id)object; -- (instancetype)init OF_UNAVAILABLE; ++ (instancetype)exception OF_UNAVAILABLE; /** * @brief Initializes an already allocated not open exception. * * @param object The object which is not open, connected or bound * @return An initialized not open exception */ - (instancetype)initWithObject: (id)object OF_DESIGNATED_INITIALIZER; + +- (instancetype)init OF_UNAVAILABLE; @end OF_ASSUME_NONNULL_END Index: src/exceptions/OFNotOpenException.m ================================================================== --- src/exceptions/OFNotOpenException.m +++ src/exceptions/OFNotOpenException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/exceptions/OFObserveFailedException.h ================================================================== --- src/exceptions/OFObserveFailedException.h +++ src/exceptions/OFObserveFailedException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -39,12 +39,10 @@ /** * @brief The errno of the error that occurred. */ @property (readonly, nonatomic) int errNo; -+ (instancetype)exception OF_UNAVAILABLE; - /** * @brief Creates a new, autoreleased observe failed exception. * * @param observer The observer which failed to observe * @param errNo The errno of the error that occurred @@ -51,11 +49,11 @@ * @return A new, autoreleased observe failed exception */ + (instancetype)exceptionWithObserver: (OFKernelEventObserver *)observer errNo: (int)errNo; -- (instancetype)init OF_UNAVAILABLE; ++ (instancetype)exception OF_UNAVAILABLE; /** * @brief Initializes an already allocated observe failed exception. * * @param observer The observer which failed to observe @@ -62,8 +60,10 @@ * @param errNo The errno of the error that occurred * @return An initialized observe failed exception */ - (instancetype)initWithObserver: (OFKernelEventObserver *)observer errNo: (int)errNo OF_DESIGNATED_INITIALIZER; + +- (instancetype)init OF_UNAVAILABLE; @end OF_ASSUME_NONNULL_END Index: src/exceptions/OFObserveFailedException.m ================================================================== --- src/exceptions/OFObserveFailedException.m +++ src/exceptions/OFObserveFailedException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/exceptions/OFOpenItemFailedException.h ================================================================== --- src/exceptions/OFOpenItemFailedException.h +++ src/exceptions/OFOpenItemFailedException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -51,12 +51,10 @@ /** * @brief The errno of the error that occurred. */ @property (readonly, nonatomic) int errNo; -+ (instancetype)exception OF_UNAVAILABLE; - /** * @brief Creates a new, autoreleased open item failed exception. * * @param URL The URL of the item which could not be opened * @param mode A string with the mode in which the item should have been opened @@ -77,11 +75,11 @@ */ + (instancetype)exceptionWithPath: (OFString *)path mode: (nullable OFString *)mode errNo: (int)errNo; -- (instancetype)init OF_UNAVAILABLE; ++ (instancetype)exception OF_UNAVAILABLE; /** * @brief Initializes an already allocated open item failed exception. * * @param URL The URL of the item which could not be opened @@ -102,8 +100,10 @@ * @return An initialized open item failed exception */ - (instancetype)initWithPath: (OFString *)path mode: (nullable OFString *)mode errNo: (int)errNo; + +- (instancetype)init OF_UNAVAILABLE; @end OF_ASSUME_NONNULL_END Index: src/exceptions/OFOpenItemFailedException.m ================================================================== --- src/exceptions/OFOpenItemFailedException.m +++ src/exceptions/OFOpenItemFailedException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -20,15 +20,10 @@ #import "OFURL.h" @implementation OFOpenItemFailedException @synthesize URL = _URL, path = _path, mode = _mode, errNo = _errNo; -+ (instancetype)exception -{ - OF_UNRECOGNIZED_SELECTOR -} - + (instancetype)exceptionWithURL: (OFURL *)URL mode: (OFString *)mode errNo: (int)errNo { return [[[self alloc] initWithURL: URL @@ -43,13 +38,13 @@ return [[[self alloc] initWithPath: path mode: mode errNo: errNo] autorelease]; } -- (instancetype)init ++ (instancetype)exception { - OF_INVALID_INIT_METHOD + OF_UNRECOGNIZED_SELECTOR } - (instancetype)initWithURL: (OFURL *)URL mode: (OFString *)mode errNo: (int)errNo @@ -83,10 +78,15 @@ @throw e; } return self; } + +- (instancetype)init +{ + OF_INVALID_INIT_METHOD +} - (void)dealloc { [_URL release]; [_path release]; Index: src/exceptions/OFOpenWindowsRegistryKeyFailedException.h ================================================================== --- src/exceptions/OFOpenWindowsRegistryKeyFailedException.h +++ src/exceptions/OFOpenWindowsRegistryKeyFailedException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -80,11 +80,11 @@ path: (OFString *)path options: (DWORD)options securityAndAccessRights: (REGSAM)securityAndAccessRights status: (LSTATUS)status; -- (instancetype)init OF_UNAVAILABLE; ++ (instancetype)exception OF_UNAVAILABLE; /** * @brief Initializes an already allocated open Windows registry key failed * exception. * @@ -100,8 +100,10 @@ initWithRegistryKey: (OFWindowsRegistryKey *)registryKey path: (OFString *)path options: (DWORD)options securityAndAccessRights: (REGSAM)securityAndAccessRights status: (LSTATUS)status OF_DESIGNATED_INITIALIZER; + +- (instancetype)init OF_UNAVAILABLE; @end OF_ASSUME_NONNULL_END Index: src/exceptions/OFOpenWindowsRegistryKeyFailedException.m ================================================================== --- src/exceptions/OFOpenWindowsRegistryKeyFailedException.m +++ src/exceptions/OFOpenWindowsRegistryKeyFailedException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -34,13 +34,13 @@ options: options securityAndAccessRights: securityAndAccessRights status: status] autorelease]; } -- (instancetype)init ++ (instancetype)exception { - OF_INVALID_INIT_METHOD + OF_UNRECOGNIZED_SELECTOR } - (instancetype) initWithRegistryKey: (OFWindowsRegistryKey *)registryKey path: (OFString *)path @@ -61,10 +61,15 @@ @throw e; } return self; } + +- (instancetype)init +{ + OF_INVALID_INIT_METHOD +} - (void)dealloc { [_registryKey release]; [_path release]; Index: src/exceptions/OFOutOfMemoryException.h ================================================================== --- src/exceptions/OFOutOfMemoryException.h +++ src/exceptions/OFOutOfMemoryException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/exceptions/OFOutOfMemoryException.m ================================================================== --- src/exceptions/OFOutOfMemoryException.m +++ src/exceptions/OFOutOfMemoryException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/exceptions/OFOutOfRangeException.h ================================================================== --- src/exceptions/OFOutOfRangeException.h +++ src/exceptions/OFOutOfRangeException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/exceptions/OFOutOfRangeException.m ================================================================== --- src/exceptions/OFOutOfRangeException.m +++ src/exceptions/OFOutOfRangeException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/exceptions/OFReadFailedException.h ================================================================== --- src/exceptions/OFReadFailedException.h +++ src/exceptions/OFReadFailedException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/exceptions/OFReadFailedException.m ================================================================== --- src/exceptions/OFReadFailedException.m +++ src/exceptions/OFReadFailedException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -19,10 +19,15 @@ #import "OFString.h" @implementation OFReadFailedException - (OFString *)description { - return [OFString stringWithFormat: - @"Failed to read %zu bytes from an object of type %@: %@", - _requestedLength, [_object class], OFStrError(_errNo)]; + if (_errNo != 0) + return [OFString stringWithFormat: + @"Failed to read %zu bytes from an object of type %@: %@", + _requestedLength, [_object class], OFStrError(_errNo)]; + else + return [OFString stringWithFormat: + @"Failed to read %zu bytes from an object of type %@", + _requestedLength, [_object class]]; } @end Index: src/exceptions/OFReadOrWriteFailedException.h ================================================================== --- src/exceptions/OFReadOrWriteFailedException.h +++ src/exceptions/OFReadOrWriteFailedException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/exceptions/OFReadOrWriteFailedException.m ================================================================== --- src/exceptions/OFReadOrWriteFailedException.m +++ src/exceptions/OFReadOrWriteFailedException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -61,11 +61,17 @@ [super dealloc]; } - (OFString *)description { - return [OFString stringWithFormat: - @"Failed to read or write %zu bytes from / to an object of type " - @"%@: %@", - _requestedLength, [_object class], OFStrError(_errNo)]; + if (_errNo != 0) + return [OFString stringWithFormat: + @"Failed to read or write %zu bytes from / to an object of " + @"type %@: %@", + _requestedLength, [_object class], OFStrError(_errNo)]; + else + return [OFString stringWithFormat: + @"Failed to read or write %zu bytes from / to an object of " + @"type %@", + _requestedLength, [_object class]]; } @end Index: src/exceptions/OFRemoveItemFailedException.h ================================================================== --- src/exceptions/OFRemoveItemFailedException.h +++ src/exceptions/OFRemoveItemFailedException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -39,22 +39,20 @@ /** * @brief The errno of the error that occurred. */ @property (readonly, nonatomic) int errNo; -+ (instancetype)exception OF_UNAVAILABLE; - /** * @brief Creates a new, autoreleased remove failed exception. * * @param URL The URL of the item which could not be removed * @param errNo The errno of the error that occurred * @return A new, autoreleased remove item failed exception */ + (instancetype)exceptionWithURL: (OFURL *)URL errNo: (int)errNo; -- (instancetype)init OF_UNAVAILABLE; ++ (instancetype)exception OF_UNAVAILABLE; /** * @brief Initializes an already allocated remove failed exception. * * @param URL The URL of the item which could not be removed @@ -61,8 +59,10 @@ * @param errNo The errno of the error that occurred * @return An initialized remove item failed exception */ - (instancetype)initWithURL: (OFURL *)URL errNo: (int)errNo OF_DESIGNATED_INITIALIZER; + +- (instancetype)init OF_UNAVAILABLE; @end OF_ASSUME_NONNULL_END Index: src/exceptions/OFRemoveItemFailedException.m ================================================================== --- src/exceptions/OFRemoveItemFailedException.m +++ src/exceptions/OFRemoveItemFailedException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/exceptions/OFResolveHostFailedException.h ================================================================== --- src/exceptions/OFResolveHostFailedException.h +++ src/exceptions/OFResolveHostFailedException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -57,10 +57,12 @@ */ + (instancetype)exceptionWithHost: (OFString *)host addressFamily: (OFSocketAddressFamily)addressFamily errorCode: (OFDNSResolverErrorCode)errorCode; ++ (instancetype)exception OF_UNAVAILABLE; + /** * @brief Initializes an already allocated resolve host failed exception. * * @param host The host which could not be resolved * @param addressFamily The address family for which the host could not be @@ -69,8 +71,10 @@ * @return An initialized address translation failed exception */ - (instancetype)initWithHost: (OFString *)host addressFamily: (OFSocketAddressFamily)addressFamily errorCode: (OFDNSResolverErrorCode)errorCode; + +- (instancetype)init OF_UNAVAILABLE; @end OF_ASSUME_NONNULL_END Index: src/exceptions/OFResolveHostFailedException.m ================================================================== --- src/exceptions/OFResolveHostFailedException.m +++ src/exceptions/OFResolveHostFailedException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -29,10 +29,15 @@ { return [[[self alloc] initWithHost: host addressFamily: addressFamily errorCode: errorCode] autorelease]; } + ++ (instancetype)exception +{ + OF_UNRECOGNIZED_SELECTOR +} - (instancetype)initWithHost: (OFString *)host addressFamily: (OFSocketAddressFamily)addressFamily errorCode: (OFDNSResolverErrorCode)errorCode { @@ -47,10 +52,15 @@ @throw e; } return self; } + +- (instancetype)init +{ + OF_INVALID_INIT_METHOD +} - (void)dealloc { [_host release]; Index: src/exceptions/OFRetrieveItemAttributesFailedException.h ================================================================== --- src/exceptions/OFRetrieveItemAttributesFailedException.h +++ src/exceptions/OFRetrieveItemAttributesFailedException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -40,22 +40,20 @@ /** * @brief The errno of the error that occurred. */ @property (readonly, nonatomic) int errNo; -+ (instancetype)exception OF_UNAVAILABLE; - /** * @brief Creates a new, autoreleased retrieve item attributes failed exception. * * @param URL The URL of the item whose attributes could not be retrieved * @param errNo The errno of the error that occurred * @return A new, autoreleased retrieve item attributes failed exception */ + (instancetype)exceptionWithURL: (OFURL *)URL errNo: (int)errNo; -- (instancetype)init OF_UNAVAILABLE; ++ (instancetype)exception OF_UNAVAILABLE; /** * @brief Initializes an already allocated retrieve item attributes failed * exception. * @@ -63,8 +61,10 @@ * @param errNo The errno of the error that occurred * @return An initialized retrieve item attributes failed exception */ - (instancetype)initWithURL: (OFURL *)URL errNo: (int)errNo OF_DESIGNATED_INITIALIZER; + +- (instancetype)init OF_UNAVAILABLE; @end OF_ASSUME_NONNULL_END Index: src/exceptions/OFRetrieveItemAttributesFailedException.m ================================================================== --- src/exceptions/OFRetrieveItemAttributesFailedException.m +++ src/exceptions/OFRetrieveItemAttributesFailedException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/exceptions/OFSandboxActivationFailedException.h ================================================================== --- src/exceptions/OFSandboxActivationFailedException.h +++ src/exceptions/OFSandboxActivationFailedException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/exceptions/OFSandboxActivationFailedException.m ================================================================== --- src/exceptions/OFSandboxActivationFailedException.m +++ src/exceptions/OFSandboxActivationFailedException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/exceptions/OFSeekFailedException.h ================================================================== --- src/exceptions/OFSeekFailedException.h +++ src/exceptions/OFSeekFailedException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -49,12 +49,10 @@ /** * @brief The errno of the error that occurred. */ @property (readonly, nonatomic) int errNo; -+ (instancetype)exception OF_UNAVAILABLE; - /** * @brief Creates a new, autoreleased seek failed exception. * * @param stream The stream for which seeking failed * @param offset The offset to which seeking failed @@ -65,11 +63,11 @@ + (instancetype)exceptionWithStream: (OFSeekableStream *)stream offset: (OFFileOffset)offset whence: (int)whence errNo: (int)errNo; -- (instancetype)init OF_UNAVAILABLE; ++ (instancetype)exception OF_UNAVAILABLE; /** * @brief Initializes an already allocated seek failed exception. * * @param stream The stream for which seeking failed @@ -80,8 +78,10 @@ */ - (instancetype)initWithStream: (OFSeekableStream *)stream offset: (OFFileOffset)offset whence: (int)whence errNo: (int)errNo OF_DESIGNATED_INITIALIZER; + +- (instancetype)init OF_UNAVAILABLE; @end OF_ASSUME_NONNULL_END Index: src/exceptions/OFSeekFailedException.m ================================================================== --- src/exceptions/OFSeekFailedException.m +++ src/exceptions/OFSeekFailedException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/exceptions/OFSetItemAttributesFailedException.h ================================================================== --- src/exceptions/OFSetItemAttributesFailedException.h +++ src/exceptions/OFSetItemAttributesFailedException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -53,12 +53,10 @@ /** * @brief The first attribute that could not be set. */ @property (readonly, nonatomic) OFFileAttributeKey failedAttribute; -+ (instancetype)exception OF_UNAVAILABLE; - /** * @brief Creates a new, autoreleased set item attributes failed exception. * * @param URL The URL of the item whose attributes could not be set * @param attributes The attributes that should have been set for the specified @@ -70,11 +68,11 @@ + (instancetype)exceptionWithURL: (OFURL *)URL attributes: (OFFileAttributes)attributes failedAttribute: (OFFileAttributeKey)failedAttribute errNo: (int)errNo; -- (instancetype)init OF_UNAVAILABLE; ++ (instancetype)exception OF_UNAVAILABLE; /** * @brief Initializes an already allocated set item attributes failed exception. * * @param URL The URL of the item whose attributes could not be set @@ -86,8 +84,10 @@ */ - (instancetype)initWithURL: (OFURL *)URL attributes: (OFFileAttributes)attributes failedAttribute: (OFFileAttributeKey)failedAttribute errNo: (int)errNo OF_DESIGNATED_INITIALIZER; + +- (instancetype)init OF_UNAVAILABLE; @end OF_ASSUME_NONNULL_END Index: src/exceptions/OFSetItemAttributesFailedException.m ================================================================== --- src/exceptions/OFSetItemAttributesFailedException.m +++ src/exceptions/OFSetItemAttributesFailedException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/exceptions/OFSetOptionFailedException.h ================================================================== --- src/exceptions/OFSetOptionFailedException.h +++ src/exceptions/OFSetOptionFailedException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -37,22 +37,20 @@ /** * @brief The errno of the error that occurred. */ @property (readonly, nonatomic) int errNo; -+ (instancetype)exception OF_UNAVAILABLE; - /** * @brief Creates a new, autoreleased set option failed exception. * * @param object The object for which the option could not be set * @param errNo The errno of the error that occurred * @return A new, autoreleased set option failed exception */ + (instancetype)exceptionWithObject: (id)object errNo: (int)errNo; -- (instancetype)init OF_UNAVAILABLE; ++ (instancetype)exception OF_UNAVAILABLE; /** * @brief Initializes an already allocated set option failed exception. * * @param object The object for which the option could not be set @@ -59,8 +57,10 @@ * @param errNo The errno of the error that occurred * @return An initialized set option failed exception */ - (instancetype)initWithObject: (id)object errNo: (int)errNo OF_DESIGNATED_INITIALIZER; + +- (instancetype)init OF_UNAVAILABLE; @end OF_ASSUME_NONNULL_END Index: src/exceptions/OFSetOptionFailedException.m ================================================================== --- src/exceptions/OFSetOptionFailedException.m +++ src/exceptions/OFSetOptionFailedException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/exceptions/OFSetWindowsRegistryValueFailedException.h ================================================================== --- src/exceptions/OFSetWindowsRegistryValueFailedException.h +++ src/exceptions/OFSetWindowsRegistryValueFailedException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/exceptions/OFSetWindowsRegistryValueFailedException.m ================================================================== --- src/exceptions/OFSetWindowsRegistryValueFailedException.m +++ src/exceptions/OFSetWindowsRegistryValueFailedException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/exceptions/OFStillLockedException.h ================================================================== --- src/exceptions/OFStillLockedException.h +++ src/exceptions/OFStillLockedException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -24,11 +24,11 @@ * * @brief An exception indicating that a lock is still locked. */ @interface OFStillLockedException: OFException { - id _lock; + id _Nullable _lock; } /** * @brief The lock which is still locked. */ Index: src/exceptions/OFStillLockedException.m ================================================================== --- src/exceptions/OFStillLockedException.m +++ src/exceptions/OFStillLockedException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in ADDED src/exceptions/OFTLSHandshakeFailedException.h Index: src/exceptions/OFTLSHandshakeFailedException.h ================================================================== --- src/exceptions/OFTLSHandshakeFailedException.h +++ src/exceptions/OFTLSHandshakeFailedException.h @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2008-2022 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#import "OFException.h" + +#ifndef OF_HAVE_SOCKETS +# error No sockets available! +#endif + +#import "OFTLSStream.h" + +OF_ASSUME_NONNULL_BEGIN + +#ifdef __cplusplus +extern "C" { +#endif +extern int _OFTLSHandshakeFailedException_reference; +#ifdef __cplusplus +} +#endif + +/** + * @class OFTLSHandshakeFailedException \ + * OFTLSHandshakeFailedException.h ObjFW/OFTLSHandshakeFailedException.h + * + * @brief An exception indicating that a TLS handshake. + */ +@interface OFTLSHandshakeFailedException: OFException +{ + OFTLSStream *_stream; + OFString *_Nullable _host; + OFTLSStreamErrorCode _errorCode; +} + +/** + * @brief The TLS stream which failed the handshake. + */ +@property (readonly, nonatomic) OFTLSStream *stream; + +/** + * @brief The host for the handshake. + */ +@property OF_NULLABLE_PROPERTY (readonly, nonatomic) OFString *host; + +/** + * @brief The error code from the TLS stream. + */ +@property (readonly, nonatomic) OFTLSStreamErrorCode errorCode; + +/** + * @brief Creates a new, autoreleased TLS handshake failed exception. + * + * @param stream The TLS stream which failed the handshake + * @param host The host for the handshake + * @param errorCode The error code from the TLS stream + * @return A new, autoreleased TLS handshake failed exception + */ ++ (instancetype)exceptionWithStream: (OFTLSStream *)stream + host: (nullable OFString *)host + errorCode: (OFTLSStreamErrorCode)errorCode; + ++ (instancetype)exception OF_UNAVAILABLE; + +/** + * @brief Initializes an already allocated TLS handshake failed exception. + * + * @param stream The TLS stream which failed the handshake + * @param host The host for the handshake + * @param errorCode The error code from the TLS stream + * @return An initialized TLS handshake failed exception + */ +- (instancetype)initWithStream: (OFTLSStream *)stream + host: (nullable OFString *)host + errorCode: (OFTLSStreamErrorCode)errorCode + OF_DESIGNATED_INITIALIZER; + +- (instancetype)init OF_UNAVAILABLE; +@end + +OF_ASSUME_NONNULL_END ADDED src/exceptions/OFTLSHandshakeFailedException.m Index: src/exceptions/OFTLSHandshakeFailedException.m ================================================================== --- src/exceptions/OFTLSHandshakeFailedException.m +++ src/exceptions/OFTLSHandshakeFailedException.m @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2008-2022 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 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 "OFTLSHandshakeFailedException.h" +#import "OFString.h" + +int _OFTLSHandshakeFailedException_reference; + +@implementation OFTLSHandshakeFailedException +@synthesize stream = _stream, host = _host, errorCode = _errorCode; + ++ (instancetype)exceptionWithStream: (OFTLSStream *)stream + host: (OFString *)host + errorCode: (OFTLSStreamErrorCode)errorCode +{ + return [[[self alloc] initWithStream: stream + host: host + errorCode: errorCode] autorelease]; +} + ++ (instancetype)exception +{ + OF_UNRECOGNIZED_SELECTOR +} + +- (instancetype)initWithStream: (OFTLSStream *)stream + host: (OFString *)host + errorCode: (OFTLSStreamErrorCode)errorCode +{ + self = [super init]; + + @try { + _stream = [stream retain]; + _host = [host copy]; + _errorCode = errorCode; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (instancetype)init +{ + OF_INVALID_INIT_METHOD +} + +- (void)dealloc +{ + [_stream release]; + [_host release]; + + [super dealloc]; +} + +- (OFString *)description +{ + if (_host != nil) + return [OFString stringWithFormat: + @"TLS handshake in class %@ with host %@ failed: %@", + _stream.class, _host, + OFTLSStreamErrorCodeDescription(_errorCode)]; + else + return [OFString stringWithFormat: + @"TLS handshake in class %@ failed: %@", + _stream.class, OFTLSStreamErrorCodeDescription(_errorCode)]; +} +@end Index: src/exceptions/OFThreadJoinFailedException.h ================================================================== --- src/exceptions/OFThreadJoinFailedException.h +++ src/exceptions/OFThreadJoinFailedException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -29,11 +29,11 @@ * * @brief An exception indicating that joining a thread failed. */ @interface OFThreadJoinFailedException: OFException { - OFThread *_thread; + OFThread *_Nullable _thread; int _errNo; } /** * @brief The thread which could not be joined. @@ -52,10 +52,12 @@ * @param errNo The errno of the error that occurred * @return A new, autoreleased thread join failed exception */ + (instancetype)exceptionWithThread: (nullable OFThread *)thread errNo: (int)errNo; + ++ (instancetype)exception OF_UNAVAILABLE; /** * @brief Initializes an already allocated thread join failed exception. * * @param thread The thread which could not be joined Index: src/exceptions/OFThreadJoinFailedException.m ================================================================== --- src/exceptions/OFThreadJoinFailedException.m +++ src/exceptions/OFThreadJoinFailedException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -26,10 +26,15 @@ + (instancetype)exceptionWithThread: (OFThread *)thread errNo: (int)errNo { return [[[self alloc] initWithThread: thread errNo: errNo] autorelease]; } + ++ (instancetype)exception +{ + OF_UNRECOGNIZED_SELECTOR +} - (instancetype)initWithThread: (OFThread *)thread errNo: (int)errNo { self = [super init]; Index: src/exceptions/OFThreadStartFailedException.h ================================================================== --- src/exceptions/OFThreadStartFailedException.h +++ src/exceptions/OFThreadStartFailedException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -29,11 +29,11 @@ * * @brief An exception indicating that starting a thread failed. */ @interface OFThreadStartFailedException: OFException { - OFThread *_thread; + OFThread *_Nullable _thread; int _errNo; } /** * @brief The thread which could not be started. @@ -52,10 +52,12 @@ * @param errNo The errno of the error that occurred * @return A new, autoreleased thread start failed exception */ + (instancetype)exceptionWithThread: (nullable OFThread *)thread errNo: (int)errNo; + ++ (instancetype)exception OF_UNAVAILABLE; /** * @brief Initializes an already allocated thread start failed exception. * * @param thread The thread which could not be started Index: src/exceptions/OFThreadStartFailedException.m ================================================================== --- src/exceptions/OFThreadStartFailedException.m +++ src/exceptions/OFThreadStartFailedException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -26,10 +26,15 @@ + (instancetype)exceptionWithThread: (OFThread *)thread errNo: (int)errNo { return [[[self alloc] initWithThread: thread errNo: errNo] autorelease]; } + ++ (instancetype)exception +{ + OF_UNRECOGNIZED_SELECTOR +} - (instancetype)initWithThread: (OFThread *)thread errNo: (int)errNo { self = [super init]; Index: src/exceptions/OFThreadStillRunningException.h ================================================================== --- src/exceptions/OFThreadStillRunningException.h +++ src/exceptions/OFThreadStillRunningException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -29,11 +29,11 @@ * * @brief An exception indicating that a thread is still running. */ @interface OFThreadStillRunningException: OFException { - OFThread *_thread; + OFThread *_Nullable _thread; } /** * @brief The thread which is still running. */ Index: src/exceptions/OFThreadStillRunningException.m ================================================================== --- src/exceptions/OFThreadStillRunningException.m +++ src/exceptions/OFThreadStillRunningException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/exceptions/OFTruncatedDataException.h ================================================================== --- src/exceptions/OFTruncatedDataException.h +++ src/exceptions/OFTruncatedDataException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/exceptions/OFTruncatedDataException.m ================================================================== --- src/exceptions/OFTruncatedDataException.m +++ src/exceptions/OFTruncatedDataException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/exceptions/OFUnboundNamespaceException.h ================================================================== --- src/exceptions/OFUnboundNamespaceException.h +++ src/exceptions/OFUnboundNamespaceException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -35,40 +35,40 @@ * @brief The unbound namespace. */ #ifndef __cplusplus @property (readonly, nonatomic) OFString *namespace; #else -@property (readonly, nonatomic, getter=namespace) OFString *namespace_; +@property (readonly, nonatomic, getter=namespace) OFString *nameSpace; #endif /** * @brief The element in which the namespace was not bound. */ @property (readonly, nonatomic) OFXMLElement *element; -+ (instancetype)exception OF_UNAVAILABLE; - /** * @brief Creates a new, autoreleased unbound namespace exception. * - * @param namespace_ The namespace which is unbound + * @param nameSpace The namespace which is unbound * @param element The element in which the namespace was not bound * @return A new, autoreleased unbound namespace exception */ -+ (instancetype)exceptionWithNamespace: (OFString *)namespace_ ++ (instancetype)exceptionWithNamespace: (OFString *)nameSpace element: (OFXMLElement *)element; -- (instancetype)init OF_UNAVAILABLE; ++ (instancetype)exception OF_UNAVAILABLE; /** * @brief Initializes an already allocated unbound namespace exception. * - * @param namespace_ The namespace which is unbound + * @param nameSpace The namespace which is unbound * @param element The element in which the namespace was not bound * @return An initialized unbound namespace exception */ -- (instancetype)initWithNamespace: (OFString *)namespace_ +- (instancetype)initWithNamespace: (OFString *)nameSpace element: (OFXMLElement *)element OF_DESIGNATED_INITIALIZER; + +- (instancetype)init OF_UNAVAILABLE; @end OF_ASSUME_NONNULL_END Index: src/exceptions/OFUnboundNamespaceException.m ================================================================== --- src/exceptions/OFUnboundNamespaceException.m +++ src/exceptions/OFUnboundNamespaceException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/exceptions/OFUnboundPrefixException.h ================================================================== --- src/exceptions/OFUnboundPrefixException.h +++ src/exceptions/OFUnboundPrefixException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -39,12 +39,10 @@ /** * @brief The parser which encountered the unbound prefix. */ @property (readonly, nonatomic) OFXMLParser *parser; -+ (instancetype)exception OF_UNAVAILABLE; - /** * @brief Creates a new, autoreleased unbound prefix exception. * * @param prefix The prefix which is unbound * @param parser The parser which encountered the unbound prefix @@ -51,11 +49,11 @@ * @return A new, autoreleased unbound prefix exception */ + (instancetype)exceptionWithPrefix: (OFString *)prefix parser: (OFXMLParser *)parser; -- (instancetype)init OF_UNAVAILABLE; ++ (instancetype)exception OF_UNAVAILABLE; /** * @brief Initializes an already allocated unbound prefix exception. * * @param prefix The prefix which is unbound @@ -62,8 +60,10 @@ * @param parser The parser which encountered the unbound prefix * @return An initialized unbound prefix exception */ - (instancetype)initWithPrefix: (OFString *)prefix parser: (OFXMLParser *)parser OF_DESIGNATED_INITIALIZER; + +- (instancetype)init OF_UNAVAILABLE; @end OF_ASSUME_NONNULL_END Index: src/exceptions/OFUnboundPrefixException.m ================================================================== --- src/exceptions/OFUnboundPrefixException.m +++ src/exceptions/OFUnboundPrefixException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/exceptions/OFUndefinedKeyException.h ================================================================== --- src/exceptions/OFUndefinedKeyException.h +++ src/exceptions/OFUndefinedKeyException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -25,11 +25,11 @@ * Coding). */ @interface OFUndefinedKeyException: OFException { id _object; - OFString *_key; + OFString *_Nullable _key; id _Nullable _value; } /** * @brief The object on which the key is undefined. @@ -37,19 +37,17 @@ @property (readonly, nonatomic) id object; /** * @brief The key which is undefined. */ -@property (readonly, nonatomic) OFString *key; +@property OF_NULLABLE_PROPERTY (readonly, nonatomic) OFString *key; /** * @brief The value for the undefined key */ @property OF_NULLABLE_PROPERTY (readonly, nonatomic) id value; -+ (instancetype)exception OF_UNAVAILABLE; - /** * @brief Creates a new, autoreleased undefined key exception. * * @param object The object on which the key is undefined * @param key The key which is undefined @@ -66,14 +64,14 @@ * @param value The value for the undefined key * * @return A new, autoreleased undefined key exception */ + (instancetype)exceptionWithObject: (id)object - key: (OFString *)key + key: (nullable OFString *)key value: (nullable id)value; -- (instancetype)init OF_UNAVAILABLE; ++ (instancetype)exception OF_UNAVAILABLE; /** * @brief Initializes an already allocated undefined key exception. * * @param object The object on which the key is undefined @@ -91,10 +89,12 @@ * @param value The value for the undefined key * * @return An initialized undefined key exception */ - (instancetype)initWithObject: (id)object - key: (OFString *)key + key: (nullable OFString *)key value: (nullable id)value OF_DESIGNATED_INITIALIZER; + +- (instancetype)init OF_UNAVAILABLE; @end OF_ASSUME_NONNULL_END Index: src/exceptions/OFUndefinedKeyException.m ================================================================== --- src/exceptions/OFUndefinedKeyException.m +++ src/exceptions/OFUndefinedKeyException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/exceptions/OFUnknownXMLEntityException.h ================================================================== --- src/exceptions/OFUnknownXMLEntityException.h +++ src/exceptions/OFUnknownXMLEntityException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -40,18 +40,20 @@ * @param entityName The name of the unknown XML entity * @return A new, autoreleased unknown XML entity exception */ + (instancetype)exceptionWithEntityName: (OFString *)entityName; -- (instancetype)init OF_UNAVAILABLE; ++ (instancetype)exception OF_UNAVAILABLE; /** * @brief Initializes an already allocated unknown XML entity exception. * * @param entityName The name of the unknown XML entity * @return An initialized unknown XML entity exception */ - (instancetype)initWithEntityName: (OFString *)entityName OF_DESIGNATED_INITIALIZER; + +- (instancetype)init OF_UNAVAILABLE; @end OF_ASSUME_NONNULL_END Index: src/exceptions/OFUnknownXMLEntityException.m ================================================================== --- src/exceptions/OFUnknownXMLEntityException.m +++ src/exceptions/OFUnknownXMLEntityException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -24,13 +24,13 @@ + (instancetype)exceptionWithEntityName: (OFString *)entityName { return [[[self alloc] initWithEntityName: entityName] autorelease]; } -- (instancetype)init ++ (instancetype)exception { - OF_INVALID_INIT_METHOD + OF_UNRECOGNIZED_SELECTOR } - (instancetype)initWithEntityName: (OFString *)entityName { self = [super init]; @@ -42,10 +42,15 @@ @throw e; } return self; } + +- (instancetype)init +{ + OF_INVALID_INIT_METHOD +} - (void)dealloc { [_entityName release]; Index: src/exceptions/OFUnlockFailedException.h ================================================================== --- src/exceptions/OFUnlockFailedException.h +++ src/exceptions/OFUnlockFailedException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -24,11 +24,11 @@ * * @brief An exception indicating that unlocking a lock failed. */ @interface OFUnlockFailedException: OFException { - id _lock; + id _Nullable _lock; int _errNo; } /** * @brief The lock which could not be unlocked. @@ -57,10 +57,8 @@ * @param errNo The errno of the error that occurred * @return An initialized unlock failed exception */ - (instancetype)initWithLock: (nullable id )lock errNo: (int)errNo OF_DESIGNATED_INITIALIZER; - -- (instancetype)init OF_UNAVAILABLE; @end OF_ASSUME_NONNULL_END Index: src/exceptions/OFUnlockFailedException.m ================================================================== --- src/exceptions/OFUnlockFailedException.m +++ src/exceptions/OFUnlockFailedException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -36,24 +36,22 @@ _errNo = errNo; return self; } -- (instancetype)init -{ - OF_INVALID_INIT_METHOD -} - - (void)dealloc { [_lock release]; [super dealloc]; } - (OFString *)description { - return [OFString stringWithFormat: - @"A lock of type %@ could not be unlocked: %s", - [_lock class], strerror(_errNo)]; + if (_lock != nil) + return [OFString stringWithFormat: + @"A lock of type %@ could not be unlocked: %s", + [_lock class], strerror(_errNo)]; + else + return @"A lock could not be unlocked!"; } @end Index: src/exceptions/OFUnsupportedProtocolException.h ================================================================== --- src/exceptions/OFUnsupportedProtocolException.h +++ src/exceptions/OFUnsupportedProtocolException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -27,31 +27,31 @@ * @brief An exception indicating that the protocol specified by the URL is not * supported. */ @interface OFUnsupportedProtocolException: OFException { - OFURL *_URL; + OFURL *_Nullable _URL; } /** * @brief The URL whose protocol is unsupported. */ -@property (readonly, nonatomic) OFURL *URL; +@property OF_NULLABLE_PROPERTY (readonly, nonatomic) OFURL *URL; /** * @brief Creates a new, autoreleased unsupported protocol exception. * * @param URL The URL whose protocol is unsupported * @return A new, autoreleased unsupported protocol exception */ -+ (instancetype)exceptionWithURL: (OFURL*)URL; ++ (instancetype)exceptionWithURL: (nullable OFURL*)URL; /** * @brief Initializes an already allocated unsupported protocol exception * * @param URL The URL whose protocol is unsupported * @return An initialized unsupported protocol exception */ -- (instancetype)initWithURL: (OFURL*)URL OF_DESIGNATED_INITIALIZER; +- (instancetype)initWithURL: (nullable OFURL*)URL OF_DESIGNATED_INITIALIZER; @end OF_ASSUME_NONNULL_END Index: src/exceptions/OFUnsupportedProtocolException.m ================================================================== --- src/exceptions/OFUnsupportedProtocolException.m +++ src/exceptions/OFUnsupportedProtocolException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/exceptions/OFUnsupportedVersionException.h ================================================================== --- src/exceptions/OFUnsupportedVersionException.h +++ src/exceptions/OFUnsupportedVersionException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -32,27 +32,27 @@ /** * @brief The version which is unsupported. */ @property (readonly, nonatomic) OFString *version; -+ (instancetype)exception OF_UNAVAILABLE; - /** * @brief Creates a new, autoreleased unsupported version exception. * * @param version The version which is unsupported * @return A new, autoreleased unsupported version exception */ + (instancetype)exceptionWithVersion: (OFString *)version; -- (instancetype)init OF_UNAVAILABLE; ++ (instancetype)exception OF_UNAVAILABLE; /** * @brief Initializes an already allocated unsupported protocol exception. * * @param version The version which is unsupported * @return An initialized unsupported version exception */ - (instancetype)initWithVersion: (OFString *)version OF_DESIGNATED_INITIALIZER; + +- (instancetype)init OF_UNAVAILABLE; @end OF_ASSUME_NONNULL_END Index: src/exceptions/OFUnsupportedVersionException.m ================================================================== --- src/exceptions/OFUnsupportedVersionException.m +++ src/exceptions/OFUnsupportedVersionException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/exceptions/OFWriteFailedException.h ================================================================== --- src/exceptions/OFWriteFailedException.h +++ src/exceptions/OFWriteFailedException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -34,14 +34,10 @@ * This can be used to make sure that a retry does not write data already * written before. */ @property (readonly, nonatomic) size_t bytesWritten; -+ (instancetype)exceptionWithObject: (id)object - requestedLength: (size_t)requestedLength - errNo: (int)errNo OF_UNAVAILABLE; - /** * @brief Creates a new, autoreleased write failed exception. * * @param object The object from which reading or to which writing failed * @param requestedLength The requested length of the data that could not be @@ -54,13 +50,13 @@ + (instancetype)exceptionWithObject: (id)object requestedLength: (size_t)requestedLength bytesWritten: (size_t)bytesWritten errNo: (int)errNo; -- (instancetype)initWithObject: (id)object - requestedLength: (size_t)requestedLength - errNo: (int)errNo OF_UNAVAILABLE; ++ (instancetype)exceptionWithObject: (id)object + requestedLength: (size_t)requestedLength + errNo: (int)errNo OF_UNAVAILABLE; /** * @brief Initializes an already allocated write failed exception. * * @param object The object from which reading or to which writing failed @@ -73,8 +69,12 @@ */ - (instancetype)initWithObject: (id)object requestedLength: (size_t)requestedLength bytesWritten: (size_t)bytesWritten errNo: (int)errNo OF_DESIGNATED_INITIALIZER; + +- (instancetype)initWithObject: (id)object + requestedLength: (size_t)requestedLength + errNo: (int)errNo OF_UNAVAILABLE; @end OF_ASSUME_NONNULL_END Index: src/exceptions/OFWriteFailedException.m ================================================================== --- src/exceptions/OFWriteFailedException.m +++ src/exceptions/OFWriteFailedException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -62,12 +62,18 @@ return self; } - (OFString *)description { - return [OFString stringWithFormat: - @"Failed to write %zu bytes (after %zu bytes written) to an " - @"object of type %@: %@", - _requestedLength, _bytesWritten, [_object class], - OFStrError(_errNo)]; + if (_errNo != 0) + return [OFString stringWithFormat: + @"Failed to write %zu bytes (after %zu bytes written) to " + @"an object of type %@: %@", + _requestedLength, _bytesWritten, [_object class], + OFStrError(_errNo)]; + else + return [OFString stringWithFormat: + @"Failed to write %zu bytes (after %zu bytes written) to " + @"an object of type %@", + _requestedLength, _bytesWritten, [_object class]]; } @end Index: src/forwarding/apple-forwarding-arm.S ================================================================== --- src/forwarding/apple-forwarding-arm.S +++ src/forwarding/apple-forwarding-arm.S @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/forwarding/apple-forwarding-arm64.S ================================================================== --- src/forwarding/apple-forwarding-arm64.S +++ src/forwarding/apple-forwarding-arm64.S @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/forwarding/apple-forwarding-i386.S ================================================================== --- src/forwarding/apple-forwarding-i386.S +++ src/forwarding/apple-forwarding-i386.S @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/forwarding/apple-forwarding-powerpc.S ================================================================== --- src/forwarding/apple-forwarding-powerpc.S +++ src/forwarding/apple-forwarding-powerpc.S @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/forwarding/apple-forwarding-x86_64.S ================================================================== --- src/forwarding/apple-forwarding-x86_64.S +++ src/forwarding/apple-forwarding-x86_64.S @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/forwarding/forwarding-arm-elf.S ================================================================== --- src/forwarding/forwarding-arm-elf.S +++ src/forwarding/forwarding-arm-elf.S @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/forwarding/forwarding-arm64-elf.S ================================================================== --- src/forwarding/forwarding-arm64-elf.S +++ src/forwarding/forwarding-arm64-elf.S @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/forwarding/forwarding-mips-elf.S ================================================================== --- src/forwarding/forwarding-mips-elf.S +++ src/forwarding/forwarding-mips-elf.S @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/forwarding/forwarding-powerpc-elf.S ================================================================== --- src/forwarding/forwarding-powerpc-elf.S +++ src/forwarding/forwarding-powerpc-elf.S @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -192,11 +192,11 @@ stfd %f7, 88(%r1) stfd %f8, 96(%r1) mr %r3, %r4 #ifdef OF_PIC - bl object_getClass+0x800@plt + bl object_getClass+0x8000@plt lwz %r4, .Lgot_sel_forwardingTargetForSelector_-.Lbiased_got2(%r30) bl class_respondsToSelector+0x8000@plt #else bl object_getClass Index: src/forwarding/forwarding-sparc-elf.S ================================================================== --- src/forwarding/forwarding-sparc-elf.S +++ src/forwarding/forwarding-sparc-elf.S @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/forwarding/forwarding-sparc64-elf.S ================================================================== --- src/forwarding/forwarding-sparc64-elf.S +++ src/forwarding/forwarding-sparc64-elf.S @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/forwarding/forwarding-x86-elf.S ================================================================== --- src/forwarding/forwarding-x86-elf.S +++ src/forwarding/forwarding-x86-elf.S @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/forwarding/forwarding-x86-win32.S ================================================================== --- src/forwarding/forwarding-x86-win32.S +++ src/forwarding/forwarding-x86-win32.S @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/forwarding/forwarding-x86_64-elf.S ================================================================== --- src/forwarding/forwarding-x86_64-elf.S +++ src/forwarding/forwarding-x86_64-elf.S @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/forwarding/forwarding-x86_64-macho.S ================================================================== --- src/forwarding/forwarding-x86_64-macho.S +++ src/forwarding/forwarding-x86_64-macho.S @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/forwarding/forwarding-x86_64-win64.S ================================================================== --- src/forwarding/forwarding-x86_64-win64.S +++ src/forwarding/forwarding-x86_64-win64.S @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/forwarding/forwarding.S ================================================================== --- src/forwarding/forwarding.S +++ src/forwarding/forwarding.S @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/libbases.m ================================================================== --- src/libbases.m +++ src/libbases.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/macros.h ================================================================== --- src/macros.h +++ src/macros.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -254,11 +254,10 @@ # define OF_WARN_UNUSED_RESULT #endif #if __has_attribute(__unavailable__) # define OF_UNAVAILABLE __attribute__((__unavailable__)) -# define OF_HAVE_UNAVAILABLE #else # define OF_UNAVAILABLE #endif #if __has_attribute(__objc_requires_super__) @@ -417,27 +416,33 @@ OF_PREPROCESSOR_CONCAT(destructor, __LINE__)(void) static OF_INLINE uint16_t OF_CONST_FUNC OFByteSwap16Const(uint16_t i) { - return (i & 0xFF00) >> 8 | (i & 0x00FF) << 8; + return (i & UINT16_C(0xFF00)) >> 8 | (i & UINT16_C(0x00FF)) << 8; } static OF_INLINE uint32_t OF_CONST_FUNC OFByteSwap32Const(uint32_t i) { - return (i & 0xFF000000) >> 24 | (i & 0x00FF0000) >> 8 | - (i & 0x0000FF00) << 8 | (i & 0x000000FF) << 24; + return (i & UINT32_C(0xFF000000)) >> 24 | + (i & UINT32_C(0x00FF0000)) >> 8 | + (i & UINT32_C(0x0000FF00)) << 8 | + (i & UINT32_C(0x000000FF)) << 24; } static OF_INLINE uint64_t OF_CONST_FUNC OFByteSwap64Const(uint64_t i) { - return (i & 0xFF00000000000000) >> 56 | (i & 0x00FF000000000000) >> 40 | - (i & 0x0000FF0000000000) >> 24 | (i & 0x000000FF00000000) >> 8 | - (i & 0x00000000FF000000) << 8 | (i & 0x0000000000FF0000) << 24 | - (i & 0x000000000000FF00) << 40 | (i & 0x00000000000000FF) << 56; + return (i & UINT64_C(0xFF00000000000000)) >> 56 | + (i & UINT64_C(0x00FF000000000000)) >> 40 | + (i & UINT64_C(0x0000FF0000000000)) >> 24 | + (i & UINT64_C(0x000000FF00000000)) >> 8 | + (i & UINT64_C(0x00000000FF000000)) << 8 | + (i & UINT64_C(0x0000000000FF0000)) << 24 | + (i & UINT64_C(0x000000000000FF00)) << 40 | + (i & UINT64_C(0x00000000000000FF)) << 56; } static OF_INLINE uint16_t OF_CONST_FUNC OFByteSwap16NonConst(uint16_t i) { @@ -518,11 +523,12 @@ "xchgl %%eax, %%edx" : "=A"(i) : "0"(i) ); #else - i = (uint64_t)OFByteSwap32NonConst((uint32_t)(i & 0xFFFFFFFF)) << 32 | + i = (uint64_t)OFByteSwap32NonConst( + (uint32_t)(i & UINT32_C(0xFFFFFFFF))) << 32 | OFByteSwap32NonConst((uint32_t)(i >> 32)); #endif return i; } Index: src/objfw-defs.h.in ================================================================== --- src/objfw-defs.h.in +++ src/objfw-defs.h.in @@ -1,8 +1,9 @@ #undef OF_APPLE_RUNTIME #undef OF_BIG_ENDIAN #undef OF_FLOAT_BIG_ENDIAN +#undef OF_HAVE_AFUNIX_H #undef OF_HAVE_ATOMIC_BUILTINS #undef OF_HAVE_ATOMIC_OPS #undef OF_HAVE_BUILTIN_BSWAP16 #undef OF_HAVE_BUILTIN_BSWAP32 #undef OF_HAVE_BUILTIN_BSWAP64 @@ -21,11 +22,11 @@ #undef OF_HAVE_OSATOMIC #undef OF_HAVE_OSATOMIC_64 #undef OF_HAVE_PIPE #undef OF_HAVE_PLEDGE #undef OF_HAVE_PLUGINS -#undef OF_HAVE_PROCESSES +#undef OF_HAVE_SUBPROCESSES #undef OF_HAVE_PTHREADS #undef OF_HAVE_PTHREAD_SPINLOCKS #undef OF_HAVE_RECURSIVE_PTHREAD_MUTEXES #undef OF_HAVE_SCHED_YIELD #undef OF_HAVE_SOCKETS @@ -32,15 +33,19 @@ #undef OF_HAVE_STDNORETURN #undef OF_HAVE_SYMLINK #undef OF_HAVE_SYNC_BUILTINS #undef OF_HAVE_SYS_SOCKET_H #undef OF_HAVE_SYS_TYPES_H +#undef OF_HAVE_SYS_UN_H #undef OF_HAVE_THREADS #undef OF_HAVE_UNICODE_TABLES +#undef OF_HAVE_UNIX_SOCKETS #undef OF_HAVE__THREAD_LOCAL #undef OF_HAVE___THREAD #undef OF_NINTENDO_3DS #undef OF_NINTENDO_DS +#undef OF_NINTENDO_SWITCH #undef OF_NO_SHARED #undef OF_OBJFW_RUNTIME #undef OF_UNIVERSAL #undef OF_WII +#undef OF_WII_U Index: src/platform.h ================================================================== --- src/platform.h +++ src/platform.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -147,10 +147,12 @@ #elif defined(__DJGPP__) # define OF_DJGPP # define OF_MSDOS #elif defined(__riscos__) # define OF_ACORN_RISC_OS +#elif defined(__MINT__) +# define OF_MINT #endif #if defined(__ELF__) # define OF_ELF #elif defined(__MACH__) Index: src/platform/AmigaOS/OFPlainCondition.m ================================================================== --- src/platform/AmigaOS/OFPlainCondition.m +++ src/platform/AmigaOS/OFPlainCondition.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/platform/AmigaOS/OFPlainMutex.m ================================================================== --- src/platform/AmigaOS/OFPlainMutex.m +++ src/platform/AmigaOS/OFPlainMutex.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/platform/AmigaOS/OFPlainThread.m ================================================================== --- src/platform/AmigaOS/OFPlainThread.m +++ src/platform/AmigaOS/OFPlainThread.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/platform/AmigaOS/OFString+PathAdditions.m ================================================================== --- src/platform/AmigaOS/OFString+PathAdditions.m +++ src/platform/AmigaOS/OFString+PathAdditions.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -266,10 +266,31 @@ [ret makeImmutable]; return ret; } } + +- (OFString *)stringByAppendingPathExtension: (OFString *)extension +{ + if ([self hasSuffix: @"/"]) { + void *pool = objc_autoreleasePoolPush(); + OFMutableArray *components; + OFString *fileName, *ret; + + components = + [[self.pathComponents mutableCopy] autorelease]; + fileName = [components.lastObject + stringByAppendingFormat: @".%@", extension]; + [components replaceObjectAtIndex: components.count - 1 + withObject: fileName]; + + ret = [[OFString pathWithComponents: components] retain]; + objc_autoreleasePoolPop(pool); + return [ret autorelease]; + } else + return [self stringByAppendingFormat: @".%@", extension]; +} - (bool)of_isDirectoryPath { return ([self hasSuffix: @"/"] || [self hasSuffix: @":"] || [OFFileURLHandler of_directoryExistsAtPath: self]); Index: src/platform/AmigaOS/OFTLSKey.m ================================================================== --- src/platform/AmigaOS/OFTLSKey.m +++ src/platform/AmigaOS/OFTLSKey.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/platform/GCC4.7/OFAtomic.h ================================================================== --- src/platform/GCC4.7/OFAtomic.h +++ src/platform/GCC4.7/OFAtomic.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/platform/GCC4/OFAtomic.h ================================================================== --- src/platform/GCC4/OFAtomic.h +++ src/platform/GCC4/OFAtomic.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/platform/MorphOS/OFTLSKey.m ================================================================== --- src/platform/MorphOS/OFTLSKey.m +++ src/platform/MorphOS/OFTLSKey.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/platform/POSIX/OFPlainCondition.m ================================================================== --- src/platform/POSIX/OFPlainCondition.m +++ src/platform/POSIX/OFPlainCondition.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/platform/POSIX/OFPlainMutex.m ================================================================== --- src/platform/POSIX/OFPlainMutex.m +++ src/platform/POSIX/OFPlainMutex.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/platform/POSIX/OFPlainThread.m ================================================================== --- src/platform/POSIX/OFPlainThread.m +++ src/platform/POSIX/OFPlainThread.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/platform/POSIX/OFString+PathAdditions.m ================================================================== --- src/platform/POSIX/OFString+PathAdditions.m +++ src/platform/POSIX/OFString+PathAdditions.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -311,10 +311,31 @@ [ret makeImmutable]; return ret; } } + +- (OFString *)stringByAppendingPathExtension: (OFString *)extension +{ + if ([self hasSuffix: @"/"]) { + void *pool = objc_autoreleasePoolPush(); + OFMutableArray *components; + OFString *fileName, *ret; + + components = + [[self.pathComponents mutableCopy] autorelease]; + fileName = [components.lastObject + stringByAppendingFormat: @".%@", extension]; + [components replaceObjectAtIndex: components.count - 1 + withObject: fileName]; + + ret = [[OFString pathWithComponents: components] retain]; + objc_autoreleasePoolPop(pool); + return [ret autorelease]; + } else + return [self stringByAppendingFormat: @".%@", extension]; +} - (bool)of_isDirectoryPath { return ([self hasSuffix: @"/"] || [OFFileURLHandler of_directoryExistsAtPath: self]); Index: src/platform/POSIX/OFSubprocess.m ================================================================== --- src/platform/POSIX/OFSubprocess.m +++ src/platform/POSIX/OFSubprocess.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -207,12 +207,13 @@ close(_readPipe[1]); close(_writePipe[0]); OFFreeMemory(argv); - for (iter = env; *iter != NULL; iter++) - OFFreeMemory(*iter); + if (env != NULL) + for (iter = env; *iter != NULL; iter++) + OFFreeMemory(*iter); OFFreeMemory(env); } objc_autoreleasePoolPop(pool); @@ -329,12 +330,11 @@ _atEndOfStream = true; return ret; } -- (size_t)lowlevelWriteBuffer: (const void *)buffer - length: (size_t)length +- (size_t)lowlevelWriteBuffer: (const void *)buffer length: (size_t)length { ssize_t bytesWritten; if (_writePipe[1] == -1) @throw [OFNotOpenException exceptionWithObject: self]; Index: src/platform/POSIX/OFTLSKey.m ================================================================== --- src/platform/POSIX/OFTLSKey.m +++ src/platform/POSIX/OFTLSKey.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/platform/PowerPC/OFAtomic.h ================================================================== --- src/platform/PowerPC/OFAtomic.h +++ src/platform/PowerPC/OFAtomic.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/platform/Windows/OFPlainCondition.m ================================================================== --- src/platform/Windows/OFPlainCondition.m +++ src/platform/Windows/OFPlainCondition.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/platform/Windows/OFPlainMutex.m ================================================================== --- src/platform/Windows/OFPlainMutex.m +++ src/platform/Windows/OFPlainMutex.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/platform/Windows/OFPlainThread.m ================================================================== --- src/platform/Windows/OFPlainThread.m +++ src/platform/Windows/OFPlainThread.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/platform/Windows/OFString+PathAdditions.m ================================================================== --- src/platform/Windows/OFString+PathAdditions.m +++ src/platform/Windows/OFString+PathAdditions.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -12,12 +12,12 @@ * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this * file. */ /* - * This file is also used for MS-DOS! Don't forget to #ifdef Windows-specific - * parts! + * This file is also used for MS-DOS and MiNT! Don't forget to #ifdef + * Windows-specific parts! */ #include "config.h" #import "OFString+PathAdditions.h" @@ -316,10 +316,31 @@ [ret makeImmutable]; return ret; } } + +- (OFString *)stringByAppendingPathExtension: (OFString *)extension +{ + if ([self hasSuffix: @"\\"] || [self hasSuffix: @"/"]) { + void *pool = objc_autoreleasePoolPush(); + OFMutableArray *components; + OFString *fileName, *ret; + + components = + [[self.pathComponents mutableCopy] autorelease]; + fileName = [components.lastObject + stringByAppendingFormat: @".%@", extension]; + [components replaceObjectAtIndex: components.count - 1 + withObject: fileName]; + + ret = [[OFString pathWithComponents: components] retain]; + objc_autoreleasePoolPop(pool); + return [ret autorelease]; + } else + return [self stringByAppendingFormat: @".%@", extension]; +} - (bool)of_isDirectoryPath { return ([self hasSuffix: @"\\"] || [self hasSuffix: @"/"] || [OFFileURLHandler of_directoryExistsAtPath: self]); Index: src/platform/Windows/OFSubprocess.m ================================================================== --- src/platform/Windows/OFSubprocess.m +++ src/platform/Windows/OFSubprocess.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -359,11 +359,11 @@ if (GetLastError() == ERROR_BROKEN_PIPE) errNo = EPIPE; @throw [OFWriteFailedException exceptionWithObject: self requestedLength: length - bytesWritten: 0 + bytesWritten: bytesWritten errNo: errNo]; } return (size_t)bytesWritten; } Index: src/platform/Windows/OFTLSKey.m ================================================================== --- src/platform/Windows/OFTLSKey.m +++ src/platform/Windows/OFTLSKey.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/platform/libfat/OFString+PathAdditions.m ================================================================== --- src/platform/libfat/OFString+PathAdditions.m +++ src/platform/libfat/OFString+PathAdditions.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -312,10 +312,31 @@ [ret makeImmutable]; return ret; } } + +- (OFString *)stringByAppendingPathExtension: (OFString *)extension +{ + if ([self hasSuffix: @"/"]) { + void *pool = objc_autoreleasePoolPush(); + OFMutableArray *components; + OFString *fileName, *ret; + + components = + [[self.pathComponents mutableCopy] autorelease]; + fileName = [components.lastObject + stringByAppendingFormat: @".%@", extension]; + [components replaceObjectAtIndex: components.count - 1 + withObject: fileName]; + + ret = [[OFString pathWithComponents: components] retain]; + objc_autoreleasePoolPop(pool); + return [ret autorelease]; + } else + return [self stringByAppendingFormat: @".%@", extension]; +} - (bool)of_isDirectoryPath { return ([self hasSuffix: @"/"] || [OFFileURLHandler of_directoryExistsAtPath: self]); Index: src/platform/macOS/OFAtomic.h ================================================================== --- src/platform/macOS/OFAtomic.h +++ src/platform/macOS/OFAtomic.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/platform/x86/OFAtomic.h ================================================================== --- src/platform/x86/OFAtomic.h +++ src/platform/x86/OFAtomic.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/runtime/OFOnce.m ================================================================== --- src/runtime/OFOnce.m +++ src/runtime/OFOnce.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/runtime/OFPlainMutex.m ================================================================== --- src/runtime/OFPlainMutex.m +++ src/runtime/OFPlainMutex.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/runtime/OFTLSKey.m ================================================================== --- src/runtime/OFTLSKey.m +++ src/runtime/OFTLSKey.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/runtime/ObjFWRT.h ================================================================== --- src/runtime/ObjFWRT.h +++ src/runtime/ObjFWRT.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/runtime/amiga-end.m ================================================================== --- src/runtime/amiga-end.m +++ src/runtime/amiga-end.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/runtime/amiga-funcarray.inc ================================================================== --- src/runtime/amiga-funcarray.inc +++ src/runtime/amiga-funcarray.inc @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/runtime/amiga-glue.h ================================================================== --- src/runtime/amiga-glue.h +++ src/runtime/amiga-glue.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/runtime/amiga-glue.m ================================================================== --- src/runtime/amiga-glue.m +++ src/runtime/amiga-glue.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/runtime/amiga-library.m ================================================================== --- src/runtime/amiga-library.m +++ src/runtime/amiga-library.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -569,11 +569,11 @@ .rt_Version = OBJFWRT_LIB_MAJOR, .rt_Type = NT_LIBRARY, .rt_Pri = 0, .rt_Name = (char *)OBJFWRT_AMIGA_LIB, .rt_IdString = (char *)"ObjFWRT " VERSION_STRING - " \xA9 2008-2021 Jonathan Schleifer", + " \xA9 2008-2022 Jonathan Schleifer", .rt_Init = &init_table, #ifdef OF_MORPHOS .rt_Revision = OBJFWRT_LIB_MINOR, .rt_Tags = NULL, #endif Index: src/runtime/arc.m ================================================================== --- src/runtime/arc.m +++ src/runtime/arc.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/runtime/autorelease.m ================================================================== --- src/runtime/autorelease.m +++ src/runtime/autorelease.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/runtime/category.m ================================================================== --- src/runtime/category.m +++ src/runtime/category.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/runtime/class.m ================================================================== --- src/runtime/class.m +++ src/runtime/class.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/runtime/dtable.m ================================================================== --- src/runtime/dtable.m +++ src/runtime/dtable.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/runtime/exception.m ================================================================== --- src/runtime/exception.m +++ src/runtime/exception.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/runtime/hashtable.m ================================================================== --- src/runtime/hashtable.m +++ src/runtime/hashtable.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/runtime/init.m ================================================================== --- src/runtime/init.m +++ src/runtime/init.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/runtime/instance.m ================================================================== --- src/runtime/instance.m +++ src/runtime/instance.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/runtime/ivar.m ================================================================== --- src/runtime/ivar.m +++ src/runtime/ivar.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/runtime/linklib/init.m ================================================================== --- src/runtime/linklib/init.m +++ src/runtime/linklib/init.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -152,21 +152,21 @@ { CloseLibrary(ObjFWRTBase); } #if defined(OF_AMIGAOS_M68K) -ADD2INIT(ctor, -5); -ADD2EXIT(dtor, -5); +ADD2INIT(ctor, -5) +ADD2EXIT(dtor, -5) #elif defined(OF_MORPHOS) CONSTRUCTOR_P(ObjFWRT, 4000) { ctor(); return 0; } -DESTRUCTOR_P(ObjFWRT, 4000) +DESTRUCTOR_P(ObjFWRT, 0) { dtor(); } #endif Index: src/runtime/linklib/linklib.m ================================================================== --- src/runtime/linklib/linklib.m +++ src/runtime/linklib/linklib.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/runtime/lookup-asm/lookup-asm-arm-elf.S ================================================================== --- src/runtime/lookup-asm/lookup-asm-arm-elf.S +++ src/runtime/lookup-asm/lookup-asm-arm-elf.S @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/runtime/lookup-asm/lookup-asm-arm64-elf.S ================================================================== --- src/runtime/lookup-asm/lookup-asm-arm64-elf.S +++ src/runtime/lookup-asm/lookup-asm-arm64-elf.S @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/runtime/lookup-asm/lookup-asm-mips-elf.S ================================================================== --- src/runtime/lookup-asm/lookup-asm-mips-elf.S +++ src/runtime/lookup-asm/lookup-asm-mips-elf.S @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/runtime/lookup-asm/lookup-asm-mips64-n64-elf.S ================================================================== --- src/runtime/lookup-asm/lookup-asm-mips64-n64-elf.S +++ src/runtime/lookup-asm/lookup-asm-mips64-n64-elf.S @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/runtime/lookup-asm/lookup-asm-powerpc-elf.S ================================================================== --- src/runtime/lookup-asm/lookup-asm-powerpc-elf.S +++ src/runtime/lookup-asm/lookup-asm-powerpc-elf.S @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/runtime/lookup-asm/lookup-asm-powerpc64-elf.S ================================================================== --- src/runtime/lookup-asm/lookup-asm-powerpc64-elf.S +++ src/runtime/lookup-asm/lookup-asm-powerpc64-elf.S @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -14,25 +14,36 @@ */ #include "config.h" #include "platform.h" + +#if defined(_CALL_ELF) && _CALL_ELF == 2 +.abiversion 2 +#endif .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 +#if defined(_CALL_ELF) && _CALL_ELF == 2 +\name: + addis %r2, %r12, .TOC.-\name@ha + addi %r2, %r2, .TOC.-\name@l +.localentry \name, .-\name +#else .section .opd, "aw", @progbits \name: .p2align 3 .quad .Lbegin_\name .quad .TOC.@tocbase .quad 0 -.text +.section .text +#endif .Lbegin_\name: cmpdi %r3, 0 beq- .LreturnNilMethod andi. %r0, %r3, 1 @@ -87,17 +98,24 @@ .type \name, @function .size \name, .-.Lbegin_\name .endm .macro GENERATE_LOOKUP_SUPER name lookup +#if defined(_CALL_ELF) && _CALL_ELF == 2 +\name: + addis %r2, %r12, .TOC.-\name@ha + addi %r2, %r2, .TOC.-\name@l +.localentry \name, .-\name +#else .section .opd, "aw", @progbits \name: .p2align 3 .quad .Lbegin_\name .quad .TOC.@tocbase .quad 0 -.text +.section .text +#endif .Lbegin_\name: mr %r5, %r3 ld %r3, 0(%r3) cmpdi %r3, 0 beq- .LreturnNilMethod @@ -118,21 +136,28 @@ .LreturnNilMethod: addis %r3, %r2, nilMethod@toc@ha addi %r3, %r3, nilMethod@toc@l blr +#if defined(_CALL_ELF) && _CALL_ELF == 2 +nilMethod: + addis %r2, %r12, .TOC.-nilMethod@ha + addi %r2, %r2, .TOC.-nilMethod@l +.localentry nilMethod, .-nilMethod +#else .section .opd, "aw", @progbits nilMethod: .p2align 3 .quad .Lbegin_nilMethod .quad .TOC.@tocbase .quad 0 -.text +.section .text +#endif .Lbegin_nilMethod: li %r3, 0 blr .type nilMethod, @function .size nilMethod, .-.Lbegin_nilMethod #ifdef OF_LINUX .section .note.GNU-stack, "", @progbits #endif Index: src/runtime/lookup-asm/lookup-asm-sparc-elf.S ================================================================== --- src/runtime/lookup-asm/lookup-asm-sparc-elf.S +++ src/runtime/lookup-asm/lookup-asm-sparc-elf.S @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/runtime/lookup-asm/lookup-asm-sparc64-elf.S ================================================================== --- src/runtime/lookup-asm/lookup-asm-sparc64-elf.S +++ src/runtime/lookup-asm/lookup-asm-sparc64-elf.S @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/runtime/lookup-asm/lookup-asm-x86-elf.S ================================================================== --- src/runtime/lookup-asm/lookup-asm-x86-elf.S +++ src/runtime/lookup-asm/lookup-asm-x86-elf.S @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/runtime/lookup-asm/lookup-asm-x86-win32.S ================================================================== --- src/runtime/lookup-asm/lookup-asm-x86-win32.S +++ src/runtime/lookup-asm/lookup-asm-x86-win32.S @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/runtime/lookup-asm/lookup-asm-x86_64-elf.S ================================================================== --- src/runtime/lookup-asm/lookup-asm-x86_64-elf.S +++ src/runtime/lookup-asm/lookup-asm-x86_64-elf.S @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/runtime/lookup-asm/lookup-asm-x86_64-macho.S ================================================================== --- src/runtime/lookup-asm/lookup-asm-x86_64-macho.S +++ src/runtime/lookup-asm/lookup-asm-x86_64-macho.S @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/runtime/lookup-asm/lookup-asm-x86_64-win64.S ================================================================== --- src/runtime/lookup-asm/lookup-asm-x86_64-win64.S +++ src/runtime/lookup-asm/lookup-asm-x86_64-win64.S @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/runtime/lookup-asm/lookup-asm.S ================================================================== --- src/runtime/lookup-asm/lookup-asm.S +++ src/runtime/lookup-asm/lookup-asm.S @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -24,13 +24,13 @@ # 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) +# elif defined(OF_POWERPC64) # include "lookup-asm-powerpc64-elf.S" -# elif defined(OF_POWERPC) && (!defined(_CALL_ELF) || _CALL_ELF == 1) +# 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" Index: src/runtime/lookup.m ================================================================== --- src/runtime/lookup.m +++ src/runtime/lookup.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/runtime/method.m ================================================================== --- src/runtime/method.m +++ src/runtime/method.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/runtime/misc.m ================================================================== --- src/runtime/misc.m +++ src/runtime/misc.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/runtime/private.h ================================================================== --- src/runtime/private.h +++ src/runtime/private.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -357,20 +357,16 @@ objc_error("ObjFWRT @ " __FILE__ ":" OF_STRINGIFY(__LINE__), \ __VA_ARGS__) #if defined(OF_ELF) # if defined(OF_X86_64) || defined(OF_X86) || \ + defined(OF_POWERPC64) || defined(OF_POWERPC) || \ defined(OF_ARM64) || defined(OF_ARM) || \ defined(OF_MIPS64_N64) || defined(OF_MIPS) || \ defined(OF_SPARC64) || defined(OF_SPARC) # define OF_ASM_LOOKUP # endif -# 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) Index: src/runtime/property.m ================================================================== --- src/runtime/property.m +++ src/runtime/property.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/runtime/protocol.m ================================================================== --- src/runtime/protocol.m +++ src/runtime/protocol.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/runtime/selector.m ================================================================== --- src/runtime/selector.m +++ src/runtime/selector.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/runtime/sparsearray.m ================================================================== --- src/runtime/sparsearray.m +++ src/runtime/sparsearray.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/runtime/static-instances.m ================================================================== --- src/runtime/static-instances.m +++ src/runtime/static-instances.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/runtime/synchronized.m ================================================================== --- src/runtime/synchronized.m +++ src/runtime/synchronized.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/runtime/tagged-pointer.m ================================================================== --- src/runtime/tagged-pointer.m +++ src/runtime/tagged-pointer.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/runtime/threading.m ================================================================== --- src/runtime/threading.m +++ src/runtime/threading.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in ADDED src/tls/Info.plist.in Index: src/tls/Info.plist.in ================================================================== --- src/tls/Info.plist.in +++ src/tls/Info.plist.in @@ -0,0 +1,22 @@ + + + + + CFBundleExecutable + ObjFWTLS + CFBundleName + ObjFWTLS + CFBundleIdentifier + im.nil.objfw.tls + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + FMWK + CFBundleVersion + @BUNDLE_VERSION@ + CFBundleShortVersionString + @BUNDLE_SHORT_VERSION@ + MinimumOSVersion + 9.0 + + ADDED src/tls/Makefile Index: src/tls/Makefile ================================================================== --- src/tls/Makefile +++ src/tls/Makefile @@ -0,0 +1,23 @@ +include ../../extra.mk + +DISTCLEAN = Info.plist + +SHARED_LIB = ${OBJFWTLS_SHARED_LIB} +STATIC_LIB = ${OBJFWTLS_STATIC_LIB} +FRAMEWORK = ${OBJFWTLS_FRAMEWORK} +LIB_MAJOR = ${OBJFW_LIB_MAJOR} +LIB_MINOR = ${OBJFW_LIB_MINOR} + +INCLUDES := ObjFWTLS.h +SRCS = ${OF_GNUTLS_TLS_STREAM_M} \ + ${OF_OPENSSL_TLS_STREAM_M} \ + ${OF_SECURE_TRANSPORT_TLS_STREAM_M} + +includesubdir = ObjFWTLS + +include ../../buildsys.mk + +CPPFLAGS += -I. -I.. -I../.. -I../exceptions -I../runtime ${TLS_CPPFLAGS} +LD = ${OBJC} +FRAMEWORK_LIBS := ${TLS_LIBS} -F.. -framework ObjFW ${LIBS} +LIBS := ${TLS_LIBS} -L.. -lobjfw -L../runtime ${RUNTIME_LIBS} ${LIBS} ADDED src/tls/OFGnuTLSTLSStream.h Index: src/tls/OFGnuTLSTLSStream.h ================================================================== --- src/tls/OFGnuTLSTLSStream.h +++ src/tls/OFGnuTLSTLSStream.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2008-2022 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#import "OFTLSStream.h" + +#include + +OF_ASSUME_NONNULL_BEGIN + +@interface OFGnuTLSTLSStream: OFTLSStream +{ + bool _initialized, _handshakeDone; + gnutls_session_t _session; + OFString *_host; +} +@end + +OF_ASSUME_NONNULL_END ADDED src/tls/OFGnuTLSTLSStream.m Index: src/tls/OFGnuTLSTLSStream.m ================================================================== --- src/tls/OFGnuTLSTLSStream.m +++ src/tls/OFGnuTLSTLSStream.m @@ -0,0 +1,356 @@ +/* + * Copyright (c) 2008-2022 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 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 + +#import "OFGnuTLSTLSStream.h" +#import "OFData.h" + +#import "OFAlreadyConnectedException.h" +#import "OFInitializationFailedException.h" +#import "OFNotOpenException.h" +#import "OFReadFailedException.h" +#import "OFTLSHandshakeFailedException.h" +#import "OFWriteFailedException.h" + +int _ObjFWTLS_reference; +static gnutls_certificate_credentials_t systemTrustCreds; + +#ifndef GNUTLS_SAFE_PADDING_CHECK +/* Some older versions don't have it. */ +# define GNUTLS_SAFE_PADDING_CHECK 0 +#endif + +@implementation OFGnuTLSTLSStream +static ssize_t +readFunc(gnutls_transport_ptr_t transport, void *buffer, size_t length) +{ + OFGnuTLSTLSStream *stream = (OFGnuTLSTLSStream *)transport; + + @try { + length = [stream.underlyingStream readIntoBuffer: buffer + length: length]; + } @catch (OFReadFailedException *e) { + gnutls_transport_set_errno(stream->_session, e.errNo); + return -1; + } + + if (length == 0 && !stream.underlyingStream.atEndOfStream) { + gnutls_transport_set_errno(stream->_session, EAGAIN); + return -1; + } + + return length; +} + +static ssize_t +writeFunc(gnutls_transport_ptr_t transport, const void *buffer, size_t length) +{ + OFGnuTLSTLSStream *stream = (OFGnuTLSTLSStream *)transport; + + @try { + [stream.underlyingStream writeBuffer: buffer length: length]; + } @catch (OFWriteFailedException *e) { + gnutls_transport_set_errno(stream->_session, e.errNo); + + if (e.errNo == EWOULDBLOCK || e.errNo == EAGAIN) + return e.bytesWritten; + + return -1; + } + + return length; +} + ++ (void)load +{ + if (OFTLSStreamImplementation == Nil) + OFTLSStreamImplementation = self; +} + ++ (void)initialize +{ + if (self != [OFGnuTLSTLSStream class]) + return; + + if (gnutls_certificate_allocate_credentials(&systemTrustCreds) != + GNUTLS_E_SUCCESS || + gnutls_certificate_set_x509_system_trust(systemTrustCreds) < 0) + @throw [OFInitializationFailedException exception]; +} + +- (instancetype)initWithStream: (OFStream *)stream +{ + self = [super initWithStream: stream]; + + @try { + _underlyingStream.delegate = self; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (void)dealloc +{ + if (_initialized) + [self close]; + + [_host release]; + + [super dealloc]; +} + +- (void)close +{ + if (!_initialized) + @throw [OFNotOpenException exceptionWithObject: self]; + + if (_handshakeDone) + gnutls_bye(_session, GNUTLS_SHUT_WR); + + gnutls_deinit(_session); + _initialized = false; + + [_host release]; + _host = nil; + + [super close]; +} + +- (size_t)lowlevelReadIntoBuffer: (void *)buffer length: (size_t)length +{ + ssize_t ret; + + if (!_handshakeDone) + @throw [OFNotOpenException exceptionWithObject: self]; + + if ((ret = gnutls_record_recv(_session, buffer, length)) < 0) { + /* + * The underlying stream might have had data ready, but not + * enough for GnuTLS to return decrypted data. This means the + * caller might have observed the TLS stream for reading, got a + * ready signal and read - and expects the read to succeed, not + * to fail with EWOULDBLOCK/EAGAIN, as it was signaled ready. + * Therefore, return 0, as we could read 0 decrypted bytes, but + * cleared the ready signal of the underlying stream. + */ + if (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN) + return 0; + + /* FIXME: Translate error to errNo */ + @throw [OFReadFailedException exceptionWithObject: self + requestedLength: length + errNo: 0]; + } + + return ret; +} + +- (size_t)lowlevelWriteBuffer: (const void *)buffer length: (size_t)length +{ + ssize_t ret; + + if (!_handshakeDone) + @throw [OFNotOpenException exceptionWithObject: self]; + + if ((ret = gnutls_record_send(_session, buffer, length)) < 0) { + if (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN) + return 0; + + /* FIXME: Translate error to errNo */ + @throw [OFWriteFailedException exceptionWithObject: self + requestedLength: length + bytesWritten: ret + errNo: 0]; + } + + return ret; +} + +- (bool)hasDataInReadBuffer +{ + if (gnutls_record_check_pending(_session) > 0) + return true; + + return super.hasDataInReadBuffer; +} + +- (void)asyncPerformClientHandshakeWithHost: (OFString *)host + runLoopMode: (OFRunLoopMode)runLoopMode +{ + static const OFTLSStreamErrorCode initFailedErrorCode = + OFTLSStreamErrorCodeInitializationFailed; + id exception = nil; + int status; + + if (_initialized) + @throw [OFAlreadyConnectedException exceptionWithSocket: self]; + + if (gnutls_init(&_session, GNUTLS_CLIENT | GNUTLS_NONBLOCK | + GNUTLS_SAFE_PADDING_CHECK) != GNUTLS_E_SUCCESS) + @throw [OFTLSHandshakeFailedException + exceptionWithStream: self + host: host + errorCode: initFailedErrorCode]; + + _initialized = true; + + gnutls_transport_set_ptr(_session, self); + gnutls_transport_set_pull_function(_session, readFunc); + gnutls_transport_set_push_function(_session, writeFunc); + + if (gnutls_set_default_priority(_session) != GNUTLS_E_SUCCESS || + gnutls_credentials_set(_session, GNUTLS_CRD_CERTIFICATE, + systemTrustCreds) != GNUTLS_E_SUCCESS) + @throw [OFTLSHandshakeFailedException + exceptionWithStream: self + host: host + errorCode: initFailedErrorCode]; + + _host = [host copy]; + + if (gnutls_server_name_set(_session, GNUTLS_NAME_DNS, + _host.UTF8String, _host.UTF8StringLength) != GNUTLS_E_SUCCESS) + @throw [OFTLSHandshakeFailedException + exceptionWithStream: self + host: host + errorCode: initFailedErrorCode]; + + if (_verifiesCertificates) + gnutls_session_set_verify_cert(_session, _host.UTF8String, 0); + + status = gnutls_handshake(_session); + + if (status == GNUTLS_E_INTERRUPTED || status == GNUTLS_E_AGAIN) { + if (gnutls_record_get_direction(_session) == 1) + [_underlyingStream + asyncWriteData: [OFData dataWithItems: "" count: 0] + runLoopMode: runLoopMode]; + else + [_underlyingStream asyncReadIntoBuffer: (void *)"" + length: 0 + runLoopMode: runLoopMode]; + + [_delegate retain]; + return; + } + + if (status == GNUTLS_E_SUCCESS) + _handshakeDone = true; + else + /* FIXME: Map to better errors */ + exception = [OFTLSHandshakeFailedException + exceptionWithStream: self + host: host + errorCode: OFTLSStreamErrorCodeUnknown]; + + if ([_delegate respondsToSelector: + @selector(stream:didPerformClientHandshakeWithHost:exception:)]) + [_delegate stream: self + didPerformClientHandshakeWithHost: host + exception: exception]; +} + +- (bool)stream: (OFStream *)stream + didReadIntoBuffer: (void *)buffer + length: (size_t)length + exception: (nullable id)exception +{ + if (exception == nil) { + int status = gnutls_handshake(_session); + + if (status == GNUTLS_E_INTERRUPTED || + status == GNUTLS_E_AGAIN) { + if (gnutls_record_get_direction(_session) == 1) { + OFData *data = [OFData dataWithItems: "" + count: 0]; + OFRunLoopMode runLoopMode = + [OFRunLoop currentRunLoop].currentMode; + [_underlyingStream asyncWriteData: data + runLoopMode: runLoopMode]; + return false; + } else + return true; + } + + if (status == GNUTLS_E_SUCCESS) + _handshakeDone = true; + else + exception = [OFTLSHandshakeFailedException + exceptionWithStream: self + host: _host + errorCode: OFTLSStreamErrorCodeUnknown]; + } + + if ([_delegate respondsToSelector: + @selector(stream:didPerformClientHandshakeWithHost:exception:)]) + [_delegate stream: self + didPerformClientHandshakeWithHost: _host + exception: exception]; + + [_delegate release]; + + return false; +} + +- (OFData *)stream: (OFStream *)stream + didWriteData: (OFData *)data + bytesWritten: (size_t)bytesWritten + exception: (id)exception +{ + if (exception == nil) { + int status = gnutls_handshake(_session); + + if (status == GNUTLS_E_INTERRUPTED || + status == GNUTLS_E_AGAIN) { + if (gnutls_record_get_direction(_session) == 1) + return data; + else { + OFRunLoopMode runLoopMode = + [OFRunLoop currentRunLoop].currentMode; + [_underlyingStream + asyncReadIntoBuffer: (void *)"" + length: 0 + runLoopMode: runLoopMode]; + return nil; + } + } + + if (status == GNUTLS_E_SUCCESS) + _handshakeDone = true; + else + exception = [OFTLSHandshakeFailedException + exceptionWithStream: self + host: _host + errorCode: OFTLSStreamErrorCodeUnknown]; + } + + if ([_delegate respondsToSelector: + @selector(stream:didPerformClientHandshakeWithHost:exception:)]) + [_delegate stream: self + didPerformClientHandshakeWithHost: _host + exception: exception]; + + [_delegate release]; + + return nil; +} +@end ADDED src/tls/OFOpenSSLTLSStream.h Index: src/tls/OFOpenSSLTLSStream.h ================================================================== --- src/tls/OFOpenSSLTLSStream.h +++ src/tls/OFOpenSSLTLSStream.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2008-2022 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#import "OFTLSStream.h" + +#include +#include + +OF_ASSUME_NONNULL_BEGIN + +#define OFOpenSSLTLSStreamBufferSize 512 + +@interface OFOpenSSLTLSStream: OFTLSStream +{ + bool _handshakeDone; + SSL *_SSL; + BIO *_readBIO, *_writeBIO; + OFString *_host; + char _buffer[OFOpenSSLTLSStreamBufferSize]; +} +@end + +OF_ASSUME_NONNULL_END ADDED src/tls/OFOpenSSLTLSStream.m Index: src/tls/OFOpenSSLTLSStream.m ================================================================== --- src/tls/OFOpenSSLTLSStream.m +++ src/tls/OFOpenSSLTLSStream.m @@ -0,0 +1,428 @@ +/* + * Copyright (c) 2008-2022 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 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 + +#import "OFOpenSSLTLSStream.h" +#import "OFData.h" + +#import "OFAlreadyConnectedException.h" +#import "OFInitializationFailedException.h" +#import "OFNotOpenException.h" +#import "OFReadFailedException.h" +#import "OFTLSHandshakeFailedException.h" +#import "OFWriteFailedException.h" + +#define bufferSize OFOpenSSLTLSStreamBufferSize + +int _ObjFWTLS_reference; +static SSL_CTX *clientContext; + +@implementation OFOpenSSLTLSStream ++ (void)load +{ + if (OFTLSStreamImplementation == Nil) + OFTLSStreamImplementation = self; +} + ++ (void)initialize +{ + if (self != [OFOpenSSLTLSStream class]) + return; + + SSL_load_error_strings(); + SSL_library_init(); + + if ((clientContext = SSL_CTX_new(TLS_client_method())) == NULL || + SSL_CTX_set_default_verify_paths(clientContext) != 1) + @throw [OFInitializationFailedException + exceptionWithClass: self]; +} + +- (instancetype)initWithStream: (OFStream *)stream +{ + self = [super initWithStream: stream]; + + @try { + _underlyingStream.delegate = self; + /* + * Buffer writes so that nothing gets lost if we write more + * than the underlying stream can write. + */ + _underlyingStream.buffersWrites = true; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (void)dealloc +{ + if (_SSL != NULL) + [self close]; + + [_host release]; + + [super dealloc]; +} + +- (void)close +{ + if (_SSL == NULL) + @throw [OFNotOpenException exceptionWithObject: self]; + + if (_handshakeDone) + SSL_shutdown(_SSL); + + SSL_free(_SSL); + _SSL = NULL; + + [_host release]; + _host = nil; + + [super close]; +} + +- (size_t)lowlevelReadIntoBuffer: (void *)buffer length: (size_t)length +{ + int ret; + size_t bytesRead; + + if (!_handshakeDone) + @throw [OFNotOpenException exceptionWithObject: self]; + + if (BIO_ctrl_pending(_readBIO) < 1) { + @try { + size_t tmp = [_underlyingStream + readIntoBuffer: _buffer + length: bufferSize]; + + OFEnsure(tmp <= INT_MAX); + /* Writing to a memory BIO must never fail. */ + OFEnsure(BIO_write(_readBIO, _buffer, (int)tmp) == + (int)tmp); + } @catch (OFReadFailedException *e) { + if (e.errNo != EWOULDBLOCK && e.errNo != EAGAIN) + @throw e; + } + } + + ret = SSL_read_ex(_SSL, buffer, length, &bytesRead); + + while (BIO_ctrl_pending(_writeBIO) > 0) { + int tmp = BIO_read(_writeBIO, _buffer, bufferSize); + + OFEnsure(tmp >= 0); + + [_underlyingStream writeBuffer: _buffer length: tmp]; + [_underlyingStream flushWriteBuffer]; + } + + if (ret != 1) { + /* + * The underlying stream might have had data ready, but not + * enough for OpenSSL to return decrypted data. This means the + * caller might have observed the TLS stream for reading, got a + * ready signal and read - and expects the read to succeed, not + * to fail with EWOULDBLOCK, as it was signaled ready. + * Therefore, return 0, as we could read 0 decrypted bytes, but + * cleared the ready signal of the underlying stream. + */ + if (SSL_get_error(_SSL, ret) == SSL_ERROR_WANT_READ) + return 0; + + /* FIXME: Translate error to errNo */ + @throw [OFReadFailedException exceptionWithObject: self + requestedLength: length + errNo: 0]; + } + + return bytesRead; +} + +- (size_t)lowlevelWriteBuffer: (const void *)buffer length: (size_t)length +{ + int ret; + size_t bytesWritten; + + if (!_handshakeDone) + @throw [OFNotOpenException exceptionWithObject: self]; + + if ((ret = SSL_write_ex(_SSL, buffer, length, &bytesWritten)) != 1) { + /* FIXME: Translate error to errNo */ + int errNo = 0; + + if (SSL_get_error(_SSL, ret) == SSL_ERROR_WANT_WRITE) + return bytesWritten; + + @throw [OFWriteFailedException exceptionWithObject: self + requestedLength: length + bytesWritten: bytesWritten + errNo: errNo]; + } + + while (BIO_ctrl_pending(_writeBIO) > 0) { + int tmp = BIO_read(_writeBIO, _buffer, bufferSize); + + OFEnsure(tmp >= 0); + + [_underlyingStream writeBuffer: _buffer length: tmp]; + [_underlyingStream flushWriteBuffer]; + } + + return bytesWritten; +} + +- (bool)hasDataInReadBuffer +{ + if (SSL_pending(_SSL) > 0 || BIO_ctrl_pending(_readBIO) > 0) + return true; + + return super.hasDataInReadBuffer; +} + +- (void)asyncPerformClientHandshakeWithHost: (OFString *)host + runLoopMode: (OFRunLoopMode)runLoopMode +{ + static const OFTLSStreamErrorCode initFailedErrorCode = + OFTLSStreamErrorCodeInitializationFailed; + id exception = nil; + int status; + + if (_SSL != NULL) + @throw [OFAlreadyConnectedException exceptionWithSocket: self]; + + if ((_readBIO = BIO_new(BIO_s_mem())) == NULL) + @throw [OFTLSHandshakeFailedException + exceptionWithStream: self + host: host + errorCode: initFailedErrorCode]; + + if ((_writeBIO = BIO_new(BIO_s_mem())) == NULL) { + BIO_free(_readBIO); + @throw [OFTLSHandshakeFailedException + exceptionWithStream: self + host: host + errorCode: initFailedErrorCode]; + } + + BIO_set_mem_eof_return(_readBIO, -1); + BIO_set_mem_eof_return(_writeBIO, -1); + + if ((_SSL = SSL_new(clientContext)) == NULL) { + BIO_free(_readBIO); + BIO_free(_writeBIO); + @throw [OFTLSHandshakeFailedException + exceptionWithStream: self + host: host + errorCode: initFailedErrorCode]; + } + + SSL_set_bio(_SSL, _readBIO, _writeBIO); + SSL_set_connect_state(_SSL); + + _host = [host copy]; + + if (SSL_set_tlsext_host_name(_SSL, _host.UTF8String) != 1) + @throw [OFTLSHandshakeFailedException + exceptionWithStream: self + host: host + errorCode: initFailedErrorCode]; + + if (_verifiesCertificates) { + SSL_set_verify(_SSL, SSL_VERIFY_PEER, NULL); + + if (SSL_set1_host(_SSL, _host.UTF8String) != 1) + @throw [OFTLSHandshakeFailedException + exceptionWithStream: self + host: host + errorCode: initFailedErrorCode]; + } + + status = SSL_do_handshake(_SSL); + + while (BIO_ctrl_pending(_writeBIO) > 0) { + int tmp = BIO_read(_writeBIO, _buffer, bufferSize); + + OFEnsure(tmp >= 0); + + [_underlyingStream writeBuffer: _buffer length: tmp]; + [_underlyingStream flushWriteBuffer]; + } + + if (status == 1) + _handshakeDone = true; + else { + switch (SSL_get_error(_SSL, status)) { + case SSL_ERROR_WANT_READ: + [_underlyingStream asyncReadIntoBuffer: _buffer + length: bufferSize + runLoopMode: runLoopMode]; + [_delegate retain]; + return; + case SSL_ERROR_WANT_WRITE: + [_underlyingStream + asyncWriteData: [OFData dataWithItems: "" count: 0] + runLoopMode: runLoopMode]; + [_delegate retain]; + return; + default: + /* FIXME: Map to better errors */ + exception = [OFTLSHandshakeFailedException + exceptionWithStream: self + host: host + errorCode: OFTLSStreamErrorCodeUnknown]; + break; + } + } + + if ([_delegate respondsToSelector: + @selector(stream:didPerformClientHandshakeWithHost:exception:)]) + [_delegate stream: self + didPerformClientHandshakeWithHost: host + exception: exception]; +} + +- (bool)stream: (OFStream *)stream + didReadIntoBuffer: (void *)buffer + length: (size_t)length + exception: (nullable id)exception +{ + if (exception == nil) { + static const OFTLSStreamErrorCode unknownErrorCode = + OFTLSStreamErrorCodeUnknown; + int status; + OFData *data; + + OFEnsure(length <= INT_MAX); + OFEnsure(BIO_write(_readBIO, buffer, (int)length) == + (int)length); + + status = SSL_do_handshake(_SSL); + + while (BIO_ctrl_pending(_writeBIO) > 0) { + int tmp = BIO_read(_writeBIO, buffer, bufferSize); + + OFEnsure(tmp >= 0); + + [_underlyingStream writeBuffer: _buffer length: tmp]; + [_underlyingStream flushWriteBuffer]; + } + + if (status == 1) + _handshakeDone = true; + else { + switch (SSL_get_error(_SSL, status)) { + case SSL_ERROR_WANT_READ: + return true; + case SSL_ERROR_WANT_WRITE: + data = [OFData dataWithItems: "" count: 0]; + OFRunLoopMode runLoopMode = + [OFRunLoop currentRunLoop].currentMode; + [_underlyingStream asyncWriteData: data + runLoopMode: runLoopMode]; + return false; + default: + exception = [OFTLSHandshakeFailedException + exceptionWithStream: self + host: _host + errorCode: unknownErrorCode]; + break; + } + } + } + + if ([_delegate respondsToSelector: + @selector(stream:didPerformClientHandshakeWithHost:exception:)]) + [_delegate stream: self + didPerformClientHandshakeWithHost: _host + exception: exception]; + + [_delegate release]; + + return false; +} + +- (OFData *)stream: (OFStream *)stream + didWriteData: (OFData *)data + bytesWritten: (size_t)bytesWritten + exception: (id)exception +{ + if (exception == nil) { + static const OFTLSStreamErrorCode unknownErrorCode = + OFTLSStreamErrorCodeUnknown; + int status; + OFRunLoopMode runLoopMode; + + while (BIO_ctrl_pending(_writeBIO) > 0) { + int tmp = BIO_read(_writeBIO, _buffer, bufferSize); + + OFEnsure(tmp >= 0); + + [_underlyingStream writeBuffer: _buffer length: tmp]; + [_underlyingStream flushWriteBuffer]; + } + + status = SSL_do_handshake(_SSL); + + while (BIO_ctrl_pending(_writeBIO) > 0) { + int tmp = BIO_read(_writeBIO, _buffer, bufferSize); + + OFEnsure(tmp >= 0); + + [_underlyingStream writeBuffer: _buffer length: tmp]; + [_underlyingStream flushWriteBuffer]; + } + + if (status == 1) + _handshakeDone = true; + else { + switch (SSL_get_error(_SSL, status)) { + case SSL_ERROR_WANT_READ: + runLoopMode = + [OFRunLoop currentRunLoop].currentMode; + [_underlyingStream + asyncReadIntoBuffer: _buffer + length: bufferSize + runLoopMode: runLoopMode]; + return nil; + case SSL_ERROR_WANT_WRITE: + return data; + default: + exception = [OFTLSHandshakeFailedException + exceptionWithStream: self + host: _host + errorCode: unknownErrorCode]; + break; + } + } + } + + if ([_delegate respondsToSelector: + @selector(stream:didPerformClientHandshakeWithHost:exception:)]) + [_delegate stream: self + didPerformClientHandshakeWithHost: _host + exception: exception]; + + [_delegate release]; + + return nil; +} +@end ADDED src/tls/OFSecureTransportTLSStream.h Index: src/tls/OFSecureTransportTLSStream.h ================================================================== --- src/tls/OFSecureTransportTLSStream.h +++ src/tls/OFSecureTransportTLSStream.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2008-2022 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#import "OFTLSStream.h" + +#include + +OF_ASSUME_NONNULL_BEGIN + +@interface OFSecureTransportTLSStream: OFTLSStream +{ + SSLContextRef _context; + OFString *_host; +} +@end + +OF_ASSUME_NONNULL_END ADDED src/tls/OFSecureTransportTLSStream.m Index: src/tls/OFSecureTransportTLSStream.m ================================================================== --- src/tls/OFSecureTransportTLSStream.m +++ src/tls/OFSecureTransportTLSStream.m @@ -0,0 +1,281 @@ +/* + * Copyright (c) 2008-2022 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 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 + +#import "OFSecureTransportTLSStream.h" + +#import "OFAlreadyConnectedException.h" +#import "OFNotOpenException.h" +#import "OFReadFailedException.h" +#import "OFTLSHandshakeFailedException.h" +#import "OFWriteFailedException.h" + +int _ObjFWTLS_reference; + +static OSStatus +readFunc(SSLConnectionRef connection, void *data, size_t *dataLength) +{ + bool incomplete; + size_t length; + + @try { + length = [((OFTLSStream *)connection).underlyingStream + readIntoBuffer: data + length: *dataLength]; + } @catch (OFReadFailedException *e) { + if (e.errNo == EWOULDBLOCK || e.errNo == EAGAIN) { + *dataLength = 0; + return errSSLWouldBlock; + } + + @throw e; + } + + incomplete = (length < *dataLength); + *dataLength = length; + + return (incomplete ? errSSLWouldBlock : noErr); +} + +static OSStatus +writeFunc(SSLConnectionRef connection, const void *data, size_t *dataLength) +{ + @try { + [((OFTLSStream *)connection).underlyingStream + writeBuffer: data + length: *dataLength]; + } @catch (OFWriteFailedException *e) { + *dataLength = e.bytesWritten; + + if (e.errNo == EWOULDBLOCK || e.errNo == EAGAIN) + return errSSLWouldBlock; + + @throw e; + } + + return noErr; +} + +/* + * Apple deprecated Secure Transport without providing a replacement that can + * work with any socket. On top of that, their replacement, Network.framework, + * doesn't support STARTTLS at all. + */ +#if OF_GCC_VERSION >= 402 +# pragma GCC diagnostic ignored "-Wdeprecated" +#endif + +@implementation OFSecureTransportTLSStream ++ (void)load +{ + if (OFTLSStreamImplementation == Nil) + OFTLSStreamImplementation = self; +} + +- (instancetype)initWithStream: (OFStream *)stream +{ + self = [super initWithStream: stream]; + + @try { + _underlyingStream.delegate = self; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (void)dealloc +{ + if (_context != NULL) + [self close]; + + [_host release]; + + [super dealloc]; +} + +- (void)close +{ + if (_context == NULL) + @throw [OFNotOpenException exceptionWithObject: self]; + + [_host release]; + _host = nil; + + SSLClose(_context); +#ifdef HAVE_SSLCREATECONTEXT + CFRelease(_context); +#else + SSLDisposeContext(_context); +#endif + _context = NULL; + + [super close]; +} + +- (size_t)lowlevelReadIntoBuffer: (void *)buffer length: (size_t)length +{ + OSStatus status; + size_t ret; + + if (_context == NULL) + @throw [OFNotOpenException exceptionWithObject: self]; + + status = SSLRead(_context, buffer, length, &ret); + if (status != noErr && status != errSSLWouldBlock) + /* FIXME: Translate status to errNo */ + @throw [OFReadFailedException exceptionWithObject: self + requestedLength: length + errNo: 0]; + + return ret; +} + +- (size_t)lowlevelWriteBuffer: (const void *)buffer length: (size_t)length +{ + OSStatus status; + size_t bytesWritten = 0; + + if (_context == NULL) + @throw [OFNotOpenException exceptionWithObject: self]; + + status = SSLWrite(_context, buffer, length, &bytesWritten); + if (status != noErr && status != errSSLWouldBlock) + /* FIXME: Translate status to errNo */ + @throw [OFWriteFailedException exceptionWithObject: self + requestedLength: length + bytesWritten: bytesWritten + errNo: 0]; + + return bytesWritten; +} + +- (bool)hasDataInReadBuffer +{ + size_t bufferSize; + + if (SSLGetBufferedReadSize(_context, &bufferSize) == noErr && + bufferSize > 0) + return true; + + return super.hasDataInReadBuffer; +} + +- (void)asyncPerformClientHandshakeWithHost: (OFString *)host + runLoopMode: (OFRunLoopMode)runLoopMode +{ + static const OFTLSStreamErrorCode initFailedErrorCode = + OFTLSStreamErrorCodeInitializationFailed; + id exception = nil; + OSStatus status; + + if (_context != NULL) + @throw [OFAlreadyConnectedException exceptionWithSocket: self]; + +#ifdef HAVE_SSLCREATECONTEXT + if ((_context = SSLCreateContext(kCFAllocatorDefault, kSSLClientSide, + kSSLStreamType)) == NULL) +#else + if (SSLNewContext(false, &_context) != noErr) +#endif + @throw [OFTLSHandshakeFailedException + exceptionWithStream: self + host: host + errorCode: initFailedErrorCode]; + + if (SSLSetIOFuncs(_context, readFunc, writeFunc) != noErr || + SSLSetConnection(_context, self) != noErr) + @throw [OFTLSHandshakeFailedException + exceptionWithStream: self + host: host + errorCode: initFailedErrorCode]; + + _host = [host copy]; + + if (_verifiesCertificates) + if (SSLSetPeerDomainName(_context, + _host.UTF8String, _host.UTF8StringLength) != noErr) + @throw [OFTLSHandshakeFailedException + exceptionWithStream: self + host: _host + errorCode: initFailedErrorCode]; + + status = SSLHandshake(_context); + + if (status == errSSLWouldBlock) { + /* + * Theoretically it is possible we block because Secure + * Transport cannot write without blocking. But unfortunately, + * Secure Transport does not tell us whether it's blocked on + * reading or writing. Waiting for the stream to be either + * readable or writable doesn't work either, as the stream is + * almost always at least ready for one of the two. + */ + [_underlyingStream asyncReadIntoBuffer: (void *)"" + length: 0 + runLoopMode: runLoopMode]; + [_delegate retain]; + return; + } + + if (status != noErr) + /* FIXME: Map to better errors */ + exception = [OFTLSHandshakeFailedException + exceptionWithStream: self + host: _host + errorCode: OFTLSStreamErrorCodeUnknown]; + + if ([_delegate respondsToSelector: + @selector(stream:didPerformClientHandshakeWithHost:exception:)]) + [_delegate stream: self + didPerformClientHandshakeWithHost: _host + exception: exception]; +} + +- (bool)stream: (OFStream *)stream + didReadIntoBuffer: (void *)buffer + length: (size_t)length + exception: (nullable id)exception +{ + if (exception == nil) { + OSStatus status = SSLHandshake(_context); + + if (status == errSSLWouldBlock) + return true; + + if (status != noErr) + exception = [OFTLSHandshakeFailedException + exceptionWithStream: self + host: _host + errorCode: OFTLSStreamErrorCodeUnknown]; + } + + if ([_delegate respondsToSelector: + @selector(stream:didPerformClientHandshakeWithHost:exception:)]) + [_delegate stream: self + didPerformClientHandshakeWithHost: _host + exception: exception]; + + [_delegate release]; + + return false; +} +@end ADDED src/tls/ObjFWTLS.h Index: src/tls/ObjFWTLS.h ================================================================== --- src/tls/ObjFWTLS.h +++ src/tls/ObjFWTLS.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2008-2022 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either 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 "macros.h" + +#ifdef __cplusplus +extern "C" { +#endif +extern int _ObjFWTLS_reference; +#ifdef __cplusplus +} +#endif Index: src/unicode.h ================================================================== --- src/unicode.h +++ src/unicode.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/unicode.m ================================================================== --- src/unicode.m +++ src/unicode.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/unistd_wrapper.h ================================================================== --- src/unistd_wrapper.h +++ src/unistd_wrapper.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: tests/ForwardingTests.m ================================================================== --- tests/ForwardingTests.m +++ tests/ForwardingTests.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: tests/ImportTest.m ================================================================== --- tests/ImportTest.m +++ tests/ImportTest.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: tests/Makefile ================================================================== --- tests/Makefile +++ tests/Makefile @@ -5,11 +5,16 @@ terminal CLEAN = EBOOT.PBP \ boot.dol \ ${PROG_NOINST}.arm9 \ - ${PROG_NOINST}.nds + ${PROG_NOINST}.nds \ + ${PROG_NOINST}.nro \ + ${PROG_NOINST}.rpx \ + serialization_xml.m \ + testfile_bin.m \ + testfile_ini.m DISTCLEAN = Info.plist PROG_NOINST = tests${PROG_SUFFIX} STATIC_LIB_NOINST = ${TESTS_STATIC_LIB} SRCS = ForwardingTests.m \ @@ -17,20 +22,32 @@ ${OF_BLOCK_TESTS_M} \ OFCharacterSetTests.m \ OFDataTests.m \ OFDateTests.m \ OFDictionaryTests.m \ + OFHMACTests.m \ + OFINIFileTests.m \ OFInvocationTests.m \ OFJSONTests.m \ OFListTests.m \ OFLocaleTests.m \ + OFMD5HashTests.m \ + OFMemoryStreamTests.m \ OFMethodSignatureTests.m \ + OFNotificationCenterTests.m \ OFNumberTests.m \ OFObjectTests.m \ OFPBKDF2Tests.m \ OFPropertyListTests.m \ + OFRIPEMD160HashTests.m \ + OFSHA1HashTests.m \ + OFSHA224HashTests.m \ + OFSHA256HashTests.m \ + OFSHA384HashTests.m \ + OFSHA512HashTests.m \ OFScryptTests.m \ + OFSerializationTests.m \ OFSetTests.m \ OFStreamTests.m \ OFStringTests.m \ OFSystemInfoTests.m \ OFURLTests.m \ @@ -43,42 +60,45 @@ TestsAppDelegate.m \ ${USE_SRCS_FILES} \ ${USE_SRCS_PLUGINS} \ ${USE_SRCS_SOCKETS} \ ${USE_SRCS_THREADS} \ - ${USE_SRCS_WINDOWS} -SRCS_FILES = OFHMACTests.m \ - OFINIFileTests.m \ - OFMD5HashTests.m \ - OFRIPEMD160HashTests.m \ - OFSerializationTests.m \ - OFSHA1HashTests.m \ - OFSHA224HashTests.m \ - OFSHA256HashTests.m \ - OFSHA384HashTests.m \ - OFSHA512HashTests.m -SRCS_IPX = OFIPXSocketTests.m \ - OFSPXSocketTests.m \ - OFSPXStreamSocketTests.m + ${USE_SRCS_WINDOWS} \ + serialization_xml.m \ + testfile_bin.m \ + testfile_ini.m SRCS_PLUGINS = OFPluginTests.m SRCS_SOCKETS = OFDNSResolverTests.m \ ${OF_HTTP_CLIENT_TESTS_M} \ OFHTTPCookieTests.m \ OFHTTPCookieManagerTests.m \ OFKernelEventObserverTests.m \ OFSocketTests.m \ OFTCPSocketTests.m \ OFUDPSocketTests.m \ - ${USE_SRCS_IPX} + ${USE_SRCS_IPX} \ + ${USE_SRCS_UNIX_SOCKETS} +SRCS_IPX = OFIPXSocketTests.m \ + OFSPXSocketTests.m \ + OFSPXStreamSocketTests.m +SRCS_UNIX_SOCKETS = OFUNIXDatagramSocketTests.m \ + OFUNIXStreamSocketTests.m SRCS_THREADS = OFThreadTests.m SRCS_WINDOWS = OFWindowsRegistryKeyTests.m IOS_USER ?= mobile IOS_TMP ?= /tmp/objfw-test include ../buildsys.mk +serialization_xml.m: serialization.xml + ${SHELL} ../utils/objfw-embed serialization.xml /serialization.xml $@ +testfile_bin.m: testfile.bin + ${SHELL} ../utils/objfw-embed testfile.bin /testfile.bin $@ +testfile_ini.m: testfile.ini + ${SHELL} ../utils/objfw-embed testfile.ini /testfile.ini $@ + .PHONY: run run-on-ios run-on-android run: rm -f libobjfw.so.${OBJFW_LIB_MAJOR} rm -f libobjfw.so.${OBJFW_LIB_MAJOR_MINOR} rm -f objfw${OBJFW_LIB_MAJOR}.dll libobjfw.${OBJFW_LIB_MAJOR}.dylib @@ -151,12 +171,11 @@ ssh ${IOS_USER}@${IOS_HOST} \ 'rm -fr ${IOS_TMP} && mkdir -p ${IOS_TMP}/plugin' destname=libobjfw.${OBJFW_LIB_MAJOR}.dylib; \ scp -q ../src/libobjfw.dylib \ ${IOS_USER}@${IOS_HOST}:${IOS_TMP}/$$destname - scp -q tests testfile.bin testfile.txt testfile.ini serialization.xml \ - ${IOS_USER}@${IOS_HOST}:${IOS_TMP}/ + scp -q tests testfile.txt ${IOS_USER}@${IOS_HOST}:${IOS_TMP}/ scp -q plugin/TestPlugin.bundle \ ${IOS_USER}@${IOS_HOST}:${IOS_TMP}/plugin/ echo "Running tests binary on iOS device ${IOS_HOST}..." ssh ${IOS_USER}@${IOS_HOST} \ 'cd ${IOS_TMP} && DYLD_LIBRARY_PATH=. ${WRAPPER} ./tests' @@ -170,14 +189,11 @@ if test -f ../src/runtime/libobjfwrt.so; then \ adb push ../src/runtime/libobjfwrt.so \ /data/local/tmp/objfw/libobjfwrt.so.${OBJFWRT_LIB_MAJOR}; \ fi adb push tests /data/local/tmp/objfw/tests - adb push testfile.bin /data/local/tmp/objfw/testfile.bin adb push testfile.txt /data/local/tmp/objfw/testfile.txt - adb push testfile.ini /data/local/tmp/objfw/testfile.ini - adb push serialization.xml /data/local/tmp/objfw/serialization.xml if test -f plugin/TestPlugin.so; then \ adb push plugin/TestPlugin.so \ /data/local/tmp/objfw/plugin/TestPlugin.so; \ fi echo "Running tests binary on Android device..." @@ -191,24 +207,36 @@ boot.dol: ${PROG_NOINST} elf2dol ${PROG_NOINST} $@ ${PROG_NOINST}: ${LIBOBJFW_DEP} ${LIBOBJFWRT_DEP} + +${PROG_NOINST}.3dsx: ${PROG_NOINST} + 3dsxtool $< $@ ${PROG_NOINST}.arm9: ${PROG_NOINST} arm-none-eabi-objcopy -O binary $< $@ -${PROG_NOINST}.nds: ${PROG_NOINST}.arm9 +${PROG_NOINST}.nds: ${PROG_NOINST}.arm9 testfile.txt rm -fr nds-data mkdir -p nds-data - cp testfile.bin testfile.txt testfile.ini serialization.xml nds-data - ndstool -c $@ -9 $< -d nds-data + cp testfile.txt nds-data + ndstool -c $@ -9 ${PROG_NOINST} -d nds-data rm -fr nds-data -${PROG_NOINST}.3dsx: ${PROG_NOINST} - 3dsxtool $< $@ +${PROG_NOINST}.nro: ${PROG_NOINST} testfile.txt + rm -fr romfs + mkdir -p romfs + cp testfile.txt romfs + nacptool --create "ObjFW tests" "Jonathan Schleifer" \ + "${PACKAGE_VERSION}" tests.nacp + elf2nro ${PROG_NOINST} $@ --nacp=tests.nacp --romfsdir=romfs + rm -fr romfs tests.nacp + +${PROG_NOINST}.rpx: ${PROG_NOINST} + elf2rpl $< $@ CPPFLAGS += -I../src -I../src/exceptions -I../src/runtime -I.. -DSTDOUT OBJCFLAGS_RuntimeARCTests.m = -fobjc-arc -fobjc-arc-exceptions LIBS := ${TESTS_LIBS} ${LIBS} LDFLAGS += ${MAP_LDFLAGS} LD = ${OBJC} Index: tests/OFArrayTests.m ================================================================== --- tests/OFArrayTests.m +++ tests/OFArrayTests.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -208,11 +208,13 @@ [[mutableArray1 objectAtIndex: 1] isEqual: cArray[0]] && [[mutableArray1 objectAtIndex: 2] isEqual: cArray[2]]) TEST(@"-[removeObject:]", R([mutableArray1 removeObject: cArray[0]]) && - mutableArray1.count == 2) + mutableArray1.count == 1) + + [mutableArray1 addObject: cArray[0]]; TEST(@"-[removeObjectIdenticalTo:]", R([mutableArray1 removeObjectIdenticalTo: cArray[2]]) && mutableArray1.count == 1) Index: tests/OFBlockTests.m ================================================================== --- tests/OFBlockTests.m +++ tests/OFBlockTests.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: tests/OFCharacterSetTests.m ================================================================== --- tests/OFCharacterSetTests.m +++ tests/OFCharacterSetTests.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: tests/OFDNSResolverTests.m ================================================================== --- tests/OFDNSResolverTests.m +++ tests/OFDNSResolverTests.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: tests/OFDataTests.m ================================================================== --- tests/OFDataTests.m +++ tests/OFDataTests.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: tests/OFDateTests.m ================================================================== --- tests/OFDateTests.m +++ tests/OFDateTests.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -16,10 +16,11 @@ #include "config.h" #include #import "TestsAppDelegate.h" +#import "OFStrPTime.h" static OFString *const module = @"OFDate"; @implementation TestsAppDelegate (OFDateTests) - (void)dateTests Index: tests/OFDictionaryTests.m ================================================================== --- tests/OFDictionaryTests.m +++ tests/OFDictionaryTests.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: tests/OFHMACTests.m ================================================================== --- tests/OFHMACTests.m +++ tests/OFHMACTests.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -49,11 +49,13 @@ @implementation TestsAppDelegate (OFHMACTests) - (void)HMACTests { void *pool = objc_autoreleasePoolPush(); - OFFile *file = [OFFile fileWithPath: @"testfile.bin" mode: @"r"]; + OFURL *URL = [OFURL URLWithString: @"objfw-embedded:///testfile.bin"]; + OFStream *file = [[OFURLHandler handlerForURL: URL] + openItemAtURL: URL mode: @"r"]; OFHMAC *HMACMD5, *HMACSHA1, *HMACRMD160; OFHMAC *HMACSHA256, *HMACSHA384, *HMACSHA512; TEST(@"+[HMACWithHashClass:] with MD5", (HMACMD5 = [OFHMAC HMACWithHashClass: [OFMD5Hash class] @@ -101,10 +103,17 @@ [HMACSHA384 updateWithBuffer: buffer length: length]; [HMACSHA512 updateWithBuffer: buffer length: length]; } [file close]; + TEST(@"-[calculate] with MD5", R([HMACMD5 calculate])) + TEST(@"-[calculate] with SHA-1", R([HMACSHA1 calculate])) + TEST(@"-[calculate] with RIPEMD-160", R([HMACRMD160 calculate])) + TEST(@"-[calculate] with SHA-256", R([HMACSHA256 calculate])) + TEST(@"-[calculate] with SHA-384", R([HMACSHA384 calculate])) + TEST(@"-[calculate] with SHA-512", R([HMACSHA512 calculate])) + TEST(@"-[digest] with MD5", memcmp(HMACMD5.digest, MD5Digest, HMACMD5.digestSize) == 0) TEST(@"-[digest] with SHA-1", memcmp(HMACSHA1.digest, SHA1Digest, HMACSHA1.digestSize) == 0) TEST(@"-[digest] with RIPEMD-160", Index: tests/OFHTTPClientTests.m ================================================================== --- tests/OFHTTPClientTests.m +++ tests/OFHTTPClientTests.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: tests/OFHTTPCookieManagerTests.m ================================================================== --- tests/OFHTTPCookieManagerTests.m +++ tests/OFHTTPCookieManagerTests.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: tests/OFHTTPCookieTests.m ================================================================== --- tests/OFHTTPCookieTests.m +++ tests/OFHTTPCookieTests.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: tests/OFINIFileTests.m ================================================================== --- tests/OFINIFileTests.m +++ tests/OFINIFileTests.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -41,22 +41,24 @@ @"bool=false\r\n" @"float=0.25\r\n" @"array1=foo\r\n" @"array1=bar\r\n" @"double=0.75\r\n"; + OFURL *URL; OFINIFile *file; OFINICategory *tests, *foobar, *types; OFArray *array; -#ifndef OF_NINTENDO_DS - OFString *writePath; +#if defined(OF_HAVE_FILES) && !defined(OF_NINTENDO_DS) + OFURL *writeURL; #endif module = @"OFINIFile"; - TEST(@"+[fileWithPath:encoding:]", - (file = [OFINIFile fileWithPath: @"testfile.ini" - encoding: OFStringEncodingCodepage437])) + URL = [OFURL URLWithString: @"objfw-embedded:///testfile.ini"]; + TEST(@"+[fileWithURL:encoding:]", + (file = [OFINIFile fileWithURL: URL + encoding: OFStringEncodingCodepage437])) tests = [file categoryForName: @"tests"]; foobar = [file categoryForName: @"foobar"]; types = [file categoryForName: @"types"]; TEST(@"-[categoryForName:]", @@ -111,22 +113,23 @@ 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"]; +#if defined(OF_HAVE_FILES) && !defined(OF_NINTENDO_DS) + writeURL = [[OFSystemInfo temporaryDirectoryURL] + URLByAppendingPathComponent: @"objfw-tests.ini" + isDirectory: false]; TEST(@"-[writeToFile:encoding:]", - R([file writeToFile: writePath - encoding: OFStringEncodingCodepage437]) && - [[OFString stringWithContentsOfFile: writePath - encoding: OFStringEncodingCodepage437] + R([file writeToURL: writeURL + encoding: OFStringEncodingCodepage437]) && + [[OFString stringWithContentsOfURL: writeURL + encoding: OFStringEncodingCodepage437] isEqual: output]) - [[OFFileManager defaultManager] removeItemAtPath: writePath]; + [[OFFileManager defaultManager] removeItemAtURL: writeURL]; #else (void)output; #endif objc_autoreleasePoolPop(pool); } @end Index: tests/OFIPXSocketTests.m ================================================================== --- tests/OFIPXSocketTests.m +++ tests/OFIPXSocketTests.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: tests/OFInvocationTests.m ================================================================== --- tests/OFInvocationTests.m +++ tests/OFInvocationTests.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: tests/OFJSONTests.m ================================================================== --- tests/OFJSONTests.m +++ tests/OFJSONTests.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: tests/OFKernelEventObserverTests.m ================================================================== --- tests/OFKernelEventObserverTests.m +++ tests/OFKernelEventObserverTests.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: tests/OFListTests.m ================================================================== --- tests/OFListTests.m +++ tests/OFListTests.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: tests/OFLocaleTests.m ================================================================== --- tests/OFLocaleTests.m +++ tests/OFLocaleTests.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: tests/OFMD5HashTests.m ================================================================== --- tests/OFMD5HashTests.m +++ tests/OFMD5HashTests.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -27,11 +27,13 @@ @implementation TestsAppDelegate (OFMD5HashTests) - (void)MD5HashTests { void *pool = objc_autoreleasePoolPush(); OFMD5Hash *MD5, *MD5Copy; - OFFile *file = [OFFile fileWithPath: @"testfile.bin" mode: @"r"]; + OFURL *URL = [OFURL URLWithString: @"objfw-embedded:///testfile.bin"]; + OFStream *file = [[OFURLHandler handlerForURL: URL] + openItemAtURL: URL mode: @"r"]; TEST(@"+[hashWithAllowsSwappableMemory:]", (MD5 = [OFMD5Hash hashWithAllowsSwappableMemory: true])) while (!file.atEndOfStream) { @@ -40,10 +42,12 @@ [MD5 updateWithBuffer: buffer length: length]; } [file close]; TEST(@"-[copy]", (MD5Copy = [[MD5 copy] autorelease])) + + TEST(@"-[calculate]", R([MD5 calculate]) && R([MD5Copy calculate])) TEST(@"-[digest]", memcmp(MD5.digest, testFileMD5, 16) == 0 && memcmp(MD5Copy.digest, testFileMD5, 16) == 0) ADDED tests/OFMemoryStreamTests.m Index: tests/OFMemoryStreamTests.m ================================================================== --- tests/OFMemoryStreamTests.m +++ tests/OFMemoryStreamTests.m @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2008-2022 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#include "config.h" + +#import "TestsAppDelegate.h" + +static OFString *const module = @"OFMemoryStream"; +static const char string[] = "abcdefghijkl"; + +@implementation TestsAppDelegate (OFMemoryStreamTests) +- (void)memoryStreamTests +{ + void *pool = objc_autoreleasePoolPush(); + OFMemoryStream *stream; + char buffer[10]; + OFMutableData *data; + + TEST(@"+[streamWithMemoryAddress:size:writable:]", + (stream = [OFMemoryStream streamWithMemoryAddress: (char *)string + size: sizeof(string) + writable: false])); + + /* + * Test the lowlevel methods, as otherwise OFStream will do one big + * read and we will not test OFMemoryStream. + */ + + TEST(@"-[lowlevelReadIntoBuffer:length:]", + [stream lowlevelReadIntoBuffer: buffer length: 5] == 5 && + memcmp(buffer, "abcde", 5) == 0 && + [stream lowlevelReadIntoBuffer: buffer length: 3] == 3 && + memcmp(buffer, "fgh", 3) == 0 && + [stream lowlevelReadIntoBuffer: buffer length: 10] == 5 && + memcmp(buffer, "ijkl", 5) == 0) + + TEST(@"-[lowlevelIsAtEndOfStream]", [stream lowlevelIsAtEndOfStream]) + + TEST(@"-[lowlevelSeekToOffset:whence:]", + [stream lowlevelSeekToOffset: 0 whence: SEEK_CUR] == + sizeof(string) && [stream lowlevelIsAtEndOfStream] && + [stream lowlevelSeekToOffset: 4 whence: SEEK_SET] == 4 && + ![stream lowlevelIsAtEndOfStream] && + [stream lowlevelReadIntoBuffer: buffer length: 10] == 9 && + memcmp(buffer, "efghijkl", 9) == 0 && + [stream lowlevelSeekToOffset: -2 whence: SEEK_END] == 11 && + [stream lowlevelReadIntoBuffer: buffer length: 10] == 2 && + memcmp(buffer, "l", 2) == 0 && + [stream lowlevelReadIntoBuffer: buffer length: 10] == 0) + + EXPECT_EXCEPTION(@"Writes rejected on read-only stream", + OFWriteFailedException, [stream lowlevelWriteBuffer: "" length: 1]) + + data = [OFMutableData dataWithCapacity: 13]; + [data increaseCountBy: 13]; + stream = [OFMemoryStream streamWithMemoryAddress: data.mutableItems + size: data.count + writable: true]; + TEST(@"-[lowlevelWriteBuffer:length:]", + [stream lowlevelWriteBuffer: "abcde" length: 5] == 5 && + [stream lowlevelWriteBuffer: "fgh" length: 3] == 3 && + [stream lowlevelWriteBuffer: "ijkl" length: 5] == 5 && + memcmp(data.items, string, data.count) == 0 && + [stream lowlevelSeekToOffset: -3 whence: SEEK_END] == 10) + + EXPECT_EXCEPTION(@"Out of bound writes rejected", + OFWriteFailedException, + [stream lowlevelWriteBuffer: "xyz" length: 4]) + + TEST(@"Partial write for too long write", + memcmp(data.items, "abcdefghijxyz", 13) == 0) + + objc_autoreleasePoolPop(pool); +} +@end Index: tests/OFMethodSignatureTests.m ================================================================== --- tests/OFMethodSignatureTests.m +++ tests/OFMethodSignatureTests.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in ADDED tests/OFNotificationCenterTests.m Index: tests/OFNotificationCenterTests.m ================================================================== --- tests/OFNotificationCenterTests.m +++ tests/OFNotificationCenterTests.m @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2008-2022 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#include "config.h" + +#import "TestsAppDelegate.h" + +static OFString *const module = @"OFNotificationCenter"; +static const OFNotificationName notificationName = + @"OFNotificationCenterTestName"; +static const OFNotificationName otherNotificationName = + @"OFNotificationCenterTestOtherName"; + +@interface OFNotificationCenterTest: OFObject +{ +@public + id _expectedObject; + int _received; +} + +- (void)handleNotification: (OFNotification *)notification; +@end + +@implementation OFNotificationCenterTest +- (void)handleNotification: (OFNotification *)notification +{ + OFEnsure([notification.name isEqual: notificationName]); + OFEnsure(_expectedObject == nil || + notification.object == _expectedObject); + + _received++; +} +@end + +@implementation TestsAppDelegate (OFNotificationCenterTests) +- (void)notificationCenterTests +{ + void *pool = objc_autoreleasePoolPush(); + OFNotificationCenter *center = [OFNotificationCenter defaultCenter]; + OFNotificationCenterTest *test1, *test2, *test3, *test4; + OFNotification *notification; + + test1 = + [[[OFNotificationCenterTest alloc] init] autorelease]; + test1->_expectedObject = self; + test2 = + [[[OFNotificationCenterTest alloc] init] autorelease]; + test3 = + [[[OFNotificationCenterTest alloc] init] autorelease]; + test3->_expectedObject = self; + test4 = + [[[OFNotificationCenterTest alloc] init] autorelease]; + + /* First one intentionally added twice to test deduplication. */ + TEST(@"-[addObserver:selector:name:object:]", + R([center addObserver: test1 + selector: @selector(handleNotification:) + name: notificationName + object: self]) && + R([center addObserver: test1 + selector: @selector(handleNotification:) + name: notificationName + object: self]) && + R([center addObserver: test2 + selector: @selector(handleNotification:) + name: notificationName + object: nil]) && + R([center addObserver: test3 + selector: @selector(handleNotification:) + name: otherNotificationName + object: self]) && + R([center addObserver: test4 + selector: @selector(handleNotification:) + name: otherNotificationName + object: nil])) + + notification = [OFNotification notificationWithName: notificationName + object: nil]; + TEST(@"-[postNotification:] #1", + R([center postNotification: notification]) && + test1->_received == 0 && test2->_received == 1 && + test3->_received == 0 && test4->_received == 0) + + notification = [OFNotification notificationWithName: notificationName + object: self]; + TEST(@"-[postNotification:] #2", + R([center postNotification: notification]) && + test1->_received == 1 && test2->_received == 2 && + test3->_received == 0 && test4->_received == 0) + + notification = [OFNotification notificationWithName: notificationName + object: @"foo"]; + TEST(@"-[postNotification:] #3", + R([center postNotification: notification]) && + test1->_received == 1 && test2->_received == 3 && + test3->_received == 0 && test4->_received == 0) + +#ifdef OF_HAVE_BLOCKS + __block bool received = false; + OFNotificationCenterHandle *handle; + + notification = [OFNotification notificationWithName: notificationName + object: self]; + TEST(@"-[addObserverForName:object:usingBlock:]", + (handle = [center addObserverForName: notificationName + object: self + usingBlock: ^ (OFNotification *notif) { + OFEnsure(notif == notification && !received); + received = true; + }]) && R([center postNotification: notification]) && received && + test1->_received == 2 && test2->_received == 4 && + test3->_received == 0 && test4->_received == 0) + + /* Act like the block test didn't happen. */ + [center removeObserver: handle]; + test1->_received--; + test2->_received--; +#endif + + TEST(@"-[removeObserver:selector:name:object:]", + R([center removeObserver: test1 + selector: @selector(handleNotification:) + name: notificationName + object: self]) && + R([center removeObserver: test2 + selector: @selector(handleNotification:) + name: notificationName + object: nil]) && + R([center removeObserver: test3 + selector: @selector(handleNotification:) + name: otherNotificationName + object: self]) && + R([center removeObserver: test4 + selector: @selector(handleNotification:) + name: otherNotificationName + object: nil])) + + notification = [OFNotification notificationWithName: notificationName + object: self]; + TEST(@"-[postNotification:] with no observers", + R([center postNotification: notification]) && + test1->_received == 1 && test2->_received == 3 && + test3->_received == 0 && test4->_received == 0) + + objc_autoreleasePoolPop(pool); +} +@end Index: tests/OFNumberTests.m ================================================================== --- tests/OFNumberTests.m +++ tests/OFNumberTests.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: tests/OFObjectTests.m ================================================================== --- tests/OFObjectTests.m +++ tests/OFObjectTests.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: tests/OFPBKDF2Tests.m ================================================================== --- tests/OFPBKDF2Tests.m +++ tests/OFPBKDF2Tests.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: tests/OFPluginTests.m ================================================================== --- tests/OFPluginTests.m +++ tests/OFPluginTests.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -18,26 +18,39 @@ #import "TestsAppDelegate.h" #import "plugin/TestPlugin.h" #ifndef OF_IOS -static OFString *const pluginPath = @"plugin/TestPlugin"; +static OFString *const pluginName = @"plugin/TestPlugin"; #else -static OFString *const pluginPath = @"PlugIns/TestPlugin"; +static OFString *const pluginName = @"PlugIns/TestPlugin"; #endif static OFString *const module = @"OFPlugin"; @implementation TestsAppDelegate (OFPluginTests) - (void)pluginTests { void *pool = objc_autoreleasePoolPush(); - TestPlugin *plugin; + OFString *path; + OFPlugin *plugin; + Class (*class)(void); + TestPlugin *test; + + TEST(@"+[pathForName:]", (path = [OFPlugin pathForName: pluginName])) + + TEST(@"+[pluginWithPath:]", (plugin = [OFPlugin pluginWithPath: path])) - TEST(@"+[pluginWithPath:]", - (plugin = [OFPlugin pluginWithPath: pluginPath])) + TEST(@"-[addressForSymbol:]", + (class = (Class (*)(void))(uintptr_t) + [plugin addressForSymbol: @"class"])) - TEST(@"TestPlugin's -[test:]", [plugin test: 1234] == 2468) + test = [[class() alloc] init]; + @try { + TEST(@"TestPlugin's -[test:]", [test test: 1234] == 2468) + } @finally { + [test release]; + } objc_autoreleasePoolPop(pool); } @end Index: tests/OFPropertyListTests.m ================================================================== --- tests/OFPropertyListTests.m +++ tests/OFPropertyListTests.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: tests/OFRIPEMD160HashTests.m ================================================================== --- tests/OFRIPEMD160HashTests.m +++ tests/OFRIPEMD160HashTests.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -28,11 +28,13 @@ @implementation TestsAppDelegate (OFRIPEMD160HashTests) - (void)RIPEMD160HashTests { void *pool = objc_autoreleasePoolPush(); OFRIPEMD160Hash *RIPEMD160, *RIPEMD160Copy; - OFFile *file = [OFFile fileWithPath: @"testfile.bin" mode: @"r"]; + OFURL *URL = [OFURL URLWithString: @"objfw-embedded:///testfile.bin"]; + OFStream *file = [[OFURLHandler handlerForURL: URL] + openItemAtURL: URL mode: @"r"]; TEST(@"+[hashWithAllowsSwappableMemory:]", (RIPEMD160 = [OFRIPEMD160Hash hashWithAllowsSwappableMemory: true])) while (!file.atEndOfStream) { @@ -42,10 +44,13 @@ } [file close]; TEST(@"-[copy]", (RIPEMD160Copy = [[RIPEMD160 copy] autorelease])) + TEST(@"-[calculate]", + R([RIPEMD160 calculate]) && R([RIPEMD160Copy calculate])) + TEST(@"-[digest]", memcmp(RIPEMD160.digest, testFileRIPEMD160, 20) == 0 && memcmp(RIPEMD160Copy.digest, testFileRIPEMD160, 20) == 0) EXPECT_EXCEPTION(@"Detect invalid call of " Index: tests/OFSHA1HashTests.m ================================================================== --- tests/OFSHA1HashTests.m +++ tests/OFSHA1HashTests.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -28,11 +28,13 @@ @implementation TestsAppDelegate (SHA1HashTests) - (void)SHA1HashTests { void *pool = objc_autoreleasePoolPush(); OFSHA1Hash *SHA1, *SHA1Copy; - OFFile *file = [OFFile fileWithPath: @"testfile.bin" mode: @"r"]; + OFURL *URL = [OFURL URLWithString: @"objfw-embedded:///testfile.bin"]; + OFStream *file = [[OFURLHandler handlerForURL: URL] + openItemAtURL: URL mode: @"r"]; TEST(@"+[hashWithAllowsSwappableMemory:]", (SHA1 = [OFSHA1Hash hashWithAllowsSwappableMemory: true])) while (!file.atEndOfStream) { @@ -41,10 +43,12 @@ [SHA1 updateWithBuffer: buffer length: length]; } [file close]; TEST(@"-[copy]", (SHA1Copy = [[SHA1 copy] autorelease])) + + TEST(@"-[calculate]", R([SHA1 calculate]) && R([SHA1Copy calculate])) TEST(@"-[digest]", memcmp(SHA1.digest, testFileSHA1, 20) == 0 && memcmp(SHA1Copy.digest, testFileSHA1, 20) == 0) Index: tests/OFSHA224HashTests.m ================================================================== --- tests/OFSHA224HashTests.m +++ tests/OFSHA224HashTests.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -28,11 +28,13 @@ @implementation TestsAppDelegate (SHA224HashTests) - (void)SHA224HashTests { void *pool = objc_autoreleasePoolPush(); OFSHA224Hash *SHA224, *SHA224Copy; - OFFile *file = [OFFile fileWithPath: @"testfile.bin" mode: @"r"]; + OFURL *URL = [OFURL URLWithString: @"objfw-embedded:///testfile.bin"]; + OFStream *file = [[OFURLHandler handlerForURL: URL] + openItemAtURL: URL mode: @"r"]; TEST(@"+[hashWithAllowsSwappableMemory:]", (SHA224 = [OFSHA224Hash hashWithAllowsSwappableMemory: true])) while (!file.atEndOfStream) { @@ -42,10 +44,13 @@ } [file close]; TEST(@"-[copy]", (SHA224Copy = [[SHA224 copy] autorelease])) + TEST(@"-[calculate]", + R([SHA224 calculate]) && R([SHA224Copy calculate])) + TEST(@"-[digest]", memcmp(SHA224.digest, testFileSHA224, 28) == 0 && memcmp(SHA224Copy.digest, testFileSHA224, 28) == 0) EXPECT_EXCEPTION(@"Detect invalid call of " Index: tests/OFSHA256HashTests.m ================================================================== --- tests/OFSHA256HashTests.m +++ tests/OFSHA256HashTests.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -28,11 +28,13 @@ @implementation TestsAppDelegate (SHA256HashTests) - (void)SHA256HashTests { void *pool = objc_autoreleasePoolPush(); OFSHA256Hash *SHA256, *SHA256Copy; - OFFile *file = [OFFile fileWithPath: @"testfile.bin" mode: @"r"]; + OFURL *URL = [OFURL URLWithString: @"objfw-embedded:///testfile.bin"]; + OFStream *file = [[OFURLHandler handlerForURL: URL] + openItemAtURL: URL mode: @"r"]; TEST(@"+[hashWithAllowsSwappableMemory:]", (SHA256 = [OFSHA256Hash hashWithAllowsSwappableMemory: true])) while (!file.atEndOfStream) { @@ -42,10 +44,13 @@ } [file close]; TEST(@"-[copy]", (SHA256Copy = [[SHA256 copy] autorelease])) + TEST(@"-[calculate]", + R([SHA256 calculate]) && R([SHA256Copy calculate])) + TEST(@"-[digest]", memcmp(SHA256.digest, testFileSHA256, 32) == 0 && memcmp(SHA256Copy.digest, testFileSHA256, 32) == 0) EXPECT_EXCEPTION(@"Detect invalid call of " Index: tests/OFSHA384HashTests.m ================================================================== --- tests/OFSHA384HashTests.m +++ tests/OFSHA384HashTests.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -29,11 +29,13 @@ @implementation TestsAppDelegate (SHA384HashTests) - (void)SHA384HashTests { void *pool = objc_autoreleasePoolPush(); OFSHA384Hash *SHA384, *SHA384Copy; - OFFile *file = [OFFile fileWithPath: @"testfile.bin" mode: @"r"]; + OFURL *URL = [OFURL URLWithString: @"objfw-embedded:///testfile.bin"]; + OFStream *file = [[OFURLHandler handlerForURL: URL] + openItemAtURL: URL mode: @"r"]; TEST(@"+[hashWithAllowsSwappableMemory:]", (SHA384 = [OFSHA384Hash hashWithAllowsSwappableMemory: true])) while (!file.atEndOfStream) { @@ -43,10 +45,13 @@ } [file close]; TEST(@"-[copy]", (SHA384Copy = [[SHA384 copy] autorelease])) + TEST(@"-[calculate]", + R([SHA384 calculate]) && R([SHA384Copy calculate])) + TEST(@"-[digest]", memcmp(SHA384.digest, testFileSHA384, 48) == 0 && memcmp(SHA384Copy.digest, testFileSHA384, 48) == 0) EXPECT_EXCEPTION(@"Detect invalid call of " Index: tests/OFSHA512HashTests.m ================================================================== --- tests/OFSHA512HashTests.m +++ tests/OFSHA512HashTests.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -30,11 +30,13 @@ @implementation TestsAppDelegate (SHA512HashTests) - (void)SHA512HashTests { void *pool = objc_autoreleasePoolPush(); OFSHA512Hash *SHA512, *SHA512Copy; - OFFile *file = [OFFile fileWithPath: @"testfile.bin" mode: @"r"]; + OFURL *URL = [OFURL URLWithString: @"objfw-embedded:///testfile.bin"]; + OFStream *file = [[OFURLHandler handlerForURL: URL] + openItemAtURL: URL mode: @"r"]; TEST(@"+[hashWithAllowsSwappableMemory:]", (SHA512 = [OFSHA512Hash hashWithAllowsSwappableMemory: true])) while (!file.atEndOfStream) { @@ -44,10 +46,13 @@ } [file close]; TEST(@"-[copy]", (SHA512Copy = [[SHA512 copy] autorelease])) + TEST(@"-[calculate]", + R([SHA512 calculate]) && R([SHA512Copy calculate])) + TEST(@"-[digest]", memcmp(SHA512.digest, testFileSHA512, 64) == 0 && memcmp(SHA512Copy.digest, testFileSHA512, 64) == 0) EXPECT_EXCEPTION(@"Detect invalid call of " Index: tests/OFSPXSocketTests.m ================================================================== --- tests/OFSPXSocketTests.m +++ tests/OFSPXSocketTests.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -48,22 +48,22 @@ [[OFRunLoop mainRunLoop] stop]; return false; } -- (void)socket: (OFSPXSocket *)sock - didConnectToNode: (unsigned char [IPX_NODE_LEN])node - network: (uint32_t)network - port: (uint16_t)port - exception: (id)exception +- (void)socket: (OFSPXSocket *)sock + didConnectToNetwork: (uint32_t)network + node: (unsigned char [IPX_NODE_LEN])node + port: (uint16_t)port + exception: (id)exception { OFEnsure(!_connected); _connected = (sock == _expectedClientSocket && + network == _expectedNetwork && memcmp(node, _expectedNode, IPX_NODE_LEN) == 0 && - network == _expectedNetwork && port == _expectedPort && - exception == nil); + port == _expectedPort && exception == nil); if (_accepted && _connected) [[OFRunLoop mainRunLoop] stop]; } @end @@ -70,15 +70,15 @@ @implementation TestsAppDelegate (OFSPXSocketTests) - (void)SPXSocketTests { void *pool = objc_autoreleasePoolPush(); - OFSPXSocket *sockClient, *sockServer, *sockAccepted;; + OFSPXSocket *sockClient, *sockServer = nil, *sockAccepted; OFSocketAddress address1; const OFSocketAddress *address2; - unsigned char node[IPX_NODE_LEN], node2[IPX_NODE_LEN]; uint32_t network; + unsigned char node[IPX_NODE_LEN], node2[IPX_NODE_LEN]; uint16_t port; char buffer[5]; SPXSocketDelegate *delegate; TEST(@"+[socket]", (sockClient = [OFSPXSocket socket]) && @@ -113,18 +113,18 @@ objc_autoreleasePoolPop(pool); return; } - OFSocketAddressIPXNode(&address1, node); network = OFSocketAddressIPXNetwork(&address1); + OFSocketAddressIPXNode(&address1, node); port = OFSocketAddressPort(&address1); TEST(@"-[listen]", R([sockServer listen])) - TEST(@"-[connectToNode:network:port:]", - R([sockClient connectToNode: node network: network port: port])) + TEST(@"-[connectToNetwork:node:port:]", + R([sockClient connectToNetwork: network node: node port: port])) TEST(@"-[accept]", (sockAccepted = [sockServer accept])) TEST(@"-[sendBuffer:length:]", R([sockAccepted sendBuffer: "Hello" length: 5])) @@ -133,13 +133,13 @@ [sockClient receiveIntoBuffer: buffer length: 5] == 5 && memcmp(buffer, "Hello", 5) == 0) TEST(@"-[remoteAddress]", (address2 = sockAccepted.remoteAddress) && + OFSocketAddressIPXNetwork(address2) == network && R(OFSocketAddressIPXNode(address2, node2)) && - memcmp(node, node2, IPX_NODE_LEN) == 0 && - OFSocketAddressIPXNetwork(address2) == network) + memcmp(node, node2, IPX_NODE_LEN) == 0) delegate = [[[SPXSocketDelegate alloc] init] autorelease]; sockServer = [OFSPXSocket socket]; delegate->_expectedServerSocket = sockServer; @@ -151,33 +151,33 @@ address1 = [sockServer bindToPort: 0]; [sockServer listen]; [sockServer asyncAccept]; + delegate->_expectedNetwork = network = + OFSocketAddressIPXNetwork(&address1); OFSocketAddressIPXNode(&address1, node); memcpy(delegate->_expectedNode, node, IPX_NODE_LEN); - delegate->_expectedNetwork = network = - OFSocketAddressIPXNetwork(&address1); delegate->_expectedPort = port = OFSocketAddressPort(&address1); @try { - [sockClient asyncConnectToNode: node - network: network - port: port]; + [sockClient asyncConnectToNetwork: network + node: node + port: port]; [[OFRunLoop mainRunLoop] runUntilDate: [OFDate dateWithTimeIntervalSinceNow: 2]]; - TEST(@"-[asyncAccept] & -[asyncConnectToNode:network:port:]", + TEST(@"-[asyncAccept] & -[asyncConnectToNetwork:node:port:]", delegate->_accepted && delegate->_connected) } @catch (OFObserveFailedException *e) { switch (e.errNo) { case ENOTSOCK: [OFStdOut setForegroundColor: [OFColor lime]]; [OFStdOut writeLine: @"\r[OFSPXSocket] -[asyncAccept] & " - @"-[asyncConnectToNode:network:port:]: select() " + @"-[asyncConnectToNetwork:node:port:]: select() " @"not supported for SPX, skipping test"]; break; default: @throw e; } Index: tests/OFSPXStreamSocketTests.m ================================================================== --- tests/OFSPXStreamSocketTests.m +++ tests/OFSPXStreamSocketTests.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -24,12 +24,12 @@ @interface SPXStreamSocketDelegate: OFObject { @public OFStreamSocket *_expectedServerSocket; OFSPXStreamSocket *_expectedClientSocket; - unsigned char _expectedNode[IPX_NODE_LEN]; uint32_t _expectedNetwork; + unsigned char _expectedNode[IPX_NODE_LEN]; uint16_t _expectedPort; bool _accepted; bool _connected; } @end @@ -48,22 +48,22 @@ [[OFRunLoop mainRunLoop] stop]; return false; } -- (void)socket: (OFSPXStreamSocket *)sock - didConnectToNode: (unsigned char [IPX_NODE_LEN])node - network: (uint32_t)network - port: (uint16_t)port - exception: (id)exception +- (void)socket: (OFSPXStreamSocket *)sock + didConnectToNetwork: (uint32_t)network + node: (unsigned char [IPX_NODE_LEN])node + port: (uint16_t)port + exception: (id)exception { OFEnsure(!_connected); _connected = (sock == _expectedClientSocket && + network == _expectedNetwork && memcmp(node, _expectedNode, IPX_NODE_LEN) == 0 && - network == _expectedNetwork && port == _expectedPort && - exception == nil); + port == _expectedPort && exception == nil); if (_accepted && _connected) [[OFRunLoop mainRunLoop] stop]; } @end @@ -70,15 +70,15 @@ @implementation TestsAppDelegate (OFSPXStreamSocketTests) - (void)SPXStreamSocketTests { void *pool = objc_autoreleasePoolPush(); - OFSPXStreamSocket *sockClient, *sockServer, *sockAccepted;; + OFSPXStreamSocket *sockClient, *sockServer = nil, *sockAccepted; OFSocketAddress address1; const OFSocketAddress *address2; - unsigned char node[IPX_NODE_LEN], node2[IPX_NODE_LEN]; uint32_t network; + unsigned char node[IPX_NODE_LEN], node2[IPX_NODE_LEN]; uint16_t port; char buffer[5]; SPXStreamSocketDelegate *delegate; TEST(@"+[socket]", (sockClient = [OFSPXStreamSocket socket]) && @@ -113,18 +113,18 @@ objc_autoreleasePoolPop(pool); return; } - OFSocketAddressIPXNode(&address1, node); network = OFSocketAddressIPXNetwork(&address1); + OFSocketAddressIPXNode(&address1, node); port = OFSocketAddressPort(&address1); TEST(@"-[listen]", R([sockServer listen])) - TEST(@"-[connectToNode:network:port:]", - R([sockClient connectToNode: node network: network port: port])) + TEST(@"-[connectToNetwork:node:port:]", + R([sockClient connectToNetwork: network node: node port: port])) TEST(@"-[accept]", (sockAccepted = [sockServer accept])) /* Test reassembly (this would not work with OFSPXSocket) */ TEST(@"-[writeBuffer:length:]", @@ -136,13 +136,13 @@ [sockClient readIntoBuffer: buffer length: 3] == 3 && memcmp(buffer, "llo", 3) == 0) TEST(@"-[remoteAddress]", (address2 = sockAccepted.remoteAddress) && + OFSocketAddressIPXNetwork(address2) == network && R(OFSocketAddressIPXNode(address2, node2)) && - memcmp(node, node2, IPX_NODE_LEN) == 0 && - OFSocketAddressIPXNetwork(address2) == network) + memcmp(node, node2, IPX_NODE_LEN) == 0) delegate = [[[SPXStreamSocketDelegate alloc] init] autorelease]; sockServer = [OFSPXStreamSocket socket]; delegate->_expectedServerSocket = sockServer; @@ -154,33 +154,33 @@ address1 = [sockServer bindToPort: 0]; [sockServer listen]; [sockServer asyncAccept]; + delegate->_expectedNetwork = network = + OFSocketAddressIPXNetwork(&address1); OFSocketAddressIPXNode(&address1, node); memcpy(delegate->_expectedNode, node, IPX_NODE_LEN); - delegate->_expectedNetwork = network = - OFSocketAddressIPXNetwork(&address1); delegate->_expectedPort = port = OFSocketAddressPort(&address1); @try { - [sockClient asyncConnectToNode: node - network: network - port: port]; + [sockClient asyncConnectToNetwork: network + node: node + port: port]; [[OFRunLoop mainRunLoop] runUntilDate: [OFDate dateWithTimeIntervalSinceNow: 2]]; - TEST(@"-[asyncAccept] & -[asyncConnectToNode:network:port:]", + TEST(@"-[asyncAccept] & -[asyncConnectToNetwork:node:port:]", delegate->_accepted && delegate->_connected) } @catch (OFObserveFailedException *e) { switch (e.errNo) { case ENOTSOCK: [OFStdOut setForegroundColor: [OFColor lime]]; [OFStdOut writeLine: @"\r[OFSPXStreamSocket] -[asyncAccept] & " - @"-[asyncConnectToNode:network:port:]: select() " + @"-[asyncConnectToNetwork:node:port:]: select() " @"not supported for SPX, skipping test"]; break; default: @throw e; } Index: tests/OFScryptTests.m ================================================================== --- tests/OFScryptTests.m +++ tests/OFScryptTests.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -108,18 +108,21 @@ 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. */ +#ifndef OF_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, @@ -179,10 +182,12 @@ .key = output, .keyLength = 64, .allowsSwappableMemory = true })) && memcmp(output, testVector2, 64) == 0) + /* The third test vector is too expensive for m68k. */ +#ifndef OF_M68K TEST(@"scrypt test vector #3", R(OFScrypt((OFScryptParameters){ .blockSize = 8, .costFactor = 16384, .parallelization = 1, @@ -192,10 +197,11 @@ .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){ Index: tests/OFSerializationTests.m ================================================================== --- tests/OFSerializationTests.m +++ tests/OFSerializationTests.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -26,10 +26,11 @@ 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"]]; @@ -52,15 +53,20 @@ data = [OFData dataWithItems: "0123456789:; + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: tests/OFSocketTests.m ================================================================== --- tests/OFSocketTests.m +++ tests/OFSocketTests.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: tests/OFStreamTests.m ================================================================== --- tests/OFStreamTests.m +++ tests/OFStreamTests.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: tests/OFStringTests.m ================================================================== --- tests/OFStringTests.m +++ tests/OFStringTests.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -562,11 +562,12 @@ !C(@"foo").absolutePath && !C(@"b:foo").absolutePath) # elif defined(OF_AMIGAOS) TEST(@"-[isAbsolutePath]", C(@"dh0:foo").absolutePath && C(@"dh0:a/b").absolutePath && !C(@"foo/bar").absolutePath && !C(@"foo").absolutePath) -# elif defined(OF_NINTENDO_3DS) || defined(OF_WII) +# elif defined(OF_NINTENDO_3DS) || defined(OF_WII) || \ + defined(OF_NINTENDO_SWITCH) TEST(@"-[isAbsolutePath]", C(@"sdmc:/foo").absolutePath && !C(@"sdmc:foo").absolutePath && !C(@"foo/bar").absolutePath && !C(@"foo").absolutePath) # else TEST(@"-[isAbsolutePath]", @@ -592,10 +593,28 @@ TEST(@"-[stringByAppendingPathComponent:]", [[mutableString1 stringByAppendingPathComponent: @"baz"] isEqual: mutableString2] && [[string stringByAppendingPathComponent: @"baz"] isEqual: mutableString2]) + +# if defined(OF_WINDOWS) || defined(OF_MSDOS) + TEST(@"-[stringByAppendingPathExtension:]", + [[C(@"foo") stringByAppendingPathExtension: @"bar"] + isEqual: @"foo.bar"] && + [[C(@"c:\\tmp\\foo") stringByAppendingPathExtension: @"bar"] + isEqual: @"c:\\tmp\\foo.bar"] && + [[C(@"c:\\tmp\\/\\") stringByAppendingPathExtension: @"bar"] + isEqual: @"c:\\tmp.bar"]) +# else + TEST(@"-[stringByAppendingPathExtension:]", + [[C(@"foo") stringByAppendingPathExtension: @"bar"] + isEqual: @"foo.bar"] && + [[C(@"foo/bar") stringByAppendingPathExtension: @"baz"] + isEqual: @"foo/bar.baz"] && + [[C(@"foo///") stringByAppendingPathExtension: @"bar"] + isEqual: @"foo.bar"]) +# endif #endif TEST(@"-[hasPrefix:]", [C(@"foobar") hasPrefix: @"foo"] && ![C(@"foobar") hasPrefix: @"foobar0"]) @@ -728,11 +747,12 @@ [[stringClass pathWithComponents: [OFArray arrayWithObjects: @"foo/", @"bar", @"", @"baz", @"/", nil]] isEqual: @"foo//bar/baz//"] && [[stringClass pathWithComponents: [OFArray arrayWithObjects: @"foo", nil]] isEqual: @"foo"]) -# elif defined(OF_NINTENDO_3DS) || defined(OF_WII) +# elif defined(OF_NINTENDO_3DS) || defined(OF_WII) || \ + defined(OF_NINTENDO_SWITCH) TEST(@"+[pathWithComponents:]", [[stringClass pathWithComponents: [OFArray arrayWithObjects: @"foo", @"bar", @"baz", nil]] isEqual: @"foo/bar/baz"] && [[stringClass pathWithComponents: [OFArray arrayWithObjects: @"sdmc:", @"foo", @"bar", @"baz", nil]] @@ -852,11 +872,12 @@ /* 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) +# elif defined(OF_NINTENDO_3DS) || defined(OF_WII) || \ + defined(OF_NINTENDO_SWITCH) TEST(@"-[pathComponents]", /* sdmc:/tmp */ (array = C(@"sdmc:/tmp").pathComponents) && array.count == 2 && [[array objectAtIndex: 0] isEqual: @"sdmc:"] && [[array objectAtIndex: 1] isEqual: @"tmp"] && @@ -933,11 +954,12 @@ [C(@"dh0:/").lastPathComponent isEqual: @"/"] && [C(@"dh0:").lastPathComponent isEqual: @"dh0:"] && [C(@"foo").lastPathComponent isEqual: @"foo"] && [C(@"foo/bar").lastPathComponent isEqual: @"bar"] && [C(@"foo/bar/baz/").lastPathComponent isEqual: @"baz"]) -# elif defined(OF_NINTENDO_3DS) || defined(OF_WII) +# elif defined(OF_NINTENDO_3DS) || defined(OF_WII) || \ + defined(OF_NINTENDO_SWITCH) TEST(@"-[lastPathComponent]", [C(@"sdmc:/tmp").lastPathComponent isEqual: @"tmp"] && [C(@"sdmc:/tmp/").lastPathComponent isEqual: @"tmp"] && [C(@"sdmc:/").lastPathComponent isEqual: @"sdmc:/"] && [C(@"sdmc:").lastPathComponent isEqual: @"sdmc:"] && @@ -999,11 +1021,12 @@ [C(@"dh0:/").stringByDeletingLastPathComponent isEqual: @"dh0:"] && [C(@"dh0:tmp/foo/").stringByDeletingLastPathComponent isEqual: @"dh0:tmp"] && [C(@"foo/bar").stringByDeletingLastPathComponent isEqual: @"foo"] && [C(@"foo").stringByDeletingLastPathComponent isEqual: @""]) -# elif defined(OF_NINTENDO_3DS) || defined(OF_WII) +# elif defined(OF_NINTENDO_3DS) || defined(OF_WII) || \ + defined(OF_NINTENDO_SWITCH) TEST(@"-[stringByDeletingLastPathComponent]", [C(@"/tmp/").stringByDeletingLastPathComponent isEqual: @""] && [C(@"sdmc:/tmp/foo/").stringByDeletingLastPathComponent isEqual: @"sdmc:/tmp"] && [C(@"sdmc:/").stringByDeletingLastPathComponent @@ -1046,11 +1069,12 @@ [C(@"foo.bar/").stringByDeletingPathExtension isEqual: @"foo"] && [C(@".foo").stringByDeletingPathExtension isEqual: @".foo"] && [C(@".foo\\bar").stringByDeletingPathExtension isEqual: @".foo\\bar"] && [C(@".foo.bar").stringByDeletingPathExtension isEqual: @".foo"]) -# elif defined(OF_NINTENDO_3DS) || defined(OF_WII) +# elif defined(OF_NINTENDO_3DS) || defined(OF_WII) || \ + defined(OF_NINTENDO_SWITCH) TEST(@"-[stringByDeletingPathExtension]", [C(@"foo.bar").stringByDeletingPathExtension isEqual: @"foo"] && [C(@"foo..bar").stringByDeletingPathExtension isEqual: @"foo."] && [C(@"sdmc:/foo./bar").stringByDeletingPathExtension isEqual: @"sdmc:/foo./bar"] && Index: tests/OFSystemInfoTests.m ================================================================== --- tests/OFSystemInfoTests.m +++ tests/OFSystemInfoTests.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -19,13 +19,10 @@ @implementation TestsAppDelegate (OFSystemInfoTests) - (void)systemInfoTests { void *pool = objc_autoreleasePoolPush(); -#ifdef OF_HAVE_FILES - OFString *userConfigPath, *userDataPath; -#endif [OFStdOut setForegroundColor: [OFColor lime]]; [OFStdOut writeFormat: @"[OFSystemInfo] Page size: %zd\n", [OFSystemInfo pageSize]]; @@ -47,27 +44,18 @@ [OFStdOut writeFormat: @"[OFSystemInfo] Operating system version: %@\n", [OFSystemInfo operatingSystemVersion]]; -#ifdef OF_HAVE_FILES - @try { - userConfigPath = [OFSystemInfo userConfigPath]; - } @catch (OFNotImplementedException *e) { - userConfigPath = @"Not implemented"; - } - [OFStdOut writeFormat: @"[OFSystemInfo] User config path: %@\n", - userConfigPath]; - - @try { - userDataPath = [OFSystemInfo userDataPath]; - } @catch (OFNotImplementedException *e) { - userDataPath = @"Not implemented"; - } - [OFStdOut writeFormat: @"[OFSystemInfo] User data path: %@\n", - userDataPath]; -#endif + [OFStdOut writeFormat: @"[OFSystemInfo] User config URL: %@\n", + [OFSystemInfo userConfigURL].string]; + + [OFStdOut writeFormat: @"[OFSystemInfo] User data URL: %@\n", + [OFSystemInfo userDataURL].string]; + + [OFStdOut writeFormat: @"[OFSystemInfo] Temporary directory URL: %@\n", + [OFSystemInfo temporaryDirectoryURL].string]; [OFStdOut writeFormat: @"[OFSystemInfo] CPU vendor: %@\n", [OFSystemInfo CPUVendor]]; [OFStdOut writeFormat: @"[OFSystemInfo] CPU model: %@\n", Index: tests/OFTCPSocketTests.m ================================================================== --- tests/OFTCPSocketTests.m +++ tests/OFTCPSocketTests.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -44,14 +44,14 @@ TEST(@"-[remoteAddress]", [OFSocketAddressString(accepted.remoteAddress) isEqual: @"127.0.0.1"]) - TEST(@"-[writeString:]", [client writeString: @"Hello!"]) + TEST(@"-[writeString:]", R([client writeString: @"Hello!"])) TEST(@"-[readIntoBuffer:length:]", [accepted readIntoBuffer: buffer length: 6] && !memcmp(buffer, "Hello!", 6)) objc_autoreleasePoolPop(pool); } @end Index: tests/OFThreadTests.m ================================================================== --- tests/OFThreadTests.m +++ tests/OFThreadTests.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: tests/OFUDPSocketTests.m ================================================================== --- tests/OFUDPSocketTests.m +++ tests/OFUDPSocketTests.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in ADDED tests/OFUNIXDatagramSocketTests.m Index: tests/OFUNIXDatagramSocketTests.m ================================================================== --- tests/OFUNIXDatagramSocketTests.m +++ tests/OFUNIXDatagramSocketTests.m @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2008-2022 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 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 + +#import "TestsAppDelegate.h" + +static OFString *const module = @"OFUNIXDatagramSocket"; + +@implementation TestsAppDelegate (OFUNIXDatagramSocketTests) +- (void)UNIXDatagramSocketTests +{ + void *pool = objc_autoreleasePoolPush(); + OFString *path; + OFUNIXDatagramSocket *sock; + OFSocketAddress address1, address2; + char buffer[5]; + +#if defined(OF_HAVE_FILES) && !defined(OF_IOS) + path = [[OFSystemInfo temporaryDirectoryURL] + URLByAppendingPathComponent: [[OFUUID UUID] UUIDString]] + .fileSystemRepresentation; +#else + /* + * We can have sockets, including UNIX sockets, while file support is + * disabled. + * + * We also use this code path for iOS, as the temporaryDirectoryURL is + * too long on the iOS simulator. + */ + path = [OFString stringWithFormat: @"/tmp/%@", + [[OFUUID UUID] UUIDString]]; +#endif + + TEST(@"+[socket]", (sock = [OFUNIXDatagramSocket socket])) + + @try { + TEST(@"-[bindToPath:]", R(address1 = [sock bindToPath: path])) + } @catch (OFBindFailedException *e) { + switch (e.errNo) { + case EAFNOSUPPORT: + case EPERM: + [OFStdOut setForegroundColor: [OFColor lime]]; + [OFStdOut writeLine: + @"\r[OFUNIXDatagramSocket] -[bindToPath:]: " + @"UNIX datagram sockets unsupported, skipping " + @"tests"]; + + objc_autoreleasePoolPop(pool); + return; + default: + @throw e; + } + } + + @try { + TEST(@"-[sendBuffer:length:receiver:]", + R([sock sendBuffer: "Hello" length: 5 receiver: &address1])) + + TEST(@"-[receiveIntoBuffer:length:sender:]", + [sock receiveIntoBuffer: buffer + length: 5 + sender: &address2] == 5 && + memcmp(buffer, "Hello", 5) == 0 && + OFSocketAddressEqual(&address1, &address2) && + OFSocketAddressHash(&address1) == + OFSocketAddressHash(&address2)) + } @finally { +#ifdef OF_HAVE_FILES + [[OFFileManager defaultManager] removeItemAtPath: path]; +#endif + } + + objc_autoreleasePoolPop(pool); +} +@end ADDED tests/OFUNIXStreamSocketTests.m Index: tests/OFUNIXStreamSocketTests.m ================================================================== --- tests/OFUNIXStreamSocketTests.m +++ tests/OFUNIXStreamSocketTests.m @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2008-2022 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 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 + +#import "TestsAppDelegate.h" + +static OFString *const module = @"OFUNIXStreamSocket"; + +@implementation TestsAppDelegate (OFUNIXStreamSocketTests) +- (void)UNIXStreamSocketTests +{ + void *pool = objc_autoreleasePoolPush(); + OFString *path; + OFUNIXStreamSocket *sockClient, *sockServer, *sockAccepted; + char buffer[5]; + +#if defined(OF_HAVE_FILES) && !defined(OF_IOS) + path = [[OFSystemInfo temporaryDirectoryURL] + URLByAppendingPathComponent: [[OFUUID UUID] UUIDString]] + .fileSystemRepresentation; +#else + /* + * We can have sockets, including UNIX sockets, while file support is + * disabled. + * + * We also use this code path for iOS, as the temporaryDirectoryURL is + * too long on the iOS simulator. + */ + path = [OFString stringWithFormat: @"/tmp/%@", + [[OFUUID UUID] UUIDString]]; +#endif + + TEST(@"+[socket]", (sockClient = [OFUNIXStreamSocket socket]) && + (sockServer = [OFUNIXStreamSocket socket])) + + @try { + TEST(@"-[bindToPath:]", R([sockServer bindToPath: path])) + } @catch (OFBindFailedException *e) { + switch (e.errNo) { + case EAFNOSUPPORT: + case EPERM: + [OFStdOut setForegroundColor: [OFColor lime]]; + [OFStdOut writeLine: + @"\r[OFUNIXStreamSocket] -[bindToPath:]: " + @"UNIX stream sockets unsupported, skipping tests"]; + + objc_autoreleasePoolPop(pool); + return; + default: + @throw e; + } + } + + @try { + TEST(@"-[listen]", R([sockServer listen])) + + TEST(@"-[connectToPath:]", + R([sockClient connectToPath: path])) + + TEST(@"-[accept]", (sockAccepted = [sockServer accept])) + + TEST(@"-[writeBuffer:length:]", + R([sockAccepted writeBuffer: "Hello" length: 5])) + + TEST(@"-[readIntoBuffer:length:]", + [sockClient readIntoBuffer: buffer length: 5] == 5 && + memcmp(buffer, "Hello", 5) == 0) + + TEST(@"-[remoteAddress]", + OFSocketAddressUNIXPath(sockAccepted.remoteAddress) == nil) + } @finally { +#ifdef OF_HAVE_FILES + [[OFFileManager defaultManager] removeItemAtPath: path]; +#endif + } + + objc_autoreleasePoolPop(pool); +} +@end Index: tests/OFURLTests.m ================================================================== --- tests/OFURLTests.m +++ tests/OFURLTests.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: tests/OFValueTests.m ================================================================== --- tests/OFValueTests.m +++ tests/OFValueTests.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: tests/OFWindowsRegistryKeyTests.m ================================================================== --- tests/OFWindowsRegistryKeyTests.m +++ tests/OFWindowsRegistryKeyTests.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -40,17 +40,20 @@ [OFWindowsRegistryKey localMachineKey]) TEST(@"+[OFWindowsRegistryKey usersKey]", [OFWindowsRegistryKey usersKey]) - TEST(@"-[openSubkeyAtPath:securityAndAccessRights:]", + TEST(@"-[openSubkeyAtPath:securityAndAccessRights:] #1", (softwareKey = [[OFWindowsRegistryKey currentUserKey] openSubkeyAtPath: @"Software" - securityAndAccessRights: KEY_ALL_ACCESS]) && + securityAndAccessRights: KEY_ALL_ACCESS])) + + EXPECT_EXCEPTION(@"-[openSubkeyAtPath:securityAndAccessRights:] #2", + OFOpenWindowsRegistryKeyFailedException, [[OFWindowsRegistryKey currentUserKey] openSubkeyAtPath: @"nonexistent" - securityAndAccessRights: KEY_ALL_ACCESS] == nil) + securityAndAccessRights: KEY_ALL_ACCESS]) TEST(@"-[createSubkeyAtPath:securityAndAccessRights:]", (objFWKey = [softwareKey createSubkeyAtPath: @"ObjFW" securityAndAccessRights: KEY_ALL_ACCESS])) Index: tests/OFXMLElementBuilderTests.m ================================================================== --- tests/OFXMLElementBuilderTests.m +++ tests/OFXMLElementBuilderTests.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: tests/OFXMLNodeTests.m ================================================================== --- tests/OFXMLNodeTests.m +++ tests/OFXMLNodeTests.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: tests/OFXMLParserTests.m ================================================================== --- tests/OFXMLParserTests.m +++ tests/OFXMLParserTests.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: tests/RuntimeARCTests.m ================================================================== --- tests/RuntimeARCTests.m +++ tests/RuntimeARCTests.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -25,11 +25,20 @@ @implementation RuntimeARCTest - (instancetype)init { self = [super init]; +#ifdef OF_WINDOWS + /* + * Clang has a bug on Windows where it creates an invalid call into + * objc_retainAutoreleasedReturnValue(). Work around it by not using an + * autoreleased exception. + */ + @throw [[OFException alloc] init]; +#else @throw [OFException exception]; +#endif return self; } @end Index: tests/RuntimeTests.m ================================================================== --- tests/RuntimeTests.m +++ tests/RuntimeTests.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: tests/TestsAppDelegate.h ================================================================== --- tests/TestsAppDelegate.h +++ tests/TestsAppDelegate.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -116,10 +116,14 @@ @end @interface TestsAppDelegate (OFJSONTests) - (void)JSONTests; @end + +@interface TestsAppDelegate (OFHMACTests) +- (void)HMACTests; +@end @interface TestsAppDelegate (OFKernelEventObserverTests) - (void)kernelEventObserverTests; @end @@ -132,14 +136,22 @@ @end @interface TestsAppDelegate (OFMD5HashTests) - (void)MD5HashTests; @end + +@interface TestsAppDelegate (OFMemoryStreamTests) +- (void)memoryStreamTests; +@end @interface TestsAppDelegate (OFMethodSignatureTests) - (void)methodSignatureTests; @end + +@interface TestsAppDelegate (OFNotificationCenterTests) +- (void)notificationCenterTests; +@end @interface TestsAppDelegate (OFNumberTests) - (void)numberTests; @end @@ -213,14 +225,10 @@ @interface TestsAppDelegate (OFSystemInfoTests) - (void)systemInfoTests; @end -@interface TestsAppDelegate (OFHMACTests) -- (void)HMACTests; -@end - @interface TestsAppDelegate (OFSocketTests) - (void)socketTests; @end @interface TestsAppDelegate (OFStreamTests) @@ -240,10 +248,18 @@ @end @interface TestsAppDelegate (OFUDPSocketTests) - (void)UDPSocketTests; @end + +@interface TestsAppDelegate (OFUNIXDatagramSocketTests) +- (void)UNIXDatagramSocketTests; +@end + +@interface TestsAppDelegate (OFUNIXStreamSocketTests) +- (void)UNIXStreamSocketTests; +@end @interface TestsAppDelegate (OFURLTests) - (void)URLTests; @end Index: tests/TestsAppDelegate.m ================================================================== --- tests/TestsAppDelegate.m +++ tests/TestsAppDelegate.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -48,10 +48,28 @@ /* Newer versions of libctru started using id as a parameter name. */ # define id id_3ds # include <3ds.h> # undef id #endif + +#ifdef OF_NINTENDO_SWITCH +# define id nx_id +# include +# undef id + +static OFDate *lastConsoleUpdate; + +static void +updateConsole(bool force) +{ + if (force || lastConsoleUpdate.timeIntervalSinceNow <= -1.0 / 60) { + consoleUpdate(NULL); + [lastConsoleUpdate release]; + lastConsoleUpdate = [[OFDate alloc] init]; + } +} +#endif #ifdef OF_AMIGAOS extern unsigned long *OFHashSeedRef(void); #else extern unsigned long OFHashSeed; @@ -144,12 +162,23 @@ atexit(gfxExit); consoleInit(GFX_TOP, NULL); #endif -#if defined(OF_WII) || defined(OF_PSP) || defined(OF_NINTENDO_DS) || \ - defined(OF_NINTENDO_3DS) +#ifdef OF_NINTENDO_SWITCH + consoleInit(NULL); + padConfigureInput(1, HidNpadStyleSet_NpadStandard); + updateConsole(true); + +# ifdef OF_HAVE_FILES + [[OFFileManager defaultManager] changeCurrentDirectoryPath: @"romfs:/"]; +# endif +#endif + +#if defined(OF_WII) || defined(OF_WII_U) || defined(OF_PSP) || \ + defined(OF_NINTENDO_DS) || defined(OF_NINTENDO_3DS) || \ + defined(OF_NINTENDO_SWITCH) @try { return OFApplicationMain(&argc, &argv, [[TestsAppDelegate alloc] init]); } @catch (id e) { OFString *string = [OFString stringWithFormat: @@ -196,10 +225,16 @@ if (hidKeysDown() & KEY_START) [OFApplication terminateWithStatus: 1]; gspWaitForVBlank(); } +# elif defined(OF_NINTENDO_SWITCH) + while (appletMainLoop()) + updateConsole(true); + + consoleExit(NULL); + abort(); # else abort(); # endif } #else @@ -213,10 +248,14 @@ if (OFStdOut.hasTerminal) { [OFStdOut setForegroundColor: [OFColor yellow]]; [OFStdOut writeFormat: @"[%@] %@: testing...", module, test]; } else [OFStdOut writeFormat: @"[%@] %@: ", module, test]; + +#ifdef OF_NINTENDO_SWITCH + updateConsole(false); +#endif } - (void)outputSuccess: (OFString *)test inModule: (OFString *)module { if (OFStdOut.hasTerminal) { @@ -223,79 +262,99 @@ [OFStdOut setForegroundColor: [OFColor lime]]; [OFStdOut eraseLine]; [OFStdOut writeFormat: @"\r[%@] %@: ok\n", module, test]; } else [OFStdOut writeLine: @"ok"]; + +#ifdef OF_NINTENDO_SWITCH + updateConsole(false); +#endif } - (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 - [OFStdOut reset]; - [OFStdOut writeLine: @"Press A to continue!"]; - - for (;;) { - WPAD_ScanPads(); - - if (WPAD_ButtonsDown(0) & WPAD_BUTTON_A) - return; - - VIDEO_WaitVSync(); - } -#endif -#ifdef OF_PSP - [OFStdOut reset]; - [OFStdOut writeLine: @"Press X to continue!"]; - - for (;;) { - SceCtrlData pad; - - sceCtrlReadBufferPositive(&pad, 1); - if (pad.Buttons & PSP_CTRL_CROSS) { - for (;;) { - sceCtrlReadBufferPositive(&pad, 1); - if (!(pad.Buttons & PSP_CTRL_CROSS)) - return; - } - } - } -#endif -#ifdef OF_NINTENDO_DS - [OFStdOut reset]; - [OFStdOut writeString: @"Press A to continue!"]; - - for (;;) { - swiWaitForVBlank(); - scanKeys(); - if (keysDown() & KEY_A) - break; - } -#endif -#ifdef OF_NINTENDO_3DS - [OFStdOut reset]; - [OFStdOut writeString: @"Press A to continue!"]; - - for (;;) { - hidScanInput(); - - if (hidKeysDown() & KEY_A) - break; - - gspWaitForVBlank(); - } -#endif - + } else + [OFStdOut writeLine: @"failed"]; + +#ifdef OF_WII + [OFStdOut reset]; + [OFStdOut writeLine: @"Press A to continue!"]; + + for (;;) { + WPAD_ScanPads(); + + if (WPAD_ButtonsDown(0) & WPAD_BUTTON_A) + return; + + VIDEO_WaitVSync(); + } +#endif +#ifdef OF_PSP + [OFStdOut reset]; + [OFStdOut writeLine: @"Press X to continue!"]; + + for (;;) { + SceCtrlData pad; + + sceCtrlReadBufferPositive(&pad, 1); + if (pad.Buttons & PSP_CTRL_CROSS) { + for (;;) { + sceCtrlReadBufferPositive(&pad, 1); + if (!(pad.Buttons & PSP_CTRL_CROSS)) + return; + } + } + } +#endif +#ifdef OF_NINTENDO_DS + [OFStdOut reset]; + [OFStdOut writeString: @"Press A to continue!"]; + + for (;;) { + swiWaitForVBlank(); + scanKeys(); + if (keysDown() & KEY_A) + break; + } +#endif +#ifdef OF_NINTENDO_3DS + [OFStdOut reset]; + [OFStdOut writeString: @"Press A to continue!"]; + + for (;;) { + hidScanInput(); + + if (hidKeysDown() & KEY_A) + break; + + gspWaitForVBlank(); + } +#endif +#ifdef OF_NINTENDO_SWITCH + [OFStdOut reset]; + [OFStdOut writeString: @"Press A to continue!"]; + + while (appletMainLoop()) { + PadState pad; + + padUpdate(&pad); + updateConsole(true); + + if (padGetButtonsDown(&pad) & HidNpadButton_A) + break; + } +#endif + + if (OFStdOut.hasTerminal) { [OFStdOut writeString: @"\r"]; [OFStdOut reset]; [OFStdOut eraseLine]; - } else - [OFStdOut writeLine: @"failed"]; + } } - (void)applicationDidFinishLaunching { #if defined(OF_IOS) && defined(OF_HAVE_FILES) @@ -337,23 +396,23 @@ [self setTests]; [self dateTests]; [self valueTests]; [self numberTests]; [self streamTests]; -#ifdef OF_HAVE_FILES + [self memoryStreamTests]; + [self notificationCenterTests]; [self MD5HashTests]; [self RIPEMD160HashTests]; [self SHA1HashTests]; [self SHA224HashTests]; [self SHA256HashTests]; [self SHA384HashTests]; [self SHA512HashTests]; [self HMACTests]; -#endif [self PBKDF2Tests]; [self scryptTests]; -#if defined(OF_HAVE_FILES) && defined(HAVE_CODEPAGE_437) +#ifdef HAVE_CODEPAGE_437 [self INIFileTests]; #endif #ifdef OF_HAVE_SOCKETS [self socketTests]; [self TCPSocketTests]; @@ -361,10 +420,14 @@ # ifdef OF_HAVE_IPX [self IPXSocketTests]; [self SPXSocketTests]; [self SPXStreamSocketTests]; # endif +# ifdef OF_HAVE_UNIX_SOCKETS + [self UNIXDatagramSocketTests]; + [self UNIXStreamSocketTests]; +# endif [self kernelEventObserverTests]; #endif #ifdef OF_HAVE_THREADS [self threadTests]; #endif @@ -377,13 +440,11 @@ [self HTTPCookieManagerTests]; #endif [self XMLParserTests]; [self XMLNodeTests]; [self XMLElementBuilderTests]; -#ifdef OF_HAVE_FILES [self serializationTests]; -#endif [self JSONTests]; [self propertyListTests]; #if defined(OF_HAVE_PLUGINS) [self pluginTests]; #endif @@ -435,10 +496,17 @@ if (hidKeysDown() & KEY_START) [OFApplication terminateWithStatus: _fails]; gspWaitForVBlank(); } +#elif defined(OF_NINTENDO_SWITCH) + while (appletMainLoop()) + updateConsole(true); + + consoleExit(NULL); + + [OFApplication terminateWithStatus: _fails]; #else [OFApplication terminateWithStatus: _fails]; #endif } @end Index: tests/iOS.xcodeproj/project.pbxproj ================================================================== --- tests/iOS.xcodeproj/project.pbxproj +++ tests/iOS.xcodeproj/project.pbxproj @@ -133,11 +133,11 @@ /* Begin PBXProject section */ 4BEBFB532013934E002E8710 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0920; + LastUpgradeCheck = 1330; ORGANIZATIONNAME = "Jonathan Schleifer"; TargetAttributes = { 4BEBFB5A2013934E002E8710 = { CreatedOnToolsVersion = 9.2; ProvisioningStyle = Automatic; @@ -200,17 +200,19 @@ CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; @@ -255,17 +257,19 @@ CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; Index: tests/objc_sync/test.m ================================================================== --- tests/objc_sync/test.m +++ tests/objc_sync/test.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: tests/plugin/TestPlugin.h ================================================================== --- tests/plugin/TestPlugin.h +++ tests/plugin/TestPlugin.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -11,10 +11,10 @@ * Public License, either 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 "OFPlugin.h" +#import "OFObject.h" -@interface TestPlugin: OFPlugin +@interface TestPlugin: OFObject - (int)test: (int)num; @end Index: tests/plugin/TestPlugin.m ================================================================== --- tests/plugin/TestPlugin.m +++ tests/plugin/TestPlugin.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -42,10 +42,10 @@ { return num * 2; } @end -id -OFPluginInit(void) +Class +class(void) { - return [[[TestPlugin alloc] init] autorelease]; + return [TestPlugin class]; } Index: tests/serialization.xml ================================================================== --- tests/serialization.xml +++ tests/serialization.xml @@ -1,8 +1,14 @@ + + 01234567-89ab-cdef-fedc-ba9876543210 + + + uuid + Blub B"la Index: tests/terminal/TerminalTests.m ================================================================== --- tests/terminal/TerminalTests.m +++ tests/terminal/TerminalTests.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: utils/Makefile ================================================================== --- utils/Makefile +++ utils/Makefile @@ -8,25 +8,25 @@ include ../buildsys.mk DISTCLEAN = objfw-config -install-extra: objfw-config objfw-compile objfw-new - for i in objfw-config objfw-compile objfw-new; do \ +install-extra: objfw-config objfw-compile objfw-embed + for i in objfw-config objfw-compile objfw-embed; do \ ${INSTALL_STATUS}; \ if ${MKDIR_P} ${DESTDIR}${bindir} && ${INSTALL} -m 755 $$i ${DESTDIR}${bindir}/${BIN_PREFIX}$$i; then \ ${INSTALL_OK}; \ else \ ${INSTALL_FAILED}; \ fi \ done uninstall-extra: - for i in objfw-config objfw-compile objfw-new; do \ + for i in objfw-config objfw-compile objfw-embed; do \ if test -f ${DESTDIR}${bindir}/${BIN_PREFIX}$$i; then \ if rm -f ${DESTDIR}${bindir}/${BIN_PREFIX}$$i; then \ ${DELETE_OK}; \ else \ ${DELETE_FAILED}; \ fi \ fi \ done Index: utils/objfw-compile ================================================================== --- utils/objfw-compile +++ utils/objfw-compile @@ -1,8 +1,8 @@ #!/bin/sh # -# Copyright (c) 2008-2021 Jonathan Schleifer +# Copyright (c) 2008-2022 Jonathan Schleifer # # All rights reserved. # # This file is part of ObjFW. It may be distributed under the terms of the # Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -293,19 +293,19 @@ fi ;; esac objs="$objs $obj" build="no" - deps=$($OBJC -E -M $CPPFLAGS $OBJCFLAGS $i | - sed 's/.*: //' | sed 's/\\//g') - if test -f "$obj"; then + if test ! -f "$obj" -o "$i" -nt "$obj"; then + build="yes" + else + deps=$($OBJC -E -M $CPPFLAGS $OBJCFLAGS $i | + sed 's/.*: //' | sed 's/\\//g') for dep in $deps; do test "$dep" -nt $obj && build="yes" done - else - build="yes" fi if test x"$build" = x"yes"; then link="yes" status_compiling $i Index: utils/objfw-config.in ================================================================== --- utils/objfw-config.in +++ utils/objfw-config.in @@ -1,8 +1,8 @@ #!/bin/sh # -# Copyright (c) 2008-2021 Jonathan Schleifer +# Copyright (c) 2008-2022 Jonathan Schleifer # # All rights reserved. # # This file is part of ObjFW. It may be distributed under the terms of the # Q Public License 1.0, which can be found in the file LICENSE.QPL included in ADDED utils/objfw-embed Index: utils/objfw-embed ================================================================== --- utils/objfw-embed +++ utils/objfw-embed @@ -0,0 +1,26 @@ +#!/bin/sh +if test $# != 3; then + echo "Usage: $0 source_file filename output.m" 1>&2 + exit 1 +fi + +exec 1>$3 + +cat < +#include + +extern void OFRegisterEmbeddedFile(const char *, const uint8_t *, size_t); + +static const uint8_t bytes[] = { +EOF +od -vtx1 $1 | sed '/^[^ ][^ ]*$/d;s/ */ /g;s/ $//g;s/^[^ ][^ ]* //;s/ /, 0x/g;s/^/ 0x/;s/$/,/' +cat <"$name.m" <<__EOF__ -#import - -@interface $name: OFObject -@end - -OF_APPLICATION_DELEGATE($name) - -@implementation $name -- (void)applicationDidFinishLaunching -{ - [OFApplication terminate]; -} -@end -__EOF__ - ;; -class) - test -f "$name.h" && already_exists "$name.h" - test -f "$name.m" && already_exists "$name.m" - - cat >"$name.h" <<__EOF__ -#import - -@interface $name: OFObject -@end -__EOF__ - cat >"$name.m" <<__EOF__ -#import "$name.h" - -@implementation $name -@end -__EOF__ - ;; -*) - show_help - ;; -esac Index: utils/ofarc/Archive.h ================================================================== --- utils/ofarc/Archive.h +++ utils/ofarc/Archive.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: utils/ofarc/GZIPArchive.h ================================================================== --- utils/ofarc/GZIPArchive.h +++ utils/ofarc/GZIPArchive.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: utils/ofarc/GZIPArchive.m ================================================================== --- utils/ofarc/GZIPArchive.m +++ utils/ofarc/GZIPArchive.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: utils/ofarc/LHAArchive.h ================================================================== --- utils/ofarc/LHAArchive.h +++ utils/ofarc/LHAArchive.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: utils/ofarc/LHAArchive.m ================================================================== --- utils/ofarc/LHAArchive.m +++ utils/ofarc/LHAArchive.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: utils/ofarc/OFArc.h ================================================================== --- utils/ofarc/OFArc.h +++ utils/ofarc/OFArc.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: utils/ofarc/OFArc.m ================================================================== --- utils/ofarc/OFArc.m +++ utils/ofarc/OFArc.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: utils/ofarc/TarArchive.h ================================================================== --- utils/ofarc/TarArchive.h +++ utils/ofarc/TarArchive.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: utils/ofarc/TarArchive.m ================================================================== --- utils/ofarc/TarArchive.m +++ utils/ofarc/TarArchive.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: utils/ofarc/ZIPArchive.h ================================================================== --- utils/ofarc/ZIPArchive.h +++ utils/ofarc/ZIPArchive.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: utils/ofarc/ZIPArchive.m ================================================================== --- utils/ofarc/ZIPArchive.m +++ utils/ofarc/ZIPArchive.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: utils/ofdns/OFDNS.m ================================================================== --- utils/ofdns/OFDNS.m +++ utils/ofdns/OFDNS.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: utils/ofhash/OFHash.m ================================================================== --- utils/ofhash/OFHash.m +++ utils/ofhash/OFHash.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -51,12 +51,15 @@ } static void printHash(OFString *algo, OFString *path, id hash) { - const unsigned char *digest = hash.digest; size_t digestSize = hash.digestSize; + const unsigned char *digest; + + [hash calculate]; + digest = hash.digest; [OFStdOut writeFormat: @"%@ ", algo]; for (size_t i = 0; i < digestSize; i++) [OFStdOut writeFormat: @"%02x", digest[i]]; Index: utils/ofhttp/Makefile ================================================================== --- utils/ofhttp/Makefile +++ utils/ofhttp/Makefile @@ -13,14 +13,16 @@ ${PROG}: ${LIBOBJFW_DEP_LVL2} ${LIBOBJFWRT_DEP_LVL2} CPPFLAGS += -I../../src \ -I../../src/runtime \ -I../../src/exceptions \ + -I../../src/tls \ -I../.. \ -DLANGUAGE_DIR='"${datadir}/ofhttp/lang"' \ -DLIB_PREFIX='"${LIB_PREFIX}"' \ -DLIB_SUFFIX='"${LIB_SUFFIX}"' -LIBS := -L../../src -L../../src/linklib ${OBJFW_LIBS} \ +LIBS := -L../../src -L../../src/linklib -L../../src/tls \ + ${OFHTTP_LIBS} ${OBJFW_LIBS} \ -L../../src/runtime -L../../src/runtime/linklib ${RUNTIME_LIBS} \ ${LIBS} LD = ${OBJC} LDFLAGS += ${LDFLAGS_RPATH} Index: utils/ofhttp/OFHTTP.m ================================================================== --- utils/ofhttp/OFHTTP.m +++ utils/ofhttp/OFHTTP.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -31,12 +31,16 @@ #endif #import "OFSandbox.h" #import "OFStdIOStream.h" #import "OFSystemInfo.h" #import "OFTCPSocket.h" -#import "OFTLSSocket.h" +#import "OFTLSStream.h" #import "OFURL.h" + +#ifdef HAVE_TLS_SUPPORT +# import "ObjFWTLS.h" +#endif #import "OFConnectionFailedException.h" #import "OFHTTPRequestFailedException.h" #import "OFInvalidArgumentException.h" #import "OFInvalidFormatException.h" @@ -75,10 +79,18 @@ ProgressBar *_progressBar; } - (void)downloadNextURL; @end + +#ifdef HAVE_TLS_SUPPORT +void +_reference_to_ObjFWTLS(void) +{ + _ObjFWTLS_reference = 1; +} +#endif OF_APPLICATION_DELEGATE(OFHTTP) static void help(OFStream *stream, bool full, int status) @@ -276,21 +288,10 @@ objc_autoreleasePoolPop(pool); return [fileName autorelease]; } @implementation OFHTTP -#ifdef OF_HAVE_PLUGINS -+ (void)initialize -{ - if (self != [OFHTTP class]) - return; - - /* Opportunistically try loading ObjOpenSSL and ignore any errors. */ - OFDLOpen(@LIB_PREFIX @"objopenssl" @LIB_SUFFIX, OFDLOpenFlagLazy); -} -#endif - - (instancetype)init { self = [super init]; @try { @@ -534,11 +535,11 @@ else [sandbox unveilPath: [[OFFileManager defaultManager] currentDirectoryPath] permissions: (_continue ? @"rwc" : @"wc")]; - /* In case we use ObjOpenSSL for https later */ + /* In case we use OpenSSL for HTTPS later */ [sandbox unveilPath: @"/etc/ssl" permissions: @"r"]; sandbox.allowsUnveil = false; [OFApplication of_activateSandbox: sandbox]; #endif @@ -576,22 +577,25 @@ } if (_insecure) _HTTPClient.allowsInsecureRedirects = true; +#ifdef OF_WINDOWS + _useUnicode = [OFSystemInfo isWindowsNT]; +#else _useUnicode = ([OFLocale encoding] == OFStringEncodingUTF8); +#endif [self performSelector: @selector(downloadNextURL) afterDelay: 0]; } -- (void)client: (OFHTTPClient *)client - didCreateSocket: (OFTCPSocket *)sock - request: (OFHTTPRequest *)request +- (void)client: (OFHTTPClient *)client + didCreateTLSStream: (OFTLSStream *)stream + request: (OFHTTPRequest *)request { - if (_insecure && [sock respondsToSelector: - @selector(setVerifiesCertificates:)]) - ((id )sock).verifiesCertificates = false; + /* Use setter instead of property access to work around GCC bug. */ + [stream setVerifiesCertificates: !_insecure]; } - (void)client: (OFHTTPClient *)client wantsRequestBody: (OFStream *)body request: (OFHTTPRequest *)request @@ -843,15 +847,16 @@ } else if ([exception isKindOfClass: [OFUnsupportedProtocolException class]]) { if (!_quiet) [OFStdOut writeString: @"\n"]; - [OFStdErr writeLine: OF_LOCALIZED(@"no_ssl_library", - @"%[prog]: No TLS library loaded!\n" - @" In order to download via https, you need to " - @"preload an TLS library for ObjFW\n" - @" such as ObjOpenSSL!", + [OFStdErr writeLine: OF_LOCALIZED(@"no_tls_support", + @"%[prog]: No TLS support in ObjFW!\n" + @" In order to download via HTTPS, you need to " + @"either build ObjFW with TLS\n" + @" support or preload a library adding TLS " + @"support to ObjFW!", @"prog", [OFApplication programName])]; } else if ([exception isKindOfClass: [OFReadOrWriteFailedException class]]) { OFString *error = OF_LOCALIZED( @"download_failed_read_or_write_failed_any", Index: utils/ofhttp/ProgressBar.h ================================================================== --- utils/ofhttp/ProgressBar.h +++ utils/ofhttp/ProgressBar.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: utils/ofhttp/ProgressBar.m ================================================================== --- utils/ofhttp/ProgressBar.m +++ utils/ofhttp/ProgressBar.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -27,10 +27,15 @@ static const float oneKibibyte = 1024; static const float oneMebibyte = 1024 * 1024; static const float oneGibibyte = 1024 * 1024 * 1024; static const OFTimeInterval updateInterval = 0.1; + +#ifdef OF_MINT +/* freemint-gcc does not have trunc() */ +# define trunc(x) ((int64_t)(x)) +#endif #ifndef HAVE_TRUNCF # define truncf(x) trunc(x) #endif Index: utils/ofhttp/lang/de.json ================================================================== --- utils/ofhttp/lang/de.json +++ utils/ofhttp/lang/de.json @@ -50,15 +50,17 @@ ], "download_failed_invalid_server_reply": [ "%[prog]: Fehler beim Download von <%[url]>!\n", " Ungültige Antwort vom Server!" ], - "no_ssl_library": [ - "%[prog]: Keine TLS-Bibliothek geladen!\n", - " Um Dateien über https zu laden, müssen Sie eine TLS-Bibliothek für ", - "ObjFW,\n", - " wie z.B. ObjOpenSSL, mittels LD_PRELOAD laden." + "no_tls_support": [ + "%[prog]: Keine TLS-Unterstützung in ObjFW!\n", + " Um via HTTPS runterzuladen, müssen Sie entweder ObjFW mit TLS-", + "Unterstützung\n", + " kompilieren oder eine Bibliothek mittels „preoad” laden, welche ", + "TLS-Support\n", + " zu ObjFW hinzufügt!" ], "download_failed_read_or_write_failed_any": "Lesen oder Schreiben", "download_failed_read_or_write_failed_read": "Lesen", "download_failed_read_or_write_failed_write": "Schreiben", "download_failed_read_or_write_failed": [