Index: .fossil-settings/clean-glob ================================================================== --- .fossil-settings/clean-glob +++ .fossil-settings/clean-glob @@ -37,11 +37,10 @@ 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 Index: .fossil-settings/ignore-glob ================================================================== --- .fossil-settings/ignore-glob +++ .fossil-settings/ignore-glob @@ -42,11 +42,10 @@ 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 Index: .github/workflows/amiga-gcc.yml ================================================================== --- .github/workflows/amiga-gcc.yml +++ .github/workflows/amiga-gcc.yml @@ -2,20 +2,15 @@ on: [push, pull_request] jobs: build: runs-on: ubuntu-latest container: amigadev/crosstools:m68k-amigaos - strategy: - matrix: - configure_flags: - - - - --disable-amiga-lib steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: autogen.sh run: ./autogen.sh - name: configure - run: ./configure --host=m68k-amigaos ${{ matrix.configure_flags }} + run: ./configure --host=m68k-amigaos - name: make run: make -j$(nproc) - name: make install run: make install Index: .github/workflows/ios.yml ================================================================== --- .github/workflows/ios.yml +++ .github/workflows/ios.yml @@ -12,11 +12,11 @@ - - --disable-shared steps: - name: Install dependencies run: brew install autoconf automake - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: autogen.sh run: ./autogen.sh - name: configure run: | export IPHONEOS_DEPLOYMENT_TARGET="9.0" Index: .github/workflows/macos-11.yml ================================================================== --- .github/workflows/macos-11.yml +++ .github/workflows/macos-11.yml @@ -16,11 +16,11 @@ - --disable-files - --disable-shared steps: - name: Install dependencies run: brew install autoconf automake - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: autogen.sh run: ./autogen.sh - name: configure run: ./configure ${{ matrix.configure_flags }} - name: make Index: .github/workflows/macos-12.yml ================================================================== --- .github/workflows/macos-12.yml +++ .github/workflows/macos-12.yml @@ -16,11 +16,11 @@ - --disable-files - --disable-shared steps: - name: Install dependencies run: brew install autoconf automake - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: autogen.sh run: ./autogen.sh - name: configure run: ./configure ${{ matrix.configure_flags }} - name: make ADDED .github/workflows/macos-13.yml Index: .github/workflows/macos-13.yml ================================================================== --- /dev/null +++ .github/workflows/macos-13.yml @@ -0,0 +1,31 @@ +name: macos-13 +on: [push, pull_request] +jobs: + tests: + runs-on: macos-13 + strategy: + matrix: + configure_flags: + - + - --disable-threads + - --disable-threads --disable-sockets + - --disable-threads --disable-files + - --disable-threads --disable-sockets --disable-files + - --disable-sockets + - --disable-sockets --disable-files + - --disable-files + - --disable-shared + steps: + - name: Install dependencies + run: brew install autoconf automake + - uses: actions/checkout@v4 + - name: autogen.sh + run: ./autogen.sh + - name: configure + run: ./configure ${{ matrix.configure_flags }} + - name: make + run: make -j$(sysctl -n hw.logicalcpu) + - name: make check + run: make check + - name: make install + run: sudo make install Index: .github/workflows/morphos.yml ================================================================== --- .github/workflows/morphos.yml +++ .github/workflows/morphos.yml @@ -2,20 +2,15 @@ on: [push, pull_request] jobs: build: runs-on: ubuntu-latest container: amigadev/crosstools:ppc-morphos - strategy: - matrix: - configure_flags: - - - - --disable-amiga-lib steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: autogen.sh run: ./autogen.sh - name: configure - run: ./configure --host=ppc-morphos ${{ matrix.configure_flags }} + run: ./configure --host=ppc-morphos - name: make run: make -j$(nproc) - name: make install run: make install Index: .github/workflows/nintendo-3ds.yml ================================================================== --- .github/workflows/nintendo-3ds.yml +++ .github/workflows/nintendo-3ds.yml @@ -4,11 +4,11 @@ build: runs-on: ubuntu-latest steps: - name: Install dependencies run: docker pull devkitpro/devkitarm - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: autogen.sh run: ./autogen.sh - name: configure run: | docker run \ Index: .github/workflows/nintendo-ds.yml ================================================================== --- .github/workflows/nintendo-ds.yml +++ .github/workflows/nintendo-ds.yml @@ -4,11 +4,11 @@ build: runs-on: ubuntu-latest steps: - name: Install dependencies run: docker pull devkitpro/devkitarm - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: autogen.sh run: ./autogen.sh - name: configure run: | docker run \ Index: .github/workflows/nintendo-switch.yml ================================================================== --- .github/workflows/nintendo-switch.yml +++ .github/workflows/nintendo-switch.yml @@ -4,11 +4,11 @@ build: runs-on: ubuntu-latest steps: - name: Install dependencies run: docker pull devkitpro/devkita64 - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: autogen.sh run: ./autogen.sh - name: configure run: | docker run \ Index: .github/workflows/ubuntu-20.04-32bit.yml ================================================================== --- .github/workflows/ubuntu-20.04-32bit.yml +++ .github/workflows/ubuntu-20.04-32bit.yml @@ -22,11 +22,11 @@ steps: - name: Install dependencies run: | sudo apt-get update sudo apt-get install gcc-multilib - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: autogen.sh run: ./autogen.sh - name: configure run: ./configure OBJC="clang -m32" ${{ matrix.configure_flags }} - name: make 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 @@ -22,11 +22,11 @@ steps: - name: Install dependencies run: | sudo apt-get update sudo apt-get install gcc-multilib gobjc - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: autogen.sh run: ./autogen.sh - name: configure run: ./configure OBJC="gcc -m32" ${{ matrix.configure_flags }} - name: make Index: .github/workflows/ubuntu-20.04-gcc.yml ================================================================== --- .github/workflows/ubuntu-20.04-gcc.yml +++ .github/workflows/ubuntu-20.04-gcc.yml @@ -24,11 +24,11 @@ steps: - name: Install dependencies run: | sudo apt-get update sudo apt-get install gobjc libssl-dev gnutls-dev - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: autogen.sh run: ./autogen.sh - name: configure run: ./configure OBJC="gcc" ${{ matrix.configure_flags }} - name: make Index: .github/workflows/ubuntu-20.04.yml ================================================================== --- .github/workflows/ubuntu-20.04.yml +++ .github/workflows/ubuntu-20.04.yml @@ -24,11 +24,11 @@ steps: - name: Install dependencies run: | sudo apt-get update sudo apt-get install libssl-dev gnutls-dev - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: autogen.sh run: ./autogen.sh - name: configure run: ./configure ${{ matrix.configure_flags }} - name: make Index: .github/workflows/ubuntu-latest-32bit.yml ================================================================== --- .github/workflows/ubuntu-latest-32bit.yml +++ .github/workflows/ubuntu-latest-32bit.yml @@ -22,11 +22,11 @@ steps: - name: Install dependencies run: | sudo apt-get update sudo apt-get install gcc-multilib - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: autogen.sh run: ./autogen.sh - name: configure run: ./configure OBJC="clang -m32" ${{ matrix.configure_flags }} - name: make Index: .github/workflows/ubuntu-latest-gcc-32bit.yml ================================================================== --- .github/workflows/ubuntu-latest-gcc-32bit.yml +++ .github/workflows/ubuntu-latest-gcc-32bit.yml @@ -22,11 +22,11 @@ steps: - name: Install dependencies run: | sudo apt-get update sudo apt-get install gcc-multilib gobjc - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: autogen.sh run: ./autogen.sh - name: configure run: ./configure OBJC="gcc -m32" ${{ matrix.configure_flags }} - name: make Index: .github/workflows/ubuntu-latest-gcc.yml ================================================================== --- .github/workflows/ubuntu-latest-gcc.yml +++ .github/workflows/ubuntu-latest-gcc.yml @@ -24,11 +24,11 @@ steps: - name: Install dependencies run: | sudo apt-get update sudo apt-get install gobjc libssl-dev gnutls-dev - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: autogen.sh run: ./autogen.sh - name: configure run: ./configure OBJC="gcc" ${{ matrix.configure_flags }} - name: make Index: .github/workflows/ubuntu-latest.yml ================================================================== --- .github/workflows/ubuntu-latest.yml +++ .github/workflows/ubuntu-latest.yml @@ -24,11 +24,11 @@ steps: - name: Install dependencies run: | sudo apt-get update sudo apt-get install libssl-dev gnutls-dev - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: autogen.sh run: ./autogen.sh - name: configure run: ./configure ${{ matrix.configure_flags }} - name: make Index: .github/workflows/wii-u.yml ================================================================== --- .github/workflows/wii-u.yml +++ .github/workflows/wii-u.yml @@ -4,11 +4,11 @@ build: runs-on: ubuntu-latest steps: - name: Install dependencies run: docker pull devkitpro/devkitppc - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: autogen.sh run: ./autogen.sh - name: configure run: | docker run \ Index: .github/workflows/wii.yml ================================================================== --- .github/workflows/wii.yml +++ .github/workflows/wii.yml @@ -4,11 +4,11 @@ build: runs-on: ubuntu-latest steps: - name: Install dependencies run: docker pull devkitpro/devkitppc - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: autogen.sh run: ./autogen.sh - name: configure run: | docker run \ Index: .gitignore ================================================================== --- .gitignore +++ .gitignore @@ -42,11 +42,10 @@ 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 Index: ChangeLog ================================================================== --- ChangeLog +++ ChangeLog @@ -2,11 +2,51 @@ * Changes of existing features or bugfixes + New features This file only contains the most significant changes. -ObjFW 0.90.1 -> ObjFW 0.90.2, 23.10.2017 +ObjFW 1.0.4 -> ObjFW 1.0.5, 2023-11-05 + * Fixes the calculation of the extra alignment in OFAllocObject() + * Fixes +[OFSystemInfo networkInterfaces] on OpenBSD and Windows 98 + * Fixes OFSocketAddressString() for AppleTalk addresses + * Uses GetModuleHandle() instead of LoadLibrary() where possible on Windows + * Disables tests for global blocks on Win64 due to broken compilers + * Adds PGP keys to verify tarballs and commits in the code repository + +ObjFW 1.0.3 -> ObjFW 1.0.4, 2023-10-08 + * Fixes OFFile closing fd 0 when initialization fails + * Fixes -[stringByAppendingPathComponent:] on empty strings + * Fixes +[OFSystemInfo operatingSystemName] and + +[OFSystemInfo operatingSystemVersion] returning nil on some systems + * Adds a license for localizations + +ObjFW 1.0.2 -> ObjFW 1.0.3, 2023-09-14 + * Fixes -[OFConcreteData initWithItemSize:] not setting freeWhenDone to true, + which resulted in a memory leak + * Fixes -[OFData initWithContentsOfIRI:] freeing the buffer in @catch instead + of @finally, which resulted in a memory leak + +ObjFW 1.0.1 -> ObjFW 1.0.2, 2023-09-11 + * The build system has been updated to fix building .frameworks and to build + them differently for macOS and iOS + +ObjFW 1.0 -> ObjFW 1.0.1, 2023-09-10 + * Hanging connections with OFTLSStream have been fixed when using OpenSSL + * The same fix as for OpenSSL has been applied to GnuTLS and SecureTransport + out of caution, even though there have been no hangs in practice + * The build system has been updated to fix building .frameworks among other + minor changes + * Some headers have been changed to fix compatibility with ObjC++ + * Warnings about empty .o files on x86_64 Darwin have been fixed + * The OFDate documentation has been improved to list supported formats + +ObjFW 0.90.2 -> ObjFW 1.0, 2023-08-29 + + First stable release with stable API and ABI + * Too many changes to list, as it has been almost 6 years since the last + release. See commits in the repository for details. + +ObjFW 0.90.1 -> ObjFW 0.90.2, 2017-10-23 * Fix shadowed variables which caused many bugs (e.g. using the wrong object) * Many, many nullability fixes * OFTCPSocket: Fix exception not being retained for async connect * OFThread: Fix setting the name on the wrong thread * OFMutableSet: Fix missing override for -[copy] @@ -13,11 +53,11 @@ * configure: Fix posix_spawnp check * Xcode project: Set the correct version for the bridge * Better check for iOS * tests: Fix testing the wrong OFKernelEventObserver -ObjFW 0.90 -> ObjFW 0.90.1, 20.08.2017 +ObjFW 0.90 -> ObjFW 0.90.1, 2017-08-20 * OFData: Fix -[description] * OFFileManager: Set errno to 0 before readdir() * OFDate: Add -[localMinute] * OFTarArchiveEntry: Fix prefix handling for ustar * OFZIPArchive: Fix uncompressed + data descriptor @@ -26,11 +66,11 @@ * OFGZIPStream: Add missing documentation * Fix a linker warning on OpenBSD/SPARC64 * Remove the OFFile b modes from MorphOS (they were already removed for all other OSes) -ObjFW 0.8.1 -> ObjFW 0.90, 01.08.2017 +ObjFW 0.8.1 -> ObjFW 0.90, 2017-08-01 + New classes: OFFileManager, OFGZIPStream, OFTarArchive, OFTarArchiveEntry OFHMAC, OFSandbox, OFHTTPCookie, OFHTTPCookieManager, OFLocalization + New platforms: Nintendo 3DS, MorphOS + New lookup assembly for platforms: SPARC64/ELF, ARM64/ELF @@ -58,11 +98,11 @@ + scrypt + Xcode project to build for iOS + String decomposition to NFD * OFFile modes simplified ('b' removed) -ObjFW 0.8 -> ObjFW 0.8.1, 04.10.2015 +ObjFW 0.8 -> ObjFW 0.8.1, 2015-10-04 * Adjust to __nullable / __nonnull being changed to _Nullable / _Nonnull in Clang 3.7 (this fixes compilation with Clang 3.7) * Blocks: Proper handling when called from a byref handler * Fix compilation on Solaris * Fix compilation for Wii, PSP and Nintendo DS @@ -72,11 +112,11 @@ * Special cases for the Wii's weird network stack (fixes the tests) * Better length checks for write / send calls * Don't use -pedantic on platforms where it's broken by the system headers * Documentation fixes -ObjFW 0.7.1 -> ObjFW 0.8, 14.08.2015 +ObjFW 0.7.1 -> ObjFW 0.8, 2015-08-14 + An insanely huge amount of new APIs + New classes: OFHTTPServer, OFINICategory, OFINIFile, OFInflate64Stream, OFInflateStream, OFMapTable, OFRIPEMD160Hash, OFSHA224Hash, OFSHA256Hash, OFSHA384Hash, OFSHA512Hash, OFSettings, OFStdIOStream, OFSystemInfo, @@ -121,20 +161,20 @@ * Rewritten OFMD5Hash and OFSHA1Hash * Reworked OFTLSSocket API (easier verification) * Unicode support updated to Unicode 8.0 * OFURL: Proper escaping and unescaping -ObjFW 0.7 -> ObjFW 0.7.1, 12.11.2012 +ObjFW 0.7 -> ObjFW 0.7.1, 2012-11-12 + Support for Haiku * Autorelease pools now work properly without __thread * Incorrect framework version in Xcode project fixed * Documentation fixes and improvements * Blocks now only use 16 bits for the reference count in order to avoid problems with newer Clang versions * More use of OF_SENTINEL -ObjFW 0.6 -> ObjFW 0.7, 27.10.2012 +ObjFW 0.6 -> ObjFW 0.7, 2012-10-27 Again, the differences are more than in any release before, thus listing them all would be too much. The major differences are: + ObjFW now comes with its own runtime, which greatly increases performance compared to the GNU runtime and is even faster than the Apple runtime (using Clang >= 3.2 is recommended, but not necessary) @@ -154,11 +194,11 @@ * All private methods use the prefix OF_ now instead of _, making it possible to use the _ prefix in applications * Most ObjC compiler feature checks are not part of configure anymore, making it possible to use the same installation with different compilers -ObjFW 0.5.4 -> ObjFW 0.6, 27.02.2012 +ObjFW 0.5.4 -> ObjFW 0.6, 2012-02-27 The differences between 0.5.4 and 0.6 are too big to list them all. However, the major new features are: * OFString, OFArray, OFDictionary, OFSet and OFCountedSet are now class clusters + Serialization and deserialization of objects into/from XML and JSON @@ -170,38 +210,38 @@ + There are several backends for OFStreamObserver now, including kqueue, poll and select + SOCKS5 support for OFTCPSockets (client only) * Several API changes -ObjFW 0.5.3 -> ObjFW 0.5.4, 30.08.2011 +ObjFW 0.5.3 -> ObjFW 0.5.4, 2011-08-30 * The blocks runtime is now working correctly * Documentation fixes * -framework works with objfw-compile now + Support for QNX * Various small fixes -ObjFW 0.5.2 -> ObjFW 0.5.3, 01.07.2011 +ObjFW 0.5.2 -> ObjFW 0.5.3, 2011-07-01 * Lots of bugfixes, see Git log for details -ObjFW 0.5.1 -> ObjFW 0.5.2, 25.04.2011 +ObjFW 0.5.1 -> ObjFW 0.5.2, 2011-04-25 * Fix double-retain in OFList * Don't ignore the timeout in OFStreamObserver when using select() * Do -[OFURL copy] in a try block to prevent a leak when an exception occurs * Fix too big buffer in -[OFMutableString _applyTable:withSize:] * Call madvise() on the correct length variable so it covers the whole string * Fix a warning when sizeof(size_t) < sizeof(long long) * Skip possible BOMs when appending strings -ObjFW 0.5 -> ObjFW 0.5.1, 21.04.2011 +ObjFW 0.5 -> ObjFW 0.5.1, 2011-04-21 * Work around a wrong warning produced by Apple GCC 4.0.1 which would cause the build to fail due to -Werror * Call objc_thread_{add,remove} when using the GNU runtime to make sure the runtime knows about our thread * Detach a thread before restarting if it was never joined * Release the old return value when restarting a thread -ObjFW 0.4-alpha1 -> 0.5, 09.04.2011 +ObjFW 0.4-alpha1 -> 0.5, 2011-04-09 + %@ is now allowed in format strings + Added of_log for easy logging * Exceptions have one header per exception now * Lots of exception improvements * Huge improvements in XML handling @@ -217,11 +257,11 @@ + Support for Base64 + Use a real Xcode project instead of just calling make + Add Haiku to the list of supported platforms * Lots of small bugfixes and countless small changes. Read the commits! -ObjFW 0.3.1 -> 0.4-alpha1, 03.01.2011 +ObjFW 0.3.1 -> 0.4-alpha1, 2011-01-03 * ObjFW is now available under the terms of the QPL, GPLv2 and GPLv3 + Support for blocks was added, including a blocks runtime + Added support for the new GNU runtime, introduced in GCC 4.6 * Objects returned from collections are no longer retained and autoreleased + Added new classes OFXMLParser, OFXMLElement, OFXMLAttribute and @@ -236,20 +276,20 @@ * objfw-compile now has a new syntax + objfw-compile can now compile libraries and plugins * Many small changes and new features that would be too much to list here The diff between 0.3.1 and 0.4-alpha1 has almost 24000 lines! -ObjFW 0.3 -> 0.3.1, 19.06.2010 +ObjFW 0.3 -> 0.3.1, 2010-06-19 * Fix a typo in OFMutableDictionary that prevented termination in case the last bucket is already used when the dictionary is resized * The mutations pointer is now correctly initialized in enumerators for immutable collections * The objc_sync test was still using the old threads API and was updated to use the new one now * PLATFORMS has been updated to be more specific -ObjFW 0.2.1 -> 0.3, 09.05.2010 +ObjFW 0.2.1 -> 0.3, 2010-05-09 + Many new methods were added to different classes + A huge amount of methods was added to OFStream, allowing easy binary stream handling and even mixing string-based and binary operations + An optional write buffer was added to OFStream + OFSeekableStream was added for streams that allow seeking, for example @@ -286,19 +326,19 @@ by the compiler + The library version is now included in the resulting dylib and libobjc is reexported now. Additionally, objfw-config offers --reexport now to produce libraries that link against ObjFW and reexport it -ObjFW 0.2 -> 0.2.1, 14.03.2010 +ObjFW 0.2 -> 0.2.1, 2010-03-14 * Fix for OFNumbers not doing calculations * Improved -[hash] for OFNumbers with floats and doubles + Tests for OFNumber * Small optimization for OFArray's -[componentsJoinedByString:] * Documentation improvements * Updated copyright -ObjFW 0.1.2 -> 0.2, 01.02.2010 +ObjFW 0.1.2 -> 0.2, 2010-02-01 + Support for ObjC 2 Fast Enumerations on every platform which has compiler support for fast enumerations + Support for ObjC 2 properties on every platform with compiler support + Fast Enumeration through arrays and dictionaries * OFIterator has been removed @@ -323,17 +363,17 @@ * File methods unavailable on Windows don't throw an exception at runtime anymore, but instead are not even in the interface on Windows. This way, it is a compile time error instead of a runtime error -ObjFW 0.1.1 -> 0.1.2, 15.01.2010 +ObjFW 0.1.1 -> 0.1.2, 2010-01-15 * Fix a bug in OFMutableArray's -[removeObject:] and -[removeObjectIdenticalTo:] that could lead to not removing all occurrences of the object from the array and to out of bounds reads * Change the URL in the framework plist to the homepage -ObjFW 0.1 -> 0.1.1, 04.01.2010 +ObjFW 0.1 -> 0.1.1, 2010-01-04 * Fix a missing out of range check for -[removeNItems:atIndex:] that allowed the programmer to specify too big ranges so it would crash instead of throwing an exception * Fix missing calls to -[retain] and -[autorelease] when getting objects from an OFArray or OFDictionary @@ -344,7 +384,7 @@ this is a serious programmer error * -[readLineWithEncoding:] is more fault-tolerant now and does not lose data when it stumbles upon invalid encoding. Instead, it allows recalling with the correct encoding now -ObjFW 0.1, 24.12.2009 +ObjFW 0.1, 2009-12-24 + Initial release Index: Doxyfile ================================================================== --- Doxyfile +++ Doxyfile @@ -6,37 +6,46 @@ HAVE_DOT = NO GENERATE_LATEX = NO HIDE_UNDOC_CLASSES = YES HIDE_UNDOC_MEMBERS = YES TYPEDEF_HIDES_STRUCT = YES -PREDEFINED = __OBJC__ \ - _Nonnull= \ - _Nullable= \ - DOXYGEN \ - OF_BOXABLE= \ - OF_CONSUMED= \ - OF_DESIGNATED_INITIALIZER= \ - OF_GENERIC(...)= \ - OF_HAVE_BLOCKS \ - OF_HAVE_FILES \ - OF_HAVE_SANDBOX \ - OF_HAVE_SOCKETS \ - OF_HAVE_THREADS \ - OF_KINDOF(...)= \ - OF_NO_RETURN= \ - OF_NO_RETURN_FUNC= \ - OF_NULLABLE_PROPERTY(...)= \ - OF_NULL_RESETTABLE_PROPERTY(...)= \ - OF_REQUIRES_SUPER= \ - OF_RETURNS_INNER_POINTER= \ - OF_RETURNS_NOT_RETAINED= \ - OF_RETURNS_RETAINED= \ - OF_ROOT_CLASS= \ - OF_SENTINEL= \ - OF_WARN_UNUSED_RESULT= \ - OF_WEAK_UNAVAILABLE= \ - SIGHUP \ - SIGUSR1 \ +PREDEFINED = _Nonnull= \ + _Nullable= \ + DOXYGEN \ + OF_BOXABLE= \ + OF_CONSUMED= \ + OF_DESIGNATED_INITIALIZER= \ + OF_FILE_MANAGER_SUPPORTS_EXTENDED_ATTRIBUTES \ + OF_FILE_MANAGER_SUPPORTS_LINKS \ + OF_FILE_MANAGER_SUPPORTS_OWNER \ + OF_FILE_MANAGER_SUPPORTS_PERMISSIONS \ + OF_FILE_MANAGER_SUPPORTS_SYMLINKS \ + OF_GENERIC(...)= \ + OF_HAVE_APPLETALK \ + OF_HAVE_BLOCKS \ + OF_HAVE_FILES \ + OF_HAVE_IPV6 \ + OF_HAVE_IPX \ + OF_HAVE_PLUGINS \ + OF_HAVE_SANDBOX \ + OF_HAVE_SOCKETS \ + OF_HAVE_THREADS \ + OF_HAVE_UNICODE_TABLES \ + OF_KINDOF(...)= \ + OF_NO_RETURN= \ + OF_NO_RETURN_FUNC= \ + OF_NULLABLE_PROPERTY(...)= \ + OF_NULL_RESETTABLE_PROPERTY(...)= \ + OF_REQUIRES_SUPER= \ + OF_RETURNS_INNER_POINTER= \ + OF_RETURNS_NOT_RETAINED= \ + OF_RETURNS_RETAINED= \ + OF_ROOT_CLASS= \ + OF_SENTINEL= \ + OF_WARN_UNUSED_RESULT= \ + OF_WEAK_UNAVAILABLE= \ + SIGHUP \ + SIGUSR1 \ SIGUSR2 MACRO_EXPANSION = YES EXPAND_ONLY_PREDEF = YES IGNORE_PREFIX = OF of_ Index: Makefile ================================================================== --- Makefile +++ Makefile @@ -10,11 +10,11 @@ config.status \ extra.mk include buildsys.mk -.PHONY: docs release +.PHONY: check docs release utils tests: src check: tests cd tests && ${MAKE} -s run @@ -33,13 +33,10 @@ ofarc -cq objfw-${PACKAGE_VERSION}.tar objfw-${PACKAGE_VERSION} rm -fr objfw-${PACKAGE_VERSION} gzip -9 objfw-${PACKAGE_VERSION}.tar rm -f objfw-${PACKAGE_VERSION}.tar gpg -b objfw-${PACKAGE_VERSION}.tar.gz || true - echo "Generating documentation..." - rm -fr docs - doxygen >/dev/null rm -fr objfw-docs-${PACKAGE_VERSION} objfw-docs-${PACKAGE_VERSION}.tar \ objfw-docs-${PACKAGE_VERSION}.tar.gz mv docs objfw-docs-${PACKAGE_VERSION} echo "Generating docs tarball for version ${PACKAGE_VERSION}..." ofarc -cq objfw-docs-${PACKAGE_VERSION}.tar \ Index: PLATFORMS.md ================================================================== --- PLATFORMS.md +++ PLATFORMS.md @@ -43,23 +43,32 @@ DragonFlyBSD ------------ * OS Versions: 3.0, 3.3-DEVELOPMENT - * Architectures: x86, x86_64 + * Architectures: AMD64, x86 * Compilers: GCC 4.4.7 * Runtimes: ObjFW FreeBSD ------- * OS Versions: 9.1-rc3, 10.0 - * Architectures: x86_64 + * Architectures: AMD64 * Compilers: Clang 3.1, Clang 3.3 * Runtimes: ObjFW + +GNU/Hurd +-------- + + * OS Versions: 0.9 + * Architectures: i686 + * Compilers: Clang 14.0.6 + * Runtimes: ObjFW + Haiku ----- * OS version: r1-alpha4 @@ -69,11 +78,11 @@ HP-UX ----- - * OS versions: 11i v1 (PA-RISC 2.0), 11i v3 (Itanium) + * OS versions: 11i v1, 11i v3 * Architectures: Itanium, PA-RISC 2.0 * Compilers: GCC 4.7.2, GCC 7.5.0 * Runtimes: ObjFW * Notes: Exception handling on Itanium in 32 bit mode is broken, you need to use 64 bit mode by passing `OBJC="gcc -mlp64"` to `configure`. @@ -88,22 +97,22 @@ Linux ----- - * Architectures: Alpha, ARMv6, ARMv7, ARM64, Itanium, m68k, MIPS (O32), - MIPS64 (N64), RISC-V 64, PowerPC, S390x, SuperH-4, x86, - x86_64 + * Architectures: Alpha, AMD64, ARMv6, ARMv7, ARM64, Itanium, m68k, MIPS (O32), + MIPS64 (N64), RISC-V 64, PowerPC, S390x, SuperH-4, x86 * Compilers: Clang 3.0-10.0, GCC 4.6-10.0 + * C libraries: glibc, musl * Runtimes: ObjFW macOS ----- * OS Versions: 10.5, 10.7-10.15, Darling - * Architectures: PowerPC, PowerPC64, x86, x86_64 + * Architectures: AMD64, PowerPC, PowerPC64, x86 * Compilers: Clang 3.1-10.0, Apple GCC 4.0.1 & 4.2.1 * Runtimes: Apple, ObjFW MiNT @@ -127,12 +136,12 @@ NetBSD ------ * OS Versions: 5.1-9.0 - * Architectures: ARM, ARM (big endian, BE8 mode), MIPS (O32), PowerPC, SPARC, - SPARC64, x86, x86_64 + * Architectures: AMD64, ARM, ARM (big endian, BE8 mode), MIPS (O32), PowerPC, + SPARC, SPARC64, x86 * Compilers: Clang 3.0-3.2, GCC 4.1.3 & 4.5.3 & 7.4.0 * Runtimes: ObjFW Nintendo 3DS @@ -167,11 +176,11 @@ OpenBSD ------- * OS Versions: 5.2-6.7 - * Architectures: MIPS64, PA-RISC, PowerPC, SPARC64, x86_64 + * Architectures: AMD64, MIPS64, PA-RISC, PowerPC, SPARC64 * Compilers: GCC 6.3.0, Clang 4.0 * Runtimes: ObjFW PlayStation Portable @@ -194,13 +203,13 @@ Solaris ------- - * OS Versions: OpenIndiana 2015.03 - * Architectures: x86, x86_64 - * Compilers: Clang 3.4.2, GCC 4.8.3 + * OS Versions: OpenIndiana 2015.03, OpenIndiana 2023.04, Oracle Solaris 11.4 + * Architectures: AMD64, x86 + * Compilers: Clang 3.4.2, Clang 11.0.0, Clang 13.0.1, GCC 4.8.3, GCC 10.4.0 * Runtimes: ObjFW Wii --- @@ -224,16 +233,15 @@ Windows ------- - * OS Versions: 98 SE, NT 4.0, XP (x86), 7 (x64), 8 (x64), 8.1 (x64), 10, 11, - Wine (x86 & x64) - * Architectures: x86, x86_64, AArch64 - * Compilers: GCC 5.3.0 & 6.2.0 from msys2 (x86 & x64), + * OS Versions: 98 SE, NT 4.0, XP, 7, 8, 8.1, 10, 11, Wine + * Architectures: AArch64, AMD64, x86 + * Compilers: GCC 5.3.0 & 6.2.0 from msys2 (AMD64 & x86), Clang 3.9.0 from msys2 (x86), - Clang 10.0 from msys2 (x86 & x86_64), + Clang 10.0 from msys2 (AMD64 & x86), Clang 14.0.4 from msys2 (AArch64) * Runtimes: ObjFW Others @@ -254,16 +262,16 @@ As forwarding needs hand-written assembly for each combination of CPU architecture, executable format and calling convention, it is only available for the following platforms (except resolveClassMethod: and resolveInstanceMethod:, which are always available): + * AMD64 (SysV/ELF, Apple/Mach-O, Mach-O, Win64/PE) * ARM (EABI/ELF, Apple/Mach-O) * ARM64 (ARM64/ELF, Apple/Mach-O) * MIPS (O32/ELF, EABI/ELF) * PowerPC (SysV/ELF, EABI/ELF, Apple/Mach-O) * SPARC (SysV/ELF) * SPARC64 (SysV/ELF) * x86 (SysV/ELF, Apple/Mach-O, Win32/PE) - * x86_64 (SysV/ELF, Apple/Mach-O, Mach-O, Win64/PE) Apple/Mach-O means both, the Apple ABI and runtime, while Mach-O means the ObjFW runtime on Mach-O. Index: README.md ================================================================== --- README.md +++ README.md @@ -9,14 +9,15 @@

Table of Contents

* [What is ObjFW?](#what) + * [Installation](#installation) * [License](#license) * [Releases](#releases) * [Cloning the repository](#cloning) - * [Installation](#installation) + * [Building from source](#building-from-source) * [macOS and iOS](#macos-and-ios) * [Building as a framework](#building-framework) * [Using the macOS or iOS framework in Xcode](#framework-in-xcode) * [Broken Xcode versions](#broken-xcode-versions) * [Windows](#windows) @@ -52,11 +53,11 @@ * GNUstep already provides a reimplementation of Foundation, which is only compatible to a certain degree. This means that a developer still needs to care about differences between frameworks if they want to be portable. The idea behind ObjFW is that a developer does not need to concern themselves - with portablility and making sure their code works with multiple + with portability and making sure their code works with multiple frameworks: Instead, if it works it ObjFW on one platform, they can reasonably expect it to also work with ObjFW on another platform. ObjFW behaving differently on different operating systems (unless inevitable because it is a platform-specific part, like the Windows Registry) is considered a bug and will be fixed. @@ -72,10 +73,36 @@ ObjFW also comes with its own lightweight and extremely fast Objective-C runtime, which in real world use cases was found to be significantly faster than both GNU's and Apple's runtime. + +

Installation

+ + ObjFW packages are available for various operating systems and can be + installed as following: + + Operating System | Command + ---------------------------|--------------------------------------------- + Alpine Linux | `doas apk add objfw` + CRUX | `sudo prt-get depinst objfw` + Fedora | `sudo dnf install objfw` + FreeBSD | `sudo pkg install objfw` + Haiku | `pkgman install objfw` + Haiku (gcc2h) | `pkgman install objfw_x86` + macOS (Homebrew) | `brew install objfw` + macOS (pkgsrc) | `cd $PKGSRCDIR/devel/objfw && make install` + NetBSD | `cd /usr/pkgsrc/devel/objfw && make install` + OpenBSD | `doas pkg_add objfw` + OpenIndiana | `sudo pkg install developer/objfw` + Windows (MSYS2/MINGW32) | `pacman -S mingw-w64-i686-objfw` + Windows (MSYS2/CLANG64) | `pacman -S mingw-w64-clang-x86_64-objfw` + Windows (MSYS2/CLANGARM64) | `pacman -S mingw-w64-clang-aarch64-objfw` + + If your operating system is not listed, you can + build ObjFW from source. +

License

ObjFW is released under three licenses: @@ -91,11 +118,11 @@ none of them work for you, contact me and we can find a solution.

Releases

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

Cloning the repository

@@ -115,14 +142,10 @@ wiki pages, etc.: $ cd objfw $ fossil ui - It's also possible to open the same local repository multiple times, so that - you have multiple working directories all backed by the same local - repository. - In order to verify the signature of the currently checked out checkin, you can use: $ fossil artifact current | gpg --verify @@ -139,13 +162,13 @@ $ git clone https://github.com/ObjFW/ObjFW Git commits are not signed, so if you want to check the signature of an individual commit, branch head or tag, please use Fossil. -

Installation

+

Building from source

- To install ObjFW, just run the following commands: + To build ObjFW from source and install it, just run the following commands: $ ./configure $ make $ make check $ sudo make install @@ -162,29 +185,28 @@ When building for macOS or iOS, everything is built as a `.framework` by default if `--disable-shared` has not been specified to `./configure`. The frameworks will end up in `$PREFIX/Library/Frameworks`. To build for macOS, just follow the - regular instructions above. + 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" + $ clang="xcrun --sdk iphoneos clang" + $ export OBJC="$clang -arch arm64e -arch arm64" + $ export OBJCPP="$clang -arch arm64e -E" + $ export IPHONEOS_DEPLOYMENT_TARGET="10.0" $ ./configure --prefix=/usr/local/ios --host=arm64-apple-darwin To build for the iOS simulator, follow the regular instructions, but instead of `./configure` use something like this: - $ clang="clang -isysroot $(xcrun --sdk iphonesimulator --show-sdk-path)" - $ export OBJC="$clang -arch arm64 -arch x86_64" - $ export OBJCPP="$clang -arch arm64 -E" - $ export IPHONEOS_DEPLOYMENT_TARGET="9.0" - $ ./configure --prefix=/usr/local/iossim --host=arm64-apple-darwin + $ clang="xcrun --sdk iphonesimulator clang" + $ export OBJC="$clang -arch $(uname -m)" + $ export IPHONEOS_DEPLOYMENT_TARGET="10.0" + $ ./configure --prefix=/usr/local/iossim --host=$(uname -m)-apple-darwin

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`: @@ -321,11 +343,11 @@ To create your first, empty application, you can use `objfw-new`: $ objfw-new --app MyFirstApp - This creates a file `MyFirstApp.m`. The `-[applicationDidFinishLaunching]` + This creates a file `MyFirstApp.m`. The `-[applicationDidFinishLaunching:]` method is called as soon as ObjFW finished all initialization. Use this as the entry point to your own code. For example, you could add the following line there to create a "Hello World": [OFStdOut writeLine: @"Hello World!"]; @@ -366,20 +388,18 @@ If you have any questions about ObjFW or would like to talk to other ObjFW users, the following venues are available: * The [forum](https://objfw.nil.im/forum) * A [Matrix room](https://matrix.to/#/%23objfw:nil.im) + * A [Discord room](https://objfw.nil.im/discord), bridged to the Matrix + room above + * A [Telegram room](https://t.me/objfw), bridged to the Matrix room above + * A [Slack room](https://objfw.nil.im/slack), bridged to the Matrix room + above * An IRC channel named `#objfw` on `irc.oftc.net` ([Web chat](https://webchat.oftc.net/?channels=%23objfw)), bridged to the Matrix room above - * A [Slack channel](https://objfw.nil.im/slack), bridged to the Matrix room - above - * A [Discord channel](https://objfw.nil.im/discord), bridged to the Matrix - room above - * A [Telegram room](https://t.me/objfw), bridged to the Matrix room above - * A [Gitter room](https://gitter.im/ObjFW/ObjFW), bridged to the Matrix room - above Please don't hesitate to join any or all of those!

Donating

@@ -392,14 +412,14 @@ * 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! + Mini to the project in 2022!

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: autogen.sh ================================================================== --- autogen.sh +++ autogen.sh @@ -1,11 +1,13 @@ #!/bin/sh set -e # Set a version for OpenBSD -: ${AUTOCONF_VERSION:=2.69} -: ${AUTOMAKE_VERSION:=1.16} -export AUTOCONF_VERSION AUTOMAKE_VERSION +if test x"$(uname -s)" = x"OpenBSD"; then + : ${AUTOCONF_VERSION:=2.71} + : ${AUTOMAKE_VERSION:=1.16} + export AUTOCONF_VERSION AUTOMAKE_VERSION +fi aclocal -I build-aux/m4 autoconf autoheader Index: build-aux/m4/buildsys.m4 ================================================================== --- build-aux/m4/buildsys.m4 +++ build-aux/m4/buildsys.m4 @@ -1,8 +1,8 @@ dnl dnl Copyright (c) 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2016, 2017, -dnl 2018, 2020, 2021 +dnl 2018, 2020, 2021, 2022, 2023 dnl Jonathan Schleifer dnl dnl https://fossil.nil.im/buildsys dnl dnl Permission to use, copy, modify, and/or distribute this software for any @@ -27,10 +27,14 @@ AC_REQUIRE([AC_CANONICAL_HOST]) AC_ARG_ENABLE(rpath, AS_HELP_STRING([--disable-rpath], [do not use rpath])) + AC_ARG_ENABLE(silent-rules, + AS_HELP_STRING([--disable-silent-rules], + [print executed commands during build])) + case "$build_os" in darwin*) case "$host_os" in darwin*) AC_SUBST(BUILD_AND_HOST_ARE_DARWIN, yes) @@ -125,10 +129,15 @@ "$($TPUT AF 4 2>/dev/null)") AC_SUBST(TERM_SETAF6, "$($TPUT AF 6 2>/dev/null)") fi ]) + + AS_IF([test x"$enable_silent_rules" != x"no"], [ + AC_SUBST(SILENT, '.SILENT:') + AC_SUBST(MAKEFLAGS_SILENT, '-s') + ]) ]) ]) AC_DEFUN([BUILDSYS_CHECK_IOS], [ case "$host_os" in @@ -142,14 +151,16 @@ TARGET_OS_SIMULATOR) yes #endif ], [ host_is_ios="yes" + AC_SUBST(HOST_IS_IOS, yes) ], [ host_is_ios="no" ]) AC_MSG_RESULT($host_is_ios) + AC_CHECK_TOOL(CODESIGN, codesign) ;; esac ]) AC_DEFUN([BUILDSYS_PROG_IMPLIB], [ @@ -173,11 +184,11 @@ ]) AC_DEFUN([BUILDSYS_SHARED_LIB], [ AC_REQUIRE([AC_CANONICAL_HOST]) AC_REQUIRE([BUILDSYS_CHECK_IOS]) - AC_MSG_CHECKING(for shared library system) + AC_MSG_CHECKING(for shared library type) case "$host" in *-*-darwin*) AC_MSG_RESULT(Darwin) LIB_CFLAGS='-fPIC -DPIC' @@ -186,22 +197,12 @@ LIB_PREFIX='lib' LIB_SUFFIX='.dylib' AS_IF([test x"$enable_rpath" != x"no"], [ LDFLAGS_RPATH='-Wl,-rpath,${libdir}' ]) - PLUGIN_CFLAGS='-fPIC -DPIC' - PLUGIN_LDFLAGS='-bundle ${PLUGIN_LDFLAGS_BUNDLE_LOADER}' - PLUGIN_SUFFIX='.bundle' - AS_IF([test x"$host_is_ios" = x"yes"], [ - LINK_PLUGIN='rm -fr $$out && ${MKDIR_P} $$out && if test -f Info.plist; then ${INSTALL} -m 644 Info.plist $$out/Info.plist; fi && ${LD} -o $$out/$${out%${PLUGIN_SUFFIX}} ${PLUGIN_OBJS} ${PLUGIN_OBJS_EXTRA} ${PLUGIN_LDFLAGS} ${LDFLAGS} ${LIBS} && ${CODESIGN} -fs ${CODESIGN_IDENTITY} --timestamp=none $$out' - ], [ - LINK_PLUGIN='rm -fr $$out && ${MKDIR_P} $$out/Contents/MacOS && if test -f Info.plist; then ${INSTALL} -m 644 Info.plist $$out/Contents/Info.plist; fi && ${LD} -o $$out/Contents/MacOS/$${out%${PLUGIN_SUFFIX}} ${PLUGIN_OBJS} ${PLUGIN_OBJS_EXTRA} ${PLUGIN_LDFLAGS} ${LDFLAGS} ${LIBS} && ${CODESIGN} -fs ${CODESIGN_IDENTITY} --timestamp=none $$out' - ]) INSTALL_LIB='&& ${INSTALL} -m 755 $$i ${DESTDIR}${libdir}/$${i%.dylib}.${LIB_MAJOR}.${LIB_MINOR}.dylib && ${LN_S} -f $${i%.dylib}.${LIB_MAJOR}.${LIB_MINOR}.dylib ${DESTDIR}${libdir}/$${i%.dylib}.${LIB_MAJOR}.dylib && ${LN_S} -f $${i%.dylib}.${LIB_MAJOR}.${LIB_MINOR}.dylib ${DESTDIR}${libdir}/$$i' UNINSTALL_LIB='&& rm -f ${DESTDIR}${libdir}/$$i ${DESTDIR}${libdir}/$${i%.dylib}.${LIB_MAJOR}.dylib ${DESTDIR}${libdir}/$${i%.dylib}.${LIB_MAJOR}.${LIB_MINOR}.dylib' - INSTALL_PLUGIN='&& rm -fr ${DESTDIR}${plugindir}/$$i && cp -R $$i ${DESTDIR}${plugindir}/' - UNINSTALL_PLUGIN='&& rm -fr ${DESTDIR}${plugindir}/$$i' CLEAN_LIB='' ;; *-*-mingw* | *-*-cygwin*) AC_MSG_RESULT(MinGW / Cygwin) LIB_CFLAGS='' @@ -208,18 +209,12 @@ LIB_LDFLAGS='-shared -Wl,--export-all-symbols' LIB_LDFLAGS_INSTALL_NAME='' LIB_PREFIX='' LIB_SUFFIX='${LIB_MAJOR}.dll' LINK_LIB='&& rm -f lib$${out%${LIB_SUFFIX}}.dll.a && ${LN_S} $$out lib$${out%${LIB_SUFFIX}}.dll.a' - PLUGIN_CFLAGS='' - PLUGIN_LDFLAGS='-shared -Wl,--export-all-symbols' - PLUGIN_SUFFIX='.dll' - LINK_PLUGIN='${LD} -o $$out ${PLUGIN_OBJS} ${PLUGIN_OBJS_EXTRA} ${PLUGIN_LDFLAGS} ${LDFLAGS} ${LIBS}' INSTALL_LIB='&& ${MKDIR_P} ${DESTDIR}${bindir} && ${INSTALL} -m 755 $$i ${DESTDIR}${bindir}/$$i && ${INSTALL} -m 755 lib$${i%${LIB_SUFFIX}}.dll.a ${DESTDIR}${libdir}/lib$${i%${LIB_SUFFIX}}.dll.a' UNINSTALL_LIB='&& rm -f ${DESTDIR}${bindir}/$$i ${DESTDIR}${libdir}/lib$${i%${LIB_SUFFIX}}.dll.a' - INSTALL_PLUGIN='&& ${INSTALL} -m 755 $$i ${DESTDIR}${plugindir}/$$i' - UNINSTALL_PLUGIN='&& rm -f ${DESTDIR}${plugindir}/$$i' CLEAN_LIB='${SHARED_LIB}.a ${SHARED_LIB_NOINST}.a' ;; *-*-openbsd* | *-*-mirbsd*) AC_MSG_RESULT(OpenBSD) LIB_CFLAGS='-fPIC -DPIC' @@ -228,18 +223,12 @@ LIB_PREFIX='lib' LIB_SUFFIX='.so.${LIB_MAJOR}.${LIB_MINOR}' AS_IF([test x"$enable_rpath" != x"no"], [ LDFLAGS_RPATH='-Wl,-rpath,${libdir}' ]) - PLUGIN_CFLAGS='-fPIC -DPIC' - PLUGIN_LDFLAGS='-shared' - PLUGIN_SUFFIX='.so' - LINK_PLUGIN='${LD} -o $$out ${PLUGIN_OBJS} ${PLUGIN_OBJS_EXTRA} ${PLUGIN_LDFLAGS} ${LDFLAGS} ${LIBS}' INSTALL_LIB='&& ${INSTALL} -m 755 $$i ${DESTDIR}${libdir}/$$i' UNINSTALL_LIB='&& rm -f ${DESTDIR}${libdir}/$$i' - INSTALL_PLUGIN='&& ${INSTALL} -m 755 $$i ${DESTDIR}${plugindir}/$$i' - UNINSTALL_PLUGIN='&& rm -f ${DESTDIR}${plugindir}/$$i' CLEAN_LIB='' ;; *-*-solaris*) AC_MSG_RESULT(Solaris) LIB_CFLAGS='-fPIC -DPIC' @@ -248,35 +237,23 @@ LIB_PREFIX='lib' LIB_SUFFIX='.so' AS_IF([test x"$enable_rpath" != x"no"], [ LDFLAGS_RPATH='-Wl,-rpath,${libdir}' ]) - PLUGIN_CFLAGS='-fPIC -DPIC' - PLUGIN_LDFLAGS='-shared' - PLUGIN_SUFFIX='.so' - LINK_PLUGIN='${LD} -o $$out ${PLUGIN_OBJS} ${PLUGIN_OBJS_EXTRA} ${PLUGIN_LDFLAGS} ${LDFLAGS} ${LIBS}' INSTALL_LIB='&& ${INSTALL} -m 755 $$i ${DESTDIR}${libdir}/$$i.${LIB_MAJOR}.${LIB_MINOR} && rm -f ${DESTDIR}${libdir}/$$i && ${LN_S} $$i.${LIB_MAJOR}.${LIB_MINOR} ${DESTDIR}${libdir}/$$i' UNINSTALL_LIB='&& rm -f ${DESTDIR}${libdir}/$$i ${DESTDIR}${libdir}/$$i.${LIB_MAJOR}.${LIB_MINOR}' - INSTALL_PLUGIN='&& ${INSTALL} -m 755 $$i ${DESTDIR}${plugindir}/$$i' - UNINSTALL_PLUGIN='&& rm -f ${DESTDIR}${plugindir}/$$i' CLEAN_LIB='' ;; *-*-android*) AC_MSG_RESULT(Android) LIB_CFLAGS='-fPIC -DPIC' LIB_LDFLAGS='-shared -Wl,-soname=$$out.${LIB_MAJOR}' LIB_LDFLAGS_INSTALL_NAME='' LIB_PREFIX='lib' LIB_SUFFIX='.so' - PLUGIN_CFLAGS='-fPIC -DPIC' - PLUGIN_LDFLAGS='-shared' - PLUGIN_SUFFIX='.so' - LINK_PLUGIN='${LD} -o $$out ${PLUGIN_OBJS} ${PLUGIN_OBJS_EXTRA} ${PLUGIN_LDFLAGS} ${LDFLAGS} ${LIBS}' - INSTALL_LIB='&& ${INSTALL} -m 755 $$i ${DESTDIR}${libdir}/$$i.${LIB_MAJOR}.${LIB_MINOR}.0 && ${LN_S} -f $$i.${LIB_MAJOR}.${LIB_MINOR}.0 ${DESTDIR}${libdir}/$$i.${LIB_MAJOR} && ${LN_S} -f $$i.${LIB_MAJOR}.${LIB_MINOR}.0 ${DESTDIR}${libdir}/$$i' - UNINSTALL_LIB='&& rm -f ${DESTDIR}${libdir}/$$i ${DESTDIR}${libdir}/$$i.${LIB_MAJOR} ${DESTDIR}${libdir}/$$i.${LIB_MAJOR}.${LIB_MINOR}.0' - INSTALL_PLUGIN='&& ${INSTALL} -m 755 $$i ${DESTDIR}${plugindir}/$$i' - UNINSTALL_PLUGIN='&& rm -f ${DESTDIR}${plugindir}/$$i' + INSTALL_LIB='&& ${INSTALL} -m 755 $$i ${DESTDIR}${libdir}/$$i.${LIB_MAJOR}.${LIB_MINOR}.${LIB_PATCH} && ${LN_S} -f $$i.${LIB_MAJOR}.${LIB_MINOR}.${LIB_PATCH} ${DESTDIR}${libdir}/$$i.${LIB_MAJOR} && ${LN_S} -f $$i.${LIB_MAJOR}.${LIB_MINOR}.${LIB_PATCH} ${DESTDIR}${libdir}/$$i' + UNINSTALL_LIB='&& rm -f ${DESTDIR}${libdir}/$$i ${DESTDIR}${libdir}/$$i.${LIB_MAJOR} ${DESTDIR}${libdir}/$$i.${LIB_MAJOR}.${LIB_MINOR}.${LIB_PATCH}' CLEAN_LIB='' ;; hppa*-*-hpux*) AC_MSG_RESULT([HP-UX (PA-RISC)]) LIB_CFLAGS='-fPIC -DPIC' @@ -286,18 +263,12 @@ LIB_SUFFIX='.${LIB_MAJOR}' LINK_LIB='&& rm -f $${out%%.*}.sl && ${LN_S} $$out $${out%%.*}.sl' AS_IF([test x"$enable_rpath" != x"no"], [ LDFLAGS_RPATH='-Wl,+b,${libdir}' ]) - PLUGIN_CFLAGS='-fPIC -DPIC' - PLUGIN_LDFLAGS='-shared' - PLUGIN_SUFFIX='.sl' - LINK_PLUGIN='${LD} -o $$out ${PLUGIN_OBJS} ${PLUGIN_OBJS_EXTRA} ${PLUGIN_LDFLAGS} ${LDFLAGS} ${LIBS}' INSTALL_LIB='&& ${INSTALL} -m 755 $$i ${DESTDIR}${libdir}/$$i && ${LN_S} -f $$i ${DESTDIR}${libdir}/$${i%%.*}.sl' UNINSTALL_LIB='&& rm -f ${DESTDIR}${libdir}/$$i ${DESTDIR}${libdir}/$${i%%.*}.sl' - INSTALL_PLUGIN='&& ${INSTALL} -m 755 $$i ${DESTDIR}${plugindir}/$$i' - UNINSTALL_PLUGIN='&& rm -f ${DESTDIR}${plugindir}/$$i' CLEAN_LIB='' ;; ia64*-*-hpux*) AC_MSG_RESULT([HP-UX (Itanium)]) LIB_CFLAGS='-fPIC -DPIC' @@ -307,18 +278,12 @@ LIB_SUFFIX='.${LIB_MAJOR}' LINK_LIB='&& rm -f $${out%%.*}.so && ${LN_S} $$out $${out%%.*}.so' AS_IF([test x"$enable_rpath" != x"no"], [ LDFLAGS_RPATH='-Wl,+b,${libdir}' ]) - PLUGIN_CFLAGS='-fPIC -DPIC' - PLUGIN_LDFLAGS='-shared' - PLUGIN_SUFFIX='.so' - LINK_PLUGIN='${LD} -o $$out ${PLUGIN_OBJS} ${PLUGIN_OBJS_EXTRA} ${PLUGIN_LDFLAGS} ${LDFLAGS} ${LIBS}' INSTALL_LIB='&& ${INSTALL} -m 755 $$i ${DESTDIR}${libdir}/$$i && ${LN_S} -f $$i ${DESTDIR}${libdir}/$${i%%.*}.so' UNINSTALL_LIB='&& rm -f ${DESTDIR}${libdir}/$$i ${DESTDIR}${libdir}/$${i%%.*}.so' - INSTALL_PLUGIN='&& ${INSTALL} -m 755 $$i ${DESTDIR}${plugindir}/$$i' - UNINSTALL_PLUGIN='&& rm -f ${DESTDIR}${plugindir}/$$i' CLEAN_LIB='' ;; *) AC_MSG_RESULT(ELF) LIB_CFLAGS='-fPIC -DPIC' @@ -327,18 +292,12 @@ LIB_PREFIX='lib' LIB_SUFFIX='.so' AS_IF([test x"$enable_rpath" != x"no"], [ LDFLAGS_RPATH='-Wl,-rpath,${libdir}' ]) - PLUGIN_CFLAGS='-fPIC -DPIC' - PLUGIN_LDFLAGS='-shared' - PLUGIN_SUFFIX='.so' - LINK_PLUGIN='${LD} -o $$out ${PLUGIN_OBJS} ${PLUGIN_OBJS_EXTRA} ${PLUGIN_LDFLAGS} ${LDFLAGS} ${LIBS}' - INSTALL_LIB='&& ${INSTALL} -m 755 $$i ${DESTDIR}${libdir}/$$i.${LIB_MAJOR}.${LIB_MINOR}.0 && ${LN_S} -f $$i.${LIB_MAJOR}.${LIB_MINOR}.0 ${DESTDIR}${libdir}/$$i.${LIB_MAJOR} && ${LN_S} -f $$i.${LIB_MAJOR}.${LIB_MINOR}.0 ${DESTDIR}${libdir}/$$i' - UNINSTALL_LIB='&& rm -f ${DESTDIR}${libdir}/$$i ${DESTDIR}${libdir}/$$i.${LIB_MAJOR} ${DESTDIR}${libdir}/$$i.${LIB_MAJOR}.${LIB_MINOR}.0' - INSTALL_PLUGIN='&& ${INSTALL} -m 755 $$i ${DESTDIR}${plugindir}/$$i' - UNINSTALL_PLUGIN='&& rm -f ${DESTDIR}${plugindir}/$$i' + INSTALL_LIB='&& ${INSTALL} -m 755 $$i ${DESTDIR}${libdir}/$$i.${LIB_MAJOR}.${LIB_MINOR}.${LIB_PATCH} && ${LN_S} -f $$i.${LIB_MAJOR}.${LIB_MINOR}.${LIB_PATCH} ${DESTDIR}${libdir}/$$i.${LIB_MAJOR} && ${LN_S} -f $$i.${LIB_MAJOR}.${LIB_MINOR}.${LIB_PATCH} ${DESTDIR}${libdir}/$$i' + UNINSTALL_LIB='&& rm -f ${DESTDIR}${libdir}/$$i ${DESTDIR}${libdir}/$$i.${LIB_MAJOR} ${DESTDIR}${libdir}/$$i.${LIB_MAJOR}.${LIB_MINOR}.${LIB_PATCH}' CLEAN_LIB='' ;; esac AC_SUBST(LIB_CFLAGS) @@ -346,35 +305,26 @@ AC_SUBST(LIB_LDFLAGS_INSTALL_NAME) AC_SUBST(LIB_PREFIX) AC_SUBST(LIB_SUFFIX) AC_SUBST(LINK_LIB) AC_SUBST(LDFLAGS_RPATH) - AC_SUBST(PLUGIN_CFLAGS) - AC_SUBST(PLUGIN_LDFLAGS) - AC_SUBST(PLUGIN_SUFFIX) - AC_SUBST(LINK_PLUGIN) AC_SUBST(INSTALL_LIB) AC_SUBST(UNINSTALL_LIB) - AC_SUBST(INSTALL_PLUGIN) - AC_SUBST(UNINSTALL_PLUGIN) AC_SUBST(CLEAN_LIB) ]) AC_DEFUN([BUILDSYS_FRAMEWORK], [ AC_REQUIRE([AC_CANONICAL_HOST]) AC_REQUIRE([BUILDSYS_CHECK_IOS]) AC_REQUIRE([BUILDSYS_SHARED_LIB]) - AC_CHECK_TOOL(CODESIGN, codesign) - case "$host_os" in darwin*) + FRAMEWORK_LDFLAGS='-dynamiclib -current_version ${LIB_MAJOR}.${LIB_MINOR} -compatibility_version ${LIB_MAJOR}' AS_IF([test x"$host_is_ios" = x"yes"], [ - FRAMEWORK_LDFLAGS='-dynamiclib -current_version ${LIB_MAJOR}.${LIB_MINOR} -compatibility_version ${LIB_MAJOR}' FRAMEWORK_LDFLAGS_INSTALL_NAME='-Wl,-install_name,@executable_path/Frameworks/$$out/$${out%.framework}' ], [ - FRAMEWORK_LDFLAGS='-dynamiclib -current_version ${LIB_MAJOR}.${LIB_MINOR} -compatibility_version ${LIB_MAJOR}' FRAMEWORK_LDFLAGS_INSTALL_NAME='-Wl,-install_name,@executable_path/../Frameworks/$$out/$${out%.framework}' ]) AC_SUBST(FRAMEWORK_LDFLAGS) AC_SUBST(FRAMEWORK_LDFLAGS_INSTALL_NAME) @@ -382,5 +332,61 @@ $1 ;; esac ]) + +AC_DEFUN([BUILDSYS_PLUGIN], [ + AC_REQUIRE([AC_CANONICAL_HOST]) + AC_REQUIRE([BUILDSYS_CHECK_IOS]) + AC_MSG_CHECKING(for plugin type) + + case "$host" in + *-*-darwin*) + AC_MSG_RESULT(Darwin) + PLUGIN_CFLAGS='-fPIC -DPIC' + PLUGIN_LDFLAGS='-bundle ${PLUGIN_LDFLAGS_BUNDLE_LOADER}' + PLUGIN_SUFFIX='.bundle' + AS_IF([test x"$host_is_ios" = x"yes"], [ + LINK_PLUGIN='rm -fr $$out && ${MKDIR_P} $$out && if test -f Info.plist; then ${INSTALL} -m 644 Info.plist $$out/Info.plist; fi && ${LD} -o $$out/$${out%${PLUGIN_SUFFIX}} ${PLUGIN_OBJS} ${PLUGIN_OBJS_EXTRA} ${PLUGIN_LDFLAGS} ${LDFLAGS} ${LIBS} && ${CODESIGN} -fs ${CODESIGN_IDENTITY} $$out' + ], [ + LINK_PLUGIN='rm -fr $$out && ${MKDIR_P} $$out/Contents/MacOS && if test -f Info.plist; then ${INSTALL} -m 644 Info.plist $$out/Contents/Info.plist; fi && ${LD} -o $$out/Contents/MacOS/$${out%${PLUGIN_SUFFIX}} ${PLUGIN_OBJS} ${PLUGIN_OBJS_EXTRA} ${PLUGIN_LDFLAGS} ${LDFLAGS} ${LIBS} && ${CODESIGN} -fs ${CODESIGN_IDENTITY} $$out' + ]) + INSTALL_PLUGIN='&& rm -fr ${DESTDIR}${plugindir}/$$i && cp -R $$i ${DESTDIR}${plugindir}/' + UNINSTALL_PLUGIN='&& rm -fr ${DESTDIR}${plugindir}/$$i' + ;; + *-*-mingw* | *-*-cygwin*) + AC_MSG_RESULT(MinGW / Cygwin) + PLUGIN_CFLAGS='' + PLUGIN_LDFLAGS='-shared -Wl,--export-all-symbols' + PLUGIN_SUFFIX='.dll' + LINK_PLUGIN='${LD} -o $$out ${PLUGIN_OBJS} ${PLUGIN_OBJS_EXTRA} ${PLUGIN_LDFLAGS} ${LDFLAGS} ${LIBS}' + INSTALL_PLUGIN='&& ${INSTALL} -m 755 $$i ${DESTDIR}${plugindir}/$$i' + UNINSTALL_PLUGIN='&& rm -f ${DESTDIR}${plugindir}/$$i' + ;; + hppa*-*-hpux*) + AC_MSG_RESULT([HP-UX (PA-RISC)]) + PLUGIN_CFLAGS='-fPIC -DPIC' + PLUGIN_LDFLAGS='-shared' + PLUGIN_SUFFIX='.sl' + LINK_PLUGIN='${LD} -o $$out ${PLUGIN_OBJS} ${PLUGIN_OBJS_EXTRA} ${PLUGIN_LDFLAGS} ${LDFLAGS} ${LIBS}' + INSTALL_PLUGIN='&& ${INSTALL} -m 755 $$i ${DESTDIR}${plugindir}/$$i' + UNINSTALL_PLUGIN='&& rm -f ${DESTDIR}${plugindir}/$$i' + ;; + *) + AC_MSG_RESULT(ELF) + PLUGIN_CFLAGS='-fPIC -DPIC' + PLUGIN_LDFLAGS='-shared' + PLUGIN_SUFFIX='.so' + LINK_PLUGIN='${LD} -o $$out ${PLUGIN_OBJS} ${PLUGIN_OBJS_EXTRA} ${PLUGIN_LDFLAGS} ${LDFLAGS} ${LIBS}' + INSTALL_PLUGIN='&& ${INSTALL} -m 755 $$i ${DESTDIR}${plugindir}/$$i' + UNINSTALL_PLUGIN='&& rm -f ${DESTDIR}${plugindir}/$$i' + ;; + esac + + AC_SUBST(PLUGIN_CFLAGS) + AC_SUBST(PLUGIN_LDFLAGS) + AC_SUBST(PLUGIN_SUFFIX) + AC_SUBST(LINK_PLUGIN) + AC_SUBST(INSTALL_PLUGIN) + AC_SUBST(UNINSTALL_PLUGIN) +]) Index: buildsys.mk.in ================================================================== --- buildsys.mk.in +++ buildsys.mk.in @@ -1,8 +1,8 @@ # # Copyright (c) 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, -# 2017, 2018, 2020, 2021 +# 2017, 2018, 2020, 2021, 2022, 2023 # Jonathan Schleifer # # https://fossil.nil.im/buildsys # # Permission to use, copy, modify, and/or distribute this software for any @@ -121,32 +121,44 @@ ${AMIGA_LIB_OBJS:.o=.dep} \ ${PLUGIN_OBJS:.o=.dep} MO_FILES = ${LOCALES:.po=.mo} -.SILENT: +@SILENT@ .SUFFIXES: -.SUFFIXES: .amigalib.o .beam .c .cc .class .cxx .d .erl .lib.o .java .mo .m .mm .o .plugin.o .po .py .pyc .rc .S .xpm -.PHONY: all subdirs subdirs-after pre-depend depend install install-extra uninstall uninstall-extra clean distclean locales copy-headers-into-framework ${SUBDIRS} ${SUBDIRS_AFTER} +.SUFFIXES: .amigalib.o .beam .c .cc .class .cxx .d .erl .lib.o .java \ + .mo .m .mm .o .plugin.o .po .py .pyc .rc .S .xpm +.PHONY: all subdirs subdirs-after pre-depend depend install \ + install-extra uninstall uninstall-extra clean distclean locales \ + copy-headers-into-framework ${SUBDIRS} ${SUBDIRS_AFTER} all: - ${MAKE} -s pre-all - ${MAKE} -s subdirs - ${MAKE} -s depend - ${MAKE} -s ${STATIC_LIB} ${STATIC_LIB_NOINST} ${STATIC_PIC_LIB} ${STATIC_PIC_LIB_NOINST} ${STATIC_AMIGA_LIB} ${STATIC_AMIGA_LIB_NOINST} ${SHARED_LIB} ${SHARED_LIB_NOINST} ${FRAMEWORK} ${FRAMEWORK_NOINST} ${AMIGA_LIB} ${AMIGA_LIB_NOINST} ${PLUGIN} ${PLUGIN_NOINST} ${PROG} ${PROG_NOINST} ${JARFILE} locales - ${MAKE} -s subdirs-after - ${MAKE} -s post-all + ${MAKE} @MAKEFLAGS_SILENT@ pre-all + ${MAKE} @MAKEFLAGS_SILENT@ subdirs + ${MAKE} @MAKEFLAGS_SILENT@ depend + ${MAKE} @MAKEFLAGS_SILENT@ \ + ${STATIC_LIB} ${STATIC_LIB_NOINST} \ + ${STATIC_PIC_LIB} ${STATIC_PIC_LIB_NOINST} \ + ${STATIC_AMIGA_LIB}${STATIC_AMIGA_LIB_NOINST} \ + ${SHARED_LIB} ${SHARED_LIB_NOINST} \ + ${FRAMEWORK} ${FRAMEWORK_NOINST} \ + ${AMIGA_LIB} ${AMIGA_LIB_NOINST} \ + ${PLUGIN} ${PLUGIN_NOINST} \ + ${PROG} ${PROG_NOINST} \ + ${JARFILE} locales + ${MAKE} @MAKEFLAGS_SILENT@ subdirs-after + ${MAKE} @MAKEFLAGS_SILENT@ post-all pre-all post-all: subdirs: ${SUBDIRS} subdirs-after: ${SUBDIRS_AFTER} ${SUBDIRS} ${SUBDIRS_AFTER}: for i in $@; do \ ${DIR_ENTER}; \ - ${MAKE} -s || exit $$?; \ + ${MAKE} @MAKEFLAGS_SILENT@ || exit $$?; \ ${DIR_LEAVE}; \ done depend: pre-depend : >.deps @@ -167,11 +179,12 @@ fi ${JARFILE}: ${EXT_DEPS} ${JAR_MANIFEST} ${OBJS} ${OBJS_EXTRA} ${LINK_STATUS} if test x"${JAR_MANIFEST}" != x""; then \ - if ${JAR} cfm ${JARFILE} ${JAR_MANIFEST} ${OBJS} ${OBJS_EXTRA}; then \ + if ${JAR} cfm ${JARFILE} ${JAR_MANIFEST} ${OBJS} \ + ${OBJS_EXTRA}; then \ ${LINK_OK}; \ else \ ${LINK_FAILED}; \ fi \ else \ @@ -183,45 +196,106 @@ fi ${SHARED_LIB} ${SHARED_LIB_NOINST}: ${EXT_DEPS} ${LIB_OBJS} ${LIB_OBJS_EXTRA} ${LINK_STATUS} out="$@"; \ - if ${LD} -o $@ ${LIB_OBJS} ${LIB_OBJS_EXTRA} ${LIB_LDFLAGS} ${LIB_LDFLAGS_INSTALL_NAME} ${LDFLAGS} ${LIBS} ${LINK_LIB}; then \ + if ${LD} -o $@ ${LIB_OBJS} ${LIB_OBJS_EXTRA} ${LIB_LDFLAGS} \ + ${LIB_LDFLAGS_INSTALL_NAME} ${LDFLAGS} ${LIBS} ${LINK_LIB}; then \ ${LINK_OK}; \ else \ ${LINK_FAILED}; \ fi ${FRAMEWORK} ${FRAMEWORK_NOINST}: ${EXT_DEPS} ${LIB_OBJS} ${LIB_OBJS_EXTRA} ${LINK_STATUS} out="$@"; \ - if rm -fr $$out && ${MKDIR_P} $$out && ${MAKE} -s COPY_HEADERS_IF_SUBDIR=${includesubdir} COPY_HEADERS_DESTINATION=$$PWD/$@/Headers copy-headers-into-framework && if test -f Info.plist; then ${INSTALL} -m 644 Info.plist $$out/Info.plist; fi && if test -f module.modulemap; then ${MKDIR_P} $$out/Modules && ${INSTALL} -m 644 module.modulemap $$out/Modules/module.modulemap; fi && ${LD} -o $$out/$${out%.framework} ${LIB_OBJS} ${LIB_OBJS_EXTRA} ${FRAMEWORK_LDFLAGS} ${FRAMEWORK_LDFLAGS_INSTALL_NAME} ${LDFLAGS} ${FRAMEWORK_LIBS} && ${CODESIGN} -fs ${CODESIGN_IDENTITY} $$out; then \ - ${LINK_OK}; \ + if test x"@HOST_IS_IOS@" = x"yes"; then \ + if rm -fr $@ && \ + ${MAKE} @MAKEFLAGS_SILENT@ \ + COPY_HEADERS_IF_SUBDIR=${includesubdir} \ + COPY_HEADERS_DESTINATION=$$PWD/$@/Headers \ + copy-headers-into-framework && \ + if test -f Info.plist; then \ + ${INSTALL} -m 644 Info.plist $@/Info.plist; \ + fi && \ + if test -f module.modulemap; then \ + ${MKDIR_P} $@/Modules && \ + ${INSTALL} -m 644 module.modulemap \ + $@/Modules/module.modulemap; \ + fi && \ + ${LD} -o $@/$${out%.framework} \ + ${LIB_OBJS} ${LIB_OBJS_EXTRA} ${FRAMEWORK_LDFLAGS} \ + ${FRAMEWORK_LDFLAGS_INSTALL_NAME} ${LDFLAGS} \ + ${FRAMEWORK_LIBS} && \ + ${CODESIGN} -fs ${CODESIGN_IDENTITY} $@; then \ + ${LINK_OK}; \ + else \ + rm -fr $$out; false; \ + ${LINK_FAILED}; \ + fi; \ else \ - rm -fr $$out; false; \ - ${LINK_FAILED}; \ + versiondir="$@/Versions/${LIB_MAJOR}"; \ + if rm -fr $@ && \ + ${MKDIR_P} $$versiondir && \ + ${LN_S} ${LIB_MAJOR} $@/Versions/Current && \ + ${MAKE} @MAKEFLAGS_SILENT@ \ + COPY_HEADERS_IF_SUBDIR=${includesubdir} \ + COPY_HEADERS_DESTINATION=$$PWD/$$versiondir/Headers \ + copy-headers-into-framework && \ + ${LN_S} Versions/Current/Headers $@/Headers && \ + if test -f Info.plist; then \ + ${MKDIR_P} $$versiondir/Resources && \ + ${INSTALL} -m 644 Info.plist \ + $$versiondir/Resources/Info.plist && \ + ${LN_S} Versions/Current/Resources $@/Resources; \ + fi && \ + if test -f module.modulemap; then \ + ${MKDIR_P} $$versiondir/Modules && \ + ${INSTALL} -m 644 module.modulemap \ + $$versiondir/Modules/module.modulemap && \ + ${LN_S} Versions/Current/Modules $@/Modules; \ + fi && \ + ${LD} -o $$versiondir/$${out%.framework} \ + ${LIB_OBJS} ${LIB_OBJS_EXTRA} ${FRAMEWORK_LDFLAGS} \ + ${FRAMEWORK_LDFLAGS_INSTALL_NAME} ${LDFLAGS} \ + ${FRAMEWORK_LIBS} && \ + ${LN_S} Versions/Current/$${out%.framework} \ + $@/$${out%.framework} && \ + ${CODESIGN} -fs ${CODESIGN_IDENTITY} $@; then \ + ${LINK_OK}; \ + else \ + rm -fr $$out; false; \ + ${LINK_FAILED}; \ + fi; \ fi copy-headers-into-framework: for i in "" ${SUBDIRS} ${SUBDIRS_AFTER}; do \ test x"$$i" = x"" && continue; \ cd $$i || exit 1; \ - ${MAKE} -s copy-headers-into-framework || exit $$?; \ + ${MAKE} @MAKEFLAGS_SILENT@ copy-headers-into-framework || \ + exit $$?; \ cd .. || exit 1; \ done if test x"${includesubdir}" = x"${COPY_HEADERS_IF_SUBDIR}"; then \ for i in "" ${INCLUDES}; do \ test x"$$i" = x"" && continue; \ - ${MKDIR_P} $$(dirname ${COPY_HEADERS_DESTINATION}/$$i) || exit $$?; \ - ${INSTALL} -m 644 $$i ${COPY_HEADERS_DESTINATION}/$$i || exit $$?; \ + ${MKDIR_P} \ + $$(dirname ${COPY_HEADERS_DESTINATION}/$$i) || \ + exit $$?; \ + ${INSTALL} -m 644 $$i \ + ${COPY_HEADERS_DESTINATION}/$$i || exit $$?; \ done \ fi -${AMIGA_LIB} ${AMIGA_LIB_NOINST}: ${EXT_DEPS} ${AMIGA_LIB_OBJS_START} ${AMIGA_LIB_OBJS} ${AMIGA_LIB_OBJS_EXTRA} +${AMIGA_LIB} ${AMIGA_LIB_NOINST}: ${EXT_DEPS} ${AMIGA_LIB_OBJS_START} \ + ${AMIGA_LIB_OBJS} ${AMIGA_LIB_OBJS_EXTRA} ${LINK_STATUS} - if ${LD} -o $@ ${AMIGA_LIB_OBJS_START} ${AMIGA_LIB_OBJS} ${AMIGA_LIB_OBJS_EXTRA} ${AMIGA_LIB_LDFLAGS} ${AMIGA_LIB_LIBS}; then \ + if ${LD} -o $@ ${AMIGA_LIB_OBJS_START} ${AMIGA_LIB_OBJS} \ + ${AMIGA_LIB_OBJS_EXTRA} ${AMIGA_LIB_LDFLAGS} \ + ${AMIGA_LIB_LIBS}; then \ ${LINK_OK}; \ else \ ${LINK_FAILED}; \ fi @@ -280,15 +354,17 @@ dir=".$$(echo $$i | sed 's/\//_/g').objs"; \ rm -fr $$dir; \ done; \ fi -${STATIC_PIC_LIB} ${STATIC_PIC_LIB_NOINST}: ${EXT_DEPS} ${LIB_OBJS} ${LIB_OBJS_EXTRA} +${STATIC_PIC_LIB} ${STATIC_PIC_LIB_NOINST}: ${EXT_DEPS} ${LIB_OBJS} \ + ${LIB_OBJS_EXTRA} ${LINK_STATUS} rm -f $@ if test x"${BUILD_AND_HOST_ARE_DARWIN}" = x"yes"; then \ - if /usr/bin/libtool -static -o $@ ${LIB_OBJS} ${LIB_OBJS_EXTRA}; then \ + if /usr/bin/libtool -static -o $@ ${LIB_OBJS} \ + ${LIB_OBJS_EXTRA}; then \ ${LINK_OK}; \ else \ rm -f $@; false; \ ${LINK_FAILED}; \ fi; \ @@ -327,11 +403,12 @@ dir=".$$(echo $$i | sed 's/\//_/g').objs"; \ rm -fr $$dir; \ done; \ fi -${STATIC_AMIGA_LIB} ${STATIC_AMIGA_LIB_NOINST}: ${EXT_DEPS} ${AMIGA_LIB_OBJS} ${AMIGA_LIB_OBJS_EXTRA} +${STATIC_AMIGA_LIB} ${STATIC_AMIGA_LIB_NOINST}: ${EXT_DEPS} ${AMIGA_LIB_OBJS} \ + ${AMIGA_LIB_OBJS_EXTRA} ${LINK_STATUS} rm -f $@ out="$@"; \ objs=""; \ ars=""; \ @@ -371,75 +448,83 @@ .c.o: ${COMPILE_STATUS} in="$<"; \ out="$@"; \ - if ${CC} ${CFLAGS} ${CPPFLAGS} ${CFLAGS_$<} ${CFLAGS_$@} ${DEP_CFLAGS} -c -o $@ $<; then \ + if ${CC} ${CFLAGS} ${CPPFLAGS} ${CFLAGS_$<} ${CFLAGS_$@} ${DEP_CFLAGS} \ + -c -o $@ $<; then \ ${COMPILE_OK}; \ else \ ${COMPILE_FAILED}; \ fi .c.lib.o: ${COMPILE_LIB_STATUS} in="$<"; \ out="$@"; \ - if ${CC} ${LIB_CFLAGS} ${CFLAGS} ${CPPFLAGS} ${CFLAGS_$<} ${CFLAGS_$@} ${DEP_CFLAGS} -c -o $@ $<; then \ + if ${CC} ${LIB_CFLAGS} ${CFLAGS} ${CPPFLAGS} ${CFLAGS_$<} ${CFLAGS_$@} \ + ${DEP_CFLAGS} -c -o $@ $<; then \ ${COMPILE_LIB_OK}; \ else \ ${COMPILE_LIB_FAILED}; \ fi .c.amigalib.o: ${COMPILE_AMIGA_LIB_STATUS} in="$<"; \ out="$@"; \ - if ${CC} ${AMIGA_LIB_CFLAGS} ${CFLAGS} ${CPPFLAGS} ${CFLAGS_$<} ${CFLAGS_$@} ${DEP_CFLAGS} -c -o $@ $<; then \ + if ${CC} ${AMIGA_LIB_CFLAGS} ${CFLAGS} ${CPPFLAGS} ${CFLAGS_$<} \ + ${CFLAGS_$@} ${DEP_CFLAGS} -c -o $@ $<; then \ ${COMPILE_AMIGA_LIB_OK}; \ else \ ${COMPILE_AMIGA_LIB_FAILED}; \ fi .c.plugin.o: ${COMPILE_PLUGIN_STATUS} in="$<"; \ out="$@"; \ - if ${CC} ${PLUGIN_CFLAGS} ${CFLAGS} ${CPPFLAGS} ${CFLAGS_$<} ${CFLAGS_$@} ${DEP_CFLAGS} -c -o $@ $<; then \ + if ${CC} ${PLUGIN_CFLAGS} ${CFLAGS} ${CPPFLAGS} ${CFLAGS_$<} \ + ${CFLAGS_$@} ${DEP_CFLAGS} -c -o $@ $<; then \ ${COMPILE_PLUGIN_OK}; \ else \ ${COMPILE_PLUGIN_FAILED}; \ fi .cc.o .cxx.o: ${COMPILE_STATUS} in="$<"; \ out="$@"; \ - if ${CXX} ${CXXFLAGS} ${CPPFLAGS} ${CXXFLAGS_$<} ${CXXFLAGS_$@} ${DEP_CXXFLAGS} -c -o $@ $<; then \ + if ${CXX} ${CXXFLAGS} ${CPPFLAGS} ${CXXFLAGS_$<} ${CXXFLAGS_$@} \ + ${DEP_CXXFLAGS} -c -o $@ $<; then \ ${COMPILE_OK}; \ else \ ${COMPILE_FAILED}; \ fi .cc.lib.o .cxx.lib.o: ${COMPILE_LIB_STATUS} in="$<"; \ out="$@"; \ - if ${CXX} ${LIB_CFLAGS} ${CXXFLAGS} ${CPPFLAGS} ${CXXFLAGS_$<} ${CXXFLAGS_$@} ${DEP_CXXFLAGS} -c -o $@ $<; then \ + if ${CXX} ${LIB_CFLAGS} ${CXXFLAGS} ${CPPFLAGS} ${CXXFLAGS_$<} \ + ${CXXFLAGS_$@} ${DEP_CXXFLAGS} -c -o $@ $<; then \ ${COMPILE_LIB_OK}; \ else \ ${COMPILE_LIB_FAILED}; \ fi .cc.amigalib.o .cxx.amigalib.o: ${COMPILE_AMIGA_LIB_STATUS} in="$<"; \ out="$@"; \ - if ${CXX} ${AMIGA_LIB_CFLAGS} ${CXXFLAGS} ${CPPFLAGS} ${CXXFLAGS_$<} ${CXXFLAGS_$@} ${DEP_CXXFLAGS} -c -o $@ $<; then \ + if ${CXX} ${AMIGA_LIB_CFLAGS} ${CXXFLAGS} ${CPPFLAGS} ${CXXFLAGS_$<} \ + ${CXXFLAGS_$@} ${DEP_CXXFLAGS} -c -o $@ $<; then \ ${COMPILE_AMIGA_LIB_OK}; \ else \ ${COMPILE_AMIGA_LIB_FAILED}; \ fi .cc.plugin.o .cxx.plugin.o: ${COMPILE_PLUGIN_STATUS} in="$<"; \ out="$@"; \ - if ${CXX} ${PLUGIN_CFLAGS} ${CXXFLAGS} ${CPPFLAGS} ${CXXFLAGS_$<} ${CXXFLAGS_$@} ${DEP_CXXFLAGS} -c -o $@ $<; then \ + if ${CXX} ${PLUGIN_CFLAGS} ${CXXFLAGS} ${CPPFLAGS} ${CXXFLAGS_$<} \ + ${CXXFLAGS_$@} ${DEP_CXXFLAGS} -c -o $@ $<; then \ ${COMPILE_PLUGIN_OK}; \ else \ ${COMPILE_PLUGIN_FAILED}; \ fi @@ -483,75 +568,86 @@ .m.o: ${COMPILE_STATUS} in="$<"; \ out="$@"; \ - if ${OBJC} ${OBJCFLAGS} ${CPPFLAGS} ${OBJCFLAGS_$<} ${OBJCFLAGS_$@} ${DEP_OBJCFLAGS} -c -o $@ $<; then \ + if ${OBJC} ${OBJCFLAGS} ${CPPFLAGS} ${OBJCFLAGS_$<} ${OBJCFLAGS_$@} \ + ${DEP_OBJCFLAGS} -c -o $@ $<; then \ ${COMPILE_OK}; \ else \ ${COMPILE_FAILED}; \ fi .m.lib.o: ${COMPILE_LIB_STATUS} in="$<"; \ out="$@"; \ - if ${OBJC} ${LIB_CFLAGS} ${OBJCFLAGS} ${CPPFLAGS} ${OBJCFLAGS_$<} ${OBJCFLAGS_$@} ${DEP_OBJCFLAGS} -c -o $@ $<; then \ + if ${OBJC} ${LIB_CFLAGS} ${OBJCFLAGS} ${CPPFLAGS} ${OBJCFLAGS_$<} \ + ${OBJCFLAGS_$@} ${DEP_OBJCFLAGS} -c -o $@ $<; then \ ${COMPILE_LIB_OK}; \ else \ ${COMPILE_LIB_FAILED}; \ fi .m.amigalib.o: ${COMPILE_AMIGA_LIB_STATUS} in="$<"; \ out="$@"; \ - if ${OBJC} ${AMIGA_LIB_CFLAGS} ${OBJCFLAGS} ${CPPFLAGS} ${OBJCFLAGS_$<} ${OBJCFLAGS_$@} ${DEP_OBJCFLAGS} -c -o $@ $<; then \ + if ${OBJC} ${AMIGA_LIB_CFLAGS} ${OBJCFLAGS} ${CPPFLAGS} \ + ${OBJCFLAGS_$<} ${OBJCFLAGS_$@} ${DEP_OBJCFLAGS} -c -o $@ $<; then \ ${COMPILE_AMIGA_LIB_OK}; \ else \ ${COMPILE_AMIGA_LIB_FAILED}; \ fi .m.plugin.o: ${COMPILE_PLUGIN_STATUS} in="$<"; \ out="$@"; \ - if ${OBJC} ${PLUGIN_CFLAGS} ${OBJCFLAGS} ${CPPFLAGS} ${OBJCFLAGS_$<} ${OBJCFLAGS_$@} ${DEP_OBJCFLAGS} -c -o $@ $<; then \ + if ${OBJC} ${PLUGIN_CFLAGS} ${OBJCFLAGS} ${CPPFLAGS} ${OBJCFLAGS_$<} \ + ${OBJCFLAGS_$@} ${DEP_OBJCFLAGS} -c -o $@ $<; then \ ${COMPILE_PLUGIN_OK}; \ else \ ${COMPILE_PLUGIN_FAILED}; \ fi .mm.o: ${COMPILE_STATUS} in="$<"; \ out="$@"; \ - if ${OBJCXX} ${OBJCXXFLAGS} ${CPPFLAGS} ${OBJCXXFLAGS_$<} ${OBJCXXFLAGS_$@} ${DEP_OBJCXXFLAGS} -c -o $@ $<; then \ + if ${OBJCXX} ${OBJCXXFLAGS} ${CPPFLAGS} ${OBJCXXFLAGS_$<} \ + ${OBJCXXFLAGS_$@} ${DEP_OBJCXXFLAGS} -c -o $@ $<; then \ ${COMPILE_OK}; \ else \ ${COMPILE_FAILED}; \ fi .mm.lib.o: ${COMPILE_LIB_STATUS} in="$<"; \ out="$@"; \ - if ${OBJCXX} ${LIB_CFLAGS} ${OBJCXXFLAGS} ${CPPFLAGS} ${OBJCXXFLAGS_$<} ${OBJCXXFLAGS_$@} ${DEP_OBJCXXFLAGS} -c -o $@ $<; then \ + if ${OBJCXX} ${LIB_CFLAGS} ${OBJCXXFLAGS} ${CPPFLAGS} \ + ${OBJCXXFLAGS_$<} ${OBJCXXFLAGS_$@} ${DEP_OBJCXXFLAGS} -c -o $@ \ + $<; then \ ${COMPILE_LIB_OK}; \ else \ ${COMPILE_LIB_FAILED}; \ fi .mm.amigalib.o: ${COMPILE_AMIGA_LIB_STATUS} in="$<"; \ out="$@"; \ - if ${OBJCXX} ${AMIGA_LIB_CFLAGS} ${OBJCXXFLAGS} ${CPPFLAGS} ${OBJCXXFLAGS_$<} ${OBJCXXFLAGS_$@} ${DEP_OBJCXXFLAGS} -c -o $@ $<; then \ + if ${OBJCXX} ${AMIGA_LIB_CFLAGS} ${OBJCXXFLAGS} ${CPPFLAGS} \ + ${OBJCXXFLAGS_$<} ${OBJCXXFLAGS_$@} ${DEP_OBJCXXFLAGS} -c -o $@ \ + $<; then \ ${COMPILE_AMIGA_LIB_OK}; \ else \ ${COMPILE_AMIGA_LIB_FAILED}; \ fi .mm.plugin.o: ${COMPILE_PLUGIN_STATUS} in="$<"; \ out="$@"; \ - if ${OBJCXX} ${PLUGIN_CFLAGS} ${OBJCXXFLAGS} ${CPPFLAGS} ${OBJCXXFLAGS_$<} ${OBJCXXFLAGS_$@} ${DEP_OBJCXXFLAGS} -c -o $@ $<; then \ + if ${OBJCXX} ${PLUGIN_CFLAGS} ${OBJCXXFLAGS} ${CPPFLAGS} \ + ${OBJCXXFLAGS_$<} ${OBJCXXFLAGS_$@} ${DEP_OBJCXXFLAGS} -c -o $@ \ + $<; then \ ${COMPILE_PLUGIN_OK}; \ else \ ${COMPILE_PLUGIN_FAILED}; \ fi @@ -567,11 +663,12 @@ .py.pyc: ${COMPILE_STATUS} in="$<"; \ out="$@"; \ - if ${PYTHON} ${PYTHON_FLAGS} -c "import py_compile; py_compile.compile('$<')"; then \ + if ${PYTHON} ${PYTHON_FLAGS} -c \ + "import py_compile; py_compile.compile('$<')"; then \ ${COMPILE_OK}; \ else \ ${COMPILE_FAILED}; \ fi @@ -587,76 +684,83 @@ .S.o .S.amigalib.o: ${COMPILE_STATUS} in="$<"; \ out="$@"; \ - if ${AS} ${ASFLAGS} ${CPPFLAGS} ${ASFLAGS_$<} ${ASFLAGS_$@} ${DEP_ASFLAGS} -c -o $@ $<; then \ + if ${AS} ${ASFLAGS} ${CPPFLAGS} ${ASFLAGS_$<} ${ASFLAGS_$@} \ + ${DEP_ASFLAGS} -c -o $@ $<; then \ ${COMPILE_OK}; \ else \ ${COMPILE_FAILED}; \ fi .S.lib.o: ${COMPILE_LIB_STATUS} in="$<"; \ out="$@"; \ - if ${AS} ${LIB_CFLAGS} ${ASFLAGS} ${CPPFLAGS} ${ASFLAGS_$<} ${ASFLAGS_$@} ${DEP_ASFLAGS} -c -o $@ $<; then \ + if ${AS} ${LIB_CFLAGS} ${ASFLAGS} ${CPPFLAGS} ${ASFLAGS_$<} \ + ${ASFLAGS_$@} ${DEP_ASFLAGS} -c -o $@ $<; then \ ${COMPILE_LIB_OK}; \ else \ ${COMPILE_LIB_FAILED}; \ fi .S.plugin.o: ${COMPILE_PLUGIN_STATUS} in="$<"; \ out="$@"; \ - if ${AS} ${PLUGIN_CFLAGS} ${ASFLAGS} ${CPPFLAGS} ${ASFLAGS_$<} ${ASFLAGS_$@} ${DEP_ASFLAGS} -c -o $@ $<; then \ + if ${AS} ${PLUGIN_CFLAGS} ${ASFLAGS} ${CPPFLAGS} ${ASFLAGS_$<} \ + ${ASFLAGS_$@} ${DEP_ASFLAGS} -c -o $@ $<; then \ ${COMPILE_PLUGIN_OK}; \ else \ ${COMPILE_PLUGIN_FAILED}; \ fi .xpm.o: ${COMPILE_STATUS} in="$<"; \ out="$@"; \ - if ${CC} ${CFLAGS} ${CPPFLAGS} ${CFLAGS_$<} ${CFLAGS_$@} -x c -c -o $@ $<; then \ + if ${CC} ${CFLAGS} ${CPPFLAGS} ${CFLAGS_$<} ${CFLAGS_$@} -x c -c -o $@ \ + $<; then \ ${COMPILE_OK}; \ else \ ${COMPILE_FAILED}; \ fi .xpm.lib.o: ${COMPILE_LIB_STATUS} in="$<"; \ out="$@"; \ - if ${CC} ${LIB_CFLAGS} ${CFLAGS} ${CPPFLAGS} ${CFLAGS_$<} ${CFLAGS_$@} -x c -c -o $@ $<; then \ + if ${CC} ${LIB_CFLAGS} ${CFLAGS} ${CPPFLAGS} ${CFLAGS_$<} ${CFLAGS_$@} \ + -x c -c -o $@ $<; then \ ${COMPILE_LIB_OK}; \ else \ ${COMPILE_LIB_FAILED}; \ fi .xpm.amigalib.o: ${COMPILE_AMIGA_LIB_STATUS} in="$<"; \ out="$@"; \ - if ${CC} ${AMIGA_LIB_CFLAGS} ${CFLAGS} ${CPPFLAGS} ${CFLAGS_$<} ${CFLAGS_$@} -x c -c -o $@ $<; then \ + if ${CC} ${AMIGA_LIB_CFLAGS} ${CFLAGS} ${CPPFLAGS} ${CFLAGS_$<} \ + ${CFLAGS_$@} -x c -c -o $@ $<; then \ ${COMPILE_AMIGA_LIB_OK}; \ else \ ${COMPILE_AMIGA_LIB_FAILED}; \ fi .xpm.plugin.o: ${COMPILE_PLUGIN_STATUS} in="$<"; \ out="$@"; \ - if ${CC} ${PLUGIN_CFLAGS} ${CFLAGS} ${CPPFLAGS} ${CFLAGS_$<} ${CFLAGS_$@} -x c -c -o $@ $<; then \ + if ${CC} ${PLUGIN_CFLAGS} ${CFLAGS} ${CPPFLAGS} ${CFLAGS_$<} \ + ${CFLAGS_$@} -x c -c -o $@ $<; then \ ${COMPILE_PLUGIN_OK}; \ else \ ${COMPILE_PLUGIN_FAILED}; \ fi install: all install-extra for i in "" ${SUBDIRS} ${SUBDIRS_AFTER}; do \ test x"$$i" = x"" && continue; \ ${DIR_ENTER}; \ - ${MAKE} -s install || exit $$?; \ + ${MAKE} @MAKEFLAGS_SILENT@ install || exit $$?; \ ${DIR_LEAVE}; \ done for i in "" ${SHARED_LIB}; do \ test x"$$i" = x"" && continue; \ @@ -670,31 +774,34 @@ for i in "" ${FRAMEWORK}; do \ test x"$$i" = x"" && continue; \ ${INSTALL_STATUS}; \ rm -fr ${DESTDIR}${prefix}/Library/Frameworks/$$i; \ - if ${MKDIR_P} ${DESTDIR}${prefix}/Library/Frameworks && cp -R $$i ${DESTDIR}${prefix}/Library/Frameworks/; then \ + if ${MKDIR_P} ${DESTDIR}${prefix}/Library/Frameworks && \ + cp -R $$i ${DESTDIR}${prefix}/Library/Frameworks/; then \ ${INSTALL_OK}; \ else \ ${INSTALL_FAILED}; \ fi \ done for i in "" ${AMIGA_LIB}; do \ test x"$$i" = x"" && continue; \ ${INSTALL_STATUS}; \ - if ${MKDIR_P} ${DESTDIR}${amigalibdir} && ${INSTALL} -m 755 $$i ${DESTDIR}${amigalibdir}/$$i; then \ + if ${MKDIR_P} ${DESTDIR}${amigalibdir} && \ + ${INSTALL} -m 755 $$i ${DESTDIR}${amigalibdir}/$$i; then \ ${INSTALL_OK}; \ else \ ${INSTALL_FAILED}; \ fi \ done for i in "" ${STATIC_LIB} ${STATIC_PIC_LIB} ${STATIC_AMIGA_LIB}; do \ test x"$$i" = x"" && continue; \ ${INSTALL_STATUS}; \ - if ${MKDIR_P} ${DESTDIR}${libdir} && ${INSTALL} -m 644 $$i ${DESTDIR}${libdir}/$$i; then \ + if ${MKDIR_P} ${DESTDIR}${libdir} && \ + ${INSTALL} -m 644 $$i ${DESTDIR}${libdir}/$$i; then \ ${INSTALL_OK}; \ else \ ${INSTALL_FAILED}; \ fi \ done @@ -710,21 +817,25 @@ done for i in "" ${DATA}; do \ test x"$$i" = x"" && continue; \ ${INSTALL_STATUS}; \ - if ${MKDIR_P} $$(dirname ${DESTDIR}${datadir}/${PACKAGE_NAME}/$$i) && ${INSTALL} -m 644 $$i ${DESTDIR}${datadir}/${PACKAGE_NAME}/$$i; then \ + if ${MKDIR_P} $$(dirname \ + ${DESTDIR}${datadir}/${PACKAGE_NAME}/$$i) && \ + ${INSTALL} -m 644 $$i \ + ${DESTDIR}${datadir}/${PACKAGE_NAME}/$$i; then \ ${INSTALL_OK}; \ else \ ${INSTALL_FAILED}; \ fi \ done for i in "" ${PROG}; do \ test x"$$i" = x"" && continue; \ ${INSTALL_STATUS}; \ - if ${MKDIR_P} ${DESTDIR}${bindir} && ${INSTALL} -m 755 $$i ${DESTDIR}${bindir}/$$i; then \ + if ${MKDIR_P} ${DESTDIR}${bindir} && \ + ${INSTALL} -m 755 $$i ${DESTDIR}${bindir}/$$i; then \ ${INSTALL_OK}; \ else \ ${INSTALL_FAILED}; \ fi \ done @@ -731,11 +842,14 @@ if test x"${INSTALL_INCLUDES}" = x"yes"; then \ for i in "" ${INCLUDES}; do \ test x"$$i" = x"" && continue; \ ${INSTALL_STATUS}; \ - if ${MKDIR_P} $$(dirname ${DESTDIR}${includedir}/${includesubdir}/$$i) && ${INSTALL} -m 644 $$i ${DESTDIR}${includedir}/${includesubdir}/$$i; then \ + if ${MKDIR_P} $$(dirname \ + ${DESTDIR}${includedir}/${includesubdir}/$$i) && \ + ${INSTALL} -m 644 $$i \ + ${DESTDIR}${includedir}/${includesubdir}/$$i; then \ ${INSTALL_OK}; \ else \ ${INSTALL_FAILED}; \ fi \ done \ @@ -742,40 +856,46 @@ fi for i in "" ${MO_FILES}; do \ test x"$$i" = x"" && continue; \ ${INSTALL_STATUS}; \ - if ${MKDIR_P} ${DESTDIR}${localedir}/$${i%.mo}/LC_MESSAGES && ${INSTALL} -m 644 $$i ${DESTDIR}${localedir}/$${i%.mo}/LC_MESSAGES/${localename}.mo; then \ + dest="${localedir}/$${i%.mo}/LC_MESSAGES/${localename}.mo"; \ + dest="${DESTDIR}$$dest"; \ + if ${MKDIR_P} ${DESTDIR}${localedir}/$${i%.mo}/LC_MESSAGES && \ + ${INSTALL} -m 644 $$i $$dest; then \ ${INSTALL_OK}; \ else \ ${INSTALL_FAILED}; \ fi \ done for i in "" ${MAN}; do \ test x"$$i" = x"" && continue; \ ${INSTALL_STATUS}; \ - if ${MKDIR_P} ${DESTDIR}${mandir}/${mansubdir} && ${INSTALL} -m 644 $$i ${DESTDIR}${mandir}/${mansubdir}/$$i; then \ + dest="${DESTDIR}${mandir}/${mansubdir}/$$i"; \ + if ${MKDIR_P} ${DESTDIR}${mandir}/${mansubdir} && \ + ${INSTALL} -m 644 $$i $$dest; then \ ${INSTALL_OK}; \ else \ ${INSTALL_FAILED}; \ fi \ done install-extra: -uninstall: uninstall-extra +uninstall: for i in "" ${SUBDIRS} ${SUBDIRS_AFTER}; do \ test x"$$i" = x"" && continue; \ ${DIR_ENTER}; \ - ${MAKE} -s uninstall || exit $$?; \ + ${MAKE} @MAKEFLAGS_SILENT@ uninstall || exit $$?; \ ${DIR_LEAVE}; \ done for i in "" ${SHARED_LIB}; do \ test x"$$i" = x"" && continue; \ - if test -f ${DESTDIR}${libdir}/$$i -o -f ${DESTDIR}${bindir}/$$i; then \ + if test -f ${DESTDIR}${libdir}/$$i \ + -o -f ${DESTDIR}${bindir}/$$i; then \ if : @UNINSTALL_LIB@; then \ ${DELETE_OK}; \ else \ ${DELETE_FAILED}; \ fi \ @@ -783,11 +903,12 @@ done for i in "" ${FRAMEWORK}; do \ test x"$$i" = x"" && continue; \ if test -d ${DESTDIR}${prefix}/Library/Frameworks/$$i; then \ - if rm -fr ${DESTDIR}${prefix}/Library/Frameworks/$$i; then \ + if rm -fr ${DESTDIR}${prefix}/Library/Frameworks/$$i; \ + then \ ${DELETE_OK}; \ else \ ${DELETE_FAILED}; \ fi \ fi \ @@ -819,17 +940,19 @@ rmdir ${DESTDIR}${plugindir} >/dev/null 2>&1 || true for i in "" ${DATA}; do \ test x"$$i" = x"" && continue; \ if test -f ${DESTDIR}${datadir}/${PACKAGE_NAME}/$$i; then \ - if rm -f ${DESTDIR}${datadir}/${PACKAGE_NAME}/$$i; then \ + if rm -f ${DESTDIR}${datadir}/${PACKAGE_NAME}/$$i; \ + then \ ${DELETE_OK}; \ else \ ${DELETE_FAILED}; \ fi \ fi; \ - rmdir "$$(dirname ${DESTDIR}${datadir}/${PACKAGE_NAME}/$$i)" >/dev/null 2>&1 || true; \ + rmdir "$$(dirname ${DESTDIR}${datadir}/${PACKAGE_NAME}/$$i)" \ + >/dev/null 2>&1 || true; \ done rmdir ${DESTDIR}${datadir}/${PACKAGE_NAME} >/dev/null 2>&1 || true for i in "" ${PROG}; do \ test x"$$i" = x"" && continue; \ @@ -843,11 +966,12 @@ done for i in "" ${INCLUDES}; do \ test x"$$i" = x"" && continue; \ if test -f ${DESTDIR}${includedir}/${includesubdir}/$$i; then \ - if rm -f ${DESTDIR}${includedir}/${includesubdir}/$$i; then \ + if rm -f ${DESTDIR}${includedir}/${includesubdir}/$$i; \ + then \ ${DELETE_OK}; \ else \ ${DELETE_FAILED}; \ fi \ fi \ @@ -854,12 +978,14 @@ done rmdir ${DESTDIR}${includedir}/${includesubdir} >/dev/null 2>&1 || true for i in "" ${MO_FILES}; do \ test x"$$i" = x"" && continue; \ - if test -f ${DESTDIR}${localedir}/$${i%.mo}/LC_MESSAGES/${localename}.mo; then \ - if rm -f ${DESTDIR}${localedir}/$${i%.mo}/LC_MESSAGES/${localename}.mo; then \ + mo="${localedir}/$${i%.mo}/LC_MESSAGES/${localename}.mo"; \ + mo="${DESTDIR}$$mo"; \ + if test -f $$mo; then \ + if rm -f $$mo; then \ ${DELETE_OK}; \ else \ ${DELETE_FAILED}; \ fi \ fi \ @@ -874,23 +1000,32 @@ ${DELETE_FAILED}; \ fi \ fi \ done + ${MAKE} @MAKEFLAGS_SILENT@ uninstall-extra + uninstall-extra: clean: for i in "" ${SUBDIRS} ${SUBDIRS_AFTER}; do \ test x"$$i" = x"" && continue; \ ${DIR_ENTER}; \ - ${MAKE} -s clean || exit $$?; \ + ${MAKE} @MAKEFLAGS_SILENT@ clean || exit $$?; \ ${DIR_LEAVE}; \ done : >.deps - for i in "" ${DEPS} ${OBJS} ${OBJS_EXTRA} ${LIB_OBJS} ${LIB_OBJS_EXTRA} ${AMIGA_LIB_OBJS} ${AMIGA_LIB_OBJS_START} ${AMIGA_LIB_OBJS_EXTRA} ${PLUGIN_OBJS} ${PROG} ${PROG_NOINST} ${SHARED_LIB} ${SHARED_LIB_NOINST} ${AMIGA_LIB} ${AMIGA_LIB_NOINST} ${STATIC_LIB} ${STATIC_LIB_NOINST} ${STATIC_PIC_LIB} ${STATIC_PIC_LIB_NOINST} ${STATIC_AMIGA_LIB} ${STATIC_AMIGA_LIB_NOINST} ${FRAMEWORK} ${PLUGIN} ${PLUGIN_NOINST} ${CLEAN_LIB} ${MO_FILES} ${CLEAN}; do \ + for i in "" ${DEPS} ${OBJS} ${OBJS_EXTRA} ${LIB_OBJS} \ + ${LIB_OBJS_EXTRA} ${AMIGA_LIB_OBJS} ${AMIGA_LIB_OBJS_START} \ + ${AMIGA_LIB_OBJS_EXTRA} ${PLUGIN_OBJS} ${PROG} ${PROG_NOINST} \ + ${SHARED_LIB} ${SHARED_LIB_NOINST} ${AMIGA_LIB} \ + ${AMIGA_LIB_NOINST} ${STATIC_LIB} ${STATIC_LIB_NOINST} \ + ${STATIC_PIC_LIB} ${STATIC_PIC_LIB_NOINST} ${STATIC_AMIGA_LIB} \ + ${STATIC_AMIGA_LIB_NOINST} ${FRAMEWORK} ${PLUGIN} ${PLUGIN_NOINST} \ + ${CLEAN_LIB} ${MO_FILES} ${CLEAN}; do \ test x"$$i" = x"" && continue; \ if test -f $$i -o -d $$i; then \ if rm -fr $$i; then \ ${DELETE_OK}; \ else \ @@ -901,11 +1036,11 @@ distclean: clean for i in "" ${SUBDIRS} ${SUBDIRS_AFTER}; do \ test x"$$i" = x"" && continue; \ ${DIR_ENTER}; \ - ${MAKE} -s distclean || exit $$?; \ + ${MAKE} @MAKEFLAGS_SILENT@ distclean || exit $$?; \ ${DIR_LEAVE}; \ done for i in "" ${DISTCLEAN} .deps *~; do \ test x"$$i" = x"" && continue; \ @@ -921,11 +1056,12 @@ print-hierarchy: for i in "" ${SUBDIRS} ${SUBDIRS_AFTER}; do \ test x"$$i" = x"" && continue; \ echo ${PRINT_HIERARCHY_PREFIX}$$i; \ cd $$i || exit $$?; \ - ${MAKE} -s PRINT_HIERARCHY_PREFIX=$$i/ print-hierarchy || exit $$?; \ + ${MAKE} @MAKEFLAGS_SILENT@ PRINT_HIERARCHY_PREFIX=$$i/ \ + print-hierarchy || exit $$?; \ cd .. || exit $$?; \ done print-var: printf '%s\n' '${${VAR}}' Index: configure.ac ================================================================== --- configure.ac +++ configure.ac @@ -1,6 +1,6 @@ -AC_INIT(ObjFW, 1.1dev, js@nil.im) +AC_INIT(ObjFW, 1.1dev, js@nil.im, objfw, https://objfw.nil.im/) AC_CONFIG_SRCDIR(src) AC_CONFIG_AUX_DIR(build-aux) AC_CONFIG_MACRO_DIR(build-aux/m4) AC_DEFINE(OBJFW_VERSION_MAJOR, 1, [The major version of ObjFW]) @@ -35,32 +35,20 @@ enable_threads="no" enable_sockets="no" enable_files="no" ;; m68k-*-amigaos*) - AS_IF([test x"$OBJCFLAGS" = x""], [OBJCFLAGS="-O0"]) + AS_IF([test x"$OBJCFLAGS" = x""], [OBJCFLAGS="-O0 -g"]) OBJCFLAGS="$OBJCFLAGS -noixemul" OBJFW_OBJCFLAGS="$OBJFW_OBJCFLAGS -noixemul" CPPFLAGS="$CPPFLAGS -D__NO_NET_API" LDFLAGS="$LDFLAGS -noixemul" LIBS="$LIBS -ldebug" enable_files="yes" # Required for reading ENV: enable_shared="no" with_tls="no" - supports_amiga_lib="yes" - - AS_IF([test x"$enable_amiga_lib" != x"no"], [ - AC_SUBST(OBJFWRT_AMIGA_LIB, - ['objfwrt${OBJFWRT_LIB_MAJOR}.library']) - dnl For 68000, GCC emits calls to helper functions that - dnl do not work properly in a library. - t="-mcpu=68020 -fbaserel -noixemul -ffreestanding" - AC_SUBST(AMIGA_LIB_CFLAGS, $t) - t="$t -resident -nostartfiles -nodefaultlibs -ldebug -lc" - AC_SUBST(AMIGA_LIB_LDFLAGS, $t) - ]) AC_SUBST(LIBBASES_M, libbases.m) ;; powerpc-*-amigaos*) CPPFLAGS="$CPPFLAGS -D__USE_INLINE__" @@ -78,30 +66,20 @@ LDFLAGS="$LDFLAGS -noixemul" LIBS="$LIBS -ldebug" enable_files="yes" # Required for reading ENV: enable_shared="no" - supports_amiga_lib="yes" - - AS_IF([test x"$enable_amiga_lib" != x"no"], [ - AC_SUBST(OBJFWRT_AMIGA_LIB, - ['objfwrt${OBJFW_LIB_MAJOR}ppc.library']) - t="-mresident32 -ffreestanding -noixemul" - AC_SUBST(AMIGA_LIB_CFLAGS, $t) - t="-mresident32 -nostartfiles -nodefaultlibs -noixemul -ldebug" - AC_SUBST(AMIGA_LIB_LDFLAGS, "$t -lc") - ]) AC_SUBST(LIBBASES_M, libbases.m) ;; *-msdosdjgpp*) enable_shared="no" enable_threads="no" enable_sockets="no" ;; *-*-mingw*) - LDFLAGS="$LDFLAGS -Wl,--allow-multiple-definition -static-libgcc" + LDFLAGS="$LDFLAGS -Wl,--allow-multiple-definition" LIBS="$LIBS -lversion" AC_SUBST(USE_SRCS_WINDOWS, '${SRCS_WINDOWS}') ;; *-psp-*) @@ -142,10 +120,18 @@ *-*-mint*) enable_shared="no" enable_threads="no" # TODO with_tls="no" ;; +*-apple-macos*) + enable_shared="no" + enable_threads="no" # TODO + enable_sockets="no" # TODO + + AC_DEFINE(OF_CLASSIC_MACOS, 1, + [Whether we are compiling for classic macOS]) + ;; esac AS_IF([test x"$host_os" = x"msdosdjgpp" -a x"$build_os" = x"msdosdjgpp"], [ dnl Hack to make configure find these on DOS. : ${AR:=ar.exe} @@ -164,12 +150,12 @@ potential_compilers="clang egcc gcc" ;; esac AC_PROG_OBJC($potential_compilers) AC_PROG_OBJCPP -AC_PROG_LN_S AC_PROG_EGREP +AC_PROG_LN_S BUILDSYS_CHECK_IOS AC_ARG_WITH(wii, AS_HELP_STRING([--with-wii], [build for Wii])) @@ -346,10 +332,11 @@ AX_CHECK_COMPILER_FLAGS(-Xclang -fno-constant-cfstrings, [ flag="-Xclang -fno-constant-cfstrings" OBJCFLAGS="$OBJCFLAGS $flag" OBJFW_OBJCFLAGS="$OBJFW_OBJCFLAGS $flag" ]) + AX_CHECK_COMPILER_FLAGS([-Wsign-compare -Werror], [OBJCFLAGS="$OBJCFLAGS -Wsign-compare"]) AS_IF([test x"$with_nds" != x"yes"], [ AX_CHECK_COMPILER_FLAGS([-Wshadow -Werror], [OBJCFLAGS="$OBJCFLAGS -Wshadow"]) @@ -410,11 +397,13 @@ AC_ARG_ENABLE(shared, AS_HELP_STRING([--disable-shared], [do not build shared library])) AS_IF([test x"$enable_shared" != x"no"], [ BUILDSYS_SHARED_LIB - AC_SUBST(OBJFW_SHARED_LIB, "${LIB_PREFIX}objfw${LIB_SUFFIX}") + BUILDSYS_PLUGIN + + AC_SUBST(OBJFW_SHARED_LIB, '${LIB_PREFIX}objfw${LIB_SUFFIX}') AC_SUBST(EXCEPTIONS_LIB_A, "exceptions.lib.a") AC_SUBST(FORWARDING_LIB_A, "forwarding.lib.a") AC_SUBST(LOOKUP_ASM_LIB_A, "lookup-asm.lib.a") BUILDSYS_FRAMEWORK([ @@ -430,26 +419,16 @@ AS_IF([test x"$build_framework" = x"yes"], [ TESTS_LIBS="-framework ObjFW \${RUNTIME_FRAMEWORK_LIBS} $TESTS_LIBS" TESTS_LIBS="-F../src -F../src/runtime $TESTS_LIBS" ], [ TESTS_LIBS="\${RUNTIME_LIBS} $TESTS_LIBS" - TESTS_LIBS="-L../src/runtime -L../src/runtime/linklib $TESTS_LIBS" + TESTS_LIBS="-L../src/runtime $TESTS_LIBS" TESTS_LIBS="-L../src -lobjfw $TESTS_LIBS" ]) -AC_ARG_ENABLE(amiga-lib, - AS_HELP_STRING([--disable-amiga-lib], [do not build Amiga library])) -AS_IF([test x"$supports_amiga_lib" != x"yes"], [enable_amiga_lib="no"]) -AS_IF([test x"$enable_amiga_lib" != x"no"], [ - AC_SUBST(OBJFW_STATIC_LIB, "libobjfw.a") - AC_SUBST(EXCEPTIONS_A, "exceptions.a") - AC_SUBST(FORWARDING_A, "forwarding.a") - AC_SUBST(LOOKUP_ASM_AMIGALIB_A, "lookup-asm.amigalib.a") -]) - AC_ARG_ENABLE(static, AS_HELP_STRING([--enable-static], [build static library])) -AS_IF([test x"$enable_shared" = x"no" -a x"$enable_amiga_lib" = x"no"], [ +AS_IF([test x"$enable_shared" = x"no"], [ enable_static="yes" ]) AS_IF([test x"$enable_static" = x"yes"], [ AC_SUBST(OBJFW_STATIC_LIB, "libobjfw.a") AC_SUBST(EXCEPTIONS_A, "exceptions.a") @@ -525,10 +504,11 @@ AC_MSG_RESULT($objc_runtime) case "$objc_runtime" in "ObjFW runtime") AC_DEFINE(OF_OBJFW_RUNTIME, 1, [Whether we use the ObjFW runtime]) + AC_SUBST(USE_SRCS_TAGGED_POINTERS, '${SRCS_TAGGED_POINTERS}') AC_MSG_CHECKING([whether -fobjc-runtime=objfw is supported]) old_OBJCFLAGS="$OBJCFLAGS" OBJCFLAGS="$OBJCFLAGS -Xclang -fobjc-runtime=objfw" @@ -575,11 +555,11 @@ AC_SUBST(RUNTIME, "runtime") AC_CONFIG_FILES(src/runtime/Info.plist) AS_IF([test x"$enable_shared" != x"no"], [ AC_SUBST(OBJFWRT_SHARED_LIB, - "${LIB_PREFIX}objfwrt${LIB_SUFFIX}") + '${LIB_PREFIX}objfwrt${LIB_SUFFIX}') ]) AS_IF([test x"$enable_static" = x"yes"], [ AC_SUBST(OBJFWRT_STATIC_LIB, "libobjfwrt.a") ]) @@ -587,22 +567,13 @@ AS_IF([test x"$build_framework" = x"yes"], [ AC_SUBST(OBJFWRT_FRAMEWORK, "ObjFWRT.framework") AC_SUBST(RUNTIME_FRAMEWORK_LIBS, "-framework ObjFWRT") ]) - AS_IF([test x"$enable_amiga_lib" != x"no"], [ - AC_SUBST(RUNTIME_LIBS, "-lobjfwrt.library") - AC_SUBST(LINKLIB, linklib) - tmp="../src/runtime/linklib/libobjfwrt.library.a" - AC_SUBST(LIBOBJFWRT_DEP, "$tmp") - AC_SUBST(LIBOBJFWRT_DEP_LVL2, "../$tmp") - ], [ - AC_SUBST(RUNTIME_LIBS, "-lobjfwrt") - ]) - - AS_IF([test x"$enable_shared" = x"no" \ - -a x"$enable_amiga_lib" = x"no"], [ + AC_SUBST(RUNTIME_LIBS, "-lobjfwrt") + + AS_IF([test x"$enable_shared" = x"no"], [ AC_SUBST(LIBOBJFWRT_DEP, "../src/runtime/libobjfwrt.a") AC_SUBST(LIBOBJFWRT_DEP_LVL2, "../../src/runtime/libobjfwrt.a") ]) AS_IF([test x"$enable_seluid24" = x"yes"], [ @@ -1032,11 +1003,29 @@ AC_DEFINE(OF_HAVE_SCHED_YIELD, 1, [Whether we have sched_yield()]) ]) AC_CHECK_FUNCS(pthread_attr_getschedpolicy) - AC_CHECK_FUNCS(pthread_attr_setinheritsched) + + old_OBJCFLAGS="$OBJCFLAGS" + OBJCFLAGS="$OBJCFLAGS -Werror" + AC_MSG_CHECKING(for pthread_attr_setinheritsched) + AC_COMPILE_IFELSE([ + AC_LANG_PROGRAM([ + #include + ], [ + pthread_attr_setinheritsched( + (pthread_attr_t *)-1, 0); + ]) + ], [ + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_PTHREAD_ATTR_SETINHERITSCHED, 1, + [Whether we have pthread_attr_setinheritsched]) + ], [ + AC_MSG_RESULT(no) + ]) + OBJCFLAGS="$old_OBJCFLAGS" AC_CHECK_HEADERS(pthread_np.h, [], [], [#include ]) AC_CHECK_FUNCS(pthread_set_name_np pthread_setname_np, break) ;; esac @@ -1308,11 +1297,11 @@ AC_CHECK_FUNCS([fcntl nanosleep]) ;; esac AC_CHECK_HEADERS(xlocale.h) -AC_CHECK_FUNCS([strtod_l strtof_l asprintf_l]) +AC_CHECK_FUNCS([strtod_l strtof_l asprintf_l uselocale]) AS_IF([test x"$gnu_source" != x"yes" -a \( \ x"$ac_cv_func_strtod_l" = x"yes" -o x"$ac_cv_func_strtof_l" = x"yes" -o \ x"$ac_cv_func_asprintf_l" = x"yes" \)], [ AC_MSG_CHECKING(whether *_l functions need _GNU_SOURCE) AC_COMPILE_IFELSE([ @@ -1394,21 +1383,70 @@ AC_CHECK_HEADER(sys/socket.h, [ AC_DEFINE(OF_HAVE_SYS_SOCKET_H, 1, [Whether we have sys/socket.h]) ]) + AC_CHECK_MEMBERS([struct sockaddr.sa_len], [], [], [ + #ifdef OF_HAVE_SYS_TYPES_H + # include + #endif + #ifdef OF_HAVE_SYS_SOCKET_H + # include + #endif + #ifdef _WIN32 + # include + #endif + ]) + AC_CHECK_TYPE([struct sockaddr_storage], [ + AC_DEFINE(OF_HAVE_SOCKADDR_STORAGE, 1, + [Whether we have struct sockaddr_storage]) + ], [], [ + #ifdef OF_HAVE_SYS_TYPES_H + # include + #endif + #ifdef OF_HAVE_SYS_SOCKET_H + # include + #endif + #ifdef _WIN32 + # include + #endif + ]) AC_CHECK_HEADER(netinet/in.h, [ AC_DEFINE(OF_HAVE_NETINET_IN_H, 1, [Whether we have netinet/in.h]) ]) AC_CHECK_HEADER(netinet/tcp.h, [ AC_DEFINE(OF_HAVE_NETINET_TCP_H, 1, [Whether we have netinet/tcp.h]) ]) - AC_CHECK_HEADERS([arpa/inet.h netdb.h net/if.h]) - AC_CHECK_FUNCS([if_indextoname if_nametoindex]) + AC_CHECK_HEADERS([arpa/inet.h netdb.h sys/sockio.h]) + AC_CHECK_HEADERS([net/if.h], [], [], [ + #ifdef OF_HAVE_SYS_SOCKET_H + # include + #endif + ]) + AC_CHECK_HEADERS([net/if_arp.h net/if_dl.h net/if_types.h]) + AC_CHECK_FUNCS([if_indextoname if_nametoindex if_nameindex]) + AC_CHECK_TYPES([struct sockaddr_dl], [], [], [ + #ifdef HAVE_SYS_TYPES_H + # include + #endif + #ifdef HAVE_NET_IF_DL_H + # include + #endif + ]) + AC_CHECK_TYPES([struct lifconf], [], [], [ + #ifdef HAVE_NET_IF_H + # include + #endif + ]) + AC_CHECK_MEMBERS([struct ifreq.ifr_hwaddr], [], [], [ + #ifdef HAVE_NET_IF_H + # include + #endif + ]) AC_CHECK_HEADER(sys/un.h, [ AC_DEFINE(OF_HAVE_SYS_UN_H, 1, [Whether we have sys/un.h]) ]) AC_CHECK_MEMBER([struct sockaddr_in6.sin6_addr], [ AC_EGREP_CPP(egrep_cpp_yes, [ @@ -1471,10 +1509,25 @@ ]) AC_CHECK_MEMBER(struct sockaddr_un.sun_path, [ AC_DEFINE(OF_HAVE_UNIX_SOCKETS, 1, [Whether we have UNIX sockets]) AC_SUBST(USE_SRCS_UNIX_SOCKETS, '${SRCS_UNIX_SOCKETS}') + + AC_CHECK_MEMBERS(struct sockaddr_un.sun_len, [], [], [ + #ifdef OF_HAVE_SYS_TYPES_H + # include + #endif + #ifdef OF_HAVE_SYS_UN_H + # include + #endif + #ifdef _WIN32 + # include + #endif + #ifdef HAVE_AFUNIX_H + # include + #endif + ]) ], [], [ #ifdef OF_HAVE_SYS_TYPES_H # include #endif #ifdef OF_HAVE_SYS_UN_H @@ -1499,14 +1552,29 @@ AC_CHECK_HEADER(netipx/ipx.h, [ AC_DEFINE(OF_HAVE_NETIPX_IPX_H, 1, [Whether we have netipx/ipx.h]) ]) AC_CHECK_MEMBER(struct sockaddr_ipx.sipx_network, [], [ - AC_CHECK_MEMBER(struct sockaddr_ipx.sa_netnum, [], [], [ + AC_CHECK_MEMBER(struct sockaddr_ipx.sa_netnum, [], [ + AC_CHECK_MEMBER(struct sockaddr_ipx.sipx_addr.x_port, + [], [], [ + #ifdef HAVE_SYS_TYPES_H + # include + #endif + + #ifdef OF_HAVE_NETIPX_IPX_H + # include + #endif + ]) + ], [ #ifdef _WIN32 typedef int BOOL; #endif + + #ifdef HAVE_SYS_TYPES_H + # include + #endif #ifdef OF_HAVE_NETIPX_IPX_H # include #endif @@ -1523,10 +1591,14 @@ ]) ], [ #ifdef _WIN32 typedef int BOOL; #endif + + #ifdef HAVE_SYS_TYPES_H + # include + #endif #ifdef OF_HAVE_NETIPX_IPX_H # include #endif @@ -1540,11 +1612,12 @@ # include # include #endif ]) AS_IF([test x"$ac_cv_member_struct_sockaddr_ipx_sipx_network" = x"yes" \ - -o x"$ac_cv_member_struct_sockaddr_ipx_sa_netnum" = x"yes"], [ + -o x"$ac_cv_member_struct_sockaddr_ipx_sa_netnum" = x"yes" -o \ + x"$ac_cv_member_struct_sockaddr_ipx_sipx_addr_x_port" = x"yes"], [ AC_EGREP_CPP(egrep_cpp_yes, [ #ifdef _WIN32 typedef int BOOL; #endif @@ -1709,24 +1782,22 @@ esac AC_ARG_WITH(tls, AS_HELP_STRING([--with-tls], [ enable TLS support using the specified library - (yes, openssl, gnutls, securetransport or no)])) + (yes, openssl, gnutls, securetransport, mbedtls or + no)])) AS_IF([test x"$with_tls" = x""], [with_tls="yes"]) tls_support="no" AS_IF([test x"$with_tls" = x"securetransport" \ - -o x"$with_tls" = x"yes"], [ + -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, @@ -1737,29 +1808,12 @@ LIBS="$old_LIBS" ]) ]) - AS_IF([test x"$with_tls" = x"gnutls" \ - -o \( x"$with_tls" = x"yes" -a x"$tls_support" = x"no" \)], [ - PKG_CHECK_MODULES(gnutls, [gnutls >= 3.5.0], [ - AC_DEFINE(HAVE_GNUTLS, 1, [Whether we have GnuTLS]) - - tls_support="GnuTLS" - TLS_CPPFLAGS="$gnutls_CFLAGS $TLS_CPPFLAGS" - TLS_LIBS="$gnutls_LIBS $TLS_LIBS" - - AC_SUBST(OF_GNUTLS_TLS_STREAM_M, "OFGnuTLSTLSStream.m") - ], [ - dnl Disable default action-if-not-found, which exits - dnl configure with an error. - : - ]) - ]) - AS_IF([test x"$with_tls" = x"openssl" \ - -o \( x"$with_tls" = x"yes" -a x"$tls_support" = x"no" \)], [ + -o \( x"$with_tls" = x"yes" -a x"$tls_support" = x"no" \)], [ case "$host_os" in morphos*) ssl="ssl_shared" crypto="crypto_shared" ;; @@ -1769,21 +1823,60 @@ ;; 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") + + old_LIBS="$LIBS" + LIBS="$TLS_LIBS $LIBS" + AC_CHECK_FUNCS(SSL_has_pending) + LIBS="$old_LIBS" ]) ], [], [-l$crypto]) ]) + + AS_IF([test x"$with_tls" = x"gnutls" \ + -o \( x"$with_tls" = x"yes" -a x"$tls_support" = x"no" \)], [ + PKG_CHECK_MODULES(gnutls, [gnutls >= 3.5.0], [ + tls_support="GnuTLS" + TLS_CPPFLAGS="$gnutls_CFLAGS $TLS_CPPFLAGS" + TLS_LIBS="$gnutls_LIBS $TLS_LIBS" + + AC_SUBST(OF_GNUTLS_TLS_STREAM_M, "OFGnuTLSTLSStream.m") + ], [ + dnl Disable default action-if-not-found, which exits + dnl configure with an error. + : + ]) + ]) + + AS_IF([test x"$with_tls" = x"mbedtls"], [ + AC_ARG_WITH(mbedtls-ca-path, + AS_HELP_STRING([path to CA file for Mbed TLS])) + + AS_IF([test x"$with_mbedtls_ca_path" = x""], [ + AC_MSG_ERROR([--mbedtls-ca-path needs to be specified!]) + ]) + AC_DEFINE_UNQUOTED(OF_MBEDTLS_CA_PATH, "$with_mbedtls_ca_path", + [Path to CA file for Mbed TLS]) + + AC_CHECK_LIB(mbedtls, mbedtls_net_init, [ + AC_CHECK_HEADER(mbedtls/ssl.h, [ + tls_support="Mbed TLS" + TLS_LIBS="-lmbedx509 -lmbedcrypto $TLS_LIBS" + TLS_LIBS="-lmbedtls $TLS_LIBS" + + AC_SUBST(OF_MBEDTLS_TLS_STREAM_M, + "OFMbedTLSTLSStream.m") + ]) + ], [], [-lmbedx509 -lmbedcrypto]) + ]) AS_IF([test x"$tls_support" != x"no"], [ AC_SUBST(TLS, "tls") AC_SUBST(TLS_CPPFLAGS) AC_SUBST(TLS_LIBS) @@ -1793,11 +1886,11 @@ OFHTTP_LIBS="-lobjfwtls $TLS_LIBS $OFHTTP_LIBS" AS_IF([test x"$enable_shared" != x"no"], [ AC_SUBST(OBJFWTLS_SHARED_LIB, - "${LIB_PREFIX}objfwtls${LIB_SUFFIX}") + '${LIB_PREFIX}objfwtls${LIB_SUFFIX}') ]) AS_IF([test x"$enable_static" = x"yes" \ -o x"$enable_shared" = x"no"], [ AC_SUBST(OBJFWTLS_STATIC_LIB, "libobjfwtls.a") ]) @@ -1857,14 +1950,10 @@ (!defined(TARGET_OS_SIMULATOR) || !TARGET_OS_SIMULATOR) egrep_cpp_yes #endif ], [ AC_MSG_RESULT(yes) - have_subprocesses="yes" - - AC_CHECK_FUNCS(posix_spawnp) - AC_CHECK_HEADERS(spawn.h) ], [ AC_MSG_RESULT(no) have_subprocesses="no" ]) ;; @@ -1872,21 +1961,22 @@ have_subprocesses="yes" ;; msdosdjgpp*) have_subprocesses="no" ;; -*) +esac +AS_IF([test x"$have_subprocesses" = x""], [ AC_HEADER_SYS_WAIT AC_CHECK_FUNCS(kill) AC_CHECK_FUNCS(posix_spawnp, [ AS_IF([test x"$ac_cv_func_kill" = x"yes"], [ - have_subprocesses="yes" - - AC_CHECK_HEADERS(spawn.h) + AC_CHECK_HEADERS(spawn.h, [have_subprocesses="yes"]) ]) - ], [ + ]) + + AS_IF([test x"$have_subprocesses" = x""], [ AC_CHECK_FUNCS([vfork dup2 execvp _exit], [ AS_IF([test x"$ac_cv_func_vfork" = x"yes" \ -a x"$ac_cv_func_pipe" = x"yes" \ -a x"$ac_cv_func_dup2" = x"yes" \ -a x"$ac_cv_func_execvp" = x"yes" \ @@ -1896,19 +1986,18 @@ ]) ], [ break ]) ]) - ;; -esac +]) AS_IF([test x"$have_subprocesses" = x"yes"], [ AC_SUBST(OF_SUBPROCESS_M, "OFSubprocess.m") AC_DEFINE(OF_HAVE_SUBPROCESSES, 1, [Whether we have subprocesses]) ]) AC_CHECK_HEADERS_ONCE([complex.h sys/ioctl.h sys/ttycom.h]) -AC_CHECK_FUNCS(isatty) +AC_CHECK_FUNCS(ioctl isatty) AC_CHECK_FUNC(pledge, [ AC_DEFINE(OF_HAVE_PLEDGE, 1, [Whether we have pledge()]) ]) @@ -1917,11 +2006,11 @@ AC_SUBST(BRIDGE, "bridge") AC_CONFIG_FILES(src/bridge/Info.plist) AS_IF([test x"$enable_shared" != x"no"], [ AC_SUBST(OBJFWBRIDGE_SHARED_LIB, - "${LIB_PREFIX}objfwbridge${LIB_SUFFIX}") + '${LIB_PREFIX}objfwbridge${LIB_SUFFIX}') ]) AS_IF([test x"$enable_static" = x"yes" \ -o x"$enable_shared" = x"no"], [ AC_SUBST(OBJFWBRIDGE_STATIC_LIB, "libobjfwbridge.a") ]) @@ -1951,12 +2040,20 @@ AC_MSG_RESULT(no) OBJCFLAGS="$old_OBJCFLAGS" ]) AS_IF([test x"$GOBJC" = x"yes"], [ - OBJCFLAGS="$OBJCFLAGS -Wwrite-strings -Wpointer-arith -Werror" + OBJCFLAGS="$OBJCFLAGS -Wwrite-strings -Wpointer-arith" + + AC_ARG_ENABLE(werror, + AS_HELP_STRING([--disable-werror], [do not build with -Werror])) + AS_IF([test x"$enable_werror" != x"no"], [ + OBJCFLAGS="$OBJCFLAGS -Werror" + ]) + old_OBJCFLAGS="$OBJCFLAGS" + OBJCFLAGS="$OBJCFLAGS -Werror" AC_MSG_CHECKING(whether we need -Wno-strict-aliasing due to GCC bugs) AC_COMPILE_IFELSE([ AC_LANG_PROGRAM([ #ifdef __has_attribute # if __has_attribute(objc_root_class) @@ -1976,15 +2073,18 @@ Foo *test = (Foo *)&object; (void)test; /* Get rid of unused variable warning */ ]) ], [ AC_MSG_RESULT(no) + OBJCFLAGS="$old_OBJCFLAGS" ], [ AC_MSG_RESULT(yes) - OBJCFLAGS="$OBJCFLAGS -Wno-strict-aliasing" + OBJCFLAGS="$old_OBJCFLAGS -Wno-strict-aliasing" ]) + old_OBJCFLAGS="$OBJCFLAGS" + OBJCFLAGS="$OBJCFLAGS -Werror" AC_MSG_CHECKING( whether we need -Wno-unused-property-ivar due to Clang bugs) AC_COMPILE_IFELSE([ AC_LANG_SOURCE([ #ifdef __has_attribute @@ -2012,17 +2112,18 @@ } @end ]) ], [ AC_MSG_RESULT(no) + OBJCFLAGS="$old_OBJCFLAGS" ], [ AC_MSG_RESULT(yes) - OBJCFLAGS="$OBJCFLAGS -Wno-unused-property-ivar" + OBJCFLAGS="$old_OBJCFLAGS -Wno-unused-property-ivar" ]) old_OBJCFLAGS="$OBJCFLAGS" - OBJCFLAGS="$OBJCFLAGS -Wcast-align" + OBJCFLAGS="$OBJCFLAGS -Wcast-align -Werror" AC_MSG_CHECKING(whether -Wcast-align is buggy) AC_COMPILE_IFELSE([ AC_LANG_SOURCE([ #ifdef __has_attribute # if __has_attribute(objc_root_class) @@ -2043,17 +2144,18 @@ } @end ]) ], [ AC_MSG_RESULT(no) + OBJCFLAGS="$old_OBJCFLAGS -Wcast-align" ], [ AC_MSG_RESULT(yes) OBJCFLAGS="$old_OBJCFLAGS" ]) old_OBJCFLAGS="$OBJCFLAGS" - OBJCFLAGS="$OBJCFLAGS -Wunreachable-code" + OBJCFLAGS="$OBJCFLAGS -Wunreachable-code -Werror" AC_MSG_CHECKING(whether -Wunreachable-code can be used) AC_COMPILE_IFELSE([ AC_LANG_SOURCE([[ #include @@ -2119,17 +2221,18 @@ } @end ]]) ], [ AC_MSG_RESULT(yes) + OBJCFLAGS="$old_OBJCFLAGS -Wunreachable-code" ], [ AC_MSG_RESULT(no) OBJCFLAGS="$old_OBJCFLAGS" ]) old_OBJCFLAGS="$OBJCFLAGS" - OBJCFLAGS="$OBJCFLAGS -Wdocumentation" + OBJCFLAGS="$OBJCFLAGS -Wdocumentation -Werror" AC_MSG_CHECKING(whether -Wdocumentation works correctly) AC_COMPILE_IFELSE([ AC_LANG_SOURCE([ /** * @class Test conftest.m conftest.m @@ -2147,18 +2250,19 @@ */ typedef struct {} Foo; ]) ], [ AC_MSG_RESULT(yes) + OBJCFLAGS="$old_OBJCFLAGS -Wdocumentation" ], [ AC_MSG_RESULT(no) OBJCFLAGS="$old_OBJCFLAGS" ]) AS_IF([test x"$check_pedantic" = x"yes"], [ old_OBJCFLAGS="$OBJCFLAGS" - OBJCFLAGS="$OBJCFLAGS -pedantic" + OBJCFLAGS="$OBJCFLAGS -pedantic -Werror" AC_MSG_CHECKING(whether -pedantic is buggy) AC_COMPILE_IFELSE([ AC_LANG_SOURCE([ #include @@ -2190,17 +2294,37 @@ } @end ]) ], [ AC_MSG_RESULT(no) + OBJCFLAGS="$old_OBJCFLAGS -pedantic" ], [ AC_MSG_RESULT(yes) OBJCFLAGS="$old_OBJCFLAGS" ]) ]) + + old_OBJCFLAGS="$OBJCFLAGS" + OBJCFLAGS="$OBJCFLAGS -Werror" + AC_MSG_CHECKING(whether we need -Wno-strict-prototypes) + AC_COMPILE_IFELSE([ + AC_LANG_PROGRAM([ + #include + ], [ + signal(SIGINT, SIG_DFL); + ]) + ], [ + AC_MSG_RESULT(no) + OBJCFLAGS="$old_OBJCFLAGS" + ], [ + AC_MSG_RESULT(yes) + OBJCFLAGS="$old_OBJCFLAGS -Wno-strict-prototypes" + ]) AS_IF([test x"$ac_cv_header_complex_h" = x"yes"], [ + old_OBJCFLAGS="$OBJCFLAGS" + OBJCFLAGS="$OBJCFLAGS -Werror" AC_MSG_CHECKING(whether we need -Wno-gnu-imaginary-constant) AC_COMPILE_IFELSE([ AC_LANG_PROGRAM([ #include ], [ @@ -2207,13 +2331,14 @@ complex float f = 0.5 + 0.5 * I; (void)f; ]) ], [ AC_MSG_RESULT(no) + OBJCFLAGS="$old_OBJCFLAGS" ], [ AC_MSG_RESULT(yes) - OBJCFLAGS="$OBJCFLAGS -Wno-gnu-imaginary-constant" + OBJCFLAGS="$old_OBJCFLAGS -Wno-gnu-imaginary-constant" ]) ]) ]) AS_IF([test x"$cross_compiling" = x"yes"], [ @@ -2225,14 +2350,11 @@ ;; x86_64-*-mingw*) AC_CHECK_PROG(WINE, wine64, wine64) ;; esac - - AS_IF([test x"$WINE" != x""], [ - AC_SUBST(WRAPPER, "$WINE") - ]) + AS_IF([test x"$WINE" != x""], [AC_SUBST(WRAPPER, "$WINE")]) AS_IF([test x"$with_wii" = x"yes"], [ dnl Keep this lowercase, as WIILOAD is a variable used by dnl wiiload and thus likely already set by the user to something dnl that is not the path of the wiiload binary. @@ -2242,21 +2364,10 @@ AC_SUBST(WRAPPER, "$wiiload") ]) ]) ]) -AC_ARG_WITH(fish_completions, - AS_HELP_STRING([--with-fish-completions], - [install completions for the fish shell])) -AS_IF([test x"$with_fish_completions" = x""], [ - AC_CHECK_PROG(FISH, fish, fish) - AS_IF([test x"$FISH" != x""], [with_fish_completions="yes"]) -]) -AS_IF([test x"$with_fish_completions" = x"yes"], [ - AC_SUBST(FISH_COMPLETIONS, fish) -]) - dnl We don't call AC_PROG_CPP, but only AC_PROG_OBJCPP and set CPP to OBJCPP dnl and add OBJCPPFLAGS to CPPFLAGS, thus we need to AC_SUBST these ourself. AC_SUBST(CPP) AC_SUBST(CPPFLAGS) dnl We use the ObjC compiler as our assembler Index: extra.mk.in ================================================================== --- extra.mk.in +++ extra.mk.in @@ -1,47 +1,51 @@ OBJFW_SHARED_LIB = @OBJFW_SHARED_LIB@ OBJFW_STATIC_LIB = @OBJFW_STATIC_LIB@ OBJFW_FRAMEWORK = @OBJFW_FRAMEWORK@ -OBJFW_LIB_MAJOR = 0 -OBJFW_LIB_MINOR = 0 +OBJFW_LIB_MAJOR = 1 +OBJFW_LIB_MINOR = 1 +OBJFW_LIB_PATCH = 0 OBJFW_LIB_MAJOR_MINOR = ${OBJFW_LIB_MAJOR}.${OBJFW_LIB_MINOR} OBJFWRT_SHARED_LIB = @OBJFWRT_SHARED_LIB@ OBJFWRT_STATIC_LIB = @OBJFWRT_STATIC_LIB@ OBJFWRT_FRAMEWORK = @OBJFWRT_FRAMEWORK@ -OBJFWRT_AMIGA_LIB = @OBJFWRT_AMIGA_LIB@ -OBJFWRT_LIB_MAJOR = 0 +OBJFWRT_LIB_MAJOR = 1 OBJFWRT_LIB_MINOR = 0 +OBJFWRT_LIB_PATCH = 0 OBJFWRT_LIB_MAJOR_MINOR = ${OBJFWRT_LIB_MAJOR}.${OBJFWRT_LIB_MINOR} OBJFWBRIDGE_SHARED_LIB = @OBJFWBRIDGE_SHARED_LIB@ OBJFWBRIDGE_STATIC_LIB = @OBJFWBRIDGE_STATIC_LIB@ OBJFWBRIDGE_FRAMEWORK = @OBJFWBRIDGE_FRAMEWORK@ +OBJFWBRIDGE_LIB_MAJOR = 1 +OBJFWBRIDGE_LIB_MINOR = 0 +OBJFWBRIDGE_LIB_PATCH = 0 OBJFWTLS_SHARED_LIB = @OBJFWTLS_SHARED_LIB@ OBJFWTLS_STATIC_LIB = @OBJFWTLS_STATIC_LIB@ OBJFWTLS_FRAMEWORK = @OBJFWTLS_FRAMEWORK@ +OBJFWTLS_LIB_MAJOR = 1 +OBJFWTLS_LIB_MINOR = 0 +OBJFWTLS_LIB_PATCH = 2 BIN_PREFIX = @BIN_PREFIX@ BRIDGE = @BRIDGE@ CVINCLUDE_INLINE_H = @CVINCLUDE_INLINE_H@ ENCODINGS_A = @ENCODINGS_A@ ENCODINGS_LIB_A = @ENCODINGS_LIB_A@ ENCODINGS_SRCS = @ENCODINGS_SRCS@ EXCEPTIONS_A = @EXCEPTIONS_A@ EXCEPTIONS_LIB_A = @EXCEPTIONS_LIB_A@ -FISH_COMPLETIONS = @FISH_COMPLETIONS@ FORWARDING_A = @FORWARDING_A@ FORWARDING_LIB_A = @FORWARDING_LIB_A@ LIBBASES_M = @LIBBASES_M@ LIBOBJFWRT_DEP = @LIBOBJFWRT_DEP@ LIBOBJFWRT_DEP_LVL2 = @LIBOBJFWRT_DEP_LVL2@ LIBOBJFW_DEP = @LIBOBJFW_DEP@ LIBOBJFW_DEP_LVL2 = @LIBOBJFW_DEP_LVL2@ -LINKLIB = @LINKLIB@ LOOKUP_ASM_A = @LOOKUP_ASM_A@ -LOOKUP_ASM_AMIGALIB_A = @LOOKUP_ASM_AMIGALIB_A@ LOOKUP_ASM_LIB_A = @LOOKUP_ASM_LIB_A@ MAP_LDFLAGS = @MAP_LDFLAGS@ OBJC_SYNC = @OBJC_SYNC@ OBJFW_NEW = @OBJFW_NEW@ OFARC = @OFARC@ @@ -52,10 +56,11 @@ OF_BLOCK_TESTS_M = @OF_BLOCK_TESTS_M@ OF_EPOLL_KERNEL_EVENT_OBSERVER_M = @OF_EPOLL_KERNEL_EVENT_OBSERVER_M@ OF_GNUTLS_TLS_STREAM_M = @OF_GNUTLS_TLS_STREAM_M@ OF_HTTP_CLIENT_TESTS_M = @OF_HTTP_CLIENT_TESTS_M@ OF_KQUEUE_KERNEL_EVENT_OBSERVER_M = @OF_KQUEUE_KERNEL_EVENT_OBSERVER_M@ +OF_MBEDTLS_TLS_STREAM_M = @OF_MBEDTLS_TLS_STREAM_M@ OF_OPENSSL_TLS_STREAM_M = @OF_OPENSSL_TLS_STREAM_M@ OF_POLL_KERNEL_EVENT_OBSERVER_M = @OF_POLL_KERNEL_EVENT_OBSERVER_M@ OF_SECURE_TRANSPORT_TLS_STREAM_M = @OF_SECURE_TRANSPORT_TLS_STREAM_M@ OF_SELECT_KERNEL_EVENT_OBSERVER_M = @OF_SELECT_KERNEL_EVENT_OBSERVER_M@ OF_SUBPROCESS_M = @OF_SUBPROCESS_M@ @@ -82,9 +87,10 @@ USE_SRCS_APPLETALK = @USE_SRCS_APPLETALK@ USE_SRCS_FILES = @USE_SRCS_FILES@ USE_SRCS_IPX = @USE_SRCS_IPX@ USE_SRCS_PLUGINS = @USE_SRCS_PLUGINS@ USE_SRCS_SOCKETS = @USE_SRCS_SOCKETS@ +USE_SRCS_TAGGED_POINTERS = @USE_SRCS_TAGGED_POINTERS@ USE_SRCS_THREADS = @USE_SRCS_THREADS@ USE_SRCS_UNIX_SOCKETS = @USE_SRCS_UNIX_SOCKETS@ USE_SRCS_WINDOWS = @USE_SRCS_WINDOWS@ WRAPPER = @WRAPPER@ DELETED generators/library/FuncArrayGenerator.h Index: generators/library/FuncArrayGenerator.h ================================================================== --- generators/library/FuncArrayGenerator.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (c) 2008-2022 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#import "OFObject.h" - -#import "OFStream.h" -#import "OFXMLElement.h" - -@interface FuncArrayGenerator: OFObject -{ - OFXMLElement *_library; - OFStream *_include; -} - -- (instancetype)initWithLibrary: (OFXMLElement *)library - include: (OFStream *)include; -- (void)generate; -@end DELETED generators/library/FuncArrayGenerator.m Index: generators/library/FuncArrayGenerator.m ================================================================== --- generators/library/FuncArrayGenerator.m +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (c) 2008-2022 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#include "config.h" - -#import "OFArray.h" -#import "OFXMLAttribute.h" - -#import "FuncArrayGenerator.h" - -#import "OFInvalidFormatException.h" -#import "OFUnsupportedVersionException.h" - -#import "copyright.h" - -@implementation FuncArrayGenerator -- (instancetype)initWithLibrary: (OFXMLElement *)library - include: (OFStream *)include -{ - self = [super init]; - - @try { - OFXMLAttribute *version; - - if (![library.name isEqual: @"amiga-library"] || - library.namespace != nil) - @throw [OFInvalidFormatException exception]; - - if ((version = [library attributeForName: @"version"]) == nil) - @throw [OFInvalidFormatException exception]; - - if (![version.stringValue isEqual: @"1.0"]) - @throw [OFUnsupportedVersionException - exceptionWithVersion: version.stringValue]; - - _library = [library retain]; - _include = [include retain]; - } @catch (id e) { - [self release]; - @throw e; - } - - return self; -} - -- (void)dealloc -{ - [_library release]; - [_include release]; - - [super dealloc]; -} - -- (void)generate -{ - [_include writeString: COPYRIGHT]; - [_include writeString: - @"/* This file is automatically generated from amiga-library.xml */" - @"\n\n"]; - - for (OFXMLElement *function in [_library elementsForName: @"function"]) - [_include writeFormat: - @"(CONST_APTR)glue_%@,\n", - [function attributeForName: @"name"].stringValue]; -} -@end DELETED generators/library/GlueGenerator.h Index: generators/library/GlueGenerator.h ================================================================== --- generators/library/GlueGenerator.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (c) 2008-2022 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#import "OFObject.h" - -#import "OFStream.h" -#import "OFXMLElement.h" - -@interface GlueGenerator: OFObject -{ - OFXMLElement *_library; - OFStream *_header, *_impl; -} - -- (instancetype)initWithLibrary: (OFXMLElement *)library - header: (OFStream *)header - implementation: (OFStream *)implementation; -- (void)generate; -@end DELETED generators/library/GlueGenerator.m Index: generators/library/GlueGenerator.m ================================================================== --- generators/library/GlueGenerator.m +++ /dev/null @@ -1,207 +0,0 @@ -/* - * Copyright (c) 2008-2022 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#include "config.h" - -#import "OFArray.h" -#import "OFXMLAttribute.h" - -#import "GlueGenerator.h" - -#import "OFInvalidFormatException.h" -#import "OFUnsupportedVersionException.h" - -#import "copyright.h" - -@implementation GlueGenerator -- (instancetype)initWithLibrary: (OFXMLElement *)library - header: (OFStream *)header - implementation: (OFStream *)impl -{ - self = [super init]; - - @try { - OFXMLAttribute *version; - - if (![library.name isEqual: @"amiga-library"] || - library.namespace != nil) - @throw [OFInvalidFormatException exception]; - - if ((version = [library attributeForName: @"version"]) == nil) - @throw [OFInvalidFormatException exception]; - - if (![version.stringValue isEqual: @"1.0"]) - @throw [OFUnsupportedVersionException - exceptionWithVersion: version.stringValue]; - - _library = [library retain]; - _header = [header retain]; - _impl = [impl retain]; - } @catch (id e) { - [self release]; - @throw e; - } - - return self; -} - -- (void)dealloc -{ - [_library release]; - [_header release]; - [_impl release]; - - [super dealloc]; -} - -- (void)generate -{ - [_header writeString: COPYRIGHT]; - [_impl writeString: COPYRIGHT]; - - [_header writeString: - @"/* This file is automatically generated from amiga-library.xml */" - @"\n\n"]; - - [_impl writeString: - @"/* This file is automatically generated from amiga-library.xml */" - @"\n\n" - @"#include \"config.h\"\n" - @"\n" - @"#import \"amiga-glue.h\"\n" - @"\n"]; - - for (OFXMLElement *include in [_library elementsForName: @"include"]) - [_header writeFormat: @"#import \"%@\"\n", include.stringValue]; - - [_header writeString: - @"\n" - @"#ifdef OF_AMIGAOS_M68K\n" - @"# define PPC_PARAMS(...) (void)\n" - @"# define M68K_ARG(type, name, reg)\t\t\\\n" - @"\tregister type reg##name __asm__(#reg);\t\\\n" - @"\ttype name = reg##name;\n" - @"#else\n" - @"# define PPC_PARAMS(...) (__VA_ARGS__)\n" - @"# define M68K_ARG(...)\n" - @"#endif\n" - @"\n"]; - [_impl writeString: - @"#ifdef OF_MORPHOS\n" - @"/* All __saveds functions in this file need to use the SysV " - @"ABI */\n" - @"__asm__ (\n" - @" \".section .text\\n\"\n" - @" \".align 2\\n\"\n" - @" \"__restore_r13:\\n\"\n" - @" \"\tlwz\t%r13, 44(%r12)\\n\"\n" - @" \"\tblr\\n\"\n" - @");\n" - @"#endif\n"]; - - for (OFXMLElement *function in - [_library elementsForName: @"function"]) { - OFString *name = - [function attributeForName: @"name"].stringValue; - OFString *returnType = - [function attributeForName: @"return-type"].stringValue; - OFArray OF_GENERIC(OFXMLElement *) *arguments = - [function elementsForName: @"argument"]; - size_t argumentIndex; - - if (returnType == nil) - returnType = @"void"; - - [_header writeFormat: - @"extern %@%@glue_%@", - returnType, - (![returnType hasSuffix: @"*"] ? @" " : @""), - name]; - - [_impl writeFormat: @"\n" - @"%@ __saveds\n" - @"glue_%@", - returnType, name]; - - if (arguments.count > 0) { - [_header writeString: @" PPC_PARAMS("]; - [_impl writeString: @" PPC_PARAMS("]; - } else { - [_header writeString: @"(void"]; - [_impl writeString: @"(void"]; - } - - argumentIndex = 0; - for (OFXMLElement *argument in arguments) { - OFString *argName = - [argument attributeForName: @"name"].stringValue; - OFString *argType = - [argument attributeForName: @"type"].stringValue; - - if (argumentIndex++ > 0) { - [_header writeString: @", "]; - [_impl writeString: @", "]; - } - - [_header writeString: argType]; - [_impl writeString: argType]; - if (![argType hasSuffix: @"*"]) { - [_header writeString: @" "]; - [_impl writeString: @" "]; - } - [_header writeString: argName]; - [_impl writeString: argName]; - } - - [_header writeString: @");\n"]; - - [_impl writeString: @")\n{\n"]; - for (OFXMLElement *argument in arguments) { - OFString *argName = - [argument attributeForName: @"name"].stringValue; - OFString *argType = - [argument attributeForName: @"type"].stringValue; - OFString *m68kReg = [argument - attributeForName: @"m68k-reg"].stringValue; - - [_impl writeFormat: @"\tM68K_ARG(%@, %@, %@)\n", - argType, argName, m68kReg]; - } - - if (arguments.count > 0) - [_impl writeString: @"\n"]; - - if (![returnType isEqual: @"void"]) - [_impl writeString: @"\treturn "]; - else - [_impl writeString: @"\t"]; - - [_impl writeFormat: @"%@(", name]; - - argumentIndex = 0; - for (OFXMLElement *argument in arguments) { - OFString *argName = - [argument attributeForName: @"name"].stringValue; - - if (argumentIndex++ > 0) - [_impl writeString: @", "]; - - [_impl writeString: argName]; - } - - [_impl writeString: @");\n}\n"]; - } -} -@end DELETED generators/library/LibraryGenerator.m Index: generators/library/LibraryGenerator.m ================================================================== --- generators/library/LibraryGenerator.m +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (c) 2008-2022 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#include "config.h" - -#import "OFApplication.h" -#import "OFFile.h" -#import "OFFileManager.h" -#import "OFURI.h" -#import "OFXMLElement.h" - -#import "FuncArrayGenerator.h" -#import "GlueGenerator.h" -#import "LinkLibGenerator.h" - -@interface LibraryGenerator: OFObject -@end - -OF_APPLICATION_DELEGATE(LibraryGenerator) - -@implementation LibraryGenerator -- (void)applicationDidFinishLaunching -{ - OFURI *sourcesURI = [[OFFileManager defaultManager].currentDirectoryURI - URIByAppendingPathComponent: @"../../src"]; - OFURI *runtimeLibraryURI = [sourcesURI - URIByAppendingPathComponent: @"runtime/amiga-library.xml"]; - OFURI *runtimeLinkLibURI = [sourcesURI - URIByAppendingPathComponent: @"runtime/linklib/linklib.m"]; - OFURI *runtimeGlueHeaderURI = [sourcesURI - URIByAppendingPathComponent: @"runtime/amiga-glue.h"]; - OFURI *runtimeGlueURI = [sourcesURI - URIByAppendingPathComponent: @"runtime/amiga-glue.m"]; - OFURI *runtimeFuncArrayURI = [sourcesURI - URIByAppendingPathComponent: @"runtime/amiga-funcarray.inc"]; - OFXMLElement *runtimeLibrary = [OFXMLElement elementWithStream: - [OFFile fileWithPath: runtimeLibraryURI.fileSystemRepresentation - mode: @"r"]]; - OFFile *runtimeLinkLib = - [OFFile fileWithPath: runtimeLinkLibURI.fileSystemRepresentation - mode: @"w"]; - OFFile *runtimeGlueHeader = - [OFFile fileWithPath: runtimeGlueHeaderURI.fileSystemRepresentation - mode: @"w"]; - OFFile *runtimeGlue = - [OFFile fileWithPath: runtimeGlueURI.fileSystemRepresentation - mode: @"w"]; - OFFile *runtimeFuncArray = - [OFFile fileWithPath: runtimeFuncArrayURI.fileSystemRepresentation - mode: @"w"]; - LinkLibGenerator *runtimeLinkLibGenerator = [[[LinkLibGenerator alloc] - initWithLibrary: runtimeLibrary - implementation: runtimeLinkLib] autorelease]; - GlueGenerator *runtimeGlueGenerator = [[[GlueGenerator alloc] - initWithLibrary: runtimeLibrary - header: runtimeGlueHeader - implementation: runtimeGlue] autorelease]; - FuncArrayGenerator *runtimeFuncArrayGenerator; - runtimeFuncArrayGenerator = [[[FuncArrayGenerator alloc] - initWithLibrary: runtimeLibrary - include: runtimeFuncArray] autorelease]; - - [runtimeLinkLibGenerator generate]; - [runtimeGlueGenerator generate]; - [runtimeFuncArrayGenerator generate]; - - [OFApplication terminate]; -} -@end DELETED generators/library/LinkLibGenerator.h Index: generators/library/LinkLibGenerator.h ================================================================== --- generators/library/LinkLibGenerator.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (c) 2008-2022 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#import "OFObject.h" -#import "OFStream.h" -#import "OFXMLElement.h" - -@interface LinkLibGenerator: OFObject -{ - OFXMLElement *_library; - OFStream *_impl; -} - -- (instancetype)initWithLibrary: (OFXMLElement *)library - implementation: (OFStream *)impl; -- (void)generate; -@end DELETED generators/library/LinkLibGenerator.m Index: generators/library/LinkLibGenerator.m ================================================================== --- generators/library/LinkLibGenerator.m +++ /dev/null @@ -1,226 +0,0 @@ -/* - * Copyright (c) 2008-2022 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#include "config.h" - -#import "OFArray.h" -#import "OFXMLAttribute.h" - -#import "LinkLibGenerator.h" - -#import "OFInvalidFormatException.h" -#import "OFUnsupportedVersionException.h" - -#import "copyright.h" - -@implementation LinkLibGenerator -- (instancetype)initWithLibrary: (OFXMLElement *)library - implementation: (OFStream *)impl -{ - self = [super init]; - - @try { - OFXMLAttribute *version; - - if (![library.name isEqual: @"amiga-library"] || - library.namespace != nil) - @throw [OFInvalidFormatException exception]; - - if ((version = [library attributeForName: @"version"]) == nil) - @throw [OFInvalidFormatException exception]; - - if (![version.stringValue isEqual: @"1.0"]) - @throw [OFUnsupportedVersionException - exceptionWithVersion: version.stringValue]; - - _library = [library retain]; - _impl = [impl retain]; - } @catch (id e) { - [self release]; - @throw e; - } - - return self; -} - -- (void)dealloc -{ - [_library release]; - [_impl release]; - - [super dealloc]; -} - -- (void)generate -{ - OFString *libBase = [_library attributeForName: @"base"].stringValue; - OFArray OF_GENERIC(OFXMLElement *) *functions; - size_t funcIndex = 0; - - [_impl writeString: COPYRIGHT]; - [_impl writeString: - @"/* This file is automatically generated from amiga-library.xml */" - @"\n\n" - @"#include \"config.h\"\n" - @"\n"]; - - for (OFXMLElement *include in [_library elementsForName: @"include"]) - [_impl writeFormat: @"#import \"%@\"\n", - include.stringValue]; - - [_impl writeFormat: @"\n" - @"extern struct Library *%@;\n" - @"\n", - libBase]; - - functions = [_library elementsForName: @"function"]; - for (OFXMLElement *function in functions) { - OFString *name = - [function attributeForName: @"name"].stringValue; - OFString *returnType = - [function attributeForName: @"return-type"].stringValue; - OFArray OF_GENERIC(OFXMLElement *) *arguments = - [function elementsForName: @"argument"]; - size_t argumentIndex; - - if (returnType == nil) - returnType = @"void"; - - [_impl writeFormat: @"%@\n%@(", returnType, name]; - - argumentIndex = 0; - for (OFXMLElement *argument in - [function elementsForName: @"argument"]) { - OFString *argName = - [argument attributeForName: @"name"].stringValue; - OFString *argType = - [argument attributeForName: @"type"].stringValue; - - if (argumentIndex++ > 0) - [_impl writeString: @", "]; - - [_impl writeString: argType]; - if (![argType hasSuffix: @"*"]) - [_impl writeString: @" "]; - [_impl writeString: argName]; - } - - [_impl writeFormat: - @")\n" - @"{\n" - @"#if defined(OF_AMIGAOS_M68K)\n" - @"\tregister struct Library *a6 __asm__(\"a6\") = %@;\n" - @"\t(void)a6;\n" - @"\t", libBase]; - - if (![returnType isEqual: @"void"]) - [_impl writeString: @"return "]; - - [_impl writeString: @"(("]; - [_impl writeString: returnType]; - if (![returnType hasSuffix: @"*"]) - [_impl writeString: @" "]; - [_impl writeString: @"(*)("]; - - argumentIndex = 0; - for (OFXMLElement *argument in arguments) { - OFString *argType = - [argument attributeForName: @"type"].stringValue; - OFString *m68kReg = [argument - attributeForName: @"m68k-reg"].stringValue; - - if (argumentIndex++ > 0) - [_impl writeString: @", "]; - - [_impl writeString: argType]; - if (![argType hasSuffix: @"*"]) - [_impl writeString: @" "]; - [_impl writeFormat: @"__asm__(\"%@\")", - m68kReg]; - } - - [_impl writeFormat: @"))(((uintptr_t)%@) - %zu))(", - libBase, 30 + funcIndex * 6]; - - argumentIndex = 0; - for (OFXMLElement *argument in - [function elementsForName: @"argument"]) { - OFString *argName = - [argument attributeForName: @"name"].stringValue; - - if (argumentIndex++ > 0) - [_impl writeString: @", "]; - - [_impl writeString: argName]; - } - - [_impl writeFormat: @");\n" - @"#elif defined(OF_MORPHOS)\n" - @"\t__asm__ __volatile__ (\n" - @"\t \"mr\t\t%%%%r12, %%0\"\n" - @"\t :: \"r\"(%@) : \"r12\"\n" - @"\t);\n" - @"\n" - @"\t", - libBase, libBase]; - - if (![returnType isEqual: @"void"]) - [_impl writeString: @"return "]; - - [_impl writeString: @"__extension__ (("]; - [_impl writeString: returnType]; - if (![returnType hasSuffix: @"*"]) - [_impl writeString: @" "]; - [_impl writeString: @"(*)("]; - - argumentIndex = 0; - for (OFXMLElement *argument in arguments) { - OFString *argType = - [argument attributeForName: @"type"].stringValue; - - if (argumentIndex++ > 0) - [_impl writeString: @", "]; - - [_impl writeString: argType]; - } - - [_impl writeFormat: @"))*(void **)(((uintptr_t)%@) - %zu))(", - libBase, 28 + funcIndex * 6]; - - argumentIndex = 0; - for (OFXMLElement *argument in - [function elementsForName: @"argument"]) { - OFString *argName = - [argument attributeForName: @"name"].stringValue; - - if (argumentIndex++ > 0) - [_impl writeString: @", "]; - - [_impl writeString: argName]; - } - - [_impl writeString: @");\n" - @"#endif\n"]; - - if ([function attributeForName: @"noreturn"] != nil) - [_impl writeString: @"\n\tOF_UNREACHABLE\n"]; - - [_impl writeString: @"}\n"]; - - if (++funcIndex < functions.count) - [_impl writeString: @"\n"]; - } -} -@end DELETED generators/library/Makefile Index: generators/library/Makefile ================================================================== --- generators/library/Makefile +++ /dev/null @@ -1,75 +0,0 @@ -include ../../extra.mk - -PROG_NOINST = gen_libraries${PROG_SUFFIX} -SRCS = FuncArrayGenerator.m \ - GlueGenerator.m \ - LibraryGenerator.m \ - LinkLibGenerator.m - -include ../../buildsys.mk - -.PHONY: run -run: all - rm -f libobjfw.so.${OBJFW_LIB_MAJOR} - rm -f libobjfw.so.${OBJFW_LIB_MAJOR_MINOR} - rm -f objfw${OBJFW_LIB_MAJOR}.dll libobjfw.${OBJFW_LIB_MAJOR}.dylib - rm -f libobjfwrt.so.${OBJFWRT_LIB_MAJOR} - rm -f libobjfwrt.so.${OBJFWRT_LIB_MAJOR_MINOR} - rm -f objfwrt${OBJFWRT_LIB_MAJOR}.dll - rm -f libobjfwrt.${OBJFWRT_LIB_MAJOR}.dylib - rm -f ${OBJFWRT_AMIGA_LIB} - if test -f ../../src/libobjfw.so; then \ - ${LN_S} ../../src/libobjfw.so libobjfw.so.${OBJFW_LIB_MAJOR}; \ - ${LN_S} ../../src/libobjfw.so \ - libobjfw.so.${OBJFW_LIB_MAJOR_MINOR}; \ - elif test -f ../../src/libobjfw.so.${OBJFW_LIB_MAJOR_MINOR}; then \ - ${LN_S} ../../src/libobjfw.so.${OBJFW_LIB_MAJOR_MINOR} \ - libobjfw.so.${OBJFW_LIB_MAJOR_MINOR}; \ - fi - if test -f ../../src/objfw${OBJFW_LIB_MAJOR}.dll; then \ - ${LN_S} ../../src/objfw${OBJFW_LIB_MAJOR}.dll \ - objfw${OBJFW_LIB_MAJOR}.dll; \ - fi - if test -f ../../src/libobjfw.dylib; then \ - ${LN_S} ../../src/libobjfw.dylib \ - libobjfw.${OBJFW_LIB_MAJOR}.dylib; \ - fi - if test -f ../../src/runtime/libobjfwrt.so; then \ - ${LN_S} ../../src/runtime/libobjfwrt.so \ - libobjfwrt.so.${OBJFWRT_LIB_MAJOR}; \ - ${LN_S} ../../src/runtime/libobjfwrt.so \ - libobjfwrt.so.${OBJFWRT_LIB_MAJOR_MINOR}; \ - elif test -f ../../src/runtime/libobjfwrt.so.${OBJFWRT_LIB_MAJOR_MINOR}; then \ - ${LN_S} ../../src/runtime/libobjfwrt.so.${OBJFWRT_LIB_MAJOR_MINOR} libobjfwrt.so.${OBJFWRT_LIB_MAJOR_MINOR}; \ - fi - if test -f ../../src/runtime/objfwrt${OBJFWRT_LIB_MAJOR}.dll; then \ - ${LN_S} ../../src/runtime/objfwrt${OBJFWRT_LIB_MAJOR}.dll \ - objfwrt${OBJFWRT_LIB_MAJOR}.dll; \ - fi - if test -f ../../src/runtime/libobjfwrt.dylib; then \ - ${LN_S} ../../src/runtime/libobjfwrt.dylib \ - libobjfwrt.${OBJFWRT_LIB_MAJOR}.dylib; \ - fi - if test -f ../../src/runtime/${OBJFWRT_AMIGA_LIB}; then \ - ${LN_S} ../../src/runtime/${OBJFWRT_AMIGA_LIB} \ - ${OBJFWRT_AMIGA_LIB}; \ - fi - LD_LIBRARY_PATH=.$${LD_LIBRARY_PATH+:}$$LD_LIBRARY_PATH \ - DYLD_FRAMEWORK_PATH=../../src:../../src/runtime$${DYLD_FRAMEWORK_PATH+:}$$DYLD_FRAMEWORK_PATH \ - DYLD_LIBRARY_PATH=.$${DYLD_LIBRARY_PATH+:}$$DYLD_LIBRARY_PATH \ - LIBRARY_PATH=.$${LIBRARY_PATH+:}$$LIBRARY_PATH \ - ASAN_OPTIONS=allocator_may_return_null=1 \ - ${WRAPPER} ./${PROG_NOINST}; EXIT=$$?; \ - rm -f libobjfw.so.${OBJFW_LIB_MAJOR}; \ - rm -f libobjfw.so.${OBJFW_LIB_MAJOR_MINOR}; \ - rm -f objfw${OBJFW_LIB_MAJOR}.dll; \ - rm -f libobjfw.${OBJFW_LIB_MAJOR}.dylib; \ - rm -f libobjfwrt.so.${OBJFWRT_LIB_MAJOR}; \ - rm -f libobjfwrt.so.${OBJFWRT_LIB_MAJOR_MINOR}; \ - rm -f objfwrt${OBJFWRT_LIB_MAJOR}.dll; \ - rm -f libobjfwrt.${OBJFWRT_LIB_MAJOR}.dylib; \ - exit $$EXIT - -CPPFLAGS += -I../../src -I../../src/exceptions -I../../src/runtime -I../.. -LIBS := -L../../src -lobjfw -L../../src/runtime ${RUNTIME_LIBS} ${LIBS} -LD = ${OBJC} DELETED generators/library/copyright.h Index: generators/library/copyright.h ================================================================== --- generators/library/copyright.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2008-2022 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#import "OFString.h" - -#define COPYRIGHT \ - @"/*\n" \ - @" * Copyright (c) 2008-2022 Jonathan Schleifer \n" \ - @" *\n" \ - @" * All rights reserved.\n" \ - @" *\n" \ - @" * This file is part of ObjFW. It may be distributed under the terms " \ - @"of the\n" \ - @" * Q Public License 1.0, which can be found in the file LICENSE.QPL " \ - @"included in\n" \ - @" * the packaging of this file.\n" \ - @" *\n" \ - @" * Alternatively, it may be distributed under the terms of the GNU " \ - @"General\n" \ - @" * Public License, either version 2 or 3, which can be found in the " \ - @"file\n" \ - @" * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the " \ - @"packaging of this\n" \ - @" * file.\n" \ - @" */\n" \ - @"\n" Index: generators/unicode/Makefile ================================================================== --- generators/unicode/Makefile +++ generators/unicode/Makefile @@ -12,11 +12,10 @@ rm -f objfw${OBJFW_LIB_MAJOR}.dll libobjfw.${OBJFW_LIB_MAJOR}.dylib rm -f libobjfwrt.so.${OBJFWRT_LIB_MAJOR} rm -f libobjfwrt.so.${OBJFWRT_LIB_MAJOR_MINOR} rm -f objfwrt${OBJFWRT_LIB_MAJOR}.dll rm -f libobjfwrt.${OBJFWRT_LIB_MAJOR}.dylib - rm -f ${OBJFWRT_AMIGA_LIB} if test -f ../../src/libobjfw.so; then \ ${LN_S} ../../src/libobjfw.so libobjfw.so.${OBJFW_LIB_MAJOR}; \ ${LN_S} ../../src/libobjfw.so \ libobjfw.so.${OBJFW_LIB_MAJOR_MINOR}; \ elif test -f ../../src/libobjfw.so.${OBJFW_LIB_MAJOR_MINOR}; then \ @@ -45,14 +44,10 @@ fi if test -f ../../src/runtime/libobjfwrt.dylib; then \ ${LN_S} ../../src/runtime/libobjfwrt.dylib \ libobjfwrt.${OBJFWRT_LIB_MAJOR}.dylib; \ fi - if test -f ../../src/runtime/${OBJFWRT_AMIGA_LIB}; then \ - ${LN_S} ../../src/runtime/${OBJFWRT_AMIGA_LIB} \ - ${OBJFWRT_AMIGA_LIB}; \ - fi LD_LIBRARY_PATH=.$${LD_LIBRARY_PATH+:}$$LD_LIBRARY_PATH \ DYLD_FRAMEWORK_PATH=../../src:../../src/runtime$${DYLD_FRAMEWORK_PATH+:}$$DYLD_FRAMEWORK_PATH \ DYLD_LIBRARY_PATH=.$${DYLD_LIBRARY_PATH+:}$$DYLD_LIBRARY_PATH \ LIBRARY_PATH=.$${LIBRARY_PATH+:}$$LIBRARY_PATH \ ASAN_OPTIONS=allocator_may_return_null=1 \ Index: generators/unicode/TableGenerator.h ================================================================== --- generators/unicode/TableGenerator.h +++ generators/unicode/TableGenerator.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,32 +24,25 @@ OFHTTPClient *_HTTPClient; OFUnichar _uppercaseTable[0x110000]; OFUnichar _lowercaseTable[0x110000]; OFUnichar _titlecaseTable[0x110000]; OFUnichar _caseFoldingTable[0x110000]; - OFString *_decompositionTable[0x110000]; - OFString *_decompositionCompatTable[0x110000]; char _uppercaseTableUsed[0x1100]; char _lowercaseTableUsed[0x1100]; char _titlecaseTableUsed[0x1100]; char _caseFoldingTableUsed[0x1100]; - char _decompositionTableUsed[0x1100]; - char _decompositionCompatTableUsed[0x1100]; size_t _uppercaseTableSize; size_t _lowercaseTableSize; size_t _titlecaseTableSize; size_t _caseFoldingTableSize; - size_t _decompositionTableSize; - size_t _decompositionCompatTableSize; enum { stateUnicodeData, stateCaseFolding } _state; } - (void)parseUnicodeData: (OFHTTPResponse *)response; - (void)parseCaseFolding: (OFHTTPResponse *)response; -- (void)applyDecompositionRecursivelyForTable: (OFString *[0x110000])table; - (void)writeFiles; - (void)writeTablesToFile: (OFString *)path; - (void)writeHeaderToFile: (OFString *)path; @end Index: generators/unicode/TableGenerator.m ================================================================== --- generators/unicode/TableGenerator.m +++ generators/unicode/TableGenerator.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,28 +15,28 @@ #include "config.h" #include -#import "OFString.h" +#import "OFApplication.h" #import "OFArray.h" -#import "OFApplication.h" -#import "OFURI.h" +#import "OFFile.h" +#import "OFHTTPClient.h" #import "OFHTTPRequest.h" #import "OFHTTPResponse.h" -#import "OFHTTPClient.h" -#import "OFFile.h" +#import "OFIRI.h" #import "OFStdIOStream.h" +#import "OFString.h" #import "OFOutOfRangeException.h" #import "TableGenerator.h" #import "copyright.h" -static OFString *const unicodeDataURI = +static OFString *const unicodeDataIRI = @"http://www.unicode.org/Public/UNIDATA/UnicodeData.txt"; -static OFString *const caseFoldingURI = +static OFString *const caseFoldingIRI = @"http://www.unicode.org/Public/UNIDATA/CaseFolding.txt"; OF_APPLICATION_DELEGATE(TableGenerator) @implementation TableGenerator @@ -50,28 +50,26 @@ _uppercaseTableSize = SIZE_MAX; _lowercaseTableSize = SIZE_MAX; _titlecaseTableSize = SIZE_MAX; _caseFoldingTableSize = SIZE_MAX; - _decompositionTableSize = SIZE_MAX; - _decompositionCompatTableSize = SIZE_MAX; } @catch (id e) { [self release]; @throw e; } return self; } -- (void)applicationDidFinishLaunching +- (void)applicationDidFinishLaunching: (OFNotification *)notification { OFHTTPRequest *request; [OFStdOut writeString: @"Downloading UnicodeData.txt…"]; _state = stateUnicodeData; - request = [OFHTTPRequest requestWithURI: - [OFURI URIWithString: unicodeDataURI]]; + request = [OFHTTPRequest requestWithIRI: + [OFIRI IRIWithString: unicodeDataIRI]]; [_HTTPClient asyncPerformRequest: request]; } - (void)client: (OFHTTPClient *)client didPerformRequest: (OFHTTPRequest *)request @@ -127,51 +125,19 @@ _lowercaseTable[codePoint] = (OFUnichar)[[components objectAtIndex: 13] unsignedLongLongValueWithBase: 16]; _titlecaseTable[codePoint] = (OFUnichar)[[components objectAtIndex: 14] unsignedLongLongValueWithBase: 16]; - if ([[components objectAtIndex: 5] length] > 0) { - OFArray *decomposed = [[components objectAtIndex: 5] - componentsSeparatedByString: @" "]; - bool compat = false; - OFMutableString *string; - - if ([decomposed.firstObject hasPrefix: @"<"]) { - decomposed = [decomposed objectsInRange: - OFMakeRange(1, decomposed.count - 1)]; - compat = true; - } - - string = [OFMutableString string]; - - for (OFString *character in decomposed) { - OFUnichar unichar = (OFUnichar)[character - unsignedLongLongValueWithBase: 16]; - - [string appendCharacters: &unichar - length: 1]; - } - - [string makeImmutable]; - - if (!compat) - _decompositionTable[codePoint] = [string copy]; - _decompositionCompatTable[codePoint] = [string copy]; - } - objc_autoreleasePoolPop(pool2); } - [self applyDecompositionRecursivelyForTable: _decompositionTable]; - [self applyDecompositionRecursivelyForTable: _decompositionCompatTable]; - [OFStdOut writeLine: @" done"]; [OFStdOut writeString: @"Downloading CaseFolding.txt…"]; _state = stateCaseFolding; - request = [OFHTTPRequest requestWithURI: - [OFURI URIWithString: caseFoldingURI]]; + request = [OFHTTPRequest requestWithIRI: + [OFIRI IRIWithString: caseFoldingIRI]]; [_HTTPClient asyncPerformRequest: request]; } - (void)parseCaseFolding: (OFHTTPResponse *)response { @@ -214,73 +180,21 @@ [OFStdOut writeLine: @" done"]; [self writeFiles]; } -- (void)applyDecompositionRecursivelyForTable: (OFString *[0x110000])table -{ - bool done; - - do { - done = true; - - for (OFUnichar i = 0; i < 0x110000; i++) { - void *pool; - const OFUnichar *characters; - size_t length; - OFMutableString *replacement; - bool changed = false; - - if (table[i] == nil) - continue; - - pool = objc_autoreleasePoolPush(); - characters = table[i].characters; - length = table[i].length; - replacement = [OFMutableString string]; - - for (size_t j = 0; j < length; j++) { - if (characters[j] > 0x10FFFF) - @throw [OFOutOfRangeException - exception]; - - if (table[characters[j]] == nil) - [replacement - appendCharacters: &characters[j] - length: 1]; - else { - [replacement - appendString: table[characters[j]]]; - changed = true; - } - } - - [replacement makeImmutable]; - - if (changed) { - [table[i] release]; - table[i] = [replacement copy]; - - done = false; - } - - objc_autoreleasePoolPop(pool); - } - } while (!done); -} - - (void)writeFiles { - OFURI *URI; + OFIRI *IRI; [OFStdOut writeString: @"Writing files…"]; - URI = [OFURI fileURIWithPath: @"../../src/unicode.m"]; - [self writeTablesToFile: URI.fileSystemRepresentation]; + IRI = [OFIRI fileIRIWithPath: @"../../src/unicode.m"]; + [self writeTablesToFile: IRI.fileSystemRepresentation]; - URI = [OFURI fileURIWithPath: @"../../src/unicode.h"]; - [self writeHeaderToFile: URI.fileSystemRepresentation]; + IRI = [OFIRI fileIRIWithPath: @"../../src/unicode.h"]; + [self writeHeaderToFile: IRI.fileSystemRepresentation]; [OFStdOut writeLine: @" done"]; [OFApplication terminate]; } @@ -294,11 +208,10 @@ [file writeString: COPYRIGHT @"#include \"config.h\"\n" @"\n" @"#import \"OFString.h\"\n\n" @"static const OFUnichar emptyPage[0x100] = { 0 };\n" - @"static const char *emptyDecompositionPage[0x100] = { NULL };\n" @"\n"]; /* Write uppercasePage%u */ for (OFUnichar i = 0; i < 0x110000; i += 0x100) { bool isEmpty = true; @@ -455,139 +368,18 @@ objc_autoreleasePoolPop(pool2); } } - /* Write decompositionPage%u */ - for (OFUnichar i = 0; i < 0x110000; i += 0x100) { - bool isEmpty = true; - - for (OFUnichar j = i; j < i + 0x100; j++) { - if (_decompositionTable[j] != nil) { - isEmpty = false; - _decompositionTableSize = i >> 8; - _decompositionTableUsed[ - _decompositionTableSize] = 1; - break; - } - } - - if (!isEmpty) { - void *pool2 = objc_autoreleasePoolPush(); - - [file writeFormat: @"static const char *const " - @"decompositionPage%u[0x100] = {\n", - i >> 8]; - - for (OFUnichar j = i; j < i + 0x100; j++) { - if ((j - i) % 2 == 0) - [file writeString: @"\t"]; - else - [file writeString: @" "]; - - if (_decompositionTable[j] != nil) { - const char *UTF8String = - _decompositionTable[j].UTF8String; - size_t length = _decompositionTable[j] - .UTF8StringLength; - - [file writeString: @"\""]; - - for (size_t k = 0; k < length; k++) - [file writeFormat: - @"\\x%02X", - (uint8_t)UTF8String[k]]; - - [file writeString: @"\","]; - } else - [file writeString: @"NULL,"]; - - if ((j - i) % 2 == 1) - [file writeString: @"\n"]; - } - - [file writeString: @"};\n\n"]; - - objc_autoreleasePoolPop(pool2); - } - } - - /* Write decompCompatPage%u if it does NOT match decompositionPage%u */ - for (OFUnichar i = 0; i < 0x110000; i += 0x100) { - bool isEmpty = true; - - for (OFUnichar j = i; j < i + 0x100; j++) { - if (_decompositionCompatTable[j] != 0) { - /* - * We bulk-compare pointers via memcmp here. - * This is safe, as we always set the same - * pointer in both tables if both are the same. - */ - isEmpty = !memcmp(_decompositionTable + i, - _decompositionCompatTable + i, - 256 * sizeof(const char *)); - _decompositionCompatTableSize = i >> 8; - _decompositionCompatTableUsed[ - _decompositionCompatTableSize] = - (isEmpty ? 2 : 1); - - break; - } - } - - if (!isEmpty) { - void *pool2 = objc_autoreleasePoolPush(); - - [file writeFormat: @"static const char *const " - @"decompCompatPage%u[0x100] = {\n", - i >> 8]; - - for (OFUnichar j = i; j < i + 0x100; j++) { - if ((j - i) % 2 == 0) - [file writeString: @"\t"]; - else - [file writeString: @" "]; - - if (_decompositionCompatTable[j] != nil) { - const char *UTF8String = - _decompositionCompatTable[j] - .UTF8String; - size_t length = - _decompositionCompatTable[j] - .UTF8StringLength; - - [file writeString: @"\""]; - - for (size_t k = 0; k < length; k++) - [file writeFormat: - @"\\x%02X", - (uint8_t)UTF8String[k]]; - - [file writeString: @"\","]; - } else - [file writeString: @"NULL,"]; - - if ((j - i) % 2 == 1) - [file writeString: @"\n"]; - } - - [file writeString: @"};\n\n"]; - - objc_autoreleasePoolPop(pool2); - } - } - /* * Those are currently set to the last index. * But from now on, we need the size. */ _uppercaseTableSize++; _lowercaseTableSize++; _titlecaseTableSize++; _caseFoldingTableSize++; - _decompositionTableSize++; - _decompositionCompatTableSize++; /* Write OFUnicodeUppercaseTable */ [file writeFormat: @"const OFUnichar *const " @"OFUnicodeUppercaseTable[0x%X] = {\n\t", _uppercaseTableSize]; @@ -673,55 +465,10 @@ } } [file writeString: @"\n};\n\n"]; - /* Write OFUnicodeDecompositionTable */ - [file writeFormat: @"const char *const " - @"*OFUnicodeDecompositionTable[0x%X] = {\n\t", - _decompositionTableSize]; - - for (OFUnichar i = 0; i < _decompositionTableSize; i++) { - if (_decompositionTableUsed[i]) - [file writeFormat: @"decompositionPage%u", i]; - else - [file writeString: @"emptyDecompositionPage"]; - - if (i + 1 < _decompositionTableSize) { - if ((i + 1) % 3 == 0) - [file writeString: @",\n\t"]; - else - [file writeString: @", "]; - } - } - - [file writeString: @"\n};\n\n"]; - - /* Write OFUnicodeDecompositionCompatTable */ - [file writeFormat: @"const char *const " - @"*OFUnicodeDecompositionCompatTable[0x%X] = {" - @"\n\t", - _decompositionCompatTableSize]; - - for (OFUnichar i = 0; i < _decompositionCompatTableSize; i++) { - if (_decompositionCompatTableUsed[i] == 1) - [file writeFormat: @"decompCompatPage%u", i]; - else if (_decompositionCompatTableUsed[i] == 2) - [file writeFormat: @"decompositionPage%u", i]; - else - [file writeString: @"emptyDecompositionPage"]; - - if (i + 1 < _decompositionCompatTableSize) { - if ((i + 1) % 3 == 0) - [file writeString: @",\n\t"]; - else - [file writeString: @", "]; - } - } - - [file writeString: @"\n};\n"]; - objc_autoreleasePoolPop(pool); } - (void)writeHeaderToFile: (OFString *)path { @@ -734,16 +481,13 @@ [file writeFormat: @"#define OFUnicodeUppercaseTableSize 0x%X\n" @"#define OFUnicodeLowercaseTableSize 0x%X\n" @"#define OFUnicodeTitlecaseTableSize 0x%X\n" - @"#define OFUnicodeCaseFoldingTableSize 0x%X\n" - @"#define OFUnicodeDecompositionTableSize 0x%X\n" - @"#define OFUnicodeDecompositionCompatTableSize 0x%X\n\n", + @"#define OFUnicodeCaseFoldingTableSize 0x%X\n\n", _uppercaseTableSize, _lowercaseTableSize, _titlecaseTableSize, - _caseFoldingTableSize, _decompositionTableSize, - _decompositionCompatTableSize]; + _caseFoldingTableSize]; [file writeString: @"#ifdef __cplusplus\n" @"extern \"C\" {\n" @"#endif\n" @@ -753,18 +497,12 @@ @" OFUnicodeLowercaseTable[OFUnicodeLowercaseTableSize];\n" @"extern const OFUnichar *const _Nonnull\n" @" OFUnicodeTitlecaseTable[OFUnicodeTitlecaseTableSize];\n" @"extern const OFUnichar *const _Nonnull\n" @" OFUnicodeCaseFoldingTable[OFUnicodeCaseFoldingTableSize];\n" - @"extern const char *const _Nullable *const _Nonnull\n" - @" OFUnicodeDecompositionTable[" - @"OFUnicodeDecompositionTableSize];\n" - @"extern const char *const _Nullable *const _Nonnull\n" - @" OFUnicodeDecompositionCompatTable[" - @"OFUnicodeDecompositionCompatTableSize];\n" @"#ifdef __cplusplus\n" @"}\n" @"#endif\n"]; objc_autoreleasePoolPop(pool); } @end Index: generators/unicode/copyright.h ================================================================== --- generators/unicode/copyright.h +++ generators/unicode/copyright.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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-2022 Jonathan Schleifer \n" \ + @" * Copyright (c) 2008-2024 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" \ ADDED misc/keys.asc Index: misc/keys.asc ================================================================== --- /dev/null +++ misc/keys.asc @@ -0,0 +1,196 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- + +mDMEWtyz7hYJKwYBBAHaRw8BAQdAsw2r74WiB54Nr73sY2sxBLu0RUges2iPeBor +1Wc6Cre0O0pvbmF0aGFuIFNjaGxlaWZlciAoQ29tbWl0IFNpZ25pbmcgS2V5IDIw +MTgpIDxqc0BoZWFwLnpvbmU+iJkEExYKAEECGwMHCwoNDAgLBwYVCgkICwMFFgMC +AQACHgECF4AWIQTGxY7C74kJHg4TzVjYOna/43Y0XgUCXESzpAUJAWlRNgAKCRDY +Ona/43Y0XhA1AP4nIiBUL2nMtkDJSbSb0/kbyIoTNhRXtlI4crYIqfs07gD+NMdH +HzMnGtHkpaX7GAqVTeTiThZUnTGNMwnV9aerQQe0OkpvbmF0aGFuIFNjaGxlaWZl +ciAoT2JqRlcgU2lnbmluZyBLZXkgMjAxOCkgPGpzQGhlYXAuem9uZT6ImQQTFgoA +QQIbAwcLCg0MCAsHBhUKCQgLAwUWAwIBAAIeAQIXgBYhBMbFjsLviQkeDhPNWNg6 +dr/jdjReBQJcRLOoBQkBaVE2AAoJENg6dr/jdjReDVoBANvkIYUTLemog3UhjZYh +Zdvq9Axd63L2lnpzm+For3tNAP9GmJwbq/oi8E0mAwesbvQYY/R4NOOKIdV7rkVj +JzoeCJgzBFxA+ccWCSsGAQQB2kcPAQEHQIe0NK4nnagyINx6Z2DJt4lUzv7a7e6x +PLifEvo1iQVptDpKb25hdGhhbiBTY2hsZWlmZXIgKE9iakZXIFNpZ25pbmcgS2V5 +IDIwMTkpIDxqc0BoZWFwLnpvbmU+iJkEExYKAEEWIQQtKx7sQXauZ6pvl2B50hGJ +otRwjQUCXED55wIbAwUJAeEzgAcLCg0MCAsHBhUKCQgLAwUWAwIBAAIeAQIXgAAK +CRB50hGJotRwjeuIAP9wQ8r+13S0ZHPmOkeVQNqpVdvszisfszQKNRrkKrS7fgEA +AF4eI4IXb13x5hHvzYn2DMMe2ugx6LoCdzYcVlvFFQ60O0pvbmF0aGFuIFNjaGxl +aWZlciAoQ29tbWl0IFNpZ25pbmcgS2V5IDIwMTkpIDxqc0BoZWFwLnpvbmU+iJkE +ExYKAEEWIQQtKx7sQXauZ6pvl2B50hGJotRwjQUCXED5xwIbAwUJAeEzgAcLCg0M +CAsHBhUKCQgLAwUWAwIBAAIeAQIXgAAKCRB50hGJotRwjXTdAP4oYHIg5+LBhfO+ +SNSQl008KH35KmyO4xtZPKfcbWjXcgD/dWVqZDjUYkCs/0oprdJDZPRBIB5QQhjc +1un38+eCiAeYMwReJFsBFgkrBgEEAdpHDwEBB0CjTf7buaAeNxgLpbv9/j4UgcjJ +Z97STkAaM7Xac+Dg1rQ3Sm9uYXRoYW4gU2NobGVpZmVyIChPYmpGVyBTaWduaW5n +IEtleSAyMDIwKSA8anNAbmlsLmltPoiZBBMWCgBBFiEEMOaUj6yAQrWMtKlu4rzO +azXhr4sFAl4kWykCGwMFCQHhM4AHCwoNDAgLBwYVCgkICwMFFgMCAQACHgECF4AA +CgkQ4rzOazXhr4tQAgD+P45Nx/YGk2Q/JzBz+cbsdtcha7IehgXulltd3xLjdwsB +AMoefVWwHOJa7q10ZRxDN48kDGD+kiqvSdIvKRGuLmMAiQIzBBMBCgAdFiEEbR7C +JpvAtUWci6kgz9q0H4KSzu4FAl6KMHcACgkQz9q0H4KSzu7HLBAAo2it0ci2HuJT +1+x1n74dBI5nwKak15OoABW37vxt10gMdm1wo9hq0cJorXdQmE07pMWpMmz883Yg +ayqTXyEJJydVqq3rgR1zcEKOGpiJT6azRfGxcvsNh8bMto9dC6cVVmknydyvNTg7 +3TpofPmRlH8W8gt8w55EiO3Lk4RJODzGhCOrDxbR1o9rF39fUHj+g3NB7grK/TTt +dZvomOS+mcM+pANYivOTmMc5mn0mEVua3F6wRvUck8ij2JFTvJ5GV3xie6JIDa2h +l/hM2BLx2XRrwjnD+kig/CjpoFEP8bzc+epHb6ODAt2SQ5i4Zx30TFWiVeeljX1Q +zFq5pfJr3nbHQNhkzsu3uWXfqUu1M6mBadzYmLYLDgVFLFKdwhBgbvInr39UAtwE +Yl70NoqgVswPzWSkAyrLWs0+2XUXZlyhFxNaOqheWE7VQv/DPYDBPXrim3f5Alv2 +PtQJ2BXDvl1PyDg6Ckg6Pe6XoVKPJwMYsiWZOrsnRRJzeQWa1zFsVWX+CYINPiEY +v4Ls2OFGZj67tzNU8Wf2EFbNmm/V82sXrPeu0iqcJ99aaxZw+tk+h5WS0BiXceZ9 +J6dRKo2qHJJAq0FJnAt+6NRam1KYAknd9y6g5S2bRqiI1wJminmksbSLQ5wmeunl +EynylSIJx+UbXBYVbvmpLWZFFRUKBM60OEpvbmF0aGFuIFNjaGxlaWZlciAoQ29t +bWl0IFNpZ25pbmcgS2V5IDIwMjApIDxqc0BuaWwuaW0+iJkEExYKAEEWIQQw5pSP +rIBCtYy0qW7ivM5rNeGviwUCXiRbAQIbAwUJAeEzgAcLCg0MCAsHBhUKCQgLAwUW +AwIBAAIeAQIXgAAKCRDivM5rNeGvi4HuAPsEi38R7E8716m2ua2KvFB3CClSCsVT +tZjbIQBEHzQ/iAD/UEZtjaNUW/Mf8vFExbnqFes0dwF0p6PzQ0GLix12JQKJAjME +EwEKAB0WIQRtHsImm8C1RZyLqSDP2rQfgpLO7gUCXoowgQAKCRDP2rQfgpLO7jtA +D/403WskqoPnw+woWaeCPZcTU1LQ/o5baUUxbQDWTAUNav3hzDxBDQ1yPacZhwBu +ea6SNnrEZwc5wd5TPozh9sXday3vqDe6R9/AT+MokxJT3EWptTXmcawRSyDdFNZr +V8KJqfDjRNkv9Iqxsjjp9fD5Vw8zVC/KIr0JOq2oxzjU+Wukk94NhSOU2LDRaQLV +8vMpXZRpVJh30+7rq46sTzhZqB5AsTdBykFOsTl9LRmRJXnLjdK/4U7uhoj5ntfR +QzPUG3mmbHf5RlGoQIFq2Byop0MiGVWjHI93C5OU7fyjfnARnENOqCgUxs+yXauY +J+wngqdJroGEo/5kgbJxpTksuK9zQ3DDtE1p5y48qct0gvw3hYz1UGvpEQ2/Prcy +1q0Nc4hzQ2zrG9jO5971KW2alUT5lrILos17ZJlN5pI8NHhat7T9RX82ziB1fQKG +OzbSjxT8gXasy9gbMh8w9zm1prZ1+VRQT8JGLYPHM6mZID20F1q5cRLT41UyTjSe +zzStci/zo/dQKFKaTX9KesTSwVS9Zlo7yldUgH+lWyaSjF9VCrjyNI3YbEJ+/Fqt +rwxAp8kzFviOd7R5F4zAJBRwgfQNI46v9F3X9KpaTeuuJhm4KvyqPRE/0G0ond8G +yJYePoL3jMhfl50163cO69TGXyJmvKwATEa1xRU8n9lE9bg4BF4kWwESCisGAQQB +l1UBBQEBB0Cc6UB0PD0kppdYyeJV3uXSuXk7stS6si393JPKFX2wMgMBCAeIfgQY +FgoAJhYhBDDmlI+sgEK1jLSpbuK8zms14a+LBQJeJFsBAhsMBQkB4TOAAAoJEOK8 +zms14a+L7UoBAJkNXZsY3zHeiSQ23YeaABQUTtpjWb0o6xljq3PXR/hEAP44Rvf3 +hTkPPDuMCJelOxzkvr83upYCIyIpP5HpzqFWBpkCDQReih1/ARAAuXxV9zzoO2UY +YlXdNlNSxu9iJKH/RySUzIPtCWVxUfsI1NOo2ByhxxGWpATRye61Lm6cAU+tvEXj +saKpTi4i9WSy6m6xuLLqQrpDrbVOlazzM1MRQcqGK2wFPtNKV9qz+oOdPXK9a2Rl +gI2iwQh6AjCjq8oa3T1MtDF4D3uGBE+Fn9g+gryAf/TZ8gKWyYd8UZwtrlFLC7nq +8gSj2hFiRYTAPGy8GhcdyKvD0cP2xiFlpJmzCn5B+i9a5i3EJDcbfcc0BSyqxkz2 +BY8bymw4kTt5e8Bmf4KdzK5OE4w3PFPiMq+Z3LVohQCI2CRh1wGw6lzntU5nqJ0c +eD2YV9C8dHwVEN1Vu2M5mXkoe9q4iLWETppxchrQWVAWZWCOeElNxdOrW/uhxpdX +RmzTMuCIHolB4VhszS+Wr3Uj98DWa9n/cPZpvRdVdXmy95G9ocp+uBozQEjdmLOm +rqPUUbE/WLUO/tRFqp6w6QVfh81G5omLo5VWlxCODK8OjOR4/rfCH28I75bjrm9H +pIYtSasVG1/XSV+ilv3PCwadftz8BR5iE0JJtk8NtI1jOvPrIe5d9hJ9109xk/r9 +one51VLFFQDsNJexCswjD25xgpqnhZBd0yOtcE9+6hiENLZ0DFrKZSJjNC7xY/ts +K9usWwm3CBx2VFi+GpjL04Apo9ooPA0AEQEAAbQeSm9uYXRoYW4gU2NobGVpZmVy +IDxqc0BuaWwuaW0+iQJbBBMBCgBFAhsDAh4BAheACAsJCg0MCAsHBhUKCQgLAwUW +AwIBAAIZARYhBG0ewiabwLVFnIupIM/atB+Cks7uBQJj6WbtBQkJIbBuAAoJEM/a +tB+Cks7u1qUP+gLBceY67YURSNLLCO+L537Xukf2eYlzJzUvBI1nYv8C94dQcmSa +sBcAsg2ELfKE6GD1/7VwHQHwclpa3kSX55V6+Ep3VUSR7+2fqz4Ahr10FeOpjS5C +Ir51C44mAjeTkkmPIqhOWSoZyg2RxUZOAUZyFqpLDPFGrRTGmuEFnP1tXOAn3TR2 +xllK9iAbB9ZcJ+MHEz+rVW5yj3XY8/QW1kcsWIA6qV7eHPP4Y8tEIoefvsU5g188 +uHIhxWhB0Xd52VMxd32yiKRgPp9z+6e4PQ+XULv5oGiqR17XKMtMIfAe6kiDYXWT +HpqOHnOekVPuqTsjAFttgKeCEzbyit6HIFlqoXjoj23eTFQEi2qiSLCRDm2uGZJI +hAL5YeHPaNa82dg6YNCGD8FFSwP+hhXMaQ7zB2jB8smX9A9C+nHCKCFF4ba1RRNq +sFRziE2YuY+KX6bQKz6AZ7OxB16YAx75e4J/H/Si8bqm+1EKc6Xpg7uVjYYNH+dr +j4qvNsTf4tLr3FAm5tSRCdZkSlilS+565J4PInBVjcLnlRAxh1X1RJGVuFuueVdM +6joGmsPDnwdv8NOvy+4LvBHWkPLm3FVZE9fyDem+0SDooTpvFEuSRfna8agJB5kH +zA532hu1dEX/XJMCCJT4RBYy7KOVXqcjrLn/TqRiBZKPK4QbmC/JjdKJiQEiBBAB +CAAMBQJj6WgVBQMAEnUAAAoJEJcQuJvKV618c0IIAKLZVwWsgQWBjtjaIsXKUhoo +5HBwNpsNCnWAyUj0ayspkvM+hh5fa70s4Mj4oRdCd44X1iDHQw2bV6PVA+TvqkY2 +NV7iL30Vqpyt50qreUz9qCdEittaFIkRNk2qkQB89cKTrrLDu2k80NZdV4sAAJKu +XFUOEecZVv5D3gYSKDQJ0lTUzSyS4cC5wdSpeEFRTVXpOQOI32mRM9BxmjtDSBct +fnHSWYoE+IoC+OPqDvbbP4TRz3UYjAz5lbLSL5BnlHxZDG2NryH9tUn+/wnJd41m +weKZidDO/AUQ9eKKaIsgzCXAjrLjKcgBBANn1yXl+YAr7J8GFdiGkVznYhGjmAW0 +IkpvbmF0aGFuIFNjaGxlaWZlciA8anNATmV0QlNELm9yZz6JAlgEEwEKAEICGwMI +CwkKDQwICwcGFQoJCAsDBRYDAgEAAh4BAheAFiEEbR7CJpvAtUWci6kgz9q0H4KS +zu4FAmPpZvIFCQkhsG4ACgkQz9q0H4KSzu4/nRAAk5+6zavoleNtZ0/l9xs0lwwq +sENTfdWqp19YvkiQTWz0gDvRoxKbXHI4HK25th0rBu77ryQYjKrRjXhEZrNq2k6f +hTBwJ1sbsDceksaHRlUlVgn112gf6B/iKG3JpLxuFxuMS4ndN9z7H67t2RWDY/+M +qSgaNFWXQtfmtC3tfV8e5etZScVO8w+0Wed6MjGjA76crgVWXm2hGCokEk7+0uNd +VmFC+cPEBMixgAHqZvM+Gu3pZvHgV50Ybczalx/6KV2W37MsaX6iRUCCpnnoAAxN +pWo2Z2LIBVaoO9nuzO8pgF8dRdxwq3Px/RpseHtEUY4v1/aylB4z1joI7sWPqXOR +3QlRmCd2O36kCiLIvm9OQ5tmjmW9T+t/gcCzq5pHDNIx8D50urqnUH+WU/WaT5fp +uM6VifBpSZslTuRavc6kxa7kuGCrsBtVOzlMCxSVAqSgMMm4vVxJm20pYIItHHTZ +TXEehnLEst/EdEAmLmHO2Qch/qUh2i0w5+4pwjY1pIOVP8Si3xbxtoN6PIM/UBEP +fBQGB4NzljQwISdUUSGiWn7pcun350IsCjnC2c+tJQ/lHjhrJjZ+aMAi7OSV6g9P +pjFrz+z9UmTP0QUeBSNGBqAWgvC4okGgFr4cf9H01FbZPNkWIfZYPZ1Nv3apxNOx +lpzSHcURnFhXPJDlqNC0IkpvbmF0aGFuIFNjaGxlaWZlciA8anNAcGtnc3JjLm9y +Zz6JAlgEEwEKAEICGwMICwkKDQwICwcGFQoJCAsDBRYDAgEAAh4BAheAFiEEbR7C +JpvAtUWci6kgz9q0H4KSzu4FAmPpZvcFCQkhsG4ACgkQz9q0H4KSzu4TrxAAnWBr +gJnU96KbYRS7KkpUzeLeaLrHK5LIhaJ7rVxVrOo+x5Ey2NjGJKoTxC9UAfITCfO9 +9vsycp3Gb9fJnowieuQ1y1MFCrYLPPLOfNxh4Jc9GZK64DlexrsXvDhx84wgN+el +rnjuatm9LUJWe5czWKiAnoki/u+SGFVxwOUtND205I4go/8FtY8rZ1P3VEGiXeZq +hjNOodDoGEGZJwQIycN5YCrweYPwM+p80ZbzkWGB+Ov3lOO+omMf7NQ3LFtueV0J +Nq7SjmNESYLm1Gg2NFHZp4D12sSUfHTvNVJBr1qCJggQs2mefRB/aKcS4i9Ajmfk +i7TkEwutDMX6rOCZRppYpS8N6aYoiAOZHQmffk8bdi0RBGVSxR+04IwpYObUbDIZ +US2exkiaDB0tFeguIlgHU/V+3GWEUDF4AhQLbSYkEwUc65FstULrDCRfegFoUBsY +9D+qPYnsNOlTRlalR8hZaQlwZLAuZx0kn+YGxs+9z2UhgMExRtCM/3FRpDuiFJGs +QML2DUArYZeh7JyJy0m9PIt59wg5wnHUyCLop8g1gn6Wh22/R/Le6CEusJsO2qiM +oE6PSB89g3nhsvUadRpYOP9eZS0aoRgNPLp+qigthgEV9fvSADHtAvsaLYpQ+wjr +O+Ih57Y2MrU8mPehwqGz17Ur58VcI65qXTkZpni5Ag0EXoodfwEQAPc4JUVqZGxS +KtipZKGewKuNyqASMq8gNwL7ToSni5cTuQLa9YU+5Zo/BX3OEJkXp+MNN3Y1wFxV +cPBZsYpBAx3apWhi0Fki+zdPjTmRE7QcFE+UE17OnnFReb93G2ErSiY+BzsfbW/3 +dMjLfLhrVjJktLA9pGMoR483jI6rIVEBa6TikoMo8b790Ulo0xicl6ehFhQVUGN4 +CfovBjCZ9CIX6dmRGaB/FMyOXgXWsx5+UilTgJhRHbJnggw6U1H8lk/WhJzCyLyY +Tg+YkHx3WwAF37pR6g1XACMQEdumCLxW21ELC5D4aX0QejM8oIDf/xw5mHcgB0xg +07FmRbyiZheg+CSPgwHWW/K6urw/G04SbYxnk1/kPA66x6Fss3BxTuJOYmEZqklV +Np2KfJdEiBECftRRWIbZu2zFOMGK1olPIOgsKdJvaATkgeYSxjCu9+o4vY1yGXtz +BEwBfIUkU2B33QzWLq+I61WeVbqRC6k0SYBKiQK/uQJSVYuEtNJ8pttYxdYkyY+r +s0yCZHlTlJcYKhAdMi1Gbh2L6WbzsHIHfmdraWqcv7EEuVacjrgerdk3ezOQspC5 +Gfa6pLEmOoF/ctwg/uoGCyhnWBmHiuLdN7F4+z6BHBoqHU1i3z2oUJ3tHDoVnEmh +jYNOgIs7UgKxXiuczMJT4gpNM35ym32hABEBAAGJAjwEGAEKACYCGwwWIQRtHsIm +m8C1RZyLqSDP2rQfgpLO7gUCY+lnIwUJCSGwpAAKCRDP2rQfgpLO7oIlD/4oLDMH +qTzdDIXjM9x5U4ENBeGwUKHEkKeRduXuj0pZTnWTHmdXD3RPbG1EfGJU3PVBudZU +iEREibNaEYM5VFuDwMw51qw7Ox8j4r+RtP+8AI0zpRdababPP1/A4ap+xwReTWVM +/CFF3VekqeElgxSjM6luFPNDdwyBNavOLtbrWhmyclw3DLB03ZtS0sPvu0hXTnp4 +nbuWdsPOxGIomb9UF0IplMPm5ChjkZaypKY75P1k5Il+AZFWEi5YB6y8yl1gmOxY +3pnKCJWcoGsaEoxREqHH/tZAeI299u8aE8Gjl+ZxGunuPDMUd8OSlE8MI3osnWU4 +7rbVueWqJ4CG3OcYJP8Vj1Ygy68R5xBL5ku3ddv5oI2ZIDkqTBFKJQnhWMUX6Trz +e7US0jSdVFv4fYf3aHDJ0afc9RsKebPgbfN3FWak03zInVqdXRrraa410qz8fKBI +1CKalErJN7/dpXu3vfJJ2TgYcgAN9N0lY+YFQ834qpDk6KOTYzvIMJASVIJ1gjvl +iE94hE6FYuHU9DlwYL3/qbOOb6lLIFHxaeQ95ZZR+raPyi1FGVGXV8oZI5f2Uzxo +LYyioTRjgC0cr9aIK56ZQ5I/npwuEYSL/8oIWdRrYGQT0FFQQAnhhkd61DuPt3GA +fhsY1fGkPo/YC3yulOJt98FIMg/lRlYfOrxIbLkCDQReiiM/ARAAwIzaby43las5 +ApAWVw4MxCIpdY9S0tKUBgF4koKKkgUQ20KzI395LctZ6TwRSaBp9df/Wi9JtXe3 +bkt46ASjq8CCMggVptq80KyhnVMYDJD8mH+gFjUdlxTgILg1tnYwt01oBIMh8T1c +EUQ2kcWkDbIRnrrSkVxh+ntu8aqZaF9E9iScPbNO8V5qIGCTfeFti1IUfClQ10Cs +dANPxVngzttHs7eg+ddwZdiwxb7vxKy1/juqWTNFcHYd4XQ8MIuedXliHpvI5quf +MbFvOmX6xxxoXTL/efGoA/zCM6/BcM2ul1o/prJTauRuVKawE3mcMpTrubN+usf6 +QEUohxsxCvxVqGcJVAU5286Hv0Kc2jzqcWqEfiyjCJI0vwCzFk3sRbuawlDuC535 +paR23QC/ClSCghMzfRRnN4OpJQjzgc6yOZ3ydqmF5UeqGrgZhrW+O92jBb1XqGFV +zTOYHvLNJCQ0Cj53fiYpju4Pdf2BWvDo1oSoKbrvSd3DUyXlgN2Ar6t3X2uz7HhL +2496v3BoIOqzzcdvpCaDZjDdrw8SHpp45u9qrzMPKEIdqy4u5KjsKjuCZKczy4pc +u44+JjDzNJRik0Ppf2AUJLBCnik6prZIttbCfGsvid7SR5sZZgjbGk/fuQCF/tQt +aksvsIqb598/sTzNVBGkp6qWttTkPs8AEQEAAYkCPAQYAQoAJgIbIBYhBG0ewiab +wLVFnIupIM/atB+Cks7uBQJj6WcnBQkJIarkAAoJEM/atB+Cks7uei8QAIa+BrMi +fmLTSLe09CnGvacepKNao6UqSHwbmf6Tonv9rOU2EquKyCW/0YK53WGO6fnPE7FV +8JYDWxecBvtLjj+hloEHJ/wliYwd4W3FOuGnb/E9mzQgyKdWcSBIxreZLdD7xZ5B +iv3VLeKyx+xnJ99dC2+MBuL6CBk+gmzwri7/hkYG9GQW9TJEe7qi8D87iTN1YkXl +cJXdDcqapEZxv8+nAa5E4gTmLlXnKYNidC6+9gtnGpCRZtSpLwX0pMVY27w9sthU +Acnx5N3AwS7rCodqnU3ANa5a00wbWOmZ90qbofRX9RC3qkfoisr62bRELY7KFt7M +VTV0YBTCPHFeP+bubyOOyUe1OJsCvWJfIhJm87qjS37WXxYDUU+KHGN4MX9LDvTS +xy+h30Ba0XFfU1fgNtIvVR+MrrIGACq5VU2uSyBQLmIkgcusUComEx77mETE92Mw +ROJfy1O5VGsNDr61xIu72MjKAlukwgwX/qQ7i8Flyf8N++J7fETf/4DHXxNS9imV +JTVxHfvIWpclRfdUCZB6R1Ihv+n1T+yx/FroTxQ5wuilV7+0r2DhrW6Q0YISoWv5 +L1sfohVZCXF7EQgteax0/86WSboerrWQmfGk0k4SjKhBJK1O8Jhh2tk8OmlUz6Fs +7MhFJ5NGASlFL7p0W5iB3qWYwn52sEBaI8VpmDMEYBW6BBYJKwYBBAHaRw8BAQdA +WWTgOvzlX/x5OiYhMLK72aKOMvr0g6KIaynmN2YMp5O0M0pvbmF0aGFuIFNjaGxl +aWZlciAoQ29tbWl0IFNpZ25pbmcgS2V5KSA8anNAbmlsLmltPoiaBBMWCgBCAhsD +CAsJCg0MCAsHBhUKCQgLAwUWAwIBAAIeAQIXgBYhBAzGrFQcetxzPGQWEGNnA1dz +lTEvBQJj6WYYBQkFtN+UAAoJEGNnA1dzlTEvXKQBAPQ4mbtEmbuMbfpeV3pMP8bO +1OhOB4/Thx4tUrrV7JcjAQCveLdvBrB+cSh+DA7edl6/XWfafCT0qrzRFhaoEZhx +Dbg4BGAVugQSCisGAQQBl1UBBQEBB0A2sxWorhv9BEE+urAmX5GBUfcCdta9Un6E +t5wEG5jLVAMBCAeIfgQYFgoAJgIbDBYhBAzGrFQcetxzPGQWEGNnA1dzlTEvBQJj +6WYtBQkFtN+pAAoJEGNnA1dzlTEvi+8BANiiPjamWJ3iSeMEaaYPoZXNZ7NAHlK0 +UUgQvB/osfQWAP9NKXMO7P5R/K+D2nRE/Ndmk0lqBykzumouPVuR21pYB5gzBGWW +/sEWCSsGAQQB2kcPAQEHQAujl3ehBqKz3PFMW+rl8/d/1KS7Skx00xYU6xsLout+ +tDhKb25hdGhhbiBTY2hsZWlmZXIgKENvbW1pdCBTaWduaW5nIEtleSAyMDI0KSA8 +anNAbmlsLmltPoiaBBMWCgBCFiEEYy4qTb/j80NaLyG/lClu8uyb5oMFAmWW/sEC +GwMFCQHhM4AICwkKDQwICwcGFQoJCAsDBRYDAgEAAh4FAheAAAoJEJQpbvLsm+aD +g10BAP5MpkFbauicEGNTUJnmfbWZsGmmOTov7nG3ylVPp6UpAP4jIbm0Nz5L0+1B +vA35PeZfJ8z2dIcuKPKkCgxbv55NAIkCNwQTAQoAIRYhBG0ewiabwLVFnIupIM/a +tB+Cks7uBQJllwC0AwUBeAAKCRDP2rQfgpLO7sktEACdIKHR7vTHKgokw/6j2zwd +Na3sBt0jC7tsqA7xbfobwMR3yoVnD49T4zHlW5MwKaQBsTkwI9pS4qbaPsX7VoXV +5I8UpWPbXeDnofO9B+sO55ybVrGf1Fb2PmykZ85dgEe168hL0c5UX+9zCXjfFTHa +GAxRmTrYKP0h+jYZJns1QK3KZEWh0pkqJz5oOLELqeZS2GMGn1PQjmbzz72/korZ +sUswS5sDBbMVeusCWuNeY6FJZ6ziv97geu+uWe7ppwv25rebEKJgsuaIqDuAT2Gg +3NgrubfXFVLlDxjuYdaO+ieBQur5z8UPaSzEYlF2p7/cut24A8WV/d3D5dX3XO/g +AuEMkyAws9zOeY3NMMfkHEZsuX0AetH7cOQYyAUIlpye30OxeoZgO4Cl3G5q95sk +Q4i/LpzNERq+JydmniPMbM/TL8p87RYr/bidO+0KeHwRzsesVu2ae1xO/ZRSyqny +un5RZblS9QY1H3xUgKQWpMLxJGXr6n+9eRThRsrTK/JH6GFpkFnjmMpuxquAw32w +PdxGWDUUE35pC4f0X/6rL8IBf32spXG+mKbBLTJkSkteSM26Uff4zVFludQU+N06 +c6XFX7eBpbhhHhsCabOskGFXXS0bdi6NcZgazm1I4rhqrT+pQFHDOZg/dgl5cND/ +Q4zqQ9Xrv/iV6ljHHAPYGrg4BGWW/sESCisGAQQBl1UBBQEBB0CTeGWS64rbAwJz +Sioh6y0Urd5/pGIj5UEdyAFrjhiKDgMBCAeIfgQYFgoAJhYhBGMuKk2/4/NDWi8h +v5QpbvLsm+aDBQJllv7BAhsMBQkB4TOAAAoJEJQpbvLsm+aDv0sBAIFCR1MA+d7V +ll+AxWH/k2ghgfJ661e88iaoG7qUyve5APsFQbV5thutm99chCp8Sc+fulHNtrKJ +WBymwZqetu7HBg== +=mVJw +-----END PGP PUBLIC KEY BLOCK----- DELETED objfw.spec Index: objfw.spec ================================================================== --- objfw.spec +++ /dev/null @@ -1,248 +0,0 @@ -%global libobjfw_major 0 -%global libobjfw_minor 0 -%global libobjfwrt_major 0 -%global libobjfwrt_minor 0 -%global libobjfwtls_major 0 -%global libobjfwtls_minor 0 -%if 0%{?suse_version} -%global libobjfw_pkgname libobjfw%{libobjfw_major} -%global libobjfwrt_pkgname libobjfwrt%{libobjfwrt_major} -%global libobjfwtls_pkgname libobjfwtls%{libobjfwtls_major} -%else -%global libobjfw_pkgname libobjfw -%global libobjfwrt_pkgname libobjfwrt -%global libobjfwtls_pkgname libobjfwtls -%endif - -Name: objfw -Version: 1.1dev -Release: 1%{?dist} -Summary: Portable, lightweight framework for the Objective-C language - -%if 0%{?suse_version} -License: QPL-1.0 or GPL-3.0 or GPL-2.0 -Group: Development/Languages/C and C++ -%else -License: QPL or GPLv3 or GPLv2 -%endif -URL: https://objfw.nil.im -Source0: objfw-%{version}.tar.gz - -BuildRequires: autoconf -BuildRequires: automake -BuildRequires: clang -BuildRequires: make -BuildRequires: pkgconfig(gnutls) -Requires: %{libobjfw_pkgname}%{_isa} = %{version}-%{release} -Requires: %{libobjfw_pkgname}-devel = %{version}-%{release} -Requires: %{libobjfwrt_pkgname}%{_isa} = %{version}-%{release} -Requires: %{libobjfwrt_pkgname}-devel = %{version}-%{release} -Requires: ofarc%{_isa} = %{version}-%{release} -Requires: ofdns%{_isa} = %{version}-%{release} -Requires: ofhash%{_isa} = %{version}-%{release} -Requires: ofhttp%{_isa} = %{version}-%{release} - -%description -ObjFW is a portable, lightweight framework for the Objective-C language. It -enables you to write an application in Objective-C that will run on any -platform supported by ObjFW without having to worry about differences between -operating systems or various frameworks you would otherwise need if you want to -be portable. - -It supports all modern Objective-C features when using Clang, but is also -compatible with GCC ≥ 4.6 to allow maximum portability. - -ObjFW also comes with its own lightweight and extremely fast Objective-C -runtime, which in real world use cases was found to be significantly faster -than both GNU's and Apple's runtime. - -%package -n %{libobjfw_pkgname} -Summary: ObjFW library -Requires: %{libobjfwrt_pkgname}%{_isa} = %{version}-%{release} - -%description -n %{libobjfw_pkgname} -The %{libobjfw_pkgname} package contains the library needed by programs using -ObjFW. - -%package -n %{libobjfw_pkgname}-devel -Summary: Header files, libraries and tools for %{libobjfw_pkgname} -Requires: %{libobjfw_pkgname}%{_isa} = %{version}-%{release} -Requires: %{libobjfwrt_pkgname}-devel = %{version}-%{release} - -%description -n %{libobjfw_pkgname}-devel -The %{libobjfw_pkgname}-devel package contains the header files, libraries and -tools to develop programs using ObjFW. - -%package -n %{libobjfwrt_pkgname} -Summary: ObjFW Objective-C runtime library - -%description -n %{libobjfwrt_pkgname} -The %{libobjfwrt_pkgname} package contains ObjFW's Objective-C runtime library. - -%package -n %{libobjfwrt_pkgname}-devel -Summary: Header files and libraries for %{libobjfwrt_pkgname} -Requires: %{libobjfwrt_pkgname}%{_isa} = %{version}-%{release} - -%description -n %{libobjfwrt_pkgname}-devel -The %{libobjfwrt_pkgname}-devel package contains header files and libraries for -ObjFW's Objective-C runtime library. - -%package -n %{libobjfwtls_pkgname} -Summary: TLS support for ObjFW -Requires: gnutls%{_isa} >= 3.0.5 - -%description -n %{libobjfwtls_pkgname} -The %{libobjfwtls_pkgname} package contains TLS support for ObjFW - -%package -n %{libobjfwtls_pkgname}-devel -Summary: Header files and libraries for %{libobjfwtls_pkgname} -Requires: %{libobjfwtls_pkgname}%{_isa} = %{version}-%{release} - -%description -n %{libobjfwtls_pkgname}-devel -The %{libobjfwtls_pkgname}-devel package contains header files and libraries -for TLS support for ObjFW. - -%package -n ofarc -Summary: Utility for handling ZIP, Tar and LHA archives -Requires: %{libobjfw_pkgname}%{_isa} = %{version}-%{release} -Requires: %{libobjfwrt_pkgname}%{_isa} = %{version}-%{release} - -%description -n ofarc -ofarc is a multi-format archive utility that allows creating, listing, -extracting and modifying ZIP, Tar and LHA archives using ObjFW's classes for -various archive types. - -%package -n ofdns -Summary: Utility for performing DNS requests on the command line -Requires: %{libobjfw_pkgname}%{_isa} = %{version}-%{release} -Requires: %{libobjfwrt_pkgname}%{_isa} = %{version}-%{release} - -%description -n ofdns -ofdns is an utility for performing DNS requests on the command line using -ObjFW's DNS resolver. - -%package -n ofhash -Summary: Utility to hash files with various cryptographic hash functions -Requires: %{libobjfw_pkgname}%{_isa} = %{version}-%{release} -Requires: %{libobjfwrt_pkgname}%{_isa} = %{version}-%{release} - -%description -n ofhash -ofhash is an utility to hash files with various cryptographic hash functions -(even using different algorithms at once) using ObjFW's classes for various -cryptographic hashes. - -%package -n ofhttp -Summary: Command line downloader for HTTP(S) -Requires: %{libobjfw_pkgname}%{_isa} = %{version}-%{release} -Requires: %{libobjfwrt_pkgname}%{_isa} = %{version}-%{release} -Requires: %{libobjfwtls_pkgname}%{_isa} = %{version}-%{release} - -%description -n ofhttp -ofhttp is a command line downloader for HTTP and HTTPS using ObjFW's -OFHTTPClient class. It supports all features one would expect from a modern -command line downloader such as resuming of downloads, using a SOCKS5 proxy, a -modern terminal-based UI, etc. - -%prep -%autosetup -./autogen.sh - -%build -%configure OBJC=clang --disable-rpath -%make_build - -%install -%make_install - -%check -make -C tests run - -%if 0%{?suse_version} -%post -n %{libobjfw_pkgname} -p /sbin/ldconfig -%postun -n %{libobjfw_pkgname} -p /sbin/ldconfig -%post -n %{libobjfwrt_pkgname} -p /sbin/ldconfig -%postun -n %{libobjfwrt_pkgname} -p /sbin/ldconfig -%endif - -%files -%license LICENSE.QPL -%license LICENSE.GPLv3 -%license LICENSE.GPLv2 - -%files -n %{libobjfw_pkgname} -%{_libdir}/libobjfw.so.%{libobjfw_major} -%{_libdir}/libobjfw.so.%{libobjfw_major}.%{libobjfw_minor}.0 -%license LICENSE.QPL -%license LICENSE.GPLv3 -%license LICENSE.GPLv2 - -%files -n %{libobjfw_pkgname}-devel -%{_libdir}/libobjfw.so -%dir %{_includedir}/ObjFW -%{_includedir}/ObjFW -%{_bindir}/objfw-compile -%{_bindir}/objfw-config -%{_bindir}/objfw-new -%license LICENSE.QPL -%license LICENSE.GPLv3 -%license LICENSE.GPLv2 - -%files -n %{libobjfwrt_pkgname} -%{_libdir}/libobjfwrt.so.%{libobjfwrt_major} -%{_libdir}/libobjfwrt.so.%{libobjfwrt_major}.%{libobjfwrt_minor}.0 -%license LICENSE.QPL -%license LICENSE.GPLv3 -%license LICENSE.GPLv2 - -%files -n %{libobjfwrt_pkgname}-devel -%{_libdir}/libobjfwrt.so -%{_includedir}/ObjFWRT/ObjFWRT.h -%license LICENSE.QPL -%license LICENSE.GPLv3 -%license LICENSE.GPLv2 - -%files -n %{libobjfwtls_pkgname} -%{_libdir}/libobjfwtls.so.%{libobjfwtls_major} -%{_libdir}/libobjfwtls.so.%{libobjfwtls_major}.%{libobjfwtls_minor}.0 -%license LICENSE.QPL -%license LICENSE.GPLv3 -%license LICENSE.GPLv2 - -%files -n %{libobjfwtls_pkgname}-devel -%{_libdir}/libobjfwtls.so -%{_includedir}/ObjFWTLS/ObjFWTLS.h -%license LICENSE.QPL -%license LICENSE.GPLv3 -%license LICENSE.GPLv2 - -%files -n ofarc -%{_bindir}/ofarc -%{_datadir}/ofarc/lang/de.json -%{_datadir}/ofarc/lang/languages.json -%license LICENSE.QPL -%license LICENSE.GPLv3 -%license LICENSE.GPLv2 - -%files -n ofdns -%{_bindir}/ofdns -%{_datadir}/ofdns/lang/de.json -%{_datadir}/ofdns/lang/languages.json -%license LICENSE.QPL -%license LICENSE.GPLv3 -%license LICENSE.GPLv2 - -%files -n ofhash -%{_bindir}/ofhash -%{_datadir}/ofhash/lang/de.json -%{_datadir}/ofhash/lang/languages.json -%license LICENSE.QPL -%license LICENSE.GPLv3 -%license LICENSE.GPLv2 - -%files -n ofhttp -%{_bindir}/ofhttp -%{_datadir}/ofhttp/lang/de.json -%{_datadir}/ofhttp/lang/languages.json -%license LICENSE.QPL -%license LICENSE.GPLv3 -%license LICENSE.GPLv2 Index: src/Makefile ================================================================== --- src/Makefile +++ src/Makefile @@ -7,10 +7,11 @@ SHARED_LIB = ${OBJFW_SHARED_LIB} STATIC_LIB = ${OBJFW_STATIC_LIB} FRAMEWORK = ${OBJFW_FRAMEWORK} LIB_MAJOR = ${OBJFW_LIB_MAJOR} LIB_MINOR = ${OBJFW_LIB_MINOR} +LIB_PATCH = ${OBJFW_LIB_PATCH} SRCS = OFASN1BitString.m \ OFASN1Boolean.m \ OFASN1Enumerated.m \ OFASN1IA5String.m \ @@ -38,40 +39,42 @@ OFFileManager.m \ OFGZIPStream.m \ OFHMAC.m \ OFINICategory.m \ OFINIFile.m \ + OFIRI.m \ + OFIRIHandler.m \ OFInflate64Stream.m \ OFInflateStream.m \ OFInvocation.m \ OFLHAArchive.m \ OFLHAArchiveEntry.m \ OFList.m \ OFLocale.m \ OFMD5Hash.m \ OFMapTable.m \ + OFMatrix4x4.m \ OFMemoryStream.m \ OFMessagePackExtension.m \ OFMethodSignature.m \ OFMutableArray.m \ OFMutableData.m \ OFMutableDictionary.m \ + OFMutableIRI.m \ OFMutableLHAArchiveEntry.m \ OFMutablePair.m \ OFMutableSet.m \ OFMutableString.m \ OFMutableTarArchiveEntry.m \ OFMutableTriple.m \ - OFMutableURI.m \ OFMutableZIPArchiveEntry.m \ OFNotification.m \ OFNotificationCenter.m \ OFNull.m \ OFNumber.m \ OFObject.m \ OFObject+KeyValueCoding.m \ - OFObject+Serialization.m \ OFOnce.m \ OFOptionsParser.m \ OFPBKDF2.m \ OFPair.m \ OFRIPEMD160Hash.m \ @@ -84,41 +87,36 @@ OFSHA384Or512Hash.m \ OFSHA512Hash.m \ OFScrypt.m \ OFSecureData.m \ OFSeekableStream.m \ - OFSerialization.m \ OFSet.m \ + OFSettings.m \ OFSortedList.m \ OFStdIOStream.m \ OFStream.m \ OFString.m \ OFString+CryptographicHashing.m \ OFString+JSONParsing.m \ OFString+PercentEncoding.m \ OFString+PropertyListParsing.m \ - OFString+Serialization.m \ OFString+XMLEscaping.m \ OFString+XMLUnescaping.m \ ${OF_SUBPROCESS_M} \ - OFSettings.m \ OFSystemInfo.m \ OFTarArchive.m \ OFTarArchiveEntry.m \ OFThread.m \ OFTimer.m \ OFTriple.m \ - OFURI.m \ - OFURIHandler.m \ OFUUID.m \ OFValue.m \ OFXMLAttribute.m \ OFXMLCDATA.m \ OFXMLCharacters.m \ OFXMLComment.m \ OFXMLElement.m \ - OFXMLElement+Serialization.m \ OFXMLElementBuilder.m \ OFXMLNode.m \ OFXMLParser.m \ OFXMLProcessingInstruction.m \ OFZIPArchive.m \ @@ -143,10 +141,11 @@ OFHTTPResponse.m \ OFHTTPServer.m \ OFSequencedPacketSocket.m \ OFSocket.m \ OFStreamSocket.m \ + OFSystemInfo+NetworkInterfaces.m \ OFTCPSocket.m \ OFTLSStream.m \ OFUDPSocket.m \ ${USE_SRCS_APPLETALK} \ ${USE_SRCS_IPX} \ @@ -188,56 +187,61 @@ objfw-defs.h \ platform.h \ ${USE_INCLUDES_ATOMIC} SRCS += OFASPrintF.m \ - OFAdjacentArray.m \ - OFAdjacentSubarray.m \ - OFArchiveURIHandler.m \ + OFArchiveIRIHandler.m \ OFBase64.m \ OFBitSetCharacterSet.m \ - OFBytesValue.m \ OFCRC16.m \ OFCRC32.m \ - OFCountedMapTableSet.m \ - OFEmbeddedURIHandler.m \ + OFConcreteArray.m \ + OFConcreteColor.m \ + OFConcreteCountedSet.m \ + OFConcreteData.m \ + OFConcreteDate.m \ + OFConcreteDictionary.m \ + OFConcreteMutableArray.m \ + OFConcreteMutableData.m \ + OFConcreteMutableDictionary.m \ + OFConcreteMutableSet.m \ + OFConcreteNumber.m \ + OFConcreteSet.m \ + OFConcreteSubarray.m \ + OFConcreteValue.m \ + OFEmbeddedIRIHandler.m \ OFHuffmanTree.m \ OFINIFileSettings.m \ OFInvertedCharacterSet.m \ OFLHADecompressingStream.m \ - OFMapTableDictionary.m \ - OFMapTableSet.m \ - OFMutableAdjacentArray.m \ - OFMutableMapTableDictionary.m \ - OFMutableMapTableSet.m \ OFMutableUTF8String.m \ - OFNonretainedObjectValue.m \ - OFPointValue.m \ - OFPointerValue.m \ OFRangeCharacterSet.m \ - OFRangeValue.m \ - OFRectValue.m \ OFSandbox.m \ - OFSizeValue.m \ + OFStrFTime.m \ OFStrPTime.m \ OFSubarray.m \ + OFSubdata.m \ OFUTF8String.m \ ${LIBBASES_M} \ ${RUNTIME_AUTORELEASE_M} \ ${RUNTIME_INSTANCE_M} \ - ${UNICODE_M} -SRCS_FILES += OFFileURIHandler.m + ${UNICODE_M} \ + ${USE_SRCS_TAGGED_POINTERS} +SRCS_FILES += OFFileIRIHandler.m SRCS_SOCKETS += OFAsyncIPSocketConnector.m \ OFDNSResolverSettings.m \ ${OF_EPOLL_KERNEL_EVENT_OBSERVER_M} \ - OFHTTPURIHandler.m \ + OFHTTPIRIHandler.m \ OFHostAddressResolver.m \ OFKernelEventObserver.m \ ${OF_KQUEUE_KERNEL_EVENT_OBSERVER_M} \ ${OF_POLL_KERNEL_EVENT_OBSERVER_M} \ ${OF_SELECT_KERNEL_EVENT_OBSERVER_M} \ OFTCPSocketSOCKS5Connector.m +SRCS_TAGGED_POINTERS = OFTaggedPointerColor.m \ + OFTaggedPointerDate.m \ + OFTaggedPointerNumber.m SRCS_WINDOWS += platform/Windows/OFWin32ConsoleStdIOStream.m \ versioninfo.rc OBJS_EXTRA = exceptions/exceptions.a \ encodings/encodings.a \ @@ -258,5 +262,13 @@ RCFLAGS = --use-temp-file \ -DOBJFW_LIB_MAJOR=${OBJFW_LIB_MAJOR} \ -DOBJFW_LIB_MINOR=${OBJFW_LIB_MINOR} \ -DOBJFW_LIB_VERSION=\"${OBJFW_LIB_MAJOR}.${OBJFW_LIB_MINOR}\" \ -DOBJFW_SHARED_LIB=\"${OBJFW_SHARED_LIB}\" + +uninstall-extra: + for i in platform/GCC4 platform/GCC4.7 platform/PowerPC platform/macOS \ + platform/x86 platform ""; do \ + if test -d ${DESTDIR}${includedir}/${includesubdir}/$$i; then \ + rmdir ${DESTDIR}${includedir}/${includesubdir}/$$i; \ + fi; \ + done Index: src/OFASN1BitString.h ================================================================== --- src/OFASN1BitString.h +++ src/OFASN1BitString.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFASN1BitString.m ================================================================== --- src/OFASN1BitString.m +++ src/OFASN1BitString.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFASN1Boolean.h ================================================================== --- src/OFASN1Boolean.h +++ src/OFASN1Boolean.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFASN1Boolean.m ================================================================== --- src/OFASN1Boolean.m +++ src/OFASN1Boolean.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFASN1DERRepresentation.h ================================================================== --- src/OFASN1DERRepresentation.h +++ src/OFASN1DERRepresentation.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFASN1Enumerated.h ================================================================== --- src/OFASN1Enumerated.h +++ src/OFASN1Enumerated.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFASN1Enumerated.m ================================================================== --- src/OFASN1Enumerated.m +++ src/OFASN1Enumerated.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFASN1IA5String.h ================================================================== --- src/OFASN1IA5String.h +++ src/OFASN1IA5String.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFASN1IA5String.m ================================================================== --- src/OFASN1IA5String.m +++ src/OFASN1IA5String.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFASN1Integer.h ================================================================== --- src/OFASN1Integer.h +++ src/OFASN1Integer.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFASN1Integer.m ================================================================== --- src/OFASN1Integer.m +++ src/OFASN1Integer.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFASN1NumericString.h ================================================================== --- src/OFASN1NumericString.h +++ src/OFASN1NumericString.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFASN1NumericString.m ================================================================== --- src/OFASN1NumericString.m +++ src/OFASN1NumericString.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFASN1ObjectIdentifier.h ================================================================== --- src/OFASN1ObjectIdentifier.h +++ src/OFASN1ObjectIdentifier.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFASN1ObjectIdentifier.m ================================================================== --- src/OFASN1ObjectIdentifier.m +++ src/OFASN1ObjectIdentifier.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFASN1OctetString.h ================================================================== --- src/OFASN1OctetString.h +++ src/OFASN1OctetString.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFASN1OctetString.m ================================================================== --- src/OFASN1OctetString.m +++ src/OFASN1OctetString.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFASN1PrintableString.h ================================================================== --- src/OFASN1PrintableString.h +++ src/OFASN1PrintableString.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFASN1PrintableString.m ================================================================== --- src/OFASN1PrintableString.m +++ src/OFASN1PrintableString.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFASN1UTF8String.h ================================================================== --- src/OFASN1UTF8String.h +++ src/OFASN1UTF8String.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFASN1UTF8String.m ================================================================== --- src/OFASN1UTF8String.m +++ src/OFASN1UTF8String.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFASN1Value.h ================================================================== --- src/OFASN1Value.h +++ src/OFASN1Value.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFASN1Value.m ================================================================== --- src/OFASN1Value.m +++ src/OFASN1Value.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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.h ================================================================== --- src/OFASPrintF.h +++ src/OFASPrintF.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -23,11 +23,11 @@ #ifdef HAVE_WCHAR_H # include #endif -#ifdef HAVE_ASPRINTF_L +#if defined(HAVE_ASPRINTF_L) || defined(HAVE_USELOCALE) # include #endif #ifdef HAVE_XLOCALE_H # include #endif @@ -34,10 +34,11 @@ #ifdef OF_HAVE_SYS_TYPES_H # include #endif +#import "OFASPrintF.h" #import "OFString.h" #import "OFLocale.h" #import "OFInitializationFailedException.h" @@ -81,11 +82,11 @@ lengthModifierCapitalL } lengthModifier; bool useLocale; }; -#ifdef HAVE_ASPRINTF_L +#if defined(HAVE_ASPRINTF_L) || defined(HAVE_USELOCALE) static locale_t cLocale; OF_CONSTRUCTOR() { if ((cLocale = newlocale(LC_ALL_MASK, "C", NULL)) == NULL) @@ -375,11 +376,11 @@ static bool formatConversionSpecifierState(struct Context *ctx) { char *tmp = NULL; int tmpLen = 0; -#ifndef HAVE_ASPRINTF_L +#if !defined(HAVE_ASPRINTF_L) && !defined(HAVE_USELOCALE) OFString *point; #endif if (!appendSubformat(ctx, ctx->format + ctx->i, 1)) return false; @@ -546,43 +547,57 @@ case 'a': case 'A': switch (ctx->lengthModifier) { case lengthModifierNone: case lengthModifierL: -#ifdef HAVE_ASPRINTF_L +#if defined(HAVE_ASPRINTF_L) if (!ctx->useLocale) tmpLen = asprintf_l(&tmp, cLocale, ctx->subformat, va_arg(ctx->arguments, double)); else +#elif defined(HAVE_USELOCALE) + if (!ctx->useLocale) { + locale_t previousLocale = uselocale(cLocale); + tmpLen = asprintf(&tmp, ctx->subformat, + va_arg(ctx->arguments, double)); + uselocale(previousLocale); + } else #endif tmpLen = asprintf(&tmp, ctx->subformat, va_arg(ctx->arguments, double)); break; case lengthModifierCapitalL: -#ifdef HAVE_ASPRINTF_L +#if defined(HAVE_ASPRINTF_L) if (!ctx->useLocale) tmpLen = asprintf_l(&tmp, cLocale, ctx->subformat, va_arg(ctx->arguments, long double)); else +#elif defined(HAVE_USELOCALE) + if (!ctx->useLocale) { + locale_t previousLocale = uselocale(cLocale); + tmpLen = asprintf(&tmp, ctx->subformat, + va_arg(ctx->arguments, long double)); + uselocale(previousLocale); + } else #endif tmpLen = asprintf(&tmp, ctx->subformat, va_arg(ctx->arguments, long double)); break; default: return false; } -#ifndef HAVE_ASPRINTF_L +#if !defined(HAVE_ASPRINTF_L) && !defined(HAVE_USELOCALE) if (tmpLen == -1) return false; /* - * If there's no asprintf_l, we have no other choice than to - * use this ugly hack to replace the locale's decimal point - * back to ".". + * If there's no asprintf_l and no uselocale, we have no other + * choice than to use this ugly hack to replace the locale's + * decimal point back to ".". */ point = [OFLocale decimalSeparator]; if (!ctx->useLocale && point != nil && ![point isEqual: @"."]) { void *pool = objc_autoreleasePoolPush(); DELETED src/OFAdjacentArray.h Index: src/OFAdjacentArray.h ================================================================== --- src/OFAdjacentArray.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (c) 2008-2022 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#import "OFArray.h" - -OF_ASSUME_NONNULL_BEGIN - -@class OFMutableData; - -@interface OFAdjacentArray: OFArray -{ - OFMutableData *_array; -} -@end - -OF_ASSUME_NONNULL_END DELETED src/OFAdjacentArray.m Index: src/OFAdjacentArray.m ================================================================== --- src/OFAdjacentArray.m +++ /dev/null @@ -1,368 +0,0 @@ -/* - * Copyright (c) 2008-2022 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 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 "OFAdjacentArray.h" -#import "OFAdjacentSubarray.h" -#import "OFData.h" -#import "OFMutableAdjacentArray.h" -#import "OFString.h" -#import "OFXMLElement.h" - -#import "OFEnumerationMutationException.h" -#import "OFInvalidArgumentException.h" -#import "OFOutOfRangeException.h" - -@implementation OFAdjacentArray -- (instancetype)init -{ - self = [super init]; - - @try { - _array = [[OFMutableData alloc] initWithItemSize: sizeof(id)]; - } @catch (id e) { - [self release]; - @throw e; - } - - return self; -} - -- (instancetype)initWithObject: (id)object -{ - self = [self init]; - - @try { - if (object == nil) - @throw [OFInvalidArgumentException exception]; - - [_array addItem: &object]; - [object retain]; - } @catch (id e) { - [self release]; - @throw e; - } - - return self; -} - -- (instancetype)initWithObject: (id)firstObject arguments: (va_list)arguments -{ - self = [self init]; - - @try { - id object; - - [_array addItem: &firstObject]; - [firstObject retain]; - - while ((object = va_arg(arguments, id)) != nil) { - [_array addItem: &object]; - [object retain]; - } - } @catch (id e) { - [self release]; - @throw e; - } - - return self; -} - -- (instancetype)initWithArray: (OFArray *)array -{ - id const *objects; - size_t count; - - self = [super init]; - - if (array == nil) - return self; - - @try { - objects = array.objects; - count = array.count; - - _array = [[OFMutableData alloc] initWithItemSize: sizeof(id) - capacity: count]; - } @catch (id e) { - [self release]; - @throw e; - } - - @try { - for (size_t i = 0; i < count; i++) - [objects[i] retain]; - - [_array addItems: objects count: count]; - } @catch (id e) { - for (size_t i = 0; i < count; i++) - [objects[i] release]; - - /* Prevent double-release of objects */ - [_array release]; - _array = nil; - - [self release]; - @throw e; - } - - return self; -} - -- (instancetype)initWithObjects: (id const *)objects count: (size_t)count -{ - self = [self init]; - - @try { - bool ok = true; - - for (size_t i = 0; i < count; i++) { - if (objects[i] == nil) - ok = false; - - [objects[i] retain]; - } - - if (!ok) - @throw [OFInvalidArgumentException exception]; - - [_array addItems: objects count: count]; - } @catch (id e) { - for (size_t i = 0; i < count; i++) - [objects[i] release]; - - [self release]; - @throw e; - } - - return self; -} - -- (instancetype)initWithSerialization: (OFXMLElement *)element -{ - self = [self init]; - - @try { - void *pool = objc_autoreleasePoolPush(); - - if ((![element.name isEqual: @"OFArray"] && - ![element.name isEqual: @"OFMutableArray"]) || - ![element.namespace isEqual: OFSerializationNS]) - @throw [OFInvalidArgumentException exception]; - - for (OFXMLElement *child in - [element elementsForNamespace: OFSerializationNS]) { - void *pool2 = objc_autoreleasePoolPush(); - id object; - - object = child.objectByDeserializing; - [_array addItem: &object]; - [object retain]; - - objc_autoreleasePoolPop(pool2); - } - - objc_autoreleasePoolPop(pool); - } @catch (id e) { - [self release]; - @throw e; - } - - return self; -} - -- (size_t)count -{ - return _array.count; -} - -- (id const *)objects -{ - return _array.items; -} - -- (id)objectAtIndex: (size_t)idx -{ - return *((id *)[_array itemAtIndex: idx]); -} - -- (id)objectAtIndexedSubscript: (size_t)idx -{ - return *((id *)[_array itemAtIndex: idx]); -} - -- (void)getObjects: (id *)buffer inRange: (OFRange)range -{ - id const *objects = _array.items; - size_t count = _array.count; - - if (range.length > SIZE_MAX - range.location || - range.location + range.length > count) - @throw [OFOutOfRangeException exception]; - - for (size_t i = 0; i < range.length; i++) - buffer[i] = objects[range.location + i]; -} - -- (size_t)indexOfObject: (id)object -{ - id const *objects; - size_t count; - - if (object == nil) - return OFNotFound; - - objects = _array.items; - count = _array.count; - - for (size_t i = 0; i < count; i++) - if ([objects[i] isEqual: object]) - return i; - - return OFNotFound; -} - -- (size_t)indexOfObjectIdenticalTo: (id)object -{ - id const *objects; - size_t count; - - if (object == nil) - return OFNotFound; - - objects = _array.items; - count = _array.count; - - for (size_t i = 0; i < count; i++) - if (objects[i] == object) - return i; - - return OFNotFound; -} - - -- (OFArray *)objectsInRange: (OFRange)range -{ - if (range.length > SIZE_MAX - range.location || - range.location + range.length > _array.count) - @throw [OFOutOfRangeException exception]; - - if ([self isKindOfClass: [OFMutableArray class]]) - return [OFArray - arrayWithObjects: (id *)_array.items + range.location - count: range.length]; - - return [OFAdjacentSubarray arrayWithArray: self range: range]; -} - -- (bool)isEqual: (id)object -{ - OFArray *otherArray; - id const *objects, *otherObjects; - size_t count; - - if (object == self) - return true; - - if (![object isKindOfClass: [OFAdjacentArray class]] && - ![object isKindOfClass: [OFMutableAdjacentArray class]]) - return [super isEqual: object]; - - otherArray = object; - - count = _array.count; - - if (count != otherArray.count) - return false; - - objects = _array.items; - otherObjects = otherArray.objects; - - for (size_t i = 0; i < count; i++) - if (![objects[i] isEqual: otherObjects[i]]) - return false; - - return true; -} - -- (unsigned long)hash -{ - id const *objects = _array.items; - size_t count = _array.count; - unsigned long hash; - - OFHashInit(&hash); - - for (size_t i = 0; i < count; i++) - OFHashAddHash(&hash, [objects[i] hash]); - - OFHashFinalize(&hash); - - return hash; -} - -- (int)countByEnumeratingWithState: (OFFastEnumerationState *)state - objects: (id *)objects - count: (int)count_ -{ - size_t count = _array.count; - - if (count > INT_MAX) - /* - * Use the implementation from OFArray, which is slower, but can - * enumerate in chunks. - */ - return [super countByEnumeratingWithState: state - objects: objects - count: count_]; - - if (state->state >= count) - return 0; - - state->state = (unsigned long)count; - state->itemsPtr = (id *)_array.items; - state->mutationsPtr = (unsigned long *)self; - - return (int)count; -} - -#ifdef OF_HAVE_BLOCKS -- (void)enumerateObjectsUsingBlock: (OFArrayEnumerationBlock)block -{ - id const *objects = _array.items; - size_t count = _array.count; - bool stop = false; - - for (size_t i = 0; i < count && !stop; i++) - block(objects[i], i, &stop); -} -#endif - -- (void)dealloc -{ - id const *objects = _array.items; - size_t count = _array.count; - - for (size_t i = 0; i < count; i++) - [objects[i] release]; - - [_array release]; - - [super dealloc]; -} -@end DELETED src/OFAdjacentSubarray.h Index: src/OFAdjacentSubarray.h ================================================================== --- src/OFAdjacentSubarray.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (c) 2008-2022 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#import "OFSubarray.h" - -OF_ASSUME_NONNULL_BEGIN - -@interface OFAdjacentSubarray: OFSubarray -@end - -OF_ASSUME_NONNULL_END DELETED src/OFAdjacentSubarray.m Index: src/OFAdjacentSubarray.m ================================================================== --- src/OFAdjacentSubarray.m +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2008-2022 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#include "config.h" - -#import "OFAdjacentSubarray.h" -#import "OFAdjacentArray.h" -#import "OFMutableAdjacentArray.h" - -@implementation OFAdjacentSubarray -- (const id *)objects -{ - return _array.objects + _range.location; -} - -- (bool)isEqual: (id)object -{ - OFArray *otherArray; - id const *objects, *otherObjects; - - if (object == self) - return true; - - if (![object isKindOfClass: [OFAdjacentArray class]] && - ![object isKindOfClass: [OFMutableAdjacentArray class]]) - return [super isEqual: object]; - - otherArray = object; - - if (_range.length != otherArray.count) - return false; - - objects = self.objects; - otherObjects = otherArray.objects; - - for (size_t i = 0; i < _range.length; i++) - if (![objects[i] isEqual: otherObjects[i]]) - return false; - - return true; -} - -#ifdef OF_HAVE_BLOCKS -- (void)enumerateObjectsUsingBlock: (OFArrayEnumerationBlock)block -{ - id const *objects = self.objects; - bool stop = false; - - for (size_t i = 0; i < _range.length && !stop; i++) - block(objects[i], i, &stop); -} -#endif -@end Index: src/OFApplication.h ================================================================== --- src/OFApplication.h +++ src/OFApplication.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,16 @@ @class OFMutableArray OF_GENERIC(ObjectType); @class OFMutableDictionary OF_GENERIC(KeyType, ObjectType); @class OFSandbox; @class OFString; +/** + * @brief A notification that will be sent when the application did finish + * launching. + */ +extern const OFNotificationName OFApplicationDidFinishLaunchingNotification; + /** * @brief A notification that will be sent when the application will terminate. */ extern const OFNotificationName OFApplicationWillTerminateNotification; @@ -49,11 +55,11 @@ * * // In MyAppDelegate.m: * OF_APPLICATION_DELEGATE(MyAppDelegate) * * @implementation MyAppDelegate - * - (void)applicationDidFinishLaunching + * - (void)applicationDidFinishLaunching: (OFNotification *)notification * { * [OFApplication terminate]; * } * @end * @endcode @@ -79,18 +85,24 @@ */ @protocol OFApplicationDelegate /** * @brief A method which is called when the application was initialized and is * running now. + * + * @param notification A notification with name + * OFApplicationDidFinishLaunchingNotification */ -- (void)applicationDidFinishLaunching; +- (void)applicationDidFinishLaunching: (OFNotification *)notification; @optional /** * @brief A method which is called when the application will terminate. + * + * @param notification A notification with name + * OFApplicationWillTerminateNotification */ -- (void)applicationWillTerminate; +- (void)applicationWillTerminate: (OFNotification *)notification; /** * @brief A method which is called when the application received a SIGINT. * * @warning You are not allowed to send any messages inside this method, as @@ -151,11 +163,11 @@ * In order to create a new OFApplication, you should create a class conforming * to the optional @ref OFApplicationDelegate protocol and put * `OF_APPLICATION_DELEGATE(NameOfYourClass)` in the .m file of that class. * * When the application is about to be terminated, - * @ref OFApplicationDelegate#applicationWillTerminate will be called on the + * @ref OFApplicationDelegate#applicationWillTerminate: will be called on the * delegate and an @ref OFApplicationWillTerminateNotification will be sent. */ OF_SUBCLASSING_RESTRICTED @interface OFApplication: OFObject { Index: src/OFApplication.m ================================================================== --- src/OFApplication.m +++ src/OFApplication.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,10 +35,11 @@ #import "OFNotificationCenter.h" #import "OFPair.h" #import "OFRunLoop+Private.h" #import "OFRunLoop.h" #import "OFSandbox.h" +#import "OFStdIOStream.h" #import "OFString.h" #import "OFSystemInfo.h" #import "OFThread+Private.h" #import "OFThread.h" @@ -52,12 +53,14 @@ #elif defined(OF_WINDOWS) # include extern int _CRT_glob; extern void __wgetmainargs(int *, wchar_t ***, wchar_t ***, int, int *); #elif defined(OF_AMIGAOS) +# define Class IntuitionClass # include # include +# undef Class #elif !defined(OF_IOS) extern char **environ; #endif #ifdef OF_PSP @@ -82,27 +85,30 @@ andWideArgumentValues: (wchar_t *[])wargv; #endif - (void)of_run; @end +const OFNotificationName OFApplicationDidFinishLaunchingNotification = + @"OFApplicationDidFinishLaunchingNotification"; const OFNotificationName OFApplicationWillTerminateNotification = @"OFApplicationWillTerminateNotification"; static OFApplication *app = nil; static void atexitHandler(void) { id delegate = app.delegate; - - [[OFNotificationCenter defaultCenter] - postNotificationName: OFApplicationWillTerminateNotification + OFNotification *notification = [OFNotification + notificationWithName: OFApplicationWillTerminateNotification object: app]; - if ([delegate respondsToSelector: @selector(applicationWillTerminate)]) - [delegate applicationWillTerminate]; + if ([delegate respondsToSelector: @selector(applicationWillTerminate:)]) + [delegate applicationWillTerminate: notification]; [delegate release]; + + [[OFNotificationCenter defaultCenter] postNotification: notification]; #if defined(OF_HAVE_THREADS) && defined(OF_HAVE_SOCKETS) && \ defined(OF_AMIGAOS) && !defined(OF_MORPHOS) OFSocketDeinit(); #endif @@ -109,22 +115,21 @@ } int OFApplicationMain(int *argc, char **argv[], id delegate) { -#ifdef OF_WINDOWS - wchar_t **wargv, **wenvp; - int wargc, si = 0; -#endif - [[OFLocale alloc] init]; app = [[OFApplication alloc] of_init]; #ifdef OF_WINDOWS if ([OFSystemInfo isWindowsNT]) { + wchar_t **wargv, **wenvp; + int wargc, si = 0; + __wgetmainargs(&wargc, &wargv, &wenvp, _CRT_glob, &si); + [app of_setArgumentCount: argc andArgumentValues: argv andWideArgumentCount: wargc andWideArgumentValues: wargv]; } else @@ -258,13 +263,12 @@ continue; } pos = [tmp rangeOfString: @"="].location; if (pos == OFNotFound) { - fprintf(stderr, - "Warning: Invalid environment " - "variable: %s\n", tmp.UTF8String); + OFLog(@"Warning: Invalid environment " + "variable: %@", tmp); continue; } key = [tmp substringToIndex: pos]; value = [tmp substringFromIndex: pos + 1]; @@ -300,13 +304,12 @@ continue; } pos = [tmp rangeOfString: @"="].location; if (pos == OFNotFound) { - fprintf(stderr, - "Warning: Invalid environment " - "variable: %s\n", tmp.UTF8String); + OFLog(@"Warning: Invalid environment " + "variable: %@", tmp); continue; } key = [tmp substringToIndex: pos]; value = [tmp substringFromIndex: pos + 1]; @@ -394,12 +397,12 @@ void *pool = objc_autoreleasePoolPush(); OFString *key, *value; char *sep; if ((sep = strchr(*env, '=')) == NULL) { - fprintf(stderr, "Warning: Invalid " - "environment variable: %s\n", *env); + OFLog(@"Warning: Invalid environment " + "variable: %s", *env); continue; } key = [OFString stringWithCString: *env @@ -578,10 +581,11 @@ - (void)of_run { void *pool = objc_autoreleasePoolPush(); OFRunLoop *runLoop; + OFNotification *notification; #ifdef OF_HAVE_THREADS [OFThread of_createMainThread]; runLoop = [OFRunLoop currentRunLoop]; #else @@ -597,11 +601,19 @@ * of_setMainRunLoop: retained it. However, we only have a weak * reference to it now, whereas we had a strong reference before. */ pool = objc_autoreleasePoolPush(); - [_delegate applicationDidFinishLaunching]; + + notification = [OFNotification + notificationWithName: OFApplicationDidFinishLaunchingNotification + object: app]; + + [[OFNotificationCenter defaultCenter] postNotification: notification]; + + [_delegate applicationDidFinishLaunching: notification]; + objc_autoreleasePoolPop(pool); [runLoop run]; } Index: src/OFArchiveEntry.h ================================================================== --- src/OFArchiveEntry.h +++ src/OFArchiveEntry.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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/OFArchiveIRIHandler.h Index: src/OFArchiveIRIHandler.h ================================================================== --- /dev/null +++ src/OFArchiveIRIHandler.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2008-2024 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#import "OFIRIHandler.h" + +OF_ASSUME_NONNULL_BEGIN + +@interface OFArchiveIRIHandler: OFIRIHandler +@end + +#ifdef __cplusplus +extern "C" { +#endif +extern OFIRI *OFArchiveIRIHandlerIRIForFileInArchive(OFString *, OFString *, + OFIRI *); +#ifdef __cplusplus +} +#endif + +OF_ASSUME_NONNULL_END ADDED src/OFArchiveIRIHandler.m Index: src/OFArchiveIRIHandler.m ================================================================== --- /dev/null +++ src/OFArchiveIRIHandler.m @@ -0,0 +1,200 @@ +/* + * Copyright (c) 2008-2024 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 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 "OFArchiveIRIHandler.h" +#import "OFCharacterSet.h" +#import "OFGZIPStream.h" +#import "OFIRI.h" +#import "OFLHAArchive.h" +#import "OFStream.h" +#import "OFTarArchive.h" +#import "OFZIPArchive.h" + +#import "OFInvalidArgumentException.h" +#import "OFOpenItemFailedException.h" + +@interface OFArchiveIRIHandlerPathAllowedCharacterSet: OFCharacterSet +{ + OFCharacterSet *_characterSet; + bool (*_characterIsMember)(id, SEL, OFUnichar); +} +@end + +static OFCharacterSet *pathAllowedCharacters; + +static void +initPathAllowedCharacters(void) +{ + pathAllowedCharacters = + [[OFArchiveIRIHandlerPathAllowedCharacterSet alloc] init]; +} + +@implementation OFArchiveIRIHandler +- (OFStream *)openItemAtIRI: (OFIRI *)IRI mode: (OFString *)mode +{ + void *pool = objc_autoreleasePoolPush(); + OFString *scheme = IRI.scheme; + OFString *percentEncodedPath, *path; + size_t pos; + OFIRI *archiveIRI; + OFStream *stream; + + if (IRI.host != nil || IRI.port != nil || IRI.user != nil || + IRI.password != nil || IRI.query != nil || IRI.fragment != nil) + @throw [OFInvalidArgumentException exception]; + + if (![mode isEqual: @"r"]) + /* + * Writing has some implications that are not decided yet: Will + * it always append to an archive? What happens if the file + * already exists? + */ + @throw [OFInvalidArgumentException exception]; + + /* + * GZIP only compresses one file and thus has no path inside an + * archive. + */ + if ([scheme isEqual: @"gzip"]) { + stream = [OFIRIHandler openItemAtIRI: [OFIRI IRIWithString: + IRI.path] + mode: @"r"]; + stream = [OFGZIPStream streamWithStream: stream mode: @"r"]; + goto end; + } + + percentEncodedPath = IRI.percentEncodedPath; + pos = [percentEncodedPath rangeOfString: @"!"].location; + + if (pos == OFNotFound) + @throw [OFInvalidArgumentException exception]; + + archiveIRI = [OFIRI IRIWithString: + [percentEncodedPath substringWithRange: OFMakeRange(0, pos)] + .stringByRemovingPercentEncoding]; + path = [percentEncodedPath substringWithRange: + OFMakeRange(pos + 1, percentEncodedPath.length - pos - 1)] + .stringByRemovingPercentEncoding; + + if ([scheme isEqual: @"lha"]) { + OFLHAArchive *archive = [OFLHAArchive archiveWithIRI: archiveIRI + mode: @"r"]; + OFLHAArchiveEntry *entry; + + while ((entry = [archive nextEntry]) != nil) { + if ([entry.fileName isEqual: path]) { + stream = [archive streamForReadingCurrentEntry]; + goto end; + } + } + + @throw [OFOpenItemFailedException exceptionWithIRI: IRI + mode: mode + errNo: ENOENT]; + } else if ([scheme isEqual: @"tar"]) { + OFTarArchive *archive = [OFTarArchive archiveWithIRI: archiveIRI + mode: @"r"]; + OFTarArchiveEntry *entry; + + while ((entry = [archive nextEntry]) != nil) { + if ([entry.fileName isEqual: path]) { + stream = [archive streamForReadingCurrentEntry]; + goto end; + } + } + + @throw [OFOpenItemFailedException exceptionWithIRI: IRI + mode: mode + errNo: ENOENT]; + } else if ([scheme isEqual: @"zip"]) { + OFZIPArchive *archive = [OFZIPArchive archiveWithIRI: archiveIRI + mode: @"r"]; + + stream = [archive streamForReadingFile: path]; + } else + @throw [OFInvalidArgumentException exception]; + +end: + stream = [stream retain]; + + objc_autoreleasePoolPop(pool); + + return [stream autorelease]; +} +@end + +@implementation OFArchiveIRIHandlerPathAllowedCharacterSet +- (instancetype)init +{ + self = [super init]; + + @try { + _characterSet = + [[OFCharacterSet IRIPathAllowedCharacterSet] retain]; + _characterIsMember = (bool (*)(id, SEL, OFUnichar)) + [_characterSet methodForSelector: + @selector(characterIsMember:)]; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (void)dealloc +{ + [_characterSet release]; + + [super dealloc]; +} + +- (bool)characterIsMember: (OFUnichar)character +{ + return (character != '!' && _characterIsMember(_characterSet, + @selector(characterIsMember:), character)); +} +@end + +OFIRI * +OFArchiveIRIHandlerIRIForFileInArchive(OFString *scheme, + OFString *pathInArchive, OFIRI *archiveIRI) +{ + static OFOnceControl onceControl = OFOnceControlInitValue; + OFMutableIRI *ret = [OFMutableIRI IRIWithScheme: scheme]; + void *pool = objc_autoreleasePoolPush(); + OFString *archiveIRIString; + + OFOnce(&onceControl, initPathAllowedCharacters); + + pathInArchive = [pathInArchive + stringByAddingPercentEncodingWithAllowedCharacters: + pathAllowedCharacters]; + archiveIRIString = [archiveIRI.string + stringByAddingPercentEncodingWithAllowedCharacters: + pathAllowedCharacters]; + + ret.percentEncodedPath = [OFString + stringWithFormat: @"%@!%@", archiveIRIString, pathInArchive]; + [ret makeImmutable]; + + objc_autoreleasePoolPop(pool); + + return ret; +} DELETED src/OFArchiveURIHandler.h Index: src/OFArchiveURIHandler.h ================================================================== --- src/OFArchiveURIHandler.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (c) 2008-2022 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#import "OFURIHandler.h" - -OF_ASSUME_NONNULL_BEGIN - -@interface OFArchiveURIHandler: OFURIHandler -@end - -#ifdef __cplusplus -extern "C" { -#endif -extern OFURI *OFArchiveURIHandlerURIForFileInArchive(OFString *, OFString *, - OFURI *); -#ifdef __cplusplus -} -#endif - -OF_ASSUME_NONNULL_END DELETED src/OFArchiveURIHandler.m Index: src/OFArchiveURIHandler.m ================================================================== --- src/OFArchiveURIHandler.m +++ /dev/null @@ -1,200 +0,0 @@ -/* - * Copyright (c) 2008-2022 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 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 "OFArchiveURIHandler.h" -#import "OFCharacterSet.h" -#import "OFGZIPStream.h" -#import "OFLHAArchive.h" -#import "OFStream.h" -#import "OFTarArchive.h" -#import "OFURI.h" -#import "OFZIPArchive.h" - -#import "OFInvalidArgumentException.h" -#import "OFOpenItemFailedException.h" - -@interface OFArchiveURIHandlerPathAllowedCharacterSet: OFCharacterSet -{ - OFCharacterSet *_characterSet; - bool (*_characterIsMember)(id, SEL, OFUnichar); -} -@end - -static OFCharacterSet *pathAllowedCharacters; - -static void -initPathAllowedCharacters(void) -{ - pathAllowedCharacters = - [[OFArchiveURIHandlerPathAllowedCharacterSet alloc] init]; -} - -@implementation OFArchiveURIHandler -- (OFStream *)openItemAtURI: (OFURI *)URI mode: (OFString *)mode -{ - void *pool = objc_autoreleasePoolPush(); - OFString *scheme = URI.scheme; - OFString *percentEncodedPath, *path; - size_t pos; - OFURI *archiveURI; - OFStream *stream; - - if (URI.host != nil || URI.port != nil || URI.user != nil || - URI.password != nil || URI.query != nil || URI.fragment != nil) - @throw [OFInvalidArgumentException exception]; - - if (![mode isEqual: @"r"]) - /* - * Writing has some implications that are not decided yet: Will - * it always append to an archive? What happens if the file - * already exists? - */ - @throw [OFInvalidArgumentException exception]; - - /* - * GZIP only compresses one file and thus has no path inside an - * archive. - */ - if ([scheme isEqual: @"gzip"]) { - stream = [OFURIHandler openItemAtURI: [OFURI URIWithString: - URI.path] - mode: @"r"]; - stream = [OFGZIPStream streamWithStream: stream mode: @"r"]; - goto end; - } - - percentEncodedPath = URI.percentEncodedPath; - pos = [percentEncodedPath rangeOfString: @"!"].location; - - if (pos == OFNotFound) - @throw [OFInvalidArgumentException exception]; - - archiveURI = [OFURI URIWithString: - [percentEncodedPath substringWithRange: OFMakeRange(0, pos)] - .stringByRemovingPercentEncoding]; - path = [percentEncodedPath substringWithRange: - OFMakeRange(pos + 1, percentEncodedPath.length - pos - 1)] - .stringByRemovingPercentEncoding; - - if ([scheme isEqual: @"lha"]) { - OFLHAArchive *archive = [OFLHAArchive archiveWithURI: archiveURI - mode: @"r"]; - OFLHAArchiveEntry *entry; - - while ((entry = [archive nextEntry]) != nil) { - if ([entry.fileName isEqual: path]) { - stream = [archive streamForReadingCurrentEntry]; - goto end; - } - } - - @throw [OFOpenItemFailedException exceptionWithURI: URI - mode: mode - errNo: ENOENT]; - } else if ([scheme isEqual: @"tar"]) { - OFTarArchive *archive = [OFTarArchive archiveWithURI: archiveURI - mode: @"r"]; - OFTarArchiveEntry *entry; - - while ((entry = [archive nextEntry]) != nil) { - if ([entry.fileName isEqual: path]) { - stream = [archive streamForReadingCurrentEntry]; - goto end; - } - } - - @throw [OFOpenItemFailedException exceptionWithURI: URI - mode: mode - errNo: ENOENT]; - } else if ([scheme isEqual: @"zip"]) { - OFZIPArchive *archive = [OFZIPArchive archiveWithURI: archiveURI - mode: @"r"]; - - stream = [archive streamForReadingFile: path]; - } else - @throw [OFInvalidArgumentException exception]; - -end: - stream = [stream retain]; - - objc_autoreleasePoolPop(pool); - - return [stream autorelease]; -} -@end - -@implementation OFArchiveURIHandlerPathAllowedCharacterSet -- (instancetype)init -{ - self = [super init]; - - @try { - _characterSet = - [[OFCharacterSet URIPathAllowedCharacterSet] retain]; - _characterIsMember = (bool (*)(id, SEL, OFUnichar)) - [_characterSet methodForSelector: - @selector(characterIsMember:)]; - } @catch (id e) { - [self release]; - @throw e; - } - - return self; -} - -- (void)dealloc -{ - [_characterSet release]; - - [super dealloc]; -} - -- (bool)characterIsMember: (OFUnichar)character -{ - return (character != '!' && _characterIsMember(_characterSet, - @selector(characterIsMember:), character)); -} -@end - -OFURI * -OFArchiveURIHandlerURIForFileInArchive(OFString *scheme, - OFString *pathInArchive, OFURI *archiveURI) -{ - static OFOnceControl onceControl = OFOnceControlInitValue; - OFMutableURI *ret = [OFMutableURI URIWithScheme: scheme]; - void *pool = objc_autoreleasePoolPush(); - OFString *archiveURIString; - - OFOnce(&onceControl, initPathAllowedCharacters); - - pathInArchive = [pathInArchive - stringByAddingPercentEncodingWithAllowedCharacters: - pathAllowedCharacters]; - archiveURIString = [archiveURI.string - stringByAddingPercentEncodingWithAllowedCharacters: - pathAllowedCharacters]; - - ret.percentEncodedPath = [OFString - stringWithFormat: @"%@!%@", archiveURIString, pathInArchive]; - [ret makeImmutable]; - - objc_autoreleasePoolPop(pool); - - return ret; -} Index: src/OFArray+Private.h ================================================================== --- src/OFArray+Private.h +++ src/OFArray+Private.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -23,11 +23,10 @@ #include #import "OFObject.h" #import "OFCollection.h" #import "OFEnumerator.h" -#import "OFSerialization.h" #import "OFJSONRepresentation.h" #import "OFMessagePackRepresentation.h" OF_ASSUME_NONNULL_BEGIN @@ -100,11 +99,11 @@ * @brief An abstract class for storing objects in an array. * * @note Subclasses must implement @ref count and @ref objectAtIndex:. */ @interface OFArray OF_GENERIC(ObjectType): OFObject #if !defined(OF_HAVE_GENERICS) && !defined(DOXYGEN) # define ObjectType id #endif /** @@ -183,10 +182,17 @@ * @return A new autoreleased OFArray */ + (instancetype)arrayWithObjects: (ObjectType const _Nonnull *_Nonnull)objects count: (size_t)count; +/** + * @brief Initializes an OFArray with no objects. + * + * @return An initialized OFArray + */ +- (instancetype)init OF_DESIGNATED_INITIALIZER; + /** * @brief Initializes an OFArray with the specified object. * * @param object An object * @return An initialized OFArray @@ -226,11 +232,11 @@ * @param objects A C array of objects * @param count The length of the C array * @return An initialized OFArray */ - (instancetype)initWithObjects: (ObjectType const _Nonnull *_Nonnull)objects - count: (size_t)count; + count: (size_t)count OF_DESIGNATED_INITIALIZER; /** * @brief Returns an OFEnumerator to enumerate through all objects of the array. * * @return An OFEnumerator to enumerate through all objects of the array @@ -403,10 +409,24 @@ */ - (OFArray OF_GENERIC(ObjectType) *) sortedArrayUsingSelector: (SEL)selector options: (OFArraySortOptions)options; +/** + * @brief Returns a copy of the array sorted using the specified function and + * options. + * + * @param compare The function to use to sort the array + * @param context Context passed to the function to compare + * @param options The options to use when sorting the array + * @return A sorted copy of the array + */ +- (OFArray OF_GENERIC(ObjectType) *) + sortedArrayUsingFunction: (OFCompareFunction)compare + context: (nullable void *)context + options: (OFArraySortOptions)options; + #ifdef OF_HAVE_BLOCKS /** * @brief Returns a copy of the array sorted using the specified selector and * options. * Index: src/OFArray.m ================================================================== --- src/OFArray.m +++ src/OFArray.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,20 +16,17 @@ #include "config.h" #include #include -#include - #import "OFArray.h" #import "OFArray+Private.h" -#import "OFAdjacentArray.h" +#import "OFConcreteArray.h" #import "OFData.h" #import "OFNull.h" #import "OFString.h" #import "OFSubarray.h" -#import "OFXMLElement.h" #import "OFEnumerationMutationException.h" #import "OFInvalidArgumentException.h" #import "OFOutOfRangeException.h" @@ -45,82 +42,69 @@ @interface OFPlaceholderArray: OFArray @end @implementation OFPlaceholderArray +#ifdef __clang__ +/* We intentionally don't call into super, so silence the warning. */ +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wunknown-pragmas" +# pragma clang diagnostic ignored "-Wobjc-designated-initializers" +#endif - (instancetype)init { - return (id)[[OFAdjacentArray alloc] init]; + return (id)[[OFConcreteArray alloc] init]; } - (instancetype)initWithObject: (id)object { - return (id)[[OFAdjacentArray alloc] initWithObject: object]; + return (id)[[OFConcreteArray alloc] initWithObject: object]; } - (instancetype)initWithObjects: (id)firstObject, ... { id ret; va_list arguments; va_start(arguments, firstObject); - ret = [[OFAdjacentArray alloc] initWithObject: firstObject + ret = [[OFConcreteArray alloc] initWithObject: firstObject arguments: arguments]; va_end(arguments); return ret; } - (instancetype)initWithObject: (id)firstObject arguments: (va_list)arguments { - return (id)[[OFAdjacentArray alloc] initWithObject: firstObject + return (id)[[OFConcreteArray alloc] initWithObject: firstObject arguments: arguments]; } - (instancetype)initWithArray: (OFArray *)array { - return (id)[[OFAdjacentArray alloc] initWithArray: array]; + return (id)[[OFConcreteArray alloc] initWithArray: array]; } - (instancetype)initWithObjects: (id const *)objects count: (size_t)count { - return (id)[[OFAdjacentArray alloc] initWithObjects: objects + return (id)[[OFConcreteArray alloc] initWithObjects: objects count: count]; } - -- (instancetype)initWithSerialization: (OFXMLElement *)element -{ - return (id)[[OFAdjacentArray alloc] initWithSerialization: element]; -} - -- (instancetype)retain -{ - return self; -} - -- (instancetype)autorelease -{ - return self; -} - -- (void)release -{ -} - -- (void)dealloc -{ - OF_DEALLOC_UNSUPPORTED -} +#ifdef __clang__ +# pragma clang diagnostic pop +#endif + +OF_SINGLETON_METHODS @end @implementation OFArray + (void)initialize { if (self == [OFArray class]) - placeholder.isa = [OFPlaceholderArray class]; + object_setClass((id)&placeholder, [OFPlaceholderArray class]); } + (instancetype)alloc { if (self == [OFArray class]) @@ -164,11 +148,12 @@ count: count] autorelease]; } - (instancetype)init { - if ([self isMemberOfClass: [OFArray class]]) { + if ([self isMemberOfClass: [OFArray class]] || + [self isMemberOfClass: [OFMutableArray class]]) { @try { [self doesNotRecognizeSelector: _cmd]; } @catch (id e) { [self release]; @throw e; @@ -180,16 +165,11 @@ return [super init]; } - (instancetype)initWithObject: (id)object { - if (object == nil) { - [self release]; - @throw [OFInvalidArgumentException exception]; - } - - return [self initWithObjects: object, nil]; + return [self initWithObjects: &object count: 1]; } - (instancetype)initWithObjects: (id)firstObject, ... { id ret; @@ -200,31 +180,85 @@ va_end(arguments); return ret; } -- (instancetype)initWithObject: (id)firstObject - arguments: (va_list)arguments +- (instancetype)initWithObject: (id)firstObject arguments: (va_list)arguments { - OF_INVALID_INIT_METHOD + size_t count = 1; + va_list argumentsCopy; + id *objects; + + if (firstObject == nil) + return [self init]; + + va_copy(argumentsCopy, arguments); + while (va_arg(argumentsCopy, id) != nil) + count++; + + @try { + objects = OFAllocMemory(count, sizeof(id)); + } @catch (id e) { + [self release]; + @throw e; + } + + @try { + objects[0] = firstObject; + + for (size_t i = 1; i < count; i++) { + objects[i] = va_arg(arguments, id); + OFEnsure(objects[i] != nil); + } + + self = [self initWithObjects: objects count: count]; + } @finally { + OFFreeMemory(objects); + } + + return self; } - (instancetype)initWithArray: (OFArray *)array { - OF_INVALID_INIT_METHOD + id *objects; + size_t count; + + @try { + count = array.count; + objects = OFAllocMemory(count, sizeof(id)); + + [array getObjects: objects + inRange: OFMakeRange(0, count)]; + } @catch (id e) { + [self release]; + @throw e; + } + + @try { + self = [self initWithObjects: objects count: count]; + } @finally { + OFFreeMemory(objects); + } + + return self; } +#ifdef __clang__ +/* We intentionally don't call into super, so silence the warning. */ +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wunknown-pragmas" +# pragma clang diagnostic ignored "-Wobjc-designated-initializers" +#endif - (instancetype)initWithObjects: (id const *)objects count: (size_t)count { OF_INVALID_INIT_METHOD } - -- (instancetype)initWithSerialization: (OFXMLElement *)element -{ - OF_INVALID_INIT_METHOD -} +#ifdef __clang__ +# pragma clang diagnostic pop +#endif - (size_t)count { OF_UNRECOGNIZED_SELECTOR } @@ -375,11 +409,12 @@ if (range.length > SIZE_MAX - range.location || range.location + range.length < self.count) @throw [OFOutOfRangeException exception]; if (![self isKindOfClass: [OFMutableArray class]]) - return [OFSubarray arrayWithArray: self range: range]; + return [[[OFSubarray alloc] initWithArray: self + range: range] autorelease]; buffer = OFAllocMemory(range.length, sizeof(*buffer)); @try { [self getObjects: buffer inRange: range]; @@ -548,37 +583,10 @@ [ret makeImmutable]; return [ret autorelease]; } -- (OFXMLElement *)XMLElementBySerializing -{ - void *pool = objc_autoreleasePoolPush(); - OFXMLElement *element; - - if ([self isKindOfClass: [OFMutableArray class]]) - element = [OFXMLElement elementWithName: @"OFMutableArray" - namespace: OFSerializationNS]; - else - element = [OFXMLElement elementWithName: @"OFArray" - namespace: OFSerializationNS]; - - for (id object in self) { - void *pool2 = objc_autoreleasePoolPush(); - - [element addChild: object.XMLElementBySerializing]; - - objc_autoreleasePoolPop(pool2); - } - - [element retain]; - - objc_autoreleasePoolPop(pool); - - return [element autorelease]; -} - - (OFString *)JSONRepresentation { return [self of_JSONRepresentationWithOptions: 0 depth: 0]; } @@ -687,11 +695,11 @@ [data addItems: child.items count: child.count]; objc_autoreleasePoolPop(pool2); } - assert(i == count); + OFAssert(i == count); [data makeImmutable]; objc_autoreleasePoolPop(pool); @@ -725,10 +733,20 @@ OFMutableArray *new = [[self mutableCopy] autorelease]; [new sortUsingSelector: selector options: options]; [new makeImmutable]; return new; } + +- (OFArray *)sortedArrayUsingFunction: (OFCompareFunction)compare + context: (void *)context + options: (OFArraySortOptions)options +{ + OFMutableArray *new = [[self mutableCopy] autorelease]; + [new sortUsingFunction: compare context: context options: options]; + [new makeImmutable]; + return new; +} #ifdef OF_HAVE_BLOCKS - (OFArray *)sortedArrayUsingComparator: (OFComparator)comparator options: (OFArraySortOptions)options { @@ -749,10 +767,11 @@ - (int)countByEnumeratingWithState: (OFFastEnumerationState *)state objects: (id *)objects count: (int)count { + static unsigned long dummyMutations; OFRange range = OFMakeRange(state->state, count); if (range.length > SIZE_MAX - range.location) @throw [OFOutOfRangeException exception]; @@ -764,11 +783,11 @@ if (range.location + range.length > ULONG_MAX) @throw [OFOutOfRangeException exception]; state->state = (unsigned long)(range.location + range.length); state->itemsPtr = objects; - state->mutationsPtr = (unsigned long *)self; + state->mutationsPtr = &dummyMutations; return (int)range.length; } - (OFEnumerator *)objectEnumerator Index: src/OFAsyncIPSocketConnector.h ================================================================== --- src/OFAsyncIPSocketConnector.h +++ src/OFAsyncIPSocketConnector.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFAsyncIPSocketConnector.m ================================================================== --- src/OFAsyncIPSocketConnector.m +++ src/OFAsyncIPSocketConnector.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFAtomic.h ================================================================== --- src/OFAtomic.h +++ src/OFAtomic.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -167,11 +167,11 @@ static OF_INLINE void OFReleaseMemoryBarrier(void) { /* nop */ } -#elif (defined(OF_X86_64) || defined(OF_X86)) && defined(__GNUC__) +#elif (defined(OF_AMD64) || defined(OF_X86)) && defined(__GNUC__) # import "platform/x86/OFAtomic.h" #elif defined(OF_POWERPC) && defined(__GNUC__) && !defined(__APPLE_CC__) && \ !defined(OF_AIX) # import "platform/PowerPC/OFAtomic.h" #elif defined(OF_HAVE_ATOMIC_BUILTINS) Index: src/OFBase64.h ================================================================== --- src/OFBase64.h +++ src/OFBase64.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,10 +24,11 @@ # import "OFAtomic.h" #endif #ifdef OF_HAVE_THREADS # import "OFPlainMutex.h" #endif +#import "OFString.h" #import "OFAllocFailedException.h" #import "OFInitializationFailedException.h" #if defined(OF_OBJFW_RUNTIME) @@ -161,11 +162,11 @@ # endif #endif static struct { Class isa; -} alloc_failed_exception; +} allocFailedException; #ifndef OF_HAVE_ATOMIC_OPS # define numSpinlocks 8 /* needs to be a power of 2 */ # define SPINLOCK_HASH(p) ((uintptr_t)p >> 4) & (numSpinlocks - 1) static OFSpinlock blockSpinlocks[numSpinlocks]; @@ -179,14 +180,13 @@ if ([(id)block isMemberOfClass: (Class)&_NSConcreteStackBlock]) { struct Block *copy; if ((copy = malloc(block->descriptor->size)) == NULL) { - alloc_failed_exception.isa = - [OFAllocFailedException class]; - @throw (OFAllocFailedException *) - &alloc_failed_exception; + object_setClass((id)&allocFailedException, + [OFAllocFailedException class]); + @throw (OFAllocFailedException *)&allocFailedException; } memcpy(copy, block, block->descriptor->size); object_setClass((id)copy, (Class)&_NSConcreteMallocBlock); copy->flags++; @@ -268,14 +268,14 @@ src = src->forwarding; if ((src->flags & OFBlockRefCountMask) == 0) { if ((*dst = malloc(src->size)) == NULL) { - alloc_failed_exception.isa = - [OFAllocFailedException class]; + object_setClass((id)&allocFailedException, + [OFAllocFailedException class]); @throw (OFAllocFailedException *) - &alloc_failed_exception; + &allocFailedException; } memcpy(*dst, src, src->size); (*dst)->flags = ((*dst)->flags & ~OFBlockRefCountMask) | 1; DELETED src/OFBytesValue.h Index: src/OFBytesValue.h ================================================================== --- src/OFBytesValue.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (c) 2008-2022 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#import "OFValue.h" - -OF_ASSUME_NONNULL_BEGIN - -@interface OFBytesValue: OFValue -{ - size_t _size; - void *_bytes; - const char *_objCType; -} -@end - -OF_ASSUME_NONNULL_END DELETED src/OFBytesValue.m Index: src/OFBytesValue.m ================================================================== --- src/OFBytesValue.m +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) 2008-2022 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#import "OFBytesValue.h" -#import "OFMethodSignature.h" - -#import "OFOutOfRangeException.h" - -@implementation OFBytesValue -@synthesize objCType = _objCType; - -- (instancetype)initWithBytes: (const void *)bytes - objCType: (const char *)objCType -{ - self = [super init]; - - @try { - _size = OFSizeOfTypeEncoding(objCType); - _objCType = objCType; - _bytes = OFAllocMemory(1, _size); - - memcpy(_bytes, bytes, _size); - } @catch (id e) { - [self release]; - @throw e; - } - - return self; -} - -- (void)dealloc -{ - OFFreeMemory(_bytes); - - [super dealloc]; -} - -- (void)getValue: (void *)value size: (size_t)size -{ - if (size != _size) - @throw [OFOutOfRangeException exception]; - - memcpy(value, _bytes, _size); -} -@end Index: src/OFCRC16.h ================================================================== --- src/OFCRC16.h +++ src/OFCRC16.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,37 +54,19 @@ - (instancetype)initWithRange: (OFRange)range { return (id)[[OFRangeCharacterSet alloc] initWithRange: range]; } -- (instancetype)retain -{ - return self; -} - -- (instancetype)autorelease -{ - return self; -} - -- (void)release -{ -} - -- (void)dealloc -{ - OF_DEALLOC_UNSUPPORTED -} +OF_SINGLETON_METHODS @end @implementation OFCharacterSet + (void)initialize { - if (self != [OFCharacterSet class]) - return; - - placeholder.isa = [OFPlaceholderCharacterSet class]; + if (self == [OFCharacterSet class]) + object_setClass((id)&placeholder, + [OFPlaceholderCharacterSet class]); } + (instancetype)alloc { if (self == [OFCharacterSet class]) @@ -149,29 +131,10 @@ initWithCharacterSet: self] autorelease]; } @end @implementation OFWhitespaceCharacterSet -- (instancetype)autorelease -{ - return self; -} - -- (instancetype)retain -{ - return self; -} - -- (void)release -{ -} - -- (unsigned int)retainCount -{ - return OFMaxRetainCount; -} - - (bool)characterIsMember: (OFUnichar)character { switch (character) { case 0x0009: case 0x0020: @@ -194,6 +157,8 @@ return true; default: return false; } } + +OF_SINGLETON_METHODS @end Index: src/OFCollection.h ================================================================== --- src/OFCollection.h +++ src/OFCollection.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,15 +21,10 @@ * @class OFColor OFColor.h ObjFW/OFColor.h * * @brief A class for storing a color. */ @interface OFColor: OFObject -{ - float _red, _green, _blue, _alpha; - OF_RESERVE_IVARS(OFColor, 4) -} - #ifdef OF_HAVE_CLASS_PROPERTIES @property (class, readonly, nonatomic) OFColor *black; @property (class, readonly, nonatomic) OFColor *silver; @property (class, readonly, nonatomic) OFColor *grey; @property (class, readonly, nonatomic) OFColor *white; Index: src/OFColor.m ================================================================== --- src/OFColor.m +++ src/OFColor.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,27 +12,95 @@ * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this * file. */ #include "config.h" + +#include #import "OFColor.h" +#import "OFConcreteColor.h" #import "OFOnce.h" +#import "OFString.h" +#import "OFTaggedPointerColor.h" + +@interface OFPlaceholderColor: OFColor +@end + +@interface OFConcreteColorSingleton: OFConcreteColor +@end + +static struct { + Class isa; +} placeholder; + +#ifdef OF_OBJFW_RUNTIME +static const float allowedImprecision = 0.0000001; +#endif + +@implementation OFPlaceholderColor +- (instancetype)initWithRed: (float)red + green: (float)green + blue: (float)blue + alpha: (float)alpha +{ +#ifdef OF_OBJFW_RUNTIME + uint8_t redInt = nearbyintf(red * 255); + uint8_t greenInt = nearbyintf(green * 255); + uint8_t blueInt = nearbyintf(blue * 255); + + if (fabsf(red * 255 - redInt) < allowedImprecision && + fabsf(green * 255 - greenInt) < allowedImprecision && + fabsf(blue * 255 - blueInt) < allowedImprecision && alpha == 1) { + id ret = [OFTaggedPointerColor colorWithRed: redInt + green: greenInt + blue: blueInt]; + + if (ret != nil) + return ret; + } +#endif + + return (id)[[OFConcreteColor alloc] initWithRed: red + green: green + blue: blue + alpha: alpha]; +} + +OF_SINGLETON_METHODS +@end -#import "OFInvalidArgumentException.h" +@implementation OFConcreteColorSingleton +OF_SINGLETON_METHODS +@end @implementation OFColor ++ (void)initialize +{ + if (self == [OFColor class]) + object_setClass((id)&placeholder, [OFPlaceholderColor class]); +} + ++ (instancetype)alloc +{ + if (self == [OFColor class]) + return (id)&placeholder; + + return [super alloc]; +} + #define PREDEFINED_COLOR(name, redValue, greenValue, blueValue) \ static OFColor *name##Color = nil; \ \ static void \ initPredefinedColor_##name(void) \ { \ - name##Color = [[OFColor alloc] initWithRed: redValue \ - green: greenValue \ - blue: blueValue \ - alpha: 1]; \ + name##Color = [[OFConcreteColorSingleton alloc] \ + initWithRed: redValue \ + green: greenValue \ + blue: blueValue \ + alpha: 1]; \ } \ \ + (OFColor *)name \ { \ static OFOnceControl onceControl = OFOnceControlInitValue; \ @@ -72,75 +140,78 @@ - (instancetype)initWithRed: (float)red green: (float)green blue: (float)blue alpha: (float)alpha { - self = [super init]; - - @try { - if (red < 0.0 || red > 1.0 || - green < 0.0 || green > 1.0 || - blue < 0.0 || blue > 1.0 || - alpha < 0.0 || alpha > 1.0) - @throw [OFInvalidArgumentException exception]; - - _red = red; - _green = green; - _blue = blue; - _alpha = alpha; - } @catch (id e) { - [self release]; - @throw e; - } - - return self; + if ([self isMemberOfClass: [OFColor class]]) { + @try { + [self doesNotRecognizeSelector: _cmd]; + } @catch (id e) { + [self release]; + @throw e; + } + + abort(); + } + + return [super init]; } - (bool)isEqual: (id)object { OFColor *other; + float red, green, blue, alpha; + float otherRed, otherGreen, otherBlue, otherAlpha; if (object == self) return true; if (![object isKindOfClass: [OFColor class]]) return false; other = object; - - if (other->_red != _red) - return false; - if (other->_green != _green) - return false; - if (other->_blue != _blue) - return false; - if (other->_alpha != _alpha) + [self getRed: &red green: &green blue: &blue alpha: &alpha]; + [other getRed: &otherRed + green: &otherGreen + blue: &otherBlue + alpha: &otherAlpha]; + + if (otherRed != red) + return false; + if (otherGreen != green) + return false; + if (otherBlue != blue) + return false; + if (otherAlpha != alpha) return false; return true; } - (unsigned long)hash { + float red, green, blue, alpha; unsigned long hash; float tmp; + [self getRed: &red green: &green blue: &blue alpha: &alpha]; + OFHashInit(&hash); - tmp = OFToLittleEndianFloat(_red); + tmp = OFToLittleEndianFloat(red); + for (uint_fast8_t i = 0; i < sizeof(float); i++) + OFHashAddByte(&hash, ((char *)&tmp)[i]); + + tmp = OFToLittleEndianFloat(green); for (uint_fast8_t i = 0; i < sizeof(float); i++) OFHashAddByte(&hash, ((char *)&tmp)[i]); - tmp = OFToLittleEndianFloat(_green); + tmp = OFToLittleEndianFloat(blue); for (uint_fast8_t i = 0; i < sizeof(float); i++) OFHashAddByte(&hash, ((char *)&tmp)[i]); - tmp = OFToLittleEndianFloat(_blue); - for (uint_fast8_t i = 0; i < sizeof(float); i++) - OFHashAddByte(&hash, ((char *)&tmp)[i]); - - tmp = OFToLittleEndianFloat(_alpha); + tmp = OFToLittleEndianFloat(alpha); for (uint_fast8_t i = 0; i < sizeof(float); i++) OFHashAddByte(&hash, ((char *)&tmp)[i]); OFHashFinalize(&hash); @@ -150,13 +221,19 @@ - (void)getRed: (float *)red green: (float *)green blue: (float *)blue alpha: (float *)alpha { - *red = _red; - *green = _green; - *blue = _blue; + OF_UNRECOGNIZED_SELECTOR +} + +- (OFString *)description +{ + float red, green, blue, alpha; + + [self getRed: &red green: &green blue: &blue alpha: &alpha]; - if (alpha != NULL) - *alpha = _alpha; + return [OFString stringWithFormat: + @"<%@ red=%f green=%f blue=%f alpha=%f>", + self.class, red, green, blue, alpha]; } @end ADDED src/OFConcreteArray.h Index: src/OFConcreteArray.h ================================================================== --- /dev/null +++ src/OFConcreteArray.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2008-2024 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#import "OFArray.h" + +OF_ASSUME_NONNULL_BEGIN + +@class OFMutableData; + +@interface OFConcreteArray: OFArray +{ + OFMutableData *_array; +} +@end + +OF_ASSUME_NONNULL_END ADDED src/OFConcreteArray.m Index: src/OFConcreteArray.m ================================================================== --- /dev/null +++ src/OFConcreteArray.m @@ -0,0 +1,338 @@ +/* + * Copyright (c) 2008-2024 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 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 "OFConcreteArray.h" +#import "OFConcreteMutableArray.h" +#import "OFConcreteSubarray.h" +#import "OFData.h" +#import "OFString.h" + +#import "OFEnumerationMutationException.h" +#import "OFInvalidArgumentException.h" +#import "OFOutOfRangeException.h" + +@implementation OFConcreteArray +- (instancetype)init +{ + self = [super init]; + + @try { + _array = [[OFMutableData alloc] initWithItemSize: sizeof(id)]; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (instancetype)initWithObject: (id)object +{ + self = [self init]; + + @try { + if (object == nil) + @throw [OFInvalidArgumentException exception]; + + [_array addItem: &object]; + [object retain]; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (instancetype)initWithObject: (id)firstObject arguments: (va_list)arguments +{ + self = [self init]; + + @try { + id object; + + [_array addItem: &firstObject]; + [firstObject retain]; + + while ((object = va_arg(arguments, id)) != nil) { + [_array addItem: &object]; + [object retain]; + } + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (instancetype)initWithArray: (OFArray *)array +{ + id const *objects; + size_t count; + + self = [super init]; + + if (array == nil) + return self; + + @try { + objects = array.objects; + count = array.count; + + _array = [[OFMutableData alloc] initWithItemSize: sizeof(id) + capacity: count]; + } @catch (id e) { + [self release]; + @throw e; + } + + @try { + for (size_t i = 0; i < count; i++) + [objects[i] retain]; + + [_array addItems: objects count: count]; + } @catch (id e) { + for (size_t i = 0; i < count; i++) + [objects[i] release]; + + /* Prevent double-release of objects */ + [_array release]; + _array = nil; + + [self release]; + @throw e; + } + + return self; +} + +- (instancetype)initWithObjects: (id const *)objects count: (size_t)count +{ + self = [super init]; + + @try { + bool ok = true; + + for (size_t i = 0; i < count; i++) { + if (objects[i] == nil) + ok = false; + + [objects[i] retain]; + } + + if (!ok) + @throw [OFInvalidArgumentException exception]; + + _array = [[OFMutableData alloc] initWithItemSize: sizeof(id) + capacity: count]; + [_array addItems: objects count: count]; + } @catch (id e) { + for (size_t i = 0; i < count; i++) + [objects[i] release]; + + [self release]; + @throw e; + } + + return self; +} + +- (size_t)count +{ + return _array.count; +} + +- (id const *)objects +{ + return _array.items; +} + +- (id)objectAtIndex: (size_t)idx +{ + return *((id *)[_array itemAtIndex: idx]); +} + +- (id)objectAtIndexedSubscript: (size_t)idx +{ + return *((id *)[_array itemAtIndex: idx]); +} + +- (void)getObjects: (id *)buffer inRange: (OFRange)range +{ + id const *objects = _array.items; + size_t count = _array.count; + + if (range.length > SIZE_MAX - range.location || + range.location + range.length > count) + @throw [OFOutOfRangeException exception]; + + for (size_t i = 0; i < range.length; i++) + buffer[i] = objects[range.location + i]; +} + +- (size_t)indexOfObject: (id)object +{ + id const *objects; + size_t count; + + if (object == nil) + return OFNotFound; + + objects = _array.items; + count = _array.count; + + for (size_t i = 0; i < count; i++) + if ([objects[i] isEqual: object]) + return i; + + return OFNotFound; +} + +- (size_t)indexOfObjectIdenticalTo: (id)object +{ + id const *objects; + size_t count; + + if (object == nil) + return OFNotFound; + + objects = _array.items; + count = _array.count; + + for (size_t i = 0; i < count; i++) + if (objects[i] == object) + return i; + + return OFNotFound; +} + + +- (OFArray *)objectsInRange: (OFRange)range +{ + if (range.length > SIZE_MAX - range.location || + range.location + range.length > _array.count) + @throw [OFOutOfRangeException exception]; + + if ([self isKindOfClass: [OFMutableArray class]]) + return [OFArray + arrayWithObjects: (id *)_array.items + range.location + count: range.length]; + + return [[[OFConcreteSubarray alloc] initWithArray: self + range: range] autorelease]; +} + +- (bool)isEqual: (id)object +{ + OFArray *otherArray; + id const *objects, *otherObjects; + size_t count; + + if (object == self) + return true; + + if (![object isKindOfClass: [OFConcreteArray class]] && + ![object isKindOfClass: [OFConcreteMutableArray class]]) + return [super isEqual: object]; + + otherArray = object; + + count = _array.count; + + if (count != otherArray.count) + return false; + + objects = _array.items; + otherObjects = otherArray.objects; + + for (size_t i = 0; i < count; i++) + if (![objects[i] isEqual: otherObjects[i]]) + return false; + + return true; +} + +- (unsigned long)hash +{ + id const *objects = _array.items; + size_t count = _array.count; + unsigned long hash; + + OFHashInit(&hash); + + for (size_t i = 0; i < count; i++) + OFHashAddHash(&hash, [objects[i] hash]); + + OFHashFinalize(&hash); + + return hash; +} + +- (int)countByEnumeratingWithState: (OFFastEnumerationState *)state + objects: (id *)objects + count: (int)count_ +{ + static unsigned long dummyMutations; + size_t count = _array.count; + + if (count > INT_MAX) + /* + * Use the implementation from OFArray, which is slower, but can + * enumerate in chunks. + */ + return [super countByEnumeratingWithState: state + objects: objects + count: count_]; + + if (state->state >= count) + return 0; + + state->state = (unsigned long)count; + state->itemsPtr = (id *)_array.items; + state->mutationsPtr = &dummyMutations; + + return (int)count; +} + +#ifdef OF_HAVE_BLOCKS +- (void)enumerateObjectsUsingBlock: (OFArrayEnumerationBlock)block +{ + id const *objects = _array.items; + size_t count = _array.count; + bool stop = false; + + for (size_t i = 0; i < count && !stop; i++) + block(objects[i], i, &stop); +} +#endif + +- (void)dealloc +{ + id const *objects = _array.items; + size_t count = _array.count; + + for (size_t i = 0; i < count; i++) + [objects[i] release]; + + [_array release]; + + [super dealloc]; +} +@end ADDED src/OFConcreteColor.h Index: src/OFConcreteColor.h ================================================================== --- /dev/null +++ src/OFConcreteColor.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2008-2024 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#import "OFColor.h" + +OF_ASSUME_NONNULL_BEGIN + +@interface OFConcreteColor: OFColor +{ + float _red, _green, _blue, _alpha; +} +@end + +OF_ASSUME_NONNULL_END ADDED src/OFConcreteColor.m Index: src/OFConcreteColor.m ================================================================== --- /dev/null +++ src/OFConcreteColor.m @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2008-2024 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#include "config.h" + +#import "OFConcreteColor.h" + +#import "OFInvalidArgumentException.h" + +@implementation OFConcreteColor +- (instancetype)initWithRed: (float)red + green: (float)green + blue: (float)blue + alpha: (float)alpha +{ + self = [super init]; + + @try { + if (red < 0.0 || red > 1.0 || + green < 0.0 || green > 1.0 || + blue < 0.0 || blue > 1.0 || + alpha < 0.0 || alpha > 1.0) + @throw [OFInvalidArgumentException exception]; + + _red = red; + _green = green; + _blue = blue; + _alpha = alpha; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (void)getRed: (float *)red + green: (float *)green + blue: (float *)blue + alpha: (float *)alpha +{ + *red = _red; + *green = _green; + *blue = _blue; + + if (alpha != NULL) + *alpha = _alpha; +} +@end + ADDED src/OFConcreteCountedSet.h Index: src/OFConcreteCountedSet.h ================================================================== --- /dev/null +++ src/OFConcreteCountedSet.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2008-2024 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#import "OFCountedSet.h" + +OF_ASSUME_NONNULL_BEGIN + +@class OFMapTable; + +@interface OFConcreteCountedSet: OFCountedSet +{ + OFMapTable *_mapTable; +} +@end + +OF_ASSUME_NONNULL_END ADDED src/OFConcreteCountedSet.m Index: src/OFConcreteCountedSet.m ================================================================== --- /dev/null +++ src/OFConcreteCountedSet.m @@ -0,0 +1,172 @@ +/* + * Copyright (c) 2008-2024 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#include "config.h" + +#import "OFConcreteCountedSet.h" +#import "OFArray.h" +#import "OFConcreteMutableSet.h" +#import "OFMapTable.h" +#import "OFString.h" +#import "OFXMLAttribute.h" + +#import "OFInvalidArgumentException.h" +#import "OFInvalidFormatException.h" +#import "OFEnumerationMutationException.h" +#import "OFOutOfRangeException.h" + +@implementation OFConcreteCountedSet ++ (void)initialize +{ + if (self == [OFConcreteCountedSet class]) + [self inheritMethodsFromClass: [OFConcreteMutableSet class]]; +} + +- (instancetype)initWithSet: (OFSet *)set +{ + self = [self init]; + + @try { + void *pool = objc_autoreleasePoolPush(); + + if ([set isKindOfClass: [OFCountedSet class]]) { + OFCountedSet *countedSet = (OFCountedSet *)set; + + for (id object in countedSet) { + size_t count = + [countedSet countForObject: object]; + + for (size_t i = 0; i < count; i++) + [self addObject: object]; + } + } else + for (id object in set) + [self addObject: object]; + + objc_autoreleasePoolPop(pool); + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (instancetype)initWithArray: (OFArray *)array +{ + self = [self init]; + + @try { + id const *objects = array.objects; + size_t count = array.count; + + for (size_t i = 0; i < count; i++) + [self addObject: objects[i]]; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (instancetype)initWithObjects: (id const *)objects count: (size_t)count +{ + self = [self init]; + + @try { + for (size_t i = 0; i < count; i++) + [self addObject: objects[i]]; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (instancetype)initWithObject: (id)firstObject arguments: (va_list)arguments +{ + self = [self init]; + + @try { + id object; + + [self addObject: firstObject]; + + while ((object = va_arg(arguments, id)) != nil) + [self addObject: object]; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (size_t)countForObject: (id)object +{ + return (size_t)(uintptr_t)[_mapTable objectForKey: object]; +} + +#ifdef OF_HAVE_BLOCKS +- (void)enumerateObjectsAndCountUsingBlock: (OFCountedSetEnumerationBlock)block +{ + @try { + [_mapTable enumerateKeysAndObjectsUsingBlock: + ^ (void *key, void *object, bool *stop) { + block(key, (size_t)(uintptr_t)object, stop); + }]; + } @catch (OFEnumerationMutationException *e) { + @throw [OFEnumerationMutationException + exceptionWithObject: self]; + } +} +#endif + +- (void)addObject: (id)object +{ + size_t count = (size_t)(uintptr_t)[_mapTable objectForKey: object]; + + if (SIZE_MAX - count < 1 || UINTPTR_MAX - count < 1) + @throw [OFOutOfRangeException exception]; + + [_mapTable setObject: (void *)(uintptr_t)(count + 1) forKey: object]; +} + +- (void)removeObject: (id)object +{ + size_t count = (size_t)(uintptr_t)[_mapTable objectForKey: object]; + + if (count == 0) + return; + + count--; + + if (count > 0) + [_mapTable setObject: (void *)(uintptr_t)count forKey: object]; + else + [_mapTable removeObjectForKey: object]; +} + +- (void)removeAllObjects +{ + [_mapTable removeAllObjects]; +} + +- (void)makeImmutable +{ +} +@end ADDED src/OFConcreteData.h Index: src/OFConcreteData.h ================================================================== --- /dev/null +++ src/OFConcreteData.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2008-2024 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#import "OFData.h" + +OF_ASSUME_NONNULL_BEGIN + +@interface OFConcreteData: OFData +{ + unsigned char *_Nullable _items; + size_t _capacity, _count, _itemSize; + bool _freeWhenDone; +} +@end + +OF_ASSUME_NONNULL_END ADDED src/OFConcreteData.m Index: src/OFConcreteData.m ================================================================== --- /dev/null +++ src/OFConcreteData.m @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2008-2024 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 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 + +#import "OFConcreteData.h" + +#import "OFInvalidArgumentException.h" +#import "OFOutOfRangeException.h" + +@implementation OFConcreteData +- (instancetype)init +{ + return [self initWithItemSize: 1]; +} + +- (instancetype)initWithItemSize: (size_t)itemSize +{ + self = [super init]; + + @try { + if (itemSize == 0) + @throw [OFInvalidArgumentException exception]; + + _itemSize = itemSize; + _freeWhenDone = true; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (instancetype)initWithItems: (const void *)items + count: (size_t)count + itemSize: (size_t)itemSize +{ + self = [super init]; + + @try { + if (itemSize == 0) + @throw [OFInvalidArgumentException exception]; + + _items = OFAllocMemory(count, itemSize); + _capacity = _count = count; + _itemSize = itemSize; + _freeWhenDone = true; + + memcpy(_items, items, count * itemSize); + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (instancetype)initWithItemsNoCopy: (void *)items + count: (size_t)count + itemSize: (size_t)itemSize + freeWhenDone: (bool)freeWhenDone +{ + self = [super init]; + + @try { + if (itemSize == 0) + @throw [OFInvalidArgumentException exception]; + + _items = (unsigned char *)items; + _capacity = _count = count; + _itemSize = itemSize; + _freeWhenDone = freeWhenDone; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (void)dealloc +{ + if (_freeWhenDone) + OFFreeMemory(_items); + + [super dealloc]; +} + +- (size_t)count +{ + return _count; +} + +- (size_t)itemSize +{ + return _itemSize; +} + +- (const void *)items +{ + return _items; +} +@end ADDED src/OFConcreteDate.h Index: src/OFConcreteDate.h ================================================================== --- /dev/null +++ src/OFConcreteDate.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2008-2024 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#import "OFDate.h" + +OF_ASSUME_NONNULL_BEGIN + +@interface OFConcreteDate: OFDate +{ + OFTimeInterval _seconds; +} +@end + +OF_ASSUME_NONNULL_END ADDED src/OFConcreteDate.m Index: src/OFConcreteDate.m ================================================================== --- /dev/null +++ src/OFConcreteDate.m @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2008-2024 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#import "OFConcreteDate.h" + +@implementation OFConcreteDate +- (instancetype)initWithTimeIntervalSince1970: (OFTimeInterval)seconds +{ + self = [super initWithTimeIntervalSince1970: seconds]; + + _seconds = seconds; + + return self; +} + +- (OFTimeInterval)timeIntervalSince1970 +{ + return _seconds; +} +@end ADDED src/OFConcreteDictionary.h Index: src/OFConcreteDictionary.h ================================================================== --- /dev/null +++ src/OFConcreteDictionary.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2008-2024 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#import "OFDictionary.h" + +OF_ASSUME_NONNULL_BEGIN + +@class OFMapTable; +@class OFMapTableEnumerator; + +@interface OFConcreteDictionary: OFDictionary +{ + OFMapTable *_mapTable; +} + +- (instancetype)initWithCapacity: (size_t)capacity; +@end + +OF_ASSUME_NONNULL_END ADDED src/OFConcreteDictionary.m Index: src/OFConcreteDictionary.m ================================================================== --- /dev/null +++ src/OFConcreteDictionary.m @@ -0,0 +1,383 @@ +/* + * Copyright (c) 2008-2024 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#include "config.h" + +#import "OFConcreteDictionary.h" +#import "OFArray.h" +#import "OFConcreteMutableDictionary.h" +#import "OFMapTable+Private.h" +#import "OFMapTable.h" +#import "OFString.h" + +#import "OFEnumerationMutationException.h" +#import "OFInvalidArgumentException.h" +#import "OFInvalidFormatException.h" + +static void * +copy(void *object) +{ + return [(id)object copy]; +} + +static void * +retain(void *object) +{ + return [(id)object retain]; +} + +static void +release(void *object) +{ + [(id)object release]; +} + +static unsigned long +hash(void *object) +{ + return [(id)object hash]; +} + +static bool +equal(void *object1, void *object2) +{ + return [(id)object1 isEqual: (id)object2]; +} + +static const OFMapTableFunctions keyFunctions = { + .retain = copy, + .release = release, + .hash = hash, + .equal = equal +}; +static const OFMapTableFunctions objectFunctions = { + .retain = retain, + .release = release, + .hash = hash, + .equal = equal +}; + +@implementation OFConcreteDictionary +- (instancetype)init +{ + return [self initWithCapacity: 0]; +} + +- (instancetype)initWithCapacity: (size_t)capacity +{ + self = [super init]; + + @try { + _mapTable = [[OFMapTable alloc] + initWithKeyFunctions: keyFunctions + objectFunctions: objectFunctions + capacity: capacity]; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (instancetype)initWithDictionary: (OFDictionary *)dictionary +{ + size_t count; + + if (dictionary == nil) + return [self init]; + + if ([dictionary isKindOfClass: [OFConcreteDictionary class]] || + [dictionary isKindOfClass: [OFConcreteMutableDictionary class]]) { + self = [super init]; + + @try { + OFConcreteDictionary *dictionary_ = + (OFConcreteDictionary *)dictionary; + + _mapTable = [dictionary_->_mapTable copy]; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; + } + + @try { + count = dictionary.count; + } @catch (id e) { + [self release]; + @throw e; + } + + self = [self initWithCapacity: count]; + + @try { + void *pool = objc_autoreleasePoolPush(); + OFEnumerator *keyEnumerator, *objectEnumerator; + id key, object; + + keyEnumerator = [dictionary keyEnumerator]; + objectEnumerator = [dictionary objectEnumerator]; + while ((key = [keyEnumerator nextObject]) != nil && + (object = [objectEnumerator nextObject]) != nil) + [_mapTable setObject: object forKey: key]; + + objc_autoreleasePoolPop(pool); + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (instancetype)initWithObject: (id)object forKey: (id)key +{ + self = [self initWithCapacity: 1]; + + @try { + [_mapTable setObject: object forKey: key]; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (instancetype)initWithObjects: (id const *)objects + forKeys: (id const *)keys + count: (size_t)count +{ + self = [self initWithCapacity: count]; + + @try { + size_t i; + + for (i = 0; i < count; i++) + [_mapTable setObject: objects[i] forKey: keys[i]]; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (instancetype)initWithKey: (id)firstKey arguments: (va_list)arguments +{ + self = [super init]; + + @try { + va_list argumentsCopy; + id key, object; + size_t i, count; + + va_copy(argumentsCopy, arguments); + + if (firstKey == nil) + @throw [OFInvalidArgumentException exception]; + + key = firstKey; + + if ((object = va_arg(arguments, id)) == nil) + @throw [OFInvalidArgumentException exception]; + + count = 1; + for (; va_arg(argumentsCopy, id) != nil; count++); + + if (count % 2 != 0) + @throw [OFInvalidArgumentException exception]; + + count /= 2; + + _mapTable = [[OFMapTable alloc] + initWithKeyFunctions: keyFunctions + objectFunctions: objectFunctions + capacity: count]; + + [_mapTable setObject: object forKey: key]; + + for (i = 1; i < count; i++) { + key = va_arg(arguments, id); + object = va_arg(arguments, id); + + if (key == nil || object == nil) + @throw [OFInvalidArgumentException exception]; + + [_mapTable setObject: object forKey: key]; + } + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (void)dealloc +{ + [_mapTable release]; + + [super dealloc]; +} + +- (id)objectForKey: (id)key +{ + return [_mapTable objectForKey: key]; +} + +- (size_t)count +{ + return _mapTable.count; +} + +- (bool)isEqual: (id)object +{ + OFConcreteDictionary *dictionary; + + if (object == self) + return true; + + if (![object isKindOfClass: [OFConcreteDictionary class]] && + ![object isKindOfClass: [OFConcreteMutableDictionary class]]) + return [super isEqual: object]; + + dictionary = (OFConcreteDictionary *)object; + + return [dictionary->_mapTable isEqual: _mapTable]; +} + +- (bool)containsObject: (id)object +{ + return [_mapTable containsObject: object]; +} + +- (bool)containsObjectIdenticalTo: (id)object +{ + return [_mapTable containsObjectIdenticalTo: object]; +} + +- (OFArray *)allKeys +{ + OFArray *ret; + id *keys; + size_t count; + + count = _mapTable.count; + keys = OFAllocMemory(count, sizeof(*keys)); + + @try { + void *pool = objc_autoreleasePoolPush(); + OFMapTableEnumerator *enumerator; + void **keyPtr; + size_t i; + + i = 0; + enumerator = [_mapTable keyEnumerator]; + while ((keyPtr = [enumerator nextObject]) != NULL) { + OFAssert(i < count); + + keys[i++] = (id)*keyPtr; + } + + objc_autoreleasePoolPop(pool); + + ret = [OFArray arrayWithObjects: keys count: count]; + } @finally { + OFFreeMemory(keys); + } + + return ret; +} + +- (OFArray *)allObjects +{ + OFArray *ret; + id *objects; + size_t count; + + count = _mapTable.count; + objects = OFAllocMemory(count, sizeof(*objects)); + + @try { + void *pool = objc_autoreleasePoolPush(); + OFMapTableEnumerator *enumerator; + void **objectPtr; + size_t i; + + i = 0; + enumerator = [_mapTable objectEnumerator]; + while ((objectPtr = [enumerator nextObject]) != NULL) { + OFAssert(i < count); + + objects[i++] = (id)*objectPtr; + } + + objc_autoreleasePoolPop(pool); + + ret = [OFArray arrayWithObjects: objects count: count]; + } @finally { + OFFreeMemory(objects); + } + + return ret; +} + +- (OFEnumerator *)keyEnumerator +{ + return [[[OFMapTableEnumeratorWrapper alloc] + initWithEnumerator: [_mapTable keyEnumerator] + object: self] autorelease]; +} + +- (OFEnumerator *)objectEnumerator +{ + return [[[OFMapTableEnumeratorWrapper alloc] + initWithEnumerator: [_mapTable objectEnumerator] + object: self] autorelease]; +} + +- (int)countByEnumeratingWithState: (OFFastEnumerationState *)state + objects: (id *)objects + count: (int)count +{ + return [_mapTable countByEnumeratingWithState: state + objects: objects + count: count]; +} + +#ifdef OF_HAVE_BLOCKS +- (void)enumerateKeysAndObjectsUsingBlock: (OFDictionaryEnumerationBlock)block +{ + @try { + [_mapTable enumerateKeysAndObjectsUsingBlock: + ^ (void *key, void *object, bool *stop) { + block(key, object, stop); + }]; + } @catch (OFEnumerationMutationException *e) { + @throw [OFEnumerationMutationException + exceptionWithObject: self]; + } +} +#endif + +- (unsigned long)hash +{ + return _mapTable.hash; +} +@end ADDED src/OFConcreteMutableArray.h Index: src/OFConcreteMutableArray.h ================================================================== --- /dev/null +++ src/OFConcreteMutableArray.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2008-2024 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#import "OFArray.h" + +OF_ASSUME_NONNULL_BEGIN + +@class OFMutableData; + +@interface OFConcreteMutableArray: OFMutableArray +{ + OFMutableData *_array; + unsigned long _mutations; +} +@end + +OF_ASSUME_NONNULL_END ADDED src/OFConcreteMutableArray.m Index: src/OFConcreteMutableArray.m ================================================================== --- /dev/null +++ src/OFConcreteMutableArray.m @@ -0,0 +1,383 @@ +/* + * Copyright (c) 2008-2024 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 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 "OFConcreteMutableArray.h" +#import "OFConcreteArray.h" +#import "OFArray+Private.h" +#import "OFData.h" + +#import "OFEnumerationMutationException.h" +#import "OFInvalidArgumentException.h" +#import "OFOutOfRangeException.h" + +@implementation OFConcreteMutableArray ++ (void)initialize +{ + if (self == [OFConcreteMutableArray class]) + [self inheritMethodsFromClass: [OFConcreteArray class]]; +} + +- (instancetype)initWithCapacity: (size_t)capacity +{ + self = [super init]; + + @try { + _array = [[OFMutableData alloc] initWithItemSize: sizeof(id) + capacity: capacity]; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (void)addObject: (id)object +{ + if (object == nil) + @throw [OFInvalidArgumentException exception]; + + [_array addItem: &object]; + [object retain]; + + _mutations++; +} + +- (void)insertObject: (id)object atIndex: (size_t)idx +{ + if (object == nil) + @throw [OFInvalidArgumentException exception]; + + @try { + [_array insertItem: &object atIndex: idx]; + } @catch (OFOutOfRangeException *e) { + @throw [OFOutOfRangeException exception]; + } + [object retain]; + + _mutations++; +} + +- (void)insertObjectsFromArray: (OFArray *)array atIndex: (size_t)idx +{ + id const *objects = array.objects; + size_t count = array.count; + + @try { + [_array insertItems: objects atIndex: idx count: count]; + } @catch (OFOutOfRangeException *e) { + @throw [OFOutOfRangeException exception]; + } + + for (size_t i = 0; i < count; i++) + [objects[i] retain]; + + _mutations++; +} + +- (void)replaceObject: (id)oldObject withObject: (id)newObject +{ + id *objects; + size_t count; + + if (oldObject == nil || newObject == nil) + @throw [OFInvalidArgumentException exception]; + + objects = _array.mutableItems; + count = _array.count; + + for (size_t i = 0; i < count; i++) { + if ([objects[i] isEqual: oldObject]) { + [newObject retain]; + [objects[i] release]; + objects[i] = newObject; + } + } +} + +- (void)replaceObjectAtIndex: (size_t)idx withObject: (id)object +{ + id *objects; + id oldObject; + + if (object == nil) + @throw [OFInvalidArgumentException exception]; + + objects = _array.mutableItems; + + if (idx >= _array.count) + @throw [OFOutOfRangeException exception]; + + oldObject = objects[idx]; + objects[idx] = [object retain]; + [oldObject release]; +} + +- (void)replaceObjectIdenticalTo: (id)oldObject withObject: (id)newObject +{ + id *objects; + size_t count; + + if (oldObject == nil || newObject == nil) + @throw [OFInvalidArgumentException exception]; + + objects = _array.mutableItems; + count = _array.count; + + for (size_t i = 0; i < count; i++) { + if (objects[i] == oldObject) { + [newObject retain]; + [objects[i] release]; + objects[i] = newObject; + + return; + } + } +} + +- (void)removeObject: (id)object +{ + id const *objects; + size_t count; + + if (object == nil) + @throw [OFInvalidArgumentException exception]; + + objects = _array.items; + count = _array.count; + + for (size_t i = 0; i < count; i++) { + if ([objects[i] isEqual: object]) { + id tmp = objects[i]; + + [_array removeItemAtIndex: i]; + _mutations++; + + [tmp release]; + + objects = _array.items; + i--; + count--; + continue; + } + } +} + +- (void)removeObjectIdenticalTo: (id)object +{ + id const *objects; + size_t count; + + if (object == nil) + @throw [OFInvalidArgumentException exception]; + + objects = _array.items; + count = _array.count; + + for (size_t i = 0; i < count; i++) { + if (objects[i] == object) { + [_array removeItemAtIndex: i]; + _mutations++; + + [object release]; + + objects = _array.items; + i--; + count--; + continue; + } + } +} + +- (void)removeObjectAtIndex: (size_t)idx +{ +#ifndef __clang_analyzer__ + id object = [self objectAtIndex: idx]; + [_array removeItemAtIndex: idx]; + [object release]; + + _mutations++; +#endif +} + +- (void)removeAllObjects +{ + id const *objects = _array.items; + size_t count = _array.count; + + for (size_t i = 0; i < count; i++) + [objects[i] release]; + + [_array removeAllItems]; +} + +- (void)removeObjectsInRange: (OFRange)range +{ + id const *objects = _array.items; + size_t count = _array.count; + id *copy; + + if (range.length > SIZE_MAX - range.location || + range.location >= count || range.length > count - range.location) + @throw [OFOutOfRangeException exception]; + + copy = OFAllocMemory(range.length, sizeof(*copy)); + memcpy(copy, objects + range.location, range.length * sizeof(id)); + + @try { + [_array removeItemsInRange: range]; + _mutations++; + + for (size_t i = 0; i < range.length; i++) + [copy[i] release]; + } @finally { + OFFreeMemory(copy); + } +} + +- (void)removeLastObject +{ +#ifndef __clang_analyzer__ + size_t count = _array.count; + id object; + + if (count == 0) + return; + + object = [self objectAtIndex: count - 1]; + [_array removeLastItem]; + [object release]; + + _mutations++; +#endif +} + +- (void)exchangeObjectAtIndex: (size_t)idx1 withObjectAtIndex: (size_t)idx2 +{ + id *objects = _array.mutableItems; + size_t count = _array.count; + id tmp; + + if (idx1 >= count || idx2 >= count) + @throw [OFOutOfRangeException exception]; + + tmp = objects[idx1]; + objects[idx1] = objects[idx2]; + objects[idx2] = tmp; +} + +- (void)reverse +{ + id *objects = _array.mutableItems; + size_t i, j, count = _array.count; + + if (count == 0 || count == 1) + return; + + for (i = 0, j = count - 1; i < j; i++, j--) { + id tmp = objects[i]; + objects[i] = objects[j]; + objects[j] = tmp; + } +} + +- (int)countByEnumeratingWithState: (OFFastEnumerationState *)state + objects: (id *)objects + count: (int)count_ +{ + size_t count = _array.count; + + if (count > INT_MAX) { + /* + * Use the implementation from OFArray (OFMutableArray does not + * have one), which is slower, but can enumerate in chunks, and + * set the mutations pointer. + */ + int ret = [super countByEnumeratingWithState: state + objects: objects + count: count_]; + state->mutationsPtr = &_mutations; + return ret; + } + + if (state->state >= count) + return 0; + + state->state = (unsigned long)count; + state->itemsPtr = (id *)_array.items; + state->mutationsPtr = &_mutations; + + return (int)count; +} + +- (OFEnumerator *)objectEnumerator +{ + return [[[OFArrayEnumerator alloc] + initWithArray: self + mutationsPtr: &_mutations] autorelease]; +} + +#ifdef OF_HAVE_BLOCKS +- (void)enumerateObjectsUsingBlock: (OFArrayEnumerationBlock)block +{ + id const *objects = _array.items; + size_t count = _array.count; + bool stop = false; + unsigned long mutations = _mutations; + + for (size_t i = 0; i < count && !stop; i++) { + if (_mutations != mutations) + @throw [OFEnumerationMutationException + exceptionWithObject: self]; + + block(objects[i], i, &stop); + } +} + +- (void)replaceObjectsUsingBlock: (OFArrayReplaceBlock)block +{ + id *objects = _array.mutableItems; + size_t count = _array.count; + unsigned long mutations = _mutations; + + for (size_t i = 0; i < count; i++) { + id new; + + if (_mutations != mutations) + @throw [OFEnumerationMutationException + exceptionWithObject: self]; + + new = block(objects[i], i); + + if (new == nil) + @throw [OFInvalidArgumentException exception]; + + if (new != objects[i]) { + [objects[i] release]; + objects[i] = [new retain]; + } + } +} +#endif + +- (void)makeImmutable +{ + object_setClass(self, [OFConcreteArray class]); +} +@end ADDED src/OFConcreteMutableData.h Index: src/OFConcreteMutableData.h ================================================================== --- /dev/null +++ src/OFConcreteMutableData.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2008-2024 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#import "OFMutableData.h" + +OF_ASSUME_NONNULL_BEGIN + +@interface OFConcreteMutableData: OFMutableData +{ + unsigned char *_Nullable _items; + size_t _capacity, _count, _itemSize; + bool _freeWhenDone; +} +@end + +OF_ASSUME_NONNULL_END ADDED src/OFConcreteMutableData.m Index: src/OFConcreteMutableData.m ================================================================== --- /dev/null +++ src/OFConcreteMutableData.m @@ -0,0 +1,189 @@ +/* + * Copyright (c) 2008-2024 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 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 + +#import "OFConcreteMutableData.h" +#import "OFConcreteData.h" + +#import "OFInvalidArgumentException.h" +#import "OFOutOfMemoryException.h" +#import "OFOutOfRangeException.h" + +@implementation OFConcreteMutableData ++ (void)initialize +{ + if (self == [OFConcreteMutableData class]) + [self inheritMethodsFromClass: [OFConcreteData class]]; +} + +- (instancetype)initWithItemSize: (size_t)itemSize capacity: (size_t)capacity +{ + self = [super init]; + + @try { + if (itemSize == 0) + @throw [OFInvalidArgumentException exception]; + + _items = OFAllocMemory(capacity, itemSize); + _itemSize = itemSize; + _capacity = capacity; + _freeWhenDone = true; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (instancetype)initWithItemsNoCopy: (void *)items + count: (size_t)count + itemSize: (size_t)itemSize + freeWhenDone: (bool)freeWhenDone +{ + self = [self initWithItems: items count: count itemSize: itemSize]; + + if (freeWhenDone) + OFFreeMemory(items); + + return self; +} + +- (void *)mutableItems +{ + return _items; +} + +- (void)addItem: (const void *)item +{ + if (SIZE_MAX - _count < 1) + @throw [OFOutOfRangeException exception]; + + if (_count + 1 > _capacity) { + _items = OFResizeMemory(_items, _count + 1, _itemSize); + _capacity = _count + 1; + } + + memcpy(_items + _count * _itemSize, item, _itemSize); + + _count++; +} + +- (void)addItems: (const void *)items count: (size_t)count +{ + if (count > SIZE_MAX - _count) + @throw [OFOutOfRangeException exception]; + + if (_count + count > _capacity) { + _items = OFResizeMemory(_items, _count + count, _itemSize); + _capacity = _count + count; + } + + memcpy(_items + _count * _itemSize, items, count * _itemSize); + _count += count; +} + +- (void)insertItems: (const void *)items + atIndex: (size_t)idx + count: (size_t)count +{ + if (count > SIZE_MAX - _count || idx > _count) + @throw [OFOutOfRangeException exception]; + + if (_count + count > _capacity) { + _items = OFResizeMemory(_items, _count + count, _itemSize); + _capacity = _count + count; + } + + memmove(_items + (idx + count) * _itemSize, _items + idx * _itemSize, + (_count - idx) * _itemSize); + memcpy(_items + idx * _itemSize, items, count * _itemSize); + + _count += count; +} + +- (void)increaseCountBy: (size_t)count +{ + if (count > SIZE_MAX - _count) + @throw [OFOutOfRangeException exception]; + + if (_count + count > _capacity) { + _items = OFResizeMemory(_items, _count + count, _itemSize); + _capacity = _count + count; + } + + memset(_items + _count * _itemSize, '\0', count * _itemSize); + _count += count; +} + +- (void)removeItemsInRange: (OFRange)range +{ + if (range.length > SIZE_MAX - range.location || + range.location + range.length > _count) + @throw [OFOutOfRangeException exception]; + + memmove(_items + range.location * _itemSize, + _items + (range.location + range.length) * _itemSize, + (_count - range.location - range.length) * _itemSize); + + _count -= range.length; + @try { + _items = OFResizeMemory(_items, _count, _itemSize); + _capacity = _count; + } @catch (OFOutOfMemoryException *e) { + /* We don't really care, as we only made it smaller */ + } +} + +- (void)removeLastItem +{ + if (_count == 0) + return; + + _count--; + @try { + _items = OFResizeMemory(_items, _count, _itemSize); + _capacity = _count; + } @catch (OFOutOfMemoryException *e) { + /* We don't care, as we only made it smaller */ + } +} + +- (void)removeAllItems +{ + OFFreeMemory(_items); + _items = NULL; + _count = 0; + _capacity = 0; +} + +- (void)makeImmutable +{ + if (_capacity != _count) { + @try { + _items = OFResizeMemory(_items, _count, _itemSize); + _capacity = _count; + } @catch (OFOutOfMemoryException *e) { + /* We don't care, as we only made it smaller */ + } + } + + object_setClass(self, [OFConcreteData class]); +} +@end ADDED src/OFConcreteMutableDictionary.h Index: src/OFConcreteMutableDictionary.h ================================================================== --- /dev/null +++ src/OFConcreteMutableDictionary.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2008-2024 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#import "OFDictionary.h" + +OF_ASSUME_NONNULL_BEGIN + +@class OFMapTable; + +@interface OFConcreteMutableDictionary: OFMutableDictionary +{ + OFMapTable *_mapTable; +} +@end + +OF_ASSUME_NONNULL_END ADDED src/OFConcreteMutableDictionary.m Index: src/OFConcreteMutableDictionary.m ================================================================== --- /dev/null +++ src/OFConcreteMutableDictionary.m @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2008-2024 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 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 "OFConcreteMutableDictionary.h" +#import "OFConcreteDictionary.h" +#import "OFMapTable.h" + +#import "OFEnumerationMutationException.h" +#import "OFOutOfRangeException.h" + +@implementation OFConcreteMutableDictionary ++ (void)initialize +{ + if (self == [OFConcreteMutableDictionary class]) + [self inheritMethodsFromClass: [OFConcreteDictionary class]]; +} + +- (void)setObject: (id)object forKey: (id)key +{ + [_mapTable setObject: object forKey: key]; +} + +- (void)removeObjectForKey: (id)key +{ + [_mapTable removeObjectForKey: key]; +} + +- (void)removeAllObjects +{ + [_mapTable removeAllObjects]; +} + +#ifdef OF_HAVE_BLOCKS +- (void)replaceObjectsUsingBlock: (OFDictionaryReplaceBlock)block +{ + @try { + [_mapTable replaceObjectsUsingBlock: + ^ void *(void *key, void *object) { + return block(key, object); + }]; + } @catch (OFEnumerationMutationException *e) { + @throw [OFEnumerationMutationException + exceptionWithObject: self]; + } +} +#endif + +- (void)makeImmutable +{ + object_setClass(self, [OFConcreteDictionary class]); +} +@end ADDED src/OFConcreteMutableSet.h Index: src/OFConcreteMutableSet.h ================================================================== --- /dev/null +++ src/OFConcreteMutableSet.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2008-2024 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#import "OFMutableSet.h" + +OF_ASSUME_NONNULL_BEGIN + +@class OFMapTable; + +@interface OFConcreteMutableSet: OFMutableSet +{ + OFMapTable *_mapTable; +} +@end + +OF_ASSUME_NONNULL_END ADDED src/OFConcreteMutableSet.m Index: src/OFConcreteMutableSet.m ================================================================== --- /dev/null +++ src/OFConcreteMutableSet.m @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2008-2024 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#include "config.h" + +#import "OFConcreteMutableSet.h" +#import "OFConcreteSet.h" +#import "OFMapTable.h" + +@implementation OFConcreteMutableSet ++ (void)initialize +{ + if (self == [OFConcreteMutableSet class]) + [self inheritMethodsFromClass: [OFConcreteSet class]]; +} + +- (void)addObject: (id)object +{ + [_mapTable setObject: (void *)1 forKey: object]; +} + +- (void)removeObject: (id)object +{ + [_mapTable removeObjectForKey: object]; +} + +- (void)removeAllObjects +{ + [_mapTable removeAllObjects]; +} + +- (void)makeImmutable +{ + object_setClass(self, [OFConcreteSet class]); +} +@end ADDED src/OFConcreteNumber.h Index: src/OFConcreteNumber.h ================================================================== --- /dev/null +++ src/OFConcreteNumber.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2008-2024 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#import "OFNumber.h" + +OF_ASSUME_NONNULL_BEGIN + +@interface OFConcreteNumber: OFNumber +{ + union { + double float_; + long long signed_; + unsigned long long unsigned_; + } _value; + char _typeEncoding; +} +@end + +OF_ASSUME_NONNULL_END ADDED src/OFConcreteNumber.m Index: src/OFConcreteNumber.m ================================================================== --- /dev/null +++ src/OFConcreteNumber.m @@ -0,0 +1,267 @@ +/* + * Copyright (c) 2008-2024 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 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 "OFConcreteNumber.h" + +#import "OFInvalidFormatException.h" + +static bool +isUnsigned(OFNumber *number) +{ + switch (*number.objCType) { + case 'B': + case 'C': + case 'S': + case 'I': + case 'L': + case 'Q': + return true; + default: + return false; + } +} + +static bool +isSigned(OFNumber *number) +{ + switch (*number.objCType) { + case 'c': + case 's': + case 'i': + case 'l': + case 'q': + return true; + default: + return false; + } +} + +static bool +isFloat(OFNumber *number) +{ + switch (*number.objCType) { + case 'f': + case 'd': + return true; + default: + return false; + } +} + +@implementation OFConcreteNumber +- (instancetype)initWithBytes: (const void *)bytes + objCType: (const char *)objCType +{ +#define CASE(type, method) \ + if (strcmp(objCType, @encode(type)) == 0) { \ + type value; \ + memcpy(&value, bytes, sizeof(type)); \ + return [self method value]; \ + } + + CASE(bool, initWithBool:) + CASE(signed char, initWithChar:) + CASE(short, initWithShort:) + CASE(int, initWithInt:) + CASE(long, initWithLong:) + CASE(long long, initWithLongLong:) + CASE(unsigned char, initWithUnsignedChar:) + CASE(unsigned short, initWithUnsignedShort:) + CASE(unsigned int, initWithUnsignedInt:) + CASE(unsigned long, initWithUnsignedLong:) + CASE(unsigned long long, initWithUnsignedLongLong:) + CASE(float, initWithFloat:) + CASE(double, initWithDouble:) + + [self release]; + @throw [OFInvalidFormatException exception]; +} + +- (instancetype)initWithBool: (bool)value +{ + self = [super initWithBytes: &value objCType: @encode(bool)]; + + _value.unsigned_ = value; + _typeEncoding = *@encode(bool); + + return self; +} + +- (instancetype)initWithChar: (signed char)value +{ + self = [super initWithBytes: &value objCType: @encode(signed char)]; + + _value.signed_ = value; + _typeEncoding = *@encode(signed char); + + return self; +} + +- (instancetype)initWithShort: (short)value +{ + self = [super initWithBytes: &value objCType: @encode(short)]; + + _value.signed_ = value; + _typeEncoding = *@encode(short); + + return self; +} + +- (instancetype)initWithInt: (int)value +{ + self = [super initWithBytes: &value objCType: @encode(int)]; + + _value.signed_ = value; + _typeEncoding = *@encode(int); + + return self; +} + +- (instancetype)initWithLong: (long)value +{ + self = [super initWithBytes: &value objCType: @encode(long)]; + + _value.signed_ = value; + _typeEncoding = *@encode(long); + + return self; +} + +- (instancetype)initWithLongLong: (long long)value +{ + self = [super initWithBytes: &value objCType: @encode(long long)]; + + _value.signed_ = value; + _typeEncoding = *@encode(long long); + + return self; +} + +- (instancetype)initWithUnsignedChar: (unsigned char)value +{ + self = [super initWithBytes: &value objCType: @encode(unsigned char)]; + + _value.unsigned_ = value; + _typeEncoding = *@encode(unsigned long); + + return self; +} + +- (instancetype)initWithUnsignedShort: (unsigned short)value +{ + self = [super initWithBytes: &value objCType: @encode(unsigned short)]; + + _value.unsigned_ = value; + _typeEncoding = *@encode(unsigned short); + + return self; +} + +- (instancetype)initWithUnsignedInt: (unsigned int)value +{ + self = [super initWithBytes: &value objCType: @encode(unsigned int)]; + + _value.unsigned_ = value; + _typeEncoding = *@encode(unsigned int); + + return self; +} + +- (instancetype)initWithUnsignedLong: (unsigned long)value +{ + self = [super initWithBytes: &value objCType: @encode(unsigned long)]; + + _value.unsigned_ = value; + _typeEncoding = *@encode(unsigned long); + + return self; +} + +- (instancetype)initWithUnsignedLongLong: (unsigned long long)value +{ + self = [super initWithBytes: &value + objCType: @encode(unsigned long long)]; + + _value.unsigned_ = value; + _typeEncoding = *@encode(unsigned long long); + + return self; +} + +- (instancetype)initWithFloat: (float)value +{ + self = [super initWithBytes: &value objCType: @encode(float)]; + + _value.float_ = value; + _typeEncoding = *@encode(float); + + return self; +} + +- (instancetype)initWithDouble: (double)value +{ + self = [super initWithBytes: &value objCType: @encode(double)]; + + _value.float_ = value; + _typeEncoding = *@encode(double); + + return self; +} + +- (const char *)objCType +{ + return &_typeEncoding; +} + +- (long long)longLongValue +{ + if (isFloat(self)) + return _value.float_; + else if (isSigned(self)) + return _value.signed_; + else if (isUnsigned(self)) + return _value.unsigned_; + else + @throw [OFInvalidFormatException exception]; +} + +- (unsigned long long)unsignedLongLongValue +{ + if (isFloat(self)) + return _value.float_; + else if (isSigned(self)) + return _value.signed_; + else if (isUnsigned(self)) + return _value.unsigned_; + else + @throw [OFInvalidFormatException exception]; +} + +- (double)doubleValue +{ + if (isFloat(self)) + return _value.float_; + else if (isSigned(self)) + return _value.signed_; + else if (isUnsigned(self)) + return _value.unsigned_; + else + @throw [OFInvalidFormatException exception]; +} +@end ADDED src/OFConcreteSet.h Index: src/OFConcreteSet.h ================================================================== --- /dev/null +++ src/OFConcreteSet.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2008-2024 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#import "OFSet.h" + +OF_ASSUME_NONNULL_BEGIN + +@class OFMapTable; + +@interface OFConcreteSet: OFSet +{ + OFMapTable *_mapTable; +} + +- (instancetype)initWithCapacity: (size_t)capacity; +@end + +OF_ASSUME_NONNULL_END ADDED src/OFConcreteSet.m Index: src/OFConcreteSet.m ================================================================== --- /dev/null +++ src/OFConcreteSet.m @@ -0,0 +1,270 @@ +/* + * Copyright (c) 2008-2024 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#include "config.h" + +#import "OFConcreteSet.h" +#import "OFArray.h" +#import "OFConcreteCountedSet.h" +#import "OFConcreteMutableSet.h" +#import "OFMapTable+Private.h" +#import "OFMapTable.h" +#import "OFString.h" + +#import "OFInvalidArgumentException.h" +#import "OFEnumerationMutationException.h" + +static void * +retain(void *object) +{ + return [(id)object retain]; +} + +static void +release(void *object) +{ + [(id)object release]; +} + +static unsigned long +hash(void *object) +{ + return [(id)object hash]; +} + +static bool +equal(void *object1, void *object2) +{ + return [(id)object1 isEqual: (id)object2]; +} + +static const OFMapTableFunctions keyFunctions = { + .retain = retain, + .release = release, + .hash = hash, + .equal = equal +}; +static const OFMapTableFunctions objectFunctions = { NULL }; + +@implementation OFConcreteSet +- (instancetype)init +{ + return [self initWithCapacity: 0]; +} + +- (instancetype)initWithCapacity: (size_t)capacity +{ + self = [super init]; + + @try { + _mapTable = [[OFMapTable alloc] + initWithKeyFunctions: keyFunctions + objectFunctions: objectFunctions + capacity: capacity]; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (instancetype)initWithSet: (OFSet *)set +{ + size_t count; + + if (set == nil) + return [self init]; + + @try { + count = set.count; + } @catch (id e) { + [self release]; + @throw e; + } + + self = [self initWithCapacity: count]; + + @try { + for (id object in set) + [_mapTable setObject: (void *)1 forKey: object]; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (instancetype)initWithArray: (OFArray *)array +{ + size_t count; + + if (array == nil) + return self; + + @try { + count = array.count; + } @catch (id e) { + [self release]; + @throw e; + } + + self = [self initWithCapacity: count]; + + @try { + for (id object in array) + [_mapTable setObject: (void *)1 forKey: object]; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (instancetype)initWithObjects: (id const *)objects count: (size_t)count +{ + self = [self initWithCapacity: count]; + + @try { + for (size_t i = 0; i < count; i++) + [_mapTable setObject: (void *)1 forKey: objects[i]]; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (instancetype)initWithObject: (id)firstObject arguments: (va_list)arguments +{ + self = [super init]; + + @try { + id object; + va_list argumentsCopy; + size_t count; + + va_copy(argumentsCopy, arguments); + + for (count = 1; va_arg(argumentsCopy, id) != nil; count++); + + _mapTable = [[OFMapTable alloc] + initWithKeyFunctions: keyFunctions + objectFunctions: objectFunctions + capacity: count]; + + [_mapTable setObject: (void *)1 forKey: firstObject]; + + while ((object = va_arg(arguments, id)) != nil) + [_mapTable setObject: (void *)1 forKey: object]; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (void)dealloc +{ + [_mapTable release]; + + [super dealloc]; +} + +- (size_t)count +{ + return [_mapTable count]; +} + +- (bool)containsObject: (id)object +{ + if (object == nil) + return false; + + return ([_mapTable objectForKey: object] != nil); +} + +- (bool)isEqual: (id)object +{ + OFConcreteSet *set; + + if (object == self) + return true; + + if (![object isKindOfClass: [OFConcreteSet class]] && + ![object isKindOfClass: [OFConcreteMutableSet class]] && + ![object isKindOfClass: [OFConcreteCountedSet class]]) + return [super isEqual: object]; + + set = object; + + return [set->_mapTable isEqual: _mapTable]; +} + +- (id)anyObject +{ + void *pool = objc_autoreleasePoolPush(); + void **objectPtr; + id object; + + objectPtr = [[_mapTable keyEnumerator] nextObject]; + + if (objectPtr == NULL) { + objc_autoreleasePoolPop(pool); + return nil; + } + + object = [(id)*objectPtr retain]; + + objc_autoreleasePoolPop(pool); + + return [object autorelease]; +} + +- (OFEnumerator *)objectEnumerator +{ + return [[[OFMapTableEnumeratorWrapper alloc] + initWithEnumerator: [_mapTable keyEnumerator] + object: self] autorelease]; +} + +- (int)countByEnumeratingWithState: (OFFastEnumerationState *)state + objects: (id *)objects + count: (int)count +{ + return [_mapTable countByEnumeratingWithState: state + objects: objects + count: count]; +} + +#ifdef OF_HAVE_BLOCKS +- (void)enumerateObjectsUsingBlock: (OFSetEnumerationBlock)block +{ + @try { + [_mapTable enumerateKeysAndObjectsUsingBlock: + ^ (void *key, void *object, bool *stop) { + block(key, stop); + }]; + } @catch (OFEnumerationMutationException *e) { + @throw [OFEnumerationMutationException + exceptionWithObject: self]; + } +} +#endif +@end ADDED src/OFConcreteSubarray.h Index: src/OFConcreteSubarray.h ================================================================== --- /dev/null +++ src/OFConcreteSubarray.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2008-2024 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#import "OFSubarray.h" + +OF_ASSUME_NONNULL_BEGIN + +@interface OFConcreteSubarray: OFSubarray +@end + +OF_ASSUME_NONNULL_END ADDED src/OFConcreteSubarray.m Index: src/OFConcreteSubarray.m ================================================================== --- /dev/null +++ src/OFConcreteSubarray.m @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2008-2024 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#include "config.h" + +#import "OFConcreteSubarray.h" +#import "OFConcreteArray.h" +#import "OFConcreteMutableArray.h" + +@implementation OFConcreteSubarray +- (const id *)objects +{ + return _array.objects + _range.location; +} + +- (bool)isEqual: (id)object +{ + OFArray *otherArray; + id const *objects, *otherObjects; + + if (object == self) + return true; + + if (![object isKindOfClass: [OFConcreteArray class]] && + ![object isKindOfClass: [OFConcreteMutableArray class]]) + return [super isEqual: object]; + + otherArray = object; + + if (_range.length != otherArray.count) + return false; + + objects = self.objects; + otherObjects = otherArray.objects; + + for (size_t i = 0; i < _range.length; i++) + if (![objects[i] isEqual: otherObjects[i]]) + return false; + + return true; +} + +#ifdef OF_HAVE_BLOCKS +- (void)enumerateObjectsUsingBlock: (OFArrayEnumerationBlock)block +{ + id const *objects = self.objects; + bool stop = false; + + for (size_t i = 0; i < _range.length && !stop; i++) + block(objects[i], i, &stop); +} +#endif +@end ADDED src/OFConcreteValue.h Index: src/OFConcreteValue.h ================================================================== --- /dev/null +++ src/OFConcreteValue.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2008-2024 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#import "OFValue.h" + +OF_ASSUME_NONNULL_BEGIN + +@interface OFConcreteValue: OFValue +{ + size_t _size; + void *_bytes; + char *_objCType; +} +@end + +OF_ASSUME_NONNULL_END ADDED src/OFConcreteValue.m Index: src/OFConcreteValue.m ================================================================== --- /dev/null +++ src/OFConcreteValue.m @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2008-2024 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#import "OFConcreteValue.h" +#import "OFMethodSignature.h" +#import "OFString.h" + +#import "OFOutOfRangeException.h" + +@implementation OFConcreteValue +- (instancetype)initWithBytes: (const void *)bytes + objCType: (const char *)objCType +{ + self = [super initWithBytes: bytes objCType: objCType]; + + @try { + _size = OFSizeOfTypeEncoding(objCType); + _objCType = OFStrDup(objCType); + _bytes = OFAllocMemory(1, _size); + memcpy(_bytes, bytes, _size); + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (void)dealloc +{ + OFFreeMemory(_bytes); + OFFreeMemory(_objCType); + + [super dealloc]; +} + +- (const char *)objCType +{ + return _objCType; +} + +- (void)getValue: (void *)value size: (size_t)size +{ + if (size != _size) + @throw [OFOutOfRangeException exception]; + + memcpy(value, _bytes, _size); +} +@end Index: src/OFCondition.h ================================================================== --- src/OFCondition.h +++ src/OFCondition.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,11 +48,11 @@ * * @throw OFWaitForConditionFailedException Waiting for the condition failed */ - (void)wait; -#ifdef OF_AMIGAOS +#if defined(OF_AMIGAOS) || defined(DOXYGEN) /** * @brief Blocks the current thread until another thread calls @ref signal, * @ref broadcast or an Exec Signal is received. * * @note This is only available on AmigaOS! @@ -75,11 +75,11 @@ * @return Whether the condition has been signaled * @throw OFWaitForConditionFailedException Waiting for the condition failed */ - (bool)waitForTimeInterval: (OFTimeInterval)timeInterval; -#ifdef OF_AMIGAOS +#if defined(OF_AMIGAOS) || defined(DOXYGEN) /** * @brief Blocks the current thread until another thread calls @ref signal, * @ref broadcast, the timeout is reached or an Exec Signal is received. * * @note This is only available on AmigaOS! @@ -105,11 +105,11 @@ * @return Whether the condition has been signaled * @throw OFWaitForConditionFailedException Waiting for the condition failed */ - (bool)waitUntilDate: (OFDate *)date; -#ifdef OF_AMIGAOS +#if defined(OF_AMIGAOS) || defined(DOXYGEN) /** * @brief Blocks the current thread until another thread calls @ref signal, * @ref broadcast, the timeout is reached or an Exec Signal is received. * * @note This is only available on AmigaOS! Index: src/OFCondition.m ================================================================== --- src/OFCondition.m +++ src/OFCondition.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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 @@ #include #import "OFCondition.h" #import "OFDate.h" +#import "OFString.h" #import "OFBroadcastConditionFailedException.h" #import "OFConditionStillWaitingException.h" #import "OFInitializationFailedException.h" #import "OFSignalConditionFailedException.h" Index: src/OFConstantString.h ================================================================== --- src/OFConstantString.h +++ src/OFConstantString.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,14 +11,11 @@ * Public License, either version 2 or 3, which can be found in the file * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this * file. */ -#ifndef OBJFW_OF_CONSTANT_STRING_H -#define OBJFW_OF_CONSTANT_STRING_H - -#include "OFString.h" +#import "OFString.h" OF_ASSUME_NONNULL_BEGIN #if !defined(OF_CONSTANT_STRING_M) && \ defined(OF_APPLE_RUNTIME) && !defined(__OBJC2__) @@ -29,11 +26,10 @@ # ifdef __cplusplus } # endif #endif -#ifdef __OBJC__ /** * @class OFConstantString OFConstantString.h ObjFW/OFConstantString.h * * @brief A class for storing constant strings using the `@""` literal. */ @@ -42,10 +38,7 @@ { char *_cString; unsigned int _cStringLength; } @end -#endif OF_ASSUME_NONNULL_END - -#endif Index: src/OFConstantString.m ================================================================== --- src/OFConstantString.m +++ src/OFConstantString.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,33 +50,11 @@ + (instancetype)alloc { OF_UNRECOGNIZED_SELECTOR } -- (instancetype)retain -{ - return self; -} - -- (instancetype)autorelease -{ - return self; -} - -- (unsigned int)retainCount -{ - return OFMaxRetainCount; -} - -- (void)release -{ -} - -- (void)dealloc -{ - OF_DEALLOC_UNSUPPORTED -} +OF_SINGLETON_METHODS @end @implementation OFConstantString + (void)load { @@ -133,33 +111,11 @@ + (instancetype)alloc { OF_UNRECOGNIZED_SELECTOR } -- (instancetype)retain -{ - return self; -} - -- (instancetype)autorelease -{ - return self; -} - -- (unsigned int)retainCount -{ - return OFMaxRetainCount; -} - -- (void)release -{ -} - -- (void)dealloc -{ - OF_DEALLOC_UNSUPPORTED -} +OF_SINGLETON_METHODS /* * In all following methods, the constant string is converted to an * OFConstantUTF8String and the message sent again. */ @@ -547,24 +503,10 @@ { [self finishInitialization]; return [self dataWithEncoding: encoding]; } -#ifdef OF_HAVE_UNICODE_TABLES -- (OFString *)decomposedStringWithCanonicalMapping -{ - [self finishInitialization]; - return self.decomposedStringWithCanonicalMapping; -} - -- (OFString *)decomposedStringWithCompatibilityMapping -{ - [self finishInitialization]; - return self.decomposedStringWithCompatibilityMapping; -} -#endif - #ifdef OF_WINDOWS - (OFString *)stringByExpandingWindowsEnvironmentStrings { [self finishInitialization]; return self.stringByExpandingWindowsEnvironmentStrings; @@ -583,20 +525,20 @@ [self finishInitialization]; [self writeToFile: path encoding: encoding]; } #endif -- (void)writeToURI: (OFURI *)URI +- (void)writeToIRI: (OFIRI *)IRI { [self finishInitialization]; - [self writeToURI: URI]; + [self writeToIRI: IRI]; } -- (void)writeToURI: (OFURI *)URI encoding: (OFStringEncoding)encoding +- (void)writeToIRI: (OFIRI *)IRI encoding: (OFStringEncoding)encoding { [self finishInitialization]; - [self writeToURI: URI encoding: encoding]; + [self writeToIRI: IRI encoding: encoding]; } #ifdef OF_HAVE_BLOCKS - (void)enumerateLinesUsingBlock: (OFStringLineEnumerationBlock)block { DELETED src/OFCountedMapTableSet.h Index: src/OFCountedMapTableSet.h ================================================================== --- src/OFCountedMapTableSet.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (c) 2008-2022 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#import "OFCountedSet.h" - -OF_ASSUME_NONNULL_BEGIN - -@class OFMapTable; - -@interface OFCountedMapTableSet: OFCountedSet -{ - OFMapTable *_mapTable; -} -@end - -OF_ASSUME_NONNULL_END DELETED src/OFCountedMapTableSet.m Index: src/OFCountedMapTableSet.m ================================================================== --- src/OFCountedMapTableSet.m +++ /dev/null @@ -1,219 +0,0 @@ -/* - * Copyright (c) 2008-2022 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#include "config.h" - -#import "OFCountedMapTableSet.h" -#import "OFArray.h" -#import "OFMapTable.h" -#import "OFMutableMapTableSet.h" -#import "OFString.h" -#import "OFXMLAttribute.h" -#import "OFXMLElement.h" - -#import "OFInvalidArgumentException.h" -#import "OFInvalidFormatException.h" -#import "OFEnumerationMutationException.h" -#import "OFOutOfRangeException.h" - -@implementation OFCountedMapTableSet -+ (void)initialize -{ - if (self == [OFCountedMapTableSet class]) - [self inheritMethodsFromClass: [OFMutableMapTableSet class]]; -} - -- (instancetype)initWithSet: (OFSet *)set -{ - self = [self init]; - - @try { - void *pool = objc_autoreleasePoolPush(); - - if ([set isKindOfClass: [OFCountedSet class]]) { - OFCountedSet *countedSet = (OFCountedSet *)set; - - for (id object in countedSet) { - size_t count = - [countedSet countForObject: object]; - - for (size_t i = 0; i < count; i++) - [self addObject: object]; - } - } else - for (id object in set) - [self addObject: object]; - - objc_autoreleasePoolPop(pool); - } @catch (id e) { - [self release]; - @throw e; - } - - return self; -} - -- (instancetype)initWithArray: (OFArray *)array -{ - self = [self init]; - - @try { - id const *objects = array.objects; - size_t count = array.count; - - for (size_t i = 0; i < count; i++) - [self addObject: objects[i]]; - } @catch (id e) { - [self release]; - @throw e; - } - - return self; -} - -- (instancetype)initWithObjects: (id const *)objects count: (size_t)count -{ - self = [self init]; - - @try { - for (size_t i = 0; i < count; i++) - [self addObject: objects[i]]; - } @catch (id e) { - [self release]; - @throw e; - } - - return self; -} - -- (instancetype)initWithObject: (id)firstObject arguments: (va_list)arguments -{ - self = [self init]; - - @try { - id object; - - [self addObject: firstObject]; - - while ((object = va_arg(arguments, id)) != nil) - [self addObject: object]; - } @catch (id e) { - [self release]; - @throw e; - } - - return self; -} - -- (instancetype)initWithSerialization: (OFXMLElement *)element -{ - self = [self init]; - - @try { - void *pool = objc_autoreleasePoolPush(); - - if (![element.name isEqual: @"OFCountedSet"] || - ![element.namespace isEqual: OFSerializationNS]) - @throw [OFInvalidArgumentException exception]; - - for (OFXMLElement *objectElement in - [element elementsForName: @"object" - namespace: OFSerializationNS]) { - void *pool2 = objc_autoreleasePoolPush(); - OFXMLElement *object; - OFXMLAttribute *countAttribute; - unsigned long long count; - - object = [objectElement elementsForNamespace: - OFSerializationNS].firstObject; - countAttribute = - [objectElement attributeForName: @"count"]; - - if (object == nil || countAttribute == nil) - @throw [OFInvalidFormatException exception]; - - count = countAttribute.unsignedLongLongValue; - if (count > SIZE_MAX || count > UINTPTR_MAX) - @throw [OFOutOfRangeException exception]; - - [_mapTable setObject: (void *)(uintptr_t)count - forKey: object.objectByDeserializing]; - - objc_autoreleasePoolPop(pool2); - } - - objc_autoreleasePoolPop(pool); - } @catch (id e) { - [self release]; - @throw e; - } - - return self; -} - -- (size_t)countForObject: (id)object -{ - return (size_t)(uintptr_t)[_mapTable objectForKey: object]; -} - -#ifdef OF_HAVE_BLOCKS -- (void)enumerateObjectsAndCountUsingBlock: (OFCountedSetEnumerationBlock)block -{ - @try { - [_mapTable enumerateKeysAndObjectsUsingBlock: - ^ (void *key, void *object, bool *stop) { - block(key, (size_t)(uintptr_t)object, stop); - }]; - } @catch (OFEnumerationMutationException *e) { - @throw [OFEnumerationMutationException - exceptionWithObject: self]; - } -} -#endif - -- (void)addObject: (id)object -{ - size_t count = (size_t)(uintptr_t)[_mapTable objectForKey: object]; - - if (SIZE_MAX - count < 1 || UINTPTR_MAX - count < 1) - @throw [OFOutOfRangeException exception]; - - [_mapTable setObject: (void *)(uintptr_t)(count + 1) forKey: object]; -} - -- (void)removeObject: (id)object -{ - size_t count = (size_t)(uintptr_t)[_mapTable objectForKey: object]; - - if (count == 0) - return; - - count--; - - if (count > 0) - [_mapTable setObject: (void *)(uintptr_t)count forKey: object]; - else - [_mapTable removeObjectForKey: object]; -} - -- (void)removeAllObjects -{ - [_mapTable removeAllObjects]; -} - -- (void)makeImmutable -{ -} -@end Index: src/OFCountedSet.h ================================================================== --- src/OFCountedSet.h +++ src/OFCountedSet.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,94 +16,80 @@ #include "config.h" #include #import "OFCountedSet.h" -#import "OFCountedMapTableSet.h" +#import "OFConcreteCountedSet.h" #import "OFNumber.h" #import "OFString.h" -#import "OFXMLElement.h" static struct { Class isa; } placeholder; -@interface OFCountedSetPlaceholder: OFCountedSet +@interface OFPlaceholderCountedSet: OFCountedSet @end -@implementation OFCountedSetPlaceholder +@implementation OFPlaceholderCountedSet +#ifdef __clang__ +/* We intentionally don't call into super, so silence the warning. */ +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wunknown-pragmas" +# pragma clang diagnostic ignored "-Wobjc-designated-initializers" +#endif - (instancetype)init { - return (id)[[OFCountedMapTableSet alloc] init]; + return (id)[[OFConcreteCountedSet alloc] init]; } - (instancetype)initWithSet: (OFSet *)set { - return (id)[[OFCountedMapTableSet alloc] initWithSet: set]; + return (id)[[OFConcreteCountedSet alloc] initWithSet: set]; } - (instancetype)initWithArray: (OFArray *)array { - return (id)[[OFCountedMapTableSet alloc] initWithArray: array]; + return (id)[[OFConcreteCountedSet alloc] initWithArray: array]; } - (instancetype)initWithObjects: (id)firstObject, ... { id ret; va_list arguments; va_start(arguments, firstObject); - ret = [[OFCountedMapTableSet alloc] initWithObject: firstObject + ret = [[OFConcreteCountedSet alloc] initWithObject: firstObject arguments: arguments]; va_end(arguments); return ret; } - (instancetype)initWithObjects: (id const *)objects count: (size_t)count { - return (id)[[OFCountedMapTableSet alloc] initWithObjects: objects + return (id)[[OFConcreteCountedSet alloc] initWithObjects: objects count: count]; } - (instancetype)initWithObject: (id)firstObject arguments: (va_list)arguments { - return (id)[[OFCountedMapTableSet alloc] initWithObject: firstObject + return (id)[[OFConcreteCountedSet alloc] initWithObject: firstObject arguments: arguments]; } - -- (instancetype)initWithSerialization: (OFXMLElement *)element -{ - return (id)[[OFCountedMapTableSet alloc] - initWithSerialization: element]; -} - -- (instancetype)retain -{ - return self; -} - -- (instancetype)autorelease -{ - return self; -} - -- (void)release -{ -} - -- (void)dealloc -{ - OF_DEALLOC_UNSUPPORTED -} +#ifdef __clang__ +# pragma clang diagnostic pop +#endif + +OF_SINGLETON_METHODS @end @implementation OFCountedSet + (void)initialize { if (self == [OFCountedSet class]) - placeholder.isa = [OFCountedSetPlaceholder class]; + object_setClass((id)&placeholder, + [OFPlaceholderCountedSet class]); } + (instancetype)alloc { if (self == [OFCountedSet class]) @@ -110,26 +96,10 @@ return (id)&placeholder; return [super alloc]; } -- (instancetype)init -{ - if ([self isMemberOfClass: [OFCountedSet class]]) { - @try { - [self doesNotRecognizeSelector: _cmd]; - } @catch (id e) { - [self release]; - @throw e; - } - - abort(); - } - - return [super init]; -} - - (size_t)countForObject: (id)object { OF_UNRECOGNIZED_SELECTOR } @@ -175,46 +145,10 @@ - (id)mutableCopy { return [[OFCountedSet alloc] initWithSet: self]; } -- (OFXMLElement *)XMLElementBySerializing -{ - void *pool = objc_autoreleasePoolPush(); - OFXMLElement *element; - - element = [OFXMLElement elementWithName: @"OFCountedSet" - namespace: OFSerializationNS]; - - for (id object in self) { - void *pool2 = objc_autoreleasePoolPush(); - - OFXMLElement *objectElement; - OFString *count; - - count = - [OFString stringWithFormat: @"%zu", - [self countForObject: object]]; - - objectElement = [OFXMLElement - elementWithName: @"object" - namespace: OFSerializationNS]; - [objectElement addAttributeWithName: @"count" - stringValue: count]; - [objectElement addChild: object.XMLElementBySerializing]; - [element addChild: objectElement]; - - objc_autoreleasePoolPop(pool2); - } - - [element retain]; - - objc_autoreleasePoolPop(pool); - - return [element autorelease]; -} - #ifdef OF_HAVE_BLOCKS - (void)enumerateObjectsAndCountUsingBlock: (OFCountedSetEnumerationBlock)block { [self enumerateObjectsUsingBlock: ^ (id object, bool *stop) { block(object, [self countForObject: object], stop); Index: src/OFCryptographicHash.h ================================================================== --- src/OFCryptographicHash.h +++ src/OFCryptographicHash.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFDDPSocket.h ================================================================== --- src/OFDDPSocket.h +++ src/OFDDPSocket.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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 @@ #import "OFDatagramSocket.h" OF_ASSUME_NONNULL_BEGIN @class OFString; +@class OFDictionary OF_GENERIC(KeyType, ObjectType); /** * @protocol OFDDPSocketDelegate OFDDPSocket.h ObjFW/OFDDPSocket.h * * @brief A delegate for OFDDPSocket. @@ -41,11 +42,11 @@ * socket number). * * @note On some systems, packets received with the wrong protocol type just * get filtered by the kernel, however, on other systems, the packet is * queued up and will raise an @ref OFReadFailedException with the - * @ref errNo set to `ENOMSG` when being received. + * @ref OFReadFailedException#errNo set to `ENOMSG` when being received. * * @warning Even though the OFCopying protocol is implemented, it does *not* * return an independent copy of the socket, but instead retains it. * This is so that the socket can be used as a key for a dictionary, * so context can be associated with a socket. Using a socket in more @@ -79,14 +80,14 @@ * @param protocolType The DDP protocol type to use. Must not be 0. If you want * to use DDP directly and not a protocol built on top of * it, use 11 for compatibility with Open Transport. * @return The address on which this socket can be reached * @throw OFBindDDPSockeFailedException Binding failed - * @throw OFAlreadyConnectedException The socket is already bound + * @throw OFAlreadyOpenException The socket is already bound */ - (OFSocketAddress)bindToNetwork: (uint16_t)network node: (uint8_t)node port: (uint8_t)port protocolType: (uint8_t)protocolType; @end OF_ASSUME_NONNULL_END Index: src/OFDDPSocket.m ================================================================== --- src/OFDDPSocket.m +++ src/OFDDPSocket.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,19 +20,32 @@ #ifdef HAVE_FCNTL_H # include #endif #import "OFDDPSocket.h" +#import "OFDictionary.h" +#import "OFNumber.h" +#import "OFPair.h" #import "OFSocket.h" #import "OFSocket+Private.h" -#import "OFAlreadyConnectedException.h" +#import "OFAlreadyOpenException.h" #import "OFBindDDPSocketFailedException.h" +#import "OFGetOptionFailedException.h" #import "OFInvalidArgumentException.h" #import "OFNotOpenException.h" +#import "OFOutOfRangeException.h" #import "OFReadFailedException.h" +#import "OFSetOptionFailedException.h" #import "OFWriteFailedException.h" + +#ifdef HAVE_NET_IF_H +# include +#endif +#ifdef HAVE_SYS_IOCTL_H +# include +#endif #ifdef OF_HAVE_NETAT_APPLETALK_H # include # include @@ -65,11 +78,11 @@ if (protocolType == 0) @throw [OFInvalidArgumentException exception]; if (_socket != OFInvalidSocketHandle) - @throw [OFAlreadyConnectedException exceptionWithSocket: self]; + @throw [OFAlreadyOpenException exceptionWithObject: self]; address = OFSocketAddressMakeAppleTalk(network, node, port); #if defined(OF_MACOS) if ((_socket = socket(address.sockaddr.at.sat_family, Index: src/OFDNSQuery.h ================================================================== --- src/OFDNSQuery.h +++ src/OFDNSQuery.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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 @@ void *pool = objc_autoreleasePoolPush(); if (![domainName hasSuffix: @"."]) domainName = [domainName stringByAppendingString: @"."]; - _domainName = [domainName copy]; + _domainName = [domainName.lowercaseString copy]; _DNSClass = DNSClass; _recordType = recordType; objc_autoreleasePoolPop(pool); } @catch (id e) { Index: src/OFDNSResolver.h ================================================================== --- src/OFDNSResolver.h +++ src/OFDNSResolver.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,12 +28,14 @@ @class OFDNSResolver; @class OFDNSResolverContext; @class OFDNSResolverSettings; @class OFDate; @class OFDictionary OF_GENERIC(KeyType, ObjectType); +@class OFMutableArray OF_GENERIC(ObjectType); @class OFMutableDictionary OF_GENERIC(KeyType, ObjectType); @class OFNumber; +@class OFPair OF_GENERIC(FirstType, SecondType); @class OFTCPSocket; @class OFUDPSocket; /** * @enum OFDNSResolverErrorCode OFDNSResolver.h ObjFW/OFDNSResolver.h @@ -132,24 +134,36 @@ char _buffer[OFDNSResolverBufferLength]; OFMutableDictionary OF_GENERIC(OFNumber *, OFDNSResolverContext *) *_queries; OFMutableDictionary OF_GENERIC(OFTCPSocket *, OFDNSResolverContext *) *_TCPQueries; + OFMutableDictionary OF_GENERIC(OFDNSQuery *, + OFPair OF_GENERIC(OFDate *, OFDNSResponse *) *) *_cache; + OFMutableArray OF_GENERIC(OFString *) *_lastNameServers; + OFTimeInterval _lastCacheCleanup; } /** * @brief A dictionary of static hosts. * * This dictionary is checked before actually looking up a host. + * + * @warning If you change this, you need to set @ref configReloadInterval to 0 + * to disable reloading the config after some time. If you don't, the + * config will be reloaded and your change overridden. */ @property (copy, nonatomic) OFDictionary OF_GENERIC(OFString *, OFArray OF_GENERIC(OFString *) *) *staticHosts; /** * @brief An array of name servers to use. * * The name servers are tried in order. + * + * @warning If you change this, you need to set @ref configReloadInterval to 0 + * to disable reloading the config after some time. If you don't, the + * config will be reloaded and your change overridden. */ @property (copy, nonatomic) OFArray OF_GENERIC(OFString *) *nameServers; /** * @brief The local domain. @@ -156,40 +170,64 @@ */ @property OF_NULLABLE_PROPERTY (readonly, nonatomic) OFString *localDomain; /** * @brief The domains to search for queries for short names. + * + * @warning If you change this, you need to set @ref configReloadInterval to 0 + * to disable reloading the config after some time. If you don't, the + * config will be reloaded and your change overridden. */ @property (copy, nonatomic) OFArray OF_GENERIC(OFString *) *searchDomains; /** * @brief The timeout, in seconds, after which the next name server should be * tried. + * + * @warning If you change this, you need to set @ref configReloadInterval to 0 + * to disable reloading the config after some time. If you don't, the + * config will be reloaded and your change overridden. */ @property (nonatomic) OFTimeInterval timeout; /** * @brief The number of attempts before giving up to resolve a host. * * Trying all name servers once is considered a single attempt. + * + * @warning If you change this, you need to set @ref configReloadInterval to 0 + * to disable reloading the config after some time. If you don't, the + * config will be reloaded and your change overridden. */ @property (nonatomic) unsigned int maxAttempts; /** * @brief The minimum number of dots for a name to be considered absolute. + * + * @warning If you change this, you need to set @ref configReloadInterval to 0 + * to disable reloading the config after some time. If you don't, the + * config will be reloaded and your change overridden. */ @property (nonatomic) unsigned int minNumberOfDotsInAbsoluteName; /** - * @brief Whether the resolver uses TCP to talk to a name server. + * @brief Whether the resolver forces TCP to talk to a name server. + * + * @warning If you change this, you need to set @ref configReloadInterval to 0 + * to disable reloading the config after some time. If you don't, the + * config will be reloaded and your change overridden. */ -@property (nonatomic) bool usesTCP; +@property (nonatomic) bool forcesTCP; /** * @brief The interval in seconds in which the config should be reloaded. * * Setting this to 0 disables config reloading. + * + * @warning If you change this to anything other than 0, the config will be + * reloaded eventually, which in turn can override the config + * reloading interval itself again. */ @property (nonatomic) OFTimeInterval configReloadInterval; /** * @brief Creates a new, autoreleased OFDNSResolver. Index: src/OFDNSResolver.m ================================================================== --- src/OFDNSResolver.m +++ src/OFDNSResolver.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -421,11 +421,11 @@ OFEnumerator OF_GENERIC(OFMutableArray *) *objectEnumerator; OFMutableArray *array; for (uint_fast16_t j = 0; j < count; j++) { OFString *name = parseName(buffer, length, i, - maxAllowedPointers); + maxAllowedPointers).lowercaseString; OFDNSClass DNSClass; OFDNSRecordType recordType; uint32_t TTL; uint16_t dataLength; OFDNSResourceRecord *record; @@ -464,10 +464,24 @@ [ret makeImmutable]; return ret; } + +static bool +containsExpiredRecord(OFDNSResponseRecords responseRecords, uint32_t age) +{ + OFEnumerator *enumerator = [responseRecords objectEnumerator]; + OFArray OF_GENERIC(OFDNSResourceRecord *) *records; + + while ((records = [enumerator nextObject]) != nil) + for (OFDNSResourceRecord *record in records) + if (record.TTL < age) + return true; + + return false; +} @implementation OFDNSResolverContext - (instancetype)initWithQuery: (OFDNSQuery *)query ID: (OFNumber *)ID settings: (OFDNSResolverSettings *)settings @@ -576,10 +590,11 @@ @try { _settings = [[OFDNSResolverSettings alloc] init]; _queries = [[OFMutableDictionary alloc] init]; _TCPQueries = [[OFMutableDictionary alloc] init]; + _cache = [[OFMutableDictionary alloc] init]; [_settings reload]; } @catch (id e) { [self release]; @throw e; @@ -599,10 +614,12 @@ [_IPv6Socket cancelAsyncRequests]; [_IPv6Socket release]; #endif [_queries release]; [_TCPQueries release]; + [_cache release]; + [_lastNameServers release]; [super dealloc]; } - (OFDictionary *)staticHosts @@ -676,18 +693,18 @@ { _settings->_minNumberOfDotsInAbsoluteName = minNumberOfDotsInAbsoluteName; } -- (bool)usesTCP -{ - return _settings->_usesTCP; -} - -- (void)setUsesTCP: (bool)usesTCP -{ - _settings->_usesTCP = usesTCP; +- (bool)forcesTCP +{ + return _settings->_forcesTCP; +} + +- (void)setForcesTCP: (bool)forcesTCP +{ + _settings->_forcesTCP = forcesTCP; } - (OFTimeInterval)configReloadInterval { return _settings->_configReloadInterval; @@ -721,11 +738,11 @@ forMode: runLoopMode]; nameServer = [context->_settings->_nameServers objectAtIndex: context->_nameServersIndex]; - if (context->_settings->_usesTCP) { + if (context->_settings->_forcesTCP) { OFEnsure(context->_TCPSocket == nil); context->_TCPSocket = [[OFTCPSocket alloc] init]; [_TCPQueries setObject: context forKey: context->_TCPSocket]; @@ -786,10 +803,49 @@ runLoopMode: runLoopMode]; [sock asyncReceiveIntoBuffer: _buffer length: bufferLength runLoopMode: runLoopMode]; } + +- (void)of_cleanUpCache +{ + OFTimeInterval now = [[OFDate date] timeIntervalSince1970]; + OFMutableArray *removeList; + + if (_lastNameServers != _settings->_nameServers && + ![_lastNameServers isEqual: _settings->_nameServers]) { + OFArray *old = _lastNameServers; + _lastNameServers = [_settings->_nameServers copy]; + [old release]; + + [_cache removeAllObjects]; + + return; + } + + if (now - _lastCacheCleanup < 1) + return; + + _lastCacheCleanup = now; + removeList = [OFMutableArray arrayWithCapacity: _cache.count]; + + for (OFDNSQuery *query in _cache) { + OFPair OF_GENERIC(OFDate *, OFDNSResponse *) *entry = + [_cache objectForKey: query]; + uint32_t age = + (uint32_t)now - [entry.firstObject timeIntervalSince1970]; + OFDNSResponse *response = entry.secondObject; + + if (containsExpiredRecord(response.answerRecords, age) || + containsExpiredRecord(response.authorityRecords, age) || + containsExpiredRecord(response.additionalRecords, age)) + [removeList addObject: query]; + } + + for (OFDNSQuery *query in removeList) + [_cache removeObjectForKey: query]; +} - (void)asyncPerformQuery: (OFDNSQuery *)query delegate: (id )delegate { [self asyncPerformQuery: query @@ -802,10 +858,40 @@ delegate: (id )delegate { void *pool = objc_autoreleasePoolPush(); OFNumber *ID; OFDNSResolverContext *context; + OFPair OF_GENERIC(OFDate *, OFDNSResponse *) *cacheEntry; + + [self of_cleanUpCache]; + + if ((cacheEntry = [_cache objectForKey: query]) != nil) { + uint32_t age = + (uint32_t)-[cacheEntry.firstObject timeIntervalSinceNow]; + OFDNSResponse *response = cacheEntry.secondObject; + + if (!containsExpiredRecord(response.answerRecords, age) && + !containsExpiredRecord(response.authorityRecords, age) && + !containsExpiredRecord(response.additionalRecords, age)) { + OFTimer *timer = [OFTimer + timerWithTimeInterval: 0 + target: delegate + selector: @selector(resolver: + didPerformQuery:response: + exception:) + object: self + object: query + object: response + object: nil + repeats: false]; + [[OFRunLoop currentRunLoop] addTimer: timer + forMode: runLoopMode]; + + objc_autoreleasePoolPop(pool); + return; + } + } /* Random, unused ID */ do { ID = [OFNumber numberWithUnsignedShort: OFRandom16()]; } while ([_queries objectForKey: ID] != nil); @@ -946,14 +1032,14 @@ /* TC */ if (buffer[2] & 0x02) { OFRunLoopMode runLoopMode; - if (context->_settings->_usesTCP) + if (context->_settings->_forcesTCP) @throw [OFTruncatedDataException exception]; - context->_settings->_usesTCP = true; + context->_settings->_forcesTCP = true; runLoopMode = [OFRunLoop currentRunLoop].currentMode; [self of_sendQueryForContext: context runLoopMode: runLoopMode]; return false; } @@ -1038,10 +1124,19 @@ } if (exception != nil) response = nil; + [self of_cleanUpCache]; + + if (response != nil) + [_cache setObject: [OFPair pairWithFirstObject: [OFDate date] + secondObject: response] + forKey: context->_query]; + else + [_cache removeObjectForKey: context->_query]; + [context->_delegate resolver: self didPerformQuery: context->_query response: response exception: exception]; Index: src/OFDNSResolverSettings.h ================================================================== --- src/OFDNSResolverSettings.h +++ src/OFDNSResolverSettings.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,15 +29,15 @@ OFArray OF_GENERIC(OFString *) *_nameServers; OFString *_Nullable _localDomain; OFArray OF_GENERIC(OFString *) *_searchDomains; OFTimeInterval _timeout; unsigned int _maxAttempts, _minNumberOfDotsInAbsoluteName; - bool _usesTCP; + bool _forcesTCP; OFTimeInterval _configReloadInterval; @protected OFDate *_lastConfigReload; } - (void)reload; @end OF_ASSUME_NONNULL_END Index: src/OFDNSResolverSettings.m ================================================================== --- src/OFDNSResolverSettings.m +++ src/OFDNSResolverSettings.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,22 +20,29 @@ #import "OFDNSResolverSettings.h" #import "OFArray.h" #import "OFCharacterSet.h" #import "OFDate.h" #import "OFDictionary.h" -#import "OFFile.h" +#ifdef OF_HAVE_FILES +# import "OFFile.h" +# import "OFFileManager.h" +#endif #import "OFLocale.h" #import "OFSocket+Private.h" #import "OFString.h" #ifdef OF_WINDOWS # import "OFWindowsRegistryKey.h" #endif #import "OFInvalidFormatException.h" #import "OFOpenItemFailedException.h" +#ifdef OF_WINDOWS +# import "OFOpenWindowsRegistryKeyFailedException.h" +#endif #import "OFOutOfMemoryException.h" #import "OFOutOfRangeException.h" +#import "OFUndefinedKeyException.h" #ifdef OF_WINDOWS # define interface struct # include # undef interface @@ -46,24 +53,24 @@ # define id id_3ds # include <3ds.h> # undef id #endif +#if defined(OF_AMIGAOS_M68K) || defined(OF_AMIGAOS4) +# define Class IntuitionClass +# include +# undef Class +#endif #ifdef OF_MORPHOS # include # include # include #endif #if defined(OF_HAIKU) # define HOSTS_PATH @"/system/settings/network/hosts" # define RESOLV_CONF_PATH @"/system/settings/network/resolv.conf" -#elif defined(OF_AMIGAOS4) -# define HOSTS_PATH @"DEVS:Internet/hosts" -#elif defined(OF_AMIGAOS) -# define HOSTS_PATH @"AmiTCP:db/hosts" -# define RESOLV_CONF_PATH @"AmiTCP:db/resolv.conf" #else # define HOSTS_PATH @"/etc/hosts" # define RESOLV_CONF_PATH @"/etc/resolv.conf" #endif @@ -113,10 +120,21 @@ return [OFString stringWithCString: hostname encoding: [OFLocale encoding]]; } #endif + +#ifdef OF_AMIGAOS_M68K +static bool +assignExists(const char *assign) +{ + struct DosList *list = LockDosList(LDF_ASSIGNS | LDF_READ); + bool found = (FindDosEntry(list, assign, LDF_ASSIGNS) != NULL); + UnLockDosList(LDF_ASSIGNS | LDF_READ); + return found; +} +#endif #ifdef OF_MORPHOS static OFString * arexxCommand(const char *port, const char *command) { @@ -211,11 +229,11 @@ copy->_searchDomains = [_searchDomains copy]; copy->_timeout = _timeout; copy->_maxAttempts = _maxAttempts; copy->_minNumberOfDotsInAbsoluteName = _minNumberOfDotsInAbsoluteName; - copy->_usesTCP = _usesTCP; + copy->_forcesTCP = _forcesTCP; copy->_configReloadInterval = _configReloadInterval; copy->_lastConfigReload = [_lastConfigReload copy]; } @catch (id e) { [copy release]; @throw e; @@ -239,11 +257,11 @@ _searchDomains = nil; _timeout = 2; _maxAttempts = 3; _minNumberOfDotsInAbsoluteName = 1; - _usesTCP = false; + _forcesTCP = false; #ifndef OF_NINTENDO_3DS _configReloadInterval = 2; #else _configReloadInterval = 0; #endif @@ -253,10 +271,12 @@ - (void)parseHosts: (OFString *)path { void *pool = objc_autoreleasePoolPush(); OFCharacterSet *whitespaceCharacterSet = [OFCharacterSet whitespaceCharacterSet]; + OFCharacterSet *commentCharacters = + [OFCharacterSet characterSetWithCharactersInString: @"#;"]; OFMutableDictionary *staticHosts; OFFile *file; OFString *line; @try { @@ -272,11 +292,11 @@ [file readLineWithEncoding: [OFLocale encoding]]) != nil) { OFArray *components, *hosts; size_t pos; OFString *address; - pos = [line rangeOfString: @"#"].location; + pos = [line indexOfCharacterFromSet: commentCharacters]; if (pos != OFNotFound) line = [line substringToIndex: pos]; components = [line componentsSeparatedByCharactersInSet: whitespaceCharacterSet @@ -288,12 +308,14 @@ address = components.firstObject; hosts = [components objectsInRange: OFMakeRange(1, components.count - 1)]; for (OFString *host in hosts) { - OFMutableArray *addresses = - [staticHosts objectForKey: host]; + OFMutableArray *addresses; + + host = host.lowercaseString; + addresses = [staticHosts objectForKey: host]; if (addresses == nil) { addresses = [OFMutableArray array]; [staticHosts setObject: addresses forKey: host]; } @@ -308,11 +330,11 @@ _staticHosts = [staticHosts copy]; objc_autoreleasePoolPop(pool); } -# if !defined(OF_WINDOWS) && !defined(OF_AMIGAOS4) +# ifndef OF_WINDOWS - (void)parseResolvConfOption: (OFString *)option { @try { if ([option hasPrefix: @"ndots:"]) { unsigned long long number; @@ -341,11 +363,11 @@ } else if ([option hasPrefix: @"reload-period:"]) { option = [option substringFromIndex: 14]; _configReloadInterval = option.unsignedLongLongValue; } else if ([option isEqual: @"tcp"]) - _usesTCP = true; + _forcesTCP = true; } @catch (OFInvalidFormatException *e) { } } - (void)parseResolvConf: (OFString *)path @@ -387,11 +409,11 @@ if (components.count < 2) { objc_autoreleasePoolPop(pool2); continue; } - option = components.firstObject; + option = [components.firstObject lowercaseString]; arguments = [components objectsInRange: OFMakeRange(1, components.count - 1)]; if ([option isEqual: @"nameserver"]) { if (arguments.count != 1) { @@ -445,14 +467,19 @@ if (GetNetworkParams(fixedInfo, &length) != ERROR_SUCCESS) return; nameServers = [OFMutableArray array]; - for (iter = &fixedInfo->DnsServerList; iter != NULL; iter = iter->Next) - [nameServers addObject: + for (iter = &fixedInfo->DnsServerList; iter != NULL; + iter = iter->Next) { + OFString *nameServer = [OFString stringWithCString: iter->IpAddress.String - encoding: encoding]]; + encoding: encoding]; + + if (nameServer.length > 0) + [nameServers addObject: nameServer]; + } if (nameServers.count > 0) { [nameServers makeImmutable]; _nameServers = [nameServers copy]; } @@ -491,12 +518,14 @@ address = components.firstObject; hosts = [components objectsInRange: OFMakeRange(1, components.count - 1)]; for (OFString *host in hosts) { - OFMutableArray *addresses = - [staticHosts objectForKey: host]; + OFMutableArray *addresses; + + host = host.lowercaseString; + addresses = [staticHosts objectForKey: host]; if (addresses == nil) { addresses = [OFMutableArray array]; [staticHosts setObject: addresses forKey: host]; } @@ -512,17 +541,26 @@ objc_autoreleasePoolPop(pool); } #endif -#ifdef OF_AMIGAOS4 -- (void)obtainAmigaOS4SystemConfig +#if defined(OF_AMIGAOS_M68K) || defined(OF_AMIGAOS4) +- (bool)obtainRoadshowSystemConfig { - OFMutableArray *nameServers = [OFMutableArray array]; - OFStringEncoding encoding = [OFLocale encoding]; - struct List *nameServerList = ObtainDomainNameServerList(); + OFMutableArray *nameServers; + OFStringEncoding encoding; + struct List *nameServerList; char buffer[MAXHOSTNAMELEN]; + LONG hasDNSAPI; + + if (SocketBaseTags(SBTM_GETREF(SBTC_HAVE_DNS_API), (ULONG)&hasDNSAPI, + TAG_END) != 0 || !hasDNSAPI) + return false; + + nameServers = [OFMutableArray array]; + encoding = [OFLocale encoding]; + nameServerList = ObtainDomainNameServerList(); if (nameServerList == NULL) @throw [OFOutOfMemoryException exception]; @try { @@ -552,10 +590,12 @@ } if (GetDefaultDomainName(buffer, sizeof(buffer))) _localDomain = [[OFString alloc] initWithCString: buffer encoding: encoding]; + + return true; } #endif #ifdef OF_NINTENDO_3DS - (void)obtainNintendo3DSSytemConfig @@ -600,14 +640,17 @@ } #endif - (void)reload { - void *pool; #ifdef OF_WINDOWS - OFString *path; + OFString *path = nil; +#endif +#if (defined(OF_AMIGAOS_M68K) || defined(OF_AMIGAOS4)) && defined(OF_HAVE_FILES) + OFFileManager *fileManager = [OFFileManager defaultManager]; #endif + void *pool; /* * TODO: Rather than reparsing every time, check what actually changed * (mtime) and only reset those. */ @@ -620,29 +663,53 @@ [self setDefaults]; #if defined(OF_WINDOWS) # ifdef OF_HAVE_FILES - OFWindowsRegistryKey *key = [[OFWindowsRegistryKey localMachineKey] - openSubkeyAtPath: @"SYSTEM\\CurrentControlSet\\Services\\" - @"Tcpip\\Parameters" - accessRights: KEY_QUERY_VALUE - options: 0]; - path = [[[key stringForValueNamed: @"DataBasePath"] - stringByAppendingPathComponent: @"hosts"] - stringByExpandingWindowsEnvironmentStrings]; + @try { + OFWindowsRegistryKey *key; + + key = [[OFWindowsRegistryKey localMachineKey] + openSubkeyAtPath: @"SYSTEM\\CurrentControlSet\\Services\\" + @"Tcpip\\Parameters" + accessRights: KEY_QUERY_VALUE + options: 0]; + path = [[[key stringForValueNamed: @"DataBasePath"] + stringByAppendingPathComponent: @"hosts"] + stringByExpandingWindowsEnvironmentStrings]; + } @catch (OFOpenWindowsRegistryKeyFailedException *e) { + /* Ignore */ + } @catch (OFUndefinedKeyException *e) { + /* Ignore */ + } if (path != nil) [self parseHosts: path]; # endif [self obtainWindowsSystemConfig]; #elif defined(OF_MORPHOS) [self obtainMorphOSSystemConfig]; -#elif defined(OF_AMIGAOS4) - [self parseHosts: HOSTS_PATH]; - [self obtainAmigaOS4SystemConfig]; +#elif defined(OF_AMIGAOS_M68K) || defined(OF_AMIGAOS4) +# ifdef OF_HAVE_FILES + if (![self obtainRoadshowSystemConfig]) { + if (assignExists("AmiTCP")) + /* + * FIXME: The installer puts it there, but theoretically + * it could also be in AmiTCP:db/netdb or any of + * the files included there. + */ + [self parseResolvConf: @"AmiTCP:db/netdb-myhost"]; + } + + if ([fileManager fileExistsAtPath: @"DEVS:Internet/hosts"]) + [self parseHosts: @"DEVS:Internet/hosts"]; + else if (assignExists("AmiTCP")) + [self parseHosts: @"AmiTCP:db/hosts"]; +# else + [self obtainRoadshowSystemConfig]; +# endif #elif defined(OF_NINTENDO_3DS) [self obtainNintendo3DSSytemConfig]; #elif defined(OF_HAVE_FILES) [self parseHosts: HOSTS_PATH]; [self parseResolvConf: RESOLV_CONF_PATH]; Index: src/OFDNSResourceRecord.h ================================================================== --- src/OFDNSResourceRecord.h +++ src/OFDNSResourceRecord.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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+ASN1DERParsing.h ================================================================== --- src/OFData+ASN1DERParsing.h +++ src/OFData+ASN1DERParsing.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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+ASN1DERParsing.m ================================================================== --- src/OFData+ASN1DERParsing.m +++ src/OFData+ASN1DERParsing.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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.h ================================================================== --- src/OFData+CryptographicHashing.h +++ src/OFData+CryptographicHashing.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,12 @@ [class hashWithAllowsSwappableMemory: true]; size_t digestSize = [class digestSize]; const unsigned char *digest; char cString[digestSize * 2]; - [hash updateWithBuffer: self->_items - length: self->_count * self->_itemSize]; + [hash 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,19 +12,18 @@ * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this * file. */ #import "OFObject.h" -#import "OFSerialization.h" #import "OFMessagePackRepresentation.h" /*! @file */ OF_ASSUME_NONNULL_BEGIN +@class OFIRI; @class OFString; -@class OFURI; /** * @brief Options for searching in data. * * This is a bit mask. @@ -36,25 +35,13 @@ /** * @class OFData OFData.h ObjFW/OFData.h * * @brief A class for storing arbitrary data in an array. - * - * For security reasons, serialization and deserialization is only implemented - * for OFData with item size 1. */ @interface OFData: OFObject -{ - unsigned char *_Nullable _items; - size_t _count, _itemSize; - bool _freeWhenDone; -@private - OFData *_Nullable _parentData; - OF_RESERVE_IVARS(OFData, 4) -} - + OFMessagePackRepresentation> /** * @brief The size of a single item in the OFData in bytes. */ @property (readonly, nonatomic) size_t itemSize; @@ -94,10 +81,25 @@ /** * @brief A string containing the data in Base64 encoding. */ @property (readonly, nonatomic) OFString *stringByBase64Encoding; +/** + * @brief Creates a new OFData that is empty with an item size of 1. + * + * @return A new autoreleased OFData + */ ++ (instancetype)data; + +/** + * @brief Creates a new OFData that is empty with the specified item size. + * + * @param itemSize The size of a single element in the OFData + * @return A new autoreleased OFData + */ ++ (instancetype)dataWithItemSize: (size_t)itemSize; + /** * @brief Creates a new OFData with the specified `count` items of size 1. * * @param items The items to store in the OFData * @param count The number of items @@ -165,16 +167,16 @@ + (instancetype)dataWithContentsOfFile: (OFString *)path; #endif /** * @brief Creates a new OFData with an item size of 1, containing the data of - * the specified URI. + * the specified IRI. * - * @param URI The URI to the contents for the OFData + * @param IRI The IRI to the contents for the OFData * @return A new autoreleased OFData */ -+ (instancetype)dataWithContentsOfURI: (OFURI *)URI; ++ (instancetype)dataWithContentsOfIRI: (OFIRI *)IRI; /** * @brief Creates a new OFData with an item size of 1, containing the data of * the hex string representation. * @@ -194,10 +196,27 @@ * @throw OFInvalidFormatException The specified string is not correctly * formatted */ + (instancetype)dataWithBase64EncodedString: (OFString *)string; +/** + * @brief Initializes an already allocated OFData to be empty with an item size + * of 1. + * + * @return An initialized OFData + */ +- (instancetype)init; + +/** + * @brief Initializes an already allocated OFData to be empty with the + * specified item size. + * + * @param itemSize The size of a single element in the OFData + * @return An initialized OFData + */ +- (instancetype)initWithItemSize: (size_t)itemSize; + /** * @brief Initializes an already allocated OFData with the specified `count` * items of size 1. * * @param items The items to store in the OFData @@ -268,16 +287,16 @@ - (instancetype)initWithContentsOfFile: (OFString *)path; #endif /** * @brief Initializes an already allocated OFData with an item size of 1, - * containing the data of the specified URI. + * containing the data of the specified IRI. * - * @param URI The URI to the contents for the OFData + * @param IRI The IRI to the contents for the OFData * @return A new autoreleased OFData */ -- (instancetype)initWithContentsOfURI: (OFURI *)URI; +- (instancetype)initWithContentsOfIRI: (OFIRI *)IRI; /** * @brief Initializes an already allocated OFData with an item size of 1, * containing the data of the hex string representation. * @@ -344,18 +363,18 @@ */ - (void)writeToFile: (OFString *)path; #endif /** - * @brief Writes the OFData to the specified URI. + * @brief Writes the OFData to the specified IRI. * - * @param URI The URI to write to + * @param IRI The IRI to write to */ -- (void)writeToURI: (OFURI *)URI; +- (void)writeToIRI: (OFIRI *)IRI; @end OF_ASSUME_NONNULL_END #import "OFMutableData.h" #import "OFData+ASN1DERParsing.h" #import "OFData+CryptographicHashing.h" #import "OFData+MessagePackParsing.h" Index: src/OFData.m ================================================================== --- src/OFData.m +++ src/OFData.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,41 +19,142 @@ #include #include #import "OFData.h" #import "OFBase64.h" +#import "OFConcreteData.h" #import "OFDictionary.h" #ifdef OF_HAVE_FILES # import "OFFile.h" # import "OFFileManager.h" #endif +#import "OFIRI.h" +#import "OFIRIHandler.h" #import "OFStream.h" #import "OFString.h" +#import "OFSubdata.h" #import "OFSystemInfo.h" -#import "OFURI.h" -#import "OFURIHandler.h" -#import "OFXMLElement.h" #import "OFInvalidArgumentException.h" #import "OFInvalidFormatException.h" #import "OFNotImplementedException.h" #import "OFOutOfMemoryException.h" #import "OFOutOfRangeException.h" #import "OFTruncatedDataException.h" #import "OFUnsupportedProtocolException.h" + +static struct { + Class isa; +} placeholder; + +@interface OFPlaceholderData: OFString +@end /* References for static linking */ void _references_to_categories_of_OFData(void) { _OFData_ASN1DERParsing_reference = 1; _OFData_CryptographicHashing_reference = 1; _OFData_MessagePackParsing_reference = 1; } + +@implementation OFPlaceholderData +- (instancetype)init +{ + return (id)[[OFConcreteData alloc] init]; +} + +- (instancetype)initWithItemSize: (size_t)itemSize +{ + return (id)[[OFConcreteData alloc] initWithItemSize: itemSize]; +} + +- (instancetype)initWithItems: (const void *)items count: (size_t)count +{ + return (id)[[OFConcreteData alloc] initWithItems: items count: count]; +} + +- (instancetype)initWithItems: (const void *)items + count: (size_t)count + itemSize: (size_t)itemSize +{ + return (id)[[OFConcreteData alloc] initWithItems: items + count: count + itemSize: itemSize]; +} + +- (instancetype)initWithItemsNoCopy: (void *)items + count: (size_t)count + freeWhenDone: (bool)freeWhenDone +{ + return (id)[[OFConcreteData alloc] initWithItemsNoCopy: items + count: count + freeWhenDone: freeWhenDone]; +} + +- (instancetype)initWithItemsNoCopy: (void *)items + count: (size_t)count + itemSize: (size_t)itemSize + freeWhenDone: (bool)freeWhenDone +{ + return (id)[[OFConcreteData alloc] initWithItemsNoCopy: items + count: count + itemSize: itemSize + freeWhenDone: freeWhenDone]; +} + +#ifdef OF_HAVE_FILES +- (instancetype)initWithContentsOfFile: (OFString *)path +{ + return (id)[[OFConcreteData alloc] initWithContentsOfFile: path]; +} +#endif + +- (instancetype)initWithContentsOfIRI: (OFIRI *)IRI +{ + return (id)[[OFConcreteData alloc] initWithContentsOfIRI: IRI]; +} + +- (instancetype)initWithStringRepresentation: (OFString *)string +{ + return (id)[[OFConcreteData alloc] + initWithStringRepresentation: string]; +} + +- (instancetype)initWithBase64EncodedString: (OFString *)string +{ + return (id)[[OFConcreteData alloc] initWithBase64EncodedString: string]; +} + +OF_SINGLETON_METHODS +@end @implementation OFData -@synthesize itemSize = _itemSize; ++ (void)initialize +{ + if (self == [OFData class]) + object_setClass((id)&placeholder, [OFPlaceholderData class]); +} + ++ (instancetype)alloc +{ + if (self == [OFData class]) + return (id)&placeholder; + + return [super alloc]; +} + ++ (instancetype)data +{ + return [[[self alloc] init] autorelease]; +} + ++ (instancetype)dataWithItemSize: (size_t)itemSize +{ + return [[[self alloc] initWithItemSize: itemSize] autorelease]; +} + (instancetype)dataWithItems: (const void *)items count: (size_t)count { return [[[self alloc] initWithItems: items count: count] autorelease]; } @@ -92,13 +193,13 @@ { return [[[self alloc] initWithContentsOfFile: path] autorelease]; } #endif -+ (instancetype)dataWithContentsOfURI: (OFURI *)URI ++ (instancetype)dataWithContentsOfIRI: (OFIRI *)IRI { - return [[[self alloc] initWithContentsOfURI: URI] autorelease]; + return [[[self alloc] initWithContentsOfIRI: IRI] autorelease]; } + (instancetype)dataWithStringRepresentation: (OFString *)string { return [[[self alloc] @@ -107,10 +208,32 @@ + (instancetype)dataWithBase64EncodedString: (OFString *)string { return [[[self alloc] initWithBase64EncodedString: string] autorelease]; } + +- (instancetype)init +{ + if ([self isMemberOfClass: [OFData class]] || + [self isMemberOfClass: [OFMutableData class]]) { + @try { + [self doesNotRecognizeSelector: _cmd]; + } @catch (id e) { + [self release]; + @throw e; + } + + abort(); + } + + return [super init]; +} + +- (instancetype)initWithItemSize: (size_t)itemSize +{ + OF_INVALID_INIT_METHOD +} - (instancetype)initWithItems: (const void *)items count: (size_t)count { return [self initWithItems: items count: count itemSize: 1]; } @@ -117,28 +240,11 @@ - (instancetype)initWithItems: (const void *)items count: (size_t)count itemSize: (size_t)itemSize { - self = [super init]; - - @try { - if (itemSize == 0) - @throw [OFInvalidArgumentException exception]; - - _items = OFAllocMemory(count, itemSize); - _count = count; - _itemSize = itemSize; - _freeWhenDone = true; - - memcpy(_items, items, count * itemSize); - } @catch (id e) { - [self release]; - @throw e; - } - - return self; + OF_INVALID_INIT_METHOD } - (instancetype)initWithItemsNoCopy: (void *)items count: (size_t)count freeWhenDone: (bool)freeWhenDone @@ -152,131 +258,97 @@ - (instancetype)initWithItemsNoCopy: (void *)items count: (size_t)count itemSize: (size_t)itemSize freeWhenDone: (bool)freeWhenDone { - self = [super init]; - - @try { - if (itemSize == 0) - @throw [OFInvalidArgumentException exception]; - - _items = (unsigned char *)items; - _count = count; - _itemSize = itemSize; - _freeWhenDone = freeWhenDone; - } @catch (id e) { - [self release]; - @throw e; - } - - return self; + OF_INVALID_INIT_METHOD } #ifdef OF_HAVE_FILES - (instancetype)initWithContentsOfFile: (OFString *)path { - char *buffer = NULL; - OFStreamOffset fileSize; - - @try { - void *pool = objc_autoreleasePoolPush(); - OFFile *file = [OFFile fileWithPath: path mode: @"r"]; - fileSize = [file seekToOffset: 0 whence: OFSeekEnd]; - - if (fileSize < 0 || (unsigned long long)fileSize > SIZE_MAX) - @throw [OFOutOfRangeException exception]; - - [file seekToOffset: 0 whence: OFSeekSet]; - - buffer = OFAllocMemory((size_t)fileSize, 1); - [file readIntoBuffer: buffer exactLength: (size_t)fileSize]; - - objc_autoreleasePoolPop(pool); - } @catch (id e) { - OFFreeMemory(buffer); - [self release]; - - @throw e; - } - - @try { - self = [self initWithItemsNoCopy: buffer - count: (size_t)fileSize - freeWhenDone: true]; - } @catch (id e) { - OFFreeMemory(buffer); - @throw e; - } + void *pool = objc_autoreleasePoolPush(); + OFIRI *IRI; + + @try { + IRI = [OFIRI fileIRIWithPath: path]; + } @catch (id e) { + [self release]; + @throw e; + } + + self = [self initWithContentsOfIRI: IRI]; + + objc_autoreleasePoolPop(pool); return self; } #endif -- (instancetype)initWithContentsOfURI: (OFURI *)URI +- (instancetype)initWithContentsOfIRI: (OFIRI *)IRI { - self = [super init]; + char *items = NULL, *buffer = NULL; + size_t count = 0; @try { void *pool = objc_autoreleasePoolPush(); - OFStream *stream = [OFURIHandler openItemAtURI: URI mode: @"r"]; + OFStream *stream = [OFIRIHandler openItemAtIRI: IRI mode: @"r"]; size_t pageSize; - unsigned char *buffer; - - _count = 0; - _itemSize = 1; - _freeWhenDone = true; pageSize = [OFSystemInfo pageSize]; buffer = OFAllocMemory(1, pageSize); - @try { - while (!stream.atEndOfStream) { - size_t length = [stream - readIntoBuffer: buffer - length: pageSize]; - - if (SIZE_MAX - _count < length) - @throw [OFOutOfRangeException - exception]; - - _items = OFResizeMemory(_items, - _count + length, 1); - memcpy(_items + _count, buffer, length); - _count += length; - } - } @finally { - OFFreeMemory(buffer); + while (!stream.atEndOfStream) { + size_t length = [stream readIntoBuffer: buffer + length: pageSize]; + + if (SIZE_MAX - count < length) + @throw [OFOutOfRangeException exception]; + + items = OFResizeMemory(items, count + length, 1); + memcpy(items + count, buffer, length); + count += length; } objc_autoreleasePoolPop(pool); } @catch (id e) { + OFFreeMemory(items); [self release]; + + @throw e; + } @finally { + OFFreeMemory(buffer); + } + + @try { + self = [self initWithItemsNoCopy: items + count: count + freeWhenDone: true]; + } @catch (id e) { + OFFreeMemory(items); @throw e; } return self; } - (instancetype)initWithStringRepresentation: (OFString *)string { - self = [super init]; + char *items = NULL; + size_t count = 0; @try { - size_t count = [string - cStringLengthWithEncoding: OFStringEncodingASCII]; const char *cString; + count = [string + cStringLengthWithEncoding: OFStringEncodingASCII]; + if (count % 2 != 0) @throw [OFInvalidFormatException exception]; count /= 2; - - _items = OFAllocMemory(count, 1); - _count = count; - _itemSize = 1; - _freeWhenDone = true; + items = OFAllocMemory(count, 1); cString = [string cStringWithEncoding: OFStringEncodingASCII]; for (size_t i = 0; i < count; i++) { uint8_t c1 = cString[2 * i]; @@ -299,165 +371,180 @@ else if (c2 >= 'A' && c2 <= 'F') byte |= c2 - 'A' + 10; else @throw [OFInvalidFormatException exception]; - _items[i] = byte; + items[i] = byte; } } @catch (id e) { + OFFreeMemory(items); [self release]; + + @throw e; + } + + @try { + self = [self initWithItemsNoCopy: items + count: count + freeWhenDone: true]; + } @catch (id e) { + OFFreeMemory(items); @throw e; } return self; } - (instancetype)initWithBase64EncodedString: (OFString *)string { - bool mutable = [self isKindOfClass: [OFMutableData class]]; - - if (!mutable) { - [self release]; - self = [OFMutableData alloc]; - } - - self = [(OFMutableData *)self initWithCapacity: string.length / 3]; + void *pool = objc_autoreleasePoolPush(); + OFMutableData *data; @try { - if (!OFBase64Decode((OFMutableData *)self, + data = [OFMutableData data]; + + if (!OFBase64Decode(data, [string cStringWithEncoding: OFStringEncodingASCII], [string cStringLengthWithEncoding: OFStringEncodingASCII])) @throw [OFInvalidFormatException exception]; } @catch (id e) { [self release]; @throw e; } - if (!mutable) - [(OFMutableData *)self makeImmutable]; - - return self; -} - -- (instancetype)initWithSerialization: (OFXMLElement *)element -{ - void *pool = objc_autoreleasePoolPush(); - OFString *stringValue; - + /* Avoid copying if the class already matches. */ + if (data.class == self.class) { + [self release]; + self = [data retain]; + objc_autoreleasePoolPop(pool); + return self; + } + + /* + * Make it immutable and avoid copying if the class already matches + * after that. + */ @try { - if (![element.name isEqual: self.className] || - ![element.namespace isEqual: OFSerializationNS]) - @throw [OFInvalidArgumentException exception]; - - stringValue = element.stringValue; + [data makeImmutable]; } @catch (id e) { [self release]; @throw e; } - self = [self initWithBase64EncodedString: stringValue]; + if (data.class == self.class) { + [self release]; + self = [data retain]; + objc_autoreleasePoolPop(pool); + return self; + } + + self = [self initWithItems: data.items count: data.count]; objc_autoreleasePoolPop(pool); return self; } -- (void)dealloc -{ - if (_freeWhenDone) - OFFreeMemory(_items); - - [_parentData release]; - - [super dealloc]; -} - - (size_t)count { - return _count; + OF_UNRECOGNIZED_SELECTOR +} + +- (size_t)itemSize +{ + OF_UNRECOGNIZED_SELECTOR } - (const void *)items { - return _items; + OF_UNRECOGNIZED_SELECTOR } - (const void *)itemAtIndex: (size_t)idx { - if (idx >= _count) + if (idx >= self.count) @throw [OFOutOfRangeException exception]; - return _items + idx * _itemSize; + return (const unsigned char *)self.items + idx * self.itemSize; } - (const void *)firstItem { - if (_items == NULL || _count == 0) + const void *items = self.items; + + if (items == NULL || self.count == 0) return NULL; - return _items; + return items; } - (const void *)lastItem { - if (_items == NULL || _count == 0) + const unsigned char *items = self.items; + size_t count = self.count; + + if (items == NULL || count == 0) return NULL; - return _items + (_count - 1) * _itemSize; + return items + (count - 1) * self.itemSize; } - (id)copy { return [self retain]; } - (id)mutableCopy { - return [[OFMutableData alloc] initWithItems: _items - count: _count - itemSize: _itemSize]; + return [[OFMutableData alloc] initWithItems: self.items + count: self.count + itemSize: self.itemSize]; } - (bool)isEqual: (id)object { + size_t count, itemSize; OFData *data; if (object == self) return true; if (![object isKindOfClass: [OFData class]]) return false; + count = self.count; + itemSize = self.itemSize; data = object; - if (data.count != _count || data.itemSize != _itemSize) + if (data.count != count || data.itemSize != itemSize) return false; - if (memcmp(data.items, _items, _count * _itemSize) != 0) + if (memcmp(data.items, self.items, count * itemSize) != 0) return false; return true; } - (OFComparisonResult)compare: (OFData *)data { int comparison; - size_t count, minCount; + size_t count, dataCount, minCount; if (![data isKindOfClass: [OFData class]]) @throw [OFInvalidArgumentException exception]; - if (data.itemSize != _itemSize) + if (data.itemSize != self.itemSize) @throw [OFInvalidArgumentException exception]; - count = data.count; - minCount = (_count > count ? count : _count); + count = self.count; + dataCount = data.count; + minCount = (count > dataCount ? dataCount : count); - if ((comparison = memcmp(_items, data.items, - minCount * _itemSize)) == 0) { - if (_count > count) + if ((comparison = memcmp(self.items, data.items, + minCount * self.itemSize)) == 0) { + if (count > dataCount) return OFOrderedDescending; - if (_count < count) + if (count < dataCount) return OFOrderedAscending; return OFOrderedSame; } @@ -467,49 +554,52 @@ return OFOrderedAscending; } - (unsigned long)hash { + const unsigned char *items = self.items; + size_t count = self.count, itemSize = self.itemSize; unsigned long hash; OFHashInit(&hash); - for (size_t i = 0; i < _count * _itemSize; i++) - OFHashAddByte(&hash, ((uint8_t *)_items)[i]); + for (size_t i = 0; i < count * itemSize; i++) + OFHashAddByte(&hash, items[i]); OFHashFinalize(&hash); return hash; } - (OFData *)subdataWithRange: (OFRange)range { - OFData *ret; - if (range.length > SIZE_MAX - range.location || - range.location + range.length > _count) + range.location + range.length > self.count) @throw [OFOutOfRangeException exception]; - ret = [OFData dataWithItemsNoCopy: _items + (range.location * _itemSize) - count: range.length - itemSize: _itemSize - freeWhenDone: false]; - ret->_parentData = [(_parentData != nil ? _parentData : self) copy]; + if (![self isKindOfClass: [OFMutableData class]]) + return [[[OFSubdata alloc] initWithData: self + range: range] autorelease]; - return ret; + return [OFData dataWithItems: (const unsigned char *)self.items + + (range.location * self.itemSize) + count: self.count + itemSize: self.itemSize]; } - (OFString *)description { OFMutableString *ret = [OFMutableString stringWithString: @"<"]; + const unsigned char *items = self.items; + size_t count = self.count, itemSize = self.itemSize; - for (size_t i = 0; i < _count; i++) { + for (size_t i = 0; i < count; i++) { if (i > 0) [ret appendString: @" "]; - for (size_t j = 0; j < _itemSize; j++) - [ret appendFormat: @"%02x", _items[i * _itemSize + j]]; + for (size_t j = 0; j < itemSize; j++) + [ret appendFormat: @"%02x", items[i * itemSize + j]]; } [ret appendString: @">"]; [ret makeImmutable]; @@ -517,36 +607,40 @@ } - (OFString *)stringRepresentation { OFMutableString *ret = [OFMutableString string]; + const unsigned char *items = self.items; + size_t count = self.count, itemSize = self.itemSize; - for (size_t i = 0; i < _count; i++) - for (size_t j = 0; j < _itemSize; j++) - [ret appendFormat: @"%02x", _items[i * _itemSize + j]]; + for (size_t i = 0; i < count; i++) + for (size_t j = 0; j < itemSize; j++) + [ret appendFormat: @"%02x", items[i * itemSize + j]]; [ret makeImmutable]; return ret; } - (OFString *)stringByBase64Encoding { - return OFBase64Encode(_items, _count * _itemSize); + return OFBase64Encode(self.items, self.count * self.itemSize); } - (OFRange)rangeOfData: (OFData *)data options: (OFDataSearchOptions)options range: (OFRange)range { + const unsigned char *items = self.items; + size_t count = self.count, itemSize = self.itemSize; const char *search; size_t searchLength; if (range.length > SIZE_MAX - range.location || - range.location + range.length > _count) + range.location + range.length > count) @throw [OFOutOfRangeException exception]; - if (data == nil || data.itemSize != _itemSize) + if (data == nil || data.itemSize != itemSize) @throw [OFInvalidArgumentException exception]; if ((searchLength = data.count) == 0) return OFMakeRange(0, 0); @@ -555,23 +649,23 @@ search = data.items; if (options & OFDataSearchBackwards) { for (size_t i = range.length - searchLength;; i--) { - if (memcmp(_items + i * _itemSize, search, - searchLength * _itemSize) == 0) + if (memcmp(items + i * itemSize, search, + searchLength * itemSize) == 0) return OFMakeRange(i, searchLength); /* No match and we're at the last item */ if (i == 0) break; } } else { for (size_t i = range.location; i <= range.length - searchLength; i++) - if (memcmp(_items + i * _itemSize, search, - searchLength * _itemSize) == 0) + if (memcmp(items + i * itemSize, search, + searchLength * itemSize) == 0) return OFMakeRange(i, searchLength); } return OFMakeRange(OFNotFound, 0); } @@ -579,81 +673,63 @@ #ifdef OF_HAVE_FILES - (void)writeToFile: (OFString *)path { OFFile *file = [[OFFile alloc] initWithPath: path mode: @"w"]; @try { - [file writeBuffer: _items length: _count * _itemSize]; + [file writeBuffer: self.items + length: self.count * self.itemSize]; } @finally { [file release]; } } #endif -- (void)writeToURI: (OFURI *)URI +- (void)writeToIRI: (OFIRI *)IRI { void *pool = objc_autoreleasePoolPush(); - [[OFURIHandler openItemAtURI: URI mode: @"w"] writeData: self]; - - objc_autoreleasePoolPop(pool); -} - -- (OFXMLElement *)XMLElementBySerializing -{ - void *pool; - OFXMLElement *element; - - if (_itemSize != 1) - @throw [OFNotImplementedException exceptionWithSelector: _cmd - object: self]; - - pool = objc_autoreleasePoolPush(); - element = [OFXMLElement - elementWithName: self.className - namespace: OFSerializationNS - stringValue: OFBase64Encode(_items, _count * _itemSize)]; - - [element retain]; - - objc_autoreleasePoolPop(pool); - - return [element autorelease]; + [[OFIRIHandler openItemAtIRI: IRI mode: @"w"] writeData: self]; + + objc_autoreleasePoolPop(pool); } - (OFData *)messagePackRepresentation { OFMutableData *data; + size_t count; - if (_itemSize != 1) + if (self.itemSize != 1) @throw [OFNotImplementedException exceptionWithSelector: _cmd object: self]; - if (_count <= UINT8_MAX) { + count = self.count; + + if (count <= UINT8_MAX) { uint8_t type = 0xC4; - uint8_t tmp = (uint8_t)_count; + uint8_t tmp = (uint8_t)count; - data = [OFMutableData dataWithCapacity: _count + 2]; + data = [OFMutableData dataWithCapacity: count + 2]; [data addItem: &type]; [data addItem: &tmp]; - } else if (_count <= UINT16_MAX) { + } else if (count <= UINT16_MAX) { uint8_t type = 0xC5; - uint16_t tmp = OFToBigEndian16((uint16_t)_count); + uint16_t tmp = OFToBigEndian16((uint16_t)count); - data = [OFMutableData dataWithCapacity: _count + 3]; + data = [OFMutableData dataWithCapacity: count + 3]; [data addItem: &type]; [data addItems: &tmp count: sizeof(tmp)]; - } else if (_count <= UINT32_MAX) { + } else if (count <= UINT32_MAX) { uint8_t type = 0xC6; - uint32_t tmp = OFToBigEndian32((uint32_t)_count); + uint32_t tmp = OFToBigEndian32((uint32_t)count); - data = [OFMutableData dataWithCapacity: _count + 5]; + data = [OFMutableData dataWithCapacity: count + 5]; [data addItem: &type]; [data addItems: &tmp count: sizeof(tmp)]; } else @throw [OFOutOfRangeException exception]; - [data addItems: _items count: _count]; + [data addItems: self.items count: count]; [data makeImmutable]; return data; } @end Index: src/OFDatagramSocket.h ================================================================== --- src/OFDatagramSocket.h +++ src/OFDatagramSocket.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -103,10 +103,14 @@ */ @interface OFDatagramSocket: OFObject { OFSocketHandle _socket; +#ifdef OF_AMIGAOS + LONG _socketID; + int _family; /* unused, reserved for ABI stability */ +#endif bool _canBlock; #ifdef OF_WII bool _canSendToBroadcastAddresses; #endif id _Nullable _delegate; @@ -116,17 +120,19 @@ /** * @brief Whether the socket can block. * * By default, a socket can block. * + * @throw OFGetOptionFailedException The option could not be retrieved * @throw OFSetOptionFailedException The option could not be set */ @property (nonatomic) bool canBlock; /** * @brief Whether the socket can send to broadcast addresses. * + * @throw OFGetOptionFailedException The option could not be retrieved * @throw OFSetOptionFailedException The option could not be set */ @property (nonatomic) bool canSendToBroadcastAddresses; /** @@ -295,10 +301,34 @@ receiver: (const OFSocketAddress *)receiver runLoopMode: (OFRunLoopMode)runLoopMode block: (OFDatagramSocketAsyncSendDataBlock)block; #endif +/** + * @brief Releases the socket from the current thread. + * + * This is necessary on some platforms in order to allow a different thread to + * use the socket, e.g. on AmigaOS, but you should call it on all operating + * systems before using the socket from a different thread. + * + * After calling this method, you must no longer use the socket until + * @ref obtainSocketForCurrentThread has been called. + */ +- (void)releaseSocketFromCurrentThread; + +/** + * @brief Obtains the socket for the current thread. + * + * This is necessary on some platforms in order to allow a different thread to + * use the socket, e.g. on AmigaOS, but you should call it on all operating + * systems before using the socket from a different thread. + * + * You must only call this method after @ref releaseSocketFromCurrentThread has + * been called from a different thread. + */ +- (void)obtainSocketForCurrentThread; + /** * @brief Cancels all pending asynchronous requests on the socket. */ - (void)cancelAsyncRequests; Index: src/OFDatagramSocket.m ================================================================== --- src/OFDatagramSocket.m +++ src/OFDatagramSocket.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,18 +31,24 @@ #import "OFRunLoop.h" #import "OFRunLoop+Private.h" #import "OFSocket.h" #import "OFSocket+Private.h" +#import "OFAlreadyOpenException.h" #import "OFGetOptionFailedException.h" #import "OFInitializationFailedException.h" #import "OFNotOpenException.h" +#import "OFOutOfMemoryException.h" #import "OFOutOfRangeException.h" #import "OFReadFailedException.h" #import "OFSetOptionFailedException.h" #import "OFSetOptionFailedException.h" #import "OFWriteFailedException.h" + +#if defined(OF_AMIGAOS) && !defined(UNIQUE_ID) +# define UNIQUE_ID -1 +#endif @implementation OFDatagramSocket @synthesize delegate = _delegate; + (void)initialize @@ -69,10 +75,13 @@ [self doesNotRecognizeSelector: _cmd]; abort(); } _socket = OFInvalidSocketHandle; +#ifdef OF_HAVE_AMIGAOS + _socketID = -1; +#endif _canBlock = true; } @catch (id e) { [self release]; @throw e; } @@ -196,38 +205,43 @@ requestedLength: length errNo: OFSocketErrNo()]; #endif if (sender != NULL) { - switch (((struct sockaddr *)&sender->sockaddr)->sa_family) { - case AF_INET: - sender->family = OFSocketAddressFamilyIPv4; - break; + struct sockaddr *sa = (struct sockaddr *)&sender->sockaddr; + + if (sender->length >= (socklen_t)sizeof(sa->sa_family)) { + switch (sa->sa_family) { + case AF_INET: + sender->family = OFSocketAddressFamilyIPv4; + break; #ifdef OF_HAVE_IPV6 - case AF_INET6: - sender->family = OFSocketAddressFamilyIPv6; - break; + case AF_INET6: + sender->family = OFSocketAddressFamilyIPv6; + break; #endif #ifdef OF_HAVE_UNIX_SOCKETS - case AF_UNIX: - sender->family = OFSocketAddressFamilyUNIX; - break; + case AF_UNIX: + sender->family = OFSocketAddressFamilyUNIX; + break; #endif #ifdef OF_HAVE_IPX - case AF_IPX: - sender->family = OFSocketAddressFamilyIPX; - break; + case AF_IPX: + sender->family = OFSocketAddressFamilyIPX; + break; #endif #ifdef OF_HAVE_APPLETALK - case AF_APPLETALK: - sender->family = OFSocketAddressFamilyAppleTalk; - break; + case AF_APPLETALK: + sender->family = OFSocketAddressFamilyAppleTalk; + break; #endif - default: + default: + sender->family = OFSocketAddressFamilyUnknown; + break; + } + } else sender->family = OFSocketAddressFamilyUnknown; - break; - } } return ret; } @@ -399,10 +413,55 @@ @throw [OFOutOfRangeException exception]; return (int)_socket; #endif } + +- (void)releaseSocketFromCurrentThread +{ +#ifdef OF_AMIGAOS + if (_socket == OFInvalidSocketHandle) + @throw [OFNotOpenException exceptionWithObject: self]; + + if ((_socketID = ReleaseSocket(_socket, UNIQUE_ID)) == -1) { + switch (Errno()) { + case ENOMEM: + @throw [OFOutOfMemoryException + exceptionWithRequestedSize: 0]; + case EBADF: + @throw [OFNotOpenException exceptionWithObject: self]; + default: + OFEnsure(0); + } + } + + _socket = OFInvalidSocketHandle; +#endif +} + +- (void)obtainSocketForCurrentThread +{ +#ifdef OF_AMIGAOS + if (_socket != OFInvalidSocketHandle) + @throw [OFAlreadyOpenException exceptionWithObject: self]; + + if (_socketID == -1) + @throw [OFNotOpenException exceptionWithObject: self]; + + /* + * FIXME: We should store these, but that requires changing all + * subclasses. This only becomes a problem if IPv6 support ever + * gets added. + */ + _socket = ObtainSocket(_socketID, AF_INET, SOCK_DGRAM, 0); + if (_socket == OFInvalidSocketHandle) + @throw [OFInitializationFailedException + exceptionWithClass: self.class]; + + _socketID = -1; +#endif +} - (void)close { if (_socket == OFInvalidSocketHandle) @throw [OFNotOpenException exceptionWithObject: self]; Index: src/OFDate.h ================================================================== --- src/OFDate.h +++ src/OFDate.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,11 +13,10 @@ * file. */ #import "OFObject.h" #import "OFMessagePackRepresentation.h" -#import "OFSerialization.h" OF_ASSUME_NONNULL_BEGIN @class OFString; @class OFConstantString; @@ -25,19 +24,12 @@ /** * @class OFDate OFDate.h ObjFW/OFDate.h * * @brief A class for storing, accessing and comparing dates. */ -#ifndef OF_DATE_M -OF_SUBCLASSING_RESTRICTED -#endif -@interface OFDate: OFObject -{ - OFTimeInterval _seconds; -} - #ifdef OF_HAVE_CLASS_PROPERTIES @property (class, readonly, nonatomic) OFDate *distantFuture; @property (class, readonly, nonatomic) OFDate *distantPast; #endif @@ -281,10 +273,14 @@ /** * @brief Creates a string of the date with the specified format. * * See the man page for `strftime` for information on the format. + * + * @warning The format is currently limited to the following format specifiers: + * %%a, %%b, %%d, %%e, %%H, %%m, %%M, %%S, %%y, %%Y, %%z, %%, %%n and + * %%t. * * @param format The format for the date string * @return A new, autoreleased OFString * @throw OFInvalidFormatException The specified format is invalid */ @@ -292,10 +288,14 @@ /** * @brief Creates a string of the local date with the specified format. * * See the man page for `strftime` for information on the format. + * + * @warning The format is currently limited to the following format specifiers: + * %%a, %%b, %%d, %%e, %%H, %%m, %%M, %%S, %%y, %%Y, %%z, %%, %%n and + * %%t. * * @param format The format for the date string * @return A new, autoreleased OFString * @throw OFInvalidFormatException The specified format is invalid */ Index: src/OFDate.m ================================================================== --- src/OFDate.m +++ src/OFDate.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,21 +22,23 @@ #include #include #import "OFDate.h" +#import "OFConcreteDate.h" #import "OFData.h" #import "OFDictionary.h" #import "OFMessagePackExtension.h" #ifdef OF_HAVE_THREADS # import "OFMutex.h" #endif +#import "OFStrFTime.h" #import "OFStrPTime.h" #import "OFString.h" #import "OFSystemInfo.h" +#import "OFTaggedPointerDate.h" #import "OFXMLAttribute.h" -#import "OFXMLElement.h" #import "OFInitializationFailedException.h" #import "OFInvalidArgumentException.h" #import "OFInvalidFormatException.h" #import "OFOutOfMemoryException.h" @@ -45,51 +47,40 @@ #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; +@interface OFPlaceholderDate: OFDate @end -@interface OFDateSingleton: OFDate -@end - -@interface OFDatePlaceholder: OFDateSingleton -@end - -#if defined(OF_OBJFW_RUNTIME) && UINTPTR_MAX == UINT64_MAX -@interface OFTaggedPointerDate: OFDateSingleton -@end -#endif +@interface OFConcreteDateSingleton: OFConcreteDate +@end static struct { Class isa; } placeholder; -static OFDateSingleton *zeroDate, *distantFuture, *distantPast; -#if defined(OF_OBJFW_RUNTIME) && UINTPTR_MAX == UINT64_MAX -static int dateTag; -#endif +static OFConcreteDateSingleton *zeroDate, *distantFuture, *distantPast; static void initZeroDate(void) { - zeroDate = [[OFDateSingleton alloc] initWithTimeIntervalSince1970: 0]; + zeroDate = [[OFConcreteDateSingleton alloc] + initWithTimeIntervalSince1970: 0]; } static void initDistantFuture(void) { - distantFuture = [[OFDateSingleton alloc] + distantFuture = [[OFConcreteDateSingleton alloc] initWithTimeIntervalSince1970: 64060588800.0]; } static void initDistantPast(void) { - distantPast = [[OFDateSingleton alloc] + distantPast = [[OFConcreteDateSingleton alloc] initWithTimeIntervalSince1970: -62167219200.0]; } static OFTimeInterval now(void) @@ -258,32 +249,15 @@ seconds += -(double)tz * 60; return seconds; } -@implementation OFDateSingleton -- (instancetype)autorelease -{ - return self; -} - -- (instancetype)retain -{ - return self; -} - -- (void)release -{ -} - -- (unsigned int)retainCount -{ - return OFMaxRetainCount; -} +@implementation OFConcreteDateSingleton +OF_SINGLETON_METHODS @end -@implementation OFDatePlaceholder +@implementation OFPlaceholderDate #ifdef __clang__ /* We intentionally don't call into super, so silence the warning. */ # pragma clang diagnostic push # pragma clang diagnostic ignored "-Wunknown-pragmas" # pragma clang diagnostic ignored "-Wobjc-designated-initializers" @@ -304,38 +278,28 @@ value = OFFromBigEndian64(OFDoubleToRawUInt64(OFToBigEndianDouble( seconds))); /* Almost all dates fall into this range. */ if (value & (UINT64_C(4) << 60)) { - id ret = objc_createTaggedPointer(dateTag, - value & ~(UINT64_C(4) << 60)); + id ret = [OFTaggedPointerDate + dateWithUInt64TimeIntervalSince1970: value]; if (ret != nil) return ret; } #endif - return (id)[[OFDate of_alloc] initWithTimeIntervalSince1970: seconds]; + return (id)[[OFConcreteDate alloc] + initWithTimeIntervalSince1970: seconds]; } #ifdef __clang__ # pragma clang diagnostic pop #endif -@end - -#if defined(OF_OBJFW_RUNTIME) && UINTPTR_MAX == UINT64_MAX -@implementation OFTaggedPointerDate -- (OFTimeInterval)timeIntervalSince1970 -{ - uint64_t value = (uint64_t)object_getTaggedPointerValue(self); - - value |= UINT64_C(4) << 60; - - return OFFromBigEndianDouble(OFRawUInt64ToDouble(OFToBigEndian64( - value))); -} -@end -#endif + +OF_SINGLETON_METHODS +@end + @implementation OFDate + (void)initialize { #ifdef OF_WINDOWS @@ -343,32 +307,23 @@ #endif if (self != [OFDate class]) return; - placeholder.isa = [OFDatePlaceholder class]; + object_setClass((id)&placeholder, [OFPlaceholderDate class]); #if (!defined(HAVE_GMTIME_R) || !defined(HAVE_LOCALTIME_R)) && \ defined(OF_HAVE_THREADS) mutex = [[OFMutex alloc] init]; atexit(releaseMutex); #endif #ifdef OF_WINDOWS - if ((module = LoadLibrary("msvcrt.dll")) != NULL) + if ((module = GetModuleHandle("msvcrt.dll")) != NULL) _mktime64FuncPtr = (__time64_t (*)(struct tm *)) GetProcAddress(module, "_mktime64"); #endif - -#if defined(OF_OBJFW_RUNTIME) && UINTPTR_MAX == UINT64_MAX - dateTag = objc_registerTaggedPointerClass([OFTaggedPointerDate class]); -#endif -} - -+ (instancetype)of_alloc -{ - return [super alloc]; } + (instancetype)alloc { if (self == [OFDate class]) @@ -427,15 +382,22 @@ return [self initWithTimeIntervalSince1970: now()]; } - (instancetype)initWithTimeIntervalSince1970: (OFTimeInterval)seconds { - self = [super init]; + if ([self isMemberOfClass: [OFDate class]]) { + @try { + [self doesNotRecognizeSelector: _cmd]; + } @catch (id e) { + [self release]; + @throw e; + } - _seconds = seconds; + abort(); + } - return self; + return [super init]; } - (instancetype)initWithTimeIntervalSinceNow: (OFTimeInterval)seconds { return [self initWithTimeIntervalSince1970: now() + seconds]; @@ -494,43 +456,10 @@ objc_autoreleasePoolPop(pool); return [self initWithTimeIntervalSince1970: seconds]; } -- (instancetype)initWithSerialization: (OFXMLElement *)element -{ - OFTimeInterval seconds; - - @try { - void *pool = objc_autoreleasePoolPush(); - unsigned long long value; - - if (![element.name isEqual: @"OFDate"] || - ![element.namespace isEqual: OFSerializationNS]) - @throw [OFInvalidArgumentException exception]; - - if (![[element attributeForName: @"encoding"].stringValue - isEqual: @"hex"]) - @throw [OFInvalidFormatException exception]; - - value = [element unsignedLongLongValueWithBase: 16]; - - if (value > UINT64_MAX) - @throw [OFOutOfRangeException exception]; - - seconds = OFFromBigEndianDouble(OFRawUInt64ToDouble( - OFToBigEndian64(value))); - - objc_autoreleasePoolPop(pool); - } @catch (id e) { - [self release]; - @throw e; - } - - return [self initWithTimeIntervalSince1970: seconds]; -} - - (bool)isEqual: (id)object { OFDate *otherDate; if (object == self) @@ -582,31 +511,11 @@ return OFOrderedSame; } - (OFString *)description { - return [self dateStringWithFormat: @"%Y-%m-%dT%H:%M:%SZ"]; -} - -- (OFXMLElement *)XMLElementBySerializing -{ - void *pool = objc_autoreleasePoolPush(); - OFXMLElement *element; - - element = [OFXMLElement elementWithName: @"OFDate" - namespace: OFSerializationNS]; - - [element addAttributeWithName: @"encoding" stringValue: @"hex"]; - element.stringValue = [OFString stringWithFormat: @"%016" PRIx64, - OFFromBigEndian64(OFDoubleToRawUInt64(OFToBigEndianDouble( - self.timeIntervalSince1970)))]; - - [element retain]; - - objc_autoreleasePoolPop(pool); - - return [element autorelease]; + return [self dateStringWithFormat: @"%Y-%m-%dT%H:%M:%S%z"]; } - (OFData *)messagePackRepresentation { void *pool = objc_autoreleasePoolPush(); @@ -748,15 +657,11 @@ OFString *ret; OFTimeInterval timeInterval = self.timeIntervalSince1970; time_t seconds = (time_t)timeInterval; struct tm tm; size_t pageSize; -#ifndef OF_WINDOWS char *buffer; -#else - wchar_t *buffer; -#endif if (seconds != trunc(timeInterval)) @throw [OFOutOfRangeException exception]; #ifdef HAVE_GMTIME_R @@ -782,22 +687,15 @@ #endif pageSize = [OFSystemInfo pageSize]; buffer = OFAllocMemory(1, pageSize); @try { -#ifndef OF_WINDOWS - if (strftime(buffer, pageSize, format.UTF8String, &tm) == 0) + if (OFStrFTime(buffer, pageSize, format.UTF8String, &tm, + 0) == 0) @throw [OFOutOfRangeException exception]; ret = [OFString stringWithUTF8String: buffer]; -#else - if (wcsftime(buffer, pageSize / sizeof(wchar_t), - format.UTF16String, &tm) == 0) - @throw [OFOutOfRangeException exception]; - - ret = [OFString stringWithUTF16String: buffer]; -#endif } @finally { OFFreeMemory(buffer); } return ret; @@ -808,15 +706,11 @@ OFString *ret; OFTimeInterval timeInterval = self.timeIntervalSince1970; time_t seconds = (time_t)timeInterval; struct tm tm; size_t pageSize; -#ifndef OF_WINDOWS char *buffer; -#else - wchar_t *buffer; -#endif if (seconds != trunc(timeInterval)) @throw [OFOutOfRangeException exception]; #ifdef HAVE_LOCALTIME_R @@ -842,22 +736,15 @@ #endif pageSize = [OFSystemInfo pageSize]; buffer = OFAllocMemory(1, pageSize); @try { -#ifndef OF_WINDOWS - if (strftime(buffer, pageSize, format.UTF8String, &tm) == 0) + if (OFStrFTime(buffer, pageSize, format.UTF8String, &tm, + 0) == 0) @throw [OFOutOfRangeException exception]; ret = [OFString stringWithUTF8String: buffer]; -#else - if (wcsftime(buffer, pageSize / sizeof(wchar_t), - format.UTF16String, &tm) == 0) - @throw [OFOutOfRangeException exception]; - - ret = [OFString stringWithUTF16String: buffer]; -#endif } @finally { OFFreeMemory(buffer); } return ret; @@ -885,11 +772,11 @@ return self; } - (OFTimeInterval)timeIntervalSince1970 { - return _seconds; + OF_UNRECOGNIZED_SELECTOR } - (OFTimeInterval)timeIntervalSinceDate: (OFDate *)otherDate { return self.timeIntervalSince1970 - otherDate.timeIntervalSince1970; Index: src/OFDictionary.h ================================================================== --- src/OFDictionary.h +++ src/OFDictionary.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -23,11 +23,10 @@ #include #import "OFObject.h" #import "OFCollection.h" #import "OFEnumerator.h" -#import "OFSerialization.h" #import "OFJSONRepresentation.h" #import "OFMessagePackRepresentation.h" OF_ASSUME_NONNULL_BEGIN @@ -75,11 +74,11 @@ * * @note Subclasses must implement @ref objectForKey:, @ref count and * @ref keyEnumerator. */ @interface OFDictionary OF_GENERIC(KeyType, ObjectType): OFObject #if !defined(OF_HAVE_GENERICS) && !defined(DOXYGEN) # define KeyType id # define ObjectType id #endif @@ -148,10 +147,17 @@ * @return A new autoreleased OFDictionary */ + (instancetype)dictionaryWithKeysAndObjects: (KeyType)firstKey, ... OF_SENTINEL; +/** + * @brief Initializes an already allocated OFDictionary to be empty. + * + * @return An initialized OFDictionary + */ +- (instancetype)init OF_DESIGNATED_INITIALIZER; + /** * @brief Initializes an already allocated OFDictionary with the specified * OFDictionary. * * @param dictionary An OFDictionary @@ -190,11 +196,11 @@ * @param count The number of objects in the arrays * @return An initialized OFDictionary */ - (instancetype)initWithObjects: (ObjectType const _Nonnull *_Nonnull)objects forKeys: (KeyType const _Nonnull *_Nonnull)keys - count: (size_t)count; + count: (size_t)count OF_DESIGNATED_INITIALIZER; /** * @brief Initializes an already allocated OFDictionary with the specified keys * and objects. * Index: src/OFDictionary.m ================================================================== --- src/OFDictionary.m +++ src/OFDictionary.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,38 +15,33 @@ #include "config.h" #include -#include - #import "OFDictionary.h" #import "OFArray.h" #import "OFCharacterSet.h" +#import "OFConcreteDictionary.h" #import "OFData.h" #import "OFEnumerator.h" -#import "OFMapTableDictionary.h" #import "OFString.h" -#import "OFXMLElement.h" #import "OFInvalidArgumentException.h" #import "OFOutOfRangeException.h" #import "OFUndefinedKeyException.h" static struct { Class isa; } placeholder; -static OFCharacterSet *URIQueryPartAllowedCharacterSet = nil; - @interface OFDictionary () - (OFString *) of_JSONRepresentationWithOptions: (OFJSONRepresentationOptions)options depth: (size_t)depth; @end -@interface OFDictionaryPlaceholder: OFDictionary +@interface OFPlaceholderDictionary: OFDictionary @end OF_DIRECT_MEMBERS @interface OFDictionaryObjectEnumerator: OFEnumerator { @@ -55,44 +50,45 @@ } - (instancetype)initWithDictionary: (OFDictionary *)dictionary; @end -OF_DIRECT_MEMBERS -@interface OFURIQueryPartAllowedCharacterSet: OFCharacterSet -+ (OFCharacterSet *)URIQueryPartAllowedCharacterSet; -@end - -@implementation OFDictionaryPlaceholder +@implementation OFPlaceholderDictionary +#ifdef __clang__ +/* We intentionally don't call into super, so silence the warning. */ +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wunknown-pragmas" +# pragma clang diagnostic ignored "-Wobjc-designated-initializers" +#endif - (instancetype)init { - return (id)[[OFMapTableDictionary alloc] init]; + return (id)[[OFConcreteDictionary alloc] init]; } - (instancetype)initWithDictionary: (OFDictionary *)dictionary { - return (id)[[OFMapTableDictionary alloc] + return (id)[[OFConcreteDictionary alloc] initWithDictionary: dictionary]; } - (instancetype)initWithObject: (id)object forKey: (id)key { - return (id)[[OFMapTableDictionary alloc] initWithObject: object + return (id)[[OFConcreteDictionary alloc] initWithObject: object forKey: key]; } - (instancetype)initWithObjects: (OFArray *)objects forKeys: (OFArray *)keys { - return (id)[[OFMapTableDictionary alloc] initWithObjects: objects + return (id)[[OFConcreteDictionary alloc] initWithObjects: objects forKeys: keys]; } - (instancetype)initWithObjects: (id const *)objects forKeys: (id const *)keys count: (size_t)count { - return (id)[[OFMapTableDictionary alloc] initWithObjects: objects + return (id)[[OFConcreteDictionary alloc] initWithObjects: objects forKeys: keys count: count]; } - (instancetype)initWithKeysAndObjects: (id )firstKey, ... @@ -99,115 +95,36 @@ { id ret; va_list arguments; va_start(arguments, firstKey); - ret = [[OFMapTableDictionary alloc] initWithKey: firstKey + ret = [[OFConcreteDictionary alloc] initWithKey: firstKey arguments: arguments]; va_end(arguments); return ret; } - (instancetype)initWithKey: (id )firstKey arguments: (va_list)arguments { - return (id)[[OFMapTableDictionary alloc] initWithKey: firstKey + return (id)[[OFConcreteDictionary alloc] initWithKey: firstKey arguments: arguments]; } - -- (instancetype)initWithSerialization: (OFXMLElement *)element -{ - return (id)[[OFMapTableDictionary alloc] - initWithSerialization: element]; -} - -- (instancetype)retain -{ - return self; -} - -- (instancetype)autorelease -{ - return self; -} - -- (void)release -{ -} - -- (void)dealloc -{ - OF_DEALLOC_UNSUPPORTED -} -@end - -@implementation OFURIQueryPartAllowedCharacterSet -+ (void)initialize -{ - if (self != [OFURIQueryPartAllowedCharacterSet class]) - return; - - URIQueryPartAllowedCharacterSet = - [[OFURIQueryPartAllowedCharacterSet alloc] init]; -} - -+ (OFCharacterSet *)URIQueryPartAllowedCharacterSet -{ - return URIQueryPartAllowedCharacterSet; -} - -- (instancetype)autorelease -{ - return self; -} - -- (instancetype)retain -{ - return self; -} - -- (void)release -{ -} - -- (unsigned int)retainCount -{ - return OFMaxRetainCount; -} - -- (bool)characterIsMember: (OFUnichar)character -{ - if (character < CHAR_MAX && OFASCIIIsAlnum(character)) - return true; - - switch (character) { - case '-': - case '.': - case '_': - case '~': - case '!': - case '$': - case '\'': - case '(': - case ')': - case '*': - case '+': - case ',': - case ';': - return true; - default: - return false; - } -} +#ifdef __clang__ +# pragma clang diagnostic pop +#endif + +OF_SINGLETON_METHODS @end @implementation OFDictionary + (void)initialize { if (self == [OFDictionary class]) - placeholder.isa = [OFDictionaryPlaceholder class]; + object_setClass((id)&placeholder, + [OFPlaceholderDictionary class]); } + (instancetype)alloc { if (self == [OFDictionary class]) @@ -261,11 +178,12 @@ return ret; } - (instancetype)init { - if ([self isMemberOfClass: [OFDictionary class]]) { + if ([self isMemberOfClass: [OFDictionary class]] || + [self isMemberOfClass: [OFMutableDictionary class]]) { @try { [self doesNotRecognizeSelector: _cmd]; } @catch (id e) { [self release]; @throw e; @@ -277,23 +195,57 @@ return [super init]; } - (instancetype)initWithDictionary: (OFDictionary *)dictionary { - OF_INVALID_INIT_METHOD + void *pool = objc_autoreleasePoolPush(); + id const *objects, *keys; + size_t count; + + @try { + OFArray *objects_ = [dictionary.objectEnumerator allObjects]; + OFArray *keys_ = [dictionary.keyEnumerator allObjects]; + + count = dictionary.count; + + if (count != keys_.count || count != objects_.count) + @throw [OFInvalidArgumentException exception]; + + objects = objects_.objects; + keys = keys_.objects; + } @catch (id e) { + [self release]; + @throw e; + } + + @try { + self = [self initWithObjects: objects + forKeys: keys + count: count]; + } @finally { + objc_autoreleasePoolPop(pool); + } + + return self; } - (instancetype)initWithObject: (id)object forKey: (id)key { - if (key == nil || object == nil) - @throw [OFInvalidArgumentException exception]; + @try { + if (key == nil || object == nil) + @throw [OFInvalidArgumentException exception]; + } @catch (id e) { + [self release]; + @throw e; + } - return [self initWithKeysAndObjects: key, object, nil]; + return [self initWithObjects: &object forKeys: &key count: 1]; } - (instancetype)initWithObjects: (OFArray *)objects_ forKeys: (OFArray *)keys_ { + void *pool = objc_autoreleasePoolPush(); id const *objects, *keys; size_t count; @try { count = objects_.count; @@ -306,19 +258,32 @@ } @catch (id e) { [self release]; @throw e; } - return [self initWithObjects: objects forKeys: keys count: count]; + self = [self initWithObjects: objects forKeys: keys count: count]; + + objc_autoreleasePoolPop(pool); + + return self; } +#ifdef __clang__ +/* We intentionally don't call into super, so silence the warning. */ +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wunknown-pragmas" +# pragma clang diagnostic ignored "-Wobjc-designated-initializers" +#endif - (instancetype)initWithObjects: (id const *)objects forKeys: (id const *)keys count: (size_t)count { OF_INVALID_INIT_METHOD } +#ifdef __clang__ +# pragma clang diagnostic pop +#endif - (instancetype)initWithKeysAndObjects: (id)firstKey, ... { id ret; va_list arguments; @@ -330,16 +295,60 @@ return ret; } - (instancetype)initWithKey: (id)firstKey arguments: (va_list)arguments { - OF_INVALID_INIT_METHOD -} + size_t count = 1; + id *objects = NULL, *keys = NULL; + va_list argumentsCopy; -- (instancetype)initWithSerialization: (OFXMLElement *)element -{ - OF_INVALID_INIT_METHOD + if (firstKey == nil) + return [self init]; + + va_copy(argumentsCopy, arguments); + while (va_arg(argumentsCopy, id) != nil) + count++; + + @try { + size_t i = 0; + id key, object; + + if (count % 2 != 0) + @throw [OFInvalidArgumentException exception]; + + count /= 2; + + objects = OFAllocMemory(count, sizeof(id)); + keys = OFAllocMemory(count, sizeof(id)); + + while ((key = va_arg(arguments, id)) != nil && + (object = va_arg(arguments, id)) != nil) { + OFEnsure(i < count); + + objects[i] = object; + keys[i] = key; + + i++; + } + } @catch (id e) { + OFFreeMemory(objects); + OFFreeMemory(keys); + + [self release]; + @throw e; + } + + @try { + self = [self initWithObjects: objects + forKeys: keys + count: count]; + } @finally { + OFFreeMemory(objects); + OFFreeMemory(keys); + } + + return self; } - (id)objectForKey: (id)key { OF_UNRECOGNIZED_SELECTOR @@ -510,10 +519,11 @@ - (int)countByEnumeratingWithState: (OFFastEnumerationState *)state objects: (id *)objects count: (int)count { + static unsigned long dummyMutations; OFEnumerator *enumerator; int i; memcpy(&enumerator, state->extra, sizeof(enumerator)); @@ -521,11 +531,11 @@ enumerator = [self keyEnumerator]; memcpy(state->extra, &enumerator, sizeof(enumerator)); } state->itemsPtr = objects; - state->mutationsPtr = (unsigned long *)self; + state->mutationsPtr = &dummyMutations; for (i = 0; i < count; i++) { id object = [enumerator nextObject]; if (object == nil) @@ -637,54 +647,10 @@ objc_autoreleasePoolPop(pool); return ret; } -- (OFXMLElement *)XMLElementBySerializing -{ - void *pool = objc_autoreleasePoolPush(); - OFXMLElement *element; - OFEnumerator *keyEnumerator, *objectEnumerator; - id key, object; - - if ([self isKindOfClass: [OFMutableDictionary class]]) - element = [OFXMLElement elementWithName: @"OFMutableDictionary" - namespace: OFSerializationNS]; - else - element = [OFXMLElement elementWithName: @"OFDictionary" - namespace: OFSerializationNS]; - - keyEnumerator = [self keyEnumerator]; - objectEnumerator = [self objectEnumerator]; - while ((key = [keyEnumerator nextObject]) != nil && - (object = [objectEnumerator nextObject]) != nil) { - void *pool2 = objc_autoreleasePoolPush(); - OFXMLElement *keyElement, *objectElement; - - keyElement = [OFXMLElement - elementWithName: @"key" - namespace: OFSerializationNS]; - [keyElement addChild: key.XMLElementBySerializing]; - - objectElement = [OFXMLElement - elementWithName: @"object" - namespace: OFSerializationNS]; - [objectElement addChild: object.XMLElementBySerializing]; - - [element addChild: keyElement]; - [element addChild: objectElement]; - - objc_autoreleasePoolPop(pool2); - } - - [element retain]; - - objc_autoreleasePoolPop(pool); - - return [element autorelease]; -} - - (OFString *)JSONRepresentation { return [self of_JSONRepresentationWithOptions: 0 depth: 0]; } @@ -824,11 +790,11 @@ [data addItems: child.items count: child.count]; objc_autoreleasePoolPop(pool2); } - assert(i == count); + OFAssert(i == count); [data makeImmutable]; objc_autoreleasePoolPop(pool); ADDED src/OFEmbeddedIRIHandler.h Index: src/OFEmbeddedIRIHandler.h ================================================================== --- /dev/null +++ src/OFEmbeddedIRIHandler.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2008-2024 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#import "OFIRIHandler.h" + +OF_ASSUME_NONNULL_BEGIN + +@interface OFEmbeddedIRIHandler: OFIRIHandler +@end + +#ifdef __cplusplus +extern "C" { +#endif +/** + * @brief Register a file for the `embedded:` IRI scheme. + * + * Usually, you should not use the directly, but rather generate a source file + * for a file to be embedded using the `objfw-embed` tool. + * + * @param path The path to the file under the `embedded:` scheme. This is not + * retained, so you must either pass a constant string or pass a + * string that is already retained! + * @param bytes The raw bytes for the file + * @param size The size of the file + */ +extern void OFRegisterEmbeddedFile(OFString *path, const uint8_t *bytes, + size_t size); +#ifdef __cplusplus +} +#endif + +OF_ASSUME_NONNULL_END ADDED src/OFEmbeddedIRIHandler.m Index: src/OFEmbeddedIRIHandler.m ================================================================== --- /dev/null +++ src/OFEmbeddedIRIHandler.m @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2008-2024 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 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 "OFEmbeddedIRIHandler.h" +#import "OFIRI.h" +#import "OFMemoryStream.h" + +#import "OFInvalidArgumentException.h" +#import "OFOpenItemFailedException.h" + +#ifdef OF_HAVE_THREADS +# import "OFOnce.h" +# import "OFPlainMutex.h" +#endif + +struct EmbeddedFile { + OFString *path; + const uint8_t *bytes; + size_t size; +} *embeddedFiles = NULL; +size_t numEmbeddedFiles = 0; +#ifdef OF_HAVE_THREADS +static OFPlainMutex mutex; +static OFOnceControl mutexOnceControl = OFOnceControlInitValue; + +static void +initMutex(void) +{ + OFEnsure(OFPlainMutexNew(&mutex) == 0); +} +#endif + +void +OFRegisterEmbeddedFile(OFString *path, const uint8_t *bytes, size_t size) +{ +#ifdef OF_HAVE_THREADS + OFOnce(&mutexOnceControl, initMutex); + + OFEnsure(OFPlainMutexLock(&mutex) == 0); +#endif + + embeddedFiles = realloc(embeddedFiles, + sizeof(*embeddedFiles) * (numEmbeddedFiles + 1)); + OFEnsure(embeddedFiles != NULL); + + embeddedFiles[numEmbeddedFiles].path = path; + embeddedFiles[numEmbeddedFiles].bytes = bytes; + embeddedFiles[numEmbeddedFiles].size = size; + numEmbeddedFiles++; + +#ifdef OF_HAVE_THREADS + OFEnsure(OFPlainMutexUnlock(&mutex) == 0); +#endif +} + +@implementation OFEmbeddedIRIHandler +#ifdef OF_HAVE_THREADS ++ (void)initialize +{ + if (self == [OFEmbeddedIRIHandler class]) + OFOnce(&mutexOnceControl, initMutex); +} +#endif + +- (OFStream *)openItemAtIRI: (OFIRI *)IRI mode: (OFString *)mode +{ + OFString *path; + + if (![IRI.scheme isEqual: @"embedded"] || IRI.host.length > 0 || + IRI.port != nil || IRI.user != nil || IRI.password != nil || + IRI.query != nil || IRI.fragment != nil) + @throw [OFInvalidArgumentException exception]; + + if (![mode isEqual: @"r"]) + @throw [OFOpenItemFailedException exceptionWithIRI: IRI + mode: mode + errNo: EROFS]; + + if ((path = IRI.path) == nil) { + @throw [OFInvalidArgumentException exception]; + } + +#ifdef OF_HAVE_THREADS + OFEnsure(OFPlainMutexLock(&mutex) == 0); + @try { +#endif + for (size_t i = 0; i < numEmbeddedFiles; i++) { + if (![embeddedFiles[i].path isEqual: path]) + continue; + + return [OFMemoryStream + streamWithMemoryAddress: (void *) + embeddedFiles[i].bytes + size: embeddedFiles[i].size + writable: false]; + } +#ifdef OF_HAVE_THREADS + } @finally { + OFEnsure(OFPlainMutexUnlock(&mutex) == 0); + } +#endif + + @throw [OFOpenItemFailedException exceptionWithIRI: IRI + mode: mode + errNo: ENOENT]; +} +@end DELETED src/OFEmbeddedURIHandler.h Index: src/OFEmbeddedURIHandler.h ================================================================== --- src/OFEmbeddedURIHandler.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (c) 2008-2022 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#import "OFURIHandler.h" - -OF_ASSUME_NONNULL_BEGIN - -@interface OFEmbeddedURIHandler: OFURIHandler -@end - -OF_ASSUME_NONNULL_END DELETED src/OFEmbeddedURIHandler.m Index: src/OFEmbeddedURIHandler.m ================================================================== --- src/OFEmbeddedURIHandler.m +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright (c) 2008-2022 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 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 "OFEmbeddedURIHandler.h" -#import "OFMemoryStream.h" -#import "OFURI.h" - -#import "OFInvalidArgumentException.h" -#import "OFOpenItemFailedException.h" - -#ifdef OF_HAVE_THREADS -# import "OFOnce.h" -# import "OFPlainMutex.h" -#endif - -struct EmbeddedFile { - const char *name; - const uint8_t *bytes; - size_t size; -} *embeddedFiles = NULL; -size_t numEmbeddedFiles = 0; -#ifdef OF_HAVE_THREADS -static OFPlainMutex mutex; - -static void -init(void) -{ - OFEnsure(OFPlainMutexNew(&mutex) == 0); -} -#endif - -void -OFRegisterEmbeddedFile(const char *name, const uint8_t *bytes, size_t size) -{ -#ifdef OF_HAVE_THREADS - static OFOnceControl onceControl = OFOnceControlInitValue; - OFOnce(&onceControl, init); - - OFEnsure(OFPlainMutexLock(&mutex) == 0); -#endif - - embeddedFiles = realloc(embeddedFiles, - sizeof(*embeddedFiles) * (numEmbeddedFiles + 1)); - OFEnsure(embeddedFiles != NULL); - - embeddedFiles[numEmbeddedFiles].name = name; - embeddedFiles[numEmbeddedFiles].bytes = bytes; - embeddedFiles[numEmbeddedFiles].size = size; - numEmbeddedFiles++; - -#ifdef OF_HAVE_THREADS - OFEnsure(OFPlainMutexUnlock(&mutex) == 0); -#endif -} - -@implementation OFEmbeddedURIHandler -- (OFStream *)openItemAtURI: (OFURI *)URI mode: (OFString *)mode -{ - const char *path; - - if (![URI.scheme isEqual: @"embedded"] || URI.host.length > 0 || - URI.port != nil || URI.user != nil || URI.password != nil || - URI.query != nil || URI.fragment != nil) - @throw [OFInvalidArgumentException exception]; - - if (![mode isEqual: @"r"]) - @throw [OFOpenItemFailedException exceptionWithURI: URI - mode: mode - errNo: EROFS]; - - if ((path = URI.path.UTF8String) == NULL) { - @throw [OFInvalidArgumentException exception]; - } - -#ifdef OF_HAVE_THREADS - OFEnsure(OFPlainMutexLock(&mutex) == 0); - @try { -#endif - for (size_t i = 0; i < numEmbeddedFiles; i++) { - if (strcmp(embeddedFiles[i].name, path) != 0) - continue; - - return [OFMemoryStream - streamWithMemoryAddress: (void *) - embeddedFiles[i].bytes - size: embeddedFiles[i].size - writable: false]; - } -#ifdef OF_HAVE_THREADS - } @finally { - OFEnsure(OFPlainMutexUnlock(&mutex) == 0); - } -#endif - - @throw [OFOpenItemFailedException exceptionWithURI: URI - mode: mode - errNo: ENOENT]; -} -@end Index: src/OFEnumerator.h ================================================================== --- src/OFEnumerator.h +++ src/OFEnumerator.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFEnumerator.m ================================================================== --- src/OFEnumerator.m +++ src/OFEnumerator.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -59,14 +59,15 @@ - (int)countByEnumeratingWithState: (OFFastEnumerationState *)state objects: (id *)objects count: (int)count { + static unsigned long dummyMutations; int i; state->itemsPtr = objects; - state->mutationsPtr = (unsigned long *)self; + state->mutationsPtr = &dummyMutations; for (i = 0; i < count; i++) { id object = [self nextObject]; if (object == nil) Index: src/OFEpollKernelEventObserver.h ================================================================== --- src/OFEpollKernelEventObserver.h +++ src/OFEpollKernelEventObserver.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,11 +13,10 @@ * file. */ #include "config.h" -#include #include #ifdef HAVE_FCNTL_H # include #endif Index: src/OFFile.h ================================================================== --- src/OFFile.h +++ src/OFFile.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,12 +25,10 @@ static const OFFileHandle OFInvalidFileHandle = NULL; #endif OF_ASSUME_NONNULL_BEGIN -@class OFURI; - /** * @class OFFile OFFile.h ObjFW/OFFile.h * * @brief A class which provides methods to read and write files. */ @@ -39,11 +37,11 @@ #ifdef OF_FILE_HANDLE_IS_FD #endif { OFFileHandle _handle; - bool _atEndOfStream; + bool _initialized, _atEndOfStream; } /** * @brief Creates a new OFFile with the specified path and mode. * Index: src/OFFile.m ================================================================== --- src/OFFile.m +++ src/OFFile.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,13 +13,14 @@ * file. */ #include "config.h" -#define _LARGEFILE64_SOURCE +#ifndef _LARGEFILE64_SOURCE +# define _LARGEFILE64_SOURCE +#endif -#include #include #ifdef HAVE_FCNTL_H # include #endif @@ -31,11 +32,10 @@ #import "OFFile.h" #import "OFLocale.h" #import "OFString.h" #import "OFSystemInfo.h" -#import "OFURI.h" #import "OFInitializationFailedException.h" #import "OFInvalidArgumentException.h" #import "OFNotOpenException.h" #import "OFOpenItemFailedException.h" @@ -48,12 +48,14 @@ #ifdef OF_WINDOWS # include #endif #ifdef OF_AMIGAOS +# define Class IntuitionClass # include # include +# undef Class #endif #ifdef OF_WII # include #endif @@ -337,10 +339,11 @@ - (instancetype)initWithHandle: (OFFileHandle)handle { self = [super init]; _handle = handle; + _initialized = true; return self; } - (instancetype)init @@ -552,11 +555,11 @@ [super close]; } - (void)dealloc { - if (_handle != OFInvalidFileHandle) + if (_initialized && _handle != OFInvalidFileHandle) [self close]; [super dealloc]; } @end ADDED src/OFFileIRIHandler.h Index: src/OFFileIRIHandler.h ================================================================== --- /dev/null +++ src/OFFileIRIHandler.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2008-2024 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#import "OFIRIHandler.h" + +OF_ASSUME_NONNULL_BEGIN + +@interface OFFileIRIHandler: OFIRIHandler ++ (bool)of_directoryExistsAtPath: (OFString *)path OF_DIRECT; +@end + +OF_ASSUME_NONNULL_END ADDED src/OFFileIRIHandler.m Index: src/OFFileIRIHandler.m ================================================================== --- /dev/null +++ src/OFFileIRIHandler.m @@ -0,0 +1,1674 @@ +/* + * Copyright (c) 2008-2024 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#include "config.h" + +#ifndef _LARGEFILE64_SOURCE +# define _LARGEFILE64_SOURCE +#endif + +#include +#include + +#ifdef HAVE_DIRENT_H +# include +#endif +#include "unistd_wrapper.h" + +#include "platform.h" +#ifdef HAVE_SYS_STAT_H +# include +#endif +#include +#if defined(OF_LINUX) || defined(OF_MACOS) +# include +#endif +#ifdef OF_WINDOWS +# include +#endif +#ifdef OF_DJGPP +# include +#endif + +#ifdef HAVE_FCNTL_H +# include +#endif +#ifdef HAVE_PWD_H +# include +#endif +#ifdef HAVE_GRP_H +# include +#endif + +#import "OFFileIRIHandler.h" +#import "OFArray.h" +#import "OFData.h" +#import "OFDate.h" +#import "OFFile.h" +#import "OFFileManager.h" +#import "OFIRI.h" +#import "OFLocale.h" +#import "OFNumber.h" +#import "OFSystemInfo.h" + +#ifdef OF_HAVE_THREADS +# import "OFMutex.h" +#endif + +#import "OFCreateDirectoryFailedException.h" +#import "OFCreateSymbolicLinkFailedException.h" +#import "OFGetItemAttributesFailedException.h" +#import "OFInitializationFailedException.h" +#import "OFInvalidArgumentException.h" +#import "OFLinkItemFailedException.h" +#import "OFMoveItemFailedException.h" +#import "OFNotImplementedException.h" +#import "OFOpenItemFailedException.h" +#import "OFOutOfRangeException.h" +#import "OFReadFailedException.h" +#import "OFRemoveItemFailedException.h" +#import "OFSetItemAttributesFailedException.h" + +#ifdef OF_WINDOWS +# include +# include +# include +# include +#endif + +#ifdef OF_AMIGAOS +# define Class IntuitionClass +# include +# include +# include +# undef Class +# ifdef OF_AMIGAOS4 +# define DeleteFile(path) Delete(path) +# endif +#endif + +#if defined(OF_WINDOWS) || defined(OF_AMIGAOS) +typedef struct { + OFStreamOffset st_size; + unsigned int st_mode; + OFTimeInterval st_atime, st_mtime, st_ctime; +# ifdef OF_WINDOWS +# define HAVE_STRUCT_STAT_ST_BIRTHTIME + OFTimeInterval st_birthtime; + DWORD fileAttributes; +# endif +} Stat; +#elif defined(HAVE_STAT64) +typedef struct stat64 Stat; +#else +typedef struct stat Stat; +#endif + +#ifdef OF_WINDOWS +# define S_IFLNK 0x10000 +# define S_ISLNK(mode) (mode & S_IFLNK) +#endif + +#if defined(OF_FILE_MANAGER_SUPPORTS_OWNER) && defined(OF_HAVE_THREADS) +static OFMutex *passwdMutex; + +static void +releasePasswdMutex(void) +{ + [passwdMutex release]; +} +#endif +#if !defined(HAVE_READDIR_R) && defined(OF_HAVE_THREADS) && !defined(OF_WINDOWS) +static OFMutex *readdirMutex; + +static void +releaseReaddirMutex(void) +{ + [readdirMutex release]; +} +#endif + +#ifdef OF_WINDOWS +static int (*_wutime64FuncPtr)(const wchar_t *, struct __utimbuf64 *); +static WINAPI BOOLEAN (*createSymbolicLinkWFuncPtr)(LPCWSTR, LPCWSTR, DWORD); +static WINAPI BOOLEAN (*createHardLinkWFuncPtr)(LPCWSTR, LPCWSTR, + LPSECURITY_ATTRIBUTES); +#endif + +#ifdef OF_WINDOWS +static OFTimeInterval +filetimeToTimeInterval(const FILETIME *filetime) +{ + return (double)((int64_t)filetime->dwHighDateTime << 32 | + filetime->dwLowDateTime) / 10000000.0 - 11644473600.0; +} + +static int +lastError(void) +{ + switch (GetLastError()) { + case ERROR_FILE_NOT_FOUND: + case ERROR_PATH_NOT_FOUND: + case ERROR_NO_MORE_FILES: + return ENOENT; + case ERROR_ACCESS_DENIED: + return EACCES; + case ERROR_DIRECTORY: + return ENOTDIR; + case ERROR_NOT_READY: + return EBUSY; + default: + return EIO; + } +} +#endif + +#ifdef OF_AMIGAOS +static int +lastError(void) +{ + switch (IoErr()) { + case ERROR_DELETE_PROTECTED: + case ERROR_READ_PROTECTED: + case ERROR_WRITE_PROTECTED: + return EACCES; + case ERROR_DISK_NOT_VALIDATED: + case ERROR_OBJECT_IN_USE: + return EBUSY; + case ERROR_OBJECT_EXISTS: + return EEXIST; + case ERROR_DIR_NOT_FOUND: + case ERROR_NO_MORE_ENTRIES: + case ERROR_OBJECT_NOT_FOUND: + return ENOENT; + case ERROR_NO_FREE_STORE: + return ENOMEM; + case ERROR_DISK_FULL: + return ENOSPC; + case ERROR_DIRECTORY_NOT_EMPTY: + return ENOTEMPTY; + case ERROR_DISK_WRITE_PROTECTED: + return EROFS; + case ERROR_RENAME_ACROSS_DEVICES: + return EXDEV; + default: + return EIO; + } +} +#endif + +static int +statWrapper(OFString *path, Stat *buffer) +{ +#if defined(OF_WINDOWS) + WIN32_FILE_ATTRIBUTE_DATA data; + bool success; + + if ([OFSystemInfo isWindowsNT]) + success = GetFileAttributesExW(path.UTF16String, + GetFileExInfoStandard, &data); + else + success = GetFileAttributesExA( + [path cStringWithEncoding: [OFLocale encoding]], + GetFileExInfoStandard, &data); + + if (!success) + return lastError(); + + buffer->st_size = (uint64_t)data.nFileSizeHigh << 32 | + data.nFileSizeLow; + + if (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + buffer->st_mode = S_IFDIR; + else if (data.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) { + /* + * No need to use A functions in this branch: This is only + * available on NTFS (and hence Windows NT) anyway. + */ + WIN32_FIND_DATAW findData; + HANDLE findHandle; + + if ((findHandle = FindFirstFileW(path.UTF16String, + &findData)) == INVALID_HANDLE_VALUE) + return lastError(); + + @try { + if (!(findData.dwFileAttributes & + FILE_ATTRIBUTE_REPARSE_POINT)) + /* Race? Indicate to try again. */ + return EAGAIN; + + buffer->st_mode = + (findData.dwReserved0 == IO_REPARSE_TAG_SYMLINK + ? S_IFLNK : S_IFREG); + } @finally { + FindClose(findHandle); + } + } else + buffer->st_mode = S_IFREG; + + buffer->st_mode |= (data.dwFileAttributes & FILE_ATTRIBUTE_READONLY + ? (S_IRUSR | S_IXUSR) : (S_IRUSR | S_IWUSR | S_IXUSR)); + + buffer->st_atime = filetimeToTimeInterval(&data.ftLastAccessTime); + buffer->st_mtime = filetimeToTimeInterval(&data.ftLastWriteTime); + buffer->st_ctime = buffer->st_birthtime = + filetimeToTimeInterval(&data.ftCreationTime); + buffer->fileAttributes = data.dwFileAttributes; + + return 0; +#elif defined(OF_AMIGAOS) + BPTR lock; +# ifdef OF_AMIGAOS4 + struct ExamineData *ed; +# else + struct FileInfoBlock fib; +# endif + OFTimeInterval timeInterval; + struct Locale *locale; + struct DateStamp *date; + + if ((lock = Lock([path cStringWithEncoding: [OFLocale encoding]], + SHARED_LOCK)) == 0) + return lastError(); + +# if defined(OF_MORPHOS) + if (!Examine64(lock, &fib, TAG_DONE)) { +# elif defined(OF_AMIGAOS4) + if ((ed = ExamineObjectTags(EX_FileLockInput, lock, TAG_END)) == NULL) { +# else + if (!Examine(lock, &fib)) { +# endif + int error = lastError(); + UnLock(lock); + return error; + } + + UnLock(lock); + +# if defined(OF_MORPHOS) + buffer->st_size = fib.fib_Size64; +# elif defined(OF_AMIGAOS4) + buffer->st_size = ed->FileSize; +# else + buffer->st_size = fib.fib_Size; +# endif +# ifdef OF_AMIGAOS4 + buffer->st_mode = (EXD_IS_DIRECTORY(ed) ? S_IFDIR : S_IFREG); +# else + buffer->st_mode = (fib.fib_DirEntryType > 0 ? S_IFDIR : S_IFREG); +# endif + + timeInterval = 252460800; /* 1978-01-01 */ + + locale = OpenLocale(NULL); + /* + * FIXME: This does not take DST into account. But unfortunately, there + * is no way to figure out if DST was in effect when the file was + * modified. + */ + timeInterval += locale->loc_GMTOffset * 60.0; + CloseLocale(locale); + +# ifdef OF_AMIGAOS4 + date = &ed->Date; +# else + date = &fib.fib_Date; +# endif + timeInterval += date->ds_Days * 86400.0; + timeInterval += date->ds_Minute * 60.0; + timeInterval += date->ds_Tick / (OFTimeInterval)TICKS_PER_SECOND; + + buffer->st_atime = buffer->st_mtime = buffer->st_ctime = timeInterval; + +# ifdef OF_AMIGAOS4 + FreeDosObject(DOS_EXAMINEDATA, ed); +# endif + + return 0; +#elif defined(HAVE_STAT64) + if (stat64([path cStringWithEncoding: [OFLocale encoding]], + buffer) != 0) + return errno; + + return 0; +#else + if (stat([path cStringWithEncoding: [OFLocale encoding]], buffer) != 0) + return errno; + + return 0; +#endif +} + +static int +lstatWrapper(OFString *path, Stat *buffer) +{ +#if defined(HAVE_LSTAT) && !defined(OF_WINDOWS) && !defined(OF_AMIGAOS) && \ + !defined(OF_NINTENDO_3DS) && !defined(OF_WII) +# ifdef HAVE_LSTAT64 + if (lstat64([path cStringWithEncoding: [OFLocale encoding]], + buffer) != 0) + return errno; +# else + if (lstat([path cStringWithEncoding: [OFLocale encoding]], buffer) != 0) + return errno; +# endif + + return 0; +#else + return statWrapper(path, buffer); +#endif +} + +static void +setTypeAttribute(OFMutableFileAttributes attributes, Stat *s) +{ + if (S_ISREG(s->st_mode)) + [attributes setObject: OFFileTypeRegular forKey: OFFileType]; + else if (S_ISDIR(s->st_mode)) + [attributes setObject: OFFileTypeDirectory forKey: OFFileType]; +#ifdef S_ISLNK + else if (S_ISLNK(s->st_mode)) + [attributes setObject: OFFileTypeSymbolicLink + forKey: OFFileType]; +#endif +#ifdef S_ISFIFO + else if (S_ISFIFO(s->st_mode)) + [attributes setObject: OFFileTypeFIFO forKey: OFFileType]; +#endif +#ifdef S_ISCHR + else if (S_ISCHR(s->st_mode)) + [attributes setObject: OFFileTypeCharacterSpecial + forKey: OFFileType]; +#endif +#ifdef S_ISBLK + else if (S_ISBLK(s->st_mode)) + [attributes setObject: OFFileTypeBlockSpecial + forKey: OFFileType]; +#endif +#ifdef S_ISSOCK + else if (S_ISSOCK(s->st_mode)) + [attributes setObject: OFFileTypeSocket forKey: OFFileType]; +#endif + else + [attributes setObject: OFFileTypeUnknown forKey: OFFileType]; +} + +static void +setDateAttributes(OFMutableFileAttributes attributes, Stat *s) +{ + /* FIXME: We could be more precise on some OSes */ + [attributes + setObject: [OFDate dateWithTimeIntervalSince1970: s->st_atime] + forKey: OFFileLastAccessDate]; + [attributes + setObject: [OFDate dateWithTimeIntervalSince1970: s->st_mtime] + forKey: OFFileModificationDate]; + [attributes + setObject: [OFDate dateWithTimeIntervalSince1970: s->st_ctime] + forKey: OFFileStatusChangeDate]; +#ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME + [attributes + setObject: [OFDate dateWithTimeIntervalSince1970: s->st_birthtime] + forKey: OFFileCreationDate]; +#endif +} + +static void +setOwnerAndGroupAttributes(OFMutableFileAttributes attributes, Stat *s) +{ +#ifdef OF_FILE_MANAGER_SUPPORTS_OWNER + [attributes setObject: [NSNumber numberWithUnsignedLong: s->st_uid] + forKey: OFFileOwnerAccountID]; + [attributes setObject: [NSNumber numberWithUnsignedLong: s->st_gid] + forKey: OFFileGroupOwnerAccountID]; + +# ifdef OF_HAVE_THREADS + [passwdMutex lock]; + @try { +# endif + OFStringEncoding encoding = [OFLocale encoding]; + struct passwd *passwd = getpwuid(s->st_uid); + struct group *group_ = getgrgid(s->st_gid); + + if (passwd != NULL) { + OFString *owner = [OFString + stringWithCString: passwd->pw_name + encoding: encoding]; + + [attributes setObject: owner + forKey: OFFileOwnerAccountName]; + } + + if (group_ != NULL) { + OFString *group = [OFString + stringWithCString: group_->gr_name + encoding: encoding]; + + [attributes setObject: group + forKey: OFFileGroupOwnerAccountName]; + } +# ifdef OF_HAVE_THREADS + } @finally { + [passwdMutex unlock]; + } +# endif +#endif +} + +#ifdef OF_FILE_MANAGER_SUPPORTS_SYMLINKS +static void +setSymbolicLinkDestinationAttribute(OFMutableFileAttributes attributes, + OFIRI *IRI) +{ + OFString *path = IRI.fileSystemRepresentation; +# ifdef OF_WINDOWS + HANDLE handle; + OFString *destination; + + if (createSymbolicLinkWFuncPtr == NULL) + return; + + if ((handle = CreateFileW(path.UTF16String, 0, (FILE_SHARE_READ | + FILE_SHARE_WRITE), NULL, OPEN_EXISTING, + FILE_FLAG_OPEN_REPARSE_POINT, NULL)) == INVALID_HANDLE_VALUE) + @throw [OFGetItemAttributesFailedException + exceptionWithIRI: IRI + errNo: lastError()]; + + @try { + union { + char bytes[MAXIMUM_REPARSE_DATA_BUFFER_SIZE]; + REPARSE_DATA_BUFFER data; + } buffer; + DWORD size; + wchar_t *tmp; + + if (!DeviceIoControl(handle, FSCTL_GET_REPARSE_POINT, NULL, 0, + buffer.bytes, MAXIMUM_REPARSE_DATA_BUFFER_SIZE, &size, + NULL)) + @throw [OFGetItemAttributesFailedException + exceptionWithIRI: IRI + errNo: lastError()]; + + if (buffer.data.ReparseTag != IO_REPARSE_TAG_SYMLINK) + @throw [OFGetItemAttributesFailedException + exceptionWithIRI: IRI + errNo: lastError()]; + +# define slrb buffer.data.SymbolicLinkReparseBuffer + tmp = slrb.PathBuffer + + (slrb.SubstituteNameOffset / sizeof(wchar_t)); + + destination = [OFString + stringWithUTF16String: tmp + length: slrb.SubstituteNameLength / + sizeof(wchar_t)]; + + [attributes setObject: OFFileTypeSymbolicLink + forKey: OFFileType]; + [attributes setObject: destination + forKey: OFFileSymbolicLinkDestination]; +# undef slrb + } @finally { + CloseHandle(handle); + } +# elif defined(OF_HURD) + OFStringEncoding encoding = [OFLocale encoding]; + int fd; + OFMutableData *destinationData; + OFString *destination; + + fd = open([path cStringWithEncoding: encoding], O_RDONLY | O_NOLINK); + if (fd == -1) + @throw [OFGetItemAttributesFailedException + exceptionWithIRI: IRI + errNo: errno]; + + @try { + char buffer[512]; + ssize_t length; + + destinationData = [OFMutableData data]; + while ((length = read(fd, buffer, 512)) > 0) + [destinationData addItems: buffer count: length]; + } @finally { + close(fd); + } + + destination = [OFString stringWithCString: destinationData.items + encoding: encoding + length: destinationData.count]; + + [attributes setObject: destination + forKey: OFFileSymbolicLinkDestination]; +# else + OFStringEncoding encoding = [OFLocale encoding]; + char destinationC[PATH_MAX]; + ssize_t length; + OFString *destination; + + length = readlink([path cStringWithEncoding: encoding], destinationC, + PATH_MAX); + + if (length < 0) + @throw [OFGetItemAttributesFailedException + exceptionWithIRI: IRI + errNo: errno]; + + destination = [OFString stringWithCString: destinationC + encoding: encoding + length: length]; + + [attributes setObject: destination + forKey: OFFileSymbolicLinkDestination]; +# endif +} +#endif + +#ifdef OF_FILE_MANAGER_SUPPORTS_EXTENDED_ATTRIBUTES +static void +setExtendedAttributes(OFMutableFileAttributes attributes, OFIRI *IRI) +{ + OFString *path = IRI.fileSystemRepresentation; + OFStringEncoding encoding = [OFLocale encoding]; + const char *cPath = [path cStringWithEncoding: encoding]; +# if defined(OF_LINUX) + ssize_t size = llistxattr(cPath, NULL, 0); +# elif defined(OF_MACOS) + ssize_t size = listxattr(cPath, NULL, 0, XATTR_NOFOLLOW); +# endif + char *list = OFAllocMemory(1, size); + OFMutableArray *names = nil; + + @try { + char *name; + +# if defined(OF_LINUX) + if ((size = llistxattr(cPath, list, size)) < 0) +# elif defined(OF_MACOS) + if ((size = listxattr(cPath, list, size, XATTR_NOFOLLOW)) < 0) +# endif + return; + + names = [OFMutableArray array]; + name = list; + + while (size > 0) { + size_t length = strlen(name); + + [names addObject: [OFString stringWithCString: name + encoding: encoding + length: length]]; + + name += length + 1; + size -= length + 1; + } + } @finally { + OFFreeMemory(list); + } + + [attributes setObject: names forKey: OFFileExtendedAttributesNames]; +} +#endif + +@implementation OFFileIRIHandler ++ (void)initialize +{ +#ifdef OF_WINDOWS + HMODULE module; +#endif + + if (self != [OFFileIRIHandler class]) + return; + +#if defined(OF_FILE_MANAGER_SUPPORTS_OWNER) && defined(OF_HAVE_THREADS) + passwdMutex = [[OFMutex alloc] init]; + atexit(releasePasswdMutex); +#endif +#if !defined(HAVE_READDIR_R) && !defined(OF_WINDOWS) && defined(OF_HAVE_THREADS) + readdirMutex = [[OFMutex alloc] init]; + atexit(releaseReaddirMutex); +#endif + +#ifdef OF_WINDOWS + if ((module = GetModuleHandle("msvcrt.dll")) != NULL) + _wutime64FuncPtr = (int (*)(const wchar_t *, + struct __utimbuf64 *))GetProcAddress(module, "_wutime64"); + + if ((module = GetModuleHandleA("kernel32.dll")) != NULL) { + createSymbolicLinkWFuncPtr = + (WINAPI BOOLEAN (*)(LPCWSTR, LPCWSTR, DWORD)) + GetProcAddress(module, "CreateSymbolicLinkW"); + createHardLinkWFuncPtr = + (WINAPI BOOLEAN (*)(LPCWSTR, LPCWSTR, + LPSECURITY_ATTRIBUTES)) + GetProcAddress(module, "CreateHardLinkW"); + } +#endif + + /* + * Make sure OFFile is initialized. + * On some systems, this is needed to initialize the file system driver. + */ + [OFFile class]; +} + ++ (bool)of_directoryExistsAtPath: (OFString *)path +{ + Stat s; + + if (statWrapper(path, &s) != 0) + return false; + + return S_ISDIR(s.st_mode); +} + +- (OFStream *)openItemAtIRI: (OFIRI *)IRI mode: (OFString *)mode +{ + void *pool = objc_autoreleasePoolPush(); + OFFile *file = [[OFFile alloc] + initWithPath: IRI.fileSystemRepresentation + mode: mode]; + + objc_autoreleasePoolPop(pool); + + return [file autorelease]; +} + +- (OFFileAttributes)attributesOfItemAtIRI: (OFIRI *)IRI +{ + OFMutableFileAttributes ret = [OFMutableDictionary dictionary]; + void *pool = objc_autoreleasePoolPush(); + OFString *path; + int error; + Stat s; + + if (IRI == nil) + @throw [OFInvalidArgumentException exception]; + + if (![[IRI scheme] isEqual: _scheme]) + @throw [OFInvalidArgumentException exception]; + + path = IRI.fileSystemRepresentation; + + if ((error = lstatWrapper(path, &s)) != 0) + @throw [OFGetItemAttributesFailedException + exceptionWithIRI: IRI + errNo: error]; + + if (s.st_size < 0) + @throw [OFOutOfRangeException exception]; + + [ret setObject: [NSNumber numberWithUnsignedLongLong: s.st_size] + forKey: OFFileSize]; + + setTypeAttribute(ret, &s); + + [ret setObject: [NSNumber numberWithUnsignedLong: s.st_mode] + forKey: OFFilePOSIXPermissions]; + + setOwnerAndGroupAttributes(ret, &s); + setDateAttributes(ret, &s); + +#ifdef OF_FILE_MANAGER_SUPPORTS_SYMLINKS + if (S_ISLNK(s.st_mode)) + setSymbolicLinkDestinationAttribute(ret, IRI); +#endif + +#ifdef OF_FILE_MANAGER_SUPPORTS_EXTENDED_ATTRIBUTES + setExtendedAttributes(ret, IRI); +#endif + + objc_autoreleasePoolPop(pool); + + return ret; +} + +- (void)of_setLastAccessDate: (OFDate *)lastAccessDate + andModificationDate: (OFDate *)modificationDate + ofItemAtIRI: (OFIRI *)IRI + attributes: (OFFileAttributes)attributes OF_DIRECT +{ + OFString *path = IRI.fileSystemRepresentation; + OFFileAttributeKey attributeKey = (modificationDate != nil + ? OFFileModificationDate : OFFileLastAccessDate); + + if (lastAccessDate == nil) + lastAccessDate = modificationDate; + if (modificationDate == nil) + modificationDate = lastAccessDate; + +#if defined(OF_WINDOWS) + if (_wutime64FuncPtr != NULL) { + struct __utimbuf64 times = { + .actime = + (__time64_t)lastAccessDate.timeIntervalSince1970, + .modtime = + (__time64_t)modificationDate.timeIntervalSince1970 + }; + + if (_wutime64FuncPtr([path UTF16String], ×) != 0) { + int errNo = errno; + + if (errNo == EACCES && [self directoryExistsAtIRI: IRI]) + errNo = EISDIR; + + @throw [OFSetItemAttributesFailedException + exceptionWithIRI: IRI + attributes: attributes + failedAttribute: attributeKey + errNo: errNo]; + } + } else { + struct _utimbuf times = { + .actime = (time_t)lastAccessDate.timeIntervalSince1970, + .modtime = + (time_t)modificationDate.timeIntervalSince1970 + }; + int status; + + if ([OFSystemInfo isWindowsNT]) + status = _wutime([path UTF16String], ×); + else + status = _utime( + [path cStringWithEncoding: [OFLocale encoding]], + ×); + + if (status != 0) { + int errNo = errno; + + if (errNo == EACCES && [self directoryExistsAtIRI: IRI]) + errNo = EISDIR; + + @throw [OFSetItemAttributesFailedException + exceptionWithIRI: IRI + attributes: attributes + failedAttribute: attributeKey + errNo: errNo]; + } + } +#elif defined(OF_AMIGAOS) + /* AmigaOS does not support access time. */ + OFTimeInterval modificationTime = + modificationDate.timeIntervalSince1970; + struct Locale *locale; + struct DateStamp date; + + modificationTime -= 252460800; /* 1978-01-01 */ + + if (modificationTime < 0) + @throw [OFOutOfRangeException exception]; + + locale = OpenLocale(NULL); + /* + * FIXME: This does not take DST into account. But unfortunately, there + * is no way to figure out if DST should be in effect for the + * timestamp. + */ + modificationTime -= locale->loc_GMTOffset * 60.0; + CloseLocale(locale); + + date.ds_Days = modificationTime / 86400; + date.ds_Minute = ((LONG)modificationTime % 86400) / 60; + date.ds_Tick = fmod(modificationTime, 60) * TICKS_PER_SECOND; + +# ifdef OF_AMIGAOS4 + if (!SetDate([path cStringWithEncoding: [OFLocale encoding]], + &date) != 0) +# else + if (!SetFileDate([path cStringWithEncoding: [OFLocale encoding]], + &date) != 0) +# endif + @throw [OFSetItemAttributesFailedException + exceptionWithIRI: IRI + attributes: attributes + failedAttribute: attributeKey + errNo: lastError()]; +#else + OFTimeInterval lastAccessTime = lastAccessDate.timeIntervalSince1970; + OFTimeInterval modificationTime = + modificationDate.timeIntervalSince1970; + struct timeval times[2] = { + { + .tv_sec = (time_t)lastAccessTime, + .tv_usec = (int)((lastAccessTime - + (time_t)lastAccessTime) * 1000000) + }, + { + .tv_sec = (time_t)modificationTime, + .tv_usec = (int)((modificationTime - + (time_t)modificationTime) * 1000000) + }, + }; + + if (utimes([path cStringWithEncoding: [OFLocale encoding]], times) != 0) + @throw [OFSetItemAttributesFailedException + exceptionWithIRI: IRI + attributes: attributes + failedAttribute: attributeKey + errNo: errno]; +#endif +} + +- (void)of_setPOSIXPermissions: (OFNumber *)permissions + ofItemAtIRI: (OFIRI *)IRI + attributes: (OFFileAttributes)attributes OF_DIRECT +{ +#ifdef OF_FILE_MANAGER_SUPPORTS_PERMISSIONS + mode_t mode = (mode_t)permissions.unsignedLongValue; + OFString *path = IRI.fileSystemRepresentation; + int status; + +# ifdef OF_WINDOWS + if ([OFSystemInfo isWindowsNT]) + status = _wchmod(path.UTF16String, mode); + else +# endif + status = chmod( + [path cStringWithEncoding: [OFLocale encoding]], mode); + + if (status != 0) + @throw [OFSetItemAttributesFailedException + exceptionWithIRI: IRI + attributes: attributes + failedAttribute: OFFilePOSIXPermissions + errNo: errno]; +#else + OF_UNRECOGNIZED_SELECTOR +#endif +} + +- (void)of_setOwnerAccountName: (OFString *)owner + andGroupOwnerAccountName: (OFString *)group + ofItemAtIRI: (OFIRI *)IRI + attributeKey: (OFFileAttributeKey)attributeKey + attributes: (OFFileAttributes)attributes OF_DIRECT +{ +#ifdef OF_FILE_MANAGER_SUPPORTS_OWNER + OFString *path = IRI.fileSystemRepresentation; + uid_t uid = -1; + gid_t gid = -1; + OFStringEncoding encoding; + + if (owner == nil && group == nil) + @throw [OFInvalidArgumentException exception]; + + encoding = [OFLocale encoding]; + +# ifdef OF_HAVE_THREADS + [passwdMutex lock]; + @try { +# endif + if (owner != nil) { + struct passwd *passwd; + + if ((passwd = getpwnam([owner + cStringWithEncoding: encoding])) == NULL) + @throw [OFSetItemAttributesFailedException + exceptionWithIRI: IRI + attributes: attributes + failedAttribute: attributeKey + errNo: errno]; + + uid = passwd->pw_uid; + } + + if (group != nil) { + struct group *group_; + + if ((group_ = getgrnam([group + cStringWithEncoding: encoding])) == NULL) + @throw [OFSetItemAttributesFailedException + exceptionWithIRI: IRI + attributes: attributes + failedAttribute: attributeKey + errNo: errno]; + + gid = group_->gr_gid; + } +# ifdef OF_HAVE_THREADS + } @finally { + [passwdMutex unlock]; + } +# endif + + if (chown([path cStringWithEncoding: encoding], uid, gid) != 0) + @throw [OFSetItemAttributesFailedException + exceptionWithIRI: IRI + attributes: attributes + failedAttribute: attributeKey + errNo: errno]; +#else + OF_UNRECOGNIZED_SELECTOR +#endif +} + +- (void)setAttributes: (OFFileAttributes)attributes ofItemAtIRI: (OFIRI *)IRI +{ + void *pool = objc_autoreleasePoolPush(); + OFEnumerator OF_GENERIC(OFFileAttributeKey) *keyEnumerator; + OFEnumerator *objectEnumerator; + OFFileAttributeKey key; + id object; + OFDate *lastAccessDate, *modificationDate; + + if (IRI == nil) + @throw [OFInvalidArgumentException exception]; + + if (![IRI.scheme isEqual: _scheme]) + @throw [OFInvalidArgumentException exception]; + + keyEnumerator = [attributes keyEnumerator]; + objectEnumerator = [attributes objectEnumerator]; + + while ((key = [keyEnumerator nextObject]) != nil && + (object = [objectEnumerator nextObject]) != nil) { + if ([key isEqual: OFFileModificationDate] || + [key isEqual: OFFileLastAccessDate]) + continue; + else if ([key isEqual: OFFilePOSIXPermissions]) + [self of_setPOSIXPermissions: object + ofItemAtIRI: IRI + attributes: attributes]; + else if ([key isEqual: OFFileOwnerAccountName]) + [self of_setOwnerAccountName: object + andGroupOwnerAccountName: nil + ofItemAtIRI: IRI + attributeKey: key + attributes: attributes]; + else if ([key isEqual: OFFileGroupOwnerAccountName]) + [self of_setOwnerAccountName: nil + andGroupOwnerAccountName: object + ofItemAtIRI: IRI + attributeKey: key + attributes: attributes]; + else + @throw [OFNotImplementedException + exceptionWithSelector: _cmd + object: self]; + } + + lastAccessDate = [attributes objectForKey: OFFileLastAccessDate]; + modificationDate = [attributes objectForKey: OFFileModificationDate]; + + if (lastAccessDate != nil || modificationDate != nil) + [self of_setLastAccessDate: lastAccessDate + andModificationDate: modificationDate + ofItemAtIRI: IRI + attributes: attributes]; + + objc_autoreleasePoolPop(pool); +} + +- (bool)fileExistsAtIRI: (OFIRI *)IRI +{ + void *pool = objc_autoreleasePoolPush(); + Stat s; + bool ret; + + if (IRI == nil) + @throw [OFInvalidArgumentException exception]; + + if (![IRI.scheme isEqual: _scheme]) + @throw [OFInvalidArgumentException exception]; + + ret = (statWrapper(IRI.fileSystemRepresentation, &s) == 0); + + objc_autoreleasePoolPop(pool); + + return ret; +} + +- (bool)directoryExistsAtIRI: (OFIRI *)IRI +{ + void *pool = objc_autoreleasePoolPush(); + Stat s; + bool ret; + + if (IRI == nil) + @throw [OFInvalidArgumentException exception]; + + if (![IRI.scheme isEqual: _scheme]) + @throw [OFInvalidArgumentException exception]; + + if (statWrapper(IRI.fileSystemRepresentation, &s) != 0) { + objc_autoreleasePoolPop(pool); + return false; + } + + ret = S_ISDIR(s.st_mode); + + objc_autoreleasePoolPop(pool); + + return ret; +} + +- (void)createDirectoryAtIRI: (OFIRI *)IRI +{ + void *pool = objc_autoreleasePoolPush(); + OFString *path; + + if (IRI == nil) + @throw [OFInvalidArgumentException exception]; + + if (![IRI.scheme isEqual: _scheme]) + @throw [OFInvalidArgumentException exception]; + + path = IRI.fileSystemRepresentation; + +#if defined(OF_WINDOWS) + int status; + + if ([OFSystemInfo isWindowsNT]) + status = _wmkdir(path.UTF16String); + else + status = _mkdir( + [path cStringWithEncoding: [OFLocale encoding]]); + + if (status != 0) + @throw [OFCreateDirectoryFailedException + exceptionWithIRI: IRI + errNo: errno]; +#elif defined(OF_AMIGAOS) + BPTR lock; + + if ((lock = CreateDir( + [path cStringWithEncoding: [OFLocale encoding]])) == 0) + @throw [OFCreateDirectoryFailedException + exceptionWithIRI: IRI + errNo: lastError()]; + + UnLock(lock); +#else + if (mkdir([path cStringWithEncoding: [OFLocale encoding]], 0777) != 0) + @throw [OFCreateDirectoryFailedException + exceptionWithIRI: IRI + errNo: errno]; +#endif + + objc_autoreleasePoolPop(pool); +} + +- (OFArray OF_GENERIC(OFIRI *) *)contentsOfDirectoryAtIRI: (OFIRI *)IRI +{ + OFMutableArray *IRIs = [OFMutableArray array]; + void *pool = objc_autoreleasePoolPush(); + OFString *path; + + if (IRI == nil) + @throw [OFInvalidArgumentException exception]; + + if (![IRI.scheme isEqual: _scheme]) + @throw [OFInvalidArgumentException exception]; + + path = IRI.fileSystemRepresentation; + +#if defined(OF_WINDOWS) + HANDLE handle; + + path = [path stringByAppendingString: @"\\*"]; + + if ([OFSystemInfo isWindowsNT]) { + WIN32_FIND_DATAW fd; + + if ((handle = FindFirstFileW(path.UTF16String, + &fd)) == INVALID_HANDLE_VALUE) + @throw [OFOpenItemFailedException + exceptionWithIRI: IRI + mode: nil + errNo: lastError()]; + + @try { + do { + OFString *file; + + if (wcscmp(fd.cFileName, L".") == 0 || + wcscmp(fd.cFileName, L"..") == 0) + continue; + + file = [[OFString alloc] + initWithUTF16String: fd.cFileName]; + @try { + [IRIs addObject: [IRI + IRIByAppendingPathComponent: file]]; + } @finally { + [file release]; + } + } while (FindNextFileW(handle, &fd)); + + if (GetLastError() != ERROR_NO_MORE_FILES) + @throw [OFReadFailedException + exceptionWithObject: self + requestedLength: 0 + errNo: lastError()]; + } @finally { + FindClose(handle); + } + } else { + OFStringEncoding encoding = [OFLocale encoding]; + WIN32_FIND_DATA fd; + + if ((handle = FindFirstFileA( + [path cStringWithEncoding: encoding], &fd)) == + INVALID_HANDLE_VALUE) + @throw [OFOpenItemFailedException + exceptionWithIRI: IRI + mode: nil + errNo: lastError()]; + + @try { + do { + OFString *file; + + if (strcmp(fd.cFileName, ".") == 0 || + strcmp(fd.cFileName, "..") == 0) + continue; + + file = [[OFString alloc] + initWithCString: fd.cFileName + encoding: encoding]; + @try { + [IRIs addObject: [IRI + IRIByAppendingPathComponent: file]]; + } @finally { + [file release]; + } + } while (FindNextFileA(handle, &fd)); + + if (GetLastError() != ERROR_NO_MORE_FILES) + @throw [OFReadFailedException + exceptionWithObject: self + requestedLength: 0 + errNo: lastError()]; + } @finally { + FindClose(handle); + } + } +#elif defined(OF_AMIGAOS) + OFStringEncoding encoding = [OFLocale encoding]; + BPTR lock; + + if ((lock = Lock([path cStringWithEncoding: encoding], + SHARED_LOCK)) == 0) + @throw [OFOpenItemFailedException + exceptionWithIRI: IRI + mode: nil + errNo: lastError()]; + + @try { +# ifdef OF_AMIGAOS4 + struct ExamineData *ed; + APTR context; + + if ((context = ObtainDirContextTags(EX_FileLockInput, lock, + EX_DoCurrentDir, TRUE, EX_DataFields, EXF_NAME, + TAG_END)) == NULL) + @throw [OFOpenItemFailedException + exceptionWithIRI: IRI + mode: nil + errNo: lastError()]; + + @try { + while ((ed = ExamineDir(context)) != NULL) { + OFString *file = [[OFString alloc] + initWithCString: ed->Name + encoding: encoding]; + + @try { + [IRIs addObject: [IRI + IRIByAppendingPathComponent: file]]; + } @finally { + [file release]; + } + } + } @finally { + ReleaseDirContext(context); + } +# else + struct FileInfoBlock fib; + + if (!Examine(lock, &fib)) + @throw [OFOpenItemFailedException + exceptionWithIRI: IRI + mode: nil + errNo: lastError()]; + + while (ExNext(lock, &fib)) { + OFString *file = [[OFString alloc] + initWithCString: fib.fib_FileName + encoding: encoding]; + @try { + [IRIs addObject: + [IRI IRIByAppendingPathComponent: file]]; + } @finally { + [file release]; + } + } +# endif + + if (IoErr() != ERROR_NO_MORE_ENTRIES) + @throw [OFReadFailedException + exceptionWithObject: self + requestedLength: 0 + errNo: lastError()]; + } @finally { + UnLock(lock); + } +#else + OFStringEncoding encoding = [OFLocale encoding]; + DIR *dir; + if ((dir = opendir([path cStringWithEncoding: encoding])) == NULL) + @throw [OFOpenItemFailedException exceptionWithIRI: IRI + mode: nil + errNo: errno]; + +# if !defined(HAVE_READDIR_R) && defined(OF_HAVE_THREADS) + @try { + [readdirMutex lock]; + } @catch (id e) { + closedir(dir); + @throw e; + } +# endif + + @try { + for (;;) { + struct dirent *dirent; +# ifdef HAVE_READDIR_R + struct dirent buffer; +# endif + OFString *file; + +# ifdef HAVE_READDIR_R + if (readdir_r(dir, &buffer, &dirent) != 0) + @throw [OFReadFailedException + exceptionWithObject: self + requestedLength: 0 + errNo: errno]; + + if (dirent == NULL) + break; +# else + errno = 0; + if ((dirent = readdir(dir)) == NULL) { + if (errno == 0) + break; + else + @throw [OFReadFailedException + exceptionWithObject: self + requestedLength: 0 + errNo: errno]; + } +# endif + + if (strcmp(dirent->d_name, ".") == 0 || + strcmp(dirent->d_name, "..") == 0) + continue; + + file = [[OFString alloc] initWithCString: dirent->d_name + encoding: encoding]; + @try { + [IRIs addObject: + [IRI IRIByAppendingPathComponent: file]]; + } @finally { + [file release]; + } + } + } @finally { + closedir(dir); +# if !defined(HAVE_READDIR_R) && defined(OF_HAVE_THREADS) + [readdirMutex unlock]; +# endif + } +#endif + + [IRIs makeImmutable]; + + objc_autoreleasePoolPop(pool); + + return IRIs; +} + +- (void)removeItemAtIRI: (OFIRI *)IRI +{ + void *pool = objc_autoreleasePoolPush(); + OFString *path; + int error; + Stat s; + + if (IRI == nil) + @throw [OFInvalidArgumentException exception]; + + if (![IRI.scheme isEqual: _scheme]) + @throw [OFInvalidArgumentException exception]; + + path = IRI.fileSystemRepresentation; + + if ((error = lstatWrapper(path, &s)) != 0) + @throw [OFRemoveItemFailedException exceptionWithIRI: IRI + errNo: error]; + + if (S_ISDIR(s.st_mode)) { + OFArray OF_GENERIC(OFIRI *) *contents; + + @try { + contents = [self contentsOfDirectoryAtIRI: IRI]; + } @catch (id e) { + /* + * Only convert exceptions to + * OFRemoveItemFailedException that have an errNo + * property. This covers all I/O related exceptions + * from the operations used to remove an item, all + * others should be left as is. + */ + if ([e respondsToSelector: @selector(errNo)]) + @throw [OFRemoveItemFailedException + exceptionWithIRI: IRI + errNo: [e errNo]]; + + @throw e; + } + + for (OFIRI *item in contents) { + void *pool2 = objc_autoreleasePoolPush(); + + [self removeItemAtIRI: item]; + + objc_autoreleasePoolPop(pool2); + } + +#ifndef OF_AMIGAOS + int status; + +# ifdef OF_WINDOWS + if ([OFSystemInfo isWindowsNT]) + status = _wrmdir(path.UTF16String); + else +# endif + status = rmdir( + [path cStringWithEncoding: [OFLocale encoding]]); + + if (status != 0) + @throw [OFRemoveItemFailedException + exceptionWithIRI: IRI + errNo: errno]; + } else { + int status; + +# ifdef OF_WINDOWS + if ([OFSystemInfo isWindowsNT]) + status = _wunlink(path.UTF16String); + else +# endif + status = unlink( + [path cStringWithEncoding: [OFLocale encoding]]); + + if (status != 0) + @throw [OFRemoveItemFailedException + exceptionWithIRI: IRI + errNo: errno]; +#endif + } + +#ifdef OF_AMIGAOS + if (!DeleteFile([path cStringWithEncoding: [OFLocale encoding]])) + @throw [OFRemoveItemFailedException + exceptionWithIRI: IRI + errNo: lastError()]; +#endif + + objc_autoreleasePoolPop(pool); +} + +#ifdef OF_FILE_MANAGER_SUPPORTS_LINKS +- (void)linkItemAtIRI: (OFIRI *)source toIRI: (OFIRI *)destination +{ + void *pool = objc_autoreleasePoolPush(); + OFString *sourcePath, *destinationPath; + + if (source == nil || destination == nil) + @throw [OFInvalidArgumentException exception]; + + if (![source.scheme isEqual: _scheme] || + ![destination.scheme isEqual: _scheme]) + @throw [OFInvalidArgumentException exception]; + + sourcePath = source.fileSystemRepresentation; + destinationPath = destination.fileSystemRepresentation; + +# ifndef OF_WINDOWS + OFStringEncoding encoding = [OFLocale encoding]; + + if (link([sourcePath cStringWithEncoding: encoding], + [destinationPath cStringWithEncoding: encoding]) != 0) + @throw [OFLinkItemFailedException + exceptionWithSourceIRI: source + destinationIRI: destination + errNo: errno]; +# else + if (createHardLinkWFuncPtr == NULL) + @throw [OFNotImplementedException exceptionWithSelector: _cmd + object: self]; + + if (!createHardLinkWFuncPtr(destinationPath.UTF16String, + sourcePath.UTF16String, NULL)) + @throw [OFLinkItemFailedException + exceptionWithSourceIRI: source + destinationIRI: destination + errNo: lastError()]; +# endif + + objc_autoreleasePoolPop(pool); +} +#endif + +#ifdef OF_FILE_MANAGER_SUPPORTS_SYMLINKS +- (void)createSymbolicLinkAtIRI: (OFIRI *)IRI + withDestinationPath: (OFString *)target +{ + void *pool = objc_autoreleasePoolPush(); + OFString *path; + + if (IRI == nil || target == nil) + @throw [OFInvalidArgumentException exception]; + + if (![IRI.scheme isEqual: _scheme]) + @throw [OFInvalidArgumentException exception]; + + path = IRI.fileSystemRepresentation; + +# ifndef OF_WINDOWS + OFStringEncoding encoding = [OFLocale encoding]; + + if (symlink([target cStringWithEncoding: encoding], + [path cStringWithEncoding: encoding]) != 0) + @throw [OFCreateSymbolicLinkFailedException + exceptionWithIRI: IRI + target: target + errNo: errno]; +# else + if (createSymbolicLinkWFuncPtr == NULL) + @throw [OFNotImplementedException exceptionWithSelector: _cmd + object: self]; + + if (!createSymbolicLinkWFuncPtr(path.UTF16String, target.UTF16String, + 0)) + @throw [OFCreateSymbolicLinkFailedException + exceptionWithIRI: IRI + target: target + errNo: lastError()]; +# endif + + objc_autoreleasePoolPop(pool); +} +#endif + +- (bool)moveItemAtIRI: (OFIRI *)source toIRI: (OFIRI *)destination +{ + void *pool; + + if (![source.scheme isEqual: _scheme] || + ![destination.scheme isEqual: _scheme]) + return false; + + if ([self fileExistsAtIRI: destination]) + @throw [OFMoveItemFailedException + exceptionWithSourceIRI: source + destinationIRI: destination + errNo: EEXIST]; + + pool = objc_autoreleasePoolPush(); + +#ifdef OF_AMIGAOS + OFStringEncoding encoding = [OFLocale encoding]; + + if (!Rename([source.fileSystemRepresentation + cStringWithEncoding: encoding], + [destination.fileSystemRepresentation + cStringWithEncoding: encoding])) + @throw [OFMoveItemFailedException + exceptionWithSourceIRI: source + destinationIRI: destination + errNo: lastError()]; +#else + int status; + +# ifdef OF_WINDOWS + if ([OFSystemInfo isWindowsNT]) + status = _wrename(source.fileSystemRepresentation.UTF16String, + destination.fileSystemRepresentation.UTF16String); + else { +# endif + OFStringEncoding encoding = [OFLocale encoding]; + + status = rename([source.fileSystemRepresentation + cStringWithEncoding: encoding], + [destination.fileSystemRepresentation + cStringWithEncoding: encoding]); +# ifdef OF_WINDOWS + } +# endif + + if (status != 0) + @throw [OFMoveItemFailedException + exceptionWithSourceIRI: source + destinationIRI: destination + errNo: errno]; +#endif + + objc_autoreleasePoolPop(pool); + + return true; +} + +#ifdef OF_FILE_MANAGER_SUPPORTS_EXTENDED_ATTRIBUTES +- (OFData *)extendedAttributeDataForName: (OFString *)name + ofItemAtIRI: (OFIRI *)IRI +{ + void *pool = objc_autoreleasePoolPush(); + OFString *path = IRI.fileSystemRepresentation; + OFStringEncoding encoding = [OFLocale encoding]; + const char *cPath = [path cStringWithEncoding: encoding]; + const char *cName = [name cStringWithEncoding: encoding]; +# if defined(OF_LINUX) + ssize_t size = lgetxattr(cPath, cName, NULL, 0); +# elif defined(OF_MACOS) + ssize_t size = getxattr(cPath, cName, NULL, 0, 0, XATTR_NOFOLLOW); +# endif + void *value = OFAllocMemory(1, size); + OFData *data; + + @try { +# if defined(OF_LINUX) + if ((size = lgetxattr(cPath, cName, value, size)) < 0) +# elif defined(OF_MACOS) + if ((size = getxattr(cPath, cName, value, size, 0, + XATTR_NOFOLLOW)) < 0) +# endif + @throw [OFGetItemAttributesFailedException + exceptionWithIRI: IRI + errNo: errno]; + + data = [OFData dataWithItems: value count: size]; + } @finally { + OFFreeMemory(value); + } + + [data retain]; + + objc_autoreleasePoolPop(pool); + + return [data autorelease]; +} + +- (void)setExtendedAttributeData: (OFData *)data + forName: (OFString *)name + ofItemAtIRI: (OFIRI *)IRI +{ + void *pool = objc_autoreleasePoolPush(); + OFString *path = IRI.fileSystemRepresentation; + OFStringEncoding encoding = [OFLocale encoding]; + +# if defined(OF_LINUX) + if (lsetxattr([path cStringWithEncoding: encoding], + [name cStringWithEncoding: encoding], data.items, + data.count * data.itemSize, 0) != 0) { +# elif defined(OF_MACOS) + if (setxattr([path cStringWithEncoding: encoding], + [name cStringWithEncoding: encoding], data.items, + data.count * data.itemSize, 0, XATTR_NOFOLLOW) != 0) { +# endif + int errNo = errno; + + /* TODO: Add an attribute (prefix?) for extended attributes? */ + @throw [OFSetItemAttributesFailedException + exceptionWithIRI: IRI + attributes: [OFDictionary dictionary] + failedAttribute: @"" + errNo: errNo]; + } + + objc_autoreleasePoolPop(pool); +} + +- (void)removeExtendedAttributeForName: (OFString *)name + ofItemAtIRI: (OFIRI *)IRI +{ + void *pool = objc_autoreleasePoolPush(); + OFString *path = IRI.fileSystemRepresentation; + OFStringEncoding encoding = [OFLocale encoding]; + +# if defined(OF_LINUX) + if (lremovexattr([path cStringWithEncoding: encoding], + [name cStringWithEncoding: encoding]) != 0) { +# elif defined(OF_MACOS) + if (removexattr([path cStringWithEncoding: encoding], + [name cStringWithEncoding: encoding], XATTR_NOFOLLOW) != 0) { +# endif + int errNo = errno; + + /* TODO: Add an attribute (prefix?) for extended attributes? */ + @throw [OFSetItemAttributesFailedException + exceptionWithIRI: IRI + attributes: [OFDictionary dictionary] + failedAttribute: @"" + errNo: errNo]; + } + + objc_autoreleasePoolPop(pool); +} +#endif +@end Index: src/OFFileManager.h ================================================================== --- src/OFFileManager.h +++ src/OFFileManager.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,34 +19,39 @@ OF_ASSUME_NONNULL_BEGIN /** @file */ #ifdef OF_HAVE_FILES -# if defined(OF_HAVE_CHMOD) && !defined(OF_AMIGAOS) +# if (defined(OF_HAVE_CHMOD) && !defined(OF_AMIGAOS)) || defined(DOXYGEN) # define OF_FILE_MANAGER_SUPPORTS_PERMISSIONS # endif -# if defined(OF_HAVE_CHOWN) && !defined(OF_AMIGAOS) +# if (defined(OF_HAVE_CHOWN) && !defined(OF_AMIGAOS)) || defined(DOXYGEN) # define OF_FILE_MANAGER_SUPPORTS_OWNER # endif -# if (defined(OF_HAVE_LINK) && !defined(OF_AMIGAOS)) || defined(OF_WINDOWS) +# if (defined(OF_HAVE_LINK) && !defined(OF_AMIGAOS)) || defined(OF_WINDOWS) || \ + defined(DOXYGEN) # define OF_FILE_MANAGER_SUPPORTS_LINKS # endif -# if (defined(OF_HAVE_SYMLINK) && !defined(OF_AMIGAOS)) || defined(OF_WINDOWS) +# if (defined(OF_HAVE_SYMLINK) && !defined(OF_AMIGAOS)) || \ + defined(OF_WINDOWS) || defined(DOXYGEN) # define OF_FILE_MANAGER_SUPPORTS_SYMLINKS +# endif +# if defined(OF_LINUX) || defined(OF_MACOS) || defined(DOXYGEN) +# define OF_FILE_MANAGER_SUPPORTS_EXTENDED_ATTRIBUTES # endif #endif @class OFArray OF_GENERIC(ObjectType); @class OFConstantString; @class OFDate; +@class OFIRI; @class OFString; -@class OFURI; /** * @brief A key for a file attribute in the file attributes dictionary. * - * Possible keys for file URIs are: + * Possible keys for file IRIs are: * * * @ref OFFileSize * * @ref OFFileType * * @ref OFFilePOSIXPermissions * * @ref OFFileOwnerAccountID @@ -56,19 +61,20 @@ * * @ref OFFileLastAccessDate * * @ref OFFileModificationDate * * @ref OFFileStatusChangeDate * * @ref OFFileCreationDate * * @ref OFFileSymbolicLinkDestination + * * @ref OFFileExtendedAttributesNames * - * Other URI schemes might not have all keys and might have keys not listed. + * Other IRI schemes might not have all keys and might have keys not listed. */ typedef OFConstantString *OFFileAttributeKey; /** * @brief The type of a file. * - * Possibles values for file URIs are: + * Possibles values for file IRIs are: * * * @ref OFFileTypeRegular * * @ref OFFileTypeDirectory * * @ref OFFileTypeSymbolicLink * * @ref OFFileTypeFIFO @@ -75,11 +81,11 @@ * * @ref OFFileTypeCharacterSpecial * * @ref OFFileTypeBlockSpecial * * @ref OFFileTypeSocket * * @ref OFFileTypeUnknown * - * Other URI schemes might not have all types and might have types not listed. + * Other IRI schemes might not have all types and might have types not listed. */ typedef OFConstantString *OFFileAttributeType; /** * @brief A dictionary mapping keys of type @ref OFFileAttributeKey to their @@ -186,17 +192,26 @@ * via @ref OFDictionary#fileCreationDate. */ extern const OFFileAttributeKey OFFileCreationDate; /** - * @brief The destination of a symbolic link as an OFString. + * @brief The destination of a symbolic link as an @ref OFString. * * For convenience, a category on @ref OFDictionary is provided to access this * via @ref OFDictionary#fileSymbolicLinkDestination. */ extern const OFFileAttributeKey OFFileSymbolicLinkDestination; +/** + * @brief The names of the extended attributes as an @ref OFArray of + * @ref OFString. + * + * For convenience, a category on @ref OFDictionary is provided to access this + * via @ref OFDictionary#fileExtendedAttributesNames. + */ +extern const OFFileAttributeKey OFFileExtendedAttributesNames; + /** * @brief A regular file. */ extern const OFFileAttributeType OFFileTypeRegular; @@ -263,15 +278,15 @@ * @throw OFGetCurrentDirectoryFailedException Couldn't get current directory */ @property (readonly, nonatomic) OFString *currentDirectoryPath; /** - * @brief The URI of the current working directory. + * @brief The IRI of the current working directory. * * @throw OFGetCurrentDirectoryFailedException Couldn't get current directory */ -@property (readonly, nonatomic) OFURI *currentDirectoryURI; +@property (readonly, nonatomic) OFIRI *currentDirectoryIRI; #endif /** * @brief Returns the default file manager. */ @@ -289,21 +304,21 @@ */ - (OFFileAttributes)attributesOfItemAtPath: (OFString *)path; #endif /** - * @brief Returns the attributes for the item at the specified URI. + * @brief Returns the attributes for the item at the specified IRI. * - * @param URI The URI to return the attributes for - * @return A dictionary of attributes for the specified URI, with the keys of + * @param IRI The IRI to return the attributes for + * @return A dictionary of attributes for the specified IRI, with the keys of * type @ref OFFileAttributeKey * @throw OFGetItemAttributesFailedException Failed to get the attributes of * the item - * @throw OFUnsupportedProtocolException No handler is registered for the URI's + * @throw OFUnsupportedProtocolException No handler is registered for the IRI's * scheme */ -- (OFFileAttributes)attributesOfItemAtURI: (OFURI *)URI; +- (OFFileAttributes)attributesOfItemAtIRI: (OFIRI *)IRI; #ifdef OF_HAVE_FILES /** * @brief Sets the attributes for the item at the specified path. * @@ -320,25 +335,25 @@ - (void)setAttributes: (OFFileAttributes)attributes ofItemAtPath: (OFString *)path; #endif /** - * @brief Sets the attributes for the item at the specified URI. + * @brief Sets the attributes for the item at the specified IRI. * * All attributes not part of the dictionary are left unchanged. * - * @param attributes The attributes to set for the specified URI - * @param URI The URI of the item to set the attributes for + * @param attributes The attributes to set for the specified IRI + * @param IRI The IRI of the item to set the attributes for * @throw OFSetItemAttributesFailedException Failed to set the attributes of * the item - * @throw OFUnsupportedProtocolException No handler is registered for the URI's + * @throw OFUnsupportedProtocolException No handler is registered for the IRI's * scheme * @throw OFNotImplementedException Setting one or more of the specified * attributes is not implemented for the * specified item */ -- (void)setAttributes: (OFFileAttributes)attributes ofItemAtURI: (OFURI *)URI; +- (void)setAttributes: (OFFileAttributes)attributes ofItemAtIRI: (OFIRI *)IRI; #ifdef OF_HAVE_FILES /** * @brief Checks whether a file exists at the specified path. * @@ -347,18 +362,18 @@ */ - (bool)fileExistsAtPath: (OFString *)path; #endif /** - * @brief Checks whether a file exists at the specified URI. + * @brief Checks whether a file exists at the specified IRI. * - * @param URI The URI to check - * @return A boolean whether there is a file at the specified URI - * @throw OFUnsupportedProtocolException No handler is registered for the URI's + * @param IRI The IRI to check + * @return A boolean whether there is a file at the specified IRI + * @throw OFUnsupportedProtocolException No handler is registered for the IRI's * scheme */ -- (bool)fileExistsAtURI: (OFURI *)URI; +- (bool)fileExistsAtIRI: (OFIRI *)IRI; #ifdef OF_HAVE_FILES /** * @brief Checks whether a directory exists at the specified path. * @@ -367,18 +382,18 @@ */ - (bool)directoryExistsAtPath: (OFString *)path; #endif /** - * @brief Checks whether a directory exists at the specified URI. + * @brief Checks whether a directory exists at the specified IRI. * - * @param URI The URI to check - * @return A boolean whether there is a directory at the specified URI - * @throw OFUnsupportedProtocolException No handler is registered for the URI's + * @param IRI The IRI to check + * @return A boolean whether there is a directory at the specified IRI + * @throw OFUnsupportedProtocolException No handler is registered for the IRI's * scheme */ -- (bool)directoryExistsAtURI: (OFURI *)URI; +- (bool)directoryExistsAtIRI: (OFIRI *)IRI; #ifdef OF_HAVE_FILES /** * @brief Creates a directory at the specified path. * @@ -398,30 +413,30 @@ - (void)createDirectoryAtPath: (OFString *)path createParents: (bool)createParents; #endif /** - * @brief Creates a directory at the specified URI. + * @brief Creates a directory at the specified IRI. * - * @param URI The URI of the directory to create + * @param IRI The IRI of the directory to create * @throw OFCreateDirectoryFailedException Creating the directory failed - * @throw OFUnsupportedProtocolException No handler is registered for the URI's + * @throw OFUnsupportedProtocolException No handler is registered for the IRI's * scheme */ -- (void)createDirectoryAtURI: (OFURI *)URI; +- (void)createDirectoryAtIRI: (OFIRI *)IRI; /** - * @brief Creates a directory at the specified URI. + * @brief Creates a directory at the specified IRI. * - * @param URI The URI of the directory to create + * @param IRI The IRI of the directory to create * @param createParents Whether to create the parents of the directory * @throw OFCreateDirectoryFailedException Creating the directory or one of its * parents failed - * @throw OFUnsupportedProtocolException No handler is registered for the URI's + * @throw OFUnsupportedProtocolException No handler is registered for the IRI's * scheme */ -- (void)createDirectoryAtURI: (OFURI *)URI createParents: (bool)createParents; +- (void)createDirectoryAtIRI: (OFIRI *)IRI createParents: (bool)createParents; #ifdef OF_HAVE_FILES /** * @brief Returns an array with the items in the specified directory. * @@ -434,23 +449,23 @@ */ - (OFArray OF_GENERIC(OFString *) *)contentsOfDirectoryAtPath: (OFString *)path; #endif /** - * @brief Returns an array with the URIs of the items in the specified + * @brief Returns an array with the IRIs of the items in the specified * directory. * * @note `.` and `..` are not part of the returned array. * - * @param URI The URI to the directory whose items should be returned - * @return An array with the URIs of the items in the specified directory + * @param IRI The IRI to the directory whose items should be returned + * @return An array with the IRIs of the items in the specified directory * @throw OFOpenItemFailedException Opening the directory failed * @throw OFReadFailedException Reading from the directory failed - * @throw OFUnsupportedProtocolException No handler is registered for the URI's + * @throw OFUnsupportedProtocolException No handler is registered for the IRI's * scheme */ -- (OFArray OF_GENERIC(OFURI *) *)contentsOfDirectoryAtURI: (OFURI *)URI; +- (OFArray OF_GENERIC(OFIRI *) *)contentsOfDirectoryAtIRI: (OFIRI *)IRI; #ifdef OF_HAVE_FILES /** * @brief Returns an array with all subpaths of the specified directory. * @@ -472,15 +487,15 @@ - (void)changeCurrentDirectoryPath: (OFString *)path; /** * @brief Changes the current working directory. * - * @param URI The new directory to change to + * @param IRI The new directory to change to * @throw OFChangeCurrentDirectoryFailedException Changing the current working * directory failed */ -- (void)changeCurrentDirectoryURI: (OFURI *)URI; +- (void)changeCurrentDirectoryIRI: (OFIRI *)IRI; /** * @brief Copies a file, directory or symbolic link (if supported by the OS). * * The destination path must be a full path, which means it must include the @@ -500,26 +515,26 @@ #endif /** * @brief Copies a file, directory or symbolic link (if supported by the OS). * - * The destination URI must have a full path, which means it must include the + * The destination IRI must have a full path, which means it must include the * name of the item. * * If an item already exists, the copy operation fails. This is also the case * if a directory is copied and an item already exists in the destination * directory. * * @param source The file, directory or symbolic link to copy - * @param destination The destination URI + * @param destination The destination IRI * @throw OFCopyItemFailedException Copying failed * @throw OFCreateDirectoryFailedException Creating a destination directory * failed * @throw OFUnsupportedProtocolException No handler is registered for either of - * the URI's scheme + * the IRI's scheme */ -- (void)copyItemAtURI: (OFURI *)source toURI: (OFURI *)destination; +- (void)copyItemAtIRI: (OFIRI *)source toIRI: (OFIRI *)destination; #ifdef OF_HAVE_FILES /** * @brief Moves an item. * @@ -545,16 +560,16 @@ #endif /** * @brief Moves an item. * - * The destination URI must have a full path, which means it must include the + * The destination IRI must have a full path, which means it must include the * name of the item. * * If the destination is on a different logical device or uses a different * scheme, the source will be copied to the destination using - * @ref copyItemAtURI:toURI: and the source removed using @ref removeItemAtURI:. + * @ref copyItemAtIRI:toIRI: and the source removed using @ref removeItemAtIRI:. * * @param source The item to rename * @param destination The new name for the item * @throw OFMoveItemFailedException Moving failed * @throw OFCopyItemFailedException Copying (to move between different devices) @@ -563,13 +578,13 @@ * destination (to move between different * devices) failed * @throw OFCreateDirectoryFailedException Creating a destination directory * failed * @throw OFUnsupportedProtocolException No handler is registered for either of - * the URI's scheme + * the IRI's scheme */ -- (void)moveItemAtURI: (OFURI *)source toURI: (OFURI *)destination; +- (void)moveItemAtIRI: (OFIRI *)source toIRI: (OFIRI *)destination; #ifdef OF_HAVE_FILES /** * @brief Removes the item at the specified path. * @@ -580,20 +595,20 @@ */ - (void)removeItemAtPath: (OFString *)path; #endif /** - * @brief Removes the item at the specified URI. + * @brief Removes the item at the specified IRI. * - * If the item at the specified URI is a directory, it is removed recursively. + * If the item at the specified IRI is a directory, it is removed recursively. * - * @param URI The URI to the item which should be removed + * @param IRI The IRI to the item which should be removed * @throw OFRemoveItemFailedException Removing the item failed - * @throw OFUnsupportedProtocolException No handler is registered for the URI's + * @throw OFUnsupportedProtocolException No handler is registered for the IRI's * scheme */ -- (void)removeItemAtURI: (OFURI *)URI; +- (void)removeItemAtIRI: (OFIRI *)IRI; #ifdef OF_FILE_MANAGER_SUPPORTS_LINKS /** * @brief Creates a hard link for the specified item. * @@ -604,32 +619,32 @@ * * @param source The path to the item for which a link should be created * @param destination The path to the item which should link to the source * @throw OFLinkItemFailedException Linking the item failed * @throw OFNotImplementedException Hardlinks are not implemented for the - * specified URI + * specified IRI */ - (void)linkItemAtPath: (OFString *)source toPath: (OFString *)destination; #endif /** * @brief Creates a hard link for the specified item. * - * The destination URI must have a full path, which means it must include the + * The destination IRI must have a full path, which means it must include the * name of the item. * - * This method is not available for all URIs. + * This method is not available for all IRIs. * - * @param source The URI to the item for which a link should be created - * @param destination The URI to the item which should link to the source + * @param source The IRI to the item for which a link should be created + * @param destination The IRI to the item which should link to the source * @throw OFLinkItemFailedException Linking the item failed - * @throw OFUnsupportedProtocolException No handler is registered for the URI's + * @throw OFUnsupportedProtocolException No handler is registered for the IRI's * scheme * @throw OFNotImplementedException Hardlinks are not implemented for the - * specified URI + * specified IRI */ -- (void)linkItemAtURI: (OFURI *)source toURI: (OFURI *)destination; +- (void)linkItemAtIRI: (OFIRI *)source toIRI: (OFIRI *)destination; #ifdef OF_FILE_MANAGER_SUPPORTS_SYMLINKS /** * @brief Creates a symbolic link for an item. * @@ -643,34 +658,147 @@ * * @param path The path to the item which should symbolically link to the target * @param target The target of the symbolic link * @throw OFCreateSymbolicLinkFailedException Creating the symbolic link failed * @throw OFNotImplementedException Symbolic links are not implemented for the - * specified URI + * specified IRI */ - (void)createSymbolicLinkAtPath: (OFString *)path withDestinationPath: (OFString *)target; #endif /** * @brief Creates a symbolic link for an item. * - * The destination URI must have a full path, which means it must include the + * The destination IRI must have a full path, which means it must include the * name of the item. * - * This method is not available for all URIs. + * This method is not available for all IRIs. * - * @note On Windows, this requires at least Windows Vista and administrator - * privileges! + * @note For file IRIs on Windows, this requires at least Windows Vista and + * administrator privileges! * - * @param URI The URI to the item which should symbolically link to the target + * @param IRI The IRI to the item which should symbolically link to the target * @param target The target of the symbolic link - * @throw OFUnsupportedProtocolException No handler is registered for the URI's + * @throw OFOFCreateSymbolicLinkFailedException Creating a symbolic link failed + * @throw OFUnsupportedProtocolException No handler is registered for the IRI's * scheme */ -- (void)createSymbolicLinkAtURI: (OFURI *)URI +- (void)createSymbolicLinkAtIRI: (OFIRI *)IRI withDestinationPath: (OFString *)target; + +#ifdef OF_FILE_MANAGER_SUPPORTS_EXTENDED_ATTRIBUTES +/** + * @brief Returns the extended attribute data for the specified name of the + * item at the specified path. + * + * This method is not available on some systems. + * + * @param name The name of the extended attribute + * @param path The path of the item to return the extended attribute from + * @throw OFGetItemAttributesFailedException Getting the extended attribute + * failed + * @throw OFNotImplementedException Getting extended attributes is not + * implemented for the specified item + */ +- (OFData *)extendedAttributeDataForName: (OFString *)name + ofItemAtPath: (OFString *)path; +#endif + +/** + * @brief Returns the extended attribute data for the specified name of the + * item at the specified IRI. + * + * This method is not available for all IRIs. + * + * @param name The name of the extended attribute + * @param IRI The IRI of the item to return the extended attribute from + * @throw OFGetItemAttributesFailedException Getting the extended attribute + * failed + * @throw OFUnsupportedProtocolException No handler is registered for the IRI's + * scheme + * @throw OFNotImplementedException Getting extended attributes is not + * implemented for the specified item + */ +- (OFData *)extendedAttributeDataForName: (OFString *)name + ofItemAtIRI: (OFIRI *)IRI; + +#ifdef OF_FILE_MANAGER_SUPPORTS_EXTENDED_ATTRIBUTES +/** + * @brief Sets the extended attribute data for the specified name of the item + * at the specified path. + * + * This method is not available on some systems. + * + * @param data The data for the extended attribute + * @param name The name of the extended attribute + * @param path The path of the item to set the extended attribute on + * @throw OFSetItemAttributesFailedException Setting the extended attribute + * failed + * @throw OFNotImplementedException Setting extended attributes is not + * implemented for the specified item + */ +- (void)setExtendedAttributeData: (OFData *)data + forName: (OFString *)name + ofItemAtPath: (OFString *)path; +#endif + +/** + * @brief Sets the extended attribute data for the specified name of the item + * at the specified IRI. + * + * This method is not available for all IRIs. + * + * @param data The data for the extended attribute + * @param name The name of the extended attribute + * @param IRI The IRI of the item to set the extended attribute on + * @throw OFSetItemAttributesFailedException Setting the extended attribute + * failed + * @throw OFUnsupportedProtocolException No handler is registered for the IRI's + * scheme + * @throw OFNotImplementedException Setting extended attributes is not + * implemented for the specified item + */ +- (void)setExtendedAttributeData: (OFData *)data + forName: (OFString *)name + ofItemAtIRI: (OFIRI *)IRI; + +#ifdef OF_FILE_MANAGER_SUPPORTS_EXTENDED_ATTRIBUTES +/** + * @brief Removes the extended attribute for the specified name wof the item at + * the specified path. + * + * This method is not available on some systems. + * + * @param name The name of the extended attribute to remove + * @param path The path of the item to remove the extended attribute from + * @throw OFSetItemAttributesFailedException Removing the extended attribute + * failed + * @throw OFNotImplementedException Removing extended attributes is not + * implemented for the specified item + */ +- (void)removeExtendedAttributeForName: (OFString *)name + ofItemAtPath: (OFString *)path; +#endif + +/** + * @brief Removes the extended attribute for the specified name wof the item at + * the specified IRI. + * + * This method is not available for all IRIs. + * + * @param name The name of the extended attribute to remove + * @param IRI The IRI of the item to remove the extended attribute from + * @throw OFSetItemAttributesFailedException Removing the extended attribute + * failed + * @throw OFUnsupportedProtocolException No handler is registered for the IRI's + * scheme + * @throw OFNotImplementedException Removing extended attributes is not + * implemented for the specified item + */ +- (void)removeExtendedAttributeForName: (OFString *)name + ofItemAtIRI: (OFIRI *)IRI; @end @interface OFDictionary (FileAttributes) /** * @brief The @ref OFFileSize key from the dictionary. @@ -753,8 +881,16 @@ * @brief The @ref OFFileSymbolicLinkDestination key from the dictionary. * * @throw OFUndefinedKeyException The key is missing */ @property (readonly, nonatomic) OFString *fileSymbolicLinkDestination; + +/** + * @brief The @ref OFFileExtendedAttributesNames key from the dictionary. + * + * @throw OFUndefinedKeyException The key is missing + */ +@property (readonly, nonatomic) + OFArray OF_GENERIC(OFString *) *fileExtendedAttributesNames; @end OF_ASSUME_NONNULL_END Index: src/OFFileManager.m ================================================================== --- src/OFFileManager.m +++ src/OFFileManager.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,28 +21,32 @@ #include #include "unistd_wrapper.h" #include "platform.h" +#ifdef OF_DJGPP +# include +#endif #ifdef OF_PSP # include #endif #import "OFArray.h" +#import "OFData.h" #import "OFDate.h" #import "OFDictionary.h" #ifdef OF_HAVE_FILES # import "OFFile.h" #endif #import "OFFileManager.h" +#import "OFIRI.h" +#import "OFIRIHandler.h" #import "OFLocale.h" #import "OFNumber.h" #import "OFStream.h" #import "OFString.h" #import "OFSystemInfo.h" -#import "OFURI.h" -#import "OFURIHandler.h" #import "OFChangeCurrentDirectoryFailedException.h" #import "OFCopyItemFailedException.h" #import "OFCreateDirectoryFailedException.h" #import "OFGetCurrentDirectoryFailedException.h" @@ -62,12 +66,14 @@ # include # include #endif #ifdef OF_AMIGAOS +# define Class IntuitionClass # include # include +# undef Class #endif #ifdef OF_MINT # include #endif @@ -165,10 +171,26 @@ return nil; } return [OFString stringWithCString: buffer encoding: [OFLocale encoding]]; +# elif defined(OF_GLIBC) + char *buffer; + OFString *path; + + if ((buffer = getcwd(NULL, 0)) == NULL) + @throw [OFGetCurrentDirectoryFailedException + exceptionWithErrNo: errno]; + + @try { + path = [OFString stringWithCString: buffer + encoding: [OFLocale encoding]]; + } @finally { + free(buffer); + } + + return path; # else char buffer[PATH_MAX]; if ((getcwd(buffer, PATH_MAX)) == NULL) @throw [OFGetCurrentDirectoryFailedException @@ -187,157 +209,161 @@ return [OFString stringWithCString: buffer encoding: [OFLocale encoding]]; # endif } -- (OFURI *)currentDirectoryURI +- (OFIRI *)currentDirectoryIRI { void *pool = objc_autoreleasePoolPush(); - OFURI *ret; + OFIRI *ret; - ret = [OFURI fileURIWithPath: self.currentDirectoryPath]; + ret = [OFIRI fileIRIWithPath: self.currentDirectoryPath]; + ret = [ret retain]; - [ret retain]; objc_autoreleasePoolPop(pool); return [ret autorelease]; } #endif -- (OFFileAttributes)attributesOfItemAtURI: (OFURI *)URI +- (OFFileAttributes)attributesOfItemAtIRI: (OFIRI *)IRI { - OFURIHandler *URIHandler; + OFIRIHandler *IRIHandler; - if (URI == nil) + if (IRI == nil) @throw [OFInvalidArgumentException exception]; - if ((URIHandler = [OFURIHandler handlerForURI: URI]) == nil) - @throw [OFUnsupportedProtocolException exceptionWithURI: URI]; + if ((IRIHandler = [OFIRIHandler handlerForIRI: IRI]) == nil) + @throw [OFUnsupportedProtocolException exceptionWithIRI: IRI]; - return [URIHandler attributesOfItemAtURI: URI]; + return [IRIHandler attributesOfItemAtIRI: IRI]; } #ifdef OF_HAVE_FILES - (OFFileAttributes)attributesOfItemAtPath: (OFString *)path { void *pool = objc_autoreleasePoolPush(); OFFileAttributes ret; - ret = [self attributesOfItemAtURI: [OFURI fileURIWithPath: path]]; - - [ret retain]; + ret = [self attributesOfItemAtIRI: [OFIRI fileIRIWithPath: path]]; + ret = [ret retain]; objc_autoreleasePoolPop(pool); return [ret autorelease]; } #endif -- (void)setAttributes: (OFFileAttributes)attributes ofItemAtURI: (OFURI *)URI +- (void)setAttributes: (OFFileAttributes)attributes ofItemAtIRI: (OFIRI *)IRI { - OFURIHandler *URIHandler; + OFIRIHandler *IRIHandler; - if (URI == nil) + if (IRI == nil) @throw [OFInvalidArgumentException exception]; - if ((URIHandler = [OFURIHandler handlerForURI: URI]) == nil) - @throw [OFUnsupportedProtocolException exceptionWithURI: URI]; + if ((IRIHandler = [OFIRIHandler handlerForIRI: IRI]) == nil) + @throw [OFUnsupportedProtocolException exceptionWithIRI: IRI]; - [URIHandler setAttributes: attributes ofItemAtURI: URI]; + [IRIHandler setAttributes: attributes ofItemAtIRI: IRI]; } #ifdef OF_HAVE_FILES - (void)setAttributes: (OFFileAttributes)attributes ofItemAtPath: (OFString *)path { void *pool = objc_autoreleasePoolPush(); [self setAttributes: attributes - ofItemAtURI: [OFURI fileURIWithPath: path]]; + ofItemAtIRI: [OFIRI fileIRIWithPath: path]]; objc_autoreleasePoolPop(pool); } #endif -- (bool)fileExistsAtURI: (OFURI *)URI +- (bool)fileExistsAtIRI: (OFIRI *)IRI { - OFURIHandler *URIHandler; + OFIRIHandler *IRIHandler; - if (URI == nil) + if (IRI == nil) @throw [OFInvalidArgumentException exception]; - if ((URIHandler = [OFURIHandler handlerForURI: URI]) == nil) - @throw [OFUnsupportedProtocolException exceptionWithURI: URI]; + if ((IRIHandler = [OFIRIHandler handlerForIRI: IRI]) == nil) + @throw [OFUnsupportedProtocolException exceptionWithIRI: IRI]; - return [URIHandler fileExistsAtURI: URI]; + return [IRIHandler fileExistsAtIRI: IRI]; } #ifdef OF_HAVE_FILES - (bool)fileExistsAtPath: (OFString *)path { void *pool = objc_autoreleasePoolPush(); bool ret; - ret = [self fileExistsAtURI: [OFURI fileURIWithPath: path]]; + ret = [self fileExistsAtIRI: [OFIRI fileIRIWithPath: path]]; objc_autoreleasePoolPop(pool); return ret; } #endif -- (bool)directoryExistsAtURI: (OFURI *)URI +- (bool)directoryExistsAtIRI: (OFIRI *)IRI { - OFURIHandler *URIHandler; + OFIRIHandler *IRIHandler; - if (URI == nil) + if (IRI == nil) @throw [OFInvalidArgumentException exception]; - if ((URIHandler = [OFURIHandler handlerForURI: URI]) == nil) - @throw [OFUnsupportedProtocolException exceptionWithURI: URI]; + if ((IRIHandler = [OFIRIHandler handlerForIRI: IRI]) == nil) + @throw [OFUnsupportedProtocolException exceptionWithIRI: IRI]; - return [URIHandler directoryExistsAtURI: URI]; + return [IRIHandler directoryExistsAtIRI: IRI]; } #ifdef OF_HAVE_FILES - (bool)directoryExistsAtPath: (OFString *)path { void *pool = objc_autoreleasePoolPush(); bool ret; - ret = [self directoryExistsAtURI: [OFURI fileURIWithPath: path]]; + ret = [self directoryExistsAtIRI: [OFIRI fileIRIWithPath: path]]; objc_autoreleasePoolPop(pool); return ret; } #endif -- (void)createDirectoryAtURI: (OFURI *)URI +- (void)createDirectoryAtIRI: (OFIRI *)IRI { - OFURIHandler *URIHandler; + void *pool = objc_autoreleasePoolPush(); + OFIRIHandler *IRIHandler; - if (URI == nil) + if (IRI == nil) @throw [OFInvalidArgumentException exception]; - if ((URIHandler = [OFURIHandler handlerForURI: URI]) == nil) - @throw [OFUnsupportedProtocolException exceptionWithURI: URI]; + if ((IRIHandler = [OFIRIHandler handlerForIRI: IRI]) == nil) + @throw [OFUnsupportedProtocolException exceptionWithIRI: IRI]; - [URIHandler createDirectoryAtURI: URI]; + [IRIHandler createDirectoryAtIRI: IRI]; + + objc_autoreleasePoolPop(pool); } -- (void)createDirectoryAtURI: (OFURI *)URI createParents: (bool)createParents +- (void)createDirectoryAtIRI: (OFIRI *)IRI createParents: (bool)createParents { void *pool = objc_autoreleasePoolPush(); - OFMutableURI *mutableURI; + OFMutableIRI *mutableIRI; OFArray OF_GENERIC(OFString *) *components; - OFMutableArray OF_GENERIC(OFURI *) *componentURIs; - size_t componentURIsCount; + OFMutableArray OF_GENERIC(OFIRI *) *componentIRIs; + size_t componentIRIsCount; ssize_t i; - if (URI == nil) + if (IRI == nil) @throw [OFInvalidArgumentException exception]; if (!createParents) { - [self createDirectoryAtURI: URI]; + [self createDirectoryAtIRI: IRI]; + + objc_autoreleasePoolPop(pool); return; } /* * Try blindly creating the directory first. @@ -344,15 +370,20 @@ * * The reason for this is that we might be sandboxed, so attempting to * create any of the parent directories will fail, while creating the * directory itself will work. */ - if ([self directoryExistsAtURI: URI]) + + if ([self directoryExistsAtIRI: IRI]) { + objc_autoreleasePoolPop(pool); return; + } @try { - [self createDirectoryAtURI: URI]; + [self createDirectoryAtIRI: IRI]; + + objc_autoreleasePoolPop(pool); return; } @catch (OFCreateDirectoryFailedException *e) { /* * If we didn't fail because any of the parents is missing, * there is no point in trying to create the parents. @@ -360,101 +391,101 @@ if (e.errNo != ENOENT) @throw e; } /* - * Because we might be sandboxed (and for remote URIs don't even know - * anything at all), we generate the URI for every component. We then + * Because we might be sandboxed (and for remote IRIs don't even know + * anything at all), we generate the IRI for every component. We then * iterate them in reverse order until we find the first existing * directory, and then create subdirectories from there. */ - mutableURI = [[URI mutableCopy] autorelease]; - mutableURI.percentEncodedPath = @"/"; - components = URI.pathComponents; - componentURIs = [OFMutableArray arrayWithCapacity: components.count]; + mutableIRI = [[IRI mutableCopy] autorelease]; + mutableIRI.percentEncodedPath = @"/"; + components = IRI.pathComponents; + componentIRIs = [OFMutableArray arrayWithCapacity: components.count]; for (OFString *component in components) { - [mutableURI appendPathComponent: component]; + [mutableIRI appendPathComponent: component]; - if (![mutableURI.percentEncodedPath isEqual: @"/"]) - [componentURIs addObject: - [[mutableURI copy] autorelease]]; + if (![mutableIRI.percentEncodedPath isEqual: @"/"]) + [componentIRIs addObject: + [[mutableIRI copy] autorelease]]; } - componentURIsCount = componentURIs.count; - for (i = componentURIsCount - 1; i > 0; i--) { - if ([self directoryExistsAtURI: - [componentURIs objectAtIndex: i]]) + componentIRIsCount = componentIRIs.count; + for (i = componentIRIsCount - 1; i > 0; i--) { + if ([self directoryExistsAtIRI: + [componentIRIs objectAtIndex: i]]) break; } - if (++i == (ssize_t)componentURIsCount) { + if (++i == (ssize_t)componentIRIsCount) { /* - * The URI exists, even though before we made sure it did not. + * The IRI exists, even though before we made sure it did not. * That means it was created in the meantime by something else, * so we're done here. */ objc_autoreleasePoolPop(pool); return; } - for (; i < (ssize_t)componentURIsCount; i++) - [self createDirectoryAtURI: [componentURIs objectAtIndex: i]]; + for (; i < (ssize_t)componentIRIsCount; i++) + [self createDirectoryAtIRI: [componentIRIs objectAtIndex: i]]; objc_autoreleasePoolPop(pool); } #ifdef OF_HAVE_FILES - (void)createDirectoryAtPath: (OFString *)path { void *pool = objc_autoreleasePoolPush(); - [self createDirectoryAtURI: [OFURI fileURIWithPath: path]]; + [self createDirectoryAtIRI: [OFIRI fileIRIWithPath: path]]; objc_autoreleasePoolPop(pool); } - (void)createDirectoryAtPath: (OFString *)path createParents: (bool)createParents { void *pool = objc_autoreleasePoolPush(); - [self createDirectoryAtURI: [OFURI fileURIWithPath: path] + [self createDirectoryAtIRI: [OFIRI fileIRIWithPath: path] createParents: createParents]; objc_autoreleasePoolPop(pool); } #endif -- (OFArray OF_GENERIC(OFURI *) *)contentsOfDirectoryAtURI: (OFURI *)URI +- (OFArray OF_GENERIC(OFIRI *) *)contentsOfDirectoryAtIRI: (OFIRI *)IRI { - OFURIHandler *URIHandler; + OFIRIHandler *IRIHandler; - if (URI == nil) + if (IRI == nil) @throw [OFInvalidArgumentException exception]; - if ((URIHandler = [OFURIHandler handlerForURI: URI]) == nil) - @throw [OFUnsupportedProtocolException exceptionWithURI: URI]; + if ((IRIHandler = [OFIRIHandler handlerForIRI: IRI]) == nil) + @throw [OFUnsupportedProtocolException exceptionWithIRI: IRI]; - return [URIHandler contentsOfDirectoryAtURI: URI]; + return [IRIHandler contentsOfDirectoryAtIRI: IRI]; } #ifdef OF_HAVE_FILES - (OFArray OF_GENERIC(OFString *) *)contentsOfDirectoryAtPath: (OFString *)path { void *pool = objc_autoreleasePoolPush(); - OFArray OF_GENERIC(OFURI *) *URIs; + OFArray OF_GENERIC(OFIRI *) *IRIs; OFMutableArray OF_GENERIC(OFString *) *ret; - URIs = [self contentsOfDirectoryAtURI: [OFURI fileURIWithPath: path]]; - ret = [OFMutableArray arrayWithCapacity: URIs.count]; + IRIs = [self contentsOfDirectoryAtIRI: [OFIRI fileIRIWithPath: path]]; + ret = [OFMutableArray arrayWithCapacity: IRIs.count]; - for (OFURI *URI in URIs) - [ret addObject: URI.lastPathComponent]; + for (OFIRI *IRI in IRIs) + [ret addObject: IRI.lastPathComponent]; [ret makeImmutable]; - [ret retain]; + ret = [ret retain]; objc_autoreleasePoolPop(pool); return [ret autorelease]; } @@ -480,11 +511,11 @@ objc_autoreleasePoolPop(pool2); } [ret makeImmutable]; - [ret retain]; + ret = [ret retain]; objc_autoreleasePoolPop(pool); return [ret autorelease]; } @@ -543,71 +574,71 @@ exceptionWithPath: path errNo: errno]; # endif } -- (void)changeCurrentDirectoryURI: (OFURI *)URI +- (void)changeCurrentDirectoryIRI: (OFIRI *)IRI { void *pool = objc_autoreleasePoolPush(); - [self changeCurrentDirectoryPath: URI.fileSystemRepresentation]; + [self changeCurrentDirectoryPath: IRI.fileSystemRepresentation]; objc_autoreleasePoolPop(pool); } - (void)copyItemAtPath: (OFString *)source toPath: (OFString *)destination { void *pool = objc_autoreleasePoolPush(); - [self copyItemAtURI: [OFURI fileURIWithPath: source] - toURI: [OFURI fileURIWithPath: destination]]; + [self copyItemAtIRI: [OFIRI fileIRIWithPath: source] + toIRI: [OFIRI fileIRIWithPath: destination]]; objc_autoreleasePoolPop(pool); } #endif -- (void)copyItemAtURI: (OFURI *)source toURI: (OFURI *)destination +- (void)copyItemAtIRI: (OFIRI *)source toIRI: (OFIRI *)destination { void *pool; - OFURIHandler *URIHandler; + OFIRIHandler *IRIHandler; OFFileAttributes attributes; OFFileAttributeType type; if (source == nil || destination == nil) @throw [OFInvalidArgumentException exception]; pool = objc_autoreleasePoolPush(); - if ((URIHandler = [OFURIHandler handlerForURI: source]) == nil) + if ((IRIHandler = [OFIRIHandler handlerForIRI: source]) == nil) @throw [OFUnsupportedProtocolException - exceptionWithURI: source]; + exceptionWithIRI: source]; - if ([URIHandler copyItemAtURI: source toURI: destination]) + if ([IRIHandler copyItemAtIRI: source toIRI: destination]) return; - if ([self fileExistsAtURI: destination]) + if ([self fileExistsAtIRI: destination]) @throw [OFCopyItemFailedException - exceptionWithSourceURI: source - destinationURI: destination + exceptionWithSourceIRI: source + destinationIRI: destination errNo: EEXIST]; @try { - attributes = [self attributesOfItemAtURI: source]; + attributes = [self attributesOfItemAtIRI: source]; } @catch (OFGetItemAttributesFailedException *e) { @throw [OFCopyItemFailedException - exceptionWithSourceURI: source - destinationURI: destination + exceptionWithSourceIRI: source + destinationIRI: destination errNo: e.errNo]; } type = attributes.fileType; if ([type isEqual: OFFileTypeDirectory]) { - OFArray OF_GENERIC(OFURI *) *contents; + OFArray OF_GENERIC(OFIRI *) *contents; @try { - [self createDirectoryAtURI: destination]; + [self createDirectoryAtIRI: destination]; @try { OFFileAttributeKey key = OFFilePOSIXPermissions; OFNumber *permissions = [attributes objectForKey: key]; @@ -617,39 +648,39 @@ destinationAttributes = [OFDictionary dictionaryWithObject: permissions forKey: key]; [self setAttributes: destinationAttributes - ofItemAtURI: destination]; + ofItemAtIRI: destination]; } } @catch (OFNotImplementedException *e) { } - contents = [self contentsOfDirectoryAtURI: source]; + contents = [self contentsOfDirectoryAtIRI: source]; } @catch (id e) { /* * Only convert exceptions to OFCopyItemFailedException * that have an errNo property. This covers all I/O * related exceptions from the operations used to copy * an item, all others should be left as is. */ if ([e respondsToSelector: @selector(errNo)]) @throw [OFCopyItemFailedException - exceptionWithSourceURI: source - destinationURI: destination + exceptionWithSourceIRI: source + destinationIRI: destination errNo: [e errNo]]; @throw e; } - for (OFURI *item in contents) { + for (OFIRI *item in contents) { void *pool2 = objc_autoreleasePoolPush(); - OFURI *destinationURI = [destination - URIByAppendingPathComponent: + OFIRI *destinationIRI = [destination + IRIByAppendingPathComponent: item.lastPathComponent]; - [self copyItemAtURI: item toURI: destinationURI]; + [self copyItemAtIRI: item toIRI: destinationIRI]; objc_autoreleasePoolPop(pool2); } } else if ([type isEqual: OFFileTypeRegular]) { size_t pageSize = [OFSystemInfo pageSize]; @@ -657,14 +688,14 @@ OFStream *destinationStream = nil; char *buffer; buffer = OFAllocMemory(1, pageSize); @try { - sourceStream = [OFURIHandler openItemAtURI: source + sourceStream = [OFIRIHandler openItemAtIRI: source mode: @"r"]; - destinationStream = [OFURIHandler - openItemAtURI: destination + destinationStream = [OFIRIHandler + openItemAtIRI: destination mode: @"w"]; while (!sourceStream.atEndOfStream) { size_t length; @@ -685,11 +716,11 @@ destinationAttributes = [OFDictionary dictionaryWithObject: permissions forKey: key]; [self setAttributes: destinationAttributes - ofItemAtURI: destination]; + ofItemAtIRI: destination]; } } @catch (OFNotImplementedException *e) { } } @catch (id e) { /* @@ -698,12 +729,12 @@ * related exceptions from the operations used to copy * an item, all others should be left as is. */ if ([e respondsToSelector: @selector(errNo)]) @throw [OFCopyItemFailedException - exceptionWithSourceURI: source - destinationURI: destination + exceptionWithSourceIRI: source + destinationIRI: destination errNo: [e errNo]]; @throw e; } @finally { [sourceStream close]; @@ -713,11 +744,11 @@ } else if ([type isEqual: OFFileTypeSymbolicLink]) { @try { OFString *linkDestination = attributes.fileSymbolicLinkDestination; - [self createSymbolicLinkAtURI: destination + [self createSymbolicLinkAtIRI: destination withDestinationPath: linkDestination]; } @catch (id e) { /* * Only convert exceptions to OFCopyItemFailedException * that have an errNo property. This covers all I/O @@ -724,190 +755,260 @@ * related exceptions from the operations used to copy * an item, all others should be left as is. */ if ([e respondsToSelector: @selector(errNo)]) @throw [OFCopyItemFailedException - exceptionWithSourceURI: source - destinationURI: destination + exceptionWithSourceIRI: source + destinationIRI: destination errNo: [e errNo]]; @throw e; } } else @throw [OFCopyItemFailedException - exceptionWithSourceURI: source - destinationURI: destination + exceptionWithSourceIRI: source + destinationIRI: destination errNo: EINVAL]; objc_autoreleasePoolPop(pool); } #ifdef OF_HAVE_FILES - (void)moveItemAtPath: (OFString *)source toPath: (OFString *)destination { void *pool = objc_autoreleasePoolPush(); - [self moveItemAtURI: [OFURI fileURIWithPath: source] - toURI: [OFURI fileURIWithPath: destination]]; + [self moveItemAtIRI: [OFIRI fileIRIWithPath: source] + toIRI: [OFIRI fileIRIWithPath: destination]]; objc_autoreleasePoolPop(pool); } #endif -- (void)moveItemAtURI: (OFURI *)source toURI: (OFURI *)destination +- (void)moveItemAtIRI: (OFIRI *)source toIRI: (OFIRI *)destination { void *pool; - OFURIHandler *URIHandler; + OFIRIHandler *IRIHandler; if (source == nil || destination == nil) @throw [OFInvalidArgumentException exception]; pool = objc_autoreleasePoolPush(); - if ((URIHandler = [OFURIHandler handlerForURI: source]) == nil) + if ((IRIHandler = [OFIRIHandler handlerForIRI: source]) == nil) @throw [OFUnsupportedProtocolException - exceptionWithURI: source]; + exceptionWithIRI: source]; @try { - if ([URIHandler moveItemAtURI: source toURI: destination]) + if ([IRIHandler moveItemAtIRI: source toIRI: destination]) return; } @catch (OFMoveItemFailedException *e) { if (e.errNo != EXDEV) @throw e; } - if ([self fileExistsAtURI: destination]) + if ([self fileExistsAtIRI: destination]) @throw [OFMoveItemFailedException - exceptionWithSourceURI: source - destinationURI: destination + exceptionWithSourceIRI: source + destinationIRI: destination errNo: EEXIST]; @try { - [self copyItemAtURI: source toURI: destination]; + [self copyItemAtIRI: source toIRI: destination]; } @catch (OFCopyItemFailedException *e) { - [self removeItemAtURI: destination]; + [self removeItemAtIRI: destination]; @throw [OFMoveItemFailedException - exceptionWithSourceURI: source - destinationURI: destination + exceptionWithSourceIRI: source + destinationIRI: destination errNo: e.errNo]; } @try { - [self removeItemAtURI: source]; + [self removeItemAtIRI: source]; } @catch (OFRemoveItemFailedException *e) { @throw [OFMoveItemFailedException - exceptionWithSourceURI: source - destinationURI: destination + exceptionWithSourceIRI: source + destinationIRI: destination errNo: e.errNo]; } objc_autoreleasePoolPop(pool); } -- (void)removeItemAtURI: (OFURI *)URI +- (void)removeItemAtIRI: (OFIRI *)IRI { - OFURIHandler *URIHandler; + OFIRIHandler *IRIHandler; - if (URI == nil) + if (IRI == nil) @throw [OFInvalidArgumentException exception]; - if ((URIHandler = [OFURIHandler handlerForURI: URI]) == nil) - @throw [OFUnsupportedProtocolException exceptionWithURI: URI]; + if ((IRIHandler = [OFIRIHandler handlerForIRI: IRI]) == nil) + @throw [OFUnsupportedProtocolException exceptionWithIRI: IRI]; - [URIHandler removeItemAtURI: URI]; + [IRIHandler removeItemAtIRI: IRI]; } #ifdef OF_HAVE_FILES - (void)removeItemAtPath: (OFString *)path { void *pool = objc_autoreleasePoolPush(); - [self removeItemAtURI: [OFURI fileURIWithPath: path]]; + [self removeItemAtIRI: [OFIRI fileIRIWithPath: path]]; objc_autoreleasePoolPop(pool); } #endif -- (void)linkItemAtURI: (OFURI *)source toURI: (OFURI *)destination +- (void)linkItemAtIRI: (OFIRI *)source toIRI: (OFIRI *)destination { void *pool = objc_autoreleasePoolPush(); - OFURIHandler *URIHandler; + OFIRIHandler *IRIHandler; if (source == nil || destination == nil) @throw [OFInvalidArgumentException exception]; if (![destination.scheme isEqual: source.scheme]) @throw [OFInvalidArgumentException exception]; - URIHandler = [OFURIHandler handlerForURI: source]; + IRIHandler = [OFIRIHandler handlerForIRI: source]; - if (URIHandler == nil) + if (IRIHandler == nil) @throw [OFUnsupportedProtocolException - exceptionWithURI: source]; + exceptionWithIRI: source]; - [URIHandler linkItemAtURI: source toURI: destination]; + [IRIHandler linkItemAtIRI: source toIRI: destination]; objc_autoreleasePoolPop(pool); } #ifdef OF_FILE_MANAGER_SUPPORTS_LINKS - (void)linkItemAtPath: (OFString *)source toPath: (OFString *)destination { void *pool = objc_autoreleasePoolPush(); - [self linkItemAtURI: [OFURI fileURIWithPath: source] - toURI: [OFURI fileURIWithPath: destination]]; + [self linkItemAtIRI: [OFIRI fileIRIWithPath: source] + toIRI: [OFIRI fileIRIWithPath: destination]]; objc_autoreleasePoolPop(pool); } #endif -- (void)createSymbolicLinkAtURI: (OFURI *)URI +- (void)createSymbolicLinkAtIRI: (OFIRI *)IRI withDestinationPath: (OFString *)target { void *pool = objc_autoreleasePoolPush(); - OFURIHandler *URIHandler; + OFIRIHandler *IRIHandler; - if (URI == nil || target == nil) + if (IRI == nil || target == nil) @throw [OFInvalidArgumentException exception]; - URIHandler = [OFURIHandler handlerForURI: URI]; + IRIHandler = [OFIRIHandler handlerForIRI: IRI]; - if (URIHandler == nil) - @throw [OFUnsupportedProtocolException exceptionWithURI: URI]; + if (IRIHandler == nil) + @throw [OFUnsupportedProtocolException exceptionWithIRI: IRI]; - [URIHandler createSymbolicLinkAtURI: URI withDestinationPath: target]; + [IRIHandler createSymbolicLinkAtIRI: IRI withDestinationPath: target]; objc_autoreleasePoolPop(pool); } #ifdef OF_FILE_MANAGER_SUPPORTS_SYMLINKS - (void)createSymbolicLinkAtPath: (OFString *)path withDestinationPath: (OFString *)target { void *pool = objc_autoreleasePoolPush(); - [self createSymbolicLinkAtURI: [OFURI fileURIWithPath: path] + [self createSymbolicLinkAtIRI: [OFIRI fileIRIWithPath: path] withDestinationPath: target]; objc_autoreleasePoolPop(pool); } #endif + +- (OFData *)extendedAttributeDataForName: (OFString *)name + ofItemAtIRI: (OFIRI *)IRI +{ + OFIRIHandler *IRIHandler; + + if (IRI == nil) + @throw [OFInvalidArgumentException exception]; + + if ((IRIHandler = [OFIRIHandler handlerForIRI: IRI]) == nil) + @throw [OFUnsupportedProtocolException exceptionWithIRI: IRI]; + + return [IRIHandler extendedAttributeDataForName: name ofItemAtIRI: IRI]; +} + +#ifdef OF_FILE_MANAGER_SUPPORTS_EXTENDED_ATTRIBUTES +- (OFData *)extendedAttributeDataForName: (OFString *)name + ofItemAtPath: (OFString *)path +{ + void *pool = objc_autoreleasePoolPush(); + OFData *ret; + + ret = [self + extendedAttributeDataForName: name + ofItemAtIRI: [OFIRI fileIRIWithPath: path]]; + ret = [ret retain]; + + objc_autoreleasePoolPop(pool); + + return [ret autorelease]; +} +#endif + +- (void)setExtendedAttributeData: (OFData *)data + forName: (OFString *)name + ofItemAtIRI: (OFIRI *)IRI +{ + OFIRIHandler *IRIHandler; + + if (IRI == nil) + @throw [OFInvalidArgumentException exception]; + + if ((IRIHandler = [OFIRIHandler handlerForIRI: IRI]) == nil) + @throw [OFUnsupportedProtocolException exceptionWithIRI: IRI]; + + [IRIHandler setExtendedAttributeData: data + forName: name + ofItemAtIRI: IRI]; +} + +#ifdef OF_FILE_MANAGER_SUPPORTS_EXTENDED_ATTRIBUTES +- (void)setExtendedAttributeData: (OFData *)data + forName: (OFString *)name + ofItemAtPath: (OFString *)path +{ + void *pool = objc_autoreleasePoolPush(); + [self setExtendedAttributeData: data + forName: name + ofItemAtIRI: [OFIRI fileIRIWithPath: path]]; + objc_autoreleasePoolPop(pool); +} +#endif + +- (void)removeExtendedAttributeForName: (OFString *)name + ofItemAtIRI: (OFIRI *)IRI +{ + OFIRIHandler *IRIHandler; + + if (IRI == nil) + @throw [OFInvalidArgumentException exception]; + + if ((IRIHandler = [OFIRIHandler handlerForIRI: IRI]) == nil) + @throw [OFUnsupportedProtocolException exceptionWithIRI: IRI]; + + [IRIHandler removeExtendedAttributeForName: name ofItemAtIRI: IRI]; +} + +#ifdef OF_FILE_MANAGER_SUPPORTS_EXTENDED_ATTRIBUTES +- (void)removeExtendedAttributeForName: (OFString *)name + ofItemAtPath: (OFString *)path +{ + void *pool = objc_autoreleasePoolPush(); + [self removeExtendedAttributeForName: name + ofItemAtIRI: [OFIRI fileIRIWithPath: path]]; + objc_autoreleasePoolPop(pool); +} +#endif @end @implementation OFDefaultFileManager -- (instancetype)autorelease -{ - return self; -} - -- (instancetype)retain -{ - return self; -} - -- (void)release -{ -} - -- (unsigned int)retainCount -{ - return OFMaxRetainCount; -} +OF_SINGLETON_METHODS @end @implementation OFDictionary (FileAttributes) - (unsigned long long)fileSize { @@ -970,6 +1071,11 @@ - (OFString *)fileSymbolicLinkDestination { return attributeForKeyOrException(self, OFFileSymbolicLinkDestination); } + +- (OFArray OF_GENERIC(OFString *) *)fileExtendedAttributesNames +{ + return attributeForKeyOrException(self, OFFileExtendedAttributesNames); +} @end Index: src/OFFileManagerConstants.inc ================================================================== --- src/OFFileManagerConstants.inc +++ src/OFFileManagerConstants.inc @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,12 @@ const OFFileAttributeKey OFFileModificationDate = @"OFFileModificationDate"; const OFFileAttributeKey OFFileStatusChangeDate = @"OFFileStatusChangeDate"; const OFFileAttributeKey OFFileCreationDate = @"OFFileCreationDate"; const OFFileAttributeKey OFFileSymbolicLinkDestination = @"OFFileSymbolicLinkDestination"; +const OFFileAttributeKey OFFileExtendedAttributesNames = + @"OFFileExtendedAttributesNames"; const OFFileAttributeType OFFileTypeRegular = @"OFFileTypeRegular"; const OFFileAttributeType OFFileTypeDirectory = @"OFFileTypeDirectory"; const OFFileAttributeType OFFileTypeSymbolicLink = @"OFFileTypeSymbolicLink"; const OFFileAttributeType OFFileTypeFIFO = @"OFFileTypeFIFO"; DELETED src/OFFileURIHandler.h Index: src/OFFileURIHandler.h ================================================================== --- src/OFFileURIHandler.h +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (c) 2008-2022 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#import "OFURIHandler.h" - -OF_ASSUME_NONNULL_BEGIN - -@interface OFFileURIHandler: OFURIHandler -+ (bool)of_directoryExistsAtPath: (OFString *)path OF_DIRECT; -@end - -OF_ASSUME_NONNULL_END DELETED src/OFFileURIHandler.m Index: src/OFFileURIHandler.m ================================================================== --- src/OFFileURIHandler.m +++ /dev/null @@ -1,1476 +0,0 @@ -/* - * Copyright (c) 2008-2022 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#include "config.h" - -#define _LARGEFILE64_SOURCE - -#include -#include - -#ifdef HAVE_DIRENT_H -# include -#endif -#include "unistd_wrapper.h" - -#include "platform.h" -#ifdef HAVE_SYS_STAT_H -# include -#endif -#include -#ifdef OF_WINDOWS -# include -#endif - -#ifdef HAVE_PWD_H -# include -#endif -#ifdef HAVE_GRP_H -# include -#endif - -#import "OFFileURIHandler.h" -#import "OFArray.h" -#import "OFDate.h" -#import "OFFile.h" -#import "OFFileManager.h" -#import "OFLocale.h" -#import "OFNumber.h" -#import "OFSystemInfo.h" -#import "OFURI.h" - -#ifdef OF_HAVE_THREADS -# import "OFMutex.h" -#endif - -#import "OFCreateDirectoryFailedException.h" -#import "OFCreateSymbolicLinkFailedException.h" -#import "OFGetItemAttributesFailedException.h" -#import "OFInitializationFailedException.h" -#import "OFInvalidArgumentException.h" -#import "OFLinkItemFailedException.h" -#import "OFMoveItemFailedException.h" -#import "OFNotImplementedException.h" -#import "OFOpenItemFailedException.h" -#import "OFOutOfRangeException.h" -#import "OFReadFailedException.h" -#import "OFRemoveItemFailedException.h" -#import "OFSetItemAttributesFailedException.h" - -#ifdef OF_WINDOWS -# include -# include -# include -# include -#endif - -#ifdef OF_AMIGAOS -# include -# include -# include -# ifdef OF_AMIGAOS4 -# define DeleteFile(path) Delete(path) -# endif -#endif - -#if defined(OF_WINDOWS) || defined(OF_AMIGAOS) -typedef struct { - OFStreamOffset st_size; - unsigned int st_mode; - OFTimeInterval st_atime, st_mtime, st_ctime; -# ifdef OF_WINDOWS -# define HAVE_STRUCT_STAT_ST_BIRTHTIME - OFTimeInterval st_birthtime; - DWORD fileAttributes; -# endif -} Stat; -#elif defined(HAVE_STAT64) -typedef struct stat64 Stat; -#else -typedef struct stat Stat; -#endif - -#ifdef OF_WINDOWS -# define S_IFLNK 0x10000 -# define S_ISLNK(mode) (mode & S_IFLNK) -#endif - -#if defined(OF_FILE_MANAGER_SUPPORTS_OWNER) && defined(OF_HAVE_THREADS) -static OFMutex *passwdMutex; - -static void -releasePasswdMutex(void) -{ - [passwdMutex release]; -} -#endif -#if !defined(HAVE_READDIR_R) && defined(OF_HAVE_THREADS) && !defined(OF_WINDOWS) -static OFMutex *readdirMutex; - -static void -releaseReaddirMutex(void) -{ - [readdirMutex release]; -} -#endif - -#ifdef OF_WINDOWS -static int (*_wutime64FuncPtr)(const wchar_t *, struct __utimbuf64 *); -static WINAPI BOOLEAN (*createSymbolicLinkWFuncPtr)(LPCWSTR, LPCWSTR, DWORD); -static WINAPI BOOLEAN (*createHardLinkWFuncPtr)(LPCWSTR, LPCWSTR, - LPSECURITY_ATTRIBUTES); -#endif - -#ifdef OF_WINDOWS -static OFTimeInterval -filetimeToTimeInterval(const FILETIME *filetime) -{ - return (double)((int64_t)filetime->dwHighDateTime << 32 | - filetime->dwLowDateTime) / 10000000.0 - 11644473600.0; -} - -static int -lastError(void) -{ - switch (GetLastError()) { - case ERROR_FILE_NOT_FOUND: - case ERROR_PATH_NOT_FOUND: - case ERROR_NO_MORE_FILES: - return ENOENT; - case ERROR_ACCESS_DENIED: - return EACCES; - case ERROR_DIRECTORY: - return ENOTDIR; - case ERROR_NOT_READY: - return EBUSY; - default: - return EIO; - } -} -#endif - -#ifdef OF_AMIGAOS -static int -lastError(void) -{ - switch (IoErr()) { - case ERROR_DELETE_PROTECTED: - case ERROR_READ_PROTECTED: - case ERROR_WRITE_PROTECTED: - return EACCES; - case ERROR_DISK_NOT_VALIDATED: - case ERROR_OBJECT_IN_USE: - return EBUSY; - case ERROR_OBJECT_EXISTS: - return EEXIST; - case ERROR_DIR_NOT_FOUND: - case ERROR_NO_MORE_ENTRIES: - case ERROR_OBJECT_NOT_FOUND: - return ENOENT; - case ERROR_NO_FREE_STORE: - return ENOMEM; - case ERROR_DISK_FULL: - return ENOSPC; - case ERROR_DIRECTORY_NOT_EMPTY: - return ENOTEMPTY; - case ERROR_DISK_WRITE_PROTECTED: - return EROFS; - case ERROR_RENAME_ACROSS_DEVICES: - return EXDEV; - default: - return EIO; - } -} -#endif - -static int -statWrapper(OFString *path, Stat *buffer) -{ -#if defined(OF_WINDOWS) - WIN32_FILE_ATTRIBUTE_DATA data; - bool success; - - if ([OFSystemInfo isWindowsNT]) - success = GetFileAttributesExW(path.UTF16String, - GetFileExInfoStandard, &data); - else - success = GetFileAttributesExA( - [path cStringWithEncoding: [OFLocale encoding]], - GetFileExInfoStandard, &data); - - if (!success) - return lastError(); - - buffer->st_size = (uint64_t)data.nFileSizeHigh << 32 | - data.nFileSizeLow; - - if (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) - buffer->st_mode = S_IFDIR; - else if (data.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) { - /* - * No need to use A functions in this branch: This is only - * available on NTFS (and hence Windows NT) anyway. - */ - WIN32_FIND_DATAW findData; - HANDLE findHandle; - - if ((findHandle = FindFirstFileW(path.UTF16String, - &findData)) == INVALID_HANDLE_VALUE) - return lastError(); - - @try { - if (!(findData.dwFileAttributes & - FILE_ATTRIBUTE_REPARSE_POINT)) - /* Race? Indicate to try again. */ - return EAGAIN; - - buffer->st_mode = - (findData.dwReserved0 == IO_REPARSE_TAG_SYMLINK - ? S_IFLNK : S_IFREG); - } @finally { - FindClose(findHandle); - } - } else - buffer->st_mode = S_IFREG; - - buffer->st_mode |= (data.dwFileAttributes & FILE_ATTRIBUTE_READONLY - ? (S_IRUSR | S_IXUSR) : (S_IRUSR | S_IWUSR | S_IXUSR)); - - buffer->st_atime = filetimeToTimeInterval(&data.ftLastAccessTime); - buffer->st_mtime = filetimeToTimeInterval(&data.ftLastWriteTime); - buffer->st_ctime = buffer->st_birthtime = - filetimeToTimeInterval(&data.ftCreationTime); - buffer->fileAttributes = data.dwFileAttributes; - - return 0; -#elif defined(OF_AMIGAOS) - BPTR lock; -# ifdef OF_AMIGAOS4 - struct ExamineData *ed; -# else - struct FileInfoBlock fib; -# endif - OFTimeInterval timeInterval; - struct Locale *locale; - struct DateStamp *date; - - if ((lock = Lock([path cStringWithEncoding: [OFLocale encoding]], - SHARED_LOCK)) == 0) - return lastError(); - -# if defined(OF_MORPHOS) - if (!Examine64(lock, &fib, TAG_DONE)) { -# elif defined(OF_AMIGAOS4) - if ((ed = ExamineObjectTags(EX_FileLockInput, lock, TAG_END)) == NULL) { -# else - if (!Examine(lock, &fib)) { -# endif - int error = lastError(); - UnLock(lock); - return error; - } - - UnLock(lock); - -# if defined(OF_MORPHOS) - buffer->st_size = fib.fib_Size64; -# elif defined(OF_AMIGAOS4) - buffer->st_size = ed->FileSize; -# else - buffer->st_size = fib.fib_Size; -# endif -# ifdef OF_AMIGAOS4 - buffer->st_mode = (EXD_IS_DIRECTORY(ed) ? S_IFDIR : S_IFREG); -# else - buffer->st_mode = (fib.fib_DirEntryType > 0 ? S_IFDIR : S_IFREG); -# endif - - timeInterval = 252460800; /* 1978-01-01 */ - - locale = OpenLocale(NULL); - /* - * FIXME: This does not take DST into account. But unfortunately, there - * is no way to figure out if DST was in effect when the file was - * modified. - */ - timeInterval += locale->loc_GMTOffset * 60.0; - CloseLocale(locale); - -# ifdef OF_AMIGAOS4 - date = &ed->Date; -# else - date = &fib.fib_Date; -# endif - timeInterval += date->ds_Days * 86400.0; - timeInterval += date->ds_Minute * 60.0; - timeInterval += date->ds_Tick / (OFTimeInterval)TICKS_PER_SECOND; - - buffer->st_atime = buffer->st_mtime = buffer->st_ctime = timeInterval; - -# ifdef OF_AMIGAOS4 - FreeDosObject(DOS_EXAMINEDATA, ed); -# endif - - return 0; -#elif defined(HAVE_STAT64) - if (stat64([path cStringWithEncoding: [OFLocale encoding]], - buffer) != 0) - return errno; - - return 0; -#else - if (stat([path cStringWithEncoding: [OFLocale encoding]], buffer) != 0) - return errno; - - return 0; -#endif -} - -static int -lstatWrapper(OFString *path, Stat *buffer) -{ -#if defined(HAVE_LSTAT) && !defined(OF_WINDOWS) && !defined(OF_AMIGAOS) && \ - !defined(OF_NINTENDO_3DS) && !defined(OF_WII) -# ifdef HAVE_LSTAT64 - if (lstat64([path cStringWithEncoding: [OFLocale encoding]], - buffer) != 0) - return errno; -# else - if (lstat([path cStringWithEncoding: [OFLocale encoding]], buffer) != 0) - return errno; -# endif - - return 0; -#else - return statWrapper(path, buffer); -#endif -} - -static void -setTypeAttribute(OFMutableFileAttributes attributes, Stat *s) -{ - if (S_ISREG(s->st_mode)) - [attributes setObject: OFFileTypeRegular forKey: OFFileType]; - else if (S_ISDIR(s->st_mode)) - [attributes setObject: OFFileTypeDirectory forKey: OFFileType]; -#ifdef S_ISLNK - else if (S_ISLNK(s->st_mode)) - [attributes setObject: OFFileTypeSymbolicLink - forKey: OFFileType]; -#endif -#ifdef S_ISFIFO - else if (S_ISFIFO(s->st_mode)) - [attributes setObject: OFFileTypeFIFO forKey: OFFileType]; -#endif -#ifdef S_ISCHR - else if (S_ISCHR(s->st_mode)) - [attributes setObject: OFFileTypeCharacterSpecial - forKey: OFFileType]; -#endif -#ifdef S_ISBLK - else if (S_ISBLK(s->st_mode)) - [attributes setObject: OFFileTypeBlockSpecial - forKey: OFFileType]; -#endif -#ifdef S_ISSOCK - else if (S_ISSOCK(s->st_mode)) - [attributes setObject: OFFileTypeSocket forKey: OFFileType]; -#endif - else - [attributes setObject: OFFileTypeUnknown forKey: OFFileType]; -} - -static void -setDateAttributes(OFMutableFileAttributes attributes, Stat *s) -{ - /* FIXME: We could be more precise on some OSes */ - [attributes - setObject: [OFDate dateWithTimeIntervalSince1970: s->st_atime] - forKey: OFFileLastAccessDate]; - [attributes - setObject: [OFDate dateWithTimeIntervalSince1970: s->st_mtime] - forKey: OFFileModificationDate]; - [attributes - setObject: [OFDate dateWithTimeIntervalSince1970: s->st_ctime] - forKey: OFFileStatusChangeDate]; -#ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME - [attributes - setObject: [OFDate dateWithTimeIntervalSince1970: s->st_birthtime] - forKey: OFFileCreationDate]; -#endif -} - -static void -setOwnerAndGroupAttributes(OFMutableFileAttributes attributes, Stat *s) -{ -#ifdef OF_FILE_MANAGER_SUPPORTS_OWNER - [attributes setObject: [NSNumber numberWithUnsignedLong: s->st_uid] - forKey: OFFileOwnerAccountID]; - [attributes setObject: [NSNumber numberWithUnsignedLong: s->st_gid] - forKey: OFFileGroupOwnerAccountID]; - -# ifdef OF_HAVE_THREADS - [passwdMutex lock]; - @try { -# endif - OFStringEncoding encoding = [OFLocale encoding]; - struct passwd *passwd = getpwuid(s->st_uid); - struct group *group_ = getgrgid(s->st_gid); - - if (passwd != NULL) { - OFString *owner = [OFString - stringWithCString: passwd->pw_name - encoding: encoding]; - - [attributes setObject: owner - forKey: OFFileOwnerAccountName]; - } - - if (group_ != NULL) { - OFString *group = [OFString - stringWithCString: group_->gr_name - encoding: encoding]; - - [attributes setObject: group - forKey: OFFileGroupOwnerAccountName]; - } -# ifdef OF_HAVE_THREADS - } @finally { - [passwdMutex unlock]; - } -# endif -#endif -} - -#ifdef OF_FILE_MANAGER_SUPPORTS_SYMLINKS -static void -setSymbolicLinkDestinationAttribute(OFMutableFileAttributes attributes, - OFURI *URI) -{ - OFString *path = URI.fileSystemRepresentation; -# ifndef OF_WINDOWS - OFStringEncoding encoding = [OFLocale encoding]; - char destinationC[PATH_MAX]; - ssize_t length; - OFString *destination; - - length = readlink([path cStringWithEncoding: encoding], destinationC, - PATH_MAX); - - if (length < 0) - @throw [OFGetItemAttributesFailedException - exceptionWithURI: URI - errNo: errno]; - - destination = [OFString stringWithCString: destinationC - encoding: encoding - length: length]; - - [attributes setObject: destination - forKey: OFFileSymbolicLinkDestination]; -# else - HANDLE handle; - OFString *destination; - - if (createSymbolicLinkWFuncPtr == NULL) - return; - - if ((handle = CreateFileW(path.UTF16String, 0, (FILE_SHARE_READ | - FILE_SHARE_WRITE), NULL, OPEN_EXISTING, - FILE_FLAG_OPEN_REPARSE_POINT, NULL)) == INVALID_HANDLE_VALUE) - @throw [OFGetItemAttributesFailedException - exceptionWithURI: URI - errNo: lastError()]; - - @try { - union { - char bytes[MAXIMUM_REPARSE_DATA_BUFFER_SIZE]; - REPARSE_DATA_BUFFER data; - } buffer; - DWORD size; - wchar_t *tmp; - - if (!DeviceIoControl(handle, FSCTL_GET_REPARSE_POINT, NULL, 0, - buffer.bytes, MAXIMUM_REPARSE_DATA_BUFFER_SIZE, &size, - NULL)) - @throw [OFGetItemAttributesFailedException - exceptionWithURI: URI - errNo: lastError()]; - - if (buffer.data.ReparseTag != IO_REPARSE_TAG_SYMLINK) - @throw [OFGetItemAttributesFailedException - exceptionWithURI: URI - errNo: lastError()]; - -# define slrb buffer.data.SymbolicLinkReparseBuffer - tmp = slrb.PathBuffer + - (slrb.SubstituteNameOffset / sizeof(wchar_t)); - - destination = [OFString - stringWithUTF16String: tmp - length: slrb.SubstituteNameLength / - sizeof(wchar_t)]; - - [attributes setObject: OFFileTypeSymbolicLink - forKey: OFFileType]; - [attributes setObject: destination - forKey: OFFileSymbolicLinkDestination]; -# undef slrb - } @finally { - CloseHandle(handle); - } -# endif -} -#endif - -@implementation OFFileURIHandler -+ (void)initialize -{ -#ifdef OF_WINDOWS - HMODULE module; -#endif - - if (self != [OFFileURIHandler class]) - return; - -#if defined(OF_FILE_MANAGER_SUPPORTS_OWNER) && defined(OF_HAVE_THREADS) - passwdMutex = [[OFMutex alloc] init]; - atexit(releasePasswdMutex); -#endif -#if !defined(HAVE_READDIR_R) && !defined(OF_WINDOWS) && defined(OF_HAVE_THREADS) - readdirMutex = [[OFMutex alloc] init]; - atexit(releaseReaddirMutex); -#endif - -#ifdef OF_WINDOWS - if ((module = LoadLibrary("msvcrt.dll")) != NULL) - _wutime64FuncPtr = (int (*)(const wchar_t *, - struct __utimbuf64 *))GetProcAddress(module, "_wutime64"); - - if ((module = LoadLibrary("kernel32.dll")) != NULL) { - createSymbolicLinkWFuncPtr = - (WINAPI BOOLEAN (*)(LPCWSTR, LPCWSTR, DWORD)) - GetProcAddress(module, "CreateSymbolicLinkW"); - createHardLinkWFuncPtr = - (WINAPI BOOLEAN (*)(LPCWSTR, LPCWSTR, - LPSECURITY_ATTRIBUTES)) - GetProcAddress(module, "CreateHardLinkW"); - } -#endif - - /* - * Make sure OFFile is initialized. - * On some systems, this is needed to initialize the file system driver. - */ - [OFFile class]; -} - -+ (bool)of_directoryExistsAtPath: (OFString *)path -{ - Stat s; - - if (statWrapper(path, &s) != 0) - return false; - - return S_ISDIR(s.st_mode); -} - -- (OFStream *)openItemAtURI: (OFURI *)URI mode: (OFString *)mode -{ - void *pool = objc_autoreleasePoolPush(); - OFFile *file = [[OFFile alloc] - initWithPath: URI.fileSystemRepresentation - mode: mode]; - - objc_autoreleasePoolPop(pool); - - return [file autorelease]; -} - -- (OFFileAttributes)attributesOfItemAtURI: (OFURI *)URI -{ - OFMutableFileAttributes ret = [OFMutableDictionary dictionary]; - void *pool = objc_autoreleasePoolPush(); - OFString *path; - int error; - Stat s; - - if (URI == nil) - @throw [OFInvalidArgumentException exception]; - - if (![[URI scheme] isEqual: _scheme]) - @throw [OFInvalidArgumentException exception]; - - path = URI.fileSystemRepresentation; - - if ((error = lstatWrapper(path, &s)) != 0) - @throw [OFGetItemAttributesFailedException - exceptionWithURI: URI - errNo: error]; - - if (s.st_size < 0) - @throw [OFOutOfRangeException exception]; - - [ret setObject: [NSNumber numberWithUnsignedLongLong: s.st_size] - forKey: OFFileSize]; - - setTypeAttribute(ret, &s); - - [ret setObject: [NSNumber numberWithUnsignedLong: s.st_mode] - forKey: OFFilePOSIXPermissions]; - - setOwnerAndGroupAttributes(ret, &s); - setDateAttributes(ret, &s); - -#ifdef OF_FILE_MANAGER_SUPPORTS_SYMLINKS - if (S_ISLNK(s.st_mode)) - setSymbolicLinkDestinationAttribute(ret, URI); -#endif - - objc_autoreleasePoolPop(pool); - - return ret; -} - -- (void)of_setLastAccessDate: (OFDate *)lastAccessDate - andModificationDate: (OFDate *)modificationDate - ofItemAtURI: (OFURI *)URI - attributes: (OFFileAttributes)attributes OF_DIRECT -{ - OFString *path = URI.fileSystemRepresentation; - OFFileAttributeKey attributeKey = (modificationDate != nil - ? OFFileModificationDate : OFFileLastAccessDate); - - if (lastAccessDate == nil) - lastAccessDate = modificationDate; - if (modificationDate == nil) - modificationDate = lastAccessDate; - -#if defined(OF_WINDOWS) - if (_wutime64FuncPtr != NULL) { - struct __utimbuf64 times = { - .actime = - (__time64_t)lastAccessDate.timeIntervalSince1970, - .modtime = - (__time64_t)modificationDate.timeIntervalSince1970 - }; - - if (_wutime64FuncPtr([path UTF16String], ×) != 0) - @throw [OFSetItemAttributesFailedException - exceptionWithURI: URI - attributes: attributes - failedAttribute: attributeKey - errNo: errno]; - } else { - struct _utimbuf times = { - .actime = (time_t)lastAccessDate.timeIntervalSince1970, - .modtime = - (time_t)modificationDate.timeIntervalSince1970 - }; - int status; - - if ([OFSystemInfo isWindowsNT]) - status = _wutime([path UTF16String], ×); - else - status = _utime( - [path cStringWithEncoding: [OFLocale encoding]], - ×); - - if (status != 0) - @throw [OFSetItemAttributesFailedException - exceptionWithURI: URI - attributes: attributes - failedAttribute: attributeKey - errNo: errno]; - } -#elif defined(OF_AMIGAOS) - /* AmigaOS does not support access time. */ - OFTimeInterval modificationTime = - modificationDate.timeIntervalSince1970; - struct Locale *locale; - struct DateStamp date; - - modificationTime -= 252460800; /* 1978-01-01 */ - - if (modificationTime < 0) - @throw [OFOutOfRangeException exception]; - - locale = OpenLocale(NULL); - /* - * FIXME: This does not take DST into account. But unfortunately, there - * is no way to figure out if DST should be in effect for the - * timestamp. - */ - modificationTime -= locale->loc_GMTOffset * 60.0; - CloseLocale(locale); - - date.ds_Days = modificationTime / 86400; - date.ds_Minute = ((LONG)modificationTime % 86400) / 60; - date.ds_Tick = fmod(modificationTime, 60) * TICKS_PER_SECOND; - -# ifdef OF_AMIGAOS4 - if (!SetDate([path cStringWithEncoding: [OFLocale encoding]], - &date) != 0) -# else - if (!SetFileDate([path cStringWithEncoding: [OFLocale encoding]], - &date) != 0) -# endif - @throw [OFSetItemAttributesFailedException - exceptionWithURI: URI - attributes: attributes - failedAttribute: attributeKey - errNo: lastError()]; -#else - OFTimeInterval lastAccessTime = lastAccessDate.timeIntervalSince1970; - OFTimeInterval modificationTime = - modificationDate.timeIntervalSince1970; - struct timeval times[2] = { - { - .tv_sec = (time_t)lastAccessTime, - .tv_usec = - (int)((lastAccessTime - times[0].tv_sec) * 1000000) - }, - { - .tv_sec = (time_t)modificationTime, - .tv_usec = (int)((modificationTime - times[1].tv_sec) * - 1000000) - }, - }; - - if (utimes([path cStringWithEncoding: [OFLocale encoding]], times) != 0) - @throw [OFSetItemAttributesFailedException - exceptionWithURI: URI - attributes: attributes - failedAttribute: attributeKey - errNo: errno]; -#endif -} - -- (void)of_setPOSIXPermissions: (OFNumber *)permissions - ofItemAtURI: (OFURI *)URI - attributes: (OFFileAttributes)attributes OF_DIRECT -{ -#ifdef OF_FILE_MANAGER_SUPPORTS_PERMISSIONS - mode_t mode = (mode_t)permissions.unsignedLongValue; - OFString *path = URI.fileSystemRepresentation; - int status; - -# ifdef OF_WINDOWS - if ([OFSystemInfo isWindowsNT]) - status = _wchmod(path.UTF16String, mode); - else -# endif - status = chmod( - [path cStringWithEncoding: [OFLocale encoding]], mode); - - if (status != 0) - @throw [OFSetItemAttributesFailedException - exceptionWithURI: URI - attributes: attributes - failedAttribute: OFFilePOSIXPermissions - errNo: errno]; -#else - OF_UNRECOGNIZED_SELECTOR -#endif -} - -- (void)of_setOwnerAccountName: (OFString *)owner - andGroupOwnerAccountName: (OFString *)group - ofItemAtURI: (OFURI *)URI - attributeKey: (OFFileAttributeKey)attributeKey - attributes: (OFFileAttributes)attributes OF_DIRECT -{ -#ifdef OF_FILE_MANAGER_SUPPORTS_OWNER - OFString *path = URI.fileSystemRepresentation; - uid_t uid = -1; - gid_t gid = -1; - OFStringEncoding encoding; - - if (owner == nil && group == nil) - @throw [OFInvalidArgumentException exception]; - - encoding = [OFLocale encoding]; - -# ifdef OF_HAVE_THREADS - [passwdMutex lock]; - @try { -# endif - if (owner != nil) { - struct passwd *passwd; - - if ((passwd = getpwnam([owner - cStringWithEncoding: encoding])) == NULL) - @throw [OFSetItemAttributesFailedException - exceptionWithURI: URI - attributes: attributes - failedAttribute: attributeKey - errNo: errno]; - - uid = passwd->pw_uid; - } - - if (group != nil) { - struct group *group_; - - if ((group_ = getgrnam([group - cStringWithEncoding: encoding])) == NULL) - @throw [OFSetItemAttributesFailedException - exceptionWithURI: URI - attributes: attributes - failedAttribute: attributeKey - errNo: errno]; - - gid = group_->gr_gid; - } -# ifdef OF_HAVE_THREADS - } @finally { - [passwdMutex unlock]; - } -# endif - - if (chown([path cStringWithEncoding: encoding], uid, gid) != 0) - @throw [OFSetItemAttributesFailedException - exceptionWithURI: URI - attributes: attributes - failedAttribute: attributeKey - errNo: errno]; -#else - OF_UNRECOGNIZED_SELECTOR -#endif -} - -- (void)setAttributes: (OFFileAttributes)attributes ofItemAtURI: (OFURI *)URI -{ - void *pool = objc_autoreleasePoolPush(); - OFEnumerator OF_GENERIC(OFFileAttributeKey) *keyEnumerator; - OFEnumerator *objectEnumerator; - OFFileAttributeKey key; - id object; - OFDate *lastAccessDate, *modificationDate; - - if (URI == nil) - @throw [OFInvalidArgumentException exception]; - - if (![URI.scheme isEqual: _scheme]) - @throw [OFInvalidArgumentException exception]; - - keyEnumerator = [attributes keyEnumerator]; - objectEnumerator = [attributes objectEnumerator]; - - while ((key = [keyEnumerator nextObject]) != nil && - (object = [objectEnumerator nextObject]) != nil) { - if ([key isEqual: OFFileModificationDate] || - [key isEqual: OFFileLastAccessDate]) - continue; - else if ([key isEqual: OFFilePOSIXPermissions]) - [self of_setPOSIXPermissions: object - ofItemAtURI: URI - attributes: attributes]; - else if ([key isEqual: OFFileOwnerAccountName]) - [self of_setOwnerAccountName: object - andGroupOwnerAccountName: nil - ofItemAtURI: URI - attributeKey: key - attributes: attributes]; - else if ([key isEqual: OFFileGroupOwnerAccountName]) - [self of_setOwnerAccountName: nil - andGroupOwnerAccountName: object - ofItemAtURI: URI - attributeKey: key - attributes: attributes]; - else - @throw [OFNotImplementedException - exceptionWithSelector: _cmd - object: self]; - } - - lastAccessDate = [attributes objectForKey: OFFileLastAccessDate]; - modificationDate = [attributes objectForKey: OFFileModificationDate]; - - if (lastAccessDate != nil || modificationDate != nil) - [self of_setLastAccessDate: lastAccessDate - andModificationDate: modificationDate - ofItemAtURI: URI - attributes: attributes]; - - objc_autoreleasePoolPop(pool); -} - -- (bool)fileExistsAtURI: (OFURI *)URI -{ - void *pool = objc_autoreleasePoolPush(); - Stat s; - bool ret; - - if (URI == nil) - @throw [OFInvalidArgumentException exception]; - - if (![URI.scheme isEqual: _scheme]) - @throw [OFInvalidArgumentException exception]; - - if (statWrapper(URI.fileSystemRepresentation, &s) != 0) { - objc_autoreleasePoolPop(pool); - return false; - } - - ret = S_ISREG(s.st_mode); - - objc_autoreleasePoolPop(pool); - - return ret; -} - -- (bool)directoryExistsAtURI: (OFURI *)URI -{ - void *pool = objc_autoreleasePoolPush(); - Stat s; - bool ret; - - if (URI == nil) - @throw [OFInvalidArgumentException exception]; - - if (![URI.scheme isEqual: _scheme]) - @throw [OFInvalidArgumentException exception]; - - if (statWrapper(URI.fileSystemRepresentation, &s) != 0) { - objc_autoreleasePoolPop(pool); - return false; - } - - ret = S_ISDIR(s.st_mode); - - objc_autoreleasePoolPop(pool); - - return ret; -} - -- (void)createDirectoryAtURI: (OFURI *)URI -{ - void *pool = objc_autoreleasePoolPush(); - OFString *path; - - if (URI == nil) - @throw [OFInvalidArgumentException exception]; - - if (![URI.scheme isEqual: _scheme]) - @throw [OFInvalidArgumentException exception]; - - path = URI.fileSystemRepresentation; - -#if defined(OF_WINDOWS) - int status; - - if ([OFSystemInfo isWindowsNT]) - status = _wmkdir(path.UTF16String); - else - status = _mkdir( - [path cStringWithEncoding: [OFLocale encoding]]); - - if (status != 0) - @throw [OFCreateDirectoryFailedException - exceptionWithURI: URI - errNo: errno]; -#elif defined(OF_AMIGAOS) - BPTR lock; - - if ((lock = CreateDir( - [path cStringWithEncoding: [OFLocale encoding]])) == 0) - @throw [OFCreateDirectoryFailedException - exceptionWithURI: URI - errNo: lastError()]; - - UnLock(lock); -#else - if (mkdir([path cStringWithEncoding: [OFLocale encoding]], 0777) != 0) - @throw [OFCreateDirectoryFailedException - exceptionWithURI: URI - errNo: errno]; -#endif - - objc_autoreleasePoolPop(pool); -} - -- (OFArray OF_GENERIC(OFURI *) *)contentsOfDirectoryAtURI: (OFURI *)URI -{ - OFMutableArray *URIs = [OFMutableArray array]; - void *pool = objc_autoreleasePoolPush(); - OFString *path; - - if (URI == nil) - @throw [OFInvalidArgumentException exception]; - - if (![URI.scheme isEqual: _scheme]) - @throw [OFInvalidArgumentException exception]; - - path = URI.fileSystemRepresentation; - -#if defined(OF_WINDOWS) - HANDLE handle; - - path = [path stringByAppendingString: @"\\*"]; - - if ([OFSystemInfo isWindowsNT]) { - WIN32_FIND_DATAW fd; - - if ((handle = FindFirstFileW(path.UTF16String, - &fd)) == INVALID_HANDLE_VALUE) - @throw [OFOpenItemFailedException - exceptionWithURI: URI - mode: nil - errNo: lastError()]; - - @try { - do { - OFString *file; - - if (wcscmp(fd.cFileName, L".") == 0 || - wcscmp(fd.cFileName, L"..") == 0) - continue; - - file = [[OFString alloc] - initWithUTF16String: fd.cFileName]; - @try { - [URIs addObject: [URI - URIByAppendingPathComponent: file]]; - } @finally { - [file release]; - } - } while (FindNextFileW(handle, &fd)); - - if (GetLastError() != ERROR_NO_MORE_FILES) - @throw [OFReadFailedException - exceptionWithObject: self - requestedLength: 0 - errNo: lastError()]; - } @finally { - FindClose(handle); - } - } else { - OFStringEncoding encoding = [OFLocale encoding]; - WIN32_FIND_DATA fd; - - if ((handle = FindFirstFileA( - [path cStringWithEncoding: encoding], &fd)) == - INVALID_HANDLE_VALUE) - @throw [OFOpenItemFailedException - exceptionWithURI: URI - mode: nil - errNo: lastError()]; - - @try { - do { - OFString *file; - - if (strcmp(fd.cFileName, ".") == 0 || - strcmp(fd.cFileName, "..") == 0) - continue; - - file = [[OFString alloc] - initWithCString: fd.cFileName - encoding: encoding]; - @try { - [URIs addObject: [URI - URIByAppendingPathComponent: file]]; - } @finally { - [file release]; - } - } while (FindNextFileA(handle, &fd)); - - if (GetLastError() != ERROR_NO_MORE_FILES) - @throw [OFReadFailedException - exceptionWithObject: self - requestedLength: 0 - errNo: lastError()]; - } @finally { - FindClose(handle); - } - } -#elif defined(OF_AMIGAOS) - OFStringEncoding encoding = [OFLocale encoding]; - BPTR lock; - - if ((lock = Lock([path cStringWithEncoding: encoding], - SHARED_LOCK)) == 0) - @throw [OFOpenItemFailedException - exceptionWithURI: URI - mode: nil - errNo: lastError()]; - - @try { -# ifdef OF_AMIGAOS4 - struct ExamineData *ed; - APTR context; - - if ((context = ObtainDirContextTags(EX_FileLockInput, lock, - EX_DoCurrentDir, TRUE, EX_DataFields, EXF_NAME, - TAG_END)) == NULL) - @throw [OFOpenItemFailedException - exceptionWithURI: URI - mode: nil - errNo: lastError()]; - - @try { - while ((ed = ExamineDir(context)) != NULL) { - OFString *file = [[OFString alloc] - initWithCString: ed->Name - encoding: encoding]; - - @try { - [URIs addObject: [URI - URIByAppendingPathComponent: file]]; - } @finally { - [file release]; - } - } - } @finally { - ReleaseDirContext(context); - } -# else - struct FileInfoBlock fib; - - if (!Examine(lock, &fib)) - @throw [OFOpenItemFailedException - exceptionWithURI: URI - mode: nil - errNo: lastError()]; - - while (ExNext(lock, &fib)) { - OFString *file = [[OFString alloc] - initWithCString: fib.fib_FileName - encoding: encoding]; - @try { - [URIs addObject: - [URI URIByAppendingPathComponent: file]]; - } @finally { - [file release]; - } - } -# endif - - if (IoErr() != ERROR_NO_MORE_ENTRIES) - @throw [OFReadFailedException - exceptionWithObject: self - requestedLength: 0 - errNo: lastError()]; - } @finally { - UnLock(lock); - } -#else - OFStringEncoding encoding = [OFLocale encoding]; - DIR *dir; - if ((dir = opendir([path cStringWithEncoding: encoding])) == NULL) - @throw [OFOpenItemFailedException exceptionWithURI: URI - mode: nil - errNo: errno]; - -# if !defined(HAVE_READDIR_R) && defined(OF_HAVE_THREADS) - @try { - [readdirMutex lock]; - } @catch (id e) { - closedir(dir); - @throw e; - } -# endif - - @try { - for (;;) { - struct dirent *dirent; -# ifdef HAVE_READDIR_R - struct dirent buffer; -# endif - OFString *file; - -# ifdef HAVE_READDIR_R - if (readdir_r(dir, &buffer, &dirent) != 0) - @throw [OFReadFailedException - exceptionWithObject: self - requestedLength: 0 - errNo: errno]; - - if (dirent == NULL) - break; -# else - errno = 0; - if ((dirent = readdir(dir)) == NULL) { - if (errno == 0) - break; - else - @throw [OFReadFailedException - exceptionWithObject: self - requestedLength: 0 - errNo: errno]; - } -# endif - - if (strcmp(dirent->d_name, ".") == 0 || - strcmp(dirent->d_name, "..") == 0) - continue; - - file = [[OFString alloc] initWithCString: dirent->d_name - encoding: encoding]; - @try { - [URIs addObject: - [URI URIByAppendingPathComponent: file]]; - } @finally { - [file release]; - } - } - } @finally { - closedir(dir); -# if !defined(HAVE_READDIR_R) && defined(OF_HAVE_THREADS) - [readdirMutex unlock]; -# endif - } -#endif - - [URIs makeImmutable]; - - objc_autoreleasePoolPop(pool); - - return URIs; -} - -- (void)removeItemAtURI: (OFURI *)URI -{ - void *pool = objc_autoreleasePoolPush(); - OFString *path; - int error; - Stat s; - - if (URI == nil) - @throw [OFInvalidArgumentException exception]; - - if (![URI.scheme isEqual: _scheme]) - @throw [OFInvalidArgumentException exception]; - - path = URI.fileSystemRepresentation; - - if ((error = lstatWrapper(path, &s)) != 0) - @throw [OFRemoveItemFailedException exceptionWithURI: URI - errNo: error]; - - if (S_ISDIR(s.st_mode)) { - OFArray OF_GENERIC(OFURI *) *contents; - - @try { - contents = [self contentsOfDirectoryAtURI: URI]; - } @catch (id e) { - /* - * Only convert exceptions to - * OFRemoveItemFailedException that have an errNo - * property. This covers all I/O related exceptions - * from the operations used to remove an item, all - * others should be left as is. - */ - if ([e respondsToSelector: @selector(errNo)]) - @throw [OFRemoveItemFailedException - exceptionWithURI: URI - errNo: [e errNo]]; - - @throw e; - } - - for (OFURI *item in contents) { - void *pool2 = objc_autoreleasePoolPush(); - - [self removeItemAtURI: item]; - - objc_autoreleasePoolPop(pool2); - } - -#ifndef OF_AMIGAOS - int status; - -# ifdef OF_WINDOWS - if ([OFSystemInfo isWindowsNT]) - status = _wrmdir(path.UTF16String); - else -# endif - status = rmdir( - [path cStringWithEncoding: [OFLocale encoding]]); - - if (status != 0) - @throw [OFRemoveItemFailedException - exceptionWithURI: URI - errNo: errno]; - } else { - int status; - -# ifdef OF_WINDOWS - if ([OFSystemInfo isWindowsNT]) - status = _wunlink(path.UTF16String); - else -# endif - status = unlink( - [path cStringWithEncoding: [OFLocale encoding]]); - - if (status != 0) - @throw [OFRemoveItemFailedException - exceptionWithURI: URI - errNo: errno]; -#endif - } - -#ifdef OF_AMIGAOS - if (!DeleteFile([path cStringWithEncoding: [OFLocale encoding]])) - @throw [OFRemoveItemFailedException - exceptionWithURI: URI - errNo: lastError()]; -#endif - - objc_autoreleasePoolPop(pool); -} - -#ifdef OF_FILE_MANAGER_SUPPORTS_LINKS -- (void)linkItemAtURI: (OFURI *)source toURI: (OFURI *)destination -{ - void *pool = objc_autoreleasePoolPush(); - OFString *sourcePath, *destinationPath; - - if (source == nil || destination == nil) - @throw [OFInvalidArgumentException exception]; - - if (![source.scheme isEqual: _scheme] || - ![destination.scheme isEqual: _scheme]) - @throw [OFInvalidArgumentException exception]; - - sourcePath = source.fileSystemRepresentation; - destinationPath = destination.fileSystemRepresentation; - -# ifndef OF_WINDOWS - OFStringEncoding encoding = [OFLocale encoding]; - - if (link([sourcePath cStringWithEncoding: encoding], - [destinationPath cStringWithEncoding: encoding]) != 0) - @throw [OFLinkItemFailedException - exceptionWithSourceURI: source - destinationURI: destination - errNo: errno]; -# else - if (createHardLinkWFuncPtr == NULL) - @throw [OFNotImplementedException exceptionWithSelector: _cmd - object: self]; - - if (!createHardLinkWFuncPtr(destinationPath.UTF16String, - sourcePath.UTF16String, NULL)) - @throw [OFLinkItemFailedException - exceptionWithSourceURI: source - destinationURI: destination - errNo: lastError()]; -# endif - - objc_autoreleasePoolPop(pool); -} -#endif - -#ifdef OF_FILE_MANAGER_SUPPORTS_SYMLINKS -- (void)createSymbolicLinkAtURI: (OFURI *)URI - withDestinationPath: (OFString *)target -{ - void *pool = objc_autoreleasePoolPush(); - OFString *path; - - if (URI == nil || target == nil) - @throw [OFInvalidArgumentException exception]; - - if (![URI.scheme isEqual: _scheme]) - @throw [OFInvalidArgumentException exception]; - - path = URI.fileSystemRepresentation; - -# ifndef OF_WINDOWS - OFStringEncoding encoding = [OFLocale encoding]; - - if (symlink([target cStringWithEncoding: encoding], - [path cStringWithEncoding: encoding]) != 0) - @throw [OFCreateSymbolicLinkFailedException - exceptionWithURI: URI - target: target - errNo: errno]; -# else - if (createSymbolicLinkWFuncPtr == NULL) - @throw [OFNotImplementedException exceptionWithSelector: _cmd - object: self]; - - if (!createSymbolicLinkWFuncPtr(path.UTF16String, target.UTF16String, - 0)) - @throw [OFCreateSymbolicLinkFailedException - exceptionWithURI: URI - target: target - errNo: lastError()]; -# endif - - objc_autoreleasePoolPop(pool); -} -#endif - -- (bool)moveItemAtURI: (OFURI *)source toURI: (OFURI *)destination -{ - void *pool; - - if (![source.scheme isEqual: _scheme] || - ![destination.scheme isEqual: _scheme]) - return false; - - if ([self fileExistsAtURI: destination]) - @throw [OFMoveItemFailedException - exceptionWithSourceURI: source - destinationURI: destination - errNo: EEXIST]; - - pool = objc_autoreleasePoolPush(); - -#ifdef OF_AMIGAOS - OFStringEncoding encoding = [OFLocale encoding]; - - if (!Rename([source.fileSystemRepresentation - cStringWithEncoding: encoding], - [destination.fileSystemRepresentation - cStringWithEncoding: encoding])) - @throw [OFMoveItemFailedException - exceptionWithSourceURI: source - destinationURI: destination - errNo: lastError()]; -#else - int status; - -# ifdef OF_WINDOWS - if ([OFSystemInfo isWindowsNT]) - status = _wrename(source.fileSystemRepresentation.UTF16String, - destination.fileSystemRepresentation.UTF16String); - else { -# endif - OFStringEncoding encoding = [OFLocale encoding]; - - status = rename([source.fileSystemRepresentation - cStringWithEncoding: encoding], - [destination.fileSystemRepresentation - cStringWithEncoding: encoding]); -# ifdef OF_WINDOWS - } -# endif - - if (status != 0) - @throw [OFMoveItemFailedException - exceptionWithSourceURI: source - destinationURI: destination - errNo: errno]; -#endif - - objc_autoreleasePoolPop(pool); - - return true; -} -@end Index: src/OFGZIPStream.h ================================================================== --- src/OFGZIPStream.h +++ src/OFGZIPStream.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -304,17 +304,16 @@ @throw [OFNotOpenException exceptionWithObject: self]; return _stream.atEndOfStream; } -- (bool)hasDataInReadBuffer +- (bool)lowlevelHasDataInReadBuffer { if (_state == OFGZIPStreamStateData) - return (super.hasDataInReadBuffer || - _inflateStream.hasDataInReadBuffer); - - return (super.hasDataInReadBuffer || _stream.hasDataInReadBuffer); + return _inflateStream.hasDataInReadBuffer; + else + return _stream.hasDataInReadBuffer; } - (void)close { if (_stream == nil) Index: src/OFHMAC.h ================================================================== --- src/OFHMAC.h +++ src/OFHMAC.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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.m ================================================================== --- src/OFHMAC.m +++ src/OFHMAC.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFHTTPClient.h ================================================================== --- src/OFHTTPClient.h +++ src/OFHTTPClient.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -23,23 +23,24 @@ @class OFDictionary OF_GENERIC(KeyType, ObjectType); @class OFHTTPClient; @class OFHTTPRequest; @class OFHTTPResponse; +@class OFIRI; @class OFStream; @class OFTCPSocket; @class OFTLSStream; -@class OFURI; /** * @protocol OFHTTPClientDelegate OFHTTPClient.h ObjFW/OFHTTPClient.h * * @brief A delegate for OFHTTPClient. */ @protocol OFHTTPClientDelegate /** - * @brief A callback which is called when an OFHTTPClient performed a request. + * @brief A callback which is called when an @ref OFHTTPClient performed a + * request. * * @param client The OFHTTPClient which performed the request * @param request The request the OFHTTPClient performed * @param response The response to the request performed, or nil on error * @param exception An exception if the request failed, or nil on success @@ -49,11 +50,12 @@ response: (nullable OFHTTPResponse *)response exception: (nullable id)exception; @optional /** - * @brief A callback which is called when an OFHTTPClient creates a TCP socket. + * @brief A callback which is called when an @ref OFHTTPClient creates a TCP + * socket. * * This can be used to tell the socket about a SOCKS5 proxy it should use for * this connection. * * @param client The OFHTTPClient that created a TCP socket @@ -63,11 +65,12 @@ - (void)client: (OFHTTPClient *)client didCreateTCPSocket: (OFTCPSocket *)TCPSocket request: (OFHTTPRequest *)request; /** - * @brief A callback which is called when an OFHTTPClient creates a TLS stream. + * @brief A callback which is called when an @ref OFHTTPClient creates a TLS + * stream. * * This can be used to tell the TLS stream about a client certificate it should * use before performing the TLS handshake. * * @param client The OFHTTPClient that created a TLS stream @@ -77,12 +80,12 @@ - (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. + * @brief A callback which is called when an @ref OFHTTPClient wants to send + * the body for a request. * * @param client The OFHTTPClient that wants to send the body * @param requestBody A stream into which the body of the request should be * written * @param request The request for which the OFHTTPClient wants to send the body @@ -90,11 +93,11 @@ - (void)client: (OFHTTPClient *)client wantsRequestBody: (OFStream *)requestBody request: (OFHTTPRequest *)request; /** - * @brief A callback which is called when an OFHTTPClient received headers. + * @brief A callback which is called when an @ref OFHTTPClient received headers. * * @param client The OFHTTPClient which received the headers * @param headers The headers received * @param statusCode The status code received * @param request The request for which the headers and status code have been @@ -104,12 +107,12 @@ didReceiveHeaders: (OFDictionary OF_GENERIC(OFString *, OFString *) *)headers statusCode: (short)statusCode request: (OFHTTPRequest *)request; /** - * @brief A callback which is called when an OFHTTPClient wants to follow a - * redirect. + * @brief A callback which is called when an @ref OFHTTPClient wants to follow + * a redirect. * * If you want to get the headers and data for each redirect, set the number of * redirects to 0 and perform a new OFHTTPClient for each redirect. However, * this callback will not be called then and you have to look at the status code * to detect a redirect. @@ -117,22 +120,22 @@ * This callback will only be called if the OFHTTPClient will follow a * redirect. If the maximum number of redirects has been reached already, this * callback will not be called. * * @param client The OFHTTPClient which wants to follow a redirect - * @param URI The URI to which it will follow a redirect + * @param IRI The IRI to which it will follow a redirect * @param statusCode The status code for the redirection * @param request The request for which the OFHTTPClient wants to redirect. * You are allowed to change the request's headers from this * callback and they will be used when following the redirect - * (e.g. to set the cookies for the new URI), however, keep in + * (e.g. to set the cookies for the new IRI), however, keep in * mind that this will change the request you originally passed. * @param response The response indicating the redirect * @return A boolean whether the OFHTTPClient should follow the redirect */ - (bool)client: (OFHTTPClient *)client - shouldFollowRedirectToURI: (OFURI *)URI + shouldFollowRedirectToIRI: (OFIRI *)IRI statusCode: (short)statusCode request: (OFHTTPRequest *)request response: (OFHTTPResponse *)response; @end @@ -148,11 +151,11 @@ @public #endif OFObject *_Nullable _delegate; bool _allowsInsecureRedirects, _inProgress; OFStream *_Nullable _stream; - OFURI *_Nullable _lastURI; + OFIRI *_Nullable _lastIRI; bool _lastWasHEAD; OFHTTPResponse *_Nullable _lastResponse; } /** @@ -184,11 +187,11 @@ * @return The OFHTTPResponse for the request * @throw OFHTTPRequestFailedException The HTTP request failed * @throw OFInvalidServerResponseException The server sent an invalid response * @throw OFUnsupportedVersionException The server responded in an unsupported * version - * @throw OFAlreadyConnectedException The client is already performing a request + * @throw OFAlreadyOpenException The client is already performing a request */ - (OFHTTPResponse *)performRequest: (OFHTTPRequest *)request; /** * @brief Synchronously performs the specified HTTP request. @@ -204,20 +207,20 @@ * @return The OFHTTPResponse for the request * @throw OFHTTPRequestFailedException The HTTP request failed * @throw OFInvalidServerResponseException The server sent an invalid response * @throw OFUnsupportedVersionException The server responded in an unsupported * version - * @throw OFAlreadyConnectedException The client is already performing a request + * @throw OFAlreadyOpenException The client is already performing a request */ - (OFHTTPResponse *)performRequest: (OFHTTPRequest *)request redirects: (unsigned int)redirects; /** * @brief Asynchronously performs the specified HTTP request. * * @param request The request to perform - * @throw OFAlreadyConnectedException The client is already performing a request + * @throw OFAlreadyOpenException The client is already performing a request */ - (void)asyncPerformRequest: (OFHTTPRequest *)request; /** * @brief Asynchronously performs the specified HTTP request. @@ -224,11 +227,11 @@ * * @param request The request to perform * @param redirects The maximum number of redirects after which no further * attempt is done to follow the redirect, but instead the * redirect is treated as an OFHTTPResponse - * @throw OFAlreadyConnectedException The client is already performing a request + * @throw OFAlreadyOpenException The client is already performing a request */ - (void)asyncPerformRequest: (OFHTTPRequest *)request redirects: (unsigned int)redirects; /** Index: src/OFHTTPClient.m ================================================================== --- src/OFHTTPClient.m +++ src/OFHTTPClient.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -23,19 +23,19 @@ #import "OFHTTPClient.h" #import "OFData.h" #import "OFDictionary.h" #import "OFHTTPRequest.h" #import "OFHTTPResponse.h" +#import "OFIRI.h" #import "OFKernelEventObserver.h" #import "OFNumber.h" #import "OFRunLoop.h" #import "OFString.h" #import "OFTCPSocket.h" #import "OFTLSStream.h" -#import "OFURI.h" -#import "OFAlreadyConnectedException.h" +#import "OFAlreadyOpenException.h" #import "OFHTTPRequestFailedException.h" #import "OFInvalidArgumentException.h" #import "OFInvalidEncodingException.h" #import "OFInvalidFormatException.h" #import "OFInvalidServerResponseException.h" @@ -115,30 +115,30 @@ static OFString * constructRequestString(OFHTTPRequest *request) { void *pool = objc_autoreleasePoolPush(); OFHTTPRequestMethod method = request.method; - OFURI *URI = request.URI; + OFIRI *IRI = request.IRI.IRIByAddingPercentEncodingForUnicodeCharacters; OFString *path; - OFString *user = URI.user, *password = URI.password; + OFString *user = IRI.user, *password = IRI.password; OFMutableString *requestString; OFMutableDictionary OF_GENERIC(OFString *, OFString *) *headers; bool hasContentLength, chunked; OFEnumerator OF_GENERIC(OFString *) *keyEnumerator, *objectEnumerator; OFString *key, *object; - if (URI.path.length > 0) - path = URI.percentEncodedPath; + if (IRI.path.length > 0) + path = IRI.percentEncodedPath; else path = @"/"; requestString = [OFMutableString stringWithFormat: - @"%s %@", OFHTTPRequestMethodName(method), path]; + @"%@ %@", OFHTTPRequestMethodString(method), path]; - if (URI.query != nil) { + if (IRI.query != nil) { [requestString appendString: @"?"]; - [requestString appendString: URI.percentEncodedQuery]; + [requestString appendString: IRI.percentEncodedQuery]; } [requestString appendString: @" HTTP/"]; [requestString appendString: request.protocolVersionString]; [requestString appendString: @"\r\n"]; @@ -146,19 +146,19 @@ headers = [[request.headers mutableCopy] autorelease]; if (headers == nil) headers = [OFMutableDictionary dictionary]; if ([headers objectForKey: @"Host"] == nil) { - OFNumber *port = URI.port; + OFNumber *port = IRI.port; if (port != nil) { OFString *host = [OFString stringWithFormat: - @"%@:%@", URI.percentEncodedHost, port]; + @"%@:%@", IRI.percentEncodedHost, port]; [headers setObject: host forKey: @"Host"]; } else - [headers setObject: URI.percentEncodedHost + [headers setObject: IRI.percentEncodedHost forKey: @"Host"]; } if ((user.length > 0 || password.length > 0) && [headers objectForKey: @"Authorization"] == nil) { @@ -176,12 +176,12 @@ [headers setObject: authorization forKey: @"Authorization"]; } if ([headers objectForKey: @"User-Agent"] == nil) - [headers setObject: @"Something using ObjFW " - @"" + [headers setObject: @"OFHTTPClient (ObjFW's HTTP client class " + @")" forKey: @"User-Agent"]; if (request.protocolVersion.major == 1 && request.protocolVersion.minor == 0 && [headers objectForKey: @"Connection"] == nil) @@ -297,11 +297,11 @@ exception: exception]; } - (void)createResponseWithStreamOrThrow: (OFStream *)stream { - OFURI *URI = _request.URI; + OFIRI *IRI = _request.IRI; OFHTTPClientResponse *response; OFString *connectionHeader; bool keepAlive; OFString *location; id exception; @@ -328,44 +328,44 @@ if (keepAlive) { response.of_keepAlive = true; _client->_stream = [stream retain]; - _client->_lastURI = [URI copy]; + _client->_lastIRI = [IRI copy]; _client->_lastWasHEAD = (_request.method == OFHTTPRequestMethodHead); _client->_lastResponse = [response retain]; } if (_redirects > 0 && (_status == 301 || _status == 302 || _status == 303 || _status == 307) && (location = [_serverHeaders objectForKey: @"Location"]) != nil) { bool follow = true; - OFURI *newURI; - OFString *newURIScheme; + OFIRI *newIRI; + OFString *newIRIScheme; - newURI = [OFURI URIWithString: location relativeToURI: URI]; - newURIScheme = newURI.scheme; + newIRI = [OFIRI IRIWithString: location relativeToIRI: IRI]; + newIRIScheme = newIRI.scheme; - if ([newURIScheme caseInsensitiveCompare: @"http"] != + if ([newIRIScheme caseInsensitiveCompare: @"http"] != OFOrderedSame && - [newURIScheme caseInsensitiveCompare: @"https"] != + [newIRIScheme caseInsensitiveCompare: @"https"] != OFOrderedSame) follow = false; if (!_client->_allowsInsecureRedirects && - [URI.scheme caseInsensitiveCompare: @"https"] == + [IRI.scheme caseInsensitiveCompare: @"https"] == OFOrderedSame && - [newURIScheme caseInsensitiveCompare: @"http"] == + [newIRIScheme caseInsensitiveCompare: @"http"] == OFOrderedSame) follow = false; if (follow && [_client->_delegate respondsToSelector: - @selector(client:shouldFollowRedirectToURI:statusCode: + @selector(client:shouldFollowRedirectToIRI:statusCode: request:response:)]) follow = [_client->_delegate client: _client - shouldFollowRedirectToURI: newURI + shouldFollowRedirectToIRI: newIRI statusCode: _status request: _request response: response]; else if (follow) follow = defaultShouldFollow(_request.method, _status); @@ -376,37 +376,29 @@ OFHTTPRequest *newRequest = [[_request copy] autorelease]; OFMutableDictionary *newHeaders = [[headers mutableCopy] autorelease]; - if (![newURI.host isEqual: URI.host]) + if (![newIRI.host isEqual: IRI.host]) [newHeaders removeObjectForKey: @"Host"]; /* * 303 means the request should be converted to a GET * request before redirection. This also means stripping * the entity of the request. */ if (_status == 303) { - OFEnumerator *keyEnumerator, *objectEnumerator; - OFString *key, *object; - - keyEnumerator = [headers keyEnumerator]; - objectEnumerator = [headers objectEnumerator]; - while ((key = [keyEnumerator nextObject]) != - nil && - (object = [objectEnumerator nextObject]) != - nil) + for (OFString *key in headers) if ([key hasPrefix: @"Content-"] || [key hasPrefix: @"Transfer-"]) [newHeaders removeObjectForKey: key]; newRequest.method = OFHTTPRequestMethodGet; } - newRequest.URI = newURI; + newRequest.IRI = newIRI; newRequest.headers = newHeaders; _client->_inProgress = false; [_client asyncPerformRequest: newRequest @@ -638,27 +630,25 @@ if (exception != nil) { [self raiseException: exception]; return; } - sock.canBlock = false; - if ([_client->_delegate respondsToSelector: @selector(client:didCreateTCPSocket:request:)]) [_client->_delegate client: _client didCreateTCPSocket: sock request: _request]; - if ([_request.URI.scheme caseInsensitiveCompare: @"https"] == + if ([_request.IRI.scheme caseInsensitiveCompare: @"https"] == OFOrderedSame) { OFTLSStream *stream; @try { stream = [OFTLSStream streamWithStream: sock]; } @catch (OFNotImplementedException *e) { [self raiseException: [OFUnsupportedProtocolException - exceptionWithURI: _request.URI]]; + exceptionWithIRI: _request.IRI]]; return; } if ([_client->_delegate respondsToSelector: @selector(client:didCreateTLSStream:request:)]) @@ -665,11 +655,12 @@ [_client->_delegate client: _client didCreateTLSStream: stream request: _request]; stream.delegate = self; - [stream asyncPerformClientHandshakeWithHost: _request.URI.host]; + [stream asyncPerformClientHandshakeWithHost: _request.IRI + .IRIByAddingPercentEncodingForUnicodeCharacters.host]; } else { sock.delegate = self; [self performSelector: @selector(handleStream:) withObject: sock afterDelay: 0]; @@ -690,30 +681,30 @@ afterDelay: 0]; } - (void)start { - OFURI *URI = _request.URI; + OFIRI *IRI = _request.IRI; OFStream *stream; /* Can we reuse the last socket? */ if (_client->_stream != nil && !_client->_stream.atEndOfStream && - [_client->_lastURI.scheme isEqual: URI.scheme] && - [_client->_lastURI.host isEqual: URI.host] && - (_client->_lastURI.port == URI.port || - [_client->_lastURI.port isEqual: URI.port]) && + [_client->_lastIRI.scheme isEqual: IRI.scheme] && + [_client->_lastIRI.host isEqual: IRI.host] && + (_client->_lastIRI.port == IRI.port || + [_client->_lastIRI.port isEqual: IRI.port]) && (_client->_lastWasHEAD || _client->_lastResponse.atEndOfStream)) { /* * Set _stream to nil, so that in case of an error it won't be * reused. If everything is successful, we set _stream again * at the end. */ stream = [_client->_stream autorelease]; _client->_stream = nil; - [_client->_lastURI release]; - _client->_lastURI = nil; + [_client->_lastIRI release]; + _client->_lastIRI = nil; [_client->_lastResponse release]; _client->_lastResponse = nil; stream.delegate = self; @@ -726,31 +717,32 @@ } - (void)closeAndReconnect { @try { - OFURI *URI = _request.URI; + OFIRI *IRI = + _request.IRI.IRIByAddingPercentEncodingForUnicodeCharacters; OFTCPSocket *sock; uint16_t port; - OFNumber *URIPort; + OFNumber *IRIPort; [_client close]; sock = [OFTCPSocket socket]; - if ([URI.scheme caseInsensitiveCompare: @"https"] == + if ([IRI.scheme caseInsensitiveCompare: @"https"] == OFOrderedSame) port = 443; else port = 80; - URIPort = URI.port; - if (URIPort != nil) - port = URIPort.unsignedShortValue; + IRIPort = IRI.port; + if (IRIPort != nil) + port = IRIPort.unsignedShortValue; sock.delegate = self; - [sock asyncConnectToHost: URI.host port: port]; + [sock asyncConnectToHost: IRI.host port: port]; } @catch (id e) { [self raiseException: e]; } } @end @@ -1074,13 +1066,13 @@ return ((OFStream *)_stream) .fileDescriptorForReading; } -- (bool)hasDataInReadBuffer +- (bool)lowlevelHasDataInReadBuffer { - return (super.hasDataInReadBuffer || _stream.hasDataInReadBuffer); + return _stream.hasDataInReadBuffer; } - (void)close { if (_stream == nil) @@ -1201,19 +1193,19 @@ statusCode: statusCode request: request]; } - (bool)client: (OFHTTPClient *)client - shouldFollowRedirectToURI: (OFURI *)URI + shouldFollowRedirectToIRI: (OFIRI *)IRI statusCode: (short)statusCode request: (OFHTTPRequest *)request response: (OFHTTPResponse *)response { if ([_delegate respondsToSelector: @selector( - client:shouldFollowRedirectToURI:statusCode:request:response:)]) + client:shouldFollowRedirectToIRI:statusCode:request:response:)]) return [_delegate client: client - shouldFollowRedirectToURI: URI + shouldFollowRedirectToIRI: IRI statusCode: statusCode request: request response: response]; else return defaultShouldFollow(request.method, statusCode); @@ -1265,19 +1257,19 @@ - (void)asyncPerformRequest: (OFHTTPRequest *)request redirects: (unsigned int)redirects { void *pool = objc_autoreleasePoolPush(); - OFURI *URI = request.URI; - OFString *scheme = URI.scheme; + OFIRI *IRI = request.IRI; + OFString *scheme = IRI.scheme; if ([scheme caseInsensitiveCompare: @"http"] != OFOrderedSame && [scheme caseInsensitiveCompare: @"https"] != OFOrderedSame) - @throw [OFUnsupportedProtocolException exceptionWithURI: URI]; + @throw [OFUnsupportedProtocolException exceptionWithIRI: IRI]; if (_inProgress) - @throw [OFAlreadyConnectedException exception]; + @throw [OFAlreadyOpenException exceptionWithObject: self]; _inProgress = true; [[[[OFHTTPClientRequestHandler alloc] initWithClient: self @@ -1290,12 +1282,12 @@ - (void)close { [_stream release]; _stream = nil; - [_lastURI release]; - _lastURI = nil; + [_lastIRI release]; + _lastIRI = nil; [_lastResponse release]; _lastResponse = nil; } @end Index: src/OFHTTPCookie.h ================================================================== --- src/OFHTTPCookie.h +++ src/OFHTTPCookie.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,12 +19,12 @@ OF_ASSUME_NONNULL_BEGIN @class OFArray OF_GENERIC(ObjectType); @class OFDate; @class OFDictionary OF_GENERIC(KeyType, ObjectType); +@class OFIRI; @class OFMutableArray OF_GENERIC(ObjectType); -@class OFURI; /** * @class OFHTTPCookie OFHTTPCookie.h ObjFW/OFHTTPCookie.h * * @brief A class for storing and manipulating HTTP cookies. @@ -78,22 +78,22 @@ */ @property (readonly, nonatomic) OFMutableArray OF_GENERIC(OFString *) *extensions; /** - * @brief Parses the specified response header fields for the specified URI and + * @brief Parses the specified response header fields for the specified IRI and * returns an array of cookies. * * @param headerFields The response header fields to parse - * @param URI The URI for the response header fields to parse + * @param IRI The IRI for the response header fields to parse * @return An array of cookies * @throw OFInvalidFormatException The specified response header has an invalid * format */ + (OFArray OF_GENERIC(OFHTTPCookie *) *)cookiesWithResponseHeaderFields: (OFDictionary OF_GENERIC(OFString *, OFString *) *)headerFields - forURI: (OFURI *)URI; + forIRI: (OFIRI *)IRI; /** * @brief Returns the request header fields for the specified cookies. * * @param cookies The cookies to return the request header fields for Index: src/OFHTTPCookie.m ================================================================== --- src/OFHTTPCookie.m +++ src/OFHTTPCookie.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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 "OFHTTPCookie.h" #import "OFArray.h" #import "OFDate.h" #import "OFDictionary.h" -#import "OFURI.h" +#import "OFIRI.h" #import "OFInvalidFormatException.h" static void handleAttribute(OFHTTPCookie *cookie, OFString *name, OFString *value) @@ -60,16 +60,17 @@ @synthesize expires = _expires, secure = _secure, HTTPOnly = _HTTPOnly; @synthesize extensions = _extensions; + (OFArray OF_GENERIC(OFHTTPCookie *) *)cookiesWithResponseHeaderFields: (OFDictionary OF_GENERIC(OFString *, OFString *) *)headerFields - forURI: (OFURI *)URI + forIRI: (OFIRI *)IRI { OFMutableArray OF_GENERIC(OFHTTPCookie *) *ret = [OFMutableArray array]; void *pool = objc_autoreleasePoolPush(); OFString *string = [headerFields objectForKey: @"Set-Cookie"]; - OFString *domain = URI.host; + OFString *domain = IRI.IRIByAddingPercentEncodingForUnicodeCharacters + .host; const OFUnichar *characters = string.characters; size_t length = string.length, last = 0; enum { statePreName, stateName, Index: src/OFHTTPCookieManager.h ================================================================== --- src/OFHTTPCookieManager.h +++ src/OFHTTPCookieManager.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,12 +17,12 @@ OF_ASSUME_NONNULL_BEGIN @class OFArray OF_GENERIC(ObjectType); @class OFHTTPCookie; +@class OFIRI; @class OFMutableArray OF_GENERIC(ObjectType); -@class OFURI; /** * @class OFHTTPCookieManager OFHTTPCookieManager.h ObjFW/OFHTTPCookieManager.h * * @brief A class for managing cookies for multiple domains. @@ -44,42 +44,42 @@ * @return A new, autoreleased OFHTTPCookieManager */ + (instancetype)manager; /** - * @brief Adds the specified cookie for the specified URI. + * @brief Adds the specified cookie for the specified IRI. * * @warning This modifies the cookie (e.g. it sets the domain if it is unset)! * If you do not want this, pass a copy! * * @param cookie The cookie to add to the manager - * @param URI The URI for which the cookie should be added + * @param IRI The IRI for which the cookie should be added */ -- (void)addCookie: (OFHTTPCookie *)cookie forURI: (OFURI *)URI; +- (void)addCookie: (OFHTTPCookie *)cookie forIRI: (OFIRI *)IRI; /** - * @brief Adds the specified cookies for the specified URI. + * @brief Adds the specified cookies for the specified IRI. * * @warning This modifies the cookies (e.g. it sets the domain if it is unset)! * If you do not want this, pass copies! * * @param cookies An array of cookies to add to the manager - * @param URI The URI for which the cookies should be added + * @param IRI The IRI for which the cookies should be added */ - (void)addCookies: (OFArray OF_GENERIC(OFHTTPCookie *) *)cookies - forURI: (OFURI *)URI; + forIRI: (OFIRI *)IRI; /** - * @brief Returns the cookies for the specified URI. + * @brief Returns the cookies for the specified IRI. * - * @param URI The URI for which the cookies should be returned - * @return The cookies for the specified URI + * @param IRI The IRI for which the cookies should be returned + * @return The cookies for the specified IRI */ -- (OFArray OF_GENERIC(OFHTTPCookie *) *)cookiesForURI: (OFURI *)URI; +- (OFArray OF_GENERIC(OFHTTPCookie *) *)cookiesForIRI: (OFIRI *)IRI; /** * @brief Purges all expired cookies. */ - (void)purgeExpiredCookies; @end OF_ASSUME_NONNULL_END Index: src/OFHTTPCookieManager.m ================================================================== --- src/OFHTTPCookieManager.m +++ src/OFHTTPCookieManager.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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 "OFHTTPCookieManager.h" #import "OFArray.h" #import "OFDate.h" #import "OFHTTPCookie.h" -#import "OFURI.h" +#import "OFIRI.h" @implementation OFHTTPCookieManager + (instancetype)manager { return [[[self alloc] init] autorelease]; @@ -51,33 +51,35 @@ - (OFArray OF_GENERIC(OFHTTPCookie *) *)cookies { return [[_cookies copy] autorelease]; } -- (void)addCookie: (OFHTTPCookie *)cookie forURI: (OFURI *)URI +- (void)addCookie: (OFHTTPCookie *)cookie forIRI: (OFIRI *)IRI { void *pool = objc_autoreleasePoolPush(); - OFString *cookieDomain, *URIHost; + OFString *cookieDomain, *IRIHost; size_t i; + + IRI = IRI.IRIByAddingPercentEncodingForUnicodeCharacters; if (![cookie.path hasPrefix: @"/"]) cookie.path = @"/"; if (cookie.secure && - [URI.scheme caseInsensitiveCompare: @"https"] != OFOrderedSame) { + [IRI.scheme caseInsensitiveCompare: @"https"] != OFOrderedSame) { objc_autoreleasePoolPop(pool); return; } cookieDomain = cookie.domain.lowercaseString; cookie.domain = cookieDomain; - URIHost = URI.host.lowercaseString; - if (![cookieDomain isEqual: URIHost]) { - URIHost = [@"." stringByAppendingString: URIHost]; + IRIHost = IRI.host.lowercaseString; + if (![cookieDomain isEqual: IRIHost]) { + IRIHost = [@"." stringByAppendingString: IRIHost]; - if (![cookieDomain hasSuffix: URIHost]) { + if (![cookieDomain hasSuffix: IRIHost]) { objc_autoreleasePoolPop(pool); return; } } @@ -98,78 +100,83 @@ objc_autoreleasePoolPop(pool); } - (void)addCookies: (OFArray OF_GENERIC(OFHTTPCookie *) *)cookies - forURI: (OFURI *)URI + forIRI: (OFIRI *)IRI { for (OFHTTPCookie *cookie in cookies) - [self addCookie: cookie forURI: URI]; + [self addCookie: cookie forIRI: IRI]; } -- (OFArray OF_GENERIC(OFHTTPCookie *) *)cookiesForURI: (OFURI *)URI +- (OFArray OF_GENERIC(OFHTTPCookie *) *)cookiesForIRI: (OFIRI *)IRI { OFMutableArray *ret = [OFMutableArray array]; + void *pool = objc_autoreleasePoolPush(); + + IRI = IRI.IRIByAddingPercentEncodingForUnicodeCharacters; for (OFHTTPCookie *cookie in _cookies) { - void *pool; + void *pool2; OFDate *expires; - OFString *cookieDomain, *URIHost, *cookiePath, *URIPath; + OFString *cookieDomain, *IRIHost, *cookiePath, *IRIPath; bool match; expires = cookie.expires; if (expires != nil && expires.timeIntervalSinceNow <= 0) continue; - if (cookie.secure && [URI.scheme caseInsensitiveCompare: + if (cookie.secure && [IRI.scheme caseInsensitiveCompare: @"https"] != OFOrderedSame) continue; - pool = objc_autoreleasePoolPush(); + pool2 = objc_autoreleasePoolPush(); cookieDomain = cookie.domain.lowercaseString; - URIHost = URI.host.lowercaseString; + IRIHost = IRI.host.lowercaseString; if ([cookieDomain hasPrefix: @"."]) { - if ([URIHost hasSuffix: cookieDomain]) + if ([IRIHost hasSuffix: cookieDomain]) match = true; else { cookieDomain = [cookieDomain substringFromIndex: 1]; - match = [cookieDomain isEqual: URIHost]; + match = [cookieDomain isEqual: IRIHost]; } } else - match = [cookieDomain isEqual: URIHost]; + match = [cookieDomain isEqual: IRIHost]; if (!match) { - objc_autoreleasePoolPop(pool); + objc_autoreleasePoolPop(pool2); continue; } cookiePath = cookie.path; - URIPath = URI.path; + IRIPath = IRI.path; if (![cookiePath isEqual: @"/"]) { - if ([cookiePath isEqual: URIPath]) + if ([cookiePath isEqual: IRIPath]) match = true; else { if (![cookiePath hasSuffix: @"/"]) cookiePath = [cookiePath stringByAppendingString: @"/"]; - match = [URIPath hasPrefix: cookiePath]; + match = [IRIPath hasPrefix: cookiePath]; } if (!match) { - objc_autoreleasePoolPop(pool); + objc_autoreleasePoolPop(pool2); continue; } } [ret addObject: cookie]; } [ret makeImmutable]; + + objc_autoreleasePoolPop(pool); return ret; } - (void)purgeExpiredCookies ADDED src/OFHTTPIRIHandler.h Index: src/OFHTTPIRIHandler.h ================================================================== --- /dev/null +++ src/OFHTTPIRIHandler.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2008-2024 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#import "OFIRIHandler.h" + +OF_ASSUME_NONNULL_BEGIN + +@interface OFHTTPIRIHandler: OFIRIHandler +@end + +OF_ASSUME_NONNULL_END ADDED src/OFHTTPIRIHandler.m Index: src/OFHTTPIRIHandler.m ================================================================== --- /dev/null +++ src/OFHTTPIRIHandler.m @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2008-2024 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#include "config.h" + +#import "OFHTTPIRIHandler.h" +#import "OFHTTPClient.h" +#import "OFHTTPRequest.h" +#import "OFHTTPResponse.h" + +@implementation OFHTTPIRIHandler +- (OFStream *)openItemAtIRI: (OFIRI *)IRI mode: (OFString *)mode +{ + void *pool = objc_autoreleasePoolPush(); + OFHTTPClient *client = [OFHTTPClient client]; + OFHTTPRequest *request = [OFHTTPRequest requestWithIRI: IRI]; + OFHTTPResponse *response = [client performRequest: request]; + + [response retain]; + + objc_autoreleasePoolPop(pool); + + return [response autorelease]; +} +@end Index: src/OFHTTPRequest.h ================================================================== --- src/OFHTTPRequest.h +++ src/OFHTTPRequest.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,13 +17,13 @@ #import "OFSocket.h" #import "OFString.h" OF_ASSUME_NONNULL_BEGIN -@class OFURI; +@class OFData; @class OFDictionary OF_GENERIC(KeyType, ObjectType); -@class OFData; +@class OFIRI; @class OFString; /** @file */ /** @@ -51,11 +51,11 @@ /** * @struct OFHTTPRequestProtocolVersion OFHTTPRequest.h ObjFW/OFHTTPRequest.h * * @brief The HTTP version of the HTTP request. */ -typedef struct OF_BOXABLE { +typedef struct OF_BOXABLE OFHTTPRequestProtocolVersion { /** The major of the HTTP version */ unsigned char major; /** The minor of the HTTP version */ unsigned char minor; } OFHTTPRequestProtocolVersion; @@ -66,22 +66,22 @@ * @brief A class for storing HTTP requests. */ OF_SUBCLASSING_RESTRICTED @interface OFHTTPRequest: OFObject { - OFURI *_URI; + OFIRI *_IRI; OFHTTPRequestMethod _method; OFHTTPRequestProtocolVersion _protocolVersion; OFDictionary OF_GENERIC(OFString *, OFString *) *_Nullable _headers; OFSocketAddress _remoteAddress; bool _hasRemoteAddress; } /** - * @brief The URI of the HTTP request. + * @brief The IRI of the HTTP request. */ -@property (copy, nonatomic) OFURI *URI; +@property (copy, nonatomic) OFIRI *IRI; /** * @brief The protocol version of the HTTP request. * * @throw OFUnsupportedVersionException The specified version cannot be set @@ -116,38 +116,38 @@ * @note The setter creates a copy of the remote address. */ @property OF_NULLABLE_PROPERTY (nonatomic) const OFSocketAddress *remoteAddress; /** - * @brief Creates a new OFHTTPRequest with the specified URI. + * @brief Creates a new OFHTTPRequest with the specified IRI. * - * @param URI The URI for the request + * @param IRI The IRI for the request * @return A new, autoreleased OFHTTPRequest */ -+ (instancetype)requestWithURI: (OFURI *)URI; ++ (instancetype)requestWithIRI: (OFIRI *)IRI; /** - * @brief Initializes an already allocated OFHTTPRequest with the specified URI. + * @brief Initializes an already allocated OFHTTPRequest with the specified IRI. * - * @param URI The URI for the request + * @param IRI The IRI for the request * @return An initialized OFHTTPRequest */ -- (instancetype)initWithURI: (OFURI *)URI; +- (instancetype)initWithIRI: (OFIRI *)IRI; - (instancetype)init OF_UNAVAILABLE; @end #ifdef __cplusplus extern "C" { #endif /** - * @brief Returns a C string describing the specified request method. + * @brief Returns a string describing the specified request method. * - * @param method The request method which should be described as a C string - * @return A C string describing the specified request method + * @param method The request method which should be described as a string + * @return A string describing the specified request method */ -extern const char *_Nullable OFHTTPRequestMethodName( +extern OFString *_Nullable OFHTTPRequestMethodString( OFHTTPRequestMethod method); /** * @brief Returns the request method for the specified string. * @@ -154,11 +154,35 @@ * @param string The string for which the request method should be returned * @return The request method for the specified string * @throw OFInvalidFormatException The specified string is not a valid HTTP * request method */ -extern OFHTTPRequestMethod OFHTTPRequestMethodParseName(OFString *string); +extern OFHTTPRequestMethod OFHTTPRequestMethodParseString(OFString *string); + +/** + * @brief Returns a C string describing the specified request method. + * + * @deprecated Use @ref OFHTTPRequestMethodString instead. + * + * @param method The request method which should be described as a C string + * @return A C string describing the specified request method + */ +extern const char *_Nullable OFHTTPRequestMethodName(OFHTTPRequestMethod method) + OF_DEPRECATED(ObjFW, 1, 1, "Use OFHTTPRequestMethodString instead"); + +/** + * @brief Returns the request method for the specified string. + * + * @deprecated Use @ref OFHTTPRequestMethodParseString instead. + * + * @param string The string for which the request method should be returned + * @return The request method for the specified string + * @throw OFInvalidFormatException The specified string is not a valid HTTP + * request method + */ +extern OFHTTPRequestMethod OFHTTPRequestMethodParseName(OFString *string) + OF_DEPRECATED(ObjFW, 1, 1, "Use OFHTTPRequestMethodParseString instead"); #ifdef __cplusplus } #endif OF_ASSUME_NONNULL_END Index: src/OFHTTPRequest.m ================================================================== --- src/OFHTTPRequest.m +++ src/OFHTTPRequest.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,48 +16,48 @@ #include "config.h" #include #import "OFHTTPRequest.h" -#import "OFString.h" -#import "OFURI.h" +#import "OFArray.h" +#import "OFData.h" #import "OFDictionary.h" -#import "OFData.h" -#import "OFArray.h" +#import "OFIRI.h" +#import "OFString.h" #import "OFInvalidArgumentException.h" #import "OFInvalidFormatException.h" #import "OFOutOfRangeException.h" #import "OFUnsupportedVersionException.h" -const char * -OFHTTPRequestMethodName(OFHTTPRequestMethod method) +OFString * +OFHTTPRequestMethodString(OFHTTPRequestMethod method) { switch (method) { case OFHTTPRequestMethodOptions: - return "OPTIONS"; - case OFHTTPRequestMethodGet: - return "GET"; - case OFHTTPRequestMethodHead: - return "HEAD"; - case OFHTTPRequestMethodPost: - return "POST"; - case OFHTTPRequestMethodPut: - return "PUT"; - case OFHTTPRequestMethodDelete: - return "DELETE"; - case OFHTTPRequestMethodTrace: - return "TRACE"; - case OFHTTPRequestMethodConnect: - return "CONNECT"; - } - - return NULL; + return @"OPTIONS"; + case OFHTTPRequestMethodGet: + return @"GET"; + case OFHTTPRequestMethodHead: + return @"HEAD"; + case OFHTTPRequestMethodPost: + return @"POST"; + case OFHTTPRequestMethodPut: + return @"PUT"; + case OFHTTPRequestMethodDelete: + return @"DELETE"; + case OFHTTPRequestMethodTrace: + return @"TRACE"; + case OFHTTPRequestMethodConnect: + return @"CONNECT"; + } + + return nil; } OFHTTPRequestMethod -OFHTTPRequestMethodParseName(OFString *string) +OFHTTPRequestMethodParseString(OFString *string) { if ([string isEqual: @"OPTIONS"]) return OFHTTPRequestMethodOptions; if ([string isEqual: @"GET"]) return OFHTTPRequestMethodGet; @@ -74,25 +74,39 @@ if ([string isEqual: @"CONNECT"]) return OFHTTPRequestMethodConnect; @throw [OFInvalidFormatException exception]; } + +/* Deprecated */ +const char * +OFHTTPRequestMethodName(OFHTTPRequestMethod method) +{ + return OFHTTPRequestMethodString(method).UTF8String; +} + +/* Deprecated */ +OFHTTPRequestMethod +OFHTTPRequestMethodParseName(OFString *string) +{ + return OFHTTPRequestMethodParseString(string); +} @implementation OFHTTPRequest -@synthesize URI = _URI, method = _method, headers = _headers; +@synthesize IRI = _IRI, method = _method, headers = _headers; -+ (instancetype)requestWithURI: (OFURI *)URI ++ (instancetype)requestWithIRI: (OFIRI *)IRI { - return [[[self alloc] initWithURI: URI] autorelease]; + return [[[self alloc] initWithIRI: IRI] autorelease]; } -- (instancetype)initWithURI: (OFURI *)URI +- (instancetype)initWithIRI: (OFIRI *)IRI { self = [super init]; @try { - _URI = [URI copy]; + _IRI = [IRI copy]; _method = OFHTTPRequestMethodGet; _protocolVersion.major = 1; _protocolVersion.minor = 1; } @catch (id e) { [self release]; @@ -107,11 +121,11 @@ OF_INVALID_INIT_METHOD } - (void)dealloc { - [_URI release]; + [_IRI release]; [_headers release]; [super dealloc]; } @@ -131,11 +145,11 @@ return NULL; } - (id)copy { - OFHTTPRequest *copy = [[OFHTTPRequest alloc] initWithURI: _URI]; + OFHTTPRequest *copy = [[OFHTTPRequest alloc] initWithIRI: _IRI]; @try { copy->_method = _method; copy->_protocolVersion = _protocolVersion; copy.headers = _headers; @@ -161,11 +175,11 @@ request = object; if (request->_method != _method || request->_protocolVersion.major != _protocolVersion.major || request->_protocolVersion.minor != _protocolVersion.minor || - ![request->_URI isEqual: _URI] || + ![request->_IRI isEqual: _IRI] || ![request->_headers isEqual: _headers]) return false; if (request.remoteAddress != self.remoteAddress && !OFSocketAddressEqual(request.remoteAddress, self.remoteAddress)) @@ -181,11 +195,11 @@ OFHashInit(&hash); OFHashAddByte(&hash, _method); OFHashAddByte(&hash, _protocolVersion.major); OFHashAddByte(&hash, _protocolVersion.minor); - OFHashAddHash(&hash, _URI.hash); + OFHashAddHash(&hash, _IRI.hash); OFHashAddHash(&hash, _headers.hash); if (_hasRemoteAddress) OFHashAddHash(&hash, OFSocketAddressHash(&_remoteAddress)); OFHashFinalize(&hash); @@ -241,11 +255,11 @@ } - (OFString *)description { void *pool = objc_autoreleasePoolPush(); - const char *method = OFHTTPRequestMethodName(_method); + OFString *method = OFHTTPRequestMethodString(_method); OFString *indentedHeaders, *remoteAddress, *ret; indentedHeaders = [_headers.description stringByReplacingOccurrencesOfString: @"\n" withString: @"\n\t"]; @@ -254,17 +268,17 @@ remoteAddress = OFSocketAddressString(&_remoteAddress); else remoteAddress = nil; ret = [[OFString alloc] initWithFormat: - @"<%@:\n\tURI = %@\n" - @"\tMethod = %s\n" + @"<%@:\n\tIRI = %@\n" + @"\tMethod = %@\n" @"\tHeaders = %@\n" @"\tRemote address = %@\n" @">", - self.class, _URI, method, indentedHeaders, remoteAddress]; + self.class, _IRI, method, indentedHeaders, remoteAddress]; objc_autoreleasePoolPop(pool); return [ret autorelease]; } @end Index: src/OFHTTPResponse.h ================================================================== --- src/OFHTTPResponse.h +++ src/OFHTTPResponse.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFHTTPResponse.m ================================================================== --- src/OFHTTPResponse.m +++ src/OFHTTPResponse.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -212,14 +212,16 @@ if ([name isEqual: @"charset"]) charset = value; } - @try { - ret = OFStringEncodingParseName(charset); - } @catch (OFInvalidArgumentException *e) { - ret = OFStringEncodingAutodetect; + ret = OFStringEncodingAutodetect; + if (charset != nil) { + @try { + ret = OFStringEncodingParseName(charset); + } @catch (OFInvalidArgumentException *e) { + } } return ret; } Index: src/OFHTTPServer.h ================================================================== --- src/OFHTTPServer.h +++ src/OFHTTPServer.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -104,20 +104,20 @@ } /** * @brief The host on which the HTTP server will listen. * - * @throw OFAlreadyConnectedException The host could not be set because - * @ref start had already been called + * @throw OFAlreadyOpenException The host could not be set because @ref start + * had already been called */ @property OF_NULLABLE_PROPERTY (copy, nonatomic) OFString *host; /** * @brief The port on which the HTTP server will listen. * - * @throw OFAlreadyConnectedException The port could not be set because - * @ref start had already been called + * @throw OFAlreadyOpenException The port could not be set because @ref start + * had already been called */ @property (nonatomic) uint16_t port; /** * @brief The delegate for the HTTP server. @@ -132,12 +132,12 @@ * If this is larger than 1 (the default), one thread will be used to accept * incoming connections and all others will be used to handle connections. * * For maximum CPU utilization, set this to `[OFSystemInfo numberOfCPUs] + 1`. * - * @throw OFAlreadyConnectedException The number of threads could not be set - * because @ref start had already been called + * @throw OFAlreadyOpenException The number of threads could not be set because + * @ref start had already been called */ @property (nonatomic) size_t numberOfThreads; #endif /** @@ -156,11 +156,11 @@ + (instancetype)server; /** * @brief Starts the HTTP server in the current thread's run loop. * - * @throw OFAlreadyConnectedException The server had already been started + * @throw OFAlreadyOpenException The server had already been started */ - (void)start; /** * @brief Stops the HTTP server, meaning it will not accept any new incoming Index: src/OFHTTPServer.m ================================================================== --- src/OFHTTPServer.m +++ src/OFHTTPServer.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,18 +26,18 @@ #import "OFData.h" #import "OFDate.h" #import "OFDictionary.h" #import "OFHTTPRequest.h" #import "OFHTTPResponse.h" +#import "OFIRI.h" #import "OFNumber.h" #import "OFSocket+Private.h" #import "OFTCPSocket.h" #import "OFThread.h" #import "OFTimer.h" -#import "OFURI.h" -#import "OFAlreadyConnectedException.h" +#import "OFAlreadyOpenException.h" #import "OFInvalidArgumentException.h" #import "OFInvalidEncodingException.h" #import "OFInvalidFormatException.h" #import "OFNotOpenException.h" #import "OFOutOfMemoryException.h" @@ -380,11 +380,11 @@ if (pos == OFNotFound) return [self sendErrorAndClose: 400]; method = [line substringToIndex: pos]; @try { - _method = OFHTTPRequestMethodParseName(method); + _method = OFHTTPRequestMethodParseString(method); } @catch (OFInvalidArgumentException *e) { return [self sendErrorAndClose: 405]; } @try { @@ -512,11 +512,11 @@ } - (void)createResponse { void *pool = objc_autoreleasePoolPush(); - OFMutableURI *URI; + OFMutableIRI *IRI; OFHTTPRequest *request; OFHTTPServerResponse *response; size_t pos; [_timer invalidate]; @@ -532,36 +532,36 @@ [_host release]; _host = [_server.host copy]; _port = [_server port]; } - URI = [OFMutableURI URIWithScheme: @"http"]; - URI.host = _host; + IRI = [OFMutableIRI IRIWithScheme: @"http"]; + IRI.host = _host; if (_port != 80) - URI.port = [OFNumber numberWithUnsignedShort: _port]; + IRI.port = [OFNumber numberWithUnsignedShort: _port]; @try { if ((pos = [_path rangeOfString: @"?"].location) != OFNotFound) { OFString *path, *query; path = [_path substringToIndex: pos]; query = [_path substringFromIndex: pos + 1]; - URI.percentEncodedPath = path; - URI.percentEncodedQuery = query; + IRI.percentEncodedPath = path; + IRI.percentEncodedQuery = query; } else - URI.percentEncodedPath = _path; + IRI.percentEncodedPath = _path; } @catch (OFInvalidFormatException *e) { objc_autoreleasePoolPop(pool); [self sendErrorAndClose: 400]; return; } - [URI makeImmutable]; + [IRI makeImmutable]; - request = [OFHTTPRequest requestWithURI: URI]; + request = [OFHTTPRequest requestWithIRI: IRI]; request.method = _method; request.protocolVersion = (OFHTTPRequestProtocolVersion){ 1, _HTTPMinorVersion }; request.headers = _headers; request.remoteAddress = _socket.remoteAddress; @@ -733,13 +733,13 @@ return 0; } } -- (bool)hasDataInReadBuffer +- (bool)lowlevelHasDataInReadBuffer { - return (super.hasDataInReadBuffer || _socket.hasDataInReadBuffer); + return _socket.hasDataInReadBuffer; } - (int)fileDescriptorForReading { return _socket.fileDescriptorForReading; @@ -802,11 +802,11 @@ - (void)setHost: (OFString *)host { OFString *old; if (_listeningSocket != nil) - @throw [OFAlreadyConnectedException exception]; + @throw [OFAlreadyOpenException exceptionWithObject: self]; old = _host; _host = [host copy]; [old release]; } @@ -817,11 +817,11 @@ } - (void)setPort: (uint16_t)port { if (_listeningSocket != nil) - @throw [OFAlreadyConnectedException exception]; + @throw [OFAlreadyOpenException exceptionWithObject: self]; _port = port; } - (uint16_t)port @@ -834,11 +834,11 @@ { if (numberOfThreads == 0) @throw [OFInvalidArgumentException exception]; if (_listeningSocket != nil) - @throw [OFAlreadyConnectedException exception]; + @throw [OFAlreadyOpenException exceptionWithObject: self]; _numberOfThreads = numberOfThreads; } - (size_t)numberOfThreads @@ -848,19 +848,21 @@ #endif - (void)start { void *pool = objc_autoreleasePoolPush(); + OFSocketAddress address; if (_host == nil) @throw [OFInvalidArgumentException exception]; if (_listeningSocket != nil) - @throw [OFAlreadyConnectedException exception]; + @throw [OFAlreadyOpenException exceptionWithObject: self]; _listeningSocket = [[OFTCPSocket alloc] init]; - _port = [_listeningSocket bindToHost: _host port: _port]; + address = [_listeningSocket bindToHost: _host port: _port]; + _port = OFSocketAddressIPPort(&address); [_listeningSocket listen]; #ifdef OF_HAVE_THREADS if (_numberOfThreads > 1) { OFMutableArray *threads = DELETED src/OFHTTPURIHandler.h Index: src/OFHTTPURIHandler.h ================================================================== --- src/OFHTTPURIHandler.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (c) 2008-2022 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#import "OFURIHandler.h" - -OF_ASSUME_NONNULL_BEGIN - -@interface OFHTTPURIHandler: OFURIHandler -@end - -OF_ASSUME_NONNULL_END DELETED src/OFHTTPURIHandler.m Index: src/OFHTTPURIHandler.m ================================================================== --- src/OFHTTPURIHandler.m +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2008-2022 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#include "config.h" - -#import "OFHTTPURIHandler.h" -#import "OFHTTPClient.h" -#import "OFHTTPRequest.h" -#import "OFHTTPResponse.h" - -@implementation OFHTTPURIHandler -- (OFStream *)openItemAtURI: (OFURI *)URI mode: (OFString *)mode -{ - void *pool = objc_autoreleasePoolPush(); - OFHTTPClient *client = [OFHTTPClient client]; - OFHTTPRequest *request = [OFHTTPRequest requestWithURI: URI]; - OFHTTPResponse *response = [client performRequest: request]; - - [response retain]; - - objc_autoreleasePoolPop(pool); - - return [response autorelease]; -} -@end Index: src/OFHostAddressResolver.h ================================================================== --- src/OFHostAddressResolver.h +++ src/OFHostAddressResolver.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -151,12 +151,15 @@ - (void)sendQueries { OFString *domainName; if (!_isFQDN) { - OFString *searchDomain = [_settings->_searchDomains - objectAtIndex: _searchDomainIndex]; + OFString *searchDomain = @""; + + if (_searchDomainIndex < _settings->_searchDomains.count) + searchDomain = [_settings->_searchDomains + objectAtIndex: _searchDomainIndex]; domainName = [OFString stringWithFormat: @"%@.%@", _host, searchDomain]; } else domainName = _host; @@ -286,11 +289,12 @@ objc_autoreleasePoolPop(pool); return; } @catch (OFInvalidFormatException *e) { } - if ((aliases = [_settings->_staticHosts objectForKey: _host]) != nil) { + if ((aliases = [_settings->_staticHosts objectForKey: + _host.lowercaseString]) != nil) { OFMutableData *addresses = [OFMutableData dataWithItemSize: sizeof(OFSocketAddress)]; id exception = nil; for (OFString *alias in aliases) { Index: src/OFHuffmanTree.h ================================================================== --- src/OFHuffmanTree.h +++ src/OFHuffmanTree.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,97 +42,97 @@ /** * @brief Returns the string for the specified key, or `nil` if it does not * exist. * - * If the specified key is a multi-key (see @ref stringArrayForKey:), the value + * If the specified key is a multi-key (see @ref arrayValueForKey:), the value * of the first key/value pair found is returned. * * @param key The key for which the string should be returned * @return The string for the specified key, or `nil` if it does not exist */ -- (nullable OFString *)stringForKey: (OFString *)key; +- (nullable OFString *)stringValueForKey: (OFString *)key; /** * @brief Returns the string for the specified key or the specified default * value if it does not exist. * - * If the specified key is a multi-key (see @ref stringArrayForKey:), the value + * If the specified key is a multi-key (see @ref arrayValueForKey:), the value * of the first key/value pair found is returned. * * @param key The key for which the string should be returned * @param defaultValue The value to return if the key does not exist * @return The string for the specified key or the specified default value if * it does not exist */ -- (nullable OFString *)stringForKey: (OFString *)key - defaultValue: (nullable OFString *)defaultValue; +- (nullable OFString *)stringValueForKey: (OFString *)key + defaultValue: (nullable OFString *)defaultValue; /** - * @brief Returns the long long for the specified key or the specified default - * value if it does not exist. + * @brief Returns the long long value for the specified key or the specified + * default value if it does not exist. * - * If the specified key is a multi-key (see @ref stringArrayForKey:), the value + * If the specified key is a multi-key (see @ref arrayValueForKey:), the value * of the first key/value pair found is returned. * * @param key The key for which the long long should be returned * @param defaultValue The value to return if the key does not exist * @return The long long for the specified key or the specified default value * if it does not exist * @throw OFInvalidFormatException The specified key is not in the correct * format for a long long */ -- (long long)longLongForKey: (OFString *)key - defaultValue: (long long)defaultValue; +- (long long)longLongValueForKey: (OFString *)key + defaultValue: (long long)defaultValue; /** - * @brief Returns the bool for the specified key or the specified default value - * if it does not exist. + * @brief Returns the bool value for the specified key or the specified default + * value if it does not exist. * - * If the specified key is a multi-key (see @ref stringArrayForKey:), the value + * If the specified key is a multi-key (see @ref arrayValueForKey:), the value * of the first key/value pair found is returned. * * @param key The key for which the bool should be returned * @param defaultValue The value to return if the key does not exist * @return The bool for the specified key or the specified default value if it * does not exist * @throw OFInvalidFormatException The specified key is not in the correct * format for a bool */ -- (bool)boolForKey: (OFString *)key defaultValue: (bool)defaultValue; +- (bool)boolValueForKey: (OFString *)key defaultValue: (bool)defaultValue; /** - * @brief Returns the float for the specified key or the specified default + * @brief Returns the float value for the specified key or the specified default * value if it does not exist. * - * If the specified key is a multi-key (see @ref stringArrayForKey:), the value + * If the specified key is a multi-key (see @ref arrayValueForKey:), the value * of the first key/value pair found is returned. * * @param key The key for which the float should be returned * @param defaultValue The value to return if the key does not exist * @return The float for the specified key or the specified default value if it * does not exist * @throw OFInvalidFormatException The specified key is not in the correct * format for a float */ -- (float)floatForKey: (OFString *)key defaultValue: (float)defaultValue; +- (float)floatValueForKey: (OFString *)key defaultValue: (float)defaultValue; /** - * @brief Returns the double for the specified key or the specified default - * value if it does not exist. + * @brief Returns the double value for the specified key or the specified + * default value if it does not exist. * - * If the specified key is a multi-key (see @ref stringArrayForKey:), the value + * If the specified key is a multi-key (see @ref arrayValueForKey:), the value * of the first key/value pair found is returned. * * @param key The key for which the double should be returned * @param defaultValue The value to return if the key does not exist * @return The double for the specified key or the specified default value if * it does not exist * @throw OFInvalidFormatException The specified key is not in the correct * format for a double */ -- (double)doubleForKey: (OFString *)key defaultValue: (double)defaultValue; +- (double)doubleValueForKey: (OFString *)key defaultValue: (double)defaultValue; /** * @brief Returns an array of strings for the specified multi-key, or an empty * array if the key does not exist. * @@ -141,89 +141,89 @@ * * @param key The multi-key for which the array should be returned * @return The array for the specified key, or an empty array if it does not * exist */ -- (OFArray OF_GENERIC(OFString *) *)stringArrayForKey: (OFString *)key; +- (OFArray OF_GENERIC(OFString *) *)arrayValueForKey: (OFString *)key; /** * @brief Sets the value of the specified key to the specified string. * - * If the specified key is a multi-key (see @ref stringArrayForKey:), the value + * If the specified key is a multi-key (see @ref arrayValueForKey:), the value * of the first key/value pair found is changed. * - * @param string The string to which the key should be set + * @param stringValue The string to which the key should be set * @param key The key for which the new value should be set */ -- (void)setString: (OFString *)string forKey: (OFString *)key; +- (void)setStringValue: (OFString *)stringValue forKey: (OFString *)key; /** * @brief Sets the value of the specified key to the specified long long. * - * If the specified key is a multi-key (see @ref stringArrayForKey:), the value + * If the specified key is a multi-key (see @ref arrayValueForKey:), the value * of the first key/value pair found is changed. * - * @param longLong The long long to which the key should be set + * @param longLongValue The long long to which the key should be set * @param key The key for which the new value should be set */ -- (void)setLongLong: (long long)longLong forKey: (OFString *)key; +- (void)setLongLongValue: (long long)longLongValue forKey: (OFString *)key; /** * @brief Sets the value of the specified key to the specified bool. * - * If the specified key is a multi-key (see @ref stringArrayForKey:), the value + * If the specified key is a multi-key (see @ref arrayValueForKey:), the value * of the first key/value pair found is changed. * - * @param bool_ The bool to which the key should be set + * @param boolValue The bool to which the key should be set * @param key The key for which the new value should be set */ -- (void)setBool: (bool)bool_ forKey: (OFString *)key; +- (void)setBoolValue: (bool)boolValue forKey: (OFString *)key; /** * @brief Sets the value of the specified key to the specified float. * - * If the specified key is a multi-key (see @ref stringArrayForKey:), the value + * If the specified key is a multi-key (see @ref arrayValueForKey:), the value * of the first key/value pair found is changed. * - * @param float_ The float to which the key should be set + * @param floatValue The float to which the key should be set * @param key The key for which the new value should be set */ -- (void)setFloat: (float)float_ forKey: (OFString *)key; +- (void)setFloatValue: (float)floatValue forKey: (OFString *)key; /** * @brief Sets the value of the specified key to the specified double. * - * If the specified key is a multi-key (see @ref stringArrayForKey:), the value + * If the specified key is a multi-key (see @ref arrayValueForKey:), the value * of the first key/value pair found is changed. * - * @param double_ The double to which the key should be set + * @param doubleValue The double to which the key should be set * @param key The key for which the new value should be set */ -- (void)setDouble: (double)double_ forKey: (OFString *)key; +- (void)setDoubleValue: (double)doubleValue forKey: (OFString *)key; /** * @brief Sets the specified multi-key to the specified array of strings. * * It replaces the first occurrence of the multi-key with several key/value * pairs and removes all following occurrences. If the multi-key does not exist * yet, it is appended to the section. * - * See also @ref stringArrayForKey: for more information about multi-keys. + * See also @ref arrayValueForKey: for more information about multi-keys. * - * @param array The array of strings to which the multi-key should be set + * @param arrayValue The array of strings to which the multi-key should be set * @param key The multi-key for which the new values should be set */ -- (void)setStringArray: (OFArray OF_GENERIC(OFString *) *)array - forKey: (OFString *)key; +- (void)setArrayValue: (OFArray OF_GENERIC(OFString *) *)arrayValue + forKey: (OFString *)key; /** * @brief Removes the value for the specified key * - * If the specified key is a multi-key (see @ref stringArrayForKey:), all + * If the specified key is a multi-key (see @ref arrayValueForKey:), all * key/value pairs matching the specified key are removed. * * @param key The key of the value to remove */ - (void)removeValueForKey: (OFString *)key; @end OF_ASSUME_NONNULL_END Index: src/OFINICategory.m ================================================================== --- src/OFINICategory.m +++ src/OFINICategory.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -176,17 +176,17 @@ [_lines addObject: comment]; } } -- (OFString *)stringForKey: (OFString *)key +- (OFString *)stringValueForKey: (OFString *)key { - return [self stringForKey: key defaultValue: nil]; + return [self stringValueForKey: key defaultValue: nil]; } -- (OFString *)stringForKey: (OFString *)key - defaultValue: (OFString *)defaultValue +- (OFString *)stringValueForKey: (OFString *)key + defaultValue: (OFString *)defaultValue { for (id line in _lines) { OFINICategoryPair *pair; if (![line isKindOfClass: [OFINICategoryPair class]]) @@ -199,15 +199,15 @@ } return defaultValue; } -- (long long)longLongForKey: (OFString *)key - defaultValue: (long long)defaultValue +- (long long)longLongValueForKey: (OFString *)key + defaultValue: (long long)defaultValue { void *pool = objc_autoreleasePoolPush(); - OFString *value = [self stringForKey: key defaultValue: nil]; + OFString *value = [self stringValueForKey: key defaultValue: nil]; long long ret; if (value != nil) ret = [value longLongValueWithBase: 0]; else @@ -216,14 +216,14 @@ objc_autoreleasePoolPop(pool); return ret; } -- (bool)boolForKey: (OFString *)key defaultValue: (bool)defaultValue +- (bool)boolValueForKey: (OFString *)key defaultValue: (bool)defaultValue { void *pool = objc_autoreleasePoolPush(); - OFString *value = [self stringForKey: key defaultValue: nil]; + OFString *value = [self stringValueForKey: key defaultValue: nil]; bool ret; if (value != nil) { if ([value isEqual: @"true"]) ret = true; @@ -237,14 +237,14 @@ objc_autoreleasePoolPop(pool); return ret; } -- (float)floatForKey: (OFString *)key defaultValue: (float)defaultValue +- (float)floatValueForKey: (OFString *)key defaultValue: (float)defaultValue { void *pool = objc_autoreleasePoolPush(); - OFString *value = [self stringForKey: key defaultValue: nil]; + OFString *value = [self stringValueForKey: key defaultValue: nil]; float ret; if (value != nil) ret = value.floatValue; else @@ -253,14 +253,14 @@ objc_autoreleasePoolPop(pool); return ret; } -- (double)doubleForKey: (OFString *)key defaultValue: (double)defaultValue +- (double)doubleValueForKey: (OFString *)key defaultValue: (double)defaultValue { void *pool = objc_autoreleasePoolPush(); - OFString *value = [self stringForKey: key defaultValue: nil]; + OFString *value = [self stringValueForKey: key defaultValue: nil]; double ret; if (value != nil) ret = value.doubleValue; else @@ -269,11 +269,11 @@ objc_autoreleasePoolPop(pool); return ret; } -- (OFArray OF_GENERIC(OFString *) *)stringArrayForKey: (OFString *)key +- (OFArray OF_GENERIC(OFString *) *)arrayValueForKey: (OFString *)key { OFMutableArray *ret = [OFMutableArray array]; void *pool = objc_autoreleasePoolPush(); for (id line in _lines) { @@ -293,11 +293,11 @@ [ret makeImmutable]; return ret; } -- (void)setString: (OFString *)string forKey: (OFString *)key +- (void)setStringValue: (OFString *)string forKey: (OFString *)key { void *pool = objc_autoreleasePoolPush(); OFINICategoryPair *pair; for (id line in _lines) { @@ -333,64 +333,65 @@ } objc_autoreleasePoolPop(pool); } -- (void)setLongLong: (long long)longLong forKey: (OFString *)key -{ - void *pool = objc_autoreleasePoolPush(); - - [self setString: [OFString stringWithFormat: @"%lld", longLong] - forKey: key]; - - objc_autoreleasePoolPop(pool); -} - -- (void)setBool: (bool)bool_ forKey: (OFString *)key -{ - [self setString: (bool_ ? @"true" : @"false") forKey: key]; -} - -- (void)setFloat: (float)float_ forKey: (OFString *)key -{ - void *pool = objc_autoreleasePoolPush(); - - [self setString: [OFString stringWithFormat: @"%g", float_] - forKey: key]; - - objc_autoreleasePoolPop(pool); -} - -- (void)setDouble: (double)double_ forKey: (OFString *)key -{ - void *pool = objc_autoreleasePoolPush(); - - [self setString: [OFString stringWithFormat: @"%g", double_] - forKey: key]; - - objc_autoreleasePoolPop(pool); -} - -- (void)setStringArray: (OFArray OF_GENERIC(OFString *) *)array - forKey: (OFString *)key +- (void)setLongLongValue: (long long)longLongValue forKey: (OFString *)key +{ + void *pool = objc_autoreleasePoolPush(); + + [self setStringValue: [OFString stringWithFormat: + @"%lld", longLongValue] + forKey: key]; + + objc_autoreleasePoolPop(pool); +} + +- (void)setBoolValue: (bool)boolValue forKey: (OFString *)key +{ + [self setStringValue: (boolValue ? @"true" : @"false") forKey: key]; +} + +- (void)setFloatValue: (float)floatValue forKey: (OFString *)key +{ + void *pool = objc_autoreleasePoolPush(); + + [self setStringValue: [OFString stringWithFormat: @"%g", floatValue] + forKey: key]; + + objc_autoreleasePoolPop(pool); +} + +- (void)setDoubleValue: (double)doubleValue forKey: (OFString *)key +{ + void *pool = objc_autoreleasePoolPush(); + + [self setStringValue: [OFString stringWithFormat: @"%g", doubleValue] + forKey: key]; + + objc_autoreleasePoolPop(pool); +} + +- (void)setArrayValue: (OFArray OF_GENERIC(OFString *) *)arrayValue + forKey: (OFString *)key { void *pool; OFMutableArray *pairs; id const *lines; size_t count; bool replaced; - if (array.count == 0) { + if (arrayValue.count == 0) { [self removeValueForKey: key]; return; } pool = objc_autoreleasePoolPush(); - pairs = [OFMutableArray arrayWithCapacity: array.count]; + pairs = [OFMutableArray arrayWithCapacity: arrayValue.count]; - for (OFString *string in array) { + for (OFString *string in arrayValue) { OFINICategoryPair *pair; if (![string isKindOfClass: [OFString class]]) @throw [OFInvalidArgumentException exception]; @@ -420,11 +421,11 @@ [_lines insertObjectsFromArray: pairs atIndex: i]; replaced = true; /* Continue after inserted pairs */ - i += array.count - 1; + i += arrayValue.count - 1; } else i--; /* Continue at same position */ lines = _lines.objects; count = _lines.count; Index: src/OFINIFile.h ================================================================== --- src/OFINIFile.h +++ src/OFINIFile.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,12 +17,12 @@ #import "OFString.h" #import "OFINICategory.h" OF_ASSUME_NONNULL_BEGIN +@class OFIRI; @class OFMutableArray OF_GENERIC(ObjectType); -@class OFURI; /** * @class OFINIFile OFINIFile.h ObjFW/OFINIFile.h * * @brief A class for reading, creating and modifying INI files. @@ -39,63 +39,63 @@ @property (readonly, nonatomic) OFArray OF_GENERIC(OFINICategory *) *categories; /** * @brief Creates a new OFINIFile with the contents of the specified file. * - * @param URI The URI to the file whose contents the OFINIFile should contain + * @param IRI The IRI to the file whose contents the OFINIFile should contain * * @return A new, autoreleased OFINIFile with the contents of the specified file * @throw OFInvalidFormatException The format of the specified INI file is * invalid * @throw OFInvalidEncodingException The INI file is not in the specified * encoding */ -+ (instancetype)fileWithURI: (OFURI *)URI; ++ (instancetype)fileWithIRI: (OFIRI *)IRI; /** * @brief Creates a new OFINIFile with the contents of the specified file in * the specified encoding. * - * @param URI The URI to the file whose contents the OFINIFile should contain + * @param IRI The IRI to the file whose contents the OFINIFile should contain * @param encoding The encoding of the specified file * @return A new, autoreleased OFINIFile with the contents of the specified file * @throw OFInvalidFormatException The format of the specified INI file is * invalid * @throw OFInvalidEncodingException The INI file is not in the specified * encoding */ -+ (instancetype)fileWithURI: (OFURI *)URI encoding: (OFStringEncoding)encoding; ++ (instancetype)fileWithIRI: (OFIRI *)IRI encoding: (OFStringEncoding)encoding; - (instancetype)init OF_UNAVAILABLE; /** * @brief Initializes an already allocated OFINIFile with the contents of the * specified file. * - * @param URI The URI to the file whose contents the OFINIFile should contain + * @param IRI The IRI to the file whose contents the OFINIFile should contain * * @return An initialized OFINIFile with the contents of the specified file * @throw OFInvalidFormatException The format of the specified INI file is * invalid * @throw OFInvalidEncodingException The INI file is not in the specified * encoding */ -- (instancetype)initWithURI: (OFURI *)URI; +- (instancetype)initWithIRI: (OFIRI *)IRI; /** * @brief Initializes an already allocated OFINIFile with the contents of the * specified file in the specified encoding. * - * @param URI The URI to the file whose contents the OFINIFile should contain + * @param IRI The IRI to the file whose contents the OFINIFile should contain * @param encoding The encoding of the specified file * @return An initialized OFINIFile with the contents of the specified file * @throw OFInvalidFormatException The format of the specified INI file is * invalid * @throw OFInvalidEncodingException The INI file is not in the specified * encoding */ -- (instancetype)initWithURI: (OFURI *)URI +- (instancetype)initWithIRI: (OFIRI *)IRI encoding: (OFStringEncoding)encoding OF_DESIGNATED_INITIALIZER; /** * @brief Returns an @ref OFINICategory for the category with the specified @@ -109,20 +109,20 @@ - (OFINICategory *)categoryForName: (OFString *)name; /** * @brief Writes the contents of the OFINIFile to a file. * - * @param URI The URI of the file to write to + * @param IRI The IRI of the file to write to */ -- (void)writeToURI: (OFURI *)URI; +- (void)writeToIRI: (OFIRI *)IRI; /** * @brief Writes the contents of the OFINIFile to a file in the specified * encoding. * - * @param URI The URI of the file to write to + * @param IRI The IRI of the file to write to * @param encoding The encoding to use */ -- (void)writeToURI: (OFURI *)URI encoding: (OFStringEncoding)encoding; +- (void)writeToIRI: (OFIRI *)IRI encoding: (OFStringEncoding)encoding; @end OF_ASSUME_NONNULL_END Index: src/OFINIFile.m ================================================================== --- src/OFINIFile.m +++ src/OFINIFile.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,21 +19,21 @@ #import "OFINIFile.h" #import "OFArray.h" #import "OFINICategory+Private.h" #import "OFINICategory.h" +#import "OFIRI.h" +#import "OFIRIHandler.h" #import "OFStream.h" #import "OFString.h" -#import "OFURI.h" -#import "OFURIHandler.h" #import "OFInvalidFormatException.h" #import "OFOpenItemFailedException.h" OF_DIRECT_MEMBERS @interface OFINIFile () -- (void)of_parseURI: (OFURI *)URI encoding: (OFStringEncoding)encoding; +- (void)of_parseIRI: (OFIRI *)IRI encoding: (OFStringEncoding)encoding; @end static bool isWhitespaceLine(OFString *line) { @@ -48,38 +48,38 @@ } @implementation OFINIFile @synthesize categories = _categories; -+ (instancetype)fileWithURI: (OFURI *)URI ++ (instancetype)fileWithIRI: (OFIRI *)IRI { - return [[[self alloc] initWithURI: URI] autorelease]; + return [[[self alloc] initWithIRI: IRI] autorelease]; } -+ (instancetype)fileWithURI: (OFURI *)URI encoding: (OFStringEncoding)encoding ++ (instancetype)fileWithIRI: (OFIRI *)IRI encoding: (OFStringEncoding)encoding { - return [[[self alloc] initWithURI: URI encoding: encoding] autorelease]; + return [[[self alloc] initWithIRI: IRI encoding: encoding] autorelease]; } - (instancetype)init { OF_INVALID_INIT_METHOD } -- (instancetype)initWithURI: (OFURI *)URI +- (instancetype)initWithIRI: (OFIRI *)IRI { - return [self initWithURI: URI encoding: OFStringEncodingAutodetect]; + return [self initWithIRI: IRI encoding: OFStringEncodingAutodetect]; } -- (instancetype)initWithURI: (OFURI *)URI encoding: (OFStringEncoding)encoding +- (instancetype)initWithIRI: (OFIRI *)IRI encoding: (OFStringEncoding)encoding { self = [super init]; @try { _categories = [[OFMutableArray alloc] init]; - [self of_parseURI: URI encoding: encoding]; + [self of_parseIRI: IRI encoding: encoding]; } @catch (id e) { [self release]; @throw e; } @@ -108,11 +108,11 @@ objc_autoreleasePoolPop(pool); return category; } -- (void)of_parseURI: (OFURI *)URI encoding: (OFStringEncoding)encoding +- (void)of_parseIRI: (OFIRI *)IRI encoding: (OFStringEncoding)encoding { void *pool = objc_autoreleasePoolPush(); OFStream *file; OFINICategory *category = nil; OFString *line; @@ -119,11 +119,11 @@ if (encoding == OFStringEncodingAutodetect) encoding = OFStringEncodingUTF8; @try { - file = [OFURIHandler openItemAtURI: URI mode: @"r"]; + file = [OFIRIHandler openItemAtIRI: IRI mode: @"r"]; } @catch (OFOpenItemFailedException *e) { /* Handle missing file like an empty file */ if (e.errNo == ENOENT) return; @@ -154,19 +154,19 @@ } objc_autoreleasePoolPop(pool); } -- (void)writeToURI: (OFURI *)URI +- (void)writeToIRI: (OFIRI *)IRI { - [self writeToURI: URI encoding: OFStringEncodingUTF8]; + [self writeToIRI: IRI encoding: OFStringEncodingUTF8]; } -- (void)writeToURI: (OFURI *)URI encoding: (OFStringEncoding)encoding +- (void)writeToIRI: (OFIRI *)IRI encoding: (OFStringEncoding)encoding { void *pool = objc_autoreleasePoolPush(); - OFStream *file = [OFURIHandler openItemAtURI: URI mode: @"w"]; + OFStream *file = [OFIRIHandler openItemAtIRI: IRI mode: @"w"]; bool first = true; for (OFINICategory *category in _categories) if ([category of_writeToStream: file encoding: encoding Index: src/OFINIFileSettings.h ================================================================== --- src/OFINIFileSettings.h +++ src/OFINIFileSettings.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,16 +16,16 @@ #import "OFSettings.h" OF_ASSUME_NONNULL_BEGIN @class OFINIFile; +@class OFIRI; @class OFString; -@class OFURI; @interface OFINIFileSettings: OFSettings { - OFURI *_fileURI; + OFIRI *_fileIRI; OFINIFile *_INIFile; } @end OF_ASSUME_NONNULL_END Index: src/OFINIFileSettings.m ================================================================== --- src/OFINIFileSettings.m +++ src/OFINIFileSettings.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,13 +16,13 @@ #include "config.h" #import "OFINIFileSettings.h" #import "OFArray.h" #import "OFINIFile.h" +#import "OFIRI.h" #import "OFString.h" #import "OFSystemInfo.h" -#import "OFURI.h" @implementation OFINIFileSettings - (instancetype)initWithApplicationName: (OFString *)applicationName { self = [super initWithApplicationName: applicationName]; @@ -30,13 +30,13 @@ @try { void *pool = objc_autoreleasePoolPush(); OFString *fileName; fileName = [applicationName stringByAppendingString: @".ini"]; - _fileURI = [[[OFSystemInfo userConfigURI] - URIByAppendingPathComponent: fileName] copy]; - _INIFile = [[OFINIFile alloc] initWithURI: _fileURI]; + _fileIRI = [[[OFSystemInfo userConfigIRI] + IRIByAppendingPathComponent: fileName] copy]; + _INIFile = [[OFINIFile alloc] initWithIRI: _fileIRI]; objc_autoreleasePoolPop(pool); } @catch (id e) { [self release]; @throw e; @@ -45,11 +45,11 @@ return self; } - (void)dealloc { - [_fileURI release]; + [_fileIRI release]; [_INIFile release]; [super dealloc]; } @@ -74,11 +74,12 @@ { void *pool = objc_autoreleasePoolPush(); OFString *category, *key; [self of_getCategory: &category andKey: &key forPath: path]; - [[_INIFile categoryForName: category] setString: string forKey: key]; + [[_INIFile categoryForName: category] setStringValue: string + forKey: key]; objc_autoreleasePoolPop(pool); } - (void)setLongLong: (long long)longLong forPath: (OFString *)path @@ -85,12 +86,12 @@ { void *pool = objc_autoreleasePoolPush(); OFString *category, *key; [self of_getCategory: &category andKey: &key forPath: path]; - [[_INIFile categoryForName: category] setLongLong: longLong - forKey: key]; + [[_INIFile categoryForName: category] setLongLongValue: longLong + forKey: key]; objc_autoreleasePoolPop(pool); } - (void)setBool: (bool)bool_ forPath: (OFString *)path @@ -97,11 +98,11 @@ { void *pool = objc_autoreleasePoolPush(); OFString *category, *key; [self of_getCategory: &category andKey: &key forPath: path]; - [[_INIFile categoryForName: category] setBool: bool_ forKey: key]; + [[_INIFile categoryForName: category] setBoolValue: bool_ forKey: key]; objc_autoreleasePoolPop(pool); } - (void)setFloat: (float)float_ forPath: (OFString *)path @@ -108,11 +109,12 @@ { void *pool = objc_autoreleasePoolPush(); OFString *category, *key; [self of_getCategory: &category andKey: &key forPath: path]; - [[_INIFile categoryForName: category] setFloat: float_ forKey: key]; + [[_INIFile categoryForName: category] setFloatValue: float_ + forKey: key]; objc_autoreleasePoolPop(pool); } - (void)setDouble: (double)double_ forPath: (OFString *)path @@ -119,11 +121,12 @@ { void *pool = objc_autoreleasePoolPush(); OFString *category, *key; [self of_getCategory: &category andKey: &key forPath: path]; - [[_INIFile categoryForName: category] setDouble: double_ forKey: key]; + [[_INIFile categoryForName: category] setDoubleValue: double_ + forKey: key]; objc_autoreleasePoolPop(pool); } - (void)setStringArray: (OFArray OF_GENERIC(OFString *) *)array @@ -131,12 +134,12 @@ { void *pool = objc_autoreleasePoolPush(); OFString *category, *key; [self of_getCategory: &category andKey: &key forPath: path]; - [[_INIFile categoryForName: category] setStringArray: array - forKey: key]; + [[_INIFile categoryForName: category] setArrayValue: array + forKey: key]; objc_autoreleasePoolPop(pool); } - (OFString *)stringForPath: (OFString *)path @@ -144,12 +147,13 @@ { void *pool = objc_autoreleasePoolPush(); OFString *category, *key, *ret; [self of_getCategory: &category andKey: &key forPath: path]; - ret = [[_INIFile categoryForName: category] stringForKey: key - defaultValue: defaultValue]; + ret = [[_INIFile categoryForName: category] + stringValueForKey: key + defaultValue: defaultValue]; [ret retain]; objc_autoreleasePoolPop(pool); return [ret autorelease]; } @@ -161,12 +165,12 @@ OFString *category, *key; long long ret; [self of_getCategory: &category andKey: &key forPath: path]; ret = [[_INIFile categoryForName: category] - longLongForKey: key - defaultValue: defaultValue]; + longLongValueForKey: key + defaultValue: defaultValue]; objc_autoreleasePoolPop(pool); return ret; } @@ -176,12 +180,13 @@ void *pool = objc_autoreleasePoolPush(); OFString *category, *key; bool ret; [self of_getCategory: &category andKey: &key forPath: path]; - ret = [[_INIFile categoryForName: category] boolForKey: key - defaultValue: defaultValue]; + ret = [[_INIFile categoryForName: category] + boolValueForKey: key + defaultValue: defaultValue]; objc_autoreleasePoolPop(pool); return ret; } @@ -191,12 +196,13 @@ void *pool = objc_autoreleasePoolPush(); OFString *category, *key; float ret; [self of_getCategory: &category andKey: &key forPath: path]; - ret = [[_INIFile categoryForName: category] floatForKey: key - defaultValue: defaultValue]; + ret = [[_INIFile categoryForName: category] + floatValueForKey: key + defaultValue: defaultValue]; objc_autoreleasePoolPop(pool); return ret; } @@ -206,12 +212,13 @@ void *pool = objc_autoreleasePoolPush(); OFString *category, *key; double ret; [self of_getCategory: &category andKey: &key forPath: path]; - ret = [[_INIFile categoryForName: category] doubleForKey: key - defaultValue: defaultValue]; + ret = [[_INIFile categoryForName: category] + doubleValueForKey: key + defaultValue: defaultValue]; objc_autoreleasePoolPop(pool); return ret; } @@ -221,11 +228,11 @@ void *pool = objc_autoreleasePoolPush(); OFString *category, *key; OFArray *ret; [self of_getCategory: &category andKey: &key forPath: path]; - ret = [[_INIFile categoryForName: category] stringArrayForKey: key]; + ret = [[_INIFile categoryForName: category] arrayValueForKey: key]; [ret retain]; objc_autoreleasePoolPop(pool); return [ret autorelease]; } @@ -241,8 +248,8 @@ objc_autoreleasePoolPop(pool); } - (void)save { - [_INIFile writeToURI: _fileURI]; + [_INIFile writeToIRI: _fileIRI]; } @end Index: src/OFIPXSocket.h ================================================================== --- src/OFIPXSocket.h +++ src/OFIPXSocket.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,11 +33,11 @@ * @brief A class which provides methods to create and use IPX sockets. * * Addresses are of type @ref OFSocketAddress. You can use * @ref OFSocketAddressMakeIPX to create an address or * @ref OFSocketAddressIPXNetwork to get the IPX network, - * @ref OFSocketAddressIPXNode to get the IPX node and + * @ref OFSocketAddressGetIPXNode to get the IPX node and * @ref OFSocketAddressIPXPort to get the port (sometimes also called * socket number). * * @warning Even though the OFCopying protocol is implemented, it does *not* * return an independent copy of the socket, but instead retains it. @@ -73,15 +73,15 @@ * @param port The port (sometimes called socket number) to bind to. 0 means to * pick one and return via the returned socket address. * @param packetType The packet type to use on the socket * @return The address on which this socket can be reached * @throw OFBindIPXSocketFailedException Binding failed - * @throw OFAlreadyConnectedException The socket is already bound + * @throw OFAlreadyOpenException The socket is already bound */ - (OFSocketAddress) bindToNetwork: (uint32_t)network node: (const unsigned char [_Nonnull IPX_NODE_LEN])node port: (uint16_t)port packetType: (uint8_t)packetType; @end OF_ASSUME_NONNULL_END Index: src/OFIPXSocket.m ================================================================== --- src/OFIPXSocket.m +++ src/OFIPXSocket.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -23,12 +23,16 @@ #import "OFIPXSocket.h" #import "OFSocket.h" #import "OFSocket+Private.h" -#import "OFAlreadyConnectedException.h" +#import "OFAlreadyOpenException.h" #import "OFBindIPXSocketFailedException.h" + +#ifndef NSPROTO_IPX +# define NSPROTO_IPX 0 +#endif @implementation OFIPXSocket @dynamic delegate; - (OFSocketAddress)bindToNetwork: (uint32_t)network @@ -41,15 +45,15 @@ #if SOCK_CLOEXEC == 0 && defined(HAVE_FCNTL_H) && defined(FD_CLOEXEC) int flags; #endif if (_socket != OFInvalidSocketHandle) - @throw [OFAlreadyConnectedException exceptionWithSocket: self]; + @throw [OFAlreadyOpenException exceptionWithObject: self]; address = OFSocketAddressMakeIPX(network, node, port); -#ifdef OF_WINDOWS +#if defined(OF_WINDOWS) || defined(OF_FREEBSD) protocol = NSPROTO_IPX + packetType; #else _packetType = address.sockaddr.ipx.sipx_type = packetType; #endif @@ -120,11 +124,11 @@ } return address; } -#ifndef OF_WINDOWS +#if !defined(OF_WINDOWS) && !defined(OF_FREEBSD) - (void)sendBuffer: (const void *)buffer length: (size_t)length receiver: (const OFSocketAddress *)receiver { OFSocketAddress fixedReceiver; ADDED src/OFIRI+Private.h Index: src/OFIRI+Private.h ================================================================== --- /dev/null +++ src/OFIRI+Private.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2008-2024 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#import "OFIRI.h" + +OF_ASSUME_NONNULL_BEGIN + +@interface OFIRI () +- (instancetype)of_init OF_METHOD_FAMILY(init); +@end + +OF_ASSUME_NONNULL_END ADDED src/OFIRI.h Index: src/OFIRI.h ================================================================== --- /dev/null +++ src/OFIRI.h @@ -0,0 +1,395 @@ +/* + * Copyright (c) 2008-2024 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#import "OFObject.h" +#import "OFCharacterSet.h" + +OF_ASSUME_NONNULL_BEGIN + +@class OFArray OF_GENERIC(ObjectType); +@class OFDictionary OF_GENERIC(KeyType, ObjectType); +@class OFNumber; +@class OFPair OF_GENERIC(FirstType, SecondType); +@class OFString; + +/** + * @class OFIRI OFIRI.h ObjFW/OFIRI.h + * + * @brief A class for representing IRIs, URIs, URLs and URNs, for parsing them + * as well as accessing parts of them. + * + * This class follows RFC 3976 and RFC 3987. + */ +@interface OFIRI: OFObject +{ + OFString *_scheme; + OFString *_Nullable _percentEncodedHost; + OFNumber *_Nullable _port; + OFString *_Nullable _percentEncodedUser; + OFString *_Nullable _percentEncodedPassword; + OFString *_percentEncodedPath; + OFString *_Nullable _percentEncodedQuery; + OFString *_Nullable _percentEncodedFragment; + OF_RESERVE_IVARS(OFIRI, 4) +} + +/** + * @brief The scheme part of the IRI. + */ +@property (readonly, copy, nonatomic) OFString *scheme; + +/** + * @brief The host part of the IRI. + */ +@property OF_NULLABLE_PROPERTY (readonly, copy, nonatomic) OFString *host; + +/** + * @brief The host part of the IRI in percent-encoded form. + */ +@property OF_NULLABLE_PROPERTY (readonly, copy, nonatomic) + OFString *percentEncodedHost; + +/** + * @brief The port part of the IRI. + */ +@property OF_NULLABLE_PROPERTY (readonly, copy, nonatomic) OFNumber *port; + +/** + * @brief The user part of the IRI. + */ +@property OF_NULLABLE_PROPERTY (readonly, copy, nonatomic) OFString *user; + +/** + * @brief The user part of the IRI in percent-encoded form. + */ +@property OF_NULLABLE_PROPERTY (readonly, copy, nonatomic) + OFString *percentEncodedUser; + +/** + * @brief The password part of the IRI. + */ +@property OF_NULLABLE_PROPERTY (readonly, copy, nonatomic) OFString *password; + +/** + * @brief The password part of the IRI in percent-encoded form. + */ +@property OF_NULLABLE_PROPERTY (readonly, copy, nonatomic) + OFString *percentEncodedPassword; + +/** + * @brief The path part of the IRI. + */ +@property (readonly, copy, nonatomic) OFString *path; + +/** + * @brief The path part of the IRI in percent-encoded form. + */ +@property (readonly, copy, nonatomic) OFString *percentEncodedPath; + +/** + * @brief The path of the IRI split into components. + * + * The first component must always be `/` to designate the root. + */ +@property (readonly, copy, nonatomic) + OFArray OF_GENERIC(OFString *) *pathComponents; + +/** + * @brief The last path component of the IRI. + * + * Returns the empty string if the path is the root. + */ +@property (readonly, copy, nonatomic) OFString *lastPathComponent; + +/** + * @brief The query part of the IRI. + */ +@property OF_NULLABLE_PROPERTY (readonly, copy, nonatomic) OFString *query; + +/** + * @brief The query part of the IRI in percent-encoded form. + */ +@property OF_NULLABLE_PROPERTY (readonly, copy, nonatomic) + OFString *percentEncodedQuery; + +/** + * @brief The query part of the IRI as an array. + * + * For example, a query like `key1=value1&key2=value2` would correspond to the + * following array: + * + * @[ + * [OFPair pairWithFirstObject: @"key1" secondObject: @"value1"], + * [OFPair pairWithFirstObject: @"key2" secondObject: @"value2"], + * ] + * + * @throw OFInvalidFormatException The query is not in the correct format + */ +@property OF_NULLABLE_PROPERTY (readonly, copy, nonatomic) + OFArray OF_GENERIC(OFPair OF_GENERIC(OFString *, OFString *) *) *queryItems; + +/** + * @brief The fragment part of the IRI. + */ +@property OF_NULLABLE_PROPERTY (readonly, copy, nonatomic) OFString *fragment; + +/** + * @brief The fragment part of the IRI in percent-encoded form. + */ +@property OF_NULLABLE_PROPERTY (readonly, copy, nonatomic) + OFString *percentEncodedFragment; + +/** + * @brief The IRI as a string. + */ +@property (readonly, nonatomic) OFString *string; + +/** + * @brief The IRI with relative subpaths resolved. + */ +@property (readonly, nonatomic) OFIRI *IRIByStandardizingPath; + +/** + * @brief The IRI with percent-encoding added for all Unicode characters. + */ +@property (readonly, nonatomic) + OFIRI *IRIByAddingPercentEncodingForUnicodeCharacters; + +#ifdef OF_HAVE_FILES +/** + * @brief The local file system representation for a file IRI. + * + * @note This only exists for IRIs with the file scheme and throws an exception + * otherwise. + */ +@property OF_NULLABLE_PROPERTY (readonly, nonatomic) + OFString *fileSystemRepresentation; +#endif + +/** + * @brief Creates a new IRI with the specified string. + * + * @param string A string describing an IRI + * @return A new, autoreleased OFIRI + * @throw OFInvalidFormatException The specified string is not a valid IRI + * string + */ ++ (instancetype)IRIWithString: (OFString *)string; + +/** + * @brief Creates a new IRI with the specified string relative to the + * specified IRI. + * + * @param string A string describing a relative or absolute IRI + * @param IRI An IRI to which the string is relative + * @return A new, autoreleased OFIRI + * @throw OFInvalidFormatException The specified string is not a valid IRI + * string + */ ++ (instancetype)IRIWithString: (OFString *)string relativeToIRI: (OFIRI *)IRI; + +#ifdef OF_HAVE_FILES +/** + * @brief Creates a new IRI with the specified local file path. + * + * If a directory exists at the specified path, a slash is appended if there is + * no slash yet. + * + * @param path The local file path + * @return A new, autoreleased OFIRI + * @throw OFInvalidFormatException The specified path is not a valid path + */ ++ (instancetype)fileIRIWithPath: (OFString *)path; + +/** + * @brief Creates a new IRI with the specified local file path. + * + * @param path The local file path + * @param isDirectory Whether the path is a directory, in which case a slash is + * appened if there is no slash yet + * @return An initialized OFIRI + */ ++ (instancetype)fileIRIWithPath: (OFString *)path + isDirectory: (bool)isDirectory; +#endif + +/** + * @brief Initializes an already allocated OFIRI with the specified string. + * + * @param string A string describing an IRI + * @return An initialized OFIRI + * @throw OFInvalidFormatException The specified string is not a valid IRI + * string + */ +- (instancetype)initWithString: (OFString *)string; + +/** + * @brief Initializes an already allocated OFIRI with the specified string and + * relative IRI. + * + * @param string A string describing a relative or absolute IRI + * @param IRI An IRI to which the string is relative + * @return An initialized OFIRI + * @throw OFInvalidFormatException The specified string is not a valid IRI + * string + */ +- (instancetype)initWithString: (OFString *)string relativeToIRI: (OFIRI *)IRI; + +#ifdef OF_HAVE_FILES +/** + * @brief Initializes an already allocated OFIRI with the specified local file + * path. + * + * If a directory exists at the specified path, a slash is appended if there is + * no slash yet. + * + * @param path The local file path + * @return An initialized OFIRI + * @throw OFInvalidFormatException The specified path is not a valid path + */ +- (instancetype)initFileIRIWithPath: (OFString *)path; + +/** + * @brief Initializes an already allocated OFIRI with the specified local file + * path. + * + * @param path The local file path + * @param isDirectory Whether the path is a directory, in which case a slash is + * appened if there is no slash yet + * @return An initialized OFIRI + */ +- (instancetype)initFileIRIWithPath: (OFString *)path + isDirectory: (bool)isDirectory; +#endif + +- (instancetype)init OF_UNAVAILABLE; + +/** + * @brief Returns a new IRI with the specified path component appended. + * + * If the IRI is a file IRI, the file system is queried whether the appended + * component is a directory. + * + * @param component The path component to append. If it starts with the slash, + * the component is not appended, but replaces the path + * instead. + * @return A new IRI with the specified path component appended + */ +- (OFIRI *)IRIByAppendingPathComponent: (OFString *)component; + +/** + * @brief Returns a new IRI with the specified path component appended. + * + * @param component The path component to append. If it starts with the slash, + * the component is not appended, but replaces the path + * instead. + * @param isDirectory Whether the appended component is a directory, meaning + * that the IRI path should have a trailing slash + * @return A new IRI with the specified path component appended + */ +- (OFIRI *)IRIByAppendingPathComponent: (OFString *)component + isDirectory: (bool)isDirectory; +@end + +@interface OFCharacterSet (IRICharacterSets) +#ifdef OF_HAVE_CLASS_PROPERTIES +@property (class, readonly, nonatomic) + OFCharacterSet *IRISchemeAllowedCharacterSet; +@property (class, readonly, nonatomic) + OFCharacterSet *IRIHostAllowedCharacterSet; +@property (class, readonly, nonatomic) + OFCharacterSet *IRIUserAllowedCharacterSet; +@property (class, readonly, nonatomic) + OFCharacterSet *IRIPasswordAllowedCharacterSet; +@property (class, readonly, nonatomic) + OFCharacterSet *IRIPathAllowedCharacterSet; +@property (class, readonly, nonatomic) + OFCharacterSet *IRIQueryAllowedCharacterSet; +@property (class, readonly, nonatomic) + OFCharacterSet *IRIQueryKeyValueAllowedCharacterSet; +@property (class, readonly, nonatomic) + OFCharacterSet *IRIFragmentAllowedCharacterSet; +#endif + +/** + * @brief Returns the characters allowed in the scheme part of an IRI. + * + * @return The characters allowed in the scheme part of an IRI. + */ ++ (OFCharacterSet *)IRISchemeAllowedCharacterSet; + +/** + * @brief Returns the characters allowed in the host part of an IRI. + * + * @return The characters allowed in the host part of an IRI. + */ ++ (OFCharacterSet *)IRIHostAllowedCharacterSet; + +/** + * @brief Returns the characters allowed in the user part of an IRI. + * + * @return The characters allowed in the user part of an IRI. + */ ++ (OFCharacterSet *)IRIUserAllowedCharacterSet; + +/** + * @brief Returns the characters allowed in the password part of an IRI. + * + * @return The characters allowed in the password part of an IRI. + */ ++ (OFCharacterSet *)IRIPasswordAllowedCharacterSet; + +/** + * @brief Returns the characters allowed in the path part of an IRI. + * + * @return The characters allowed in the path part of an IRI. + */ ++ (OFCharacterSet *)IRIPathAllowedCharacterSet; + +/** + * @brief Returns the characters allowed in the query part of an IRI. + * + * @return The characters allowed in the query part of an IRI. + */ ++ (OFCharacterSet *)IRIQueryAllowedCharacterSet; + +/** + * @brief Returns the characters allowed in a key/value in the query part of a + * IRI. + * + * @return The characters allowed in a key/value in the query part of an IRI. + */ ++ (OFCharacterSet *)IRIQueryKeyValueAllowedCharacterSet; + +/** + * @brief Returns the characters allowed in the fragment part of an IRI. + * + * @return The characters allowed in the fragment part of an IRI. + */ ++ (OFCharacterSet *)IRIFragmentAllowedCharacterSet; +@end + +#ifdef __cplusplus +extern "C" { +#endif +extern bool OFIRIIsIPv6Host(OFString *host); +extern void OFIRIVerifyIsEscaped(OFString *, OFCharacterSet *, bool); +#ifdef __cplusplus +} +#endif + +OF_ASSUME_NONNULL_END + +#import "OFMutableIRI.h" ADDED src/OFIRI.m Index: src/OFIRI.m ================================================================== --- /dev/null +++ src/OFIRI.m @@ -0,0 +1,1356 @@ +/* + * Copyright (c) 2008-2024 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 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 + +#import "OFIRI.h" +#import "OFArray.h" +#import "OFDictionary.h" +#ifdef OF_HAVE_FILES +# import "OFFileManager.h" +# import "OFFileIRIHandler.h" +#endif +#import "OFNumber.h" +#import "OFOnce.h" +#import "OFPair.h" +#import "OFString.h" + +#import "OFInvalidArgumentException.h" +#import "OFInvalidFormatException.h" +#import "OFOutOfMemoryException.h" + +@interface OFIRIAllowedCharacterSetBase: OFCharacterSet +@end + +@interface OFIRIAllowedCharacterSet: OFIRIAllowedCharacterSetBase +@end + +@interface OFIRISchemeAllowedCharacterSet: OFIRIAllowedCharacterSetBase +@end + +@interface OFIRIPathAllowedCharacterSet: OFIRIAllowedCharacterSetBase +@end + +@interface OFIRIQueryAllowedCharacterSet: OFIRIAllowedCharacterSetBase +@end + +@interface OFIRIQueryKeyValueAllowedCharacterSet: OFIRIAllowedCharacterSetBase +@end + +@interface OFIRIFragmentAllowedCharacterSet: OFIRIAllowedCharacterSetBase +@end + +OF_DIRECT_MEMBERS +@interface OFInvertedCharacterSetWithoutPercent: OFCharacterSet +{ + OFCharacterSet *_characterSet; + bool (*_characterIsMember)(id, SEL, OFUnichar); +} + +- (instancetype)initWithCharacterSet: (OFCharacterSet *)characterSet; +@end + +static OFCharacterSet *IRIAllowedCharacterSet = nil; +static OFCharacterSet *IRISchemeAllowedCharacterSet = nil; +static OFCharacterSet *IRIPathAllowedCharacterSet = nil; +static OFCharacterSet *IRIQueryAllowedCharacterSet = nil; +static OFCharacterSet *IRIQueryKeyValueAllowedCharacterSet = nil; +static OFCharacterSet *IRIFragmentAllowedCharacterSet = nil; + +static OFOnceControl IRIAllowedCharacterSetOnce = OFOnceControlInitValue; + +static void +initIRIAllowedCharacterSet(void) +{ + IRIAllowedCharacterSet = [[OFIRIAllowedCharacterSet alloc] init]; +} + +static void +initIRISchemeAllowedCharacterSet(void) +{ + IRISchemeAllowedCharacterSet = + [[OFIRISchemeAllowedCharacterSet alloc] init]; +} + +static void +initIRIPathAllowedCharacterSet(void) +{ + IRIPathAllowedCharacterSet = + [[OFIRIPathAllowedCharacterSet alloc] init]; +} + +static void +initIRIQueryAllowedCharacterSet(void) +{ + IRIQueryAllowedCharacterSet = + [[OFIRIQueryAllowedCharacterSet alloc] init]; +} + +static void +initIRIQueryKeyValueAllowedCharacterSet(void) +{ + IRIQueryKeyValueAllowedCharacterSet = + [[OFIRIQueryKeyValueAllowedCharacterSet alloc] init]; +} + +static void +initIRIFragmentAllowedCharacterSet(void) +{ + IRIFragmentAllowedCharacterSet = + [[OFIRIFragmentAllowedCharacterSet alloc] init]; +} + +bool +OFIRIIsIPv6Host(OFString *host) +{ + const char *UTF8String = host.UTF8String; + bool hasColon = false; + + while (*UTF8String != '\0') { + if (!OFASCIIIsDigit(*UTF8String) && *UTF8String != ':' && + (*UTF8String < 'a' || *UTF8String > 'f') && + (*UTF8String < 'A' || *UTF8String > 'F')) + return false; + + if (*UTF8String == ':') + hasColon = true; + + UTF8String++; + } + + return hasColon; +} + +static bool +isUnicode(OFUnichar character) +{ + if (character >= 0xA0 && character <= 0xD7FF) + return true; + if (character >= 0xF900 && character <= 0xFDCF) + return true; + if (character >= 0xFDF0 && character <= 0xFFEF) + return true; + if (character >= 0x10000 && character <= 0x1FFFD) + return true; + if (character >= 0x20000 && character <= 0x2FFFD) + return true; + if (character >= 0x30000 && character <= 0x3FFFD) + return true; + if (character >= 0x40000 && character <= 0x4FFFD) + return true; + if (character >= 0x50000 && character <= 0x5FFFD) + return true; + if (character >= 0x60000 && character <= 0x6FFFD) + return true; + if (character >= 0x70000 && character <= 0x7FFFD) + return true; + if (character >= 0x80000 && character <= 0x8FFFD) + return true; + if (character >= 0x90000 && character <= 0x9FFFD) + return true; + if (character >= 0xA0000 && character <= 0xAFFFD) + return true; + if (character >= 0xB0000 && character <= 0xBFFFD) + return true; + if (character >= 0xC0000 && character <= 0xCFFFD) + return true; + if (character >= 0xD0000 && character <= 0xDFFFD) + return true; + if (character >= 0xE0000 && character <= 0xEFFFD) + return true; + + return false; +} + +static bool +isUnicodePrivate(OFUnichar character) +{ + if (character >= 0xE00 && character <= 0xF8FF) + return true; + if (character >= 0xF0000 && character <= 0xFFFFD) + return true; + if (character >= 0x100000 && character <= 0x10FFFD) + return true; + + return false; +} + +@implementation OFIRIAllowedCharacterSetBase +OF_SINGLETON_METHODS +@end + +@implementation OFIRIAllowedCharacterSet +- (bool)characterIsMember: (OFUnichar)character +{ + if (character < CHAR_MAX && OFASCIIIsAlnum(character)) + return true; + + if (isUnicode(character)) + return true; + + switch (character) { + case '-': + case '.': + case '_': + case '~': + case '!': + case '$': + case '&': + case '\'': + case '(': + case ')': + case '*': + case '+': + case ',': + case ';': + case '=': + return true; + default: + return false; + } +} +@end + +@implementation OFIRISchemeAllowedCharacterSet +- (bool)characterIsMember: (OFUnichar)character +{ + if (character < CHAR_MAX && OFASCIIIsAlnum(character)) + return true; + + switch (character) { + case '+': + case '-': + case '.': + return true; + default: + return false; + } +} +@end + +@implementation OFIRIPathAllowedCharacterSet +- (bool)characterIsMember: (OFUnichar)character +{ + if (character < CHAR_MAX && OFASCIIIsAlnum(character)) + return true; + + if (isUnicode(character)) + return true; + + switch (character) { + case '-': + case '.': + case '_': + case '~': + case '!': + case '$': + case '&': + case '\'': + case '(': + case ')': + case '*': + case '+': + case ',': + case ';': + case '=': + case ':': + case '@': + case '/': + return true; + default: + return false; + } +} +@end + +@implementation OFIRIQueryAllowedCharacterSet +- (bool)characterIsMember: (OFUnichar)character +{ + if (character < CHAR_MAX && OFASCIIIsAlnum(character)) + return true; + + if (isUnicode(character) || isUnicodePrivate(character)) + return true; + + switch (character) { + case '-': + case '.': + case '_': + case '~': + case '!': + case '$': + case '&': + case '\'': + case '(': + case ')': + case '*': + case '+': + case ',': + case ';': + case '=': + case ':': + case '@': + case '/': + case '?': + return true; + default: + return false; + } +} +@end + +@implementation OFIRIQueryKeyValueAllowedCharacterSet +- (bool)characterIsMember: (OFUnichar)character +{ + if (character < CHAR_MAX && OFASCIIIsAlnum(character)) + return true; + + if (isUnicode(character) || isUnicodePrivate(character)) + return true; + + switch (character) { + case '-': + case '.': + case '_': + case '~': + case '!': + case '$': + case '\'': + case '(': + case ')': + case '*': + case '+': + case ',': + case ';': + case ':': + case '@': + case '/': + case '?': + return true; + default: + return false; + } +} +@end + +@implementation OFIRIFragmentAllowedCharacterSet +- (bool)characterIsMember: (OFUnichar)character +{ + if (character < CHAR_MAX && OFASCIIIsAlnum(character)) + return true; + + if (isUnicode(character)) + return true; + + switch (character) { + case '-': + case '.': + case '_': + case '~': + case '!': + case '$': + case '&': + case '\'': + case '(': + case ')': + case '*': + case '+': + case ',': + case ';': + case '=': + case ':': + case '@': + case '/': + case '?': + return true; + default: + return false; + } +} +@end + +@implementation OFInvertedCharacterSetWithoutPercent +- (instancetype)initWithCharacterSet: (OFCharacterSet *)characterSet +{ + self = [super init]; + + @try { + _characterSet = [characterSet retain]; + _characterIsMember = (bool (*)(id, SEL, OFUnichar)) + [_characterSet methodForSelector: + @selector(characterIsMember:)]; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (void)dealloc +{ + [_characterSet release]; + + [super dealloc]; +} + +- (bool)characterIsMember: (OFUnichar)character +{ + return (character != '%' && !_characterIsMember(_characterSet, + @selector(characterIsMember:), character)); +} +@end + +void +OFIRIVerifyIsEscaped(OFString *string, OFCharacterSet *characterSet, + bool allowPercent) +{ + void *pool = objc_autoreleasePoolPush(); + + if (allowPercent) + characterSet = [[[OFInvertedCharacterSetWithoutPercent alloc] + initWithCharacterSet: characterSet] autorelease]; + else + characterSet = characterSet.invertedSet; + + if ([string indexOfCharacterFromSet: characterSet] != OFNotFound) + @throw [OFInvalidFormatException exception]; + + objc_autoreleasePoolPop(pool); +} + +@implementation OFCharacterSet (IRICharacterSets) ++ (OFCharacterSet *)IRISchemeAllowedCharacterSet +{ + static OFOnceControl onceControl = OFOnceControlInitValue; + OFOnce(&onceControl, initIRISchemeAllowedCharacterSet); + + return IRISchemeAllowedCharacterSet; +} + ++ (OFCharacterSet *)IRIHostAllowedCharacterSet +{ + OFOnce(&IRIAllowedCharacterSetOnce, initIRIAllowedCharacterSet); + + return IRIAllowedCharacterSet; +} + ++ (OFCharacterSet *)IRIUserAllowedCharacterSet +{ + OFOnce(&IRIAllowedCharacterSetOnce, initIRIAllowedCharacterSet); + + return IRIAllowedCharacterSet; +} + ++ (OFCharacterSet *)IRIPasswordAllowedCharacterSet +{ + OFOnce(&IRIAllowedCharacterSetOnce, initIRIAllowedCharacterSet); + + return IRIAllowedCharacterSet; +} + ++ (OFCharacterSet *)IRIPathAllowedCharacterSet +{ + static OFOnceControl onceControl = OFOnceControlInitValue; + OFOnce(&onceControl, initIRIPathAllowedCharacterSet); + + return IRIPathAllowedCharacterSet; +} + ++ (OFCharacterSet *)IRIQueryAllowedCharacterSet +{ + static OFOnceControl onceControl = OFOnceControlInitValue; + OFOnce(&onceControl, initIRIQueryAllowedCharacterSet); + + return IRIQueryAllowedCharacterSet; +} + ++ (OFCharacterSet *)IRIQueryKeyValueAllowedCharacterSet +{ + static OFOnceControl onceControl = OFOnceControlInitValue; + OFOnce(&onceControl, initIRIQueryKeyValueAllowedCharacterSet); + + return IRIQueryKeyValueAllowedCharacterSet; +} + ++ (OFCharacterSet *)IRIFragmentAllowedCharacterSet +{ + static OFOnceControl onceControl = OFOnceControlInitValue; + OFOnce(&onceControl, initIRIFragmentAllowedCharacterSet); + + return IRIFragmentAllowedCharacterSet; +} +@end + +@implementation OFIRI ++ (instancetype)IRI +{ + return [[[self alloc] init] autorelease]; +} + ++ (instancetype)IRIWithString: (OFString *)string +{ + return [[[self alloc] initWithString: string] autorelease]; +} + ++ (instancetype)IRIWithString: (OFString *)string relativeToIRI: (OFIRI *)IRI +{ + return [[[self alloc] initWithString: string + relativeToIRI: IRI] autorelease]; +} + +#ifdef OF_HAVE_FILES ++ (instancetype)fileIRIWithPath: (OFString *)path +{ + return [[[self alloc] initFileIRIWithPath: path] autorelease]; +} + ++ (instancetype)fileIRIWithPath: (OFString *)path isDirectory: (bool)isDirectory +{ + return [[[self alloc] initFileIRIWithPath: path + isDirectory: isDirectory] autorelease]; +} +#endif + +static void +parseUserInfo(OFIRI *self, const char *UTF8String, size_t length) +{ + const char *colon; + + if ((colon = memchr(UTF8String, ':', length)) != NULL) { + self->_percentEncodedUser = [[OFString alloc] + initWithUTF8String: UTF8String + length: colon - UTF8String]; + self->_percentEncodedPassword = [[OFString alloc] + initWithUTF8String: colon + 1 + length: length - (colon - UTF8String) - 1]; + + OFIRIVerifyIsEscaped(self->_percentEncodedPassword, + [OFCharacterSet IRIPasswordAllowedCharacterSet], true); + } else + self->_percentEncodedUser = [[OFString alloc] + initWithUTF8String: UTF8String + length: length]; + + OFIRIVerifyIsEscaped(self->_percentEncodedUser, + [OFCharacterSet IRIUserAllowedCharacterSet], true); +} + +static void +parseHostPort(OFIRI *self, const char *UTF8String, size_t length) +{ + OFString *portString; + + if (*UTF8String == '[') { + const char *end = memchr(UTF8String, ']', length); + + if (end == NULL) + @throw [OFInvalidFormatException exception]; + + for (const char *iter = UTF8String + 1; iter < end; iter++) + if (!OFASCIIIsDigit(*iter) && *iter != ':' && + (*iter < 'a' || *iter > 'f') && + (*iter < 'A' || *iter > 'F')) + @throw [OFInvalidFormatException exception]; + + self->_percentEncodedHost = [[OFString alloc] + initWithUTF8String: UTF8String + length: end - UTF8String + 1]; + + length -= (end - UTF8String) + 1; + UTF8String = end + 1; + } else { + const char *colon = memchr(UTF8String, ':', length); + + if (colon != NULL) { + self->_percentEncodedHost = [[OFString alloc] + initWithUTF8String: UTF8String + length: colon - UTF8String]; + + length -= colon - UTF8String; + UTF8String = colon; + } else { + self->_percentEncodedHost = [[OFString alloc] + initWithUTF8String: UTF8String + length: length]; + + UTF8String += length; + length = 0; + } + + OFIRIVerifyIsEscaped(self->_percentEncodedHost, + [OFCharacterSet IRIHostAllowedCharacterSet], true); + } + + if (length == 0) + return; + + if (length <= 1 || *UTF8String != ':') + @throw [OFInvalidFormatException exception]; + + UTF8String++; + length--; + + for (size_t i = 0; i < length; i++) + if (!OFASCIIIsDigit(UTF8String[i])) + @throw [OFInvalidFormatException exception]; + + portString = [OFString stringWithUTF8String: UTF8String length: length]; + + if (portString.unsignedLongLongValue > 65535) + @throw [OFInvalidFormatException exception]; + + self->_port = [[OFNumber alloc] initWithUnsignedShort: + (unsigned short)portString.unsignedLongLongValue]; +} + +static size_t +parseAuthority(OFIRI *self, const char *UTF8String, size_t length) +{ + size_t ret; + const char *slash, *at; + + if ((slash = memchr(UTF8String, '/', length)) != NULL) + length = slash - UTF8String; + + ret = length; + + if ((at = memchr(UTF8String, '@', length)) != NULL) { + parseUserInfo(self, UTF8String, at - UTF8String); + + length -= at - UTF8String + 1; + UTF8String = at + 1; + } + + parseHostPort(self, UTF8String, length); + + return ret; +} + +static void +parsePathQueryFragment(const char *UTF8String, size_t length, + OFString **pathString, OFString **queryString, OFString **fragmentString) +{ + const char *fragment, *query; + + if ((fragment = memchr(UTF8String, '#', length)) != NULL) { + *fragmentString = [OFString + stringWithUTF8String: fragment + 1 + length: length - (fragment - UTF8String) - 1]; + + OFIRIVerifyIsEscaped(*fragmentString, + [OFCharacterSet IRIQueryAllowedCharacterSet], true); + + length = fragment - UTF8String; + } + + if ((query = memchr(UTF8String, '?', length)) != NULL) { + *queryString = [OFString + stringWithUTF8String: query + 1 + length: length - (query - UTF8String) - 1]; + + OFIRIVerifyIsEscaped(*queryString, + [OFCharacterSet IRIFragmentAllowedCharacterSet], true); + + length = query - UTF8String; + } + + *pathString = [OFString stringWithUTF8String: UTF8String + length: length]; + + OFIRIVerifyIsEscaped(*pathString, + [OFCharacterSet IRIPathAllowedCharacterSet], true); +} + +- (instancetype)initWithString: (OFString *)string +{ + self = [super init]; + + @try { + void *pool = objc_autoreleasePoolPush(); + const char *UTF8String = string.UTF8String; + size_t length = string.UTF8StringLength; + const char *colon; + OFString *path, *query = nil, *fragment = nil; + + if ((colon = strchr(UTF8String, ':')) == NULL || + colon - UTF8String < 1 || !OFASCIIIsAlpha(UTF8String[0])) + @throw [OFInvalidFormatException exception]; + + _scheme = [[[OFString stringWithUTF8String: UTF8String + length: colon - UTF8String] + lowercaseString] copy]; + + OFIRIVerifyIsEscaped(_scheme, + [OFCharacterSet IRISchemeAllowedCharacterSet], false); + + length -= colon - UTF8String + 1; + UTF8String = colon + 1; + + if (length >= 2 && UTF8String[0] == '/' && + UTF8String[1] == '/') { + size_t authorityLength; + + UTF8String += 2; + length -= 2; + + authorityLength = parseAuthority(self, + UTF8String, length); + + UTF8String += authorityLength; + length -= authorityLength; + + if (length > 0) + OFEnsure(UTF8String[0] == '/'); + } + + parsePathQueryFragment(UTF8String, length, + &path, &query, &fragment); + _percentEncodedPath = [path copy]; + _percentEncodedQuery = [query copy]; + _percentEncodedFragment = [fragment copy]; + + objc_autoreleasePoolPop(pool); + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +static bool +isAbsolute(OFString *string) +{ + void *pool = objc_autoreleasePoolPush(); + + @try { + const char *UTF8String = string.UTF8String; + size_t length = string.UTF8StringLength; + + if (length < 1) + return false; + + if (!OFASCIIIsAlpha(UTF8String[0])) + return false; + + for (size_t i = 1; i < length; i++) { + if (UTF8String[i] == ':') + return true; + + if (!OFASCIIIsAlnum(UTF8String[i]) && + UTF8String[i] != '+' && UTF8String[i] != '-' && + UTF8String[i] != '.') + return false; + } + } @finally { + objc_autoreleasePoolPop(pool); + } + + return false; +} + +static OFString * +merge(OFString *base, OFString *path) +{ + OFMutableArray *components; + + if (base.length == 0) + base = @"/"; + + components = [[[base componentsSeparatedByString: @"/"] + mutableCopy] autorelease]; + + if (components.count == 1) + [components addObject: path]; + else + [components replaceObjectAtIndex: components.count - 1 + withObject: path]; + + return [components componentsJoinedByString: @"/"]; +} + +- (instancetype)initWithString: (OFString *)string relativeToIRI: (OFIRI *)IRI +{ + bool absolute; + + @try { + absolute = isAbsolute(string); + } @catch (id e) { + [self release]; + @throw e; + } + + if (absolute) + return [self initWithString: string]; + + self = [super init]; + + @try { + void *pool = objc_autoreleasePoolPush(); + const char *UTF8String = string.UTF8String; + size_t length = string.UTF8StringLength; + bool hasAuthority = false; + OFString *path, *query = nil, *fragment = nil; + + _scheme = [IRI->_scheme copy]; + + if (length >= 2 && UTF8String[0] == '/' && + UTF8String[1] == '/') { + size_t authorityLength; + + hasAuthority = true; + + UTF8String += 2; + length -= 2; + + authorityLength = parseAuthority(self, + UTF8String, length); + + UTF8String += authorityLength; + length -= authorityLength; + + if (length > 0) + OFEnsure(UTF8String[0] == '/'); + } else { + _percentEncodedHost = [IRI->_percentEncodedHost copy]; + _port = [IRI->_port copy]; + _percentEncodedUser = [IRI->_percentEncodedUser copy]; + _percentEncodedPassword = + [IRI->_percentEncodedPassword copy]; + } + + parsePathQueryFragment(UTF8String, length, + &path, &query, &fragment); + _percentEncodedFragment = [fragment copy]; + + if (hasAuthority) { + _percentEncodedPath = [path copy]; + _percentEncodedQuery = [query copy]; + } else { + if (path.length == 0) { + _percentEncodedPath = + [IRI->_percentEncodedPath copy]; + _percentEncodedQuery = (query != nil + ? [query copy] + : [IRI->_percentEncodedQuery copy]); + } else { + if ([path hasPrefix: @"/"]) + _percentEncodedPath = [path copy]; + else + _percentEncodedPath = [merge( + IRI->_percentEncodedPath, path) + copy]; + + _percentEncodedQuery = [query copy]; + } + } + + objc_autoreleasePoolPop(pool); + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +#ifdef OF_HAVE_FILES +- (instancetype)initFileIRIWithPath: (OFString *)path +{ + bool isDirectory; + + @try { + void *pool = objc_autoreleasePoolPush(); + isDirectory = [path of_isDirectoryPath]; + objc_autoreleasePoolPop(pool); + } @catch (id e) { + [self release]; + @throw e; + } + + self = [self initFileIRIWithPath: path isDirectory: isDirectory]; + + return self; +} + +- (instancetype)initFileIRIWithPath: (OFString *)path + isDirectory: (bool)isDirectory +{ + self = [super init]; + + @try { + void *pool = objc_autoreleasePoolPush(); + OFString *percentEncodedHost = nil; + + if (!path.absolutePath) { + OFString *currentDirectoryPath = [OFFileManager + defaultManager].currentDirectoryPath; + + path = [currentDirectoryPath + stringByAppendingPathComponent: path]; + path = path.stringByStandardizingPath; + } + + path = [path of_pathToIRIPathWithPercentEncodedHost: + &percentEncodedHost]; + _percentEncodedHost = [percentEncodedHost copy]; + + if (isDirectory && ![path hasSuffix: @"/"]) + path = [path stringByAppendingString: @"/"]; + + _scheme = @"file"; + _percentEncodedPath = [[path + stringByAddingPercentEncodingWithAllowedCharacters: + [OFCharacterSet IRIPathAllowedCharacterSet]] copy]; + + objc_autoreleasePoolPop(pool); + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} +#endif + +- (instancetype)init +{ + OF_INVALID_INIT_METHOD +} + +- (instancetype)of_init +{ + return [super init]; +} + +- (void)dealloc +{ + [_scheme release]; + [_percentEncodedHost release]; + [_port release]; + [_percentEncodedUser release]; + [_percentEncodedPassword release]; + [_percentEncodedPath release]; + [_percentEncodedQuery release]; + [_percentEncodedFragment release]; + + [super dealloc]; +} + +- (bool)isEqual: (id)object +{ + OFIRI *IRI; + + if (object == self) + return true; + + if (![object isKindOfClass: [OFIRI class]]) + return false; + + IRI = object; + + if (![IRI->_scheme isEqual: _scheme]) + return false; + if (IRI->_percentEncodedHost != _percentEncodedHost && + ![IRI->_percentEncodedHost isEqual: _percentEncodedHost]) + return false; + if (IRI->_port != _port && ![IRI->_port isEqual: _port]) + return false; + if (IRI->_percentEncodedUser != _percentEncodedUser && + ![IRI->_percentEncodedUser isEqual: _percentEncodedUser]) + return false; + if (IRI->_percentEncodedPassword != _percentEncodedPassword && + ![IRI->_percentEncodedPassword isEqual: _percentEncodedPassword]) + return false; + if (![IRI->_percentEncodedPath isEqual: _percentEncodedPath]) + return false; + if (IRI->_percentEncodedQuery != _percentEncodedQuery && + ![IRI->_percentEncodedQuery isEqual: _percentEncodedQuery]) + return false; + if (IRI->_percentEncodedFragment != _percentEncodedFragment && + ![IRI->_percentEncodedFragment isEqual: _percentEncodedFragment]) + return false; + + return true; +} + +- (unsigned long)hash +{ + unsigned long hash; + + OFHashInit(&hash); + + OFHashAddHash(&hash, _scheme.hash); + OFHashAddHash(&hash, _percentEncodedHost.hash); + OFHashAddHash(&hash, _port.hash); + OFHashAddHash(&hash, _percentEncodedUser.hash); + OFHashAddHash(&hash, _percentEncodedPassword.hash); + OFHashAddHash(&hash, _percentEncodedPath.hash); + OFHashAddHash(&hash, _percentEncodedQuery.hash); + OFHashAddHash(&hash, _percentEncodedFragment.hash); + + OFHashFinalize(&hash); + + return hash; +} + +- (OFString *)scheme +{ + return _scheme; +} + +- (OFString *)host +{ + if ([_percentEncodedHost hasPrefix: @"["] && + [_percentEncodedHost hasSuffix: @"]"]) { + OFString *host = [_percentEncodedHost substringWithRange: + OFMakeRange(1, _percentEncodedHost.length - 2)]; + + if (!OFIRIIsIPv6Host(host)) + @throw [OFInvalidArgumentException exception]; + + return host; + } + + return _percentEncodedHost.stringByRemovingPercentEncoding; +} + +- (OFString *)percentEncodedHost +{ + return _percentEncodedHost; +} + +- (OFNumber *)port +{ + return _port; +} + +- (OFString *)user +{ + return _percentEncodedUser.stringByRemovingPercentEncoding; +} + +- (OFString *)percentEncodedUser +{ + return _percentEncodedUser; +} + +- (OFString *)password +{ + return _percentEncodedPassword.stringByRemovingPercentEncoding; +} + +- (OFString *)percentEncodedPassword +{ + return _percentEncodedPassword; +} + +- (OFString *)path +{ + return _percentEncodedPath.stringByRemovingPercentEncoding; +} + +- (OFString *)percentEncodedPath +{ + return _percentEncodedPath; +} + +- (OFArray *)pathComponents +{ + void *pool = objc_autoreleasePoolPush(); +#ifdef OF_HAVE_FILES + bool isFile = [_scheme isEqual: @"file"]; +#endif + OFMutableArray *ret; + size_t count; + +#ifdef OF_HAVE_FILES + if (isFile) { + OFString *path = [_percentEncodedPath + of_IRIPathToPathWithPercentEncodedHost: nil]; + ret = [[path.pathComponents mutableCopy] autorelease]; + + if (![ret.firstObject isEqual: @"/"]) + [ret insertObject: @"/" atIndex: 0]; + } else +#endif + ret = [[[_percentEncodedPath componentsSeparatedByString: @"/"] + mutableCopy] autorelease]; + + count = ret.count; + + if (count > 0 && [ret.firstObject length] == 0) + [ret replaceObjectAtIndex: 0 withObject: @"/"]; + + for (size_t i = 0; i < count; i++) { + OFString *component = [ret objectAtIndex: i]; + +#ifdef OF_HAVE_FILES + if (isFile) + component = + [component of_pathComponentToIRIPathComponent]; +#endif + + component = component.stringByRemovingPercentEncoding; + [ret replaceObjectAtIndex: i withObject: component]; + } + + [ret makeImmutable]; + [ret retain]; + + objc_autoreleasePoolPop(pool); + + return [ret autorelease]; +} + +- (OFString *)lastPathComponent +{ + void *pool = objc_autoreleasePoolPush(); + OFString *path = _percentEncodedPath; + const char *UTF8String, *lastComponent; + size_t length; + OFString *ret; + + if ([path isEqual: @"/"]) { + objc_autoreleasePoolPop(pool); + return @"/"; + } + + if ([path hasSuffix: @"/"]) + path = [path substringToIndex: path.length - 1]; + + UTF8String = lastComponent = path.UTF8String; + length = path.UTF8StringLength; + + for (size_t i = 1; i <= length; i++) { + if (UTF8String[length - i] == '/') { + lastComponent = UTF8String + (length - i) + 1; + break; + } + } + + ret = [OFString + stringWithUTF8String: lastComponent + length: length - (lastComponent - UTF8String)]; + ret = [ret.stringByRemovingPercentEncoding retain]; + + objc_autoreleasePoolPop(pool); + + return [ret autorelease]; +} + +- (OFString *)query +{ + return _percentEncodedQuery.stringByRemovingPercentEncoding; +} + +- (OFString *)percentEncodedQuery +{ + return _percentEncodedQuery; +} + +- (OFArray OF_GENERIC(OFPair OF_GENERIC(OFString *, OFString *) *) *)queryItems +{ + void *pool; + OFArray OF_GENERIC(OFString *) *pairs; + OFMutableArray OF_GENERIC(OFPair OF_GENERIC(OFString *, OFString *) *) + *ret; + + if (_percentEncodedQuery == nil) + return nil; + + pool = objc_autoreleasePoolPush(); + pairs = [_percentEncodedQuery componentsSeparatedByString: @"&"]; + ret = [OFMutableArray arrayWithCapacity: pairs.count]; + + for (OFString *pair in pairs) { + OFArray *parts = [pair componentsSeparatedByString: @"="]; + OFString *name, *value; + + if (parts.count != 2) + @throw [OFInvalidFormatException exception]; + + name = [[parts objectAtIndex: 0] + stringByRemovingPercentEncoding]; + value = [[parts objectAtIndex: 1] + stringByRemovingPercentEncoding]; + + [ret addObject: [OFPair pairWithFirstObject: name + secondObject: value]]; + } + + [ret makeImmutable]; + [ret retain]; + + objc_autoreleasePoolPop(pool); + + return [ret autorelease]; +} + +- (OFString *)fragment +{ + return _percentEncodedFragment.stringByRemovingPercentEncoding; +} + +- (OFString *)percentEncodedFragment +{ + return _percentEncodedFragment; +} + +- (id)copy +{ + return [self retain]; +} + +- (id)mutableCopy +{ + OFIRI *copy = [[OFMutableIRI alloc] initWithScheme: _scheme]; + + @try { + copy->_percentEncodedHost = [_percentEncodedHost copy]; + copy->_port = [_port copy]; + copy->_percentEncodedUser = [_percentEncodedUser copy]; + copy->_percentEncodedPassword = [_percentEncodedPassword copy]; + copy->_percentEncodedPath = [_percentEncodedPath copy]; + copy->_percentEncodedQuery = [_percentEncodedQuery copy]; + copy->_percentEncodedFragment = [_percentEncodedFragment copy]; + } @catch (id e) { + [copy release]; + @throw e; + } + + return copy; +} + +- (OFString *)string +{ + OFMutableString *ret = [OFMutableString string]; + + [ret appendFormat: @"%@:", _scheme]; + + if (_percentEncodedHost != nil || _port != nil || + _percentEncodedUser != nil || _percentEncodedPassword != nil) + [ret appendString: @"//"]; + + if (_percentEncodedUser != nil && _percentEncodedPassword != nil) + [ret appendFormat: @"%@:%@@", + _percentEncodedUser, + _percentEncodedPassword]; + else if (_percentEncodedUser != nil) + [ret appendFormat: @"%@@", _percentEncodedUser]; + + if (_percentEncodedHost != nil) + [ret appendString: _percentEncodedHost]; + if (_port != nil) + [ret appendFormat: @":%@", _port]; + + [ret appendString: _percentEncodedPath]; + + if (_percentEncodedQuery != nil) + [ret appendFormat: @"?%@", _percentEncodedQuery]; + + if (_percentEncodedFragment != nil) + [ret appendFormat: @"#%@", _percentEncodedFragment]; + + [ret makeImmutable]; + + return ret; +} + +#ifdef OF_HAVE_FILES +- (OFString *)fileSystemRepresentation +{ + void *pool = objc_autoreleasePoolPush(); + OFString *path; + + if (![_scheme isEqual: @"file"]) + @throw [OFInvalidArgumentException exception]; + + if (![_percentEncodedPath hasPrefix: @"/"]) + @throw [OFInvalidFormatException exception]; + + path = [self.path + of_IRIPathToPathWithPercentEncodedHost: _percentEncodedHost]; + + [path retain]; + + objc_autoreleasePoolPop(pool); + + return [path autorelease]; +} +#endif + +- (OFIRI *)IRIByAppendingPathComponent: (OFString *)component +{ + OFMutableIRI *IRI = [[self mutableCopy] autorelease]; + [IRI appendPathComponent: component]; + [IRI makeImmutable]; + return IRI; +} + +- (OFIRI *)IRIByAppendingPathComponent: (OFString *)component + isDirectory: (bool)isDirectory +{ + OFMutableIRI *IRI = [[self mutableCopy] autorelease]; + [IRI appendPathComponent: component isDirectory: isDirectory]; + [IRI makeImmutable]; + return IRI; +} + +- (OFIRI *)IRIByStandardizingPath +{ + OFMutableIRI *IRI = [[self mutableCopy] autorelease]; + [IRI standardizePath]; + [IRI makeImmutable]; + return IRI; +} + +- (OFIRI *)IRIByAddingPercentEncodingForUnicodeCharacters +{ + OFMutableIRI *IRI = [[self mutableCopy] autorelease]; + void *pool = objc_autoreleasePoolPush(); + OFCharacterSet *ASCII = + [OFCharacterSet characterSetWithRange: OFMakeRange(0, 0x80)]; + + IRI.percentEncodedHost = [_percentEncodedHost + stringByAddingPercentEncodingWithAllowedCharacters: ASCII]; + IRI.percentEncodedUser = [_percentEncodedUser + stringByAddingPercentEncodingWithAllowedCharacters: ASCII]; + IRI.percentEncodedPassword = [_percentEncodedPassword + stringByAddingPercentEncodingWithAllowedCharacters: ASCII]; + IRI.percentEncodedPath = [_percentEncodedPath + stringByAddingPercentEncodingWithAllowedCharacters: ASCII]; + IRI.percentEncodedQuery = [_percentEncodedQuery + stringByAddingPercentEncodingWithAllowedCharacters: ASCII]; + IRI.percentEncodedFragment = [_percentEncodedFragment + stringByAddingPercentEncodingWithAllowedCharacters: ASCII]; + + [IRI makeImmutable]; + + objc_autoreleasePoolPop(pool); + + return IRI; +} + +- (OFString *)description +{ + return [OFString stringWithFormat: @"<%@: %@>", + self.class, self.string]; +} +@end ADDED src/OFIRIHandler.h Index: src/OFIRIHandler.h ================================================================== --- /dev/null +++ src/OFIRIHandler.h @@ -0,0 +1,353 @@ +/* + * Copyright (c) 2008-2024 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#import "OFFileManager.h" +#import "OFObject.h" +#import "OFString.h" + +OF_ASSUME_NONNULL_BEGIN + +@class OFArray OF_GENERIC(ObjectType); +@class OFData; +@class OFDate; +@class OFIRI; +@class OFStream; + +/** + * @class OFIRIHandler OFIRIHandler.h ObjFW/OFIRIHandler.h + * + * @brief A handler for an IRI scheme. + */ +@interface OFIRIHandler: OFObject +{ + OFString *_scheme; + OF_RESERVE_IVARS(OFIRIHandler, 4) +} + +/** + * @brief The scheme this OFIRIHandler handles. + */ +@property (readonly, nonatomic) OFString *scheme; + +/** + * @brief Registers the specified class as the handler for the specified scheme. + * + * If the same class is specified for two schemes, one instance of it is + * created per scheme. + * + * @param class_ The class to register as the handler for the specified scheme + * @param scheme The scheme for which to register the handler + * @return Whether the class was successfully registered. If a handler for the + * same scheme is already registered, registration fails. + */ ++ (bool)registerClass: (Class)class_ forScheme: (OFString *)scheme; + +/** + * @brief Returns the handler for the specified IRI. + * + * @return The handler for the specified IRI. + * @throw OFUnsupportedProtocolException The specified IRI is not supported + */ ++ (OFIRIHandler *)handlerForIRI: (OFIRI *)IRI; + +/** + * @brief Opens the item at the specified IRI. + * + * @param IRI The IRI of the item which should be opened + * @param mode The mode in which the file should be opened.@n + * Possible modes are: + * @n + * Mode | Description + * ---------------|------------------------------------- + * `r` | Read-only + * `r+` | Read-write + * `w` | Write-only, create or truncate + * `wx` | Write-only, create or fail, exclusive + * `w+` | Read-write, create or truncate + * `w+x` | Read-write, create or fail, exclusive + * `a` | Write-only, create or append + * `a+` | Read-write, create or append + * @n + * The handler is allowed to not implement all modes and is also + * allowed to implement additional, scheme-specific modes. + * @return The opened stream if it was successfully opened + * @throw OFOpenItemFailedException Opening the item failed + * @throw OFUnsupportedProtocolException The specified IRI is not supported + */ ++ (OFStream *)openItemAtIRI: (OFIRI *)IRI mode: (OFString *)mode; + +- (instancetype)init OF_UNAVAILABLE; + +/** + * @brief Initializes the handler for the specified scheme. + * + * @param scheme The scheme to initialize for + * @return An initialized IRI handler + */ +- (instancetype)initWithScheme: (OFString *)scheme OF_DESIGNATED_INITIALIZER; + +/** + * @brief Opens the item at the specified IRI. + * + * @param IRI The IRI of the item which should be opened + * @param mode The mode in which the file should be opened.@n + * Possible modes are: + * @n + * Mode | Description + * ---------------|------------------------------------- + * `r` | Read-only + * `r+` | Read-write + * `w` | Write-only, create or truncate + * `wx` | Write-only, create or fail, exclusive + * `w+` | Read-write, create or truncate + * `w+x` | Read-write, create or fail, exclusive + * `a` | Write-only, create or append + * `a+` | Read-write, create or append + * @n + * The handler is allowed to not implement all modes and is also + * allowed to implement additional, scheme-specific modes. + * @return The opened stream if it was successfully opened + * @throw OFOpenItemFailedException Opening the item failed + * @throw OFUnsupportedProtocolException The specified IRI is not supported by + * the handler + */ +- (OFStream *)openItemAtIRI: (OFIRI *)IRI mode: (OFString *)mode; + +/** + * @brief Returns the attributes for the item at the specified IRI. + * + * @param IRI The IRI to return the attributes for + * @return A dictionary of attributes for the specified IRI, with the keys of + * type @ref OFFileAttributeKey + * @throw OFGetItemAttributesFailedException Failed to get the attributes of + * the item + * @throw OFUnsupportedProtocolException The handler cannot handle the IRI's + * scheme + */ +- (OFFileAttributes)attributesOfItemAtIRI: (OFIRI *)IRI; + +/** + * @brief Sets the attributes for the item at the specified IRI. + * + * All attributes not part of the dictionary are left unchanged. + * + * @param attributes The attributes to set for the specified IRI + * @param IRI The IRI of the item to set the attributes for + * @@throw OFSetItemAttributesFailedException Failed to set the attributes of + * the item + * @throw OFUnsupportedProtocolException The handler cannot handle the IRI's + * scheme + * @throw OFNotImplementedException Setting one or more of the specified + * attributes is not implemented for the + * specified item + */ +- (void)setAttributes: (OFFileAttributes)attributes ofItemAtIRI: (OFIRI *)IRI; + +/** + * @brief Checks whether a file exists at the specified IRI. + * + * @param IRI The IRI to check + * @return A boolean whether there is a file at the specified IRI + * @throw OFUnsupportedProtocolException The handler cannot handle the IRI's + * scheme + */ +- (bool)fileExistsAtIRI: (OFIRI *)IRI; + +/** + * @brief Checks whether a directory exists at the specified IRI. + * + * @param IRI The IRI to check + * @return A boolean whether there is a directory at the specified IRI + * @throw OFUnsupportedProtocolException The handler cannot handle the IRI's + * scheme + */ +- (bool)directoryExistsAtIRI: (OFIRI *)IRI; + +/** + * @brief Creates a directory at the specified IRI. + * + * @param IRI The IRI of the directory to create + * @throw OFCreateDirectoryFailedException Creating the directory failed + * @throw OFUnsupportedProtocolException The handler cannot handle the IRI's + * scheme + */ +- (void)createDirectoryAtIRI: (OFIRI *)IRI; + +/** + * @brief Returns an array with the IRIs of the items in the specified + * directory. + * + * @note `.` and `..` are not part of the returned array. + * + * @param IRI The IRI to the directory whose items should be returned + * @return An array with the IRIs of the items in the specified directory + * @throw OFOpenItemFailedException Opening the directory failed + * @throw OFReadFailedException Reading from the directory failed + * @throw OFUnsupportedProtocolException The handler cannot handle the IRI's + * scheme + */ +- (OFArray OF_GENERIC(OFIRI *) *)contentsOfDirectoryAtIRI: (OFIRI *)IRI; + +/** + * @brief Removes the item at the specified IRI. + * + * If the item at the specified IRI is a directory, it is removed recursively. + * + * @param IRI The IRI to the item which should be removed + * @throw OFRemoveItemFailedException Removing the item failed + * @throw OFUnsupportedProtocolException The handler cannot handle the IRI's + * scheme + */ +- (void)removeItemAtIRI: (OFIRI *)IRI; + +/** + * @brief Creates a hard link for the specified item. + * + * The destination IRI must have a full path, which means it must include the + * name of the item. + * + * This method is not available for all IRIs. + * + * @param source The IRI to the item for which a link should be created + * @param destination The IRI to the item which should link to the source + * @throw OFLinkItemFailedException Linking the item failed + * @throw OFUnsupportedProtocolException The handler cannot handle the scheme + * of one of the IRIs + * @throw OFNotImplementedException Hardlinks are not implemented for the + * specified IRI + */ +- (void)linkItemAtIRI: (OFIRI *)source toIRI: (OFIRI *)destination; + +/** + * @brief Creates a symbolic link for an item. + * + * The destination IRI must have a full path, which means it must include the + * name of the item. + * + * This method is not available for all IRIs. + * + * @note On Windows, this requires at least Windows Vista and administrator + * privileges! + * + * @param IRI The IRI to the item which should symbolically link to the target + * @param target The target of the symbolic link + * @throw OFCreateSymbolicLinkFailed Creating a symbolic link failed + * @throw OFUnsupportedProtocolException The handler cannot handle the IRI's + * scheme + */ +- (void)createSymbolicLinkAtIRI: (OFIRI *)IRI + withDestinationPath: (OFString *)target; + +/** + * @brief Tries to efficiently copy an item. If a copy would only be possible + * by reading the entire item and then writing it, it returns false. + * + * The destination IRI must have a full path, which means it must include the + * name of the item. + * + * If an item already exists, the copy operation fails. This is also the case + * if a directory is copied and an item already exists in the destination + * directory. + * + * @param source The file, directory or symbolic link to copy + * @param destination The destination IRI + * @return True if an efficient copy was performed, false if an efficient copy + * was not possible. Note that errors while performing a copy are + * reported via exceptions and not by returning false! + * @throw OFCopyItemFailedException Copying failed + * @throw OFUnsupportedProtocolException The handler cannot handle the IRI's + * scheme + */ +- (bool)copyItemAtIRI: (OFIRI *)source toIRI: (OFIRI *)destination; + +/** + * @brief Tries to efficiently move an item. If a move would only be possible + * by copying the source and deleting it, it returns false. + * + * The destination IRI must have a full path, which means it must include the + * name of the item. + * + * If the destination is on a different logical device or uses a different + * scheme, an efficient move is not possible and false is returned. + * + * @param source The item to rename + * @param destination The new name for the item + * @return True if an efficient move was performed, false if an efficient move + * was not possible. Note that errors while performing a move are + * reported via exceptions and not by returning false! + * @throw OFMoveItemFailedException Moving failed + * @throw OFUnsupportedProtocolException The handler cannot handle the IRI's + * scheme + */ +- (bool)moveItemAtIRI: (OFIRI *)source toIRI: (OFIRI *)destination; + +/** + * @brief Returns the extended attribute data for the specified name of the + * item at the specified IRI. + * + * This method is not available for all IRIs. + * + * @param name The name of the extended attribute + * @param IRI The IRI of the item to return the extended attribute from + * @throw OFGetItemAttributesFailedException Getting the extended attribute + * failed + * @throw OFUnsupportedProtocolException The handler cannot handle the IRI's + * scheme + * @throw OFNotImplementedException Getting extended attributes is not + * implemented for the specified item + */ +- (OFData *)extendedAttributeDataForName: (OFString *)name + ofItemAtIRI: (OFIRI *)IRI; + +/** + * @brief Sets the extended attribute data for the specified name of the item + * at the specified IRI. + * + * This method is not available for all IRIs. + * + * @param data The data for the extended attribute + * @param name The name of the extended attribute + * @param IRI The IRI of the item to set the extended attribute on + * @throw OFSetItemAttributesFailedException Setting the extended attribute + * failed + * @throw OFUnsupportedProtocolException The handler cannot handle the IRI's + * scheme + * @throw OFNotImplementedException Setting extended attributes is not + * implemented for the specified item + */ +- (void)setExtendedAttributeData: (OFData *)data + forName: (OFString *)name + ofItemAtIRI: (OFIRI *)IRI; + +/** + * @brief Removes the extended attribute for the specified name wof the item at + * the specified IRI. + * + * This method is not available for all IRIs. + * + * @param name The name of the extended attribute to remove + * @param IRI The IRI of the item to remove the extended attribute from + * @throw OFSetItemAttributesFailedException Removing the extended attribute + * failed + * @throw OFUnsupportedProtocolException The handler cannot handle the IRI's + * scheme + * @throw OFNotImplementedException Removing extended attributes is not + * implemented for the specified item + */ +- (void)removeExtendedAttributeForName: (OFString *)name + ofItemAtIRI: (OFIRI *)IRI; +@end + +OF_ASSUME_NONNULL_END ADDED src/OFIRIHandler.m Index: src/OFIRIHandler.m ================================================================== --- /dev/null +++ src/OFIRIHandler.m @@ -0,0 +1,235 @@ +/* + * Copyright (c) 2008-2024 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#include "config.h" + +#import "OFIRIHandler.h" +#import "OFDictionary.h" +#import "OFIRI.h" +#import "OFNumber.h" + +#ifdef OF_HAVE_THREADS +# import "OFMutex.h" +#endif + +#import "OFArchiveIRIHandler.h" +#import "OFEmbeddedIRIHandler.h" +#ifdef OF_HAVE_FILES +# import "OFFileIRIHandler.h" +#endif +#if defined(OF_HAVE_SOCKETS) && defined(OF_HAVE_THREADS) +# import "OFHTTPIRIHandler.h" +#endif + +#import "OFUnsupportedProtocolException.h" + +static OFMutableDictionary OF_GENERIC(OFString *, OFIRIHandler *) *handlers; +#ifdef OF_HAVE_THREADS +static OFMutex *mutex; + +static void +releaseMutex(void) +{ + [mutex release]; +} +#endif + +@implementation OFIRIHandler +@synthesize scheme = _scheme; + ++ (void)initialize +{ + if (self != [OFIRIHandler class]) + return; + + handlers = [[OFMutableDictionary alloc] init]; +#ifdef OF_HAVE_THREADS + mutex = [[OFMutex alloc] init]; + atexit(releaseMutex); +#endif + + [self registerClass: [OFEmbeddedIRIHandler class] + forScheme: @"embedded"]; +#ifdef OF_HAVE_FILES + [self registerClass: [OFFileIRIHandler class] forScheme: @"file"]; +#endif +#if defined(OF_HAVE_SOCKETS) && defined(OF_HAVE_THREADS) + [self registerClass: [OFHTTPIRIHandler class] forScheme: @"http"]; + [self registerClass: [OFHTTPIRIHandler class] forScheme: @"https"]; +#endif + [self registerClass: [OFArchiveIRIHandler class] forScheme: @"gzip"]; + [self registerClass: [OFArchiveIRIHandler class] forScheme: @"lha"]; + [self registerClass: [OFArchiveIRIHandler class] forScheme: @"tar"]; + [self registerClass: [OFArchiveIRIHandler class] forScheme: @"zip"]; +} + ++ (bool)registerClass: (Class)class forScheme: (OFString *)scheme +{ +#ifdef OF_HAVE_THREADS + [mutex lock]; + @try { +#endif + OFIRIHandler *handler; + + if ([handlers objectForKey: scheme] != nil) + return false; + + handler = [[class alloc] initWithScheme: scheme]; + @try { + [handlers setObject: handler forKey: scheme]; + } @finally { + [handler release]; + } +#ifdef OF_HAVE_THREADS + } @finally { + [mutex unlock]; + } +#endif + + return true; +} + ++ (OFIRIHandler *)handlerForIRI: (OFIRI *)IRI +{ + OF_KINDOF(OFIRIHandler *) handler; + +#ifdef OF_HAVE_THREADS + [mutex lock]; + @try { +#endif + handler = [handlers objectForKey: IRI.scheme]; +#ifdef OF_HAVE_THREADS + } @finally { + [mutex unlock]; + } +#endif + + if (handler == nil) + @throw [OFUnsupportedProtocolException exceptionWithIRI: IRI]; + + return handler; +} + ++ (OFStream *)openItemAtIRI: (OFIRI *)IRI mode: (OFString *)mode +{ + return [[self handlerForIRI: IRI] openItemAtIRI: IRI mode: mode]; +} + +- (instancetype)init +{ + OF_INVALID_INIT_METHOD +} + +- (instancetype)initWithScheme: (OFString *)scheme +{ + self = [super init]; + + @try { + _scheme = [scheme copy]; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (void)dealloc +{ + [_scheme release]; + + [super dealloc]; +} + +- (OFStream *)openItemAtIRI: (OFIRI *)IRI mode: (OFString *)mode +{ + OF_UNRECOGNIZED_SELECTOR +} + +- (OFFileAttributes)attributesOfItemAtIRI: (OFIRI *)IRI +{ + OF_UNRECOGNIZED_SELECTOR +} + +- (void)setAttributes: (OFFileAttributes)attributes ofItemAtIRI: (OFIRI *)IRI +{ + OF_UNRECOGNIZED_SELECTOR +} + +- (bool)fileExistsAtIRI: (OFIRI *)IRI +{ + OF_UNRECOGNIZED_SELECTOR +} + +- (bool)directoryExistsAtIRI: (OFIRI *)IRI +{ + OF_UNRECOGNIZED_SELECTOR +} + +- (void)createDirectoryAtIRI: (OFIRI *)IRI +{ + OF_UNRECOGNIZED_SELECTOR +} + +- (OFArray OF_GENERIC(OFIRI *) *)contentsOfDirectoryAtIRI: (OFIRI *)IRI +{ + OF_UNRECOGNIZED_SELECTOR +} + +- (void)removeItemAtIRI: (OFIRI *)IRI +{ + OF_UNRECOGNIZED_SELECTOR +} + +- (void)linkItemAtIRI: (OFIRI *)source toIRI: (OFIRI *)destination +{ + OF_UNRECOGNIZED_SELECTOR +} + +- (void)createSymbolicLinkAtIRI: (OFIRI *)destination + withDestinationPath: (OFString *)source +{ + OF_UNRECOGNIZED_SELECTOR +} + +- (bool)copyItemAtIRI: (OFIRI *)source toIRI: (OFIRI *)destination +{ + return false; +} + +- (bool)moveItemAtIRI: (OFIRI *)source toIRI: (OFIRI *)destination +{ + return false; +} + +- (OFData *)extendedAttributeDataForName: (OFString *)name + ofItemAtIRI: (OFIRI *)IRI +{ + OF_UNRECOGNIZED_SELECTOR +} + +- (void)setExtendedAttributeData: (OFData *)data + forName: (OFString *)name + ofItemAtIRI: (OFIRI *)IRI +{ + OF_UNRECOGNIZED_SELECTOR +} + +- (void)removeExtendedAttributeForName: (OFString *)name + ofItemAtIRI: (OFIRI *)IRI +{ + OF_UNRECOGNIZED_SELECTOR +} +@end Index: src/OFInflate64Stream.h ================================================================== --- src/OFInflate64Stream.h +++ src/OFInflate64Stream.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -68,10 +68,18 @@ } huffman; } _context; bool _inLastBlock, _atEndOfStream; } +/** + * @brief The underlying stream of the inflate stream. + * + * Setting this can be useful if the the data to be inflated is coming from + * multiple streams, such as split across multiple files. + */ +@property (retain, nonatomic) OFStream *underlyingStream; + /** * @brief Creates a new OFInflate64Stream with the specified underlying stream. * * @param stream The underlying stream to which compressed data is written or * from which compressed data is read Index: src/OFInflate64Stream.m ================================================================== --- src/OFInflate64Stream.m +++ src/OFInflate64Stream.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -68,10 +68,18 @@ } huffman; } _context; bool _inLastBlock, _atEndOfStream; } +/** + * @brief The underlying stream of the inflate stream. + * + * Setting this can be useful if the the data to be inflated is coming from + * multiple streams, such as split across multiple files. + */ +@property (retain, nonatomic) OFStream *underlyingStream; + /** * @brief Creates a new OFInflateStream with the specified underlying stream. * * @param stream The underlying stream to which compressed data is written or * from which compressed data is read Index: src/OFInflateStream.m ================================================================== --- src/OFInflateStream.m +++ src/OFInflateStream.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,12 +16,10 @@ #include "config.h" #include #include -#include - #ifndef OF_INFLATE64_STREAM_M # import "OFInflateStream.h" #else # import "OFInflate64Stream.h" # define OFInflateStream OFInflate64Stream @@ -100,16 +98,18 @@ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 }; static OFHuffmanTree fixedLitLenTree, fixedDistTree; @implementation OFInflateStream +@synthesize underlyingStream = _stream; + static OF_INLINE bool tryReadBits(OFInflateStream *stream, uint16_t *bits, uint8_t count) { uint16_t ret = stream->_savedBits; - assert(stream->_savedBitsLength < count); + OFAssert(stream->_savedBitsLength < count); for (uint_fast8_t i = stream->_savedBitsLength; i < count; i++) { if OF_UNLIKELY (stream->_bitIndex == 8) { if OF_LIKELY (stream->_bufferIndex < stream->_bufferLength) @@ -672,13 +672,13 @@ { return ((id )_stream) .fileDescriptorForReading; } -- (bool)hasDataInReadBuffer +- (bool)lowlevelHasDataInReadBuffer { - return (super.hasDataInReadBuffer || _stream.hasDataInReadBuffer || + return (_stream.hasDataInReadBuffer || _bufferLength - _bufferIndex > 0); } - (void)close { Index: src/OFInvertedCharacterSet.h ================================================================== --- src/OFInvertedCharacterSet.h +++ src/OFInvertedCharacterSet.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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 @@ * * @param object The object which did become ready for writing */ - (void)objectIsReadyForWriting: (id)object; -#ifdef OF_AMIGAOS +#if defined(OF_AMIGAOS) || defined(DOXYGEN) /** * @brief This callback is called when an Exec Signal was received. * * @note This is only available on AmigaOS! */ @@ -119,39 +119,39 @@ OFMutableArray OF_GENERIC(id ) *_readObjects; OFMutableArray OF_GENERIC(id ) *_writeObjects; id _Nullable _delegate; -#if defined(OF_AMIGAOS) +# if defined(OF_AMIGAOS) struct Task *_waitingTask; ULONG _cancelSignal; -#elif defined(OF_HAVE_PIPE) +# elif defined(OF_HAVE_PIPE) int _cancelFD[2]; -#else +# else OFSocketHandle _cancelFD[2]; struct sockaddr_in _cancelAddr; -#endif -#ifdef OF_AMIGAOS +# endif +# ifdef OF_AMIGAOS ULONG _execSignalMask; -#endif +# endif OF_RESERVE_IVARS(OFKernelEventObserver, 4) } /** * @brief The delegate for the OFKernelEventObserver. */ @property OF_NULLABLE_PROPERTY (assign, nonatomic) id delegate; -#ifdef OF_AMIGAOS +# if defined(OF_AMIGAOS) || defined(DOXYGEN) /** * @brief A mask of Exec Signals to wait for. * * @note This is only available on AmigaOS! */ @property (nonatomic) ULONG execSignalMask; -#endif +# endif /** * @brief Creates a new OFKernelEventObserver. * * @return A new, autoreleased OFKernelEventObserver Index: src/OFKernelEventObserver.m ================================================================== --- src/OFKernelEventObserver.m +++ src/OFKernelEventObserver.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,11 +46,13 @@ #import "OFInitializationFailedException.h" #import "OFInvalidArgumentException.h" #import "OFOutOfRangeException.h" #ifdef OF_AMIGAOS +# define Class IntuitionClass # include +# undef Class #endif @implementation OFKernelEventObserver @synthesize delegate = _delegate; #ifdef OF_AMIGAOS @@ -204,15 +206,20 @@ { void *pool = objc_autoreleasePoolPush(); bool foundInReadBuffer = false; for (id object in [[_readObjects copy] autorelease]) { - void *pool2 = objc_autoreleasePoolPush(); + void *pool2; + + if (![object isKindOfClass: [OFStream class]]) + continue; + + pool2 = objc_autoreleasePoolPush(); - if ([object isKindOfClass: [OFStream class]] && - [object hasDataInReadBuffer] && - ![(OFStream *)object of_isWaitingForDelimiter]) { + if ([object hasDataInReadBuffer] && + (![object of_isWaitingForDelimiter] || + [object lowlevelHasDataInReadBuffer])) { if ([_delegate respondsToSelector: @selector(objectIsReadyForReading:)]) [_delegate objectIsReadyForReading: object]; foundInReadBuffer = true; Index: src/OFKeyValueCoding.h ================================================================== --- src/OFKeyValueCoding.h +++ src/OFKeyValueCoding.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,11 +13,10 @@ * file. */ #include "config.h" -#include #include #ifdef HAVE_FCNTL_H # include #endif @@ -186,11 +185,11 @@ errNo: (int)eventList[i].data]; if (eventList[i].ident == (uintptr_t)_cancelFD[0]) { char buffer; - assert(eventList[i].filter == EVFILT_READ); + OFAssert(eventList[i].filter == EVFILT_READ); OFEnsure(read(_cancelFD[0], &buffer, 1) == 1); continue; } @@ -208,12 +207,12 @@ @selector(objectIsReadyForWriting:)]) [_delegate objectIsReadyForWriting: (id)eventList[i].udata]; break; default: - assert(0); + OFAssert(0); } objc_autoreleasePoolPop(pool); } } @end Index: src/OFLHAArchive.h ================================================================== --- src/OFLHAArchive.h +++ src/OFLHAArchive.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,12 +18,12 @@ #import "OFLHAArchiveEntry.h" #import "OFString.h" OF_ASSUME_NONNULL_BEGIN +@class OFIRI; @class OFStream; -@class OFURI; /** * @class OFLHAArchive OFLHAArchive.h ObjFW/OFLHAArchive.h * * @brief A class for accessing and manipulating LHA files. @@ -59,28 +59,28 @@ + (instancetype)archiveWithStream: (OFStream *)stream mode: (OFString *)mode; /** * @brief Creates a new OFLHAArchive object with the specified file. * - * @param URI The URI to the LHA file + * @param IRI The IRI to the LHA file * @param mode The mode for the LHA file. Valid modes are "r" for reading, * "w" for creating a new file and "a" for appending to an existing * archive. * @return A new, autoreleased OFLHAArchive */ -+ (instancetype)archiveWithURI: (OFURI *)URI mode: (OFString *)mode; ++ (instancetype)archiveWithIRI: (OFIRI *)IRI mode: (OFString *)mode; /** - * @brief Creates a URI for accessing a the specified file within the specified - * LHA archive. + * @brief Creates an IRI for accessing a the specified file within the + * specified LHA archive. * * @param path The path of the file within the archive - * @param URI The URI of the archive - * @return A URI for accessing the specified file within the specified LHA + * @param IRI The IRI of the archive + * @return An IRI for accessing the specified file within the specified LHA * archive */ -+ (OFURI *)URIForFilePath: (OFString *)path inArchiveWithURI: (OFURI *)URI; ++ (OFIRI *)IRIForFilePath: (OFString *)path inArchiveWithIRI: (OFIRI *)IRI; - (instancetype)init OF_UNAVAILABLE; /** * @brief Initializes an already allocated OFLHAArchive object with the @@ -98,17 +98,17 @@ /** * @brief Initializes an already allocated OFLHAArchive object with the * specified file. * - * @param URI The URI to the LHA file + * @param IRI The IRI to the LHA file * @param mode The mode for the LHA file. Valid modes are "r" for reading, * "w" for creating a new file and "a" for appending to an existing * archive. * @return An initialized OFLHAArchive */ -- (instancetype)initWithURI: (OFURI *)URI mode: (OFString *)mode; +- (instancetype)initWithIRI: (OFIRI *)IRI mode: (OFString *)mode; /** * @brief Returns the next entry from the LHA archive or `nil` if all entries * have been read. * Index: src/OFLHAArchive.m ================================================================== --- src/OFLHAArchive.m +++ src/OFLHAArchive.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,18 +20,18 @@ #include #import "OFLHAArchive.h" #import "OFLHAArchiveEntry.h" #import "OFLHAArchiveEntry+Private.h" -#import "OFArchiveURIHandler.h" +#import "OFArchiveIRIHandler.h" #import "OFCRC16.h" +#import "OFIRI.h" +#import "OFIRIHandler.h" #import "OFLHADecompressingStream.h" #import "OFSeekableStream.h" #import "OFStream.h" #import "OFString.h" -#import "OFURI.h" -#import "OFURIHandler.h" #import "OFChecksumMismatchException.h" #import "OFInvalidArgumentException.h" #import "OFNotImplementedException.h" #import "OFNotOpenException.h" @@ -86,18 +86,18 @@ + (instancetype)archiveWithStream: (OFStream *)stream mode: (OFString *)mode { return [[[self alloc] initWithStream: stream mode: mode] autorelease]; } -+ (instancetype)archiveWithURI: (OFURI *)URI mode: (OFString *)mode ++ (instancetype)archiveWithIRI: (OFIRI *)IRI mode: (OFString *)mode { - return [[[self alloc] initWithURI: URI mode: mode] autorelease]; + return [[[self alloc] initWithIRI: IRI mode: mode] autorelease]; } -+ (OFURI *)URIForFilePath: (OFString *)path inArchiveWithURI: (OFURI *)URI ++ (OFIRI *)IRIForFilePath: (OFString *)path inArchiveWithIRI: (OFIRI *)IRI { - return OFArchiveURIHandlerURIForFileInArchive(@"lha", path, URI); + return OFArchiveIRIHandlerIRIForFileInArchive(@"lha", path, IRI); } - (instancetype)init { OF_INVALID_INIT_METHOD @@ -134,20 +134,20 @@ } return self; } -- (instancetype)initWithURI: (OFURI *)URI mode: (OFString *)mode +- (instancetype)initWithIRI: (OFIRI *)IRI mode: (OFString *)mode { void *pool = objc_autoreleasePoolPush(); OFStream *stream; @try { if ([mode isEqual: @"a"]) - stream = [OFURIHandler openItemAtURI: URI mode: @"r+"]; + stream = [OFIRIHandler openItemAtIRI: IRI mode: @"r+"]; else - stream = [OFURIHandler openItemAtURI: URI mode: mode]; + stream = [OFIRIHandler openItemAtIRI: IRI mode: mode]; } @catch (id e) { [self release]; @throw e; } @@ -173,10 +173,23 @@ char header[21]; size_t headerLen; if (_mode != modeRead) @throw [OFInvalidArgumentException exception]; + + if (_currentEntry != nil && _lastReturnedStream == nil) { + /* + * No read stream was created since the last call to + * -[nextEntry]. Create it so that we can properly skip the + * data. + */ + void *pool = objc_autoreleasePoolPush(); + + [self streamForReadingCurrentEntry]; + + objc_autoreleasePoolPop(pool); + } [_currentEntry release]; _currentEntry = nil; [(OFLHAArchiveFileReadStream *)_lastReturnedStream of_skip]; @@ -200,11 +213,11 @@ headerLen += [_stream readIntoBuffer: header + headerLen length: 21 - headerLen]; } - _currentEntry= [[OFLHAArchiveEntry alloc] + _currentEntry = [[OFLHAArchiveEntry alloc] of_initWithHeader: header stream: _stream encoding: _encoding]; return _currentEntry; Index: src/OFLHAArchiveEntry+Private.h ================================================================== --- src/OFLHAArchiveEntry+Private.h +++ src/OFLHAArchiveEntry+Private.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,12 +13,10 @@ * file. */ #include "config.h" -#include - #import "OFLHADecompressingStream.h" #import "OFKernelEventObserver.h" #import "OFHuffmanTree.h" @@ -48,11 +46,11 @@ static OF_INLINE bool tryReadBits(OFLHADecompressingStream *stream, uint16_t *bits, uint8_t count) { uint16_t ret = stream->_savedBits; - assert(stream->_savedBitsLength < count); + OFAssert(stream->_savedBitsLength < count); for (uint_fast8_t i = stream->_savedBitsLength; i < count; i++) { if OF_UNLIKELY (stream->_bitIndex == 8) { if OF_LIKELY (stream->_bufferIndex < stream->_bufferLength) @@ -507,13 +505,13 @@ { return ((id )_stream) .fileDescriptorForReading; } -- (bool)hasDataInReadBuffer +- (bool)lowlevelHasDataInReadBuffer { - return (super.hasDataInReadBuffer || _stream.hasDataInReadBuffer || + return (_stream.hasDataInReadBuffer || _bufferLength - _bufferIndex > 0); } - (void)close { Index: src/OFList.h ================================================================== --- src/OFList.h +++ src/OFList.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,11 +14,10 @@ */ #import "OFObject.h" #import "OFCollection.h" #import "OFEnumerator.h" -#import "OFSerialization.h" OF_ASSUME_NONNULL_BEGIN /** @file */ @@ -79,12 +78,11 @@ /** * @class OFList OFList.h ObjFW/OFList.h * * @brief A class which provides easy to use double-linked lists. */ -@interface OFList OF_GENERIC(ObjectType): OFObject +@interface OFList OF_GENERIC(ObjectType): OFObject #if !defined(OF_HAVE_GENERICS) && !defined(DOXYGEN) # define ObjectType id #endif { OFListItem _Nullable _firstListItem; Index: src/OFList.m ================================================================== --- src/OFList.m +++ src/OFList.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,15 +14,13 @@ */ #include "config.h" #include -#include #import "OFList.h" #import "OFString.h" -#import "OFXMLElement.h" #import "OFArray.h" #import "OFEnumerationMutationException.h" #import "OFInvalidArgumentException.h" @@ -68,39 +66,10 @@ + (instancetype)list { return [[[self alloc] init] autorelease]; } -- (instancetype)initWithSerialization: (OFXMLElement *)element -{ - self = [self init]; - - @try { - void *pool = objc_autoreleasePoolPush(); - - if (![element.name isEqual: self.className] || - ![element.namespace isEqual: OFSerializationNS]) - @throw [OFInvalidArgumentException exception]; - - for (OFXMLElement *child in - [element elementsForNamespace: OFSerializationNS]) { - void *pool2 = objc_autoreleasePoolPush(); - - [self appendObject: child.objectByDeserializing]; - - objc_autoreleasePoolPop(pool2); - } - - objc_autoreleasePoolPop(pool); - } @catch (id e) { - [self release]; - @throw e; - } - - return self; -} - - (void)dealloc { OFListItem next; for (OFListItem iter = _firstListItem; iter != NULL; iter = next) { @@ -254,11 +223,11 @@ iter = iter->next, iter2 = iter2->next) if (![iter->object isEqual: iter2->object]) return false; /* One is bigger than the other even though we checked the count */ - assert(iter == NULL && iter2 == NULL); + OFAssert(iter == NULL && iter2 == NULL); return true; } - (bool)containsObject: (id)object @@ -372,28 +341,10 @@ [ret makeImmutable]; return ret; } -- (OFXMLElement *)XMLElementBySerializing -{ - OFXMLElement *element = - [OFXMLElement elementWithName: self.className - namespace: OFSerializationNS]; - - for (OFListItem iter = _firstListItem; - iter != NULL; iter = iter->next) { - void *pool = objc_autoreleasePoolPush(); - - [element addChild: [iter->object XMLElementBySerializing]]; - - objc_autoreleasePoolPop(pool); - } - - return element; -} - - (int)countByEnumeratingWithState: (OFFastEnumerationState *)state objects: (id *)objects count: (int)count { OFListItem listItem; Index: src/OFLocale.h ================================================================== --- src/OFLocale.h +++ src/OFLocale.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,12 @@ #import "OFObject.h" #import "OFString.h" OF_ASSUME_NONNULL_BEGIN + +@class OFIRI; /** @file */ /** * @def OF_LOCALIZED @@ -136,18 +138,16 @@ * * @return The decimal point of the system's locale */ + (nullable OFString *)decimalSeparator; -#ifdef OF_HAVE_FILES /** * @brief Adds a directory to scan for localizations. * - * @param path The path to the directory to scan for localizations + * @param IRI The IRI to the directory to scan for localizations */ -+ (void)addLocalizationDirectory: (OFString *)path; -#endif ++ (void)addLocalizationDirectoryIRI: (OFIRI *)IRI; /** * @brief Initializes the current OFLocale. * * @warning This sets the locale via `setlocale()`! @@ -157,18 +157,16 @@ * instance of OFLocale, which will become the current locale, and * call this method. */ - (instancetype)init; -#ifdef OF_HAVE_FILES /** * @brief Adds a directory to scan for localizations. * - * @param path The path to the directory to scan for localizations + * @param IRI The IRI to the directory to scan for localizations */ -- (void)addLocalizationDirectory: (OFString *)path; -#endif +- (void)addLocalizationDirectoryIRI: (OFIRI *)IRI; /** * @brief Returns the localized string for the specified ID, using the fallback * string if it cannot be looked up or is missing. * Index: src/OFLocale.m ================================================================== --- src/OFLocale.m +++ src/OFLocale.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,24 +16,27 @@ #include "config.h" #include #import "OFLocale.h" -#import "OFString.h" #import "OFArray.h" #import "OFDictionary.h" +#import "OFIRI.h" #import "OFNumber.h" +#import "OFString.h" #import "OFInitializationFailedException.h" #import "OFInvalidArgumentException.h" #import "OFInvalidFormatException.h" #import "OFOpenItemFailedException.h" #ifdef OF_AMIGAOS +# define Class IntuitionClass # include # include # include +# undef Class #endif static OFLocale *currentLocale = nil; static OFDictionary *operatorPrecedences = nil; @@ -359,16 +362,14 @@ + (OFString *)decimalSeparator { return currentLocale.decimalSeparator; } -#ifdef OF_HAVE_FILES -+ (void)addLocalizationDirectory: (OFString *)path ++ (void)addLocalizationDirectoryIRI: (OFIRI *)IRI { - [currentLocale addLocalizationDirectory: path]; + [currentLocale addLocalizationDirectoryIRI: IRI]; } -#endif - (instancetype)init { self = [super init]; @@ -378,11 +379,15 @@ if (currentLocale != nil) @throw [OFInitializationFailedException exceptionWithClass: self.class]; +# ifdef OF_MSDOS + _encoding = OFStringEncodingCodepage437; +# else _encoding = OFStringEncodingUTF8; +# endif _decimalSeparator = @"."; _localizedStrings = [[OFMutableArray alloc] init]; if ((locale = setlocale(LC_ALL, "")) != NULL) _decimalSeparator = [[OFString alloc] @@ -492,25 +497,25 @@ [_localizedStrings release]; [super dealloc]; } -#ifdef OF_HAVE_FILES -- (void)addLocalizationDirectory: (OFString *)path +- (void)addLocalizationDirectoryIRI: (OFIRI *)IRI { void *pool; - OFString *mapPath, *languageCode, *countryCode, *localizationFile; + OFIRI *mapIRI, *localizationIRI; + OFString *languageCode, *countryCode, *localizationFile; OFDictionary *map; if (_languageCode == nil) return; pool = objc_autoreleasePoolPush(); - mapPath = [path stringByAppendingPathComponent: @"localizations.json"]; + mapIRI = [IRI IRIByAppendingPathComponent: @"localizations.json"]; @try { - map = [[OFString stringWithContentsOfFile: mapPath] + map = [[OFString stringWithContentsOfIRI: mapIRI] objectByParsingJSON]; } @catch (OFOpenItemFailedException *e) { objc_autoreleasePoolPop(pool); return; } @@ -530,19 +535,18 @@ if (localizationFile == nil) { objc_autoreleasePoolPop(pool); return; } - localizationFile = [path stringByAppendingPathComponent: + localizationIRI = [IRI IRIByAppendingPathComponent: [localizationFile stringByAppendingString: @".json"]]; - [_localizedStrings addObject: [[OFString stringWithContentsOfFile: - localizationFile] objectByParsingJSON]]; + [_localizedStrings addObject: [[OFString stringWithContentsOfIRI: + localizationIRI] objectByParsingJSON]]; objc_autoreleasePoolPop(pool); } -#endif - (OFString *)localizedStringForID: (OFConstantString *)ID fallback: (id)fallback, ... { OFString *ret; Index: src/OFLocking.h ================================================================== --- src/OFLocking.h +++ src/OFLocking.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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+Private.h ================================================================== --- src/OFMapTable+Private.h +++ src/OFMapTable+Private.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -72,11 +72,11 @@ @interface OFMapTable: OFObject { OFMapTableFunctions _keyFunctions, _objectFunctions; struct OFMapTableBucket *_Nonnull *_Nullable _buckets; uint32_t _count, _capacity; - unsigned char _rotate; + unsigned char _rotation; unsigned long _mutations; } /** * @brief The key functions used by the map table. Index: src/OFMapTable.m ================================================================== --- src/OFMapTable.m +++ src/OFMapTable.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,12 +18,10 @@ #include "config.h" #include #include -#include - #import "OFMapTable.h" #import "OFMapTable+Private.h" #import "OFEnumerator.h" #import "OFEnumerationMutationException.h" @@ -157,11 +155,11 @@ _capacity = minCapacity; _buckets = OFAllocZeroedMemory(_capacity, sizeof(*_buckets)); if (OFHashSeed != 0) - _rotate = OFRandom16() & 31; + _rotation = OFRandom16() & 31; } @catch (id e) { [self release]; @throw e; } @@ -187,10 +185,11 @@ static void resizeForCount(OFMapTable *self, uint32_t count) { uint32_t fullness, capacity; struct OFMapTableBucket **buckets; + unsigned char newRotation; if (count > UINT32_MAX / sizeof(*self->_buckets) || count > UINT32_MAX / 8) @throw [OFOutOfRangeException exception]; @@ -213,24 +212,27 @@ if ((capacity < self->_capacity && count > self->_count) || capacity < minCapacity) return; buckets = OFAllocZeroedMemory(capacity, sizeof(*buckets)); + newRotation = (OFHashSeed != 0 ? OFRandom16() & 31 : 0); for (uint32_t i = 0; i < self->_capacity; i++) { if (self->_buckets[i] != NULL && self->_buckets[i] != &deletedBucket) { - uint32_t j, last; + uint32_t rotatedHash, j, last; + rotatedHash = OFRotateLeft(self->_buckets[i]->hash, + newRotation); last = capacity; - for (j = self->_buckets[i]->hash & (capacity - 1); + for (j = rotatedHash & (capacity - 1); j < last && buckets[j] != NULL; j++); /* In case the last bucket is already used */ if (j >= last) { - last = self->_buckets[i]->hash & (capacity - 1); + last = rotatedHash & (capacity - 1); for (j = 0; j < last && buckets[j] != NULL; j++); } @@ -242,25 +244,26 @@ } OFFreeMemory(self->_buckets); self->_buckets = buckets; self->_capacity = capacity; + self->_rotation = newRotation; } static void setObject(OFMapTable *restrict self, void *key, void *object, uint32_t hash) { - uint32_t i, last; + uint32_t rotatedHash, i, last; void *old; if (key == NULL || object == NULL) @throw [OFInvalidArgumentException exception]; - hash = OFRotateLeft(hash, self->_rotate); + rotatedHash = OFRotateLeft(hash, self->_rotation); last = self->_capacity; - for (i = hash & (self->_capacity - 1); + for (i = rotatedHash & (self->_capacity - 1); i < last && self->_buckets[i] != NULL; i++) { if (self->_buckets[i] == &deletedBucket) continue; if (self->_keyFunctions.equal(self->_buckets[i]->key, key)) @@ -267,11 +270,11 @@ break; } /* In case the last bucket is already used */ if (i >= last) { - last = hash & (self->_capacity - 1); + last = rotatedHash & (self->_capacity - 1); for (i = 0; i < last && self->_buckets[i] != NULL; i++) { if (self->_buckets[i] == &deletedBucket) continue; @@ -286,21 +289,23 @@ self->_buckets[i] == &deletedBucket || !self->_keyFunctions.equal(self->_buckets[i]->key, key)) { struct OFMapTableBucket *bucket; resizeForCount(self, self->_count + 1); + /* Resizing can change the rotation */ + rotatedHash = OFRotateLeft(hash, self->_rotation); self->_mutations++; last = self->_capacity; - for (i = hash & (self->_capacity - 1); i < last && + for (i = rotatedHash & (self->_capacity - 1); i < last && self->_buckets[i] != NULL && self->_buckets[i] != &deletedBucket; i++); /* In case the last bucket is already used */ if (i >= last) { - last = hash & (self->_capacity - 1); + last = rotatedHash & (self->_capacity - 1); for (i = 0; i < last && self->_buckets[i] != NULL && self->_buckets[i] != &deletedBucket; i++); } @@ -372,11 +377,11 @@ { unsigned long hash = 0; for (unsigned long i = 0; i < _capacity; i++) { if (_buckets[i] != NULL && _buckets[i] != &deletedBucket) { - hash ^= OFRotateRight(_buckets[i]->hash, _rotate); + hash ^= _buckets[i]->hash; hash ^= _objectFunctions.hash(_buckets[i]->object); } } return hash; @@ -392,12 +397,11 @@ @try { for (uint32_t i = 0; i < _capacity; i++) if (_buckets[i] != NULL && _buckets[i] != &deletedBucket) setObject(copy, _buckets[i]->key, - _buckets[i]->object, - OFRotateRight(_buckets[i]->hash, _rotate)); + _buckets[i]->object, _buckets[i]->hash); } @catch (id e) { [copy release]; @throw e; } @@ -409,19 +413,21 @@ return _count; } - (void *)objectForKey: (void *)key { - uint32_t i, hash, last; + uint32_t i, rotatedHash, last; if (key == NULL) @throw [OFInvalidArgumentException exception]; - hash = OFRotateLeft((uint32_t)_keyFunctions.hash(key), _rotate); + rotatedHash = OFRotateLeft((uint32_t)_keyFunctions.hash(key), + _rotation); last = _capacity; - for (i = hash & (_capacity - 1); i < last && _buckets[i] != NULL; i++) { + for (i = rotatedHash & (_capacity - 1); + i < last && _buckets[i] != NULL; i++) { if (_buckets[i] == &deletedBucket) continue; if (_keyFunctions.equal(_buckets[i]->key, key)) return _buckets[i]->object; @@ -429,11 +435,11 @@ if (i < last) return nil; /* In case the last bucket is already used */ - last = hash & (_capacity - 1); + last = rotatedHash & (_capacity - 1); for (i = 0; i < last && _buckets[i] != NULL; i++) { if (_buckets[i] == &deletedBucket) continue; @@ -449,19 +455,21 @@ setObject(self, key, object, (uint32_t)_keyFunctions.hash(key)); } - (void)removeObjectForKey: (void *)key { - uint32_t i, hash, last; + uint32_t i, rotatedHash, last; if (key == NULL) @throw [OFInvalidArgumentException exception]; - hash = OFRotateLeft((uint32_t)_keyFunctions.hash(key), _rotate); + rotatedHash = OFRotateLeft((uint32_t)_keyFunctions.hash(key), + _rotation); last = _capacity; - for (i = hash & (_capacity - 1); i < last && _buckets[i] != NULL; i++) { + for (i = rotatedHash & (_capacity - 1); + i < last && _buckets[i] != NULL; i++) { if (_buckets[i] == &deletedBucket) continue; if (_keyFunctions.equal(_buckets[i]->key, key)) { _mutations++; @@ -481,11 +489,11 @@ if (i < last) return; /* In case the last bucket is already used */ - last = hash & (_capacity - 1); + last = rotatedHash & (_capacity - 1); for (i = 0; i < last && _buckets[i] != NULL; i++) { if (_buckets[i] == &deletedBucket) continue; @@ -525,15 +533,15 @@ _count = 0; _capacity = minCapacity; _buckets = OFResizeMemory(_buckets, _capacity, sizeof(*_buckets)); /* - * Get a new random value for _rotate, so that it is not less secure + * Get a new random value for _rotation, so that it is not less secure * than creating a new hash map. */ if (OFHashSeed != 0) - _rotate = OFRandom16() & 31; + _rotation = OFRandom16() & 31; } - (bool)containsObject: (void *)object { if (object == NULL || _count == 0) DELETED src/OFMapTableDictionary.h Index: src/OFMapTableDictionary.h ================================================================== --- src/OFMapTableDictionary.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (c) 2008-2022 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#import "OFDictionary.h" - -OF_ASSUME_NONNULL_BEGIN - -@class OFMapTable; -@class OFMapTableEnumerator; - -@interface OFMapTableDictionary: OFDictionary -{ - OFMapTable *_mapTable; -} - -- (instancetype)initWithCapacity: (size_t)capacity; -@end - -OF_ASSUME_NONNULL_END DELETED src/OFMapTableDictionary.m Index: src/OFMapTableDictionary.m ================================================================== --- src/OFMapTableDictionary.m +++ /dev/null @@ -1,439 +0,0 @@ -/* - * Copyright (c) 2008-2022 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 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 "OFMapTableDictionary.h" -#import "OFArray.h" -#import "OFMapTable+Private.h" -#import "OFMapTable.h" -#import "OFMutableMapTableDictionary.h" -#import "OFString.h" -#import "OFXMLElement.h" - -#import "OFEnumerationMutationException.h" -#import "OFInvalidArgumentException.h" -#import "OFInvalidFormatException.h" - -static void * -copy(void *object) -{ - return [(id)object copy]; -} - -static void * -retain(void *object) -{ - return [(id)object retain]; -} - -static void -release(void *object) -{ - [(id)object release]; -} - -static unsigned long -hash(void *object) -{ - return [(id)object hash]; -} - -static bool -equal(void *object1, void *object2) -{ - return [(id)object1 isEqual: (id)object2]; -} - -static const OFMapTableFunctions keyFunctions = { - .retain = copy, - .release = release, - .hash = hash, - .equal = equal -}; -static const OFMapTableFunctions objectFunctions = { - .retain = retain, - .release = release, - .hash = hash, - .equal = equal -}; - -@implementation OFMapTableDictionary -- (instancetype)init -{ - return [self initWithCapacity: 0]; -} - -- (instancetype)initWithCapacity: (size_t)capacity -{ - self = [super init]; - - @try { - _mapTable = [[OFMapTable alloc] - initWithKeyFunctions: keyFunctions - objectFunctions: objectFunctions - capacity: capacity]; - } @catch (id e) { - [self release]; - @throw e; - } - - return self; -} - -- (instancetype)initWithDictionary: (OFDictionary *)dictionary -{ - size_t count; - - if (dictionary == nil) - return [self init]; - - if ([dictionary isKindOfClass: [OFMapTableDictionary class]] || - [dictionary isKindOfClass: [OFMutableMapTableDictionary class]]) { - self = [super init]; - - @try { - OFMapTableDictionary *dictionary_ = - (OFMapTableDictionary *)dictionary; - - _mapTable = [dictionary_->_mapTable copy]; - } @catch (id e) { - [self release]; - @throw e; - } - - return self; - } - - @try { - count = dictionary.count; - } @catch (id e) { - [self release]; - @throw e; - } - - self = [self initWithCapacity: count]; - - @try { - void *pool = objc_autoreleasePoolPush(); - OFEnumerator *keyEnumerator, *objectEnumerator; - id key, object; - - keyEnumerator = [dictionary keyEnumerator]; - objectEnumerator = [dictionary objectEnumerator]; - while ((key = [keyEnumerator nextObject]) != nil && - (object = [objectEnumerator nextObject]) != nil) - [_mapTable setObject: object forKey: key]; - - objc_autoreleasePoolPop(pool); - } @catch (id e) { - [self release]; - @throw e; - } - - return self; -} - -- (instancetype)initWithObject: (id)object forKey: (id)key -{ - self = [self initWithCapacity: 1]; - - @try { - [_mapTable setObject: object forKey: key]; - } @catch (id e) { - [self release]; - @throw e; - } - - return self; -} - -- (instancetype)initWithObjects: (id const *)objects - forKeys: (id const *)keys - count: (size_t)count -{ - self = [self initWithCapacity: count]; - - @try { - size_t i; - - for (i = 0; i < count; i++) - [_mapTable setObject: objects[i] forKey: keys[i]]; - } @catch (id e) { - [self release]; - @throw e; - } - - return self; -} - -- (instancetype)initWithKey: (id)firstKey arguments: (va_list)arguments -{ - self = [super init]; - - @try { - va_list argumentsCopy; - id key, object; - size_t i, count; - - va_copy(argumentsCopy, arguments); - - if (firstKey == nil) - @throw [OFInvalidArgumentException exception]; - - key = firstKey; - - if ((object = va_arg(arguments, id)) == nil) - @throw [OFInvalidArgumentException exception]; - - count = 1; - for (; va_arg(argumentsCopy, id) != nil; count++); - - if (count % 2 != 0) - @throw [OFInvalidArgumentException exception]; - - count /= 2; - - _mapTable = [[OFMapTable alloc] - initWithKeyFunctions: keyFunctions - objectFunctions: objectFunctions - capacity: count]; - - [_mapTable setObject: object forKey: key]; - - for (i = 1; i < count; i++) { - key = va_arg(arguments, id); - object = va_arg(arguments, id); - - if (key == nil || object == nil) - @throw [OFInvalidArgumentException exception]; - - [_mapTable setObject: object forKey: key]; - } - } @catch (id e) { - [self release]; - @throw e; - } - - return self; -} - -- (instancetype)initWithSerialization: (OFXMLElement *)element -{ - self = [super init]; - - @try { - void *pool = objc_autoreleasePoolPush(); - OFArray *keys, *objects; - OFEnumerator *keyEnumerator, *objectEnumerator; - OFXMLElement *keyElement, *objectElement; - - keys = [element elementsForName: @"key" - namespace: OFSerializationNS]; - objects = [element elementsForName: @"object" - namespace: OFSerializationNS]; - - if (keys.count != objects.count) - @throw [OFInvalidFormatException exception]; - - _mapTable = [[OFMapTable alloc] - initWithKeyFunctions: keyFunctions - objectFunctions: objectFunctions - capacity: keys.count]; - - keyEnumerator = [keys objectEnumerator]; - objectEnumerator = [objects objectEnumerator]; - while ((keyElement = [keyEnumerator nextObject]) != nil && - (objectElement = [objectEnumerator nextObject]) != nil) { - void *pool2 = objc_autoreleasePoolPush(); - OFXMLElement *key, *object; - - key = [keyElement elementsForNamespace: - OFSerializationNS].firstObject; - object = [objectElement elementsForNamespace: - OFSerializationNS].firstObject; - - if (key == nil || object == nil) - @throw [OFInvalidFormatException exception]; - - [_mapTable setObject: object.objectByDeserializing - forKey: key.objectByDeserializing]; - - objc_autoreleasePoolPop(pool2); - } - - objc_autoreleasePoolPop(pool); - } @catch (id e) { - [self release]; - @throw e; - } - - return self; -} - -- (void)dealloc -{ - [_mapTable release]; - - [super dealloc]; -} - -- (id)objectForKey: (id)key -{ - return [_mapTable objectForKey: key]; -} - -- (size_t)count -{ - return _mapTable.count; -} - -- (bool)isEqual: (id)object -{ - OFMapTableDictionary *dictionary; - - if (object == self) - return true; - - if (![object isKindOfClass: [OFMapTableDictionary class]] && - ![object isKindOfClass: [OFMutableMapTableDictionary class]]) - return [super isEqual: object]; - - dictionary = (OFMapTableDictionary *)object; - - return [dictionary->_mapTable isEqual: _mapTable]; -} - -- (bool)containsObject: (id)object -{ - return [_mapTable containsObject: object]; -} - -- (bool)containsObjectIdenticalTo: (id)object -{ - return [_mapTable containsObjectIdenticalTo: object]; -} - -- (OFArray *)allKeys -{ - OFArray *ret; - id *keys; - size_t count; - - count = _mapTable.count; - keys = OFAllocMemory(count, sizeof(*keys)); - - @try { - void *pool = objc_autoreleasePoolPush(); - OFMapTableEnumerator *enumerator; - void **keyPtr; - size_t i; - - i = 0; - enumerator = [_mapTable keyEnumerator]; - while ((keyPtr = [enumerator nextObject]) != NULL) { - assert(i < count); - - keys[i++] = (id)*keyPtr; - } - - objc_autoreleasePoolPop(pool); - - ret = [OFArray arrayWithObjects: keys count: count]; - } @finally { - OFFreeMemory(keys); - } - - return ret; -} - -- (OFArray *)allObjects -{ - OFArray *ret; - id *objects; - size_t count; - - count = _mapTable.count; - objects = OFAllocMemory(count, sizeof(*objects)); - - @try { - void *pool = objc_autoreleasePoolPush(); - OFMapTableEnumerator *enumerator; - void **objectPtr; - size_t i; - - i = 0; - enumerator = [_mapTable objectEnumerator]; - while ((objectPtr = [enumerator nextObject]) != NULL) { - assert(i < count); - - objects[i++] = (id)*objectPtr; - } - - objc_autoreleasePoolPop(pool); - - ret = [OFArray arrayWithObjects: objects count: count]; - } @finally { - OFFreeMemory(objects); - } - - return ret; -} - -- (OFEnumerator *)keyEnumerator -{ - return [[[OFMapTableEnumeratorWrapper alloc] - initWithEnumerator: [_mapTable keyEnumerator] - object: self] autorelease]; -} - -- (OFEnumerator *)objectEnumerator -{ - return [[[OFMapTableEnumeratorWrapper alloc] - initWithEnumerator: [_mapTable objectEnumerator] - object: self] autorelease]; -} - -- (int)countByEnumeratingWithState: (OFFastEnumerationState *)state - objects: (id *)objects - count: (int)count -{ - return [_mapTable countByEnumeratingWithState: state - objects: objects - count: count]; -} - -#ifdef OF_HAVE_BLOCKS -- (void)enumerateKeysAndObjectsUsingBlock: (OFDictionaryEnumerationBlock)block -{ - @try { - [_mapTable enumerateKeysAndObjectsUsingBlock: - ^ (void *key, void *object, bool *stop) { - block(key, object, stop); - }]; - } @catch (OFEnumerationMutationException *e) { - @throw [OFEnumerationMutationException - exceptionWithObject: self]; - } -} -#endif - -- (unsigned long)hash -{ - return _mapTable.hash; -} -@end DELETED src/OFMapTableSet.h Index: src/OFMapTableSet.h ================================================================== --- src/OFMapTableSet.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (c) 2008-2022 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#import "OFSet.h" - -OF_ASSUME_NONNULL_BEGIN - -@class OFMapTable; - -@interface OFMapTableSet: OFSet -{ - OFMapTable *_mapTable; -} - -- (instancetype)initWithCapacity: (size_t)capacity; -@end - -OF_ASSUME_NONNULL_END DELETED src/OFMapTableSet.m Index: src/OFMapTableSet.m ================================================================== --- src/OFMapTableSet.m +++ /dev/null @@ -1,302 +0,0 @@ -/* - * Copyright (c) 2008-2022 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#include "config.h" - -#import "OFMapTableSet.h" -#import "OFArray.h" -#import "OFCountedMapTableSet.h" -#import "OFMapTable.h" -#import "OFMapTable+Private.h" -#import "OFMutableMapTableSet.h" -#import "OFString.h" -#import "OFXMLElement.h" - -#import "OFInvalidArgumentException.h" -#import "OFEnumerationMutationException.h" - -static void * -retain(void *object) -{ - return [(id)object retain]; -} - -static void -release(void *object) -{ - [(id)object release]; -} - -static unsigned long -hash(void *object) -{ - return [(id)object hash]; -} - -static bool -equal(void *object1, void *object2) -{ - return [(id)object1 isEqual: (id)object2]; -} - -static const OFMapTableFunctions keyFunctions = { - .retain = retain, - .release = release, - .hash = hash, - .equal = equal -}; -static const OFMapTableFunctions objectFunctions = { NULL }; - -@implementation OFMapTableSet -- (instancetype)init -{ - return [self initWithCapacity: 0]; -} - -- (instancetype)initWithCapacity: (size_t)capacity -{ - self = [super init]; - - @try { - _mapTable = [[OFMapTable alloc] - initWithKeyFunctions: keyFunctions - objectFunctions: objectFunctions - capacity: capacity]; - } @catch (id e) { - [self release]; - @throw e; - } - - return self; -} - -- (instancetype)initWithSet: (OFSet *)set -{ - size_t count; - - if (set == nil) - return [self init]; - - @try { - count = set.count; - } @catch (id e) { - [self release]; - @throw e; - } - - self = [self initWithCapacity: count]; - - @try { - for (id object in set) - [_mapTable setObject: (void *)1 forKey: object]; - } @catch (id e) { - [self release]; - @throw e; - } - - return self; -} - -- (instancetype)initWithArray: (OFArray *)array -{ - size_t count; - - if (array == nil) - return self; - - @try { - count = array.count; - } @catch (id e) { - [self release]; - @throw e; - } - - self = [self initWithCapacity: count]; - - @try { - for (id object in array) - [_mapTable setObject: (void *)1 forKey: object]; - } @catch (id e) { - [self release]; - @throw e; - } - - return self; -} - -- (instancetype)initWithObjects: (id const *)objects count: (size_t)count -{ - self = [self initWithCapacity: count]; - - @try { - for (size_t i = 0; i < count; i++) - [_mapTable setObject: (void *)1 forKey: objects[i]]; - } @catch (id e) { - [self release]; - @throw e; - } - - return self; -} - -- (instancetype)initWithObject: (id)firstObject arguments: (va_list)arguments -{ - self = [super init]; - - @try { - id object; - va_list argumentsCopy; - size_t count; - - va_copy(argumentsCopy, arguments); - - for (count = 1; va_arg(argumentsCopy, id) != nil; count++); - - _mapTable = [[OFMapTable alloc] - initWithKeyFunctions: keyFunctions - objectFunctions: objectFunctions - capacity: count]; - - [_mapTable setObject: (void *)1 forKey: firstObject]; - - while ((object = va_arg(arguments, id)) != nil) - [_mapTable setObject: (void *)1 forKey: object]; - } @catch (id e) { - [self release]; - @throw e; - } - - return self; -} - -- (instancetype)initWithSerialization: (OFXMLElement *)element -{ - self = [self init]; - - @try { - void *pool = objc_autoreleasePoolPush(); - - if ((![element.name isEqual: @"OFSet"] && - ![element.name isEqual: @"OFMutableSet"]) || - ![element.namespace isEqual: OFSerializationNS]) - @throw [OFInvalidArgumentException exception]; - - for (OFXMLElement *child in - [element elementsForNamespace: OFSerializationNS]) { - void *pool2 = objc_autoreleasePoolPush(); - - [_mapTable setObject: (void *)1 - forKey: [child objectByDeserializing]]; - - objc_autoreleasePoolPop(pool2); - } - - objc_autoreleasePoolPop(pool); - } @catch (id e) { - [self release]; - @throw e; - } - - return self; -} - -- (void)dealloc -{ - [_mapTable release]; - - [super dealloc]; -} - -- (size_t)count -{ - return [_mapTable count]; -} - -- (bool)containsObject: (id)object -{ - if (object == nil) - return false; - - return ([_mapTable objectForKey: object] != nil); -} - -- (bool)isEqual: (id)object -{ - OFMapTableSet *set; - - if (object == self) - return true; - - if (![object isKindOfClass: [OFMapTableSet class]] && - ![object isKindOfClass: [OFMutableMapTableSet class]] && - ![object isKindOfClass: [OFCountedMapTableSet class]]) - return [super isEqual: object]; - - set = object; - - return [set->_mapTable isEqual: _mapTable]; -} - -- (id)anyObject -{ - void *pool = objc_autoreleasePoolPush(); - void **objectPtr; - id object; - - objectPtr = [[_mapTable keyEnumerator] nextObject]; - - if (objectPtr == NULL) { - objc_autoreleasePoolPop(pool); - return nil; - } - - object = [(id)*objectPtr retain]; - - objc_autoreleasePoolPop(pool); - - return [object autorelease]; -} - -- (OFEnumerator *)objectEnumerator -{ - return [[[OFMapTableEnumeratorWrapper alloc] - initWithEnumerator: [_mapTable keyEnumerator] - object: self] autorelease]; -} - -- (int)countByEnumeratingWithState: (OFFastEnumerationState *)state - objects: (id *)objects - count: (int)count -{ - return [_mapTable countByEnumeratingWithState: state - objects: objects - count: count]; -} - -#ifdef OF_HAVE_BLOCKS -- (void)enumerateObjectsUsingBlock: (OFSetEnumerationBlock)block -{ - @try { - [_mapTable enumerateKeysAndObjectsUsingBlock: - ^ (void *key, void *object, bool *stop) { - block(key, stop); - }]; - } @catch (OFEnumerationMutationException *e) { - @throw [OFEnumerationMutationException - exceptionWithObject: self]; - } -} -#endif -@end ADDED src/OFMatrix4x4.h Index: src/OFMatrix4x4.h ================================================================== --- /dev/null +++ src/OFMatrix4x4.h @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2008-2024 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#import "OFObject.h" + +OF_ASSUME_NONNULL_BEGIN + +/** + * @brief A 4x4 matrix of floats. + */ +OF_SUBCLASSING_RESTRICTED +@interface OFMatrix4x4: OFObject +{ + float (*_values)[4]; +} + +#ifdef OF_HAVE_CLASS_PROPERTIES +@property (readonly, class) OFMatrix4x4 *identityMatrix; +#endif + +/** + * @brief A 2D array of the 4x4 floats of the matrix in row-major format. + * + * These may be modified directly. + */ +@property (readonly, nonatomic) float (*values)[4]; + +/** + * @brief Returns the 4x4 identity matrix. + */ ++ (OFMatrix4x4 *)identityMatrix; + +/** + * @brief Creates a new 4x4 matrix with the specified values. + * + * @param values A 2D array of 4x4 floats in row-major format + * @return A new, autoreleased OFMatrix4x4 + */ ++ (instancetype)matrixWithValues: (const float [_Nonnull 4][4])values; + +- (instancetype)init OF_UNAVAILABLE; + +/** + * @brief Initializes an already allocated 4x4 matrix with the specified values. + * + * @param values A 2D array of 4x4 floats in row-major format + * @return An initialized OFMatrix4x4 + */ +- (instancetype)initWithValues: (const float [_Nonnull 4][4])values + OF_DESIGNATED_INITIALIZER; + +/** + * @brief Mulitplies the receiver with the specified matrix on the left side + * and the receiver on the right side. + * + * @param matrix The matrix to multiply the receiver with + */ +- (void)multiplyWithMatrix: (OFMatrix4x4 *)matrix; + +/** + * @brief Translates the matrix with the specified vector. + * + * @param vector The vector to translate the matrix with + */ +- (void)translateWithVector: (OFVector3D)vector; + +/** + * @brief Scales the matrix with the specified vector. + * + * @param vector The vector to scale the matrix with + */ +- (void)scaleWithVector: (OFVector3D)vector; + +/** + * @brief Transforms the specified vector according to the matrix. + * + * @param vector The vector to transform + * @return The transformed vector + */ +- (OFVector4D)transformedVector: (OFVector4D)vector; + +/** + * @brief Transforms the specified vectors in-place according to the matrix. + * + * @param vectors The vectors to transform + */ +- (void)transformVectors: (OFVector4D *)vectors count: (size_t)count; +@end + +OF_ASSUME_NONNULL_END ADDED src/OFMatrix4x4.m Index: src/OFMatrix4x4.m ================================================================== --- /dev/null +++ src/OFMatrix4x4.m @@ -0,0 +1,420 @@ +/* + * Copyright (c) 2008-2024 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#include "config.h" + +#import "OFMatrix4x4.h" +#import "OFString.h" +#import "OFSystemInfo.h" + +#import "OFOnce.h" + +static const float identityValues[4][4] = { + { 1, 0, 0, 0 }, + { 0, 1, 0, 0 }, + { 0, 0, 1, 0 }, + { 0, 0, 0, 1 } +}; + +@implementation OFMatrix4x4 +#if (defined(OF_AMD64) || defined(OF_X86)) && defined(__GNUC__) +# ifndef __clang__ +# pragma GCC push_options +# pragma GCC target("sse") +# endif +static void +transformVectors_SSE(OFMatrix4x4 *self, SEL _cmd, OFVector4D *vectors, + size_t count) +{ + OF_ALIGN(16) float tmp[4]; + + __asm__ __volatile__ ( + "test %[count], %[count]\n\t" + "jz 0f\n" + "\n\t" + "movaps (%[matrix]), %%xmm0\n\t" + "movaps 16(%[matrix]), %%xmm1\n\t" + "movaps 32(%[matrix]), %%xmm2\n\t" +# ifdef OF_AMD64 + "movaps 48(%[matrix]), %%xmm8\n" +# endif + "\n\t" + "0:\n\t" + "movaps (%[vectors]), %%xmm3\n" + "\n\t" + "movaps %%xmm0, %%xmm4\n\t" + "mulps %%xmm3, %%xmm4\n\t" + "movaps %%xmm4, (%[tmp])\n\t" + "addss 4(%[tmp]), %%xmm4\n\t" + "addss 8(%[tmp]), %%xmm4\n\t" + "addss 12(%[tmp]), %%xmm4\n" + "\n\t" + "movaps %%xmm1, %%xmm5\n\t" + "mulps %%xmm3, %%xmm5\n\t" + "movaps %%xmm5, (%[tmp])\n\t" + "addss 4(%[tmp]), %%xmm5\n\t" + "addss 8(%[tmp]), %%xmm5\n\t" + "addss 12(%[tmp]), %%xmm5\n" + "\n\t" + "movaps %%xmm2, %%xmm6\n\t" + "mulps %%xmm3, %%xmm6\n\t" + "movaps %%xmm6, (%[tmp])\n\t" + "addss 4(%[tmp]), %%xmm6\n\t" + "addss 8(%[tmp]), %%xmm6\n\t" + "addss 12(%[tmp]), %%xmm6\n" + "\n\t" +# ifdef OF_AMD64 + "movaps %%xmm8, %%xmm7\n\t" +# else + "movaps 48(%[matrix]), %%xmm7\n\t" +# endif + "mulps %%xmm3, %%xmm7\n\t" + "movaps %%xmm7, (%[tmp])\n\t" + "addss 4(%[tmp]), %%xmm7\n\t" + "addss 8(%[tmp]), %%xmm7\n\t" + "addss 12(%[tmp]), %%xmm7\n" + "\n\t" + "movss %%xmm4, (%[vectors])\n\t" + "movss %%xmm5, 4(%[vectors])\n\t" + "movss %%xmm6, 8(%[vectors])\n\t" + "movss %%xmm7, 12(%[vectors])\n" + "\n\t" + "add $16, %[vectors]\n\t" + "dec %[count]\n\t" + "jnz 0b\n" + : [count] "+r" (count), + [vectors] "+r" (vectors) + : [matrix] "r" (self->_values), + [tmp] "r" (&tmp) + : "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", +# ifdef OF_AMD64 + "xmm8", +# endif + "memory" + ); +} +# ifndef __clang__ +# pragma GCC pop_options +# endif + +# ifndef __clang__ +# pragma GCC push_options +# pragma GCC target("3dnow") +# endif +static void +multiplyWithMatrix_3DNow(OFMatrix4x4 *self, SEL _cmd, OFMatrix4x4 *matrix) +{ + float (*left)[4] = matrix->_values, (*right)[4] = self->_values; + float result[4][4], (*resultPtr)[4] = result; + + __asm__ __volatile__ ( + "movl $4, %%ecx\n\t" + "\n\t" + "0:\n\t" + "movd (%[right]), %%mm0\n\t" + "punpckldq 16(%[right]), %%mm0\n\t" + "pfmul (%[left]), %%mm0\n\t" + "movd 32(%[right]), %%mm1\n\t" + "punpckldq 48(%[right]), %%mm1\n\t" + "pfmul 8(%[left]), %%mm1\n\t" + "pfacc %%mm1, %%mm0\n\t" + "pfacc %%mm0, %%mm0\n\t" + "movd %%mm0, (%[result])\n\t" + "movd 4(%[right]), %%mm0\n\t" + "punpckldq 20(%[right]), %%mm0\n\t" + "pfmul (%[left]), %%mm0\n\t" + "movd 36(%[right]), %%mm1\n\t" + "punpckldq 52(%[right]), %%mm1\n\t" + "pfmul 8(%[left]), %%mm1\n\t" + "pfacc %%mm1, %%mm0\n\t" + "pfacc %%mm0, %%mm0\n\t" + "movd %%mm0, 4(%[result])\n\t" + "movd 8(%[right]), %%mm0\n\t" + "punpckldq 24(%[right]), %%mm0\n\t" + "pfmul (%[left]), %%mm0\n\t" + "movd 40(%[right]), %%mm1\n\t" + "punpckldq 56(%[right]), %%mm1\n\t" + "pfmul 8(%[left]), %%mm1\n\t" + "pfacc %%mm1, %%mm0\n\t" + "pfacc %%mm0, %%mm0\n\t" + "movd %%mm0, 8(%[result])\n\t" + "movd 12(%[right]), %%mm0\n\t" + "punpckldq 28(%[right]), %%mm0\n\t" + "pfmul (%[left]), %%mm0\n\t" + "movd 44(%[right]), %%mm1\n\t" + "punpckldq 60(%[right]), %%mm1\n\t" + "pfmul 8(%[left]), %%mm1\n\t" + "pfacc %%mm1, %%mm0\n\t" + "pfacc %%mm0, %%mm0\n\t" + "movd %%mm0, 12(%[result])\n" + "\n\t" + "add $16, %[result]\n\t" + "add $16, %[left]\n\t" + "decl %%ecx\n\t" + "jnz 0b\n" + "\n\t" + "femms" + : [result] "+r" (resultPtr), + [left] "+r" (left), + [right] "+r" (right) + : + : "ecx", "mm0", "mm1", "memory" + ); + + memcpy(self->_values, result, 16 * sizeof(float)); +} + +static void +transformVectors_3DNow(OFMatrix4x4 *self, SEL _cmd, OFVector4D *vectors, + size_t count) +{ + __asm__ __volatile__ ( + "test %[count], %[count]\n\t" + "jz 0f\n" + "\n\t" + "0:\n\t" + "movq (%[vectors]), %%mm0\n\t" + "movq 8(%[vectors]), %%mm1\n" + "\n\t" + "movq %%mm0, %%mm2\n\t" + "movq %%mm1, %%mm3\n\t" + "pfmul (%[matrix]), %%mm2\n\t" + "pfmul 8(%[matrix]), %%mm3\n\t" + "pfacc %%mm3, %%mm2\n\t" + "pfacc %%mm2, %%mm2\n\t" + "\n\t" + "movq %%mm0, %%mm3\n\t" + "movq %%mm1, %%mm4\n\t" + "pfmul 16(%[matrix]), %%mm3\n\t" + "pfmul 24(%[matrix]), %%mm4\n\t" + "pfacc %%mm4, %%mm3\n\t" + "pfacc %%mm3, %%mm3\n\t" + "\n\t" + "punpckldq %%mm3, %%mm2\n\t" + "movq %%mm2, (%[vectors])\n" + "\n\t" + "movq %%mm0, %%mm2\n\t" + "movq %%mm1, %%mm3\n\t" + "pfmul 32(%[matrix]), %%mm2\n\t" + "pfmul 40(%[matrix]), %%mm3\n\t" + "pfacc %%mm3, %%mm2\n\t" + "pfacc %%mm2, %%mm2\n\t" + "\n\t" + "pfmul 48(%[matrix]), %%mm0\n\t" + "pfmul 56(%[matrix]), %%mm1\n\t" + "pfacc %%mm1, %%mm0\n\t" + "pfacc %%mm0, %%mm0\n\t" + "\n\t" + "punpckldq %%mm0, %%mm2\n\t" + "movq %%mm2, 8(%[vectors])\n" + "\n\t" + "add $16, %[vectors]\n\t" + "dec %[count]\n\t" + "jnz 0b\n" + "\n\t" + "0:\n\t" + "femms" + : [count] "+r" (count), + [vectors] "+r" (vectors) + : [matrix] "r" (self->_values) + : "mm0", "mm1", "mm2", "mm3", "mm4", "memory" + ); +} +# ifndef __clang__ +# pragma GCC pop_options +# endif + ++ (void)initialize +{ + const char *typeEncoding; + + if (self != [OFMatrix4x4 class]) + return; + +# define REPLACE(selector, func) \ + typeEncoding = method_getTypeEncoding( \ + class_getInstanceMethod(self, selector)); \ + class_replaceMethod(self, selector, (IMP)func, typeEncoding); + + if ([OFSystemInfo supportsSSE]) { + REPLACE(@selector(transformVectors:count:), + transformVectors_SSE) + } else if ([OFSystemInfo supports3DNow]) { + REPLACE(@selector(multiplyWithMatrix:), + multiplyWithMatrix_3DNow) + REPLACE(@selector(transformVectors:count:), + transformVectors_3DNow) + } + +# undef REPLACE +} +#endif + ++ (instancetype)alloc +{ + OFMatrix4x4 *instance; + float (*values)[4]; + + instance = OFAllocObject(self, 16 * sizeof(float), 16, + (void **)&values); + instance->_values = values; + + return instance; +} + ++ (OFMatrix4x4 *)identityMatrix +{ + return [[[OFMatrix4x4 alloc] + initWithValues: identityValues] autorelease]; +} + ++ (instancetype)matrixWithValues: (const float [4][4])values +{ + return [[[self alloc] initWithValues: values] autorelease]; +} + +- (instancetype)init +{ + OF_INVALID_INIT_METHOD +} + +- (instancetype)initWithValues: (const float [4][4])values +{ + self = [super init]; + + memcpy(_values, values, 16 * sizeof(float)); + + return self; +} + +- (float (*)[4])values +{ + return _values; +} + +- (instancetype)copy +{ + return [[OFMatrix4x4 alloc] + initWithValues: (const float (*)[4])_values]; +} + +- (bool)isEqual: (OFMatrix4x4 *)matrix +{ + if (![matrix isKindOfClass: [OFMatrix4x4 class]]) + return false; + + return (memcmp(_values, matrix->_values, 16 * sizeof(float)) == 0); +} + +- (unsigned long)hash +{ + unsigned long hash; + + OFHashInit(&hash); + + for (uint_fast8_t i = 0; i < 4; i++) + for (uint_fast8_t j = 0; j < 4; j++) + OFHashAddHash(&hash, OFFloatToRawUInt32(_values[i][j])); + + OFHashFinalize(&hash); + + return hash; +} + +- (void)multiplyWithMatrix: (OFMatrix4x4 *)matrix +{ + float result[4][4]; + + for (uint_fast8_t i = 0; i < 4; i++) + for (uint_fast8_t j = 0; j < 4; j++) + result[i][j] = + matrix->_values[i][0] * _values[0][j] + + matrix->_values[i][1] * _values[1][j] + + matrix->_values[i][2] * _values[2][j] + + matrix->_values[i][3] * _values[3][j]; + + memcpy(_values, result, 16 * sizeof(float)); +} + +- (void)translateWithVector: (OFVector3D)vector +{ + OFMatrix4x4 *translation = [[OFMatrix4x4 alloc] initWithValues: + (const float [4][4]){ + { 1, 0, 0, vector.x }, + { 0, 1, 0, vector.y }, + { 0, 0, 1, vector.z }, + { 0, 0, 0, 1 } + }]; + [self multiplyWithMatrix: translation]; + [translation release]; +} + +- (void)scaleWithVector: (OFVector3D)vector +{ + OFMatrix4x4 *scale = [[OFMatrix4x4 alloc] initWithValues: + (const float [4][4]){ + { vector.x, 0, 0, 0 }, + { 0, vector.y, 0, 0 }, + { 0, 0, vector.z, 0 }, + { 0, 0, 0, 1 } + }]; + [self multiplyWithMatrix: scale]; + [scale release]; +} + +- (OFVector4D)transformedVector: (OFVector4D)vector +{ + OFVector4D copy = vector; + + [self transformVectors: © count: 1]; + + return copy; +} + +- (void)transformVectors: (OFVector4D *)vectors count: (size_t)count +{ + for (size_t i = 0; i < count; i++) { + OFVector4D vector = vectors[i]; + + vectors[i].x = _values[0][0] * vector.x + + _values[0][1] * vector.y + _values[0][2] * vector.z + + _values[0][3] * vector.w; + vectors[i].y = _values[1][0] * vector.x + + _values[1][1] * vector.y + _values[1][2] * vector.z + + _values[1][3] * vector.w; + vectors[i].z = _values[2][0] * vector.x + + _values[2][1] * vector.y + _values[2][2] * vector.z + + _values[2][3] * vector.w; + vectors[i].w = _values[3][0] * vector.x + + _values[3][1] * vector.y + _values[3][2] * vector.z + + _values[3][3] * vector.w; + } +} + +- (OFString *)description +{ + return [OFString stringWithFormat: + @"", + _values[0][0], _values[0][1], _values[0][2], _values[0][3], + _values[1][0], _values[1][1], _values[1][2], _values[1][3], + _values[2][0], _values[2][1], _values[2][2], _values[2][3], + _values[3][0], _values[3][1], _values[3][2], _values[3][3]]; +} +@end Index: src/OFMemoryStream.h ================================================================== --- src/OFMemoryStream.h +++ src/OFMemoryStream.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFMemoryStream.m ================================================================== --- src/OFMemoryStream.m +++ src/OFMemoryStream.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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.h ================================================================== --- src/OFMessagePackExtension.h +++ src/OFMessagePackExtension.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -55,19 +55,22 @@ * @return A new, autoreleased OFMethodSignature * @throw OFInvalidFormatException The type encoding is invalid */ + (instancetype)signatureWithObjCTypes: (const char *)types; +- (instancetype)init OF_UNAVAILABLE; + /** * @brief Initializes an already allocated OFMethodSignature with the specified * ObjC types. * * @param types The ObjC types of the method * @return An Initialized OFMethodSignature * @throw OFInvalidFormatException The type encoding is invalid */ -- (instancetype)initWithObjCTypes: (const char *)types; +- (instancetype)initWithObjCTypes: (const char *)types + OF_DESIGNATED_INITIALIZER; /** * @brief Returns the ObjC type for the argument at the specified index. * * @param index The index of the argument for which to return the ObjC type Index: src/OFMethodSignature.m ================================================================== --- src/OFMethodSignature.m +++ src/OFMethodSignature.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,15 +13,15 @@ * file. */ #include "config.h" -#include #include #import "OFMethodSignature.h" #import "OFData.h" +#import "OFString.h" #import "OFInvalidArgumentException.h" #import "OFInvalidFormatException.h" #import "OFOutOfRangeException.h" @@ -34,11 +34,11 @@ static size_t alignmentOfArray(const char **type, size_t *length) { size_t alignment; - assert(*length > 0); + OFAssert(*length > 0); (*type)++; (*length)--; while (*length > 0 && OFASCIIIsDigit(**type)) { @@ -63,11 +63,11 @@ size_t alignment = 0; #if defined(OF_POWERPC) && defined(OF_MACOS) bool first = true; #endif - assert(*length > 0); + OFAssert(*length > 0); (*type)++; (*length)--; /* Skip name */ @@ -109,11 +109,11 @@ static size_t alignmentOfUnion(const char **type, size_t *length) { size_t alignment = 0; - assert(*length > 0); + OFAssert(*length > 0); (*type)++; (*length)--; /* Skip name */ @@ -144,11 +144,12 @@ return alignment; } static size_t -#if defined(__clang__) && __clang_major__ == 3 && __clang_minor__ <= 7 +#if defined(__clang__) && __has_attribute(__optnone__) && \ + __clang_major__ == 3 && __clang_minor__ <= 7 /* Work around an ICE in Clang 3.7.0 on Windows/x86 */ __attribute__((__optnone__)) #endif alignmentOfEncoding(const char **type, size_t *length, bool inStruct) { @@ -290,11 +291,11 @@ sizeOfArray(const char **type, size_t *length) { size_t count = 0; size_t size; - assert(*length > 0); + OFAssert(*length > 0); (*type)++; (*length)--; while (*length > 0 && OFASCIIIsDigit(**type)) { @@ -330,11 +331,11 @@ size_t alignment = alignmentOfStruct(&typeCopy, &lengthCopy); #if defined(OF_POWERPC) && defined(OF_MACOS) bool first = true; #endif - assert(*length > 0); + OFAssert(*length > 0); (*type)++; (*length)--; /* Skip name */ @@ -403,11 +404,11 @@ static size_t sizeOfUnion(const char **type, size_t *length) { size_t size = 0; - assert(*length > 0); + OFAssert(*length > 0); (*type)++; (*length)--; /* Skip name */ @@ -438,10 +439,15 @@ return size; } static size_t +#if defined(__clang__) && __has_attribute(__optnone__) && \ + __clang_major__ == 3 && __clang_minor__ <= 7 +/* Work around an ICE in Clang 3.7.0 on Windows/x86 */ +__attribute__((__optnone__)) +#endif sizeOfEncoding(const char **type, size_t *length) { size_t size; if (*length == 0) @@ -583,10 +589,15 @@ @implementation OFMethodSignature + (instancetype)signatureWithObjCTypes: (const char*)types { return [[[self alloc] initWithObjCTypes: types] autorelease]; } + +- (instancetype)init +{ + OF_INVALID_INIT_METHOD +} - (instancetype)initWithObjCTypes: (const char *)types { self = [super init]; DELETED src/OFMutableAdjacentArray.h Index: src/OFMutableAdjacentArray.h ================================================================== --- src/OFMutableAdjacentArray.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (c) 2008-2022 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#import "OFArray.h" - -OF_ASSUME_NONNULL_BEGIN - -@class OFMutableData; - -@interface OFMutableAdjacentArray: OFMutableArray -{ - OFMutableData *_array; - unsigned long _mutations; -} -@end - -OF_ASSUME_NONNULL_END DELETED src/OFMutableAdjacentArray.m Index: src/OFMutableAdjacentArray.m ================================================================== --- src/OFMutableAdjacentArray.m +++ /dev/null @@ -1,383 +0,0 @@ -/* - * Copyright (c) 2008-2022 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 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 "OFMutableAdjacentArray.h" -#import "OFAdjacentArray.h" -#import "OFArray+Private.h" -#import "OFData.h" - -#import "OFEnumerationMutationException.h" -#import "OFInvalidArgumentException.h" -#import "OFOutOfRangeException.h" - -@implementation OFMutableAdjacentArray -+ (void)initialize -{ - if (self == [OFMutableAdjacentArray class]) - [self inheritMethodsFromClass: [OFAdjacentArray class]]; -} - -- (instancetype)initWithCapacity: (size_t)capacity -{ - self = [super init]; - - @try { - _array = [[OFMutableData alloc] initWithItemSize: sizeof(id) - capacity: capacity]; - } @catch (id e) { - [self release]; - @throw e; - } - - return self; -} - -- (void)addObject: (id)object -{ - if (object == nil) - @throw [OFInvalidArgumentException exception]; - - [_array addItem: &object]; - [object retain]; - - _mutations++; -} - -- (void)insertObject: (id)object atIndex: (size_t)idx -{ - if (object == nil) - @throw [OFInvalidArgumentException exception]; - - @try { - [_array insertItem: &object atIndex: idx]; - } @catch (OFOutOfRangeException *e) { - @throw [OFOutOfRangeException exception]; - } - [object retain]; - - _mutations++; -} - -- (void)insertObjectsFromArray: (OFArray *)array atIndex: (size_t)idx -{ - id const *objects = array.objects; - size_t count = array.count; - - @try { - [_array insertItems: objects atIndex: idx count: count]; - } @catch (OFOutOfRangeException *e) { - @throw [OFOutOfRangeException exception]; - } - - for (size_t i = 0; i < count; i++) - [objects[i] retain]; - - _mutations++; -} - -- (void)replaceObject: (id)oldObject withObject: (id)newObject -{ - id *objects; - size_t count; - - if (oldObject == nil || newObject == nil) - @throw [OFInvalidArgumentException exception]; - - objects = _array.mutableItems; - count = _array.count; - - for (size_t i = 0; i < count; i++) { - if ([objects[i] isEqual: oldObject]) { - [newObject retain]; - [objects[i] release]; - objects[i] = newObject; - } - } -} - -- (void)replaceObjectAtIndex: (size_t)idx withObject: (id)object -{ - id *objects; - id oldObject; - - if (object == nil) - @throw [OFInvalidArgumentException exception]; - - objects = _array.mutableItems; - - if (idx >= _array.count) - @throw [OFOutOfRangeException exception]; - - oldObject = objects[idx]; - objects[idx] = [object retain]; - [oldObject release]; -} - -- (void)replaceObjectIdenticalTo: (id)oldObject withObject: (id)newObject -{ - id *objects; - size_t count; - - if (oldObject == nil || newObject == nil) - @throw [OFInvalidArgumentException exception]; - - objects = _array.mutableItems; - count = _array.count; - - for (size_t i = 0; i < count; i++) { - if (objects[i] == oldObject) { - [newObject retain]; - [objects[i] release]; - objects[i] = newObject; - - return; - } - } -} - -- (void)removeObject: (id)object -{ - id const *objects; - size_t count; - - if (object == nil) - @throw [OFInvalidArgumentException exception]; - - objects = _array.items; - count = _array.count; - - for (size_t i = 0; i < count; i++) { - if ([objects[i] isEqual: object]) { - id tmp = objects[i]; - - [_array removeItemAtIndex: i]; - _mutations++; - - [tmp release]; - - objects = _array.items; - i--; - count--; - continue; - } - } -} - -- (void)removeObjectIdenticalTo: (id)object -{ - id const *objects; - size_t count; - - if (object == nil) - @throw [OFInvalidArgumentException exception]; - - objects = _array.items; - count = _array.count; - - for (size_t i = 0; i < count; i++) { - if (objects[i] == object) { - [_array removeItemAtIndex: i]; - _mutations++; - - [object release]; - - objects = _array.items; - i--; - count--; - continue; - } - } -} - -- (void)removeObjectAtIndex: (size_t)idx -{ -#ifndef __clang_analyzer__ - id object = [self objectAtIndex: idx]; - [_array removeItemAtIndex: idx]; - [object release]; - - _mutations++; -#endif -} - -- (void)removeAllObjects -{ - id const *objects = _array.items; - size_t count = _array.count; - - for (size_t i = 0; i < count; i++) - [objects[i] release]; - - [_array removeAllItems]; -} - -- (void)removeObjectsInRange: (OFRange)range -{ - id const *objects = _array.items; - size_t count = _array.count; - id *copy; - - if (range.length > SIZE_MAX - range.location || - range.location >= count || range.length > count - range.location) - @throw [OFOutOfRangeException exception]; - - copy = OFAllocMemory(range.length, sizeof(*copy)); - memcpy(copy, objects + range.location, range.length * sizeof(id)); - - @try { - [_array removeItemsInRange: range]; - _mutations++; - - for (size_t i = 0; i < range.length; i++) - [copy[i] release]; - } @finally { - OFFreeMemory(copy); - } -} - -- (void)removeLastObject -{ -#ifndef __clang_analyzer__ - size_t count = _array.count; - id object; - - if (count == 0) - return; - - object = [self objectAtIndex: count - 1]; - [_array removeLastItem]; - [object release]; - - _mutations++; -#endif -} - -- (void)exchangeObjectAtIndex: (size_t)idx1 withObjectAtIndex: (size_t)idx2 -{ - id *objects = _array.mutableItems; - size_t count = _array.count; - id tmp; - - if (idx1 >= count || idx2 >= count) - @throw [OFOutOfRangeException exception]; - - tmp = objects[idx1]; - objects[idx1] = objects[idx2]; - objects[idx2] = tmp; -} - -- (void)reverse -{ - id *objects = _array.mutableItems; - size_t i, j, count = _array.count; - - if (count == 0 || count == 1) - return; - - for (i = 0, j = count - 1; i < j; i++, j--) { - id tmp = objects[i]; - objects[i] = objects[j]; - objects[j] = tmp; - } -} - -- (int)countByEnumeratingWithState: (OFFastEnumerationState *)state - objects: (id *)objects - count: (int)count_ -{ - size_t count = _array.count; - - if (count > INT_MAX) { - /* - * Use the implementation from OFArray (OFMutableArray does not - * have one), which is slower, but can enumerate in chunks, and - * set the mutations pointer. - */ - int ret = [super countByEnumeratingWithState: state - objects: objects - count: count_]; - state->mutationsPtr = &_mutations; - return ret; - } - - if (state->state >= count) - return 0; - - state->state = (unsigned long)count; - state->itemsPtr = (id *)_array.items; - state->mutationsPtr = &_mutations; - - return (int)count; -} - -- (OFEnumerator *)objectEnumerator -{ - return [[[OFArrayEnumerator alloc] - initWithArray: self - mutationsPtr: &_mutations] autorelease]; -} - -#ifdef OF_HAVE_BLOCKS -- (void)enumerateObjectsUsingBlock: (OFArrayEnumerationBlock)block -{ - id const *objects = _array.items; - size_t count = _array.count; - bool stop = false; - unsigned long mutations = _mutations; - - for (size_t i = 0; i < count && !stop; i++) { - if (_mutations != mutations) - @throw [OFEnumerationMutationException - exceptionWithObject: self]; - - block(objects[i], i, &stop); - } -} - -- (void)replaceObjectsUsingBlock: (OFArrayReplaceBlock)block -{ - id *objects = _array.mutableItems; - size_t count = _array.count; - unsigned long mutations = _mutations; - - for (size_t i = 0; i < count; i++) { - id new; - - if (_mutations != mutations) - @throw [OFEnumerationMutationException - exceptionWithObject: self]; - - new = block(objects[i], i); - - if (new == nil) - @throw [OFInvalidArgumentException exception]; - - if (new != objects[i]) { - [objects[i] release]; - objects[i] = [new retain]; - } - } -} -#endif - -- (void)makeImmutable -{ - object_setClass(self, [OFAdjacentArray class]); -} -@end Index: src/OFMutableArchiveEntry.h ================================================================== --- src/OFMutableArchiveEntry.h +++ src/OFMutableArchiveEntry.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFMutableArray.h ================================================================== --- src/OFMutableArray.h +++ src/OFMutableArray.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,18 +51,25 @@ * @param capacity The initial capacity for the OFMutableArray * @return A new autoreleased OFMutableArray */ + (instancetype)arrayWithCapacity: (size_t)capacity; +/** + * @brief Initializes an OFMutableArray with no objects. + * + * @return An initialized OFMutableArray + */ +- (instancetype)init OF_DESIGNATED_INITIALIZER; + /** * @brief Initializes an already allocated OFMutableArray with enough memory to * hold the specified number of objects. * * @param capacity The initial capacity for the OFMutableArray * @return An initialized OFMutableArray */ -- (instancetype)initWithCapacity: (size_t)capacity; +- (instancetype)initWithCapacity: (size_t)capacity OF_DESIGNATED_INITIALIZER; /** * @brief Adds an object to the end of the array. * * @param object An object to add @@ -200,10 +207,21 @@ * should be the same as that of -[compare:]. * @param options The options to use when sorting the array */ - (void)sortUsingSelector: (SEL)selector options: (OFArraySortOptions)options; +/** + * @brief Sorts the array using the specified function and options. + * + * @param compare The function to use to sort the array + * @param context Context passed to the function to compare + * @param options The options to use when sorting the array + */ +- (void)sortUsingFunction: (OFCompareFunction)compare + context: (nullable void *)context + options: (OFArraySortOptions)options; + #ifdef OF_HAVE_BLOCKS /** * @brief Sorts the array using the specified comparator and options. * * @param comparator The comparator to use to sort the array Index: src/OFMutableArray.m ================================================================== --- src/OFMutableArray.m +++ src/OFMutableArray.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,39 +16,27 @@ #include "config.h" #include #include -#include - #import "OFMutableArray.h" -#import "OFMutableAdjacentArray.h" +#import "OFConcreteMutableArray.h" #import "OFEnumerationMutationException.h" #import "OFInvalidArgumentException.h" #import "OFOutOfRangeException.h" static struct { Class isa; } placeholder; -@interface OFMutableArrayPlaceholder: OFMutableArray +@interface OFPlaceholderMutableArray: OFMutableArray @end -static OFComparisonResult -compare(id left, id right, SEL selector) -{ - OFComparisonResult (*comparator)(id, SEL, id) = - (OFComparisonResult (*)(id, SEL, id)) - [left methodForSelector: selector]; - - return comparator(left, selector, right); -} - static void -quicksort(OFMutableArray *array, size_t left, size_t right, SEL selector, - OFArraySortOptions options) +quicksort(OFMutableArray *array, size_t left, size_t right, + OFCompareFunction compare, void *context, OFArraySortOptions options) { OFComparisonResult ascending, descending; if (options & OFArraySortDescending) { ascending = OFOrderedDescending; @@ -63,158 +51,99 @@ size_t j = right - 1; id pivot = [array objectAtIndex: right]; do { while (compare([array objectAtIndex: i], pivot, - selector) != descending && i < right) + context) != descending && i < right) i++; while (compare([array objectAtIndex: j], pivot, - selector) != ascending && j > left) + context) != ascending && j > left) j--; if (i < j) [array exchangeObjectAtIndex: i withObjectAtIndex: j]; } while (i < j); - if (compare([array objectAtIndex: i], pivot, selector) == - descending) - [array exchangeObjectAtIndex: i - withObjectAtIndex: right]; - - if (i > 0) - quicksort(array, left, i - 1, selector, options); - - left = i + 1; - } -} - -#ifdef OF_HAVE_BLOCKS -static void -quicksortWithBlock(OFMutableArray *array, size_t left, size_t right, - OFComparator comparator, OFArraySortOptions options) -{ - OFComparisonResult ascending, descending; - - if (options & OFArraySortDescending) { - ascending = OFOrderedDescending; - descending = OFOrderedAscending; - } else { - ascending = OFOrderedAscending; - descending = OFOrderedDescending; - } - - while (left < right) { - size_t i = left; - size_t j = right - 1; - id pivot = [array objectAtIndex: right]; - - do { - while (comparator([array objectAtIndex: i], pivot) != - descending && i < right) - i++; - - while (comparator([array objectAtIndex: j], pivot) != - ascending && j > left) - j--; - - if (i < j) - [array exchangeObjectAtIndex: i - withObjectAtIndex: j]; - } while (i < j); - - if (comparator([array objectAtIndex: i], pivot) == descending) - [array exchangeObjectAtIndex: i - withObjectAtIndex: right]; - - if (i > 0) - quicksortWithBlock(array, left, i - 1, comparator, - options); - - left = i + 1; - } -} -#endif - -@implementation OFMutableArrayPlaceholder -- (instancetype)init -{ - return (id)[[OFMutableAdjacentArray alloc] init]; -} - -- (instancetype)initWithCapacity: (size_t)capacity -{ - return (id)[[OFMutableAdjacentArray alloc] initWithCapacity: capacity]; -} - -- (instancetype)initWithObject: (id)object -{ - return (id)[[OFMutableAdjacentArray alloc] initWithObject: object]; + if (compare([array objectAtIndex: i], pivot, context) == + descending) + [array exchangeObjectAtIndex: i + withObjectAtIndex: right]; + + if (i > 0) + quicksort(array, left, i - 1, compare, context, + options); + + left = i + 1; + } +} + +@implementation OFPlaceholderMutableArray +#ifdef __clang__ +/* We intentionally don't call into super, so silence the warning. */ +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wunknown-pragmas" +# pragma clang diagnostic ignored "-Wobjc-designated-initializers" +#endif +- (instancetype)init +{ + return (id)[[OFConcreteMutableArray alloc] init]; +} + +- (instancetype)initWithCapacity: (size_t)capacity +{ + return (id)[[OFConcreteMutableArray alloc] initWithCapacity: capacity]; +} + +- (instancetype)initWithObject: (id)object +{ + return (id)[[OFConcreteMutableArray alloc] initWithObject: object]; } - (instancetype)initWithObjects: (id)firstObject, ... { id ret; va_list arguments; va_start(arguments, firstObject); - ret = [[OFMutableAdjacentArray alloc] initWithObject: firstObject + ret = [[OFConcreteMutableArray alloc] initWithObject: firstObject arguments: arguments]; va_end(arguments); return ret; } - (instancetype)initWithObject: (id)firstObject arguments: (va_list)arguments { - return (id)[[OFMutableAdjacentArray alloc] initWithObject: firstObject + return (id)[[OFConcreteMutableArray alloc] initWithObject: firstObject arguments: arguments]; } - (instancetype)initWithArray: (OFArray *)array { - return (id)[[OFMutableAdjacentArray alloc] initWithArray: array]; + return (id)[[OFConcreteMutableArray alloc] initWithArray: array]; } - (instancetype)initWithObjects: (id const *)objects count: (size_t)count { - return (id)[[OFMutableAdjacentArray alloc] initWithObjects: objects + return (id)[[OFConcreteMutableArray alloc] initWithObjects: objects count: count]; } - -- (instancetype)initWithSerialization: (OFXMLElement *)element -{ - return (id)[[OFMutableAdjacentArray alloc] - initWithSerialization: element]; -} - -- (instancetype)retain -{ - return self; -} - -- (instancetype)autorelease -{ - return self; -} - -- (void)release -{ -} - -- (void)dealloc -{ - OF_DEALLOC_UNSUPPORTED -} +#ifdef __clang__ +# pragma clang diagnostic pop +#endif + +OF_SINGLETON_METHODS @end @implementation OFMutableArray + (void)initialize { if (self == [OFMutableArray class]) - placeholder.isa = [OFMutableArrayPlaceholder class]; + object_setClass((id)&placeholder, + [OFPlaceholderMutableArray class]); } + (instancetype)alloc { if (self == [OFMutableArray class]) @@ -228,27 +157,32 @@ return [[[self alloc] initWithCapacity: capacity] autorelease]; } - (instancetype)init { - if ([self isMemberOfClass: [OFMutableArray class]]) { - @try { - [self doesNotRecognizeSelector: _cmd]; - abort(); - } @catch (id e) { - [self release]; - @throw e; - } - } - return [super init]; } + +#ifdef __clang__ +/* We intentionally don't call into super, so silence the warning. */ +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wunknown-pragmas" +# pragma clang diagnostic ignored "-Wobjc-designated-initializers" +#endif +- (instancetype)initWithObjects: (id const *)objects + count: (size_t)count +{ + OF_INVALID_INIT_METHOD +} - (instancetype)initWithCapacity: (size_t)capacity { OF_INVALID_INIT_METHOD } +#ifdef __clang__ +# pragma clang diagnostic pop +#endif - (id)copy { return [[OFArray alloc] initWithArray: self]; } @@ -413,32 +347,64 @@ - (void)sort { [self sortUsingSelector: @selector(compare:) options: 0]; } + +static OFComparisonResult +selectorCompare(id left, id right, void *context) +{ + SEL selector = context; + OFComparisonResult (*comparator)(id, SEL, id) = + (OFComparisonResult (*)(id, SEL, id)) + [left methodForSelector: selector]; + + return comparator(left, selector, right); +} - (void)sortUsingSelector: (SEL)selector options: (OFArraySortOptions)options { size_t count = self.count; if (count == 0 || count == 1) return; - quicksort(self, 0, count - 1, selector, options); + quicksort(self, 0, count - 1, selectorCompare, (void *)selector, + options); +} + +- (void)sortUsingFunction: (OFCompareFunction)compare + context: (void *)context + options: (OFArraySortOptions)options +{ + size_t count = self.count; + + if (count == 0 || count == 1) + return; + + quicksort(self, 0, count - 1, compare, context, options); } #ifdef OF_HAVE_BLOCKS +static OFComparisonResult +blockCompare(id left, id right, void *context) +{ + OFComparator block = (OFComparator)context; + + return block(left, right); +} + - (void)sortUsingComparator: (OFComparator)comparator options: (OFArraySortOptions)options { size_t count = self.count; if (count == 0 || count == 1) return; - quicksortWithBlock(self, 0, count - 1, comparator, options); + quicksort(self, 0, count - 1, blockCompare, comparator, options); } #endif - (void)reverse { Index: src/OFMutableData.h ================================================================== --- src/OFMutableData.h +++ src/OFMutableData.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,24 +15,16 @@ #import "OFData.h" OF_ASSUME_NONNULL_BEGIN -@class OFString; -@class OFURI; - /** * @class OFMutableData OFMutableData.h ObjFW/OFMutableData.h * * @brief A class for storing and manipulating arbitrary data in an array. */ @interface OFMutableData: OFData -{ - size_t _capacity; - OF_RESERVE_IVARS(OFMutableData, 4) -} - /** * @brief All items of the OFMutableData as a C array. * * @warning The pointer is only valid until the OFMutableData is changed! * @@ -52,26 +44,10 @@ * @brief The last item of the OFMutableData or `NULL`. */ @property OF_NULLABLE_PROPERTY (readonly, nonatomic) void *mutableLastItem OF_RETURNS_INNER_POINTER; -/** - * @brief Creates a new OFMutableData with an item size of 1. - * - * @return A new autoreleased OFMutableData - */ -+ (instancetype)data; - -/** - * @brief Creates a new OFMutableData whose items all have the same specified - * size. - * - * @param itemSize The size of a single element in the OFMutableData - * @return A new autoreleased OFMutableData - */ -+ (instancetype)dataWithItemSize: (size_t)itemSize; - /** * @brief Creates a new OFMutableData with enough memory to hold the specified * number of items which all have an item size of 1. * * @param capacity The initial capacity for the OFMutableData @@ -87,26 +63,10 @@ * @param capacity The initial capacity for the OFMutableData * @return A new autoreleased OFMutableData */ + (instancetype)dataWithItemSize: (size_t)itemSize capacity: (size_t)capacity; -/** - * @brief Initializes an already allocated OFMutableData with an item size of 1. - * - * @return An initialized OFMutableData - */ -- (instancetype)init; - -/** - * @brief Initializes an already allocated OFMutableData whose items all have - * the same size. - * - * @param itemSize The size of a single element in the OFMutableData - * @return An initialized OFMutableData - */ -- (instancetype)initWithItemSize: (size_t)itemSize; - /** * @brief Initializes an already allocated OFMutableData with enough memory to * hold the the specified number of items which all have an item size of * 1. * Index: src/OFMutableData.m ================================================================== --- src/OFMutableData.m +++ src/OFMutableData.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,20 +18,121 @@ #include #include #include #import "OFMutableData.h" -#import "OFString.h" +#import "OFConcreteMutableData.h" -#import "OFInvalidArgumentException.h" -#import "OFOutOfMemoryException.h" #import "OFOutOfRangeException.h" + +static struct { + Class isa; +} placeholder; + +@interface OFPlaceholderMutableData: OFMutableData +@end + +@implementation OFPlaceholderMutableData +- (instancetype)init +{ + return (id)[[OFConcreteMutableData alloc] init]; +} + +- (instancetype)initWithItemSize: (size_t)itemSize +{ + return (id)[[OFConcreteMutableData alloc] initWithItemSize: itemSize]; +} + +- (instancetype)initWithItems: (const void *)items count: (size_t)count +{ + return (id)[[OFConcreteMutableData alloc] initWithItems: items + count: count]; +} + +- (instancetype)initWithItems: (const void *)items + count: (size_t)count + itemSize: (size_t)itemSize +{ + return (id)[[OFConcreteMutableData alloc] initWithItems: items + count: count + itemSize: itemSize]; +} + +- (instancetype)initWithItemsNoCopy: (void *)items + count: (size_t)count + freeWhenDone: (bool)freeWhenDone +{ + return (id)[[OFConcreteMutableData alloc] + initWithItemsNoCopy: items + count: count + freeWhenDone: freeWhenDone]; +} + +- (instancetype)initWithItemsNoCopy: (void *)items + count: (size_t)count + itemSize: (size_t)itemSize + freeWhenDone: (bool)freeWhenDone +{ + return (id)[[OFConcreteMutableData alloc] + initWithItemsNoCopy: items + count: count + itemSize: itemSize + freeWhenDone: freeWhenDone]; +} + +#ifdef OF_HAVE_FILES +- (instancetype)initWithContentsOfFile: (OFString *)path +{ + return (id)[[OFConcreteMutableData alloc] initWithContentsOfFile: path]; +} +#endif + +- (instancetype)initWithContentsOfIRI: (OFIRI *)IRI +{ + return (id)[[OFConcreteMutableData alloc] initWithContentsOfIRI: IRI]; +} + +- (instancetype)initWithStringRepresentation: (OFString *)string +{ + return (id)[[OFConcreteMutableData alloc] + initWithStringRepresentation: string]; +} + +- (instancetype)initWithBase64EncodedString: (OFString *)string +{ + return (id)[[OFConcreteMutableData alloc] + initWithBase64EncodedString: string]; +} + +- (instancetype)initWithCapacity: (size_t)capacity +{ + return (id)[[OFConcreteMutableData alloc] initWithCapacity: capacity]; +} + +- (instancetype)initWithItemSize: (size_t)itemSize capacity: (size_t)capacity +{ + return (id)[[OFConcreteMutableData alloc] initWithItemSize: itemSize + capacity: capacity]; +} + +OF_SINGLETON_METHODS +@end @implementation OFMutableData -+ (instancetype)data ++ (void)initialize +{ + if (self == [OFMutableData class]) + object_setClass((id)&placeholder, + [OFPlaceholderMutableData class]); +} + ++ (instancetype)alloc { - return [[[self alloc] init] autorelease]; + if (self == [OFMutableData class]) + return (id)&placeholder; + + return [super alloc]; } + (instancetype)dataWithItemSize: (size_t)itemSize { return [[[self alloc] initWithItemSize: itemSize] autorelease]; @@ -46,73 +147,23 @@ { return [[[self alloc] initWithItemSize: itemSize capacity: capacity] autorelease]; } -- (instancetype)init -{ - self = [super init]; - - _itemSize = 1; - _freeWhenDone = true; - - return self; -} - - (instancetype)initWithItemSize: (size_t)itemSize { - self = [super init]; - - @try { - if (itemSize == 0) - @throw [OFInvalidArgumentException exception]; - - _itemSize = itemSize; - _freeWhenDone = true; - } @catch (id e) { - [self release]; - @throw e; - } - - return self; + return [self initWithItemSize: 1 capacity: 0]; } - (instancetype)initWithCapacity: (size_t)capacity { - return [self initWithItemSize: 1 - capacity: capacity]; + return [self initWithItemSize: 1 capacity: capacity]; } - (instancetype)initWithItemSize: (size_t)itemSize capacity: (size_t)capacity { - self = [super init]; - - @try { - if (itemSize == 0) - @throw [OFInvalidArgumentException exception]; - - _items = OFAllocMemory(capacity, itemSize); - _itemSize = itemSize; - _capacity = capacity; - _freeWhenDone = true; - } @catch (id e) { - [self release]; - @throw e; - } - - return self; -} - -- (instancetype)initWithItems: (const void *)items - count: (size_t)count - itemSize: (size_t)itemSize -{ - self = [super initWithItems: items count: count itemSize: itemSize]; - - _capacity = _count; - - return self; + OF_INVALID_INIT_METHOD } - (instancetype)initWithItemsNoCopy: (void *)items count: (size_t)count itemSize: (size_t)itemSize @@ -124,188 +175,117 @@ OFFreeMemory(items); return self; } -- (instancetype)initWithStringRepresentation: (OFString *)string -{ - self = [super initWithStringRepresentation: string]; - - _capacity = _count; - - return self; -} - - (void *)mutableItems { - return _items; + OF_UNRECOGNIZED_SELECTOR } - (void *)mutableItemAtIndex: (size_t)idx { - if (idx >= _count) + if (idx >= self.count) @throw [OFOutOfRangeException exception]; - return _items + idx * _itemSize; + return (unsigned char *)self.mutableItems + idx * self.itemSize; } - (void *)mutableFirstItem { - if (_items == NULL || _count == 0) + void *mutableItems = self.mutableItems; + + if (mutableItems == NULL || self.count == 0) return NULL; - return _items; + return mutableItems; } - (void *)mutableLastItem { - if (_items == NULL || _count == 0) + unsigned char *mutableItems = self.mutableItems; + size_t count = self.count; + + if (mutableItems == NULL || count == 0) return NULL; - return _items + (_count - 1) * _itemSize; + return mutableItems + (count - 1) * self.itemSize; } - (OFData *)subdataWithRange: (OFRange)range { + size_t itemSize; + if (range.length > SIZE_MAX - range.location || - range.location + range.length > _count) + range.location + range.length > self.count) @throw [OFOutOfRangeException exception]; - return [OFData dataWithItems: _items + (range.location * _itemSize) + itemSize = self.itemSize; + return [OFData dataWithItems: (unsigned char *)self.mutableItems + + (range.location * itemSize) count: range.length - itemSize: _itemSize]; + itemSize: itemSize]; } - (void)addItem: (const void *)item { - if (SIZE_MAX - _count < 1) - @throw [OFOutOfRangeException exception]; - - if (_count + 1 > _capacity) { - _items = OFResizeMemory(_items, _count + 1, _itemSize); - _capacity = _count + 1; - } - - memcpy(_items + _count * _itemSize, item, _itemSize); - - _count++; + [self insertItems: item atIndex: self.count count: 1]; } - (void)insertItem: (const void *)item atIndex: (size_t)idx { [self insertItems: item atIndex: idx count: 1]; } - (void)addItems: (const void *)items count: (size_t)count { - if (count > SIZE_MAX - _count) - @throw [OFOutOfRangeException exception]; - - if (_count + count > _capacity) { - _items = OFResizeMemory(_items, _count + count, _itemSize); - _capacity = _count + count; - } - - memcpy(_items + _count * _itemSize, items, count * _itemSize); - _count += count; + [self insertItems: items atIndex: self.count count: count]; } - (void)insertItems: (const void *)items atIndex: (size_t)idx count: (size_t)count { - if (count > SIZE_MAX - _count || idx > _count) - @throw [OFOutOfRangeException exception]; - - if (_count + count > _capacity) { - _items = OFResizeMemory(_items, _count + count, _itemSize); - _capacity = _count + count; - } - - memmove(_items + (idx + count) * _itemSize, _items + idx * _itemSize, - (_count - idx) * _itemSize); - memcpy(_items + idx * _itemSize, items, count * _itemSize); - - _count += count; + OF_UNRECOGNIZED_SELECTOR } - (void)increaseCountBy: (size_t)count { - if (count > SIZE_MAX - _count) - @throw [OFOutOfRangeException exception]; - - if (_count + count > _capacity) { - _items = OFResizeMemory(_items, _count + count, _itemSize); - _capacity = _count + count; - } - - memset(_items + _count * _itemSize, '\0', count * _itemSize); - _count += count; + OF_UNRECOGNIZED_SELECTOR } - (void)removeItemAtIndex: (size_t)idx { [self removeItemsInRange: OFMakeRange(idx, 1)]; } - (void)removeItemsInRange: (OFRange)range { - if (range.length > SIZE_MAX - range.location || - range.location + range.length > _count) - @throw [OFOutOfRangeException exception]; - - memmove(_items + range.location * _itemSize, - _items + (range.location + range.length) * _itemSize, - (_count - range.location - range.length) * _itemSize); - - _count -= range.length; - @try { - _items = OFResizeMemory(_items, _count, _itemSize); - _capacity = _count; - } @catch (OFOutOfMemoryException *e) { - /* We don't really care, as we only made it smaller */ - } + OF_UNRECOGNIZED_SELECTOR } - (void)removeLastItem { - if (_count == 0) + size_t count = self.count; + + if (count == 0) return; - _count--; - @try { - _items = OFResizeMemory(_items, _count, _itemSize); - _capacity = _count; - } @catch (OFOutOfMemoryException *e) { - /* We don't care, as we only made it smaller */ - } + [self removeItemsInRange: OFMakeRange(count - 1, 1)]; } - (void)removeAllItems { - OFFreeMemory(_items); - _items = NULL; - _count = 0; - _capacity = 0; + [self removeItemsInRange: OFMakeRange(0, self.count)]; } - (id)copy { - return [[OFData alloc] initWithItems: _items - count: _count - itemSize: _itemSize]; + return [[OFData alloc] initWithItems: self.mutableItems + count: self.count + itemSize: self.itemSize]; } - (void)makeImmutable { - if (_capacity != _count) { - @try { - _items = OFResizeMemory(_items, _count, _itemSize); - _capacity = _count; - } @catch (OFOutOfMemoryException *e) { - /* We don't care, as we only made it smaller */ - } - } - - object_setClass(self, [OFData class]); } @end Index: src/OFMutableDictionary.h ================================================================== --- src/OFMutableDictionary.h +++ src/OFMutableDictionary.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -52,18 +52,25 @@ * @param capacity The initial capacity for the OFMutableDictionary * @return A new autoreleased OFMutableDictionary */ + (instancetype)dictionaryWithCapacity: (size_t)capacity; +/** + * @brief Initializes an already allocated OFMutableDictionary to be empty. + * + * @return An initialized OFMutableDictionary + */ +- (instancetype)init OF_DESIGNATED_INITIALIZER; + /** * @brief Initializes an already allocated OFMutableDictionary with enough * memory to hold the specified number of objects. * * @param capacity The initial capacity for the OFMutableDictionary * @return An initialized OFMutableDictionary */ -- (instancetype)initWithCapacity: (size_t)capacity; +- (instancetype)initWithCapacity: (size_t)capacity OF_DESIGNATED_INITIALIZER; /** * @brief Sets an object for a key. * * A key can be any object that conforms to the OFCopying protocol. Index: src/OFMutableDictionary.m ================================================================== --- src/OFMutableDictionary.m +++ src/OFMutableDictionary.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,50 +15,50 @@ #include "config.h" #include -#import "OFMutableMapTableDictionary.h" +#import "OFConcreteMutableDictionary.h" #import "OFArray.h" #import "OFString.h" static struct { Class isa; } placeholder; -@interface OFMutableDictionaryPlaceholder: OFDictionary +@interface OFPlaceholderMutableDictionary: OFDictionary @end -@implementation OFMutableDictionaryPlaceholder +@implementation OFPlaceholderMutableDictionary - (instancetype)init { - return (id)[[OFMutableMapTableDictionary alloc] init]; + return (id)[[OFConcreteMutableDictionary alloc] init]; } - (instancetype)initWithDictionary: (OFDictionary *)dictionary { - return (id)[[OFMutableMapTableDictionary alloc] + return (id)[[OFConcreteMutableDictionary alloc] initWithDictionary: dictionary]; } - (instancetype)initWithObject: (id)object forKey: (id)key { - return (id)[[OFMutableMapTableDictionary alloc] initWithObject: object + return (id)[[OFConcreteMutableDictionary alloc] initWithObject: object forKey: key]; } - (instancetype)initWithObjects: (OFArray *)objects forKeys: (OFArray *)keys { - return (id)[[OFMutableMapTableDictionary alloc] initWithObjects: objects + return (id)[[OFConcreteMutableDictionary alloc] initWithObjects: objects forKeys: keys]; } - (instancetype)initWithObjects: (id const *)objects forKeys: (id const *)keys count: (size_t)count { - return (id)[[OFMutableMapTableDictionary alloc] initWithObjects: objects + return (id)[[OFConcreteMutableDictionary alloc] initWithObjects: objects forKeys: keys count: count]; } - (instancetype)initWithKeysAndObjects: (id)firstKey, ... @@ -65,60 +65,38 @@ { id ret; va_list arguments; va_start(arguments, firstKey); - ret = (id)[[OFMutableMapTableDictionary alloc] initWithKey: firstKey + ret = (id)[[OFConcreteMutableDictionary alloc] initWithKey: firstKey arguments: arguments]; va_end(arguments); return ret; } - (instancetype)initWithKey: (id)firstKey arguments: (va_list)arguments { - return (id)[[OFMutableMapTableDictionary alloc] initWithKey: firstKey + return (id)[[OFConcreteMutableDictionary alloc] initWithKey: firstKey arguments: arguments]; } -- (instancetype)initWithSerialization: (OFXMLElement *)element -{ - return (id)[[OFMutableMapTableDictionary alloc] - initWithSerialization: element]; -} - - (instancetype)initWithCapacity: (size_t)capacity { - return (id)[[OFMutableMapTableDictionary alloc] + return (id)[[OFConcreteMutableDictionary alloc] initWithCapacity: capacity]; } -- (instancetype)retain -{ - return self; -} - -- (instancetype)autorelease -{ - return self; -} - -- (void)release -{ -} - -- (void)dealloc -{ - OF_DEALLOC_UNSUPPORTED -} +OF_SINGLETON_METHODS @end @implementation OFMutableDictionary + (void)initialize { if (self == [OFMutableDictionary class]) - placeholder.isa = [OFMutableDictionaryPlaceholder class]; + object_setClass((id)&placeholder, + [OFPlaceholderMutableDictionary class]); } + (instancetype)alloc { if (self == [OFMutableDictionary class]) @@ -132,28 +110,33 @@ return [[[self alloc] initWithCapacity: capacity] autorelease]; } - (instancetype)init { - if ([self isMemberOfClass: [OFMutableDictionary class]]) { - @try { - [self doesNotRecognizeSelector: _cmd]; - } @catch (id e) { - [self release]; - @throw e; - } - - abort(); - } - return [super init]; } + +#ifdef __clang__ +/* We intentionally don't call into super, so silence the warning. */ +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wunknown-pragmas" +# pragma clang diagnostic ignored "-Wobjc-designated-initializers" +#endif +- (instancetype)initWithObjects: (id const *)objects + forKeys: (id const *)keys + count: (size_t)count +{ + OF_INVALID_INIT_METHOD +} - (instancetype)initWithCapacity: (size_t)capacity { OF_INVALID_INIT_METHOD } +#ifdef __clang__ +# pragma clang diagnostic pop +#endif - (void)setObject: (id)object forKey: (id)key { OF_UNRECOGNIZED_SELECTOR } ADDED src/OFMutableIRI.h Index: src/OFMutableIRI.h ================================================================== --- /dev/null +++ src/OFMutableIRI.h @@ -0,0 +1,222 @@ +/* + * Copyright (c) 2008-2024 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#import "OFIRI.h" + +OF_ASSUME_NONNULL_BEGIN + +/** + * @class OFMutableIRI OFMutableIRI.h ObjFW/OFMutableIRI.h + * + * @brief A class for representing IRIs, URIs, URLs and URNs, for parsing them, + * accessing parts of them as well as modifying them. + * + * This class follows RFC 3976 and RFC 3987. + */ +@interface OFMutableIRI: OFIRI +{ + OF_RESERVE_IVARS(OFMutableIRI, 4) +} + +/** + * @brief The scheme part of the IRI. + * + * @throw OFInvalidFormatException The scheme being set is not in the correct + * format + */ +@property (readwrite, copy, nonatomic) OFString *scheme; + +/** + * @brief The host part of the IRI. + */ +@property OF_NULLABLE_PROPERTY (readwrite, copy, nonatomic) OFString *host; + +/** + * @brief The host part of the IRI in percent-encoded form. + * + * Setting this retains the original percent-encoding used - if more characters + * than necessary are percent-encoded, it is kept this way. + * + * @throw OFInvalidFormatException The host being set is not in the correct + * format + */ +@property OF_NULLABLE_PROPERTY (readwrite, copy, nonatomic) + OFString *percentEncodedHost; + +/** + * @brief The port part of the IRI. + * + * @throw OFInvalidArgumentException The port is not valid (e.g. negative or + * too big) + */ +@property OF_NULLABLE_PROPERTY (readwrite, copy, nonatomic) OFNumber *port; + +/** + * @brief The user part of the IRI. + */ +@property OF_NULLABLE_PROPERTY (readwrite, copy, nonatomic) OFString *user; + +/** + * @brief The user part of the IRI in percent-encoded form. + * + * Setting this retains the original percent-encoding used - if more characters + * than necessary are percent-encoded, it is kept this way. + * + * @throw OFInvalidFormatException The user being set is not in the correct + * format + */ +@property OF_NULLABLE_PROPERTY (readwrite, copy, nonatomic) + OFString *percentEncodedUser; + +/** + * @brief The password part of the IRI. + */ +@property OF_NULLABLE_PROPERTY (readwrite, copy, nonatomic) OFString *password; + +/** + * @brief The password part of the IRI in percent-encoded form. + * + * Setting this retains the original percent-encoding used - if more characters + * than necessary are percent-encoded, it is kept this way. + * + * @throw OFInvalidFormatException The password being set is not in the correct + * format + */ +@property OF_NULLABLE_PROPERTY (readwrite, copy, nonatomic) + OFString *percentEncodedPassword; + +/** + * @brief The path part of the IRI. + */ +@property (readwrite, copy, nonatomic) OFString *path; + +/** + * @brief The path part of the IRI in percent-encoded form. + * + * Setting this retains the original percent-encoding used - if more characters + * than necessary are percent-encoded, it is kept this way. + * + * @throw OFInvalidFormatException The path being set is not in the correct + * format + */ +@property (readwrite, copy, nonatomic) OFString *percentEncodedPath; + +/** + * @brief The path of the IRI split into components. + * + * The first component must always be empty to designate the root. + * + * @throw OFInvalidFormatException The path components being set are not in the + * correct format + */ +@property (readwrite, copy, nonatomic) + OFArray OF_GENERIC(OFString *) *pathComponents; + +/** + * @brief The query part of the IRI. + */ +@property OF_NULLABLE_PROPERTY (readwrite, copy, nonatomic) OFString *query; + +/** + * @brief The query part of the IRI in percent-encoded form. + * + * Setting this retains the original percent-encoding used - if more characters + * than necessary are percent-encoded, it is kept this way. + * + * @throw OFInvalidFormatException The query being set is not in the correct + * format + */ +@property OF_NULLABLE_PROPERTY (readwrite, copy, nonatomic) + OFString *percentEncodedQuery; + +/** + * @brief The query part of the IRI as an array. + * + * For example, a query like `key1=value1&key2=value2` would correspond to the + * following array: + * + * @[ + * [OFPair pairWithFirstObject: @"key1" secondObject: @"value1"], + * [OFPair pairWithFirstObject: @"key2" secondObject: @"value2"], + * ] + * + * @throw OFInvalidFormatException The query is not in the correct format + */ +@property OF_NULLABLE_PROPERTY (readwrite, copy, nonatomic) + OFArray OF_GENERIC(OFPair OF_GENERIC(OFString *, OFString *) *) *queryItems; + +/** + * @brief The fragment part of the IRI. + */ +@property OF_NULLABLE_PROPERTY (readwrite, copy, nonatomic) OFString *fragment; + +/** + * @brief The fragment part of the IRI in percent-encoded form. + * + * Setting this retains the original percent-encoding used - if more characters + * than necessary are percent-encoded, it is kept this way. + * + * @throw OFInvalidFormatException The fragment being set is not in the correct + * format + */ +@property OF_NULLABLE_PROPERTY (readwrite, copy, nonatomic) + OFString *percentEncodedFragment; + +/** + * @brief Creates a new mutable IRI with the specified schemed. + * + * @param scheme The scheme for the IRI + * @return A new, autoreleased OFMutableIRI + */ ++ (instancetype)IRIWithScheme: (OFString *)scheme; + +/** + * @brief Initializes an already allocated mutable IRI with the specified + * schemed. + * + * @param scheme The scheme for the IRI + * @return An initialized OFMutableIRI + */ +- (instancetype)initWithScheme: (OFString *)scheme; + +/** + * @brief Appends the specified path component. + * + * @param component The component to append + */ +- (void)appendPathComponent: (OFString *)component; + +/** + * @brief Appends the specified path component. + * + * @param component The component to append + * @param isDirectory Whether the path is a directory, in which case a slash is + * appened if there is no slash yet + */ +- (void)appendPathComponent: (OFString *)component + isDirectory: (bool)isDirectory; + +/** + * @brief Resolves relative subpaths. + */ +- (void)standardizePath; + +/** + * @brief Converts the mutable IRI to an immutable IRI. + */ +- (void)makeImmutable; +@end + +OF_ASSUME_NONNULL_END ADDED src/OFMutableIRI.m Index: src/OFMutableIRI.m ================================================================== --- /dev/null +++ src/OFMutableIRI.m @@ -0,0 +1,439 @@ +/* + * Copyright (c) 2008-2024 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#include "config.h" + +#import "OFMutableIRI.h" +#import "OFIRI+Private.h" +#import "OFArray.h" +#import "OFDictionary.h" +#ifdef OF_HAVE_FILES +# import "OFFileManager.h" +#endif +#import "OFNumber.h" +#import "OFPair.h" +#import "OFString.h" + +#import "OFInvalidArgumentException.h" +#import "OFInvalidFormatException.h" + +@implementation OFMutableIRI +@dynamic scheme, host, percentEncodedHost, port, user, percentEncodedUser; +@dynamic password, percentEncodedPassword, path, percentEncodedPath; +@dynamic pathComponents, query, percentEncodedQuery, queryItems, fragment; +@dynamic percentEncodedFragment; + ++ (instancetype)IRIWithScheme: (OFString *)scheme +{ + return [[[self alloc] initWithScheme: scheme] autorelease]; +} + +- (instancetype)initWithScheme: (OFString *)scheme +{ + self = [super of_init]; + + @try { + self.scheme = scheme; + _percentEncodedPath = @""; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (void)setScheme: (OFString *)scheme +{ + void *pool = objc_autoreleasePoolPush(); + OFString *old = _scheme; + + if (scheme.length < 1 || !OFASCIIIsAlpha(*scheme.UTF8String)) + @throw [OFInvalidFormatException exception]; + + OFIRIVerifyIsEscaped(scheme, + [OFCharacterSet IRISchemeAllowedCharacterSet], false); + + _scheme = [scheme.lowercaseString copy]; + + [old release]; + + objc_autoreleasePoolPop(pool); +} + +- (void)setHost: (OFString *)host +{ + void *pool = objc_autoreleasePoolPush(); + OFString *old = _percentEncodedHost; + + if (OFIRIIsIPv6Host(host)) + _percentEncodedHost = [[OFString alloc] + initWithFormat: @"[%@]", host]; + else + _percentEncodedHost = [[host + stringByAddingPercentEncodingWithAllowedCharacters: + [OFCharacterSet IRIHostAllowedCharacterSet]] copy]; + + [old release]; + + objc_autoreleasePoolPop(pool); +} + +- (void)setPercentEncodedHost: (OFString *)percentEncodedHost +{ + OFString *old; + + if ([percentEncodedHost hasPrefix: @"["] && + [percentEncodedHost hasSuffix: @"]"]) { + if (!OFIRIIsIPv6Host([percentEncodedHost substringWithRange: + OFMakeRange(1, percentEncodedHost.length - 2)])) + @throw [OFInvalidFormatException exception]; + } else if (percentEncodedHost != nil) + OFIRIVerifyIsEscaped(percentEncodedHost, + [OFCharacterSet IRIHostAllowedCharacterSet], true); + + old = _percentEncodedHost; + _percentEncodedHost = [percentEncodedHost copy]; + [old release]; +} + +- (void)setPort: (OFNumber *)port +{ + OFNumber *old = _port; + + if (port.longLongValue < 0 || port.longLongValue > 65535) + @throw [OFInvalidArgumentException exception]; + + _port = [port copy]; + [old release]; +} + +- (void)setUser: (OFString *)user +{ + void *pool = objc_autoreleasePoolPush(); + OFString *old = _percentEncodedUser; + + _percentEncodedUser = [[user + stringByAddingPercentEncodingWithAllowedCharacters: + [OFCharacterSet IRIUserAllowedCharacterSet]] copy]; + + [old release]; + + objc_autoreleasePoolPop(pool); +} + +- (void)setPercentEncodedUser: (OFString *)percentEncodedUser +{ + OFString *old; + + if (percentEncodedUser != nil) + OFIRIVerifyIsEscaped(percentEncodedUser, + [OFCharacterSet IRIUserAllowedCharacterSet], true); + + old = _percentEncodedUser; + _percentEncodedUser = [percentEncodedUser copy]; + [old release]; +} + +- (void)setPassword: (OFString *)password +{ + void *pool = objc_autoreleasePoolPush(); + OFString *old = _percentEncodedPassword; + + _percentEncodedPassword = [[password + stringByAddingPercentEncodingWithAllowedCharacters: + [OFCharacterSet IRIPasswordAllowedCharacterSet]] copy]; + + [old release]; + + objc_autoreleasePoolPop(pool); +} + +- (void)setPercentEncodedPassword: (OFString *)percentEncodedPassword +{ + OFString *old; + + if (percentEncodedPassword != nil) + OFIRIVerifyIsEscaped(percentEncodedPassword, + [OFCharacterSet IRIPasswordAllowedCharacterSet], true); + + old = _percentEncodedPassword; + _percentEncodedPassword = [percentEncodedPassword copy]; + [old release]; +} + +- (void)setPath: (OFString *)path +{ + void *pool = objc_autoreleasePoolPush(); + OFString *old = _percentEncodedPath; + + _percentEncodedPath = [[path + stringByAddingPercentEncodingWithAllowedCharacters: + [OFCharacterSet IRIPathAllowedCharacterSet]] copy]; + + [old release]; + + objc_autoreleasePoolPop(pool); +} + +- (void)setPercentEncodedPath: (OFString *)percentEncodedPath +{ + OFString *old; + + OFIRIVerifyIsEscaped(percentEncodedPath, + [OFCharacterSet IRIPathAllowedCharacterSet], true); + + old = _percentEncodedPath; + _percentEncodedPath = [percentEncodedPath copy]; + [old release]; +} + +- (void)setPathComponents: (OFArray *)components +{ + void *pool = objc_autoreleasePoolPush(); + + if (components.count == 0) + @throw [OFInvalidFormatException exception]; + + if ([components.firstObject isEqual: @"/"]) { + OFMutableArray *mutComponents = + [[components mutableCopy] autorelease]; + [mutComponents replaceObjectAtIndex: 0 withObject: @""]; + components = mutComponents; + } + + self.path = [components componentsJoinedByString: @"/"]; + + objc_autoreleasePoolPop(pool); +} + +- (void)setQuery: (OFString *)query +{ + void *pool = objc_autoreleasePoolPush(); + OFString *old = _percentEncodedQuery; + + _percentEncodedQuery = [[query + stringByAddingPercentEncodingWithAllowedCharacters: + [OFCharacterSet IRIQueryAllowedCharacterSet]] copy]; + + [old release]; + + objc_autoreleasePoolPop(pool); +} + +- (void)setPercentEncodedQuery: (OFString *)percentEncodedQuery +{ + OFString *old; + + if (percentEncodedQuery != nil) + OFIRIVerifyIsEscaped(percentEncodedQuery, + [OFCharacterSet IRIQueryAllowedCharacterSet], true); + + old = _percentEncodedQuery; + _percentEncodedQuery = [percentEncodedQuery copy]; + [old release]; +} + +- (void)setQueryItems: + (OFArray OF_GENERIC(OFPair OF_GENERIC(OFString *, OFString *) *) *) + queryItems +{ + void *pool; + OFMutableString *percentEncodedQuery; + OFCharacterSet *characterSet; + OFString *old; + + if (queryItems == nil) { + [_percentEncodedQuery release]; + _percentEncodedQuery = nil; + return; + } + + pool = objc_autoreleasePoolPush(); + percentEncodedQuery = [OFMutableString string]; + characterSet = [OFCharacterSet IRIQueryKeyValueAllowedCharacterSet]; + + for (OFPair OF_GENERIC(OFString *, OFString *) *item in queryItems) { + OFString *key = [item.firstObject + stringByAddingPercentEncodingWithAllowedCharacters: + characterSet]; + OFString *value = [item.secondObject + stringByAddingPercentEncodingWithAllowedCharacters: + characterSet]; + + if (percentEncodedQuery.length > 0) + [percentEncodedQuery appendString: @"&"]; + + [percentEncodedQuery appendFormat: @"%@=%@", key, value]; + } + + old = _percentEncodedQuery; + _percentEncodedQuery = [percentEncodedQuery copy]; + [old release]; + + objc_autoreleasePoolPop(pool); +} + +- (void)setFragment: (OFString *)fragment +{ + void *pool = objc_autoreleasePoolPush(); + OFString *old = _percentEncodedFragment; + + _percentEncodedFragment = [[fragment + stringByAddingPercentEncodingWithAllowedCharacters: + [OFCharacterSet IRIFragmentAllowedCharacterSet]] copy]; + + [old release]; + + objc_autoreleasePoolPop(pool); +} + +- (void)setPercentEncodedFragment: (OFString *)percentEncodedFragment +{ + OFString *old; + + if (percentEncodedFragment != nil) + OFIRIVerifyIsEscaped(percentEncodedFragment, + [OFCharacterSet IRIFragmentAllowedCharacterSet], true); + + old = _percentEncodedFragment; + _percentEncodedFragment = [percentEncodedFragment copy]; + [old release]; +} + +- (id)copy +{ + OFMutableIRI *copy = [self mutableCopy]; + + [copy makeImmutable]; + + return copy; +} + +- (void)appendPathComponent: (OFString *)component +{ + [self appendPathComponent: component isDirectory: false]; + +#ifdef OF_HAVE_FILES + if ([_scheme isEqual: @"file"] && + ![_percentEncodedPath hasSuffix: @"/"] && + [[OFFileManager defaultManager] directoryExistsAtIRI: self]) { + void *pool = objc_autoreleasePoolPush(); + OFString *path = [_percentEncodedPath + stringByAppendingString: @"/"]; + + [_percentEncodedPath release]; + _percentEncodedPath = [path retain]; + + objc_autoreleasePoolPop(pool); + } +#endif +} + +- (void)appendPathComponent: (OFString *)component + isDirectory: (bool)isDirectory +{ + void *pool; + OFString *path; + + if ([component isEqual: @"/"] && [_percentEncodedPath hasSuffix: @"/"]) + return; + + pool = objc_autoreleasePoolPush(); + component = [component + stringByAddingPercentEncodingWithAllowedCharacters: + [OFCharacterSet IRIPathAllowedCharacterSet]]; + +#if defined(OF_WINDOWS) || defined(OF_MSDOS) + if ([_percentEncodedPath hasSuffix: @"/"] || + ([_scheme isEqual: @"file"] && + [_percentEncodedPath hasSuffix: @":"])) +#else + if ([_percentEncodedPath hasSuffix: @"/"]) +#endif + path = [_percentEncodedPath stringByAppendingString: component]; + else + path = [_percentEncodedPath + stringByAppendingFormat: @"/%@", component]; + + if (isDirectory && ![path hasSuffix: @"/"]) + path = [path stringByAppendingString: @"/"]; + + [_percentEncodedPath release]; + _percentEncodedPath = [path retain]; + + objc_autoreleasePoolPop(pool); +} + +- (void)standardizePath +{ + void *pool = objc_autoreleasePoolPush(); + OFMutableArray OF_GENERIC(OFString *) *array; + bool done = false, startsWithEmpty, endsWithEmpty; + OFString *path; + + array = [[[_percentEncodedPath + componentsSeparatedByString: @"/"] mutableCopy] autorelease]; + + endsWithEmpty = ([array.lastObject length] == 0); + startsWithEmpty = ([array.firstObject length] == 0); + + while (!done) { + size_t length = array.count; + + done = true; + + for (size_t i = 0; i < length; i++) { + OFString *current = [array objectAtIndex: i]; + OFString *parent = + (i > 0 ? [array objectAtIndex: i - 1] : nil); + + if ([current isEqual: @"."] || current.length == 0) { + [array removeObjectAtIndex: i]; + + done = false; + break; + } + + if ([current isEqual: @".."] && parent != nil && + ![parent isEqual: @".."]) { + [array removeObjectsInRange: + OFMakeRange(i - 1, 2)]; + + done = false; + break; + } + } + } + + if (startsWithEmpty) + [array insertObject: @"" atIndex: 0]; + if (endsWithEmpty) + [array addObject: @""]; + + path = [array componentsJoinedByString: @"/"]; + if (startsWithEmpty && path.length == 0) + path = @"/"; + + self.percentEncodedPath = path; + + objc_autoreleasePoolPop(pool); +} + +- (void)makeImmutable +{ + object_setClass(self, [OFIRI class]); +} +@end Index: src/OFMutableLHAArchiveEntry.h ================================================================== --- src/OFMutableLHAArchiveEntry.h +++ src/OFMutableLHAArchiveEntry.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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/OFMutableMapTableDictionary.h Index: src/OFMutableMapTableDictionary.h ================================================================== --- src/OFMutableMapTableDictionary.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (c) 2008-2022 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#import "OFDictionary.h" - -OF_ASSUME_NONNULL_BEGIN - -@class OFMapTable; - -@interface OFMutableMapTableDictionary: OFMutableDictionary -{ - OFMapTable *_mapTable; -} -@end - -OF_ASSUME_NONNULL_END DELETED src/OFMutableMapTableDictionary.m Index: src/OFMutableMapTableDictionary.m ================================================================== --- src/OFMutableMapTableDictionary.m +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (c) 2008-2022 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 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 "OFMutableMapTableDictionary.h" -#import "OFMapTable.h" -#import "OFMapTableDictionary.h" - -#import "OFEnumerationMutationException.h" -#import "OFOutOfRangeException.h" - -@implementation OFMutableMapTableDictionary -+ (void)initialize -{ - if (self == [OFMutableMapTableDictionary class]) - [self inheritMethodsFromClass: [OFMapTableDictionary class]]; -} - -- (void)setObject: (id)object forKey: (id)key -{ - [_mapTable setObject: object forKey: key]; -} - -- (void)removeObjectForKey: (id)key -{ - [_mapTable removeObjectForKey: key]; -} - -- (void)removeAllObjects -{ - [_mapTable removeAllObjects]; -} - -#ifdef OF_HAVE_BLOCKS -- (void)replaceObjectsUsingBlock: (OFDictionaryReplaceBlock)block -{ - @try { - [_mapTable replaceObjectsUsingBlock: - ^ void *(void *key, void *object) { - return block(key, object); - }]; - } @catch (OFEnumerationMutationException *e) { - @throw [OFEnumerationMutationException - exceptionWithObject: self]; - } -} -#endif - -- (void)makeImmutable -{ - object_setClass(self, [OFMapTableDictionary class]); -} -@end DELETED src/OFMutableMapTableSet.h Index: src/OFMutableMapTableSet.h ================================================================== --- src/OFMutableMapTableSet.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (c) 2008-2022 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#import "OFMutableSet.h" - -OF_ASSUME_NONNULL_BEGIN - -@class OFMapTable; - -@interface OFMutableMapTableSet: OFMutableSet -{ - OFMapTable *_mapTable; -} -@end - -OF_ASSUME_NONNULL_END DELETED src/OFMutableMapTableSet.m Index: src/OFMutableMapTableSet.m ================================================================== --- src/OFMutableMapTableSet.m +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2008-2022 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#include "config.h" - -#import "OFMutableMapTableSet.h" -#import "OFMapTableSet.h" -#import "OFMapTable.h" - -@implementation OFMutableMapTableSet -+ (void)initialize -{ - if (self == [OFMutableMapTableSet class]) - [self inheritMethodsFromClass: [OFMapTableSet class]]; -} - -- (void)addObject: (id)object -{ - [_mapTable setObject: (void *)1 forKey: object]; -} - -- (void)removeObject: (id)object -{ - [_mapTable removeObjectForKey: object]; -} - -- (void)removeAllObjects -{ - [_mapTable removeAllObjects]; -} - -- (void)makeImmutable -{ - object_setClass(self, [OFMapTableSet class]); -} -@end Index: src/OFMutablePair.h ================================================================== --- src/OFMutablePair.h +++ src/OFMutablePair.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,18 +36,25 @@ * @param capacity The initial capacity for the OFMutableSet * @return A new autoreleased OFMutableSet */ + (instancetype)setWithCapacity: (size_t)capacity; +/** + * @brief Initializes an already allocated OFMutableSet to be empty. + * + * @return An initialized OFMutableSet + */ +- (instancetype)init OF_DESIGNATED_INITIALIZER; + /** * @brief Initializes an already allocated OFMutableSet with enough memory to * hold the specified number of objects. * * @param capacity The initial capacity for the OFMutableSet * @return An initialized OFMutableSet */ -- (instancetype)initWithCapacity: (size_t)capacity; +- (instancetype)initWithCapacity: (size_t)capacity OF_DESIGNATED_INITIALIZER; /** * @brief Adds the specified object to the set. * * @param object The object to add to the set Index: src/OFMutableSet.m ================================================================== --- src/OFMutableSet.m +++ src/OFMutableSet.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,99 +15,85 @@ #include "config.h" #include -#include - #import "OFMutableSet.h" -#import "OFMutableMapTableSet.h" +#import "OFConcreteMutableSet.h" +#import "OFString.h" static struct { Class isa; } placeholder; -@interface OFMutableSetPlaceholder: OFMutableSet +@interface OFPlaceholderMutableSet: OFMutableSet @end -@implementation OFMutableSetPlaceholder +@implementation OFPlaceholderMutableSet +#ifdef __clang__ +/* We intentionally don't call into super, so silence the warning. */ +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wunknown-pragmas" +# pragma clang diagnostic ignored "-Wobjc-designated-initializers" +#endif - (instancetype)init { - return (id)[[OFMutableMapTableSet alloc] init]; + return (id)[[OFConcreteMutableSet alloc] init]; } - (instancetype)initWithSet: (OFSet *)set { - return (id)[[OFMutableMapTableSet alloc] initWithSet: set]; + return (id)[[OFConcreteMutableSet alloc] initWithSet: set]; } - (instancetype)initWithArray: (OFArray *)array { - return (id)[[OFMutableMapTableSet alloc] initWithArray: array]; + return (id)[[OFConcreteMutableSet alloc] initWithArray: array]; } - (instancetype)initWithObjects: (id)firstObject, ... { id ret; va_list arguments; va_start(arguments, firstObject); - ret = [[OFMutableMapTableSet alloc] initWithObject: firstObject + ret = [[OFConcreteMutableSet alloc] initWithObject: firstObject arguments: arguments]; va_end(arguments); return ret; } - (instancetype)initWithObjects: (id const *)objects count: (size_t)count { - return (id)[[OFMutableMapTableSet alloc] initWithObjects: objects + return (id)[[OFConcreteMutableSet alloc] initWithObjects: objects count: count]; } - (instancetype)initWithObject: (id)firstObject arguments: (va_list)arguments { - return (id)[[OFMutableMapTableSet alloc] initWithObject: firstObject + return (id)[[OFConcreteMutableSet alloc] initWithObject: firstObject arguments: arguments]; } -- (instancetype)initWithSerialization: (OFXMLElement *)element -{ - return (id)[[OFMutableMapTableSet alloc] - initWithSerialization: element]; -} - - (instancetype)initWithCapacity: (size_t)capacity { - return (id)[[OFMutableMapTableSet alloc] initWithCapacity: capacity]; -} - -- (instancetype)retain -{ - return self; -} - -- (instancetype)autorelease -{ - return self; -} - -- (void)release -{ -} - -- (void)dealloc -{ - OF_DEALLOC_UNSUPPORTED -} + return (id)[[OFConcreteMutableSet alloc] initWithCapacity: capacity]; +} +#ifdef __clang__ +# pragma clang diagnostic pop +#endif + +OF_SINGLETON_METHODS @end @implementation OFMutableSet + (void)initialize { if (self == [OFMutableSet class]) - placeholder.isa = [OFMutableSetPlaceholder class]; + object_setClass((id)&placeholder, + [OFPlaceholderMutableSet class]); } + (instancetype)alloc { if (self == [OFMutableSet class]) @@ -121,27 +107,31 @@ return [[[self alloc] initWithCapacity: capacity] autorelease]; } - (instancetype)init { - if ([self isMemberOfClass: [OFMutableSet class]]) { - @try { - [self doesNotRecognizeSelector: _cmd]; - abort(); - } @catch (id e) { - [self release]; - @throw e; - } - } - return [super init]; } + +#ifdef __clang__ +/* We intentionally don't call into super, so silence the warning. */ +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wunknown-pragmas" +# pragma clang diagnostic ignored "-Wobjc-designated-initializers" +#endif +- (instancetype)initWithObjects: (id const *)objects count: (size_t)count +{ + OF_INVALID_INIT_METHOD +} - (instancetype)initWithCapacity: (size_t)capacity { OF_INVALID_INIT_METHOD } +#ifdef __clang__ +# pragma clang diagnostic pop +#endif - (id)copy { return [[OFSet alloc] initWithSet: self]; } @@ -172,11 +162,11 @@ @try { size_t i; i = 0; for (id object in self) { - assert(i < count); + OFAssert(i < count); cArray[i++] = object; } for (i = 0; i < count; i++) if (![set containsObject: cArray[i]]) Index: src/OFMutableString.h ================================================================== --- src/OFMutableString.h +++ src/OFMutableString.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,18 +11,14 @@ * Public License, either version 2 or 3, which can be found in the file * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this * file. */ -#ifndef OBJFW_OF_MUTABLE_STRING_H -#define OBJFW_OF_MUTABLE_STRING_H - -#include "OFString.h" +#import "OFString.h" OF_ASSUME_NONNULL_BEGIN -#ifdef __OBJC__ /** * @class OFMutableString OFString.h ObjFW/OFString.h * * @brief A class for storing and modifying strings. */ @@ -208,10 +204,7 @@ /** * @brief Converts the mutable string to an immutable string. */ - (void)makeImmutable; @end -#endif OF_ASSUME_NONNULL_END - -#endif Index: src/OFMutableString.m ================================================================== --- src/OFMutableString.m +++ src/OFMutableString.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,14 +31,20 @@ static struct { Class isa; } placeholder; -@interface OFMutableStringPlaceholder: OFMutableString +@interface OFPlaceholderMutableString: OFMutableString @end -@implementation OFMutableStringPlaceholder +@implementation OFPlaceholderMutableString +#ifdef __clang__ +/* We intentionally don't call into super, so silence the warning. */ +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wunknown-pragmas" +# pragma clang diagnostic ignored "-Wobjc-designated-initializers" +#endif - (instancetype)init { return (id)[[OFMutableUTF8String alloc] init]; } @@ -172,53 +178,35 @@ initWithContentsOfFile: path encoding: encoding]; } #endif -- (instancetype)initWithContentsOfURI: (OFURI *)URI +- (instancetype)initWithContentsOfIRI: (OFIRI *)IRI { - return (id)[[OFMutableUTF8String alloc] initWithContentsOfURI: URI]; + return (id)[[OFMutableUTF8String alloc] initWithContentsOfIRI: IRI]; } -- (instancetype)initWithContentsOfURI: (OFURI *)URI +- (instancetype)initWithContentsOfIRI: (OFIRI *)IRI encoding: (OFStringEncoding)encoding { return (id)[[OFMutableUTF8String alloc] - initWithContentsOfURI: URI + initWithContentsOfIRI: IRI encoding: encoding]; } - -- (instancetype)initWithSerialization: (OFXMLElement *)element -{ - return (id)[[OFMutableUTF8String alloc] initWithSerialization: element]; -} - -- (instancetype)retain -{ - return self; -} - -- (instancetype)autorelease -{ - return self; -} - -- (void)release -{ -} - -- (void)dealloc -{ - OF_DEALLOC_UNSUPPORTED -} +#ifdef __clang__ +# pragma clang diagnostic pop +#endif + +OF_SINGLETON_METHODS @end @implementation OFMutableString + (void)initialize { if (self == [OFMutableString class]) - placeholder.isa = [OFMutableStringPlaceholder class]; + object_setClass((id)&placeholder, + [OFPlaceholderMutableString class]); } + (instancetype)alloc { if (self == [OFMutableString class]) Index: src/OFMutableTarArchiveEntry.h ================================================================== --- src/OFMutableTarArchiveEntry.h +++ src/OFMutableTarArchiveEntry.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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/OFMutableURI.h Index: src/OFMutableURI.h ================================================================== --- src/OFMutableURI.h +++ /dev/null @@ -1,220 +0,0 @@ -/* - * Copyright (c) 2008-2022 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#import "OFURI.h" - -OF_ASSUME_NONNULL_BEGIN - -/** - * @class OFMutableURI OFMutableURI.h ObjFW/OFMutableURI.h - * - * @brief A class for parsing URIs as per RFC 3986 and accessing and modifying - * parts of it. - */ -@interface OFMutableURI: OFURI -{ - OF_RESERVE_IVARS(OFMutableURI, 4) -} - -/** - * @brief The scheme part of the URI. - * - * @throw OFInvalidFormatException The scheme being set is not in the correct - * format - */ -@property (readwrite, copy, nonatomic) OFString *scheme; - -/** - * @brief The host part of the URI. - */ -@property OF_NULLABLE_PROPERTY (readwrite, copy, nonatomic) OFString *host; - -/** - * @brief The host part of the URI in percent-encoded form. - * - * Setting this retains the original percent-encoding used - if more characters - * than necessary are percent-encoded, it is kept this way. - * - * @throw OFInvalidFormatException The host being set is not in the correct - * format - */ -@property OF_NULLABLE_PROPERTY (readwrite, copy, nonatomic) - OFString *percentEncodedHost; - -/** - * @brief The port part of the URI. - * - * @throw OFInvalidArgumentException The port is not valid (e.g. negative or - * too big) - */ -@property OF_NULLABLE_PROPERTY (readwrite, copy, nonatomic) OFNumber *port; - -/** - * @brief The user part of the URI. - */ -@property OF_NULLABLE_PROPERTY (readwrite, copy, nonatomic) OFString *user; - -/** - * @brief The user part of the URI in percent-encoded form. - * - * Setting this retains the original percent-encoding used - if more characters - * than necessary are percent-encoded, it is kept this way. - * - * @throw OFInvalidFormatException The user being set is not in the correct - * format - */ -@property OF_NULLABLE_PROPERTY (readwrite, copy, nonatomic) - OFString *percentEncodedUser; - -/** - * @brief The password part of the URI. - */ -@property OF_NULLABLE_PROPERTY (readwrite, copy, nonatomic) OFString *password; - -/** - * @brief The password part of the URI in URI-encoded form. - * - * Setting this retains the original percent-encoding used - if more characters - * than necessary are percent-encoded, it is kept this way. - * - * @throw OFInvalidFormatException The password being set is not in the correct - * format - */ -@property OF_NULLABLE_PROPERTY (readwrite, copy, nonatomic) - OFString *percentEncodedPassword; - -/** - * @brief The path part of the URI. - */ -@property (readwrite, copy, nonatomic) OFString *path; - -/** - * @brief The path part of the URI in percent-encoded form. - * - * Setting this retains the original percent-encoding used - if more characters - * than necessary are percent-encoded, it is kept this way. - * - * @throw OFInvalidFormatException The path being set is not in the correct - * format - */ -@property (readwrite, copy, nonatomic) OFString *percentEncodedPath; - -/** - * @brief The path of the URI split into components. - * - * The first component must always be empty to designate the root. - * - * @throw OFInvalidFormatException The path components being set are not in the - * correct format - */ -@property (readwrite, copy, nonatomic) - OFArray OF_GENERIC(OFString *) *pathComponents; - -/** - * @brief The query part of the URI. - */ -@property OF_NULLABLE_PROPERTY (readwrite, copy, nonatomic) OFString *query; - -/** - * @brief The query part of the URI in percent-encoded form. - * - * Setting this retains the original percent-encoding used - if more characters - * than necessary are percent-encoded, it is kept this way. - * - * @throw OFInvalidFormatException The query being set is not in the correct - * format - */ -@property OF_NULLABLE_PROPERTY (readwrite, copy, nonatomic) - OFString *percentEncodedQuery; - -/** - * @brief The query part of the URI as an array. - * - * For example, a query like `key1=value1&key2=value2` would correspond to the - * following array: - * - * @[ - * [OFPair pairWithFirstObject: @"key1" secondObject: @"value1"], - * [OFPair pairWithFirstObject: @"key2" secondObject: @"value2"], - * ] - * - * @throw OFInvalidFormatException The query is not in the correct format - */ -@property OF_NULLABLE_PROPERTY (readwrite, copy, nonatomic) - OFArray OF_GENERIC(OFPair OF_GENERIC(OFString *, OFString *) *) *queryItems; - -/** - * @brief The fragment part of the URI. - */ -@property OF_NULLABLE_PROPERTY (readwrite, copy, nonatomic) OFString *fragment; - -/** - * @brief The fragment part of the URI in percent-encoded form. - * - * Setting this retains the original percent-encoding used - if more characters - * than necessary are percent-encoded, it is kept this way. - * - * @throw OFInvalidFormatException The fragment being set is not in the correct - * format - */ -@property OF_NULLABLE_PROPERTY (readwrite, copy, nonatomic) - OFString *percentEncodedFragment; - -/** - * @brief Creates a new mutable URI with the specified schemed. - * - * @param scheme The scheme for the URI - * @return A new, autoreleased OFMutableURI - */ -+ (instancetype)URIWithScheme: (OFString *)scheme; - -/** - * @brief Initializes an already allocated mutable URI with the specified - * schemed. - * - * @param scheme The scheme for the URI - * @return An initialized OFMutableURI - */ -- (instancetype)initWithScheme: (OFString *)scheme; - -/** - * @brief Appends the specified path component. - * - * @param component The component to append - */ -- (void)appendPathComponent: (OFString *)component; - -/** - * @brief Appends the specified path component. - * - * @param component The component to append - * @param isDirectory Whether the path is a directory, in which case a slash is - * appened if there is no slash yet - */ -- (void)appendPathComponent: (OFString *)component - isDirectory: (bool)isDirectory; - -/** - * @brief Resolves relative subpaths. - */ -- (void)standardizePath; - -/** - * @brief Converts the mutable URI to an immutable URI. - */ -- (void)makeImmutable; -@end - -OF_ASSUME_NONNULL_END DELETED src/OFMutableURI.m Index: src/OFMutableURI.m ================================================================== --- src/OFMutableURI.m +++ /dev/null @@ -1,439 +0,0 @@ -/* - * Copyright (c) 2008-2022 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#include "config.h" - -#import "OFMutableURI.h" -#import "OFURI+Private.h" -#import "OFArray.h" -#import "OFDictionary.h" -#ifdef OF_HAVE_FILES -# import "OFFileManager.h" -#endif -#import "OFNumber.h" -#import "OFPair.h" -#import "OFString.h" - -#import "OFInvalidArgumentException.h" -#import "OFInvalidFormatException.h" - -@implementation OFMutableURI -@dynamic scheme, host, percentEncodedHost, port, user, percentEncodedUser; -@dynamic password, percentEncodedPassword, path, percentEncodedPath; -@dynamic pathComponents, query, percentEncodedQuery, queryItems, fragment; -@dynamic percentEncodedFragment; - -+ (instancetype)URIWithScheme: (OFString *)scheme -{ - return [[[self alloc] initWithScheme: scheme] autorelease]; -} - -- (instancetype)initWithScheme: (OFString *)scheme -{ - self = [super of_init]; - - @try { - self.scheme = scheme; - _percentEncodedPath = @""; - } @catch (id e) { - [self release]; - @throw e; - } - - return self; -} - -- (void)setScheme: (OFString *)scheme -{ - void *pool = objc_autoreleasePoolPush(); - OFString *old = _scheme; - - if (scheme.length < 1 || !OFASCIIIsAlpha(*scheme.UTF8String)) - @throw [OFInvalidFormatException exception]; - - OFURIVerifyIsEscaped(scheme, - [OFCharacterSet URISchemeAllowedCharacterSet], false); - - _scheme = [scheme.lowercaseString copy]; - - [old release]; - - objc_autoreleasePoolPop(pool); -} - -- (void)setHost: (OFString *)host -{ - void *pool = objc_autoreleasePoolPush(); - OFString *old = _percentEncodedHost; - - if (OFURIIsIPv6Host(host)) - _percentEncodedHost = [[OFString alloc] - initWithFormat: @"[%@]", host]; - else - _percentEncodedHost = [[host - stringByAddingPercentEncodingWithAllowedCharacters: - [OFCharacterSet URIHostAllowedCharacterSet]] copy]; - - [old release]; - - objc_autoreleasePoolPop(pool); -} - -- (void)setPercentEncodedHost: (OFString *)percentEncodedHost -{ - OFString *old; - - if ([percentEncodedHost hasPrefix: @"["] && - [percentEncodedHost hasSuffix: @"]"]) { - if (!OFURIIsIPv6Host([percentEncodedHost substringWithRange: - OFMakeRange(1, percentEncodedHost.length - 2)])) - @throw [OFInvalidFormatException exception]; - } else if (percentEncodedHost != nil) - OFURIVerifyIsEscaped(percentEncodedHost, - [OFCharacterSet URIHostAllowedCharacterSet], true); - - old = _percentEncodedHost; - _percentEncodedHost = [percentEncodedHost copy]; - [old release]; -} - -- (void)setPort: (OFNumber *)port -{ - OFNumber *old = _port; - - if (port.longLongValue < 0 || port.longLongValue > 65535) - @throw [OFInvalidArgumentException exception]; - - _port = [port copy]; - [old release]; -} - -- (void)setUser: (OFString *)user -{ - void *pool = objc_autoreleasePoolPush(); - OFString *old = _percentEncodedUser; - - _percentEncodedUser = [[user - stringByAddingPercentEncodingWithAllowedCharacters: - [OFCharacterSet URIUserAllowedCharacterSet]] copy]; - - [old release]; - - objc_autoreleasePoolPop(pool); -} - -- (void)setPercentEncodedUser: (OFString *)percentEncodedUser -{ - OFString *old; - - if (percentEncodedUser != nil) - OFURIVerifyIsEscaped(percentEncodedUser, - [OFCharacterSet URIUserAllowedCharacterSet], true); - - old = _percentEncodedUser; - _percentEncodedUser = [percentEncodedUser copy]; - [old release]; -} - -- (void)setPassword: (OFString *)password -{ - void *pool = objc_autoreleasePoolPush(); - OFString *old = _percentEncodedPassword; - - _percentEncodedPassword = [[password - stringByAddingPercentEncodingWithAllowedCharacters: - [OFCharacterSet URIPasswordAllowedCharacterSet]] copy]; - - [old release]; - - objc_autoreleasePoolPop(pool); -} - -- (void)setPercentEncodedPassword: (OFString *)percentEncodedPassword -{ - OFString *old; - - if (percentEncodedPassword != nil) - OFURIVerifyIsEscaped(percentEncodedPassword, - [OFCharacterSet URIPasswordAllowedCharacterSet], true); - - old = _percentEncodedPassword; - _percentEncodedPassword = [percentEncodedPassword copy]; - [old release]; -} - -- (void)setPath: (OFString *)path -{ - void *pool = objc_autoreleasePoolPush(); - OFString *old = _percentEncodedPath; - - _percentEncodedPath = [[path - stringByAddingPercentEncodingWithAllowedCharacters: - [OFCharacterSet URIPathAllowedCharacterSet]] copy]; - - [old release]; - - objc_autoreleasePoolPop(pool); -} - -- (void)setPercentEncodedPath: (OFString *)percentEncodedPath -{ - OFString *old; - - OFURIVerifyIsEscaped(percentEncodedPath, - [OFCharacterSet URIPathAllowedCharacterSet], true); - - old = _percentEncodedPath; - _percentEncodedPath = [percentEncodedPath copy]; - [old release]; -} - -- (void)setPathComponents: (OFArray *)components -{ - void *pool = objc_autoreleasePoolPush(); - - if (components.count == 0) - @throw [OFInvalidFormatException exception]; - - if ([components.firstObject isEqual: @"/"]) { - OFMutableArray *mutComponents = - [[components mutableCopy] autorelease]; - [mutComponents replaceObjectAtIndex: 0 withObject: @""]; - components = mutComponents; - } - - self.path = [components componentsJoinedByString: @"/"]; - - objc_autoreleasePoolPop(pool); -} - -- (void)setQuery: (OFString *)query -{ - void *pool = objc_autoreleasePoolPush(); - OFString *old = _percentEncodedQuery; - - _percentEncodedQuery = [[query - stringByAddingPercentEncodingWithAllowedCharacters: - [OFCharacterSet URIQueryAllowedCharacterSet]] copy]; - - [old release]; - - objc_autoreleasePoolPop(pool); -} - -- (void)setPercentEncodedQuery: (OFString *)percentEncodedQuery -{ - OFString *old; - - if (percentEncodedQuery != nil) - OFURIVerifyIsEscaped(percentEncodedQuery, - [OFCharacterSet URIQueryAllowedCharacterSet], true); - - old = _percentEncodedQuery; - _percentEncodedQuery = [percentEncodedQuery copy]; - [old release]; -} - -- (void)setQueryItems: - (OFArray OF_GENERIC(OFPair OF_GENERIC(OFString *, OFString *) *) *) - queryItems -{ - void *pool; - OFMutableString *percentEncodedQuery; - OFCharacterSet *characterSet; - OFString *old; - - if (queryItems == nil) { - [_percentEncodedQuery release]; - _percentEncodedQuery = nil; - return; - } - - pool = objc_autoreleasePoolPush(); - percentEncodedQuery = [OFMutableString string]; - characterSet = [OFCharacterSet URIQueryKeyValueAllowedCharacterSet]; - - for (OFPair OF_GENERIC(OFString *, OFString *) *item in queryItems) { - OFString *key = [item.firstObject - stringByAddingPercentEncodingWithAllowedCharacters: - characterSet]; - OFString *value = [item.secondObject - stringByAddingPercentEncodingWithAllowedCharacters: - characterSet]; - - if (percentEncodedQuery.length > 0) - [percentEncodedQuery appendString: @"&"]; - - [percentEncodedQuery appendFormat: @"%@=%@", key, value]; - } - - old = _percentEncodedQuery; - _percentEncodedQuery = [percentEncodedQuery copy]; - [old release]; - - objc_autoreleasePoolPop(pool); -} - -- (void)setFragment: (OFString *)fragment -{ - void *pool = objc_autoreleasePoolPush(); - OFString *old = _percentEncodedFragment; - - _percentEncodedFragment = [[fragment - stringByAddingPercentEncodingWithAllowedCharacters: - [OFCharacterSet URIFragmentAllowedCharacterSet]] copy]; - - [old release]; - - objc_autoreleasePoolPop(pool); -} - -- (void)setPercentEncodedFragment: (OFString *)percentEncodedFragment -{ - OFString *old; - - if (percentEncodedFragment != nil) - OFURIVerifyIsEscaped(percentEncodedFragment, - [OFCharacterSet URIFragmentAllowedCharacterSet], true); - - old = _percentEncodedFragment; - _percentEncodedFragment = [percentEncodedFragment copy]; - [old release]; -} - -- (id)copy -{ - OFMutableURI *copy = [self mutableCopy]; - - [copy makeImmutable]; - - return copy; -} - -- (void)appendPathComponent: (OFString *)component -{ - [self appendPathComponent: component isDirectory: false]; - -#ifdef OF_HAVE_FILES - if ([_scheme isEqual: @"file"] && - ![_percentEncodedPath hasSuffix: @"/"] && - [[OFFileManager defaultManager] directoryExistsAtURI: self]) { - void *pool = objc_autoreleasePoolPush(); - OFString *path = [_percentEncodedPath - stringByAppendingString: @"/"]; - - [_percentEncodedPath release]; - _percentEncodedPath = [path retain]; - - objc_autoreleasePoolPop(pool); - } -#endif -} - -- (void)appendPathComponent: (OFString *)component - isDirectory: (bool)isDirectory -{ - void *pool; - OFString *path; - - if ([component isEqual: @"/"] && [_percentEncodedPath hasSuffix: @"/"]) - return; - - pool = objc_autoreleasePoolPush(); - component = [component - stringByAddingPercentEncodingWithAllowedCharacters: - [OFCharacterSet URIPathAllowedCharacterSet]]; - -#if defined(OF_WINDOWS) || defined(OF_MSDOS) - if ([_percentEncodedPath hasSuffix: @"/"] || - ([_scheme isEqual: @"file"] && - [_percentEncodedPath hasSuffix: @":"])) -#else - if ([_percentEncodedPath hasSuffix: @"/"]) -#endif - path = [_percentEncodedPath stringByAppendingString: component]; - else - path = [_percentEncodedPath - stringByAppendingFormat: @"/%@", component]; - - if (isDirectory && ![path hasSuffix: @"/"]) - path = [path stringByAppendingString: @"/"]; - - [_percentEncodedPath release]; - _percentEncodedPath = [path retain]; - - objc_autoreleasePoolPop(pool); -} - -- (void)standardizePath -{ - void *pool = objc_autoreleasePoolPush(); - OFMutableArray OF_GENERIC(OFString *) *array; - bool done = false, startsWithEmpty, endsWithEmpty; - OFString *path; - - array = [[[_percentEncodedPath - componentsSeparatedByString: @"/"] mutableCopy] autorelease]; - - endsWithEmpty = ([array.lastObject length] == 0); - startsWithEmpty = ([array.firstObject length] == 0); - - while (!done) { - size_t length = array.count; - - done = true; - - for (size_t i = 0; i < length; i++) { - OFString *current = [array objectAtIndex: i]; - OFString *parent = - (i > 0 ? [array objectAtIndex: i - 1] : nil); - - if ([current isEqual: @"."] || current.length == 0) { - [array removeObjectAtIndex: i]; - - done = false; - break; - } - - if ([current isEqual: @".."] && parent != nil && - ![parent isEqual: @".."]) { - [array removeObjectsInRange: - OFMakeRange(i - 1, 2)]; - - done = false; - break; - } - } - } - - if (startsWithEmpty) - [array insertObject: @"" atIndex: 0]; - if (endsWithEmpty) - [array addObject: @""]; - - path = [array componentsJoinedByString: @"/"]; - if (startsWithEmpty && path.length == 0) - path = @"/"; - - self.percentEncodedPath = path; - - objc_autoreleasePoolPop(pool); -} - -- (void)makeImmutable -{ - object_setClass(self, [OFURI class]); -} -@end Index: src/OFMutableUTF8String.h ================================================================== --- src/OFMutableUTF8String.h +++ src/OFMutableUTF8String.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,11 +16,10 @@ #include "config.h" #include #include #include -#include #import "OFMutableUTF8String.h" #import "OFASPrintF.h" #import "OFString.h" #import "OFUTF8String.h" @@ -77,11 +76,11 @@ if (!_s->isUTF8) { uint8_t t; const OFUnichar *const *table; - assert(startTableSize >= 1 && middleTableSize >= 1); + OFAssert(startTableSize >= 1 && middleTableSize >= 1); _s->hasHash = false; for (i = 0; i < _s->cStringLength; i++) { if (isStart) @@ -171,11 +170,11 @@ @throw [OFInvalidEncodingException exception]; } j += d; } - assert(j == newCStringLength); + OFAssert(j == newCStringLength); newCString[j] = 0; OFFreeMemory(unicodeString); OFFreeMemory(_s->cString); _s->hasHash = false; Index: src/OFMutableZIPArchiveEntry.h ================================================================== --- src/OFMutableZIPArchiveEntry.h +++ src/OFMutableZIPArchiveEntry.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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/OFNonretainedObjectValue.h Index: src/OFNonretainedObjectValue.h ================================================================== --- src/OFNonretainedObjectValue.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (c) 2008-2022 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#import "OFValue.h" - -OF_ASSUME_NONNULL_BEGIN - -@interface OFNonretainedObjectValue: OFValue -{ - id _object; -} - -- (instancetype)initWithNonretainedObject: (id)object; -@end - -OF_ASSUME_NONNULL_END DELETED src/OFNonretainedObjectValue.m Index: src/OFNonretainedObjectValue.m ================================================================== --- src/OFNonretainedObjectValue.m +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2008-2022 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#import "OFNonretainedObjectValue.h" -#import "OFMethodSignature.h" - -#import "OFOutOfRangeException.h" - -@implementation OFNonretainedObjectValue -@synthesize nonretainedObjectValue = _object; - -- (instancetype)initWithNonretainedObject: (id)object -{ - self = [super init]; - - _object = object; - - return self; -} - -- (const char *)objCType -{ - return @encode(id); -} - -- (void)getValue: (void *)value size: (size_t)size -{ - if (size != sizeof(_object)) - @throw [OFOutOfRangeException exception]; - - memcpy(value, &_object, sizeof(_object)); -} - -- (void *)pointerValue -{ - return _object; -} -@end Index: src/OFNotification.h ================================================================== --- src/OFNotification.h +++ src/OFNotification.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFNotification.m ================================================================== --- src/OFNotification.m +++ src/OFNotification.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFNotificationCenter.h ================================================================== --- src/OFNotificationCenter.h +++ src/OFNotificationCenter.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,11 +20,10 @@ @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. * @@ -62,12 +61,12 @@ /** * @brief Adds an observer for the specified notification and object. * * @param observer The object that should receive notifications * @param selector The selector to call on the observer on notifications. The - * method must take exactly one object of type @ref - * OFNotification. + * method must take exactly one object of type + * @ref OFNotification. * @param name The name of the notification to observe * @param object The object that should be sending the notification, or `nil` * if the object should be ignored to determine what * notifications to deliver */ @@ -101,22 +100,21 @@ * if the object should be ignored to determine what * notifications to deliver * @param block The block to handle notifications * @return An opaque object to remove the observer again */ -- (OFNotificationCenterHandle *) - addObserverForName: (OFNotificationName)name - object: (nullable id)object - usingBlock: (OFNotificationCenterBlock)block; +- (id)addObserverForName: (OFNotificationName)name + object: (nullable id)object + usingBlock: (OFNotificationCenterBlock)block; /** * @brief Removes an observer. The specified observer must be one returned by * @ref addObserver:selector:name:object:. * * @param observer The object that was returned when adding the observer */ -- (void)removeObserver: (OFNotificationCenterHandle *)observer; +- (void)removeObserver: (id)observer; #endif /** * @brief Posts the specified notification. * Index: src/OFNotificationCenter.m ================================================================== --- src/OFNotificationCenter.m +++ src/OFNotificationCenter.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -67,11 +67,11 @@ @try { void *pool = objc_autoreleasePoolPush(); _name = [name copy]; - _observer = [observer retain]; + _observer = observer; _selector = selector; _object = [object retain]; _selectorHash = [[OFString stringWithUTF8String: sel_getName(_selector)] hash]; @@ -106,11 +106,10 @@ #endif - (void)dealloc { [_name release]; - [_observer release]; [_object release]; #ifdef OF_HAVE_BLOCKS [_block release]; #endif @@ -245,14 +244,13 @@ objc_autoreleasePoolPop(pool); } #ifdef OF_HAVE_BLOCKS -- (OFNotificationCenterHandle *) - addObserverForName: (OFNotificationName)name - object: (id)object - usingBlock: (OFNotificationCenterBlock)block +- (id)addObserverForName: (OFNotificationName)name + object: (id)object + usingBlock: (OFNotificationCenterBlock)block { void *pool = objc_autoreleasePoolPush(); OFNotificationCenterHandle *handle = [[[OFNotificationCenterHandle alloc] initWithName: name object: object @@ -267,13 +265,20 @@ return [handle autorelease]; } #endif -- (void)removeObserver: (OFNotificationCenterHandle *)handle +- (void)removeObserver: (id)handle_ { - void *pool = objc_autoreleasePoolPush(); + OFNotificationCenterHandle *handle; + void *pool; + + if (![handle_ isKindOfClass: [OFNotificationCenterHandle class]]) + @throw [OFInvalidArgumentException exception]; + + handle = handle_; + pool = objc_autoreleasePoolPush(); /* {} required to avoid -Wmisleading-indentation false positive. */ if (![handle isKindOfClass: [OFNotificationCenterHandle class]]) { @throw [OFInvalidArgumentException exception]; } @@ -376,24 +381,7 @@ objc_autoreleasePoolPop(pool); } @end @implementation OFDefaultNotificationCenter -- (instancetype)autorelease -{ - return self; -} - -- (instancetype)retain -{ - return self; -} - -- (void)release -{ -} - -- (unsigned int)retainCount -{ - return OFMaxRetainCount; -} +OF_SINGLETON_METHODS @end Index: src/OFNull.h ================================================================== --- src/OFNull.h +++ src/OFNull.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,21 +15,20 @@ #import "OFObject.h" #import "OFASN1DERRepresentation.h" #import "OFJSONRepresentation.h" #import "OFMessagePackRepresentation.h" -#import "OFSerialization.h" OF_ASSUME_NONNULL_BEGIN /** * @class OFNull OFNull.h ObjFW/OFNull.h * * @brief A class for representing null values in collections. */ OF_SUBCLASSING_RESTRICTED -@interface OFNull: OFObject /** * @brief Returns an OFNull singleton. * * @return An OFNull singleton Index: src/OFNull.m ================================================================== --- src/OFNull.m +++ src/OFNull.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,13 +14,12 @@ */ #include "config.h" #import "OFNull.h" -#import "OFString.h" -#import "OFXMLElement.h" #import "OFData.h" +#import "OFString.h" #import "OFInvalidArgumentException.h" @interface OFNull () - (OFString *) @@ -39,27 +38,10 @@ + (OFNull *)null { return null; } -- (instancetype)initWithSerialization: (OFXMLElement *)element -{ - void *pool; - - [self release]; - - pool = objc_autoreleasePoolPush(); - - if (![element.name isEqual: self.className] || - ![element.namespace isEqual: OFSerializationNS]) - @throw [OFInvalidArgumentException exception]; - - objc_autoreleasePoolPop(pool); - - return [OFNull null]; -} - - (OFString *)description { return @""; } @@ -66,25 +48,10 @@ - (id)copy { return self; } -- (OFXMLElement *)XMLElementBySerializing -{ - void *pool = objc_autoreleasePoolPush(); - OFXMLElement *element; - - element = [OFXMLElement elementWithName: self.className - namespace: OFSerializationNS]; - - [element retain]; - - objc_autoreleasePoolPop(pool); - - return [element autorelease]; -} - - (OFString *)JSONRepresentation { return [self of_JSONRepresentationWithOptions: 0 depth: 0]; } @@ -111,29 +78,7 @@ { const unsigned char bytes[] = { OFASN1TagNumberNull, 0 }; return [OFData dataWithItems: bytes count: sizeof(bytes)]; } -- (instancetype)autorelease -{ - return self; -} - -- (instancetype)retain -{ - return self; -} - -- (void)release -{ -} - -- (unsigned int)retainCount -{ - return OFMaxRetainCount; -} - -- (void)dealloc -{ - OF_DEALLOC_UNSUPPORTED -} +OF_SINGLETON_METHODS @end Index: src/OFNumber.h ================================================================== --- src/OFNumber.h +++ src/OFNumber.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,11 +26,10 @@ # include #endif #import "OFJSONRepresentation.h" #import "OFMessagePackRepresentation.h" -#import "OFSerialization.h" #import "OFValue.h" OF_ASSUME_NONNULL_BEGIN /** @file */ @@ -38,24 +37,12 @@ /** * @class OFNumber OFNumber.h ObjFW/OFNumber.h * * @brief Provides a way to store a number in an object. */ -#ifndef OF_NUMBER_M -OF_SUBCLASSING_RESTRICTED -#endif -@interface OFNumber: OFValue -{ - union { - double float_; - long long signed_; - unsigned long long unsigned_; - } _value; - const char *_typeEncoding; -} - +@interface OFNumber: OFValue /** * @brief The OFNumber as a `bool`. */ @property (readonly, nonatomic) bool boolValue; @@ -122,12 +109,10 @@ /** * @brief The OFNumber as a string. */ @property (readonly, nonatomic) OFString *stringValue; -+ (instancetype)valueWithBytes: (const void *)bytes - objCType: (const char *)objCType OF_UNAVAILABLE; + (instancetype)valueWithPointer: (const void *)pointer OF_UNAVAILABLE; + (instancetype)valueWithNonretainedObject: (id)object OF_UNAVAILABLE; + (instancetype)valueWithRange: (OFRange)range OF_UNAVAILABLE; + (instancetype)valueWithPoint: (OFPoint)point OF_UNAVAILABLE; + (instancetype)valueWithSize: (OFSize)size OF_UNAVAILABLE; @@ -235,14 +220,10 @@ * @param value The `double` value which the OFNumber should contain * @return A new autoreleased OFNumber */ + (instancetype)numberWithDouble: (double)value; -- (instancetype)init OF_UNAVAILABLE; -- (instancetype)initWithBytes: (const void *)bytes - objCType: (const char *)objCType OF_UNAVAILABLE; - /** * @brief Initializes an already allocated OFNumber with the specified `bool`. * * @param value The `bool` value which the OFNumber should contain * @return An initialized OFNumber Index: src/OFNumber.m ================================================================== --- src/OFNumber.m +++ src/OFNumber.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,70 +11,47 @@ * Public License, either version 2 or 3, which can be found in the file * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this * file. */ -#define OF_NUMBER_M - #include "config.h" #include #import "OFNumber.h" -#import "OFString.h" -#import "OFXMLElement.h" -#import "OFXMLAttribute.h" +#import "OFConcreteNumber.h" #import "OFData.h" +#import "OFString.h" +#import "OFTaggedPointerNumber.h" #import "OFInvalidArgumentException.h" #import "OFInvalidFormatException.h" #import "OFOutOfRangeException.h" @interface OFNumber () -+ (instancetype)of_alloc; - (OFString *) of_JSONRepresentationWithOptions: (OFJSONRepresentationOptions)options depth: (size_t)depth; @end -@interface OFNumberPlaceholder: OFNumber -@end - -@interface OFNumberSingleton: OFNumber -@end - -#ifdef OF_OBJFW_RUNTIME -enum Tag { - tagChar, - tagShort, - tagInt, - tagLong, - tagLongLong, - tagUnsignedChar, - tagUnsignedShort, - tagUnsignedInt, - tagUnsignedLong, - tagUnsignedLongLong, -}; -static const uint_fast8_t tagBits = 4; -static const uintptr_t tagMask = 0xF; - -@interface OFTaggedPointerNumber: OFNumberSingleton -@end -#endif +@interface OFPlaceholderNumber: OFNumber +@end + +@interface OFConcreteNumberSingleton: OFConcreteNumber +@end static struct { Class isa; } placeholder; -#define SINGLETON(var, sel, val) \ - static OFNumberSingleton *var; \ - \ - static void \ - var##Init(void) \ - { \ - var = [[OFNumberSingleton alloc] sel val]; \ +#define SINGLETON(var, sel, val) \ + static OFConcreteNumberSingleton *var; \ + \ + static void \ + var##Init(void) \ + { \ + var = [[OFConcreteNumberSingleton alloc] sel val]; \ } SINGLETON(falseNumber, initWithBool:, false) SINGLETON(trueNumber, initWithBool:, true) SINGLETON(charZeroNumber, initWithChar:, 0) SINGLETON(shortZeroNumber, initWithShort:, 0) @@ -88,28 +65,19 @@ SINGLETON(unsignedLongLongZeroNumber, initWithUnsignedLongLong:, 0) SINGLETON(floatZeroNumber, initWithFloat:, 0) SINGLETON(doubleZeroNumber, initWithDouble:, 0) #undef SINGLETON -#ifdef OF_OBJFW_RUNTIME -static int numberTag; -#endif - static bool isUnsigned(OFNumber *number) { switch (*number.objCType) { case 'B': - return true; case 'C': - return true; case 'S': - return true; case 'I': - return true; case 'L': - return true; case 'Q': return true; default: return false; } @@ -118,17 +86,13 @@ static bool isSigned(OFNumber *number) { switch (*number.objCType) { case 'c': - return true; case 's': - return true; case 'i': - return true; case 'l': - return true; case 'q': return true; default: return false; } @@ -137,19 +101,18 @@ static bool isFloat(OFNumber *number) { switch (*number.objCType) { case 'f': - return true; case 'd': return true; default: return false; } } -@implementation OFNumberPlaceholder +@implementation OFPlaceholderNumber - (instancetype)initWithBool: (bool)value { if (value) { static OFOnceControl onceControl = OFOnceControlInitValue; OFOnce(&onceControl, trueNumberInit); @@ -170,192 +133,187 @@ if (value == 0) { static OFOnceControl onceControl = OFOnceControlInitValue; OFOnce(&onceControl, charZeroNumberInit); return (id)charZeroNumber; #ifdef OF_OBJFW_RUNTIME - } else if ((unsigned char)value <= (UINTPTR_MAX >> tagBits)) { - id ret = objc_createTaggedPointer(numberTag, - ((uintptr_t)(unsigned char)value << tagBits) | tagChar); + } else if ((unsigned char)value <= + (UINTPTR_MAX >> OFTaggedPointerNumberTagBits)) { + id ret = [OFTaggedPointerNumber numberWithChar: value]; if (ret != nil) return ret; #endif } - return (id)[[OFNumber of_alloc] initWithChar: value]; + return (id)[[OFConcreteNumber alloc] initWithChar: value]; } - (instancetype)initWithShort: (short)value { if (value == 0) { static OFOnceControl onceControl = OFOnceControlInitValue; OFOnce(&onceControl, shortZeroNumberInit); return (id)shortZeroNumber; #ifdef OF_OBJFW_RUNTIME - } else if ((unsigned short)value <= (UINTPTR_MAX >> tagBits)) { - id ret = objc_createTaggedPointer(numberTag, - ((uintptr_t)(unsigned short)value << tagBits) | tagShort); + } else if ((unsigned short)value <= + (UINTPTR_MAX >> OFTaggedPointerNumberTagBits)) { + id ret = [OFTaggedPointerNumber numberWithShort: value]; if (ret != nil) return ret; #endif } - return (id)[[OFNumber of_alloc] initWithShort: value]; + return (id)[[OFConcreteNumber alloc] initWithShort: value]; } - (instancetype)initWithInt: (int)value { if (value == 0) { static OFOnceControl onceControl = OFOnceControlInitValue; OFOnce(&onceControl, intZeroNumberInit); return (id)intZeroNumber; #ifdef OF_OBJFW_RUNTIME - } else if ((unsigned int)value <= (UINTPTR_MAX >> tagBits)) { - id ret = objc_createTaggedPointer(numberTag, - ((uintptr_t)(unsigned int)value << tagBits) | tagInt); + } else if ((unsigned int)value <= + (UINTPTR_MAX >> OFTaggedPointerNumberTagBits)) { + id ret = [OFTaggedPointerNumber numberWithInt: value]; if (ret != nil) return ret; #endif } - return (id)[[OFNumber of_alloc] initWithInt: value]; + return (id)[[OFConcreteNumber alloc] initWithInt: value]; } - (instancetype)initWithLong: (long)value { if (value == 0) { static OFOnceControl onceControl = OFOnceControlInitValue; OFOnce(&onceControl, longZeroNumberInit); return (id)longZeroNumber; #ifdef OF_OBJFW_RUNTIME - } else if ((unsigned long)value <= (UINTPTR_MAX >> tagBits)) { - id ret = objc_createTaggedPointer(numberTag, - ((uintptr_t)(unsigned long)value << tagBits) | tagLong); + } else if ((unsigned long)value <= + (UINTPTR_MAX >> OFTaggedPointerNumberTagBits)) { + id ret = [OFTaggedPointerNumber numberWithLong: value]; if (ret != nil) return ret; #endif } - return (id)[[OFNumber of_alloc] initWithLong: value]; + return (id)[[OFConcreteNumber alloc] initWithLong: value]; } - (instancetype)initWithLongLong: (long long)value { if (value == 0) { static OFOnceControl onceControl = OFOnceControlInitValue; OFOnce(&onceControl, longLongZeroNumberInit); return (id)longLongZeroNumber; #ifdef OF_OBJFW_RUNTIME - } else if ((unsigned long long)value <= (UINTPTR_MAX >> tagBits)) { - id ret = objc_createTaggedPointer(numberTag, - ((uintptr_t)(unsigned long long)value << tagBits) | - tagLongLong); + } else if ((unsigned long long)value <= + (UINTPTR_MAX >> OFTaggedPointerNumberTagBits)) { + id ret = [OFTaggedPointerNumber numberWithLongLong: value]; if (ret != nil) return ret; #endif } - return (id)[[OFNumber of_alloc] initWithLongLong: value]; + return (id)[[OFConcreteNumber alloc] initWithLongLong: value]; } - (instancetype)initWithUnsignedChar: (unsigned char)value { if (value == 0) { static OFOnceControl onceControl = OFOnceControlInitValue; OFOnce(&onceControl, unsignedCharZeroNumberInit); return (id)unsignedCharZeroNumber; #ifdef OF_OBJFW_RUNTIME - } else if (value <= (UINTPTR_MAX >> tagBits)) { - id ret = objc_createTaggedPointer(numberTag, - ((uintptr_t)value << tagBits) | tagUnsignedChar); + } else if (value <= (UINTPTR_MAX >> OFTaggedPointerNumberTagBits)) { + id ret = [OFTaggedPointerNumber numberWithUnsignedChar: value]; if (ret != nil) return ret; #endif } - return (id)[[OFNumber of_alloc] initWithUnsignedChar: value]; + return (id)[[OFConcreteNumber alloc] initWithUnsignedChar: value]; } - (instancetype)initWithUnsignedShort: (unsigned short)value { if (value == 0) { static OFOnceControl onceControl = OFOnceControlInitValue; OFOnce(&onceControl, unsignedShortZeroNumberInit); return (id)unsignedShortZeroNumber; #ifdef OF_OBJFW_RUNTIME - } else if (value <= (UINTPTR_MAX >> tagBits)) { - id ret = objc_createTaggedPointer(numberTag, - ((uintptr_t)value << tagBits) | tagUnsignedShort); + } else if (value <= (UINTPTR_MAX >> OFTaggedPointerNumberTagBits)) { + id ret = [OFTaggedPointerNumber numberWithUnsignedShort: value]; if (ret != nil) return ret; #endif } - return (id)[[OFNumber of_alloc] initWithUnsignedShort: value]; + return (id)[[OFConcreteNumber alloc] initWithUnsignedShort: value]; } - (instancetype)initWithUnsignedInt: (unsigned int)value { if (value == 0) { static OFOnceControl onceControl = OFOnceControlInitValue; OFOnce(&onceControl, unsignedIntZeroNumberInit); return (id)unsignedIntZeroNumber; #ifdef OF_OBJFW_RUNTIME - } else if (value <= (UINTPTR_MAX >> tagBits)) { - id ret = objc_createTaggedPointer(numberTag, - ((uintptr_t)value << tagBits) | tagUnsignedInt); + } else if (value <= (UINTPTR_MAX >> OFTaggedPointerNumberTagBits)) { + id ret = [OFTaggedPointerNumber numberWithUnsignedInt: value]; if (ret != nil) return ret; #endif } - return (id)[[OFNumber of_alloc] initWithUnsignedInt: value]; + return (id)[[OFConcreteNumber alloc] initWithUnsignedInt: value]; } - (instancetype)initWithUnsignedLong: (unsigned long)value { if (value == 0) { static OFOnceControl onceControl = OFOnceControlInitValue; OFOnce(&onceControl, unsignedLongZeroNumberInit); return (id)unsignedLongZeroNumber; #ifdef OF_OBJFW_RUNTIME - } else if (value <= (UINTPTR_MAX >> tagBits)) { - id ret = objc_createTaggedPointer(numberTag, - ((uintptr_t)value << tagBits) | tagUnsignedLong); + } else if (value <= (UINTPTR_MAX >> OFTaggedPointerNumberTagBits)) { + id ret = [OFTaggedPointerNumber numberWithUnsignedLong: value]; if (ret != nil) return ret; #endif } - return (id)[[OFNumber of_alloc] initWithUnsignedLong: value]; + return (id)[[OFConcreteNumber alloc] initWithUnsignedLong: value]; } - (instancetype)initWithUnsignedLongLong: (unsigned long long)value { if (value == 0) { static OFOnceControl onceControl = OFOnceControlInitValue; OFOnce(&onceControl, unsignedLongLongZeroNumberInit); return (id)unsignedLongLongZeroNumber; #ifdef OF_OBJFW_RUNTIME - } else if (value <= (UINTPTR_MAX >> tagBits)) { - id ret = objc_createTaggedPointer(numberTag, - ((uintptr_t)value << tagBits) | tagUnsignedLongLong); + } else if (value <= (UINTPTR_MAX >> OFTaggedPointerNumberTagBits)) { + id ret = [OFTaggedPointerNumber + numberWithUnsignedLongLong: value]; if (ret != nil) return ret; #endif } - return (id)[[OFNumber of_alloc] initWithUnsignedLongLong: value]; + return (id)[[OFConcreteNumber alloc] initWithUnsignedLongLong: value]; } - (instancetype)initWithFloat: (float)value { if (value == 0) { @@ -362,11 +320,11 @@ static OFOnceControl onceControl = OFOnceControlInitValue; OFOnce(&onceControl, floatZeroNumberInit); return (id)floatZeroNumber; } - return (id)[[OFNumber of_alloc] initWithFloat: value]; + return (id)[[OFConcreteNumber alloc] initWithFloat: value]; } - (instancetype)initWithDouble: (double)value { if (value == 0) { @@ -373,137 +331,28 @@ static OFOnceControl onceControl = OFOnceControlInitValue; OFOnce(&onceControl, doubleZeroNumberInit); return (id)doubleZeroNumber; } - return (id)[[OFNumber of_alloc] initWithDouble: value]; -} - -- (instancetype)initWithSerialization: (OFXMLElement *)element -{ - return (id)[[OFNumber of_alloc] initWithSerialization: element]; + return (id)[[OFConcreteNumber alloc] initWithDouble: value]; } #ifdef __clang__ # pragma clang diagnostic pop #endif -@end - -@implementation OFNumberSingleton -- (instancetype)autorelease -{ - return self; -} - -- (instancetype)retain -{ - return self; -} - -- (void)release -{ -} - -- (unsigned int)retainCount -{ - return OFMaxRetainCount; -} -@end - -#ifdef OF_OBJFW_RUNTIME -@implementation OFTaggedPointerNumber -- (const char *)objCType -{ - uintptr_t value = object_getTaggedPointerValue(self); - - switch (value & tagMask) { - case tagChar: - return @encode(signed char); - case tagShort: - return @encode(short); - case tagInt: - return @encode(int); - case tagLong: - return @encode(long); - case tagLongLong: - return @encode(long long); - case tagUnsignedChar: - return @encode(unsigned char); - case tagUnsignedShort: - return @encode(unsigned short); - case tagUnsignedInt: - return @encode(unsigned int); - case tagUnsignedLong: - return @encode(unsigned long); - case tagUnsignedLongLong: - return @encode(unsigned long long); - default: - @throw [OFInvalidArgumentException exception]; - } -} - -# define RETURN_VALUE \ - uintptr_t value = object_getTaggedPointerValue(self); \ - \ - switch (value & tagMask) { \ - case tagChar: \ - return (signed char)(unsigned char)(value >> tagBits); \ - case tagShort: \ - return (short)(unsigned short)(value >> tagBits); \ - case tagInt: \ - return (int)(unsigned int)(value >> tagBits); \ - case tagLong: \ - return (long)(unsigned long)(value >> tagBits); \ - case tagLongLong: \ - return (long long)(unsigned long long)(value >> tagBits); \ - case tagUnsignedChar: \ - return (unsigned char)(value >> tagBits); \ - case tagUnsignedShort: \ - return (unsigned short)(value >> tagBits); \ - case tagUnsignedInt: \ - return (unsigned int)(value >> tagBits); \ - case tagUnsignedLong: \ - return (unsigned long)(value >> tagBits); \ - case tagUnsignedLongLong: \ - return (unsigned long long)(value >> tagBits); \ - default: \ - @throw [OFInvalidArgumentException exception]; \ - } -- (long long)longLongValue -{ - RETURN_VALUE -} - -- (unsigned long long)unsignedLongLongValue -{ - RETURN_VALUE -} - -- (double)doubleValue -{ - RETURN_VALUE -} -@end -# undef RETURN_VALUE -#endif + +OF_SINGLETON_METHODS +@end + +@implementation OFConcreteNumberSingleton +OF_SINGLETON_METHODS +@end @implementation OFNumber + (void)initialize { - if (self != [OFNumber class]) - return; - - placeholder.isa = [OFNumberPlaceholder class]; - -#ifdef OF_OBJFW_RUNTIME - numberTag = - objc_registerTaggedPointerClass([OFTaggedPointerNumber class]); -#endif -} - -+ (instancetype)of_alloc -{ - return [super alloc]; + if (self == [OFNumber class]) + object_setClass((id)&placeholder, [OFPlaceholderNumber class]); } + (instancetype)alloc { if (self == [OFNumber class]) @@ -510,16 +359,10 @@ 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 } @@ -611,300 +454,89 @@ + (instancetype)numberWithDouble: (double)value { return [[[self alloc] initWithDouble: value] autorelease]; } -- (instancetype)init -{ - OF_INVALID_INIT_METHOD -} - -- (instancetype)initWithBytes: (const void *)bytes - objCType: (const char *)objCType -{ - OF_INVALID_INIT_METHOD -} - - (instancetype)initWithBool: (bool)value { - self = [super init]; - - _value.unsigned_ = value; - _typeEncoding = @encode(bool); - - return self; + return [self initWithBytes: &value objCType: @encode(bool)]; } - (instancetype)initWithChar: (signed char)value { - self = [super init]; - - _value.signed_ = value; - _typeEncoding = @encode(signed char); - - return self; + return [self initWithBytes: &value objCType: @encode(signed char)]; } - (instancetype)initWithShort: (short)value { - self = [super init]; - - _value.signed_ = value; - _typeEncoding = @encode(short); - - return self; + return [self initWithBytes: &value objCType: @encode(short)]; } - (instancetype)initWithInt: (int)value { - self = [super init]; - - _value.signed_ = value; - _typeEncoding = @encode(int); - - return self; + return [self initWithBytes: &value objCType: @encode(int)]; } - (instancetype)initWithLong: (long)value { - self = [super init]; - - _value.signed_ = value; - _typeEncoding = @encode(long); - - return self; + return [self initWithBytes: &value objCType: @encode(long)]; } - (instancetype)initWithLongLong: (long long)value { - self = [super init]; - - _value.signed_ = value; - _typeEncoding = @encode(long long); - - return self; + return [self initWithBytes: &value objCType: @encode(long long)]; } - (instancetype)initWithUnsignedChar: (unsigned char)value { - self = [super init]; - - _value.unsigned_ = value; - _typeEncoding = @encode(unsigned long); - - return self; + return [self initWithBytes: &value objCType: @encode(unsigned char)]; } - (instancetype)initWithUnsignedShort: (unsigned short)value { - self = [super init]; - - _value.unsigned_ = value; - _typeEncoding = @encode(unsigned short); - - return self; + return [self initWithBytes: &value objCType: @encode(unsigned short)]; } - (instancetype)initWithUnsignedInt: (unsigned int)value { - self = [super init]; - - _value.unsigned_ = value; - _typeEncoding = @encode(unsigned int); - - return self; + return [self initWithBytes: &value objCType: @encode(unsigned int)]; } - (instancetype)initWithUnsignedLong: (unsigned long)value { - self = [super init]; - - _value.unsigned_ = value; - _typeEncoding = @encode(unsigned long); - - return self; + return [self initWithBytes: &value objCType: @encode(unsigned long)]; } - (instancetype)initWithUnsignedLongLong: (unsigned long long)value { - self = [super init]; - - _value.unsigned_ = value; - _typeEncoding = @encode(unsigned long long); - - return self; -} - -- (instancetype)initWithPtrDiff: (ptrdiff_t)value -{ - self = [super init]; - - _value.signed_ = value; - _typeEncoding = @encode(ptrdiff_t); - - return self; -} - -- (instancetype)initWithIntPtr: (intptr_t)value -{ - self = [super init]; - - _value.signed_ = value; - _typeEncoding = @encode(intptr_t); - - return self; -} - -- (instancetype)initWithUIntPtr: (uintptr_t)value -{ - self = [super init]; - - _value.unsigned_ = value; - _typeEncoding = @encode(uintptr_t); - - return self; + return [self initWithBytes: &value + objCType: @encode(unsigned long long)]; } - (instancetype)initWithFloat: (float)value { - self = [super init]; - - _value.float_ = value; - _typeEncoding = @encode(float); - - return self; + return [self initWithBytes: &value objCType: @encode(float)]; } - (instancetype)initWithDouble: (double)value { - self = [super init]; - - _value.float_ = value; - _typeEncoding = @encode(double); - - return self; -} - -- (instancetype)initWithSerialization: (OFXMLElement *)element -{ - self = [super init]; - - @try { - void *pool = objc_autoreleasePoolPush(); - OFString *typeString; - - if (![element.name isEqual: @"OFNumber"] || - ![element.namespace isEqual: OFSerializationNS]) - @throw [OFInvalidArgumentException exception]; - - typeString = [element attributeForName: @"type"].stringValue; - - if ([typeString isEqual: @"bool"]) { - OFString *stringValue = element.stringValue; - if ([stringValue isEqual: @"true"]) - self = [self initWithBool: true]; - else if ([stringValue isEqual: @"false"]) - self = [self initWithBool: false]; - else - @throw [OFInvalidArgumentException exception]; - } else if ([typeString isEqual: @"float"]) { - unsigned long long value = - [element unsignedLongLongValueWithBase: 16]; - - if (value > UINT64_MAX) - @throw [OFOutOfRangeException exception]; - - self = [self initWithDouble: OFFromBigEndianDouble( - OFRawUInt64ToDouble(OFToBigEndian64(value)))]; - } else if ([typeString isEqual: @"signed"]) - self = [self initWithLongLong: element.longLongValue]; - else if ([typeString isEqual: @"unsigned"]) - self = [self initWithUnsignedLongLong: - element.unsignedLongLongValue]; - else - @throw [OFInvalidArgumentException exception]; - - objc_autoreleasePoolPop(pool); - } @catch (id e) { - [self release]; - @throw e; - } - - return self; -} - -- (const char *)objCType -{ - return _typeEncoding; -} - -- (void)getValue: (void *)value size: (size_t)size -{ - switch (*self.objCType) { -#define CASE(enc, type, property) \ - case enc: { \ - type tmp = (type)self.property; \ - \ - if (size != sizeof(type)) \ - @throw [OFOutOfRangeException exception]; \ - \ - memcpy(value, &tmp, size); \ - break; \ - } - CASE('B', bool, unsignedLongLongValue) - CASE('c', signed char, longLongValue) - CASE('s', short, longLongValue) - CASE('i', int, longLongValue) - CASE('l', long, longLongValue) - CASE('q', long long, longLongValue) - CASE('C', unsigned char, unsignedLongLongValue) - CASE('S', unsigned short, unsignedLongLongValue) - CASE('I', unsigned int, unsignedLongLongValue) - CASE('L', unsigned long, unsignedLongLongValue) - CASE('Q', unsigned long long, unsignedLongLongValue) - CASE('f', float, doubleValue) - CASE('d', double, doubleValue) -#undef CASE - default: - @throw [OFInvalidFormatException exception]; - } + return [self initWithBytes: &value objCType: @encode(double)]; } - (long long)longLongValue { - if (isFloat(self)) - return _value.float_; - else if (isSigned(self)) - return _value.signed_; - else if (isUnsigned(self)) - return _value.unsigned_; - else - @throw [OFInvalidFormatException exception]; + OF_UNRECOGNIZED_SELECTOR } - (unsigned long long)unsignedLongLongValue { - if (isFloat(self)) - return _value.float_; - else if (isSigned(self)) - return _value.signed_; - else if (isUnsigned(self)) - return _value.unsigned_; - else - @throw [OFInvalidFormatException exception]; + OF_UNRECOGNIZED_SELECTOR } - (double)doubleValue { - if (isFloat(self)) - return _value.float_; - else if (isSigned(self)) - return _value.signed_; - else if (isUnsigned(self)) - return _value.unsigned_; - else - @throw [OFInvalidFormatException exception]; + OF_UNRECOGNIZED_SELECTOR } - (bool)boolValue { return (bool)self.unsignedLongLongValue; @@ -1064,11 +696,11 @@ return [self stringValue]; } - (OFString *)stringValue { - if (*self.objCType == 'B') + if (self.objCType[0] == 'B' && self.objCType[1] == '\0') return (self.boolValue ? @"true" : @"false"); if (isFloat(self)) return [OFString stringWithFormat: @"%g", self.doubleValue]; if (isSigned(self)) return [OFString stringWithFormat: @"%lld", self.longLongValue]; @@ -1077,42 +709,10 @@ self.unsignedLongLongValue]; @throw [OFInvalidFormatException exception]; } -- (OFXMLElement *)XMLElementBySerializing -{ - void *pool = objc_autoreleasePoolPush(); - OFXMLElement *element; - - element = [OFXMLElement elementWithName: @"OFNumber" - namespace: OFSerializationNS - stringValue: self.description]; - - if (*self.objCType == 'B') - [element addAttributeWithName: @"type" stringValue: @"bool"]; - else if (isFloat(self)) { - [element addAttributeWithName: @"type" stringValue: @"float"]; - element.stringValue = [OFString - stringWithFormat: @"%016" PRIx64, - OFFromBigEndian64(OFDoubleToRawUInt64(OFToBigEndianDouble( - self.doubleValue)))]; - } else if (isSigned(self)) - [element addAttributeWithName: @"type" stringValue: @"signed"]; - else if (isUnsigned(self)) - [element addAttributeWithName: @"type" - stringValue: @"unsigned"]; - else - @throw [OFInvalidFormatException exception]; - - [element retain]; - - objc_autoreleasePoolPop(pool); - - return [element autorelease]; -} - - (OFString *)JSONRepresentation { return [self of_JSONRepresentationWithOptions: 0 depth: 0]; } @@ -1126,11 +726,11 @@ of_JSONRepresentationWithOptions: (OFJSONRepresentationOptions)options depth: (size_t)depth { double doubleValue; - if (*self.objCType == 'B') + if (self.objCType[0] == 'B' && self.objCType[1] == '\0') return (self.boolValue ? @"true" : @"false"); doubleValue = self.doubleValue; if (isinf(doubleValue)) { if (options & OFJSONRepresentationOptionJSON5) { @@ -1147,10 +747,13 @@ - (OFData *)messagePackRepresentation { OFMutableData *data; const char *typeEncoding = self.objCType; + + if (typeEncoding[0] == '\0' || typeEncoding[1] != '\0') + @throw [OFInvalidFormatException exception]; if (*typeEncoding == 'B') { uint8_t type = (self.boolValue ? 0xC3 : 0xC2); data = [OFMutableData dataWithItems: &type count: 1]; } else if (*typeEncoding == 'f') { Index: src/OFObject+KeyValueCoding.h ================================================================== --- src/OFObject+KeyValueCoding.h +++ src/OFObject+KeyValueCoding.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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/OFObject+Serialization.h Index: src/OFObject+Serialization.h ================================================================== --- src/OFObject+Serialization.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2008-2022 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#import "OFObject.h" - -OF_ASSUME_NONNULL_BEGIN - -@class OFString; - -#ifdef __cplusplus -extern "C" { -#endif -extern int _OFObject_Serialization_reference; -#ifdef __cplusplus -} -#endif - -@interface OFObject (OFSerialization) -/** - * @brief The object serialized as a string. - */ -@property (readonly, nonatomic) OFString *stringBySerializing; -@end - -OF_ASSUME_NONNULL_END DELETED src/OFObject+Serialization.m Index: src/OFObject+Serialization.m ================================================================== --- src/OFObject+Serialization.m +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) 2008-2022 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 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 "OFObject.h" -#import "OFObject+Serialization.h" -#import "OFSerialization.h" -#import "OFString.h" -#import "OFXMLElement.h" - -int _OFObject_Serialization_reference; - -@implementation OFObject (Serialization) -- (OFString *)stringBySerializing -{ - void *pool; - OFXMLElement *element; - OFXMLElement *root; - OFString *ret; - - if (![self conformsToProtocol: @protocol(OFSerialization)]) { - [self doesNotRecognizeSelector: _cmd]; - abort(); - } - - pool = objc_autoreleasePoolPush(); - element = ((id )self).XMLElementBySerializing; - - root = [OFXMLElement elementWithName: @"serialization" - namespace: OFSerializationNS]; - [root addAttributeWithName: @"version" stringValue: @"1"]; - [root addChild: element]; - - ret = [@"\n" - stringByAppendingString: [root XMLStringWithIndentation: 2]]; - - [ret retain]; - - objc_autoreleasePoolPop(pool); - - return [ret autorelease]; -} -@end Index: src/OFObject.h ================================================================== --- src/OFObject.h +++ src/OFObject.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,13 +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. */ -#ifndef OBJFW_OF_OBJECT_H -#define OBJFW_OF_OBJECT_H - #include "objfw-defs.h" #ifndef __STDC_LIMIT_MACROS # define __STDC_LIMIT_MACROS #endif @@ -30,11 +27,11 @@ #include #include #include "macros.h" -#include "OFOnce.h" +#import "OFOnce.h" /* * Some versions of MinGW require to be included before * . Do this here to make sure this is always done in the correct * order, even if another header includes just . @@ -61,10 +58,21 @@ OFOrderedSame = 0, /** The left object is bigger than the right */ OFOrderedDescending = 1 } OFComparisonResult; +/** + * @brief A function to compare two objects. + * + * @param left The left object + * @param right The right object + * @param context Context passed along for comparing + * @return The order of the objects + */ +typedef OFComparisonResult (*OFCompareFunction)(id _Nonnull left, + id _Nonnull right, void *_Nullable context); + #ifdef OF_HAVE_BLOCKS /** * @brief A comparator to compare two objects. * * @param left The left object @@ -93,11 +101,11 @@ /** * @struct OFRange OFObject.h ObjFW/OFObject.h * * @brief A range. */ -typedef struct OF_BOXABLE { +typedef struct OF_BOXABLE OFRange { /** The start of the range */ size_t location; /** The length of the range */ size_t length; } OFRange; @@ -142,13 +150,13 @@ typedef double OFTimeInterval; /** * @struct OFPoint OFObject.h ObjFW/OFObject.h * - * @brief A point. + * @brief A point in 2D space. */ -typedef struct OF_BOXABLE { +typedef struct OF_BOXABLE OFPoint { /** The x coordinate of the point */ float x; /** The y coordinate of the point */ float y; } OFPoint; @@ -190,11 +198,11 @@ /** * @struct OFSize OFObject.h ObjFW/OFObject.h * * @brief A size. */ -typedef struct OF_BOXABLE { +typedef struct OF_BOXABLE OFSize { /** The width of the size */ float width; /** The height of the size */ float height; } OFSize; @@ -236,11 +244,11 @@ /** * @struct OFRect OFObject.h ObjFW/OFObject.h * * @brief A rectangle. */ -typedef struct OF_BOXABLE { +typedef struct OF_BOXABLE OFRect { /** The point from where the rectangle originates */ OFPoint origin; /** The size of the rectangle */ OFSize size; } OFRect; @@ -279,10 +287,120 @@ return false; if (!OFEqualSizes(rect1.size, rect2.size)) return false; + return true; +} + +/** + * @struct OFVector3D OFObject.h ObjFW/OFObject.h + * + * @brief A vector in 3D space. + */ +typedef struct OF_BOXABLE OFVector3D { + /** The x coordinate of the vector */ + float x; + /** The y coordinate of the vector */ + float y; + /** The z coordinate of the vector */ + float z; +} OFVector3D; + +/** + * @brief Creates a new OFVector3D. + * + * @param x The x coordinate of the vector + * @param y The x coordinate of the vector + * @param z The z coordinate of the vector + * @return An OFVector3D with the specified coordinates + */ +static OF_INLINE OFVector3D OF_CONST_FUNC +OFMakeVector3D(float x, float y, float z) +{ + OFVector3D vector = { x, y, z }; + + return vector; +} + +/** + * @brief Returns whether the two vectors are equal. + * + * @param vector1 The first vector for the comparison + * @param vector2 The second vectors for the comparison + * @return Whether the two vectors are equal + */ +static OF_INLINE bool +OFEqualVectors3D(OFVector3D vector1, OFVector3D vector2) +{ + if (vector1.x != vector2.x) + return false; + + if (vector1.y != vector2.y) + return false; + + if (vector1.z != vector2.z) + return false; + + return true; +} + +/** + * @struct OFVector4D OFObject.h ObjFW/OFObject.h + * + * @brief A vector in 4D space. + */ +typedef struct OF_ALIGN(16) OF_BOXABLE OFVector4D { + /** The x coordinate of the vector */ + float x; + /** The y coordinate of the vector */ + float y; + /** The z coordinate of the vector */ + float z; + /** The w coordinate of the vector */ + float w; +} OFVector4D; + +/** + * @brief Creates a new OFVector4D. + * + * @param x The x coordinate of the vector + * @param y The x coordinate of the vector + * @param z The z coordinate of the vector + * @param w The w coordinate of the vector + * @return An OFVector4D with the specified coordinates + */ +static OF_INLINE OFVector4D OF_CONST_FUNC +OFMakeVector4D(float x, float y, float z, float w) +{ + OFVector4D vector = { x, y, z, w }; + + return vector; +} + +/** + * @brief Returns whether the two vectors are equal. + * + * @param vector1 The first vector for the comparison + * @param vector2 The second vectors for the comparison + * @return Whether the two vectors are equal + */ +static OF_INLINE bool +OFEqualVectors4D(OFVector4D vector1, OFVector4D vector2) +{ + if (vector1.x != vector2.x) + return false; + + if (vector1.y != vector2.y) + return false; + + if (vector1.z != vector2.z) + return false; + + if (vector1.w != vector2.w) + return false; + return true; } /** * @brief Adds the specified byte to the hash. @@ -334,11 +452,10 @@ *hash = tmp; } static const size_t OFNotFound = SIZE_MAX; -#ifdef __OBJC__ @class OFMethodSignature; @class OFString; @class OFThread; /** @@ -557,43 +674,41 @@ * * @return Whether a weak reference to this object has been retained */ - (bool)retainWeakReference; @end -#endif /** * @class OFObject OFObject.h ObjFW/OFObject.h * * @brief The root class for all other classes inside ObjFW. */ -#ifdef __OBJC__ OF_ROOT_CLASS @interface OFObject { @private -# ifndef __clang_analyzer__ +#ifndef __clang_analyzer__ Class _isa; -# else +#else Class _isa __attribute__((__unused__)); -# endif +#endif } -# ifdef OF_HAVE_CLASS_PROPERTIES -# ifndef __cplusplus +#ifdef OF_HAVE_CLASS_PROPERTIES +# ifndef __cplusplus @property (class, readonly, nonatomic) Class class; -# else +# else @property (class, readonly, nonatomic, getter=class) Class class_; -# endif +# endif @property (class, readonly, nonatomic) OFString *className; @property (class, readonly, nullable, nonatomic) Class superclass; @property (class, readonly, nonatomic) OFString *description; -# endif +#endif -# ifndef __cplusplus +#ifndef __cplusplus @property (readonly, nonatomic) Class class; -# else +#else @property (readonly, nonatomic, getter=class) Class class_; #endif @property OF_NULLABLE_PROPERTY (readonly, nonatomic) Class superclass; @property (readonly, nonatomic) unsigned long hash; @property (readonly, nonatomic) unsigned int retainCount; @@ -657,17 +772,10 @@ * object * @throw OFInitializationFailedException The instance could not be constructed */ + (instancetype)alloc; -/** - * @brief Calls @ref alloc on `self` and then `init` on the returned object. - * - * @return An allocated and initialized object - */ -+ (instancetype)new; - /** * @brief Returns the class. * * @return The class */ @@ -942,11 +1050,11 @@ withObject: (nullable id)object2 withObject: (nullable id)object3 withObject: (nullable id)object4 afterDelay: (OFTimeInterval)delay; -# ifdef OF_HAVE_THREADS +#ifdef OF_HAVE_THREADS /** * @brief Performs the specified selector on the specified thread. * * @param selector The selector to perform * @param thread The thread on which to perform the selector @@ -1200,11 +1308,11 @@ withObject: (nullable id)object1 withObject: (nullable id)object2 withObject: (nullable id)object3 withObject: (nullable id)object4 afterDelay: (OFTimeInterval)delay; -# endif +#endif /** * @brief This method is called when @ref resolveClassMethod: or * @ref resolveInstanceMethod: returned false. It should return a target * to which the message should be forwarded. @@ -1226,15 +1334,11 @@ * @param selector The selector not understood by the receiver * @throw OFNotImplementedException */ - (void)doesNotRecognizeSelector: (SEL)selector OF_NO_RETURN; @end -#else -typedef void OFObject; -#endif -#ifdef __OBJC__ /** * @protocol OFCopying OFObject.h ObjFW/OFObject.h * * @brief A protocol for the creation of copies. */ @@ -1282,11 +1386,10 @@ * @param object An object to compare the object to * @return The result of the comparison */ - (OFComparisonResult)compare: (id )object; @end -#endif #ifdef __cplusplus extern "C" { #endif /** @@ -1363,10 +1466,17 @@ #endif extern id OFAllocObject(Class class_, size_t extraSize, size_t extraAlignment, void *_Nullable *_Nullable extra); extern void OF_NO_RETURN_FUNC OFMethodNotFound(id self, SEL _cmd); +/** + * @brief Initializes the specified hash. + * + * @param hash A pointer to the hash to initialize + */ +extern void OFHashInit(unsigned long *_Nonnull hash); + /** * @brief Returns 16 bit or non-cryptographical randomness. * * @return 16 bit or non-cryptographical randomness */ @@ -1383,26 +1493,13 @@ * @brief Returns 64 bit or non-cryptographical randomness. * * @return 64 bit or non-cryptographical randomness */ extern uint64_t OFRandom64(void); - -/** - * @brief Initializes the specified hash. - * - * @param hash A pointer to the hash to initialize - */ -extern void OFHashInit(unsigned long *_Nonnull hash); #ifdef __cplusplus } #endif OF_ASSUME_NONNULL_END -#include "OFBlock.h" - -#ifdef __OBJC__ -# import "OFObject+KeyValueCoding.h" -# import "OFObject+Serialization.h" -#endif - -#endif +#import "OFBlock.h" +#import "OFObject+KeyValueCoding.h" Index: src/OFObject.m ================================================================== --- src/OFObject.m +++ src/OFObject.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,12 +18,10 @@ #include #include #include #include "unistd_wrapper.h" -#include - #ifdef OF_APPLE_RUNTIME # include #endif #ifdef HAVE_GETRANDOM @@ -39,10 +37,11 @@ #import "OFMethodSignature.h" #import "OFRunLoop.h" #if !defined(OF_HAVE_ATOMIC_OPS) && defined(OF_HAVE_THREADS) # import "OFPlainMutex.h" /* For OFSpinlock */ #endif +#import "OFStdIOStream.h" #import "OFString.h" #import "OFThread.h" #import "OFTimer.h" #import "OFValue.h" @@ -63,11 +62,13 @@ #ifdef OF_WINDOWS # include #endif #ifdef OF_AMIGAOS +# define Class IntuitionClass # include +# undef Class #endif #ifdef OF_APPLE_RUNTIME extern id _Nullable _objc_rootAutorelease(id _Nullable object); #endif @@ -250,17 +251,16 @@ #if !defined(OF_APPLE_RUNTIME) || defined(__OBJC2__) static void uncaughtExceptionHandler(id exception) { - OFString *description = [exception description]; OFArray OF_GENERIC(OFValue *) *stackTraceAddresses = nil; OFArray OF_GENERIC(OFString *) *stackTraceSymbols = nil; OFStringEncoding encoding = [OFLocale encoding]; - fprintf(stderr, "\nRuntime error: Unhandled exception:\n%s\n", - [description cStringWithEncoding: encoding]); + OFLog(@"Runtime error: Unhandled exception:"); + OFLog(@"%@", exception); if ([exception respondsToSelector: @selector(stackTraceAddresses)]) stackTraceAddresses = [exception stackTraceAddresses]; if (stackTraceAddresses != nil) { @@ -271,32 +271,31 @@ stackTraceSymbols = [exception stackTraceSymbols]; if (stackTraceSymbols.count != count) stackTraceSymbols = nil; - fputs("\nStack trace:\n", stderr); + OFLog(@""); + OFLog(@"Stack trace:"); if (stackTraceSymbols != nil) { for (size_t i = 0; i < count; i++) { void *address = [[stackTraceAddresses objectAtIndex: i] pointerValue]; const char *symbol = [[stackTraceSymbols objectAtIndex: i] cStringWithEncoding: encoding]; - fprintf(stderr, " %p %s\n", address, symbol); + OFLog(@" %p %s", address, symbol); } } else { for (size_t i = 0; i < count; i++) { void *address = [[stackTraceAddresses objectAtIndex: i] pointerValue]; - fprintf(stderr, " %p\n", address); + OFLog(@" %p", address); } } - - fputs("\n", stderr); } abort(); } #endif @@ -335,18 +334,20 @@ size_t instanceSize; instanceSize = class_getInstanceSize(class); if OF_UNLIKELY (extraAlignment > 1) - extraAlignment = ((instanceSize + extraAlignment - 1) & - ~(extraAlignment - 1)) - extraAlignment; + extraAlignment = OFRoundUpToPowerOf2(extraAlignment, + PRE_IVARS_ALIGN + instanceSize) - + PRE_IVARS_ALIGN - instanceSize; instance = calloc(1, PRE_IVARS_ALIGN + instanceSize + extraAlignment + extraSize); if OF_UNLIKELY (instance == nil) { - allocFailedException.isa = [OFAllocFailedException class]; + object_setClass((id)&allocFailedException, + [OFAllocFailedException class]); @throw (id)&allocFailedException; } ((struct PreIvars *)instance)->retainCount = 1; @@ -386,11 +387,10 @@ /* References for static linking */ void _references_to_categories_of_OFObject(void) { _OFObject_KeyValueCoding_reference = 1; - _OFObject_Serialization_reference = 1; } @implementation OFObject + (void)load { @@ -438,15 +438,10 @@ + (instancetype)alloc { return OFAllocObject(self, 0, 0, NULL); } -+ (instancetype)new -{ - return [[self alloc] init]; -} - + (Class)class { return self; } @@ -475,14 +470,12 @@ return class_respondsToSelector(self, selector); } + (bool)conformsToProtocol: (Protocol *)protocol { - Class c; - - for (c = self; c != Nil; c = class_getSuperclass(c)) - if (class_conformsToProtocol(c, protocol)) + for (Class iter = self; iter != Nil; iter = class_getSuperclass(iter)) + if (class_conformsToProtocol(iter, protocol)) return true; return false; } @@ -580,16 +573,16 @@ [self inheritMethodsFromClass: superclass]; } + (bool)resolveClassMethod: (SEL)selector { - return NO; + return false; } + (bool)resolveInstanceMethod: (SEL)selector { - return NO; + return false; } - (instancetype)init { return self; @@ -1169,11 +1162,11 @@ return self; } - (unsigned int)retainCount { - assert(PRE_IVARS->retainCount >= 0); + OFAssert(PRE_IVARS->retainCount >= 0); return PRE_IVARS->retainCount; } - (void)release { Index: src/OFOnce.h ================================================================== --- src/OFOnce.h +++ src/OFOnce.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,14 @@ # define OFOnceControlInitValue 0 #endif OF_ASSUME_NONNULL_BEGIN +/** @file */ + +typedef void (*OFOnceFunction)(void); + #ifdef __cplusplus extern "C" { #endif /** * @brief Executes the specified function exactly once in the application's @@ -40,11 +44,11 @@ * * @param control An OFOnceControl. This should be a static variable * preinitialized to `OFOnceControlInitValue`. * @param function The function to execute once */ -extern void OFOnce(OFOnceControl *control, void (*function)(void)); +extern void OFOnce(OFOnceControl *control, OFOnceFunction function); #ifdef __cplusplus } #endif OF_ASSUME_NONNULL_END Index: src/OFOnce.m ================================================================== --- src/OFOnce.m +++ src/OFOnce.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,13 @@ # import "OFAtomic.h" # import "OFPlainMutex.h" #endif #ifdef OF_AMIGAOS +# define Class IntuitionClass # include +# undef Class #endif void OFOnce(OFOnceControl *control, void (*function)(void)) { Index: src/OFOptionsParser.h ================================================================== --- src/OFOptionsParser.h +++ src/OFOptionsParser.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,13 +64,13 @@ * * @note This will call @ref OFHMAC::reset on the `HMAC` first, making it * possible to reuse the `HMAC`, but also meaning all previous results * from the `HMAC` get invalidated if they have not been copied. * - * @param param The parameters to use + * @param parameters The parameters to use */ -extern void OFPBKDF2(OFPBKDF2Parameters param); +extern void OFPBKDF2(OFPBKDF2Parameters parameters); #ifdef __cplusplus } #endif OF_ASSUME_NONNULL_END Index: src/OFPBKDF2.m ================================================================== --- src/OFPBKDF2.m +++ src/OFPBKDF2.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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.h ================================================================== --- src/OFPair.h +++ src/OFPair.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,15 +54,15 @@ extern int OFPlainConditionBroadcast(OFPlainCondition *condition); extern int OFPlainConditionWait(OFPlainCondition *condition, OFPlainMutex *mutex); extern int OFPlainConditionTimedWait(OFPlainCondition *condition, OFPlainMutex *mutex, OFTimeInterval timeout); -#ifdef OF_AMIGAOS +#if defined(OF_AMIGAOS) || defined(DOXYGEN) extern int OFPlainConditionWaitOrExecSignal(OFPlainCondition *condition, OFPlainMutex *mutex, ULONG *signalMask); extern int OFPlainConditionTimedWaitOrExecSignal(OFPlainCondition *condition, OFPlainMutex *mutex, OFTimeInterval timeout, ULONG *signalMask); #endif extern int OFPlainConditionFree(OFPlainCondition *condition); #ifdef __cplusplus } #endif Index: src/OFPlainCondition.m ================================================================== --- src/OFPlainCondition.m +++ src/OFPlainCondition.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,11 +20,11 @@ #if !defined(OF_HAVE_THREADS) || \ (!defined(OF_HAVE_PTHREADS) && !defined(OF_WINDOWS) && !defined(OF_AMIGAOS)) # error No threads available! #endif -#import "macros.h" +#import "OFObject.h" #if defined(OF_HAVE_PTHREADS) # include typedef pthread_t OFPlainThread; #elif defined(OF_WINDOWS) Index: src/OFPlainThread.m ================================================================== --- src/OFPlainThread.m +++ src/OFPlainThread.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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.m ================================================================== --- src/OFPlugin.m +++ src/OFPlugin.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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/OFPointValue.h Index: src/OFPointValue.h ================================================================== --- src/OFPointValue.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (c) 2008-2022 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#import "OFValue.h" - -OF_ASSUME_NONNULL_BEGIN - -@interface OFPointValue: OFValue -{ - OFPoint _point; -} - -- (instancetype)initWithPoint: (OFPoint)point; -@end - -OF_ASSUME_NONNULL_END DELETED src/OFPointValue.m Index: src/OFPointValue.m ================================================================== --- src/OFPointValue.m +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2008-2022 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#import "OFPointValue.h" -#import "OFMethodSignature.h" -#import "OFString.h" - -#import "OFOutOfRangeException.h" - -@implementation OFPointValue -@synthesize pointValue = _point; - -- (instancetype)initWithPoint: (OFPoint)point -{ - self = [super init]; - - _point = point; - - return self; -} - -- (const char *)objCType -{ - return @encode(OFPoint); -} - -- (void)getValue: (void *)value size: (size_t)size -{ - if (size != sizeof(_point)) - @throw [OFOutOfRangeException exception]; - - memcpy(value, &_point, sizeof(_point)); -} - -- (OFString *)description -{ - return [OFString stringWithFormat: - @"", _point.x, _point.y]; -} -@end DELETED src/OFPointerValue.h Index: src/OFPointerValue.h ================================================================== --- src/OFPointerValue.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (c) 2008-2022 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#import "OFValue.h" - -OF_ASSUME_NONNULL_BEGIN - -@interface OFPointerValue: OFValue -{ - void *_pointer; -} - -- (instancetype)initWithPointer: (const void *)pointer; -@end - -OF_ASSUME_NONNULL_END DELETED src/OFPointerValue.m Index: src/OFPointerValue.m ================================================================== --- src/OFPointerValue.m +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2008-2022 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#import "OFPointerValue.h" -#import "OFMethodSignature.h" - -#import "OFOutOfRangeException.h" - -@implementation OFPointerValue -@synthesize pointerValue = _pointer; - -- (instancetype)initWithPointer: (const void *)pointer -{ - self = [super init]; - - _pointer = (void *)pointer; - - return self; -} - -- (const char *)objCType -{ - return @encode(void *); -} - -- (void)getValue: (void *)value size: (size_t)size -{ - if (size != sizeof(_pointer)) - @throw [OFOutOfRangeException exception]; - - memcpy(value, &_pointer, sizeof(_pointer)); -} - -- (id)nonretainedObjectValue -{ - return _pointer; -} -@end Index: src/OFPollKernelEventObserver.h ================================================================== --- src/OFPollKernelEventObserver.h +++ src/OFPollKernelEventObserver.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,10 @@ #define __NO_EXT_QNX #include "config.h" -#include #include #ifdef HAVE_POLL_H # include #endif @@ -190,11 +189,11 @@ @throw [OFObserveKernelEventsFailedException exceptionWithObserver: self errNo: errno]; for (size_t i = 0; i < nFDs; i++) { - assert(FDs[i].fd <= _maxFD); + OFAssert(FDs[i].fd <= _maxFD); if (FDs[i].revents & POLLIN) { void *pool2; if (FDs[i].fd == _cancelFD[0]) { Index: src/OFRIPEMD160Hash.h ================================================================== --- src/OFRIPEMD160Hash.h +++ src/OFRIPEMD160Hash.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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.h ================================================================== --- src/OFRangeCharacterSet.h +++ src/OFRangeCharacterSet.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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/OFRangeValue.h Index: src/OFRangeValue.h ================================================================== --- src/OFRangeValue.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (c) 2008-2022 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#import "OFValue.h" - -OF_ASSUME_NONNULL_BEGIN - -@interface OFRangeValue: OFValue -{ - OFRange _range; -} - -- (instancetype)initWithRange: (OFRange)range; -@end - -OF_ASSUME_NONNULL_END DELETED src/OFRangeValue.m Index: src/OFRangeValue.m ================================================================== --- src/OFRangeValue.m +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2008-2022 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#import "OFRangeValue.h" -#import "OFMethodSignature.h" -#import "OFString.h" - -#import "OFOutOfRangeException.h" - -@implementation OFRangeValue -@synthesize rangeValue = _range; - -- (instancetype)initWithRange: (OFRange)range -{ - self = [super init]; - - _range = range; - - return self; -} - -- (const char *)objCType -{ - return @encode(OFRange); -} - -- (void)getValue: (void *)value size: (size_t)size -{ - if (size != sizeof(_range)) - @throw [OFOutOfRangeException exception]; - - memcpy(value, &_range, sizeof(_range)); -} - -- (OFString *)description -{ - return [OFString stringWithFormat: - @"", - _range.location, _range.length]; -} -@end DELETED src/OFRectValue.h Index: src/OFRectValue.h ================================================================== --- src/OFRectValue.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (c) 2008-2022 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#import "OFValue.h" - -OF_ASSUME_NONNULL_BEGIN - -@interface OFRectValue: OFValue -{ - OFRect _rect; -} - -- (instancetype)initWithRect: (OFRect)rect; -@end - -OF_ASSUME_NONNULL_END DELETED src/OFRectValue.m Index: src/OFRectValue.m ================================================================== --- src/OFRectValue.m +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2008-2022 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#import "OFRectValue.h" -#import "OFMethodSignature.h" -#import "OFString.h" - -#import "OFOutOfRangeException.h" - -@implementation OFRectValue -@synthesize rectValue = _rect; - -- (instancetype)initWithRect: (OFRect)rect -{ - self = [super init]; - - _rect = rect; - - return self; -} - -- (const char *)objCType -{ - return @encode(OFRect); -} - -- (void)getValue: (void *)value size: (size_t)size -{ - if (size != sizeof(_rect)) - @throw [OFOutOfRangeException exception]; - - memcpy(value, &_rect, sizeof(_rect)); -} - -- (OFString *)description -{ - return [OFString stringWithFormat: - @"", - _rect.origin.x, _rect.origin.y, - _rect.size.width, _rect.size.height]; -} -@end Index: src/OFRecursiveMutex.h ================================================================== --- src/OFRecursiveMutex.h +++ src/OFRecursiveMutex.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,11 +101,11 @@ * @param timer The timer to add * @param mode The run loop mode in which to run the timer */ - (void)addTimer: (OFTimer *)timer forMode: (OFRunLoopMode)mode; -#ifdef OF_AMIGAOS +#if defined(OF_AMIGAOS) || defined(DOXYGEN) /** * @brief Adds an Exec Signal to the run loop. * * If a signal is added multiple times, the specified methods will be performed * in the order added. Index: src/OFRunLoop.m ================================================================== --- src/OFRunLoop.m +++ src/OFRunLoop.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,11 +13,10 @@ * file. */ #include "config.h" -#include #include #import "OFRunLoop.h" #import "OFRunLoop+Private.h" #import "OFArray.h" @@ -272,11 +271,11 @@ * handler called -[cancelAsyncRequests]. */ OFList OF_GENERIC(OF_KINDOF(OFRunLoopReadQueueItem *)) *queue = [[_readQueues objectForKey: object] retain]; - assert(queue != nil); + OFAssert(queue != nil); @try { if (![queue.firstObject handleObject: object]) { OFListItem listItem = queue.firstListItem; @@ -316,11 +315,11 @@ * Retain the queue so that it doesn't disappear from us because the * handler called -[cancelAsyncRequests]. */ OFList *queue = [[_writeQueues objectForKey: object] retain]; - assert(queue != nil); + OFAssert(queue != nil); @try { if (![queue.firstObject handleObject: object]) { OFListItem listItem = queue.firstListItem; @@ -1326,11 +1325,11 @@ if (state == nil) return; if ((queue = [state->_writeQueues objectForKey: object]) != nil) { - assert(queue.count > 0); + OFAssert(queue.count > 0); /* * Clear the queue now, in case this has been called from a * handler, as otherwise, we'd do the cleanups below twice. */ @@ -1339,11 +1338,11 @@ [state->_kernelEventObserver removeObjectForWriting: object]; [state->_writeQueues removeObjectForKey: object]; } if ((queue = [state->_readQueues objectForKey: object]) != nil) { - assert(queue.count > 0); + OFAssert(queue.count > 0); /* * Clear the queue now, in case this has been called from a * handler, as otherwise, we'd do the cleanups below twice. */ @@ -1613,10 +1612,11 @@ [state->_timersQueueMutex unlock]; } #endif if (timer.valid) { + [timer of_reschedule]; [timer fire]; return; } } Index: src/OFRunLoopConstants.inc ================================================================== --- src/OFRunLoopConstants.inc +++ src/OFRunLoopConstants.inc @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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.h ================================================================== --- src/OFSHA224Hash.h +++ src/OFSHA224Hash.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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.h ================================================================== --- src/OFSHA256Hash.h +++ src/OFSHA256Hash.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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.h ================================================================== --- src/OFSHA512Hash.h +++ src/OFSHA512Hash.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -88,11 +88,11 @@ * @param network The network on which the node to connect to is * @param node The node to connect to * @param port The port (sometimes also called socket number) on the node to * connect to * @throw OFConnectSPXSocketFailedException Connecting failed - * @throw OFAlreadyConnectedException The socket is already connected or bound + * @throw OFAlreadyOpenException The socket is already connected or bound */ - (void)connectToNetwork: (uint32_t)network node: (const unsigned char [_Nonnull IPX_NODE_LEN])node port: (uint16_t)port; @@ -162,14 +162,14 @@ * computer's node. * @param port The port (sometimes called socket number) to bind to. 0 means to * pick one and return via the returned socket address. * @return The address on which this socket can be reached * @throw OFBindIPXSocketFailedException Binding failed - * @throw OFAlreadyConnectedException The socket is already connected or bound + * @throw OFAlreadyOpenException The socket is already connected or bound */ - (OFSocketAddress) bindToNetwork: (uint32_t)network node: (const unsigned char [_Nonnull IPX_NODE_LEN])node port: (uint16_t)port; @end OF_ASSUME_NONNULL_END Index: src/OFSPXSocket.m ================================================================== --- src/OFSPXSocket.m +++ src/OFSPXSocket.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,11 +21,11 @@ #import "OFRunLoop.h" #import "OFRunLoop+Private.h" #import "OFSocket.h" #import "OFSocket+Private.h" -#import "OFAlreadyConnectedException.h" +#import "OFAlreadyOpenException.h" #import "OFBindIPXSocketFailedException.h" #import "OFConnectSPXSocketFailedException.h" #import "OFNotOpenException.h" #ifndef NSPROTO_SPX @@ -183,11 +183,11 @@ #if SOCK_CLOEXEC == 0 && defined(HAVE_FCNTL) && defined(FD_CLOEXEC) int flags; #endif if (_socket != OFInvalidSocketHandle) - @throw [OFAlreadyConnectedException exceptionWithSocket: self]; + @throw [OFAlreadyOpenException exceptionWithObject: self]; if ((_socket = socket(address->sockaddr.ipx.sipx_family, SOCK_SEQPACKET | SOCK_CLOEXEC, NSPROTO_SPX)) == OFInvalidSocketHandle) { *errNo = OFSocketErrNo(); @@ -321,11 +321,11 @@ #if SOCK_CLOEXEC == 0 && defined(HAVE_FCNTL_H) && defined(FD_CLOEXEC) int flags; #endif if (_socket != OFInvalidSocketHandle) - @throw [OFAlreadyConnectedException exceptionWithSocket: self]; + @throw [OFAlreadyOpenException exceptionWithObject: self]; address = OFSocketAddressMakeIPX(network, node, port); if ((_socket = socket(address.sockaddr.ipx.sipx_family, SOCK_SEQPACKET | SOCK_CLOEXEC, NSPROTO_SPX)) == Index: src/OFSPXStreamSocket.h ================================================================== --- src/OFSPXStreamSocket.h +++ src/OFSPXStreamSocket.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -89,11 +89,11 @@ * @param network The network on which the node to connect to is * @param node The node to connect to * @param port The port (sometimes also called socket number) on the node to * connect to * @throw OFConnectSPXSocketFailedException Connecting failed - * @throw OFAlreadyConnectedException The socket is already connected or bound + * @throw OFAlreadyOpenException The socket is already connected or bound */ - (void)connectToNetwork: (uint32_t)network node: (const unsigned char [_Nonnull IPX_NODE_LEN])node port: (uint16_t)port; @@ -167,14 +167,14 @@ * computer's node. * @param port The port (sometimes called socket number) to bind to. 0 means to * pick one and return via the returned socket address. * @return The address on which this socket can be reached * @throw OFBindIPXSocketFailedException Binding failed - * @throw OFAlreadyConnectedException The socket is already connected or bound + * @throw OFAlreadyOpenException The socket is already connected or bound */ - (OFSocketAddress) bindToNetwork: (uint32_t)network node: (const unsigned char [_Nonnull IPX_NODE_LEN])node port: (uint16_t)port; @end OF_ASSUME_NONNULL_END Index: src/OFSPXStreamSocket.m ================================================================== --- src/OFSPXStreamSocket.m +++ src/OFSPXStreamSocket.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,11 +21,11 @@ #import "OFRunLoop.h" #import "OFRunLoop+Private.h" #import "OFSocket.h" #import "OFSocket+Private.h" -#import "OFAlreadyConnectedException.h" +#import "OFAlreadyOpenException.h" #import "OFBindIPXSocketFailedException.h" #import "OFConnectSPXSocketFailedException.h" #import "OFNotOpenException.h" #ifndef NSPROTO_SPX @@ -185,11 +185,11 @@ #if SOCK_CLOEXEC == 0 && defined(HAVE_FCNTL) && defined(FD_CLOEXEC) int flags; #endif if (_socket != OFInvalidSocketHandle) - @throw [OFAlreadyConnectedException exceptionWithSocket: self]; + @throw [OFAlreadyOpenException exceptionWithObject: self]; if ((_socket = socket(address->sockaddr.ipx.sipx_family, SOCK_STREAM | SOCK_CLOEXEC, NSPROTO_SPX)) == OFInvalidSocketHandle) { *errNo = OFSocketErrNo(); @@ -323,11 +323,11 @@ #if SOCK_CLOEXEC == 0 && defined(HAVE_FCNTL_H) && defined(FD_CLOEXEC) int flags; #endif if (_socket != OFInvalidSocketHandle) - @throw [OFAlreadyConnectedException exceptionWithSocket: self]; + @throw [OFAlreadyOpenException exceptionWithObject: self]; address = OFSocketAddressMakeIPX(network, node, port); if ((_socket = socket(address.sockaddr.ipx.sipx_family, SOCK_STREAM | SOCK_CLOEXEC, NSPROTO_SPX)) == OFInvalidSocketHandle) Index: src/OFSandbox.h ================================================================== --- src/OFSandbox.h +++ src/OFSandbox.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -68,13 +68,13 @@ size_t costFactor, uint32_t *tmp); /** * @brief Derives a key from a password and a salt using scrypt. * - * @param param The parameters to use + * @param parameters The parameters to use */ -extern void OFScrypt(OFScryptParameters param); +extern void OFScrypt(OFScryptParameters parameters); #ifdef __cplusplus } #endif OF_ASSUME_NONNULL_END Index: src/OFScrypt.m ================================================================== --- src/OFScrypt.m +++ src/OFScrypt.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,12 +30,14 @@ * memory. */ OF_SUBCLASSING_RESTRICTED @interface OFSecureData: OFData { + unsigned char *_Nullable _items; + size_t _count, _itemSize; + bool _freeWhenDone, _allowsSwappableMemory; void *_page; - bool _allowsSwappableMemory; } /** * @brief Whether the data may be stored in swappable memory. */ @@ -102,11 +104,11 @@ itemSize: (size_t)itemSize freeWhenDone: (bool)freeWhenDone OF_UNAVAILABLE; #ifdef OF_HAVE_FILES + (instancetype)dataWithContentsOfFile: (OFString *)path OF_UNAVAILABLE; #endif -+ (instancetype)dataWithContentsOfURI: (OFURI *)URI OF_UNAVAILABLE; ++ (instancetype)dataWithContentsOfIRI: (OFIRI *)IRI OF_UNAVAILABLE; + (instancetype)dataWithStringRepresentation: (OFString *)string OF_UNAVAILABLE; + (instancetype)dataWithBase64EncodedString: (OFString *)string OF_UNAVAILABLE; /** * @brief Initializes an already allocated OFSecureData with `count` items of @@ -133,10 +135,12 @@ - (instancetype)initWithCount: (size_t)count itemSize: (size_t)itemSize allowsSwappableMemory: (bool)allowsSwappableMemory OF_DESIGNATED_INITIALIZER; +- (instancetype)init OF_UNAVAILABLE; +- (instancetype)initWithItemSize: (size_t)itemSize OF_UNAVAILABLE; - (instancetype)initWithItems: (const void *)items count: (size_t)count OF_UNAVAILABLE; - (instancetype)initWithItems: (const void *)items count: (size_t)count itemSize: (size_t)itemSize OF_UNAVAILABLE; @@ -148,14 +152,13 @@ itemSize: (size_t)itemSize freeWhenDone: (bool)freeWhenDone OF_UNAVAILABLE; #ifdef OF_HAVE_FILES - (instancetype)initWithContentsOfFile: (OFString *)path OF_UNAVAILABLE; #endif -- (instancetype)initWithContentsOfURI: (OFURI *)URI OF_UNAVAILABLE; +- (instancetype)initWithContentsOfIRI: (OFIRI *)IRI OF_UNAVAILABLE; - (instancetype)initWithStringRepresentation: (OFString *)string OF_UNAVAILABLE; - (instancetype)initWithBase64EncodedString: (OFString *)string OF_UNAVAILABLE; -- (instancetype)initWithSerialization: (OFXMLElement *)element OF_UNAVAILABLE; /** * @brief Returns a specific item of the OFSecureData. * * Modifying the returned item directly is allowed and will change the contents @@ -185,11 +188,10 @@ - (OFString *)stringRepresentation OF_UNAVAILABLE; - (OFString *)stringByBase64Encoding OF_UNAVAILABLE; #ifdef OF_HAVE_FILES - (void)writeToFile: (OFString *)path OF_UNAVAILABLE; #endif -- (void)writeToURI: (OFURI *)URI OF_UNAVAILABLE; -- (OFXMLElement *)XMLElementBySerializing OF_UNAVAILABLE; +- (void)writeToIRI: (OFIRI *)IRI OF_UNAVAILABLE; - (OFData *)messagePackRepresentation OF_UNAVAILABLE; @end OF_ASSUME_NONNULL_END Index: src/OFSecureData.m ================================================================== --- src/OFSecureData.m +++ src/OFSecureData.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -338,12 +338,11 @@ itemSize: itemSize allowsSwappableMemory: allowsSwappableMemory] autorelease]; } -+ (instancetype)dataWithItems: (const void *)items - count: (size_t)count ++ (instancetype)dataWithItems: (const void *)items count: (size_t)count { OF_UNRECOGNIZED_SELECTOR } + (instancetype)dataWithItems: (const void *)items @@ -373,11 +372,11 @@ { OF_UNRECOGNIZED_SELECTOR } #endif -+ (instancetype)dataWithContentsOfURI: (OFURI *)URI ++ (instancetype)dataWithContentsOfIRI: (OFIRI *)IRI { OF_UNRECOGNIZED_SELECTOR } + (instancetype)dataWithStringRepresentation: (OFString *)string @@ -387,11 +386,10 @@ + (instancetype)dataWithBase64EncodedString: (OFString *)string { OF_UNRECOGNIZED_SELECTOR } - - (instancetype)initWithCount: (size_t)count allowsSwappableMemory: (bool)allowsSwappableMemory { return [self initWithCount: count @@ -462,10 +460,20 @@ @throw e; } return self; } + +- (instancetype)init +{ + OF_INVALID_INIT_METHOD +} + +- (instancetype)initWithItemSize: (size_t)itemSize +{ + OF_INVALID_INIT_METHOD +} - (instancetype)initWithItems: (const void *)items count: (size_t)count { OF_INVALID_INIT_METHOD } @@ -497,11 +505,11 @@ { OF_INVALID_INIT_METHOD } #endif -- (instancetype)initWithContentsOfURI: (OFURI *)URI +- (instancetype)initWithContentsOfIRI: (OFIRI *)IRI { OF_INVALID_INIT_METHOD } - (instancetype)initWithStringRepresentation: (OFString *)string @@ -509,15 +517,10 @@ OF_INVALID_INIT_METHOD } - (instancetype)initWithBase64EncodedString: (OFString *)string { - OF_INVALID_INIT_METHOD -} - -- (instancetype)initWithSerialization: (OFXMLElement *)element -{ OF_INVALID_INIT_METHOD } - (void)dealloc { @@ -538,12 +541,30 @@ removePageIfEmpty(_page); } } #endif + if (_freeWhenDone) + OFFreeMemory(_items); + [super dealloc]; } + +- (size_t)count +{ + return _count; +} + +- (size_t)itemSize +{ + return _itemSize; +} + +- (const void *)items +{ + return _items; +} - (void *)mutableItems { return _items; } @@ -586,27 +607,29 @@ } - (bool)isEqual: (id)object { OFData *otherData; + const unsigned char *otherDataItems; unsigned char diff; if (object == self) return true; if (![object isKindOfClass: [OFData class]]) return false; otherData = object; + otherDataItems = otherData.items; - if (otherData->_count != _count || otherData->_itemSize != _itemSize) + if (otherData.count != _count || otherData.itemSize != _itemSize) return false; diff = 0; for (size_t i = 0; i < _count * _itemSize; i++) - diff |= otherData->_items[i] ^ _items[i]; + diff |= otherDataItems[i] ^ _items[i]; return (diff == 0); } - (OFString *)description @@ -629,20 +652,15 @@ { OF_UNRECOGNIZED_SELECTOR } #endif -- (void)writeToURI: (OFURI *)URI -{ - OF_UNRECOGNIZED_SELECTOR -} - -- (OFXMLElement *)XMLElementBySerializing +- (void)writeToIRI: (OFIRI *)IRI { OF_UNRECOGNIZED_SELECTOR } - (OFData *)messagePackRepresentation { OF_UNRECOGNIZED_SELECTOR } @end Index: src/OFSeekableStream.h ================================================================== --- src/OFSeekableStream.h +++ src/OFSeekableStream.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,11 +35,11 @@ #if defined(OF_WINDOWS) typedef __int64 OFStreamOffset; #elif defined(OF_ANDROID) typedef long long OFStreamOffset; #elif defined(OF_MORPHOS) -typedef signed long long OFStreamOffset; +typedef long long OFStreamOffset; #elif defined(OF_HAVE_OFF64_T) typedef off64_t OFStreamOffset; #else typedef off_t OFStreamOffset; #endif Index: src/OFSeekableStream.m ================================================================== --- src/OFSeekableStream.m +++ src/OFSeekableStream.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,11 +36,13 @@ #import "OFInitializationFailedException.h" #import "OFObserveKernelEventsFailedException.h" #import "OFOutOfRangeException.h" #ifdef OF_AMIGAOS +# define Class IntuitionClass # include +# undef Class #endif #ifdef OF_HPUX /* FD_SET causes warnings on HP-UX/IA64. */ # pragma GCC diagnostic ignored "-Wstrict-aliasing" Index: src/OFSequencedPacketSocket+Private.h ================================================================== --- src/OFSequencedPacketSocket+Private.h +++ src/OFSequencedPacketSocket+Private.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -124,10 +124,14 @@ */ @interface OFSequencedPacketSocket: OFObject { OFSocketHandle _socket; +#ifdef OF_AMIGAOS + LONG _socketID; /* unused, reserved for ABI stability */ + int _family; /* unused, reserved for ABI stability */ +#endif bool _canBlock, _listening; OFSocketAddress _remoteAddress; id _Nullable _delegate; OF_RESERVE_IVARS(OFSequencedPacketSocket, 4) } @@ -135,10 +139,11 @@ /** * @brief Whether the socket can block. * * By default, a socket can block. * + * @throw OFGetOptionFailedException The option could not be retrieved * @throw OFSetOptionFailedException The option could not be set */ @property (nonatomic) bool canBlock; /** @@ -365,10 +370,34 @@ /** * @brief Cancels all pending asynchronous requests on the socket. */ - (void)cancelAsyncRequests; +/** + * @brief Releases the socket from the current thread. + * + * This is necessary on some platforms in order to allow a different thread to + * use the socket, e.g. on AmigaOS, but you should call it on all operating + * systems before using the socket from a different thread. + * + * After calling this method, you must no longer use the socket until + * @ref obtainSocketForCurrentThread has been called. + */ +- (void)releaseSocketFromCurrentThread; + +/** + * @brief Obtains the socket for the current thread. + * + * This is necessary on some platforms in order to allow a different thread to + * use the socket, e.g. on AmigaOS, but you should call it on all operating + * systems before using the socket from a different thread. + * + * You must only call this method after @ref releaseSocketFromCurrentThread has + * been called from a different thread. + */ +- (void)obtainSocketForCurrentThread; + /** * @brief Closes the socket so that it can neither receive nor send any more * datagrams. * * @throw OFNotOpenException The socket is not open Index: src/OFSequencedPacketSocket.m ================================================================== --- src/OFSequencedPacketSocket.m +++ src/OFSequencedPacketSocket.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,11 +18,10 @@ #ifndef _XOPEN_SOURCE_EXTENDED # define _XOPEN_SOURCE_EXTENDED #endif #define _HPUX_ALT_XOPEN_SOCKET_API -#include #include #ifdef HAVE_FCNTL_H # include #endif @@ -360,11 +359,11 @@ if ((flags = fcntl(client->_socket, F_GETFD, 0)) != -1) fcntl(client->_socket, F_SETFD, flags | FD_CLOEXEC); # endif #endif - assert(client->_remoteAddress.length <= + OFAssert(client->_remoteAddress.length <= (socklen_t)sizeof(client->_remoteAddress.sockaddr)); switch (((struct sockaddr *)&client->_remoteAddress.sockaddr) ->sa_family) { case AF_INET: @@ -465,10 +464,26 @@ @throw [OFOutOfRangeException exception]; return (int)_socket; #endif } + +- (void)releaseSocketFromCurrentThread +{ + /* + * Currently a nop, as all supported OSes that have SOCK_SEQPACKET do + * not need anything to move sockets between threads. + */ +} + +- (void)obtainSocketForCurrentThread +{ + /* + * Currently a nop, as all supported OSes that have SOCK_SEQPACKET do + * not need anything to move sockets between threads. + */ +} - (void)close { if (_socket == OFInvalidSocketHandle) @throw [OFNotOpenException exceptionWithObject: self]; DELETED src/OFSerialization.h Index: src/OFSerialization.h ================================================================== --- src/OFSerialization.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2008-2022 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#import "OFObject.h" - -OF_ASSUME_NONNULL_BEGIN - -@class OFConstantString; -@class OFXMLElement; - -/** - * @protocol OFSerialization OFSerialization.h ObjFW/OFSerialization.h - * - * @brief A protocol for serializing objects. - */ -@protocol OFSerialization -/** - * @brief The object serialized into an XML element. - */ -@property (readonly, nonatomic) OFXMLElement *XMLElementBySerializing; - -/** - * @brief Initializes the object with the specified XML element serialization. - * - * @param element An OFXMLElement with the serialized object - * @return An initialized object - * @throw OFInvalidFormatException The specified element is not of the correct - * serialization format - */ -- (instancetype)initWithSerialization: (OFXMLElement *)element; -@end - -#ifdef __cplusplus -extern "C" { -#endif -extern OFConstantString *const OFSerializationNS; -#ifdef __cplusplus -} -#endif - -OF_ASSUME_NONNULL_END DELETED src/OFSerialization.m Index: src/OFSerialization.m ================================================================== --- src/OFSerialization.m +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright (c) 2008-2022 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#import "OFSerialization.h" -#import "OFString.h" - -OFConstantString *const OFSerializationNS = - @"https://objfw.nil.im/serialization"; Index: src/OFSet.h ================================================================== --- src/OFSet.h +++ src/OFSet.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,10 @@ #include #import "OFObject.h" #import "OFCollection.h" -#import "OFSerialization.h" OF_ASSUME_NONNULL_BEGIN /** @file */ @@ -61,11 +60,11 @@ * * @note Subclasses must implement @ref count, @ref containsObject: and * @ref objectEnumerator. */ @interface OFSet OF_GENERIC(ObjectType): OFObject + OFMutableCopying> #if !defined(OF_HAVE_GENERICS) && !defined(DOXYGEN) # define ObjectType id #endif /** * @brief An array of all objects in the set. @@ -116,10 +115,17 @@ * @return A new, autoreleased set with the specified objects */ + (instancetype)setWithObjects: (ObjectType const _Nonnull *_Nonnull)objects count: (size_t)count; +/** + * @brief Initializes an already allocated set to be empty. + * + * @return An initialized set + */ +- (instancetype)init OF_DESIGNATED_INITIALIZER; + /** * @brief Initializes an already allocated set with the specified set. * * @param set The set to initialize the set with * @return An initialized set with the specified set @@ -159,11 +165,11 @@ * @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; + count: (size_t)count OF_DESIGNATED_INITIALIZER; /** * @brief Returns an OFEnumerator to enumerate through all objects of the set. * * @return An OFEnumerator to enumerate through all objects of the set Index: src/OFSet.m ================================================================== --- src/OFSet.m +++ src/OFSet.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,93 +17,80 @@ #include #import "OFSet.h" #import "OFArray.h" -#import "OFMapTableSet.h" +#import "OFConcreteSet.h" +#import "OFCountedSet.h" #import "OFNull.h" #import "OFString.h" -#import "OFXMLElement.h" static struct { Class isa; } placeholder; -@interface OFSetPlaceholder: OFSet +@interface OFPlaceholderSet: OFSet @end -@implementation OFSetPlaceholder +@implementation OFPlaceholderSet +#ifdef __clang__ +/* We intentionally don't call into super, so silence the warning. */ +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wunknown-pragmas" +# pragma clang diagnostic ignored "-Wobjc-designated-initializers" +#endif - (instancetype)init { - return (id)[[OFMapTableSet alloc] init]; + return (id)[[OFConcreteSet alloc] init]; } - (instancetype)initWithSet: (OFSet *)set { - return (id)[[OFMapTableSet alloc] initWithSet: set]; + return (id)[[OFConcreteSet alloc] initWithSet: set]; } - (instancetype)initWithArray: (OFArray *)array { - return (id)[[OFMapTableSet alloc] initWithArray: array]; + return (id)[[OFConcreteSet alloc] initWithArray: array]; } - (instancetype)initWithObjects: (id)firstObject, ... { id ret; va_list arguments; va_start(arguments, firstObject); - ret = [[OFMapTableSet alloc] initWithObject: firstObject + ret = [[OFConcreteSet alloc] initWithObject: firstObject arguments: arguments]; va_end(arguments); return ret; } - (instancetype)initWithObjects: (id const *)objects count: (size_t)count { - return (id)[[OFMapTableSet alloc] initWithObjects: objects + return (id)[[OFConcreteSet alloc] initWithObjects: objects count: count]; } - (instancetype)initWithObject: (id)firstObject arguments: (va_list)arguments { - return (id)[[OFMapTableSet alloc] initWithObject: firstObject + return (id)[[OFConcreteSet alloc] initWithObject: firstObject arguments: arguments]; } - -- (instancetype)initWithSerialization: (OFXMLElement *)element -{ - return (id)[[OFMapTableSet alloc] initWithSerialization: element]; -} - -- (instancetype)retain -{ - return self; -} - -- (instancetype)autorelease -{ - return self; -} - -- (void)release -{ -} - -- (void)dealloc -{ - OF_DEALLOC_UNSUPPORTED -} +#ifdef __clang__ +# pragma clang diagnostic pop +#endif + +OF_SINGLETON_METHODS @end @implementation OFSet + (void)initialize { if (self == [OFSet class]) - placeholder.isa = [OFSetPlaceholder class]; + object_setClass((id)&placeholder, [OFPlaceholderSet class]); } + (instancetype)alloc { if (self == [OFSet class]) @@ -146,11 +133,13 @@ count: count] autorelease]; } - (instancetype)init { - if ([self isMemberOfClass: [OFSet class]]) { + if ([self isMemberOfClass: [OFSet class]] || + [self isMemberOfClass: [OFMutableSet class]] || + [self isMemberOfClass: [OFCountedSet class]]) { @try { [self doesNotRecognizeSelector: _cmd]; } @catch (id e) { [self release]; @throw e; @@ -162,22 +151,76 @@ return [super init]; } - (instancetype)initWithSet: (OFSet *)set { - OF_INVALID_INIT_METHOD + id *objects = NULL; + size_t count; + + @try { + void *pool = objc_autoreleasePoolPush(); + size_t i = 0; + + count = set.count; + objects = OFAllocMemory(count, sizeof(id)); + + for (id object in set) { + OFEnsure(i < count); + objects[i++] = object; + } + + objc_autoreleasePoolPop(pool); + } @catch (id e) { + OFFreeMemory(objects); + + [self release]; + @throw e; + } + + @try { + self = [self initWithObjects: objects count: count]; + } @finally { + OFFreeMemory(objects); + } + + return self; } - (instancetype)initWithArray: (OFArray *)array { - OF_INVALID_INIT_METHOD + void *pool = objc_autoreleasePoolPush(); + size_t count; + const id *objects; + + @try { + count = array.count; + objects = array.objects; + } @catch (id e) { + [self release]; + @throw e; + } + + self = [self initWithObjects: objects count: count]; + + objc_autoreleasePoolPop(pool); + + return self; } +#ifdef __clang__ +/* We intentionally don't call into super, so silence the warning. */ +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wunknown-pragmas" +# pragma clang diagnostic ignored "-Wobjc-designated-initializers" +#endif - (instancetype)initWithObjects: (id const *)objects count: (size_t)count { OF_INVALID_INIT_METHOD } +#ifdef __clang__ +# pragma clang diagnostic pop +#endif - (instancetype)initWithObjects: (id)firstObject, ... { id ret; va_list arguments; @@ -189,16 +232,42 @@ return ret; } - (instancetype)initWithObject: (id)firstObject arguments: (va_list)arguments { - OF_INVALID_INIT_METHOD -} + size_t count = 1; + va_list argumentsCopy; + id *objects; + + if (firstObject == nil) + return [self init]; + + va_copy(argumentsCopy, arguments); + while (va_arg(argumentsCopy, id) != nil) + count++; + + @try { + objects = OFAllocMemory(count, sizeof(id)); + } @catch (id e) { + [self release]; + @throw e; + } + + @try { + objects[0] = firstObject; + + for (size_t i = 1; i < count; i++) { + objects[i] = va_arg(arguments, id); + OFEnsure(objects[i] != nil); + } + + self = [self initWithObjects: objects count: count]; + } @finally { + OFFreeMemory(objects); + } -- (instancetype)initWithSerialization: (OFXMLElement *)element -{ - OF_INVALID_INIT_METHOD + return self; } - (size_t)count { OF_UNRECOGNIZED_SELECTOR @@ -243,10 +312,11 @@ - (int)countByEnumeratingWithState: (OFFastEnumerationState *)state objects: (id *)objects count: (int)count { + static unsigned long dummyMutations; OFEnumerator *enumerator; int i; memcpy(&enumerator, state->extra, sizeof(enumerator)); @@ -254,11 +324,11 @@ enumerator = [self objectEnumerator]; memcpy(state->extra, &enumerator, sizeof(enumerator)); } state->itemsPtr = objects; - state->mutationsPtr = (unsigned long *)self; + state->mutationsPtr = &dummyMutations; for (i = 0; i < count; i++) { id object = [enumerator nextObject]; if (object == nil) @@ -360,35 +430,10 @@ return true; return false; } -- (OFXMLElement *)XMLElementBySerializing -{ - void *pool = objc_autoreleasePoolPush(); - OFXMLElement *element; - - if ([self isKindOfClass: [OFMutableSet class]]) - element = [OFXMLElement elementWithName: @"OFMutableSet" - namespace: OFSerializationNS]; - else - element = [OFXMLElement elementWithName: @"OFSet" - namespace: OFSerializationNS]; - - for (id object in self) { - void *pool2 = objc_autoreleasePoolPush(); - [element addChild: object.XMLElementBySerializing]; - objc_autoreleasePoolPop(pool2); - } - - [element retain]; - - objc_autoreleasePoolPop(pool); - - return [element autorelease]; -} - - (OFSet *)setByAddingObjectsFromSet: (OFSet *)set { OFMutableSet *new = [[self mutableCopy] autorelease]; [new unionSet: set]; [new makeImmutable]; Index: src/OFSettings.h ================================================================== --- src/OFSettings.h +++ src/OFSettings.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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/OFSizeValue.h Index: src/OFSizeValue.h ================================================================== --- src/OFSizeValue.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (c) 2008-2022 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#import "OFValue.h" - -OF_ASSUME_NONNULL_BEGIN - -@interface OFSizeValue: OFValue -{ - OFSize _size; -} - -- (instancetype)initWithSize: (OFSize)size; -@end - -OF_ASSUME_NONNULL_END DELETED src/OFSizeValue.m Index: src/OFSizeValue.m ================================================================== --- src/OFSizeValue.m +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2008-2022 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#import "OFSizeValue.h" -#import "OFMethodSignature.h" -#import "OFString.h" - -#import "OFOutOfRangeException.h" - -@implementation OFSizeValue -@synthesize sizeValue = _size; - -- (instancetype)initWithSize: (OFSize)size -{ - self = [super init]; - - _size = size; - - return self; -} - -- (const char *)objCType -{ - return @encode(OFSize); -} - -- (void)getValue: (void *)value size: (size_t)size -{ - if (size != sizeof(_size)) - @throw [OFOutOfRangeException exception]; - - memcpy(value, &_size, sizeof(_size)); -} - -- (OFString *)description -{ - return [OFString stringWithFormat: - @"", _size.width, _size.height]; -} -@end Index: src/OFSocket+Private.h ================================================================== --- src/OFSocket+Private.h +++ src/OFSocket+Private.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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 @@ #endif #ifdef HAVE_NETDB_H # include #endif -#include "OFSocket.h" +#import "OFSocket.h" #ifndef INADDR_NONE # define INADDR_NONE ((in_addr_t)-1) #endif Index: src/OFSocket.h ================================================================== --- src/OFSocket.h +++ src/OFSocket.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -59,12 +59,10 @@ # ifdef OF_HAVE_APPLETALK # include # endif #endif -/** @file */ - #ifdef OF_WII # include #endif #ifdef OF_PSP @@ -72,10 +70,12 @@ #endif #import "macros.h" OF_ASSUME_NONNULL_BEGIN + +/** @file */ #ifndef OF_WINDOWS typedef int OFSocketHandle; static const OFSocketHandle OFInvalidSocketHandle = -1; #else @@ -134,51 +134,54 @@ sa_family_t sun_family; char sun_path[108]; }; #endif -#ifndef OF_HAVE_IPX +#ifndef IPX_NODE_LEN # define IPX_NODE_LEN 6 +#endif +#if !defined(OF_HAVE_IPX) struct sockaddr_ipx { sa_family_t sipx_family; uint32_t sipx_network; unsigned char sipx_node[IPX_NODE_LEN]; uint16_t sipx_port; uint8_t sipx_type; }; -#endif -#ifdef OF_WINDOWS +#elif defined(OF_WINDOWS) # define IPX_NODE_LEN 6 # define sipx_family sa_family # define sipx_network sa_netnum # define sipx_node sa_nodenum # define sipx_port sa_socket +#elif defined(OF_FREEBSD) +# define sipx_network sipx_addr.x_net.c_net +# define sipx_node sipx_addr.x_host.c_host #endif #ifndef OF_HAVE_APPLETALK struct sockaddr_at { sa_family_t sat_family; uint8_t sat_port; - struct at_addr { - uint16_t s_net; - uint8_t s_node; - } sat_addr; + uint16_t sat_net; + uint8_t sat_node; }; -#endif -#ifdef OF_WINDOWS -# define sat_port sat_socket #else -# define sat_net sat_addr.s_net -# define sat_node sat_addr.s_node +# ifdef OF_WINDOWS +# define sat_port sat_socket +# else +# define sat_net sat_addr.s_net +# define sat_node sat_addr.s_node +# endif #endif /** * @struct OFSocketAddress OFSocket.h ObjFW/OFSocket.h * * @brief A struct which represents a host / port pair for a socket. */ -typedef struct OF_BOXABLE { +typedef struct OF_BOXABLE OFSocketAddress { OFSocketAddressFamily family; /* * We can't use struct sockaddr as it can contain variable length * arrays. */ @@ -186,10 +189,17 @@ struct sockaddr_in in; struct sockaddr_in6 in6; struct sockaddr_un un; struct sockaddr_ipx ipx; struct sockaddr_at at; +#ifdef OF_HAVE_SOCKADDR_STORAGE + /* + * Required to make the ABI stable in case we want to add more + * address types later. + */ + struct sockaddr_storage storage; +#endif } sockaddr; socklen_t length; } OFSocketAddress; #ifdef __cplusplus @@ -278,15 +288,26 @@ /** * @brief Converts the specified @ref OFSocketAddress to a string. * * @param address The address to convert to a string - * @return The address as an IP string + * @return The address as a string, without the port */ extern OFString *_Nonnull OFSocketAddressString( const OFSocketAddress *_Nonnull address); +/** + * @brief Returns a description for the specified @ref OFSocketAddress. + * + * This is similar to @ref OFSocketAddressString, but it also contains the port. + * + * @param address The address to return a description for + * @return The address as an string, with the port + */ +extern OFString *_Nonnull OFSocketAddressDescription( + const OFSocketAddress *_Nonnull address); + /** * @brief Sets the IP port of the specified @ref OFSocketAddress. * * @param address The address on which to set the port * @param port The port to set on the address @@ -306,11 +327,11 @@ * @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( +extern OFString *OFSocketAddressUNIXPath( const OFSocketAddress *_Nonnull address); /** * @brief Sets the IPX network of the specified @ref OFSocketAddress. * Index: src/OFSocket.m ================================================================== --- src/OFSocket.m +++ src/OFSocket.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,11 +51,13 @@ #ifdef HAVE_NET_IF_H # include #endif #ifdef OF_AMIGAOS +# define Class IntuitionClass # include +# undef Class #endif #ifdef OF_NINTENDO_3DS # include <3ds/types.h> # include <3ds/services/soc.h> @@ -428,10 +430,38 @@ if (number > UINT16_MAX) @throw [OFInvalidFormatException exception]; return (uint16_t)number; } + +static OFString * +transformEmbeddedIPv4(OFString *IPv6) +{ + size_t lastColon = [IPv6 + rangeOfString: @":" + options: OFStringSearchBackwards].location; + OFString *IPv4; + OFSocketAddress address; + const struct sockaddr_in *addrIn; + uint32_t addr; + + if (lastColon == OFNotFound) + @throw [OFInvalidFormatException exception]; + + IPv4 = [IPv6 substringWithRange: + OFMakeRange(lastColon + 1, IPv6.length - lastColon - 1)]; + IPv6 = [IPv6 substringWithRange: OFMakeRange(0, lastColon + 1)]; + + address = OFSocketAddressParseIPv4(IPv4, 0); + addrIn = &address.sockaddr.in; + addr = OFFromBigEndian32(addrIn->sin_addr.s_addr); + + return [IPv6 stringByAppendingString: + [OFString stringWithFormat: @"%x%02x:%x%02x", + (addr & 0xFF000000) >> 24, (addr & 0x00FF0000) >> 16, + (addr & 0x0000FF00) >> 8, addr & 0x000000FF]]; +} OFSocketAddress OFSocketAddressParseIPv6(OFString *IPv6, uint16_t port) { void *pool = objc_autoreleasePoolPush(); @@ -465,10 +495,13 @@ } if (addrIn6->sin6_scope_id == 0) @throw [OFInvalidArgumentException exception]; } + + if ([IPv6 rangeOfString: @"."].location != OFNotFound) + IPv6 = transformEmbeddedIPv4(IPv6); doubleColon = [IPv6 rangeOfString: @"::"].location; if (doubleColon != OFNotFound) { OFString *left = [IPv6 substringToIndex: doubleColon]; OFString *right = [IPv6 substringFromIndex: doubleColon + 2]; @@ -555,10 +588,13 @@ memset(&ret, '\0', sizeof(ret)); ret.family = OFSocketAddressFamilyUNIX; ret.length = (socklen_t) (offsetof(struct sockaddr_un, sun_path) + length); +#ifdef HAVE_STRUCT_SOCKADDR_UN_SUN_LEN + ret.sockaddr.un.sun_len = (uint8_t)length; +#endif #ifdef AF_UNIX ret.sockaddr.un.sun_family = AF_UNIX; #else ret.sockaddr.un.sun_family = AF_UNSPEC; #endif @@ -904,21 +940,84 @@ [string makeImmutable]; return string; } + +static OFString * +IPXString(const OFSocketAddress *address) +{ + const struct sockaddr_ipx *addrIPX = &address->sockaddr.ipx; + uint32_t network; + uint64_t node; + + memcpy(&network, &addrIPX->sipx_network, sizeof(addrIPX->sipx_network)); + node = ((uint64_t)addrIPX->sipx_node[0] << 40) | + ((uint64_t)addrIPX->sipx_node[1] << 32) | + ((uint64_t)addrIPX->sipx_node[2] << 24) | + ((uint64_t)addrIPX->sipx_node[3] << 16) | + ((uint64_t)addrIPX->sipx_node[4] << 8) | + (uint64_t)addrIPX->sipx_node[5]; + + return [OFString stringWithFormat: @"%" PRIX32 ".%" PRIX64, + OFFromBigEndian32(network), node]; +} + +static OFString * +appleTalkString(const OFSocketAddress *address) +{ + const struct sockaddr_at *addrAT = &address->sockaddr.at; + + return [OFString stringWithFormat: @"%" PRIu8 ".%" PRIu8, + OFFromBigEndian16(addrAT->sat_net), addrAT->sat_node]; +} OFString * OFSocketAddressString(const OFSocketAddress *address) { switch (address->family) { case OFSocketAddressFamilyIPv4: return IPv4String(address); case OFSocketAddressFamilyIPv6: return IPv6String(address); + case OFSocketAddressFamilyUNIX: + return OFSocketAddressUNIXPath(address); + case OFSocketAddressFamilyIPX: + return IPXString(address); + case OFSocketAddressFamilyAppleTalk: + return appleTalkString(address); + default: + @throw [OFInvalidArgumentException exception]; + } +} + +OFString * +OFSocketAddressDescription(const OFSocketAddress *address) +{ + switch (address->family) { + case OFSocketAddressFamilyIPv4: + return [OFString + stringWithFormat: @"%@:%" PRIu16, + IPv4String(address), + OFSocketAddressIPPort(address)]; + case OFSocketAddressFamilyIPv6: + return [OFString + stringWithFormat: @"[%@]:%" PRIu16, + IPv6String(address), + OFSocketAddressIPPort(address)]; + case OFSocketAddressFamilyIPX: + return [OFString + stringWithFormat: @"%@.%" PRIX16, + IPXString(address), + OFSocketAddressIPXPort(address)]; + case OFSocketAddressFamilyAppleTalk: + return [OFString + stringWithFormat: @"%@." PRIu8, + appleTalkString(address), + OFSocketAddressAppleTalkPort(address)]; default: - @throw [OFInvalidArgumentException exception]; + return OFSocketAddressString(address); } } void OFSocketAddressSetIPPort(OFSocketAddress *address, uint16_t port) @@ -960,13 +1059,10 @@ 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]; } Index: src/OFSortedList.h ================================================================== --- src/OFSortedList.h +++ src/OFSortedList.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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.h ================================================================== --- src/OFStdIOStream.h +++ src/OFStdIOStream.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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.m ================================================================== --- src/OFStdIOStream.m +++ src/OFStdIOStream.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,11 @@ #import "OFStdIOStream+Private.h" #import "OFColor.h" #import "OFDate.h" #import "OFApplication.h" #ifdef OF_WINDOWS -# include "OFWin32ConsoleStdIOStream.h" +# import "OFWin32ConsoleStdIOStream.h" #endif #import "OFInitializationFailedException.h" #import "OFInvalidArgumentException.h" #import "OFNotOpenException.h" @@ -45,12 +45,14 @@ #ifdef OF_IOS # undef HAVE_ISATTY #endif #ifdef OF_AMIGAOS +# define Class IntuitionClass # include # include +# undef Class # undef HAVE_ISATTY #endif #ifdef OF_WII_U # define BOOL WUT_BOOL @@ -102,10 +104,13 @@ #ifdef OF_HAVE_FILES me = [OFApplication programName].lastPathComponent; #else me = [OFApplication programName]; #endif + + if (me == nil) + me = @"?"; msg = [[[OFString alloc] initWithFormat: format arguments: arguments] autorelease]; [OFStdErr writeFormat: @"[%@.%03d %@(%d)] %@\n", dateString, @@ -434,11 +439,11 @@ #endif } - (int)columns { -#if defined(HAVE_SYS_IOCTL_H) && defined(TIOCGWINSZ) && \ +#if defined(HAVE_IOCTL) && defined(TIOCGWINSZ) && \ !defined(OF_AMIGAOS) && !defined(OF_WII_U) struct winsize ws; if (ioctl(_fd, TIOCGWINSZ, &ws) != 0) return -1; @@ -449,11 +454,11 @@ #endif } - (int)rows { -#if defined(HAVE_SYS_IOCTL_H) && defined(TIOCGWINSZ) && \ +#if defined(HAVE_IOCTL) && defined(TIOCGWINSZ) && \ !defined(OF_AMIGAOS) && !defined(OF_WII_U) struct winsize ws; if (ioctl(_fd, TIOCGWINSZ, &ws) != 0) return -1; ADDED src/OFStrFTime.h Index: src/OFStrFTime.h ================================================================== --- /dev/null +++ src/OFStrFTime.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2008-2024 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#ifndef __STDC_LIMIT_MACROS +# define __STDC_LIMIT_MACROS +#endif +#ifndef __STDC_CONSTANT_MACROS +# define __STDC_CONSTANT_MACROS +#endif + +#include + +#import "macros.h" + +OF_ASSUME_NONNULL_BEGIN + +#ifdef __cplusplus +extern "C" { +#endif +extern size_t OFStrFTime(char *buffer, size_t bufferLen, const char *format, + struct tm *tm, short tz); +#ifdef __cplusplus +} +#endif + +OF_ASSUME_NONNULL_END ADDED src/OFStrFTime.m Index: src/OFStrFTime.m ================================================================== --- /dev/null +++ src/OFStrFTime.m @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2008-2024 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 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 + +#import "OFStrFTime.h" +#import "macros.h" + +static const char weekDays[7][4] = { + "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" +}; +static const char monthNames[12][4] = { + "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", + "Nov", "Dec" +}; + +size_t +OFStrFTime(char *buffer, size_t bufferLen, const char *format, struct tm *tm, + short tz) +{ + enum { + stateSearchConversionSpecifier, + stateInConversionSpecifier + } state = stateSearchConversionSpecifier; + size_t j, formatLen; + + if (bufferLen == 0) + return 0; + + formatLen = strlen(format); + + j = 0; + for (size_t i = 0; i < formatLen; i++) { + switch (state) { + case stateSearchConversionSpecifier: + if (format[i] == '%') + state = stateInConversionSpecifier; + else { + if (j >= bufferLen) + return 0; + + buffer[j++] = format[i]; + } + + break; + case stateInConversionSpecifier:; + const char *appendFormat; + unsigned int value = 0; + char append[5]; + int appendLen; + + switch (format[i]) { + case '%': + appendFormat = "%%"; + break; + case 'a': + if (tm->tm_wday > 6) + return 0; + + appendFormat = weekDays[tm->tm_wday]; + break; + case 'b': + if (tm->tm_mon > 11) + return 0; + + appendFormat = monthNames[tm->tm_mon]; + break; + case 'd': + appendFormat = "%02u"; + value = tm->tm_mday; + break; + case 'e': + appendFormat = "%2u"; + value = tm->tm_mday; + break; + case 'H': + appendFormat = "%02u"; + value = tm->tm_hour; + break; + case 'M': + appendFormat = "%02u"; + value = tm->tm_min; + break; + case 'm': + appendFormat = "%02u"; + value = tm->tm_mon + 1; + break; + case 'n': + appendFormat = "\n"; + break; + case 'S': + appendFormat = "%02u"; + value = tm->tm_sec; + break; + case 't': + appendFormat = "\t"; + break; + case 'Y': + appendFormat = "%4u"; + value = tm->tm_year + 1900; + break; + case 'y': + appendFormat = "%02u"; + value = tm->tm_year; + + while (value > 100) + value -= 100; + + break; + case 'z': + if (tz == 0) + appendFormat = "Z"; + else if (tz >= 0) { + appendFormat = "+%04u"; + value = tz; + } else { + appendFormat = "-%04u"; + value = -tz; + } + + value = (value / 60) * 100 + (value % 60); + break; + default: + return 0; + } + + appendLen = snprintf(append, sizeof(append), + appendFormat, value); + if (appendLen < 0 || + (size_t)appendLen >= sizeof(append)) + return 0; + + if (bufferLen - j < (size_t)appendLen) + return 0; + + memcpy(buffer + j, append, appendLen); + j += appendLen; + + state = stateSearchConversionSpecifier; + } + } + + if (j >= bufferLen) + return 0; + + buffer[j] = 0; + + return j; +} Index: src/OFStrPTime.h ================================================================== --- src/OFStrPTime.h +++ src/OFStrPTime.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,12 +15,11 @@ #include "config.h" #include -#include - +#import "OFStrPTime.h" #import "macros.h" const char * OFStrPTime(const char *buffer, const char *format, struct tm *tm, short *tz) { Index: src/OFStream+Private.h ================================================================== --- src/OFStream+Private.h +++ src/OFStream+Private.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,12 +15,11 @@ #import "OFStream.h" OF_ASSUME_NONNULL_BEGIN -OF_DIRECT_MEMBERS @interface OFStream () @property (readonly, nonatomic, getter=of_isWaitingForDelimiter) bool of_waitingForDelimiter; @end OF_ASSUME_NONNULL_END Index: src/OFStream.h ================================================================== --- src/OFStream.h +++ src/OFStream.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -216,10 +216,11 @@ * @brief Whether the stream can block. * * By default, a stream can block. * On Win32, setting this currently only works for sockets! * + * @throw OFGetOptionFailedException The option could not be retrieved * @throw OFSetOptionFailedException The option could not be set */ @property (nonatomic) bool canBlock; /** @@ -1388,8 +1389,20 @@ * implementation when subclassing! * * @return Whether the lowlevel is at the end of the stream */ - (bool)lowlevelIsAtEndOfStream; + +/** + * @brief Returns whether the lowlevel has data in the read buffer. + * + * @warning Do not call this directly! + * + * @note Override this method in case your stream can buffer data itself, such + * as when implementing @ref OFTLSStream. If not overridden, it always + * returns false. + * @return Whether the lowlevel has data in the read buffer + */ +- (bool)lowlevelHasDataInReadBuffer; @end OF_ASSUME_NONNULL_END Index: src/OFStream.m ================================================================== --- src/OFStream.m +++ src/OFStream.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,10 @@ #define __NO_EXT_QNX #include "config.h" -#include #include #include #include #include #include @@ -95,24 +94,29 @@ OFFreeMemory(_writeBuffer); [super dealloc]; } -- (bool)lowlevelIsAtEndOfStream -{ - OF_UNRECOGNIZED_SELECTOR -} - - (size_t)lowlevelReadIntoBuffer: (void *)buffer length: (size_t)length { OF_UNRECOGNIZED_SELECTOR } - (size_t)lowlevelWriteBuffer: (const void *)buffer length: (size_t)length { OF_UNRECOGNIZED_SELECTOR } + +- (bool)lowlevelIsAtEndOfStream +{ + OF_UNRECOGNIZED_SELECTOR +} + +- (bool)lowlevelHasDataInReadBuffer +{ + return false; +} - (id)copy { return [self retain]; } @@ -700,11 +704,11 @@ delimiterLength = 1; ret = [OFString stringWithCString: _readBuffer encoding: encoding - length: i + 1 - delimiterLength]; + length: i + 1 - delimiterLength]; _readBuffer += i + 1; _readBufferLength -= i + 1; _waitingForDelimiter = false; @@ -1185,11 +1189,11 @@ } } - (bool)hasDataInReadBuffer { - return (_readBufferLength > 0); + return (_readBufferLength > 0 || [self lowlevelHasDataInReadBuffer]); } - (bool)canBlock { return _canBlock; Index: src/OFStreamSocket+Private.h ================================================================== --- src/OFStreamSocket+Private.h +++ src/OFStreamSocket+Private.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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 @@ */ @interface OFStreamSocket: OFStream { OFSocketHandle _socket; +#ifdef OF_AMIGAOS + LONG _socketID; + int _family; /* unused, reserved for ABI stability */ +#endif bool _atEndOfStream, _listening; OFSocketAddress _remoteAddress; OF_RESERVE_IVARS(OFStreamSocket, 4) } @@ -159,8 +163,32 @@ * by the specified block as well. */ - (void)asyncAcceptWithRunLoopMode: (OFRunLoopMode)runLoopMode block: (OFStreamSocketAsyncAcceptBlock)block; #endif + +/** + * @brief Releases the socket from the current thread. + * + * This is necessary on some platforms in order to allow a different thread to + * use the socket, e.g. on AmigaOS, but you should call it on all operating + * systems before using the socket from a different thread. + * + * After calling this method, you must no longer use the socket until + * @ref obtainSocketForCurrentThread has been called. + */ +- (void)releaseSocketFromCurrentThread; + +/** + * @brief Obtains the socket for the current thread. + * + * This is necessary on some platforms in order to allow a different thread to + * use the socket, e.g. on AmigaOS, but you should call it on all operating + * systems before using the socket from a different thread. + * + * You must only call this method after @ref releaseSocketFromCurrentThread has + * been called from a different thread. + */ +- (void)obtainSocketForCurrentThread; @end OF_ASSUME_NONNULL_END Index: src/OFStreamSocket.m ================================================================== --- src/OFStreamSocket.m +++ src/OFStreamSocket.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,11 +19,10 @@ # define _XOPEN_SOURCE_EXTENDED #endif #define __NO_EXT_QNX #define _HPUX_ALT_XOPEN_SOCKET_API -#include #include #include #import "OFStreamSocket.h" #import "OFStreamSocket+Private.h" @@ -30,19 +29,25 @@ #import "OFRunLoop.h" #import "OFRunLoop+Private.h" #import "OFSocket+Private.h" #import "OFAcceptSocketFailedException.h" +#import "OFAlreadyOpenException.h" #import "OFInitializationFailedException.h" #import "OFInvalidArgumentException.h" #import "OFListenOnSocketFailedException.h" #import "OFNotImplementedException.h" #import "OFNotOpenException.h" +#import "OFOutOfMemoryException.h" #import "OFOutOfRangeException.h" #import "OFReadFailedException.h" #import "OFSetOptionFailedException.h" #import "OFWriteFailedException.h" + +#if defined(OF_AMIGAOS) && !defined(UNIQUE_ID) +# define UNIQUE_ID -1 +#endif @implementation OFStreamSocket @dynamic delegate; @synthesize listening = _listening; @@ -70,10 +75,13 @@ [self doesNotRecognizeSelector: _cmd]; abort(); } _socket = OFInvalidSocketHandle; +#ifdef OF_AMIGAOS + _socketID = -1; +#endif } @catch (id e) { [self release]; @throw e; } @@ -241,17 +249,21 @@ _listening = true; } - (instancetype)accept { - OFStreamSocket *client = [[[[self class] alloc] init] autorelease]; + OFStreamSocket *client; #if (!defined(HAVE_PACCEPT) && !defined(HAVE_ACCEPT4)) || !defined(SOCK_CLOEXEC) # if defined(HAVE_FCNTL) && defined(FD_CLOEXEC) int flags; # endif #endif + if (_socket == OFInvalidSocketHandle) + @throw [OFNotOpenException exceptionWithObject: self]; + + client = [[[[self class] alloc] init] autorelease]; client->_remoteAddress.length = (socklen_t)sizeof(client->_remoteAddress.sockaddr); #if defined(HAVE_PACCEPT) && defined(SOCK_CLOEXEC) if ((client->_socket = paccept(_socket, @@ -281,11 +293,11 @@ if ((flags = fcntl(client->_socket, F_GETFD, 0)) != -1) fcntl(client->_socket, F_SETFD, flags | FD_CLOEXEC); # endif #endif - assert(client->_remoteAddress.length <= + OFAssert(client->_remoteAddress.length <= (socklen_t)sizeof(client->_remoteAddress.sockaddr)); switch (((struct sockaddr *)&client->_remoteAddress.sockaddr) ->sa_family) { case AF_INET: @@ -354,10 +366,55 @@ if (_remoteAddress.length > (socklen_t)sizeof(_remoteAddress.sockaddr)) @throw [OFOutOfRangeException exception]; return &_remoteAddress; } + +- (void)releaseSocketFromCurrentThread +{ +#ifdef OF_AMIGAOS + if (_socket == OFInvalidSocketHandle) + @throw [OFNotOpenException exceptionWithObject: self]; + + if ((_socketID = ReleaseSocket(_socket, UNIQUE_ID)) == -1) { + switch (Errno()) { + case ENOMEM: + @throw [OFOutOfMemoryException + exceptionWithRequestedSize: 0]; + case EBADF: + @throw [OFNotOpenException exceptionWithObject: self]; + default: + OFEnsure(0); + } + } + + _socket = OFInvalidSocketHandle; +#endif +} + +- (void)obtainSocketForCurrentThread +{ +#ifdef OF_AMIGAOS + if (_socket != OFInvalidSocketHandle) + @throw [OFAlreadyOpenException exceptionWithObject: self]; + + if (_socketID == -1) + @throw [OFNotOpenException exceptionWithObject: self]; + + /* + * FIXME: We should store these, but that requires changing all + * subclasses. This only becomes a problem if IPv6 support ever + * gets added. + */ + _socket = ObtainSocket(_socketID, AF_INET, SOCK_STREAM, 0); + if (_socket == OFInvalidSocketHandle) + @throw [OFInitializationFailedException + exceptionWithClass: self.class]; + + _socketID = -1; +#endif +} - (void)close { if (_socket == OFInvalidSocketHandle) @throw [OFNotOpenException exceptionWithObject: self]; Index: src/OFString+CryptographicHashing.h ================================================================== --- src/OFString+CryptographicHashing.h +++ src/OFString+CryptographicHashing.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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.h ================================================================== --- src/OFString+JSONParsing.h +++ src/OFString+JSONParsing.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,12 +18,10 @@ #include #include #include -#include - #import "OFString+JSONParsing.h" #import "OFArray.h" #import "OFDictionary.h" #import "OFNumber.h" #import "OFNull.h" @@ -651,14 +649,10 @@ const char *pointer = self.UTF8String; const char *stop = pointer + self.UTF8StringLength; id object; size_t line = 1; -#ifdef __clang_analyzer__ - assert(pointer != NULL); -#endif - object = nextObject(&pointer, stop, &line, depthLimit); skipWhitespacesAndComments(&pointer, stop, &line); if (pointer < stop || object == nil) @throw [OFInvalidJSONException exceptionWithString: self Index: src/OFString+PathAdditions.h ================================================================== --- src/OFString+PathAdditions.h +++ src/OFString+PathAdditions.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -84,13 +84,13 @@ * @return A new, autoreleased OFString with the path extension appended */ - (OFString *)stringByAppendingPathExtension: (OFString *)extension; - (bool)of_isDirectoryPath; -- (OFString *)of_pathToURIPathWithPercentEncodedHost: +- (OFString *)of_pathToIRIPathWithPercentEncodedHost: (OFString *__autoreleasing _Nullable *_Nonnull)percentEncodedHost; -- (OFString *)of_URIPathToPathWithPercentEncodedHost: +- (OFString *)of_IRIPathToPathWithPercentEncodedHost: (nullable OFString *)percentEncodedHost; -- (OFString *)of_pathComponentToURIPathComponent; +- (OFString *)of_pathComponentToIRIPathComponent; @end OF_ASSUME_NONNULL_END Index: src/OFString+PathAdditions.m ================================================================== --- src/OFString+PathAdditions.m +++ src/OFString+PathAdditions.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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+PercentEncoding.h ================================================================== --- src/OFString+PercentEncoding.h +++ src/OFString+PercentEncoding.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,11 +34,11 @@ * @throw OFInvalidFormatException The string is not in proper percent encoding */ @property (readonly, nonatomic) OFString *stringByRemovingPercentEncoding; /** - * @brief Percent-encodes a string for use in a URI, but does not escape the + * @brief Percent-encodes a string for use in an IRI, but does not escape the * specified allowed characters. * * @param allowedCharacters A character set of characters that should not be * escaped * Index: src/OFString+PercentEncoding.m ================================================================== --- src/OFString+PercentEncoding.m +++ src/OFString+PercentEncoding.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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.h ================================================================== --- src/OFString+PropertyListParsing.h +++ src/OFString+PropertyListParsing.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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/OFString+Serialization.h Index: src/OFString+Serialization.h ================================================================== --- src/OFString+Serialization.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2008-2022 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#import "OFString.h" - -OF_ASSUME_NONNULL_BEGIN - -#ifdef __cplusplus -extern "C" { -#endif -extern int _OFString_Serialization_reference; -#ifdef __cplusplus -} -#endif - -@interface OFString (Serialization) -/** - * @brief The string interpreted as serialization and parsed as an object. - * - * @throw OFMalformedXMLException The XML was malformed - * @throw OFUnboundNamespaceException A prefix was used that was not bound to - * any namespace - * @throw OFInvalidEncodingException The XML is not in the encoding it specified - * @throw OFUnsupportedVersionException The serialization is in an unsupported - * version - */ -@property (readonly, nonatomic) id objectByDeserializing; -@end - -OF_ASSUME_NONNULL_END DELETED src/OFString+Serialization.m Index: src/OFString+Serialization.m ================================================================== --- src/OFString+Serialization.m +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) 2008-2022 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#include "config.h" - -#import "OFString.h" -#import "OFString+Serialization.h" -#import "OFSerialization.h" -#import "OFArray.h" -#import "OFXMLElement.h" -#import "OFXMLAttribute.h" - -#import "OFInvalidArgumentException.h" -#import "OFMalformedXMLException.h" -#import "OFUnboundNamespaceException.h" -#import "OFUnsupportedVersionException.h" - -int _OFString_Serialization_reference; - -@implementation OFString (Serialization) -- (id)objectByDeserializing -{ - void *pool = objc_autoreleasePoolPush(); - OFXMLElement *root; - OFString *version; - OFArray *elements; - id object; - - root = [OFXMLElement elementWithXMLString: self]; - - version = [root attributeForName: @"version"].stringValue; - if (version == nil) - @throw [OFInvalidArgumentException exception]; - - if (version.unsignedLongLongValue != 1) - @throw [OFUnsupportedVersionException - exceptionWithVersion: version]; - - elements = [root elementsForNamespace: OFSerializationNS]; - - if (elements.count != 1) - @throw [OFInvalidArgumentException exception]; - - object = [[elements.firstObject objectByDeserializing] retain]; - - objc_autoreleasePoolPop(pool); - - return [object autorelease]; -} -@end Index: src/OFString+XMLEscaping.h ================================================================== --- src/OFString+XMLEscaping.h +++ src/OFString+XMLEscaping.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,11 +13,10 @@ * file. */ #include "config.h" -#include #include #include #import "OFString.h" @@ -86,11 +85,11 @@ memcpy(retCString + j, append, appendLen); j += appendLen; } else retCString[j++] = string[i]; } - assert(j == retLength); + OFAssert(j == retLength); objc_autoreleasePoolPop(pool); @try { ret = [OFString stringWithUTF8String: retCString Index: src/OFString+XMLUnescaping.h ================================================================== --- src/OFString+XMLUnescaping.h +++ src/OFString+XMLUnescaping.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,13 +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. */ -#ifndef OBJFW_OF_STRING_H -#define OBJFW_OF_STRING_H - #ifndef __STDC_LIMIT_MACROS # define __STDC_LIMIT_MACROS #endif #ifndef __STDC_CONSTANT_MACROS # define __STDC_CONSTANT_MACROS @@ -33,27 +30,23 @@ #include #ifdef OF_HAVE_INTTYPES_H # include #endif -#include "OFObject.h" -#ifdef __OBJC__ -# import "OFSerialization.h" -# import "OFJSONRepresentation.h" -# import "OFMessagePackRepresentation.h" -#endif +#import "OFObject.h" +#import "OFJSONRepresentation.h" +#import "OFMessagePackRepresentation.h" OF_ASSUME_NONNULL_BEGIN /** @file */ -#ifdef __OBJC__ +@class OFArray OF_GENERIC(ObjectType); +@class OFCharacterSet; @class OFConstantString; +@class OFIRI; @class OFString; -#else -typedef void OFString; -#endif #if defined(__cplusplus) && __cplusplus >= 201103L typedef char16_t OFChar16; typedef char32_t OFChar32; #else @@ -131,22 +124,17 @@ * enumeration */ typedef void (^OFStringLineEnumerationBlock)(OFString *line, bool *stop); #endif -#ifdef __OBJC__ -@class OFArray OF_GENERIC(ObjectType); -@class OFCharacterSet; -@class OFURI; - /** * @class OFString OFString.h ObjFW/OFString.h * * @brief A class for handling strings. */ @interface OFString: OFObject + OFJSONRepresentation, OFMessagePackRepresentation> /** * @brief The length of the string in Unicode codepoints. */ @property (readonly, nonatomic) size_t length; @@ -155,11 +143,11 @@ * * The result is valid until the autorelease pool is released. If you want to * use the result outside the scope of the current autorelease pool, you have to * copy it. */ -@property (readonly, nonatomic) const char *UTF8String OF_RETURNS_INNER_POINTER; +@property (readonly, nonatomic) const char *UTF8String; /** * @brief The number of bytes the string needs in UTF-8 encoding. */ @property (readonly, nonatomic) size_t UTF8StringLength; @@ -232,12 +220,11 @@ * use the result outside the scope of the current autorelease pool, you have to * copy it. * * The returned string is *not* null-terminated. */ -@property (readonly, nonatomic) const OFUnichar *characters - OF_RETURNS_INNER_POINTER; +@property (readonly, nonatomic) const OFUnichar *characters; /** * @brief The string in UTF-16 encoding with native byte order. * * The result is valid until the autorelease pool is released. If you want to @@ -244,12 +231,11 @@ * use the result outside the scope of the current autorelease pool, you have to * copy it. * * The returned string is null-terminated. */ -@property (readonly, nonatomic) const OFChar16 *UTF16String - OF_RETURNS_INNER_POINTER; +@property (readonly, nonatomic) const OFChar16 *UTF16String; /** * @brief The length of the string in UTF-16 characters. */ @property (readonly, nonatomic) size_t UTF16StringLength; @@ -261,12 +247,11 @@ * use the result outside the scope of the current autorelease pool, you have to * copy it. * * The returned string is null-terminated. */ -@property (readonly, nonatomic) const OFChar32 *UTF32String - OF_RETURNS_INNER_POINTER; +@property (readonly, nonatomic) const OFChar32 *UTF32String; /** * @brief The string with leading whitespaces deleted. */ @property (readonly, nonatomic) OFString *stringByDeletingLeadingWhitespaces; @@ -279,30 +264,17 @@ /** * @brief The string with leading and trailing whitespaces deleted. */ @property (readonly, nonatomic) OFString *stringByDeletingEnclosingWhitespaces; -# ifdef OF_HAVE_UNICODE_TABLES -/** - * @brief The string in Unicode Normalization Form D (NFD). - */ -@property (readonly, nonatomic) OFString *decomposedStringWithCanonicalMapping; - -/** - * @brief The string in Unicode Normalization Form KD (NFKD). - */ -@property (readonly, nonatomic) - OFString *decomposedStringWithCompatibilityMapping; -# endif - -# ifdef OF_WINDOWS +#if defined(OF_WINDOWS) || defined(DOXYGEN) /** * @brief The string with the Windows Environment Strings expanded. */ @property (readonly, nonatomic) OFString *stringByExpandingWindowsEnvironmentStrings; -# endif +#endif /** * @brief Creates a new OFString. * * @return A new, autoreleased OFString @@ -528,11 +500,11 @@ * @throw OFInvalidEncodingException The resulting string is not in not in UTF-8 * encoding */ + (instancetype)stringWithFormat: (OFConstantString *)format, ...; -# ifdef OF_HAVE_FILES +#ifdef OF_HAVE_FILES /** * @brief Creates a new OFString with the contents of the specified UTF-8 * encoded file. * * @param path The path to the file @@ -550,39 +522,46 @@ * @return A new autoreleased OFString * @throw OFInvalidEncodingException The string is not in the specified encoding */ + (instancetype)stringWithContentsOfFile: (OFString *)path encoding: (OFStringEncoding)encoding; -# endif +#endif /** - * @brief Creates a new OFString with the contents of the specified URI. + * @brief Creates a new OFString with the contents of the specified IRI. * - * If the URI's scheme is file, it tries UTF-8 encoding. + * If the IRI's scheme is file, it tries UTF-8 encoding. * - * If the URI's scheme is http(s), it tries to detect the encoding from the HTTP + * If the IRI's scheme is http(s), it tries to detect the encoding from the HTTP * headers. If it could not detect the encoding using the HTTP headers, it tries * UTF-8. * - * @param URI The URI to the contents for the string + * @param IRI The IRI to the contents for the string * @return A new autoreleased OFString * @throw OFInvalidEncodingException The string is not in the expected encoding */ -+ (instancetype)stringWithContentsOfURI: (OFURI *)URI; ++ (instancetype)stringWithContentsOfIRI: (OFIRI *)IRI; /** - * @brief Creates a new OFString with the contents of the specified URI in the + * @brief Creates a new OFString with the contents of the specified IRI in the * specified encoding. * - * @param URI The URI to the contents for the string + * @param IRI The IRI to the contents for the string * @param encoding The encoding to assume * @return A new autoreleased OFString * @throw OFInvalidEncodingException The string is not in the specified encoding */ -+ (instancetype)stringWithContentsOfURI: (OFURI *)URI ++ (instancetype)stringWithContentsOfIRI: (OFIRI *)IRI encoding: (OFStringEncoding)encoding; +/** + * @brief Initializes an already allocated OFString to be empty. + * + * @return An initialized OFString + */ +- (instancetype)init OF_DESIGNATED_INITIALIZER; + /** * @brief Initializes an already allocated OFString from a UTF-8 encoded C * string. * * @param UTF8String A UTF-8 encoded C string to initialize the OFString with @@ -821,11 +800,11 @@ * encoding */ - (instancetype)initWithFormat: (OFConstantString *)format arguments: (va_list)arguments; -# ifdef OF_HAVE_FILES +#ifdef OF_HAVE_FILES /** * @brief Initializes an already allocated OFString with the contents of the * specified file in the specified encoding. * * @param path The path to the file @@ -843,38 +822,38 @@ * @return An initialized OFString * @throw OFInvalidEncodingException The string is not in the specified encoding */ - (instancetype)initWithContentsOfFile: (OFString *)path encoding: (OFStringEncoding)encoding; -# endif +#endif /** * @brief Initializes an already allocated OFString with the contents of the - * specified URI. + * specified IRI. * - * If the URI's scheme is file, it tries UTF-8 encoding. + * If the IRI's scheme is file, it tries UTF-8 encoding. * - * If the URI's scheme is http(s), it tries to detect the encoding from the HTTP + * If the IRI's scheme is http(s), it tries to detect the encoding from the HTTP * headers. If it could not detect the encoding using the HTTP headers, it tries * UTF-8. * - * @param URI The URI to the contents for the string + * @param IRI The IRI to the contents for the string * @return An initialized OFString * @throw OFInvalidEncodingException The string is not in the expected encoding */ -- (instancetype)initWithContentsOfURI: (OFURI *)URI; +- (instancetype)initWithContentsOfIRI: (OFIRI *)IRI; /** * @brief Initializes an already allocated OFString with the contents of the - * specified URI in the specified encoding. + * specified IRI in the specified encoding. * - * @param URI The URI to the contents for the string + * @param IRI The IRI to the contents for the string * @param encoding The encoding to assume * @return An initialized OFString * @throw OFInvalidEncodingException The string is not in the specified encoding */ -- (instancetype)initWithContentsOfURI: (OFURI *)URI +- (instancetype)initWithContentsOfIRI: (OFIRI *)IRI encoding: (OFStringEncoding)encoding; /** * @brief Writes the OFString into the specified C string with the specified * encoding. @@ -918,12 +897,11 @@ * @param encoding The encoding for the C string * @return The OFString as a C string in the specified encoding * @throw OFInvalidEncodingException The string cannot be represented in the * specified encoding */ -- (const char *)cStringWithEncoding: (OFStringEncoding)encoding - OF_RETURNS_INNER_POINTER; +- (const char *)cStringWithEncoding: (OFStringEncoding)encoding; /** * @brief Returns the OFString as a C string in the specified encoding, * replacing characters that cannot be represented in the specified * encoding with a question mark. @@ -933,12 +911,11 @@ * copy it. * * @param encoding The encoding for the C string * @return The OFString as a C string in the specified encoding */ -- (const char *)lossyCStringWithEncoding: (OFStringEncoding)encoding - OF_RETURNS_INNER_POINTER; +- (const char *)lossyCStringWithEncoding: (OFStringEncoding)encoding; /** * @brief Returns the number of bytes the string needs in the specified * encoding. * @@ -1256,12 +1233,11 @@ * * @param byteOrder The byte order for the UTF-16 encoding * @return The string in UTF-16 encoding with the specified byte order * @throw OFInvalidEncodingException The string cannot be represented in UTF-16 */ -- (const OFChar16 *)UTF16StringWithByteOrder: (OFByteOrder)byteOrder - OF_RETURNS_INNER_POINTER; +- (const OFChar16 *)UTF16StringWithByteOrder: (OFByteOrder)byteOrder; /** * @brief Returns the string in UTF-32 encoding with the specified byte order. * * The result is valid until the autorelease pool is released. If you want to @@ -1271,12 +1247,11 @@ * The returned string is null-terminated. * * @param byteOrder The byte order for the UTF-32 encoding * @return The string in UTF-32 encoding with the specified byte order */ -- (const OFChar32 *)UTF32StringWithByteOrder: (OFByteOrder)byteOrder - OF_RETURNS_INNER_POINTER; +- (const OFChar32 *)UTF32StringWithByteOrder: (OFByteOrder)byteOrder; /** * @brief Returns the string as OFData with the specified encoding. * * @param encoding The encoding to use for the returned OFData @@ -1284,11 +1259,11 @@ * @throw OFInvalidEncodingException The string cannot be represented in the * specified encoding */ - (OFData *)dataWithEncoding: (OFStringEncoding)encoding; -# ifdef OF_HAVE_FILES +#ifdef OF_HAVE_FILES /** * @brief Writes the string into the specified file using UTF-8 encoding. * * @param path The path of the file to write to */ @@ -1302,39 +1277,38 @@ * @param encoding The encoding to use to write the string into the file * @throw OFInvalidEncodingException The string cannot be represented in the * specified encoding */ - (void)writeToFile: (OFString *)path encoding: (OFStringEncoding)encoding; -# endif +#endif /** - * @brief Writes the string to the specified URI using UTF-8 encoding. + * @brief Writes the string to the specified IRI using UTF-8 encoding. * - * @param URI The URI to write to + * @param IRI The IRI to write to */ -- (void)writeToURI: (OFURI *)URI; +- (void)writeToIRI: (OFIRI *)IRI; /** - * @brief Writes the string to the specified URI using the specified encoding. + * @brief Writes the string to the specified IRI using the specified encoding. * - * @param URI The URI to write to - * @param encoding The encoding to use to write the string to the URI + * @param IRI The IRI to write to + * @param encoding The encoding to use to write the string to the IRI * @throw OFInvalidEncodingException The string cannot be represented in the * specified encoding */ -- (void)writeToURI: (OFURI *)URI encoding: (OFStringEncoding)encoding; +- (void)writeToIRI: (OFIRI *)IRI encoding: (OFStringEncoding)encoding; -# ifdef OF_HAVE_BLOCKS +#ifdef OF_HAVE_BLOCKS /** * Enumerates all lines in the receiver using the specified block. * * @brief block The block to call for each line */ - (void)enumerateLinesUsingBlock: (OFStringLineEnumerationBlock)block; -# endif -@end #endif +@end #ifdef __cplusplus extern "C" { #endif /** @@ -1366,26 +1340,23 @@ } #endif OF_ASSUME_NONNULL_END -#include "OFConstantString.h" -#include "OFMutableString.h" -#ifdef __OBJC__ -# import "OFString+CryptographicHashing.h" -# import "OFString+JSONParsing.h" -# ifdef OF_HAVE_FILES -# import "OFString+PathAdditions.h" -# endif -# import "OFString+PercentEncoding.h" -# import "OFString+PropertyListParsing.h" -# import "OFString+Serialization.h" -# import "OFString+XMLEscaping.h" -# import "OFString+XMLUnescaping.h" -#endif - -#if defined(__OBJC__) && !defined(NSINTEGER_DEFINED) && !__has_feature(modules) +#import "OFConstantString.h" +#import "OFMutableString.h" +#import "OFString+CryptographicHashing.h" +#import "OFString+JSONParsing.h" +#ifdef OF_HAVE_FILES +# import "OFString+PathAdditions.h" +#endif +#import "OFString+PercentEncoding.h" +#import "OFString+PropertyListParsing.h" +#import "OFString+XMLEscaping.h" +#import "OFString+XMLUnescaping.h" + +#if !defined(NSINTEGER_DEFINED) && !__has_feature(modules) /* * Very *ugly* hack required for string boxing literals to work. * * This hack is needed in order to work with `@class NSString` from Apple's * objc/NSString.h - which is included when using modules - as @@ -1396,8 +1367,6 @@ * * TODO: Submit a patch for Clang that makes the boxing classes configurable! */ @interface NSString: OFString @end -#endif - #endif Index: src/OFString.m ================================================================== --- src/OFString.m +++ src/OFString.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,11 +20,11 @@ #include #include #include #include -#if defined(HAVE_STRTOF_L) || defined(HAVE_STRTOD_L) +#if defined(HAVE_STRTOF_L) || defined(HAVE_STRTOD_L) || defined(HAVE_USELOCALE) # include #endif #ifdef HAVE_XLOCALE_H # include #endif @@ -37,18 +37,17 @@ #import "OFDictionary.h" #ifdef OF_HAVE_FILES # import "OFFile.h" # import "OFFileManager.h" #endif +#import "OFIRI.h" +#import "OFIRIHandler.h" #import "OFLocale.h" #import "OFStream.h" #import "OFSystemInfo.h" -#import "OFURI.h" -#import "OFURIHandler.h" #import "OFUTF8String.h" #import "OFUTF8String+Private.h" -#import "OFXMLElement.h" #import "OFGetItemAttributesFailedException.h" #import "OFInitializationFailedException.h" #import "OFInvalidArgumentException.h" #import "OFInvalidEncodingException.h" @@ -80,11 +79,11 @@ static struct { Class isa; } placeholder; -#if defined(HAVE_STRTOF_L) || defined(HAVE_STRTOD_L) +#if defined(HAVE_STRTOF_L) || defined(HAVE_STRTOD_L) || defined(HAVE_USELOCALE) static locale_t cLocale; #endif @interface OFString () - (size_t)of_getCString: (char *)cString @@ -96,11 +95,11 @@ - (OFString *) of_JSONRepresentationWithOptions: (OFJSONRepresentationOptions)options depth: (size_t)depth; @end -@interface OFStringPlaceholder: OFString +@interface OFPlaceholderString: OFString @end extern bool OFUnicodeToISO8859_2(const OFUnichar *, unsigned char *, size_t, bool); extern bool OFUnicodeToISO8859_3(const OFUnichar *, unsigned char *, @@ -133,11 +132,10 @@ #ifdef OF_HAVE_FILES _OFString_PathAdditions_reference = 1; #endif _OFString_PercentEncoding_reference = 1; _OFString_PropertyListParsing_reference = 1; - _OFString_Serialization_reference = 1; _OFString_XMLEscaping_reference = 1; _OFString_XMLUnescaping_reference = 1; } void @@ -346,42 +344,17 @@ memcpy(copy, string, length + 1); return copy; } -#ifdef OF_HAVE_UNICODE_TABLES -static OFString * -decomposedString(OFString *self, const char *const *const *table, size_t size) -{ - OFMutableString *ret = [OFMutableString string]; - void *pool = objc_autoreleasePoolPush(); - const OFUnichar *characters = self.characters; - size_t length = self.length; - - for (size_t i = 0; i < length; i++) { - OFUnichar c = characters[i]; - const char *const *page; - - if (c >= size) { - [ret appendCharacters: &c length: 1]; - continue; - } - - page = table[c >> 8]; - if (page != NULL && page[c & 0xFF] != NULL) - [ret appendUTF8String: page[c & 0xFF]]; - else - [ret appendCharacters: &c length: 1]; - } - - objc_autoreleasePoolPop(pool); - - return ret; -} +@implementation OFPlaceholderString +#ifdef __clang__ +/* We intentionally don't call into super, so silence the warning. */ +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wunknown-pragmas" +# pragma clang diagnostic ignored "-Wobjc-designated-initializers" #endif - -@implementation OFStringPlaceholder - (instancetype)init { return (id)[[OFUTF8String alloc] init]; } @@ -580,56 +553,37 @@ return (id)[[OFUTF8String alloc] initWithContentsOfFile: path encoding: encoding]; } #endif -- (instancetype)initWithContentsOfURI: (OFURI *)URI +- (instancetype)initWithContentsOfIRI: (OFIRI *)IRI { - return (id)[[OFUTF8String alloc] initWithContentsOfURI: URI]; + return (id)[[OFUTF8String alloc] initWithContentsOfIRI: IRI]; } -- (instancetype)initWithContentsOfURI: (OFURI *)URI +- (instancetype)initWithContentsOfIRI: (OFIRI *)IRI encoding: (OFStringEncoding)encoding { - return (id)[[OFUTF8String alloc] initWithContentsOfURI: URI + return (id)[[OFUTF8String alloc] initWithContentsOfIRI: IRI encoding: encoding]; } - -- (instancetype)initWithSerialization: (OFXMLElement *)element -{ - return (id)[[OFUTF8String alloc] initWithSerialization: element]; -} - -- (instancetype)retain -{ - return self; -} - -- (instancetype)autorelease -{ - return self; -} - -- (void)release -{ -} - -- (void)dealloc -{ - OF_DEALLOC_UNSUPPORTED -} +#ifdef __clang__ +# pragma clang diagnostic pop +#endif + +OF_SINGLETON_METHODS @end @implementation OFString + (void)initialize { if (self != [OFString class]) return; - placeholder.isa = [OFStringPlaceholder class]; + object_setClass((id)&placeholder, [OFPlaceholderString class]); -#if defined(HAVE_STRTOF_L) || defined(HAVE_STRTOD_L) +#if defined(HAVE_STRTOF_L) || defined(HAVE_STRTOD_L) || defined(HAVE_USELOCALE) if ((cLocale = newlocale(LC_ALL_MASK, "C", NULL)) == NULL) @throw [OFInitializationFailedException exceptionWithClass: self]; #endif } @@ -794,25 +748,26 @@ return [[[self alloc] initWithContentsOfFile: path encoding: encoding] autorelease]; } #endif -+ (instancetype)stringWithContentsOfURI: (OFURI *)URI ++ (instancetype)stringWithContentsOfIRI: (OFIRI *)IRI { - return [[[self alloc] initWithContentsOfURI: URI] autorelease]; + return [[[self alloc] initWithContentsOfIRI: IRI] autorelease]; } -+ (instancetype)stringWithContentsOfURI: (OFURI *)URI ++ (instancetype)stringWithContentsOfIRI: (OFIRI *)IRI encoding: (OFStringEncoding)encoding { - return [[[self alloc] initWithContentsOfURI: URI + return [[[self alloc] initWithContentsOfIRI: IRI encoding: encoding] autorelease]; } - (instancetype)init { - if ([self isMemberOfClass: [OFString class]]) { + if ([self isMemberOfClass: [OFString class]] || + [self isMemberOfClass: [OFMutableString class]]) { @try { [self doesNotRecognizeSelector: _cmd]; } @catch (id e) { [self release]; @throw e; @@ -868,16 +823,25 @@ return [self initWithCString: cString encoding: encoding length: strlen(cString)]; } +#ifdef __clang__ +/* We intentionally don't call into super, so silence the warning. */ +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wunknown-pragmas" +# pragma clang diagnostic ignored "-Wobjc-designated-initializers" +#endif - (instancetype)initWithCString: (const char *)cString encoding: (OFStringEncoding)encoding length: (size_t)cStringLength { OF_INVALID_INIT_METHOD } +#ifdef __clang__ +# pragma clang diagnostic pop +#endif - (instancetype)initWithData: (OFData *)data encoding: (OFStringEncoding)encoding { @try { @@ -893,10 +857,16 @@ length: data.count]; return self; } +#ifdef __clang__ +/* We intentionally don't call into super, so silence the warning. */ +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wunknown-pragmas" +# pragma clang diagnostic ignored "-Wobjc-designated-initializers" +#endif - (instancetype)initWithString: (OFString *)string { OF_INVALID_INIT_METHOD } @@ -903,10 +873,13 @@ - (instancetype)initWithCharacters: (const OFUnichar *)string length: (size_t)length { OF_INVALID_INIT_METHOD } +#ifdef __clang__ +# pragma clang diagnostic pop +#endif - (instancetype)initWithUTF16String: (const OFChar16 *)string { return [self initWithUTF16String: string length: OFUTF16StringLength(string) @@ -927,16 +900,25 @@ return [self initWithUTF16String: string length: OFUTF16StringLength(string) byteOrder: byteOrder]; } +#ifdef __clang__ +/* We intentionally don't call into super, so silence the warning. */ +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wunknown-pragmas" +# pragma clang diagnostic ignored "-Wobjc-designated-initializers" +#endif - (instancetype)initWithUTF16String: (const OFChar16 *)string length: (size_t)length byteOrder: (OFByteOrder)byteOrder { OF_INVALID_INIT_METHOD } +#ifdef __clang__ +# pragma clang diagnostic pop +#endif - (instancetype)initWithUTF32String: (const OFChar32 *)string { return [self initWithUTF32String: string length: OFUTF32StringLength(string) @@ -957,16 +939,25 @@ return [self initWithUTF32String: string length: OFUTF32StringLength(string) byteOrder: byteOrder]; } +#ifdef __clang__ +/* We intentionally don't call into super, so silence the warning. */ +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wunknown-pragmas" +# pragma clang diagnostic ignored "-Wobjc-designated-initializers" +#endif - (instancetype)initWithUTF32String: (const OFChar32 *)string length: (size_t)length byteOrder: (OFByteOrder)byteOrder { OF_INVALID_INIT_METHOD } +#ifdef __clang__ +# pragma clang diagnostic pop +#endif - (instancetype)initWithFormat: (OFConstantString *)format, ... { id ret; va_list arguments; @@ -976,15 +967,24 @@ va_end(arguments); return ret; } +#ifdef __clang__ +/* We intentionally don't call into super, so silence the warning. */ +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wunknown-pragmas" +# pragma clang diagnostic ignored "-Wobjc-designated-initializers" +#endif - (instancetype)initWithFormat: (OFConstantString *)format arguments: (va_list)arguments { OF_INVALID_INIT_METHOD } +#ifdef __clang__ +# pragma clang diagnostic pop +#endif #ifdef OF_HAVE_FILES - (instancetype)initWithContentsOfFile: (OFString *)path { return [self initWithContentsOfFile: path @@ -992,79 +992,42 @@ } - (instancetype)initWithContentsOfFile: (OFString *)path encoding: (OFStringEncoding)encoding { - char *buffer = NULL; - OFStreamOffset fileSize; - - @try { - void *pool = objc_autoreleasePoolPush(); - OFFile *file = [OFFile fileWithPath: path mode: @"r"]; - fileSize = [file seekToOffset: 0 whence: OFSeekEnd]; - - if (fileSize < 0 || (unsigned long long)fileSize > SIZE_MAX) - @throw [OFOutOfRangeException exception]; - - /* - * We need one extra byte for the terminating zero if we want - * to use -[initWithUTF8StringNoCopy:length:freeWhenDone:]. - */ - if (SIZE_MAX - (size_t)fileSize < 1) - @throw [OFOutOfRangeException exception]; - - [file seekToOffset: 0 whence: OFSeekSet]; - - buffer = OFAllocMemory((size_t)fileSize + 1, 1); - [file readIntoBuffer: buffer exactLength: (size_t)fileSize]; - buffer[(size_t)fileSize] = '\0'; - - objc_autoreleasePoolPop(pool); - } @catch (id e) { - OFFreeMemory(buffer); - [self release]; - - @throw e; - } - - if (encoding == OFStringEncodingUTF8) { - @try { - self = [self initWithUTF8StringNoCopy: buffer - length: (size_t)fileSize - freeWhenDone: true]; - } @catch (id e) { - OFFreeMemory(buffer); - @throw e; - } - } else { - @try { - self = [self initWithCString: buffer - encoding: encoding - length: (size_t)fileSize]; - } @finally { - OFFreeMemory(buffer); - } - } + void *pool = objc_autoreleasePoolPush(); + OFIRI *IRI; + + @try { + IRI = [OFIRI fileIRIWithPath: path]; + } @catch (id e) { + [self release]; + @throw e; + } + + self = [self initWithContentsOfIRI: IRI encoding: encoding]; + + objc_autoreleasePoolPop(pool); return self; } #endif -- (instancetype)initWithContentsOfURI: (OFURI *)URI +- (instancetype)initWithContentsOfIRI: (OFIRI *)IRI { - return [self initWithContentsOfURI: URI + return [self initWithContentsOfIRI: IRI encoding: OFStringEncodingAutodetect]; } -- (instancetype)initWithContentsOfURI: (OFURI *)URI +- (instancetype)initWithContentsOfIRI: (OFIRI *)IRI encoding: (OFStringEncoding)encoding { void *pool = objc_autoreleasePoolPush(); OFData *data; @try { - data = [OFData dataWithContentsOfURI: URI]; + data = [OFData dataWithContentsOfIRI: IRI]; } @catch (id e) { [self release]; @throw e; } @@ -1074,40 +1037,10 @@ self = [self initWithCString: data.items encoding: encoding length: data.count * data.itemSize]; - objc_autoreleasePoolPop(pool); - - return self; -} - -- (instancetype)initWithSerialization: (OFXMLElement *)element -{ - void *pool = objc_autoreleasePoolPush(); - OFString *stringValue; - - @try { - if (![element.namespace isEqual: OFSerializationNS]) - @throw [OFInvalidArgumentException exception]; - - if ([self isKindOfClass: [OFMutableString class]]) { - if (![element.name isEqual: @"OFMutableString"]) - @throw [OFInvalidArgumentException exception]; - } else { - if (![element.name isEqual: @"OFString"]) - @throw [OFInvalidArgumentException exception]; - } - - stringValue = element.stringValue; - } @catch (id e) { - [self release]; - @throw e; - } - - self = [self initWithString: stringValue]; - objc_autoreleasePoolPop(pool); return self; } @@ -1680,32 +1613,10 @@ - (OFString *)description { return [[self copy] autorelease]; } -- (OFXMLElement *)XMLElementBySerializing -{ - void *pool = objc_autoreleasePoolPush(); - OFXMLElement *element; - OFString *className; - - if ([self isKindOfClass: [OFMutableString class]]) - className = @"OFMutableString"; - else - className = @"OFString"; - - element = [OFXMLElement elementWithName: className - namespace: OFSerializationNS - stringValue: self]; - - [element retain]; - - objc_autoreleasePoolPop(pool); - - return [element autorelease]; -} - - (OFString *)JSONRepresentation { return [self of_JSONRepresentationWithOptions: 0 depth: 0]; } @@ -2424,11 +2335,11 @@ if ([stripped caseInsensitiveCompare: @"NAN"] == OFOrderedSame) return NAN; if ([stripped caseInsensitiveCompare: @"-NAN"] == OFOrderedSame) return -NAN; -#ifdef HAVE_STRTOF_L +#if defined(HAVE_STRTOF_L) || defined(HAVE_USELOCALE) const char *UTF8String = self.UTF8String; #else /* * If we have no strtof_l, we have no other choice but to replace "." * with the locale's decimal point. @@ -2440,12 +2351,16 @@ #endif char *endPtr = NULL; float value; errno = 0; -#ifdef HAVE_STRTOF_L +#if defined(HAVE_STRTOF_L) value = strtof_l(UTF8String, &endPtr, cLocale); +#elif defined(HAVE_USELOCALE) + locale_t previousLocale = uselocale(cLocale); + value = strtof(UTF8String, &endPtr); + uselocale(previousLocale); #else value = strtof(UTF8String, &endPtr); #endif if (value == HUGE_VALF && errno == ERANGE) @@ -2477,11 +2392,11 @@ if ([stripped caseInsensitiveCompare: @"NAN"] == OFOrderedSame) return NAN; if ([stripped caseInsensitiveCompare: @"-NAN"] == OFOrderedSame) return -NAN; -#ifdef HAVE_STRTOD_L +#if defined(HAVE_STRTOD_L) || defined(HAVE_USELOCALE) const char *UTF8String = self.UTF8String; #else /* * If we have no strtod_l, we have no other choice but to replace "." * with the locale's decimal point. @@ -2493,12 +2408,16 @@ #endif char *endPtr = NULL; double value; errno = 0; -#ifdef HAVE_STRTOD_L +#if defined(HAVE_STRTOD_L) value = strtod_l(UTF8String, &endPtr, cLocale); +#elif defined(HAVE_USELOCALE) + locale_t previousLocale = uselocale(cLocale); + value = strtod(UTF8String, &endPtr); + uselocale(previousLocale); #else value = strtod(UTF8String, &endPtr); #endif if (value == HUGE_VAL && errno == ERANGE) @@ -2663,24 +2582,10 @@ objc_autoreleasePoolPop(pool); return [data autorelease]; } -#ifdef OF_HAVE_UNICODE_TABLES -- (OFString *)decomposedStringWithCanonicalMapping -{ - return decomposedString(self, OFUnicodeDecompositionTable, - OFUnicodeDecompositionTableSize); -} - -- (OFString *)decomposedStringWithCompatibilityMapping -{ - return decomposedString(self, OFUnicodeDecompositionCompatTable, - OFUnicodeDecompositionCompatTableSize); -} -#endif - #ifdef OF_WINDOWS - (OFString *)stringByExpandingWindowsEnvironmentStrings { if ([OFSystemInfo isWindowsNT]) { wchar_t buffer[512]; @@ -2722,21 +2627,21 @@ [file writeString: self encoding: encoding]; objc_autoreleasePoolPop(pool); } #endif -- (void)writeToURI: (OFURI *)URI +- (void)writeToIRI: (OFIRI *)IRI { - [self writeToURI: URI encoding: OFStringEncodingUTF8]; + [self writeToIRI: IRI encoding: OFStringEncodingUTF8]; } -- (void)writeToURI: (OFURI *)URI encoding: (OFStringEncoding)encoding +- (void)writeToIRI: (OFIRI *)IRI encoding: (OFStringEncoding)encoding { void *pool = objc_autoreleasePoolPush(); OFStream *stream; - stream = [OFURIHandler openItemAtURI: URI mode: @"w"]; + stream = [OFIRIHandler openItemAtIRI: IRI mode: @"w"]; [stream writeString: self encoding: encoding]; objc_autoreleasePoolPop(pool); } Index: src/OFSubarray.h ================================================================== --- src/OFSubarray.h +++ src/OFSubarray.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,10 +21,9 @@ { OFArray *_array; OFRange _range; } -+ (instancetype)arrayWithArray: (OFArray *)array range: (OFRange)range; - (instancetype)initWithArray: (OFArray *)array range: (OFRange)range; @end OF_ASSUME_NONNULL_END Index: src/OFSubarray.m ================================================================== --- src/OFSubarray.m +++ src/OFSubarray.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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/OFSubdata.h Index: src/OFSubdata.h ================================================================== --- /dev/null +++ src/OFSubdata.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2008-2024 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#import "OFData.h" + +OF_ASSUME_NONNULL_BEGIN + +@interface OFSubdata: OFData +{ + OFData *_data; + OFRange _range; +} + +- (instancetype)initWithData: (OFData *)data range: (OFRange)range; +@end + +OF_ASSUME_NONNULL_END ADDED src/OFSubdata.m Index: src/OFSubdata.m ================================================================== --- /dev/null +++ src/OFSubdata.m @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2008-2024 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#include "config.h" + +#import "OFSubdata.h" + +@implementation OFSubdata +- (instancetype)initWithData: (OFData *)data range: (OFRange)range +{ + self = [super init]; + + @try { + /* Should usually be retain, as it's useless with a copy */ + _data = [data copy]; + _range = range; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (void)dealloc +{ + [_data release]; + + [super dealloc]; +} + +- (size_t)count +{ + return _range.length; +} + +- (size_t)itemSize +{ + return _data.itemSize; +} + +- (const void *)items +{ + return (const unsigned char *)_data.items + + (_range.location * _data.itemSize); +} +@end Index: src/OFSubprocess.h ================================================================== --- src/OFSubprocess.h +++ src/OFSubprocess.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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.m ================================================================== --- src/OFSubprocess.m +++ src/OFSubprocess.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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/OFSystemInfo+NetworkInterfaces.h Index: src/OFSystemInfo+NetworkInterfaces.h ================================================================== --- /dev/null +++ src/OFSystemInfo+NetworkInterfaces.h @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2008-2024 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#import "OFSystemInfo.h" + +OF_ASSUME_NONNULL_BEGIN + +/** + * @brief A dictionary describing a network interface, as returned by + * @ref networkInterfaces. + * + * Keys are of type @ref OFNetworkInterfaceKey. + */ +typedef OFDictionary OF_GENERIC(OFString *, id) *OFNetworkInterface; + +/** + * @brief A key of an @ref OFNetworkInterface. + * + * Possible values are: + * + * * @ref OFNetworkInterfaceIndex + */ +typedef OFConstantString *OFNetworkInterfaceKey; + +/** + * @brief The index of a network interface. + * + * This maps to an @ref OFNumber. + */ +extern OFNetworkInterfaceKey OFNetworkInterfaceIndex; + +/** + * @brief The hardware address of a network interface. + * + * This maps to an @ref OFData. + */ +extern OFNetworkInterfaceKey OFNetworkInterfaceHardwareAddress; + +/** + * @brief The IPv4 addresses of a network interface. + * + * This maps to an @ref OFData of @ref OFSocketAddress. + */ +extern OFNetworkInterfaceKey OFNetworkInterfaceIPv4Addresses; + +#ifdef OF_HAVE_IPV6 +/** + * @brief The IPv6 addresses of a network interface. + * + * This maps to an @ref OFData of @ref OFSocketAddress. + */ +extern OFNetworkInterfaceKey OFNetworkInterfaceIPv6Addresses; +#endif + +#ifdef OF_HAVE_IPX +/** + * @brief The IPX addresses of a network interface. + * + * This maps to an @ref OFData of @ref OFSocketAddress. + */ +extern OFNetworkInterfaceKey OFNetworkInterfaceIPXAddresses; +#endif + +#ifdef OF_HAVE_APPLETALK +/** + * @brief The AppleTalk addresses of a network interface. + * + * This maps to an @ref OFData of @ref OFSocketAddress. + */ +extern OFNetworkInterfaceKey OFNetworkInterfaceAppleTalkAddresses; +#endif + +@interface OFSystemInfo (NetworkInterfaces) + +#ifdef OF_HAVE_CLASS_PROPERTIES +@property (class, readonly, nullable, nonatomic) + OFDictionary OF_GENERIC(OFString *, OFNetworkInterface) *networkInterfaces; +#endif + +/** + * @brief Returns the available (though not necessarily configured) network + * interfaces. + * + * @return The available network interfaces + */ ++ (nullable OFDictionary OF_GENERIC(OFString *, OFNetworkInterface) *) + networkInterfaces; +@end + +OF_ASSUME_NONNULL_END ADDED src/OFSystemInfo+NetworkInterfaces.m Index: src/OFSystemInfo+NetworkInterfaces.m ================================================================== --- /dev/null +++ src/OFSystemInfo+NetworkInterfaces.m @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2008-2024 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#include "config.h" + +#import "OFSystemInfo.h" + +OFNetworkInterfaceKey OFNetworkInterfaceIndex = @"OFNetworkInterfaceIndex"; +OFNetworkInterfaceKey OFNetworkInterfaceHardwareAddress = + @"OFNetworkInterfaceHardwareAddress"; +OFNetworkInterfaceKey OFNetworkInterfaceIPv4Addresses = + @"OFNetworkInterfaceIPv4Addresses"; +#ifdef OF_HAVE_IPV6 +OFNetworkInterfaceKey OFNetworkInterfaceIPv6Addresses = + @"OFNetworkInterfaceIPv6Addresses"; +#endif +#ifdef OF_HAVE_IPX +OFNetworkInterfaceKey OFNetworkInterfaceIPXAddresses = + @"OFNetworkInterfaceIPXAddresses"; +#endif +#ifdef OF_HAVE_APPLETALK +OFNetworkInterfaceKey OFNetworkInterfaceAppleTalkAddresses = + @"OFNetworkInterfaceAppleTalkAddresses"; +#endif + +#ifdef OF_WINDOWS +# include "platform/Windows/OFSystemInfo+NetworkInterfaces.m" +#else +# include "platform/POSIX/OFSystemInfo+NetworkInterfaces.m" +#endif Index: src/OFSystemInfo.h ================================================================== --- src/OFSystemInfo.h +++ src/OFSystemInfo.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,11 +16,12 @@ #import "OFObject.h" #import "OFString.h" OF_ASSUME_NONNULL_BEGIN -@class OFURI; +@class OFDictionary OF_GENERIC(KeyType, ObjectType); +@class OFIRI; /** * @class OFSystemInfo OFSystemInfo.h ObjFW/OFSystemInfo.h * * @brief A class for querying information about the system. @@ -34,17 +35,19 @@ @property (class, readonly, nonatomic) unsigned short ObjFWVersionMajor; @property (class, readonly, nonatomic) unsigned short ObjFWVersionMinor; @property (class, readonly, nullable, nonatomic) OFString *operatingSystemName; @property (class, readonly, nullable, nonatomic) OFString *operatingSystemVersion; -@property (class, readonly, nullable, nonatomic) OFURI *userDataURI; -@property (class, readonly, nullable, nonatomic) OFURI *userConfigURI; -@property (class, readonly, nullable, nonatomic) OFURI *temporaryDirectoryURI; +@property (class, readonly, nullable, nonatomic) OFIRI *userDataIRI; +@property (class, readonly, nullable, nonatomic) OFIRI *userConfigIRI; +@property (class, readonly, nullable, nonatomic) OFIRI *temporaryDirectoryIRI; @property (class, readonly, nullable, nonatomic) OFString *CPUVendor; @property (class, readonly, nullable, nonatomic) OFString *CPUModel; -# if defined(OF_X86_64) || defined(OF_X86) || defined(DOXYGEN) +# if defined(OF_AMD64) || defined(OF_X86) || defined(DOXYGEN) @property (class, readonly, nonatomic) bool supportsMMX; +@property (class, readonly, nonatomic) bool supports3DNow; +@property (class, readonly, nonatomic) bool supportsEnhanced3DNow; @property (class, readonly, nonatomic) bool supportsSSE; @property (class, readonly, nonatomic) bool supportsSSE2; @property (class, readonly, nonatomic) bool supportsSSE3; @property (class, readonly, nonatomic) bool supportsSSSE3; @property (class, readonly, nonatomic) bool supportsSSE41; @@ -51,15 +54,42 @@ @property (class, readonly, nonatomic) bool supportsSSE42; @property (class, readonly, nonatomic) bool supportsAVX; @property (class, readonly, nonatomic) bool supportsAVX2; @property (class, readonly, nonatomic) bool supportsAESNI; @property (class, readonly, nonatomic) bool supportsSHAExtensions; +@property (class, readonly, nonatomic) bool supportsFusedMultiplyAdd; +@property (class, readonly, nonatomic) bool supportsF16C; +@property (class, readonly, nonatomic) bool supportsAVX512Foundation; +@property (class, readonly, nonatomic) + bool supportsAVX512ConflictDetectionInstructions; +@property (class, readonly, nonatomic) + bool supportsAVX512ExponentialAndReciprocalInstructions; +@property (class, readonly, nonatomic) bool supportsAVX512PrefetchInstructions; +@property (class, readonly, nonatomic) + bool supportsAVX512VectorLengthExtensions; +@property (class, readonly, nonatomic) + bool supportsAVX512DoublewordAndQuadwordInstructions; +@property (class, readonly, nonatomic) + bool supportsAVX512ByteAndWordInstructions; +@property (class, readonly, nonatomic) + bool supportsAVX512IntegerFusedMultiplyAdd; +@property (class, readonly, nonatomic) + bool supportsAVX512VectorByteManipulationInstructions; +@property (class, readonly, nonatomic) + bool supportsAVX512VectorPopulationCountInstruction; +@property (class, readonly, nonatomic) + bool supportsAVX512VectorNeuralNetworkInstructions; +@property (class, readonly, nonatomic) + bool supportsAVX512VectorByteManipulationInstructions2; +@property (class, readonly, nonatomic) bool supportsAVX512BitAlgorithms; +@property (class, readonly, nonatomic) bool supportsAVX512Float16Instructions; +@property (class, readonly, nonatomic) bool supportsAVX512BFloat16Instructions; # endif # if defined(OF_POWERPC) || defined(OF_POWERPC64) || defined(DOXYGEN) @property (class, readonly, nonatomic) bool supportsAltiVec; # endif -# ifdef OF_WINDOWS +# if defined(OF_WINDOWS) || defined(DOXYGEN) @property (class, readonly, nonatomic, getter=isWindowsNT) bool windowsNT; # endif #endif /** @@ -124,11 +154,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 OFURI *)userDataURI; ++ (nullable OFIRI *)userDataIRI; /** * @brief Returns the path where user configuration for the application can be * stored. * @@ -139,11 +169,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 OFURI *)userConfigURI; ++ (nullable OFIRI *)userConfigIRI; /** * @brief Returns a path where temporary files for can be stored. * * If possible, returns a temporary directory for the user, otherwise returns a @@ -157,11 +187,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 OFURI *)temporaryDirectoryURI; ++ (nullable OFIRI *)temporaryDirectoryIRI; /** * @brief Returns the vendor of the CPU. * * If the vendor could not be determined, `nil` is returned instead. @@ -177,128 +207,300 @@ * * @return The model of the CPU */ + (nullable OFString *)CPUModel; -#if defined(OF_X86_64) || defined(OF_X86) || defined(DOXYGEN) +#if defined(OF_AMD64) || defined(OF_X86) || defined(DOXYGEN) /** * @brief Returns whether the CPU supports MMX. * - * @note This method is only available on x86 and x86_64. + * @note This method is only available on AMD64 and x86. * * @return Whether the CPU supports MMX */ + (bool)supportsMMX; +/** + * @brief Returns whether the CPU supports 3DNow!. + * + * @note This method is only available on AMD64 and x86. + * + * @return Whether the CPU supports 3DNow! + */ ++ (bool)supports3DNow; + +/** + * @brief Returns whether the CPU supports enhanced 3DNow!. + * + * @note This method is only available on AMD64 and x86. + * + * @return Whether the CPU supports enhanced 3DNow! + */ ++ (bool)supportsEnhanced3DNow; + /** * @brief Returns whether the CPU supports SSE. * - * @warning This method only checks CPU support and assumes OS support! - * - * @note This method is only available on x86 and x86_64. + * @note This method is only available on AMD64 and x86. * * @return Whether the CPU supports SSE */ + (bool)supportsSSE; /** * @brief Returns whether the CPU supports SSE2. * - * @warning This method only checks CPU support and assumes OS support! - * - * @note This method is only available on x86 and x86_64. + * @note This method is only available on AMD64 and x86. * * @return Whether the CPU supports SSE2 */ + (bool)supportsSSE2; /** * @brief Returns whether the CPU supports SSE3. * - * @warning This method only checks CPU support and assumes OS support! - * - * @note This method is only available on x86 and x86_64. + * @note This method is only available on AMD64 and x86. * * @return Whether the CPU supports SSE3 */ + (bool)supportsSSE3; /** * @brief Returns whether the CPU supports SSSE3. * - * @warning This method only checks CPU support and assumes OS support! - * - * @note This method is only available on x86 and x86_64. + * @note This method is only available on AMD64 and x86. * * @return Whether the CPU supports SSSE3 */ + (bool)supportsSSSE3; /** * @brief Returns whether the CPU supports SSE4.1. * - * @warning This method only checks CPU support and assumes OS support! - * - * @note This method is only available on x86 and x86_64. + * @note This method is only available on AMD64 and x86. * * @return Whether the CPU supports SSE4.1 */ + (bool)supportsSSE41; /** * @brief Returns whether the CPU supports SSE4.2. * - * @warning This method only checks CPU support and assumes OS support! - * - * @note This method is only available on x86 and x86_64. + * @note This method is only available on AMD64 and x86. * * @return Whether the CPU supports SSE4.2 */ + (bool)supportsSSE42; /** - * @brief Returns whether the CPU supports AVX. + * @brief Returns whether the CPU and OS support AVX. * - * @warning This method only checks CPU support and assumes OS support! + * @note This method is only available on AMD64 and x86. * - * @note This method is only available on x86 and x86_64. - * - * @return Whether the CPU supports AVX + * @return Whether the CPU and OS support AVX */ + (bool)supportsAVX; /** - * @brief Returns whether the CPU supports AVX2. + * @brief Returns whether the CPU and OS support AVX2. * - * @warning This method only checks CPU support and assumes OS support! + * @note This method is only available on AMD64 and x86. * - * @note This method is only available on x86 and x86_64. - * - * @return Whether the CPU supports AVX2 + * @return Whether the CPU and OS support AVX2 */ + (bool)supportsAVX2; /** * @brief Returns whether the CPU supports AES-NI. * - * @note This method is only available on x86 and x86_64. + * @note This method is only available on AMD64 and x86. * * @return Whether the CPU supports AES-NI */ + (bool)supportsAESNI; /** * @brief Returns whether the CPU supports Intel SHA Extensions. * - * @note This method is only available on x86 and x86_64. + * @note This method is only available on AMD64 and x86. * * @return Whether the CPU supports Intel SHA Extensions */ + (bool)supportsSHAExtensions; + +/** + * @brief Returns whether the CPU supports fused multiply-add. + * + * @note This method is only available on AMD64 and x86. + * + * @return Whether the CPU supports fused multiply-add + */ ++ (bool)supportsFusedMultiplyAdd; + +/** + * @brief Returns whether the CPU supports F16C. + * + * @note This method is only available on AMD64 and x86. + * + * @return Whether the CPU supports F16C + */ ++ (bool)supportsF16C; + +/** + * @brief Returns whether the CPU and OS support AVX-512 Foundation. + * + * @note This method is only available on AMD64 and x86. + * + * @return Whether the CPU and OS support AVX-512 Foundation + */ ++ (bool)supportsAVX512Foundation; + +/** + * @brief Returns whether the CPU and OS support AVX-512 Conflict Detection + * Instructions. + * + * @note This method is only available on AMD64 and x86. + * + * @return Whether the CPU and OS support AVX-512 Conflict Detection + * Instructions + */ ++ (bool)supportsAVX512ConflictDetectionInstructions; + +/** + * @brief Returns whether the CPU and OS support AVX-512 Exponential and + * Reciprocal Instructions. + * + * @note This method is only available on AMD64 and x86. + * + * @return Whether the CPU and OS support AVX-512 Exponential and Reciprocal + * Instructions + */ ++ (bool)supportsAVX512ExponentialAndReciprocalInstructions; + +/** + * @brief Returns whether the CPU and OS support AVX-512 Prefetch Instructions. + * + * @note This method is only available on AMD64 and x86. + * + * @return Whether the CPU and OS support AVX-512 Prefetch Instructions + */ ++ (bool)supportsAVX512PrefetchInstructions; + +/** + * @brief Returns whether the CPU and OS support AVX-512 Vector Length + * Extensions. + * + * @note This method is only available on AMD64 and x86. + * + * @return Whether the CPU and OS support AVX-512 Vector Length Extensions + */ ++ (bool)supportsAVX512VectorLengthExtensions; + +/** + * @brief Returns whether the CPU and OS support AVX-512 Doubleword and Quadword + * Instructions. + * + * @note This method is only available on AMD64 and x86. + * + * @return Whether the CPU and OS support AVX-512 Doubleword and Quadword + * Instructions + */ ++ (bool)supportsAVX512DoublewordAndQuadwordInstructions; + +/** + * @brief Returns whether the CPU and OS support AVX-512 Byte and Word + * Instructions. + * + * @note This method is only available on AMD64 and x86. + * + * @return Whether the CPU and OS support AVX-512 Byte and Word Instructions + */ ++ (bool)supportsAVX512ByteAndWordInstructions; + +/** + * @brief Returns whether the CPU and OS support AVX-512 Integer Fused + * Multiply-Add. + * + * @note This method is only available on AMD64 and x86. + * + * @return Whether the CPU and OS support AVX-512 Integer Fused Multiply-Add + */ ++ (bool)supportsAVX512IntegerFusedMultiplyAdd; + +/** + * @brief Returns whether the CPU and OS support AVX-512 Vector Byte + * Manipulation Instructions. + * + * @note This method is only available on AMD64 and x86. + * + * @return Whether the CPU and OS support AVX-512 Vector Byte Manipulation + * Instructions + */ ++ (bool)supportsAVX512VectorByteManipulationInstructions; + +/** + * @brief Returns whether the CPU and OS support the AVX-512 Vector Population + * Count Instruction. + * + * @note This method is only available on AMD64 and x86. + * + * @return Whether the CPU and OS support AVX-512 the Vector Population Count + * Instruction + */ ++ (bool)supportsAVX512VectorPopulationCountInstruction; + +/** + * @brief Returns whether the CPU and OS support AVX-512 Vector Neural Network + * Instructions. + * + * @note This method is only available on AMD64 and x86. + * + * @return Whether the CPU and OS support AVX-512 Vector Neural Network + * Instructions + */ ++ (bool)supportsAVX512VectorNeuralNetworkInstructions; + +/** + * @brief Returns whether the CPU and OS support AVX-512 Vector Byte + * Manipulation Instructions 2. + * + * @note This method is only available on AMD64 and x86. + * + * @return Whether the CPU and OS support AVX-512 Vector Byte Manipulation + * Instructions 2 + */ ++ (bool)supportsAVX512VectorByteManipulationInstructions2; + +/** + * @brief Returns whether the CPU and OS support AVX-512 Bit Algorithms. + * + * @note This method is only available on AMD64 and x86. + * + * @return Whether the CPU and OS support AVX-512 Bit Algorithms + */ ++ (bool)supportsAVX512BitAlgorithms; + +/** + * @brief Returns whether the CPU and OS support AVX-512 Float16 Instructions. + * + * @note This method is only available on AMD64 and x86. + * + * @return Whether the CPU and OS support AVX-512 Float16 Instructions + */ ++ (bool)supportsAVX512Float16Instructions; + +/** + * @brief Returns whether the CPU and OS support AVX-512 BFloat16 Instructions. + * + * @note This method is only available on AMD64 and x86. + * + * @return Whether the CPU and OS support AVX-512 BFloat16 Instructions + */ ++ (bool)supportsAVX512BFloat16Instructions; #endif -#if defined(OF_POWERPC) || defined(OF_POWERPC64) +#if defined(OF_POWERPC) || defined(OF_POWERPC64) || defined(DOXYGEN) /** * @brief Returns whether the CPU and OS support AltiVec. * * @note This method is only available on PowerPC and PowerPC 64. * @@ -305,11 +507,11 @@ * @return Whether the CPU and OS support AltiVec */ + (bool)supportsAltiVec; #endif -#ifdef OF_WINDOWS +#if defined(OF_WINDOWS) || defined(DOXYGEN) /** * @brief Returns whether the application is running on Windows NT. * * @note This method is only available on Windows. * @@ -321,5 +523,9 @@ + (instancetype)alloc OF_UNAVAILABLE; - (instancetype)init OF_UNAVAILABLE; @end OF_ASSUME_NONNULL_END + +#ifdef OF_HAVE_SOCKETS +# import "OFSystemInfo+NetworkInterfaces.h" +#endif Index: src/OFSystemInfo.m ================================================================== --- src/OFSystemInfo.m +++ src/OFSystemInfo.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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 @@ #define __NO_EXT_QNX #include "config.h" #include /* include any libc header to get the libc defines */ +#include +#include #include "unistd_wrapper.h" #include "platform.h" @@ -29,12 +31,14 @@ #if defined(OF_MACOS) || defined(OF_IOS) || defined(OF_NETBSD) # include #endif #ifdef OF_AMIGAOS +# define Class IntuitionClass # include # include +# undef Class #endif #if defined(OF_AMIGAOS4) # include #elif defined(OF_MORPHOS) @@ -44,28 +48,38 @@ #ifdef OF_NINTENDO_SWITCH # define id nx_id # import # undef nx_id #endif + +#ifdef OF_DJGPP +# include +#endif #import "OFSystemInfo.h" #import "OFApplication.h" #import "OFArray.h" +#import "OFData.h" #import "OFDictionary.h" +#ifdef OF_HAVE_FILES +# import "OFFile.h" +# import "OFFileManager.h" +#endif +#import "OFIRI.h" #import "OFLocale.h" +#import "OFNumber.h" #import "OFOnce.h" #import "OFString.h" -#import "OFURI.h" + +#import "OFInvalidFormatException.h" +#import "OFOpenItemFailedException.h" #if defined(OF_MACOS) || defined(OF_IOS) # ifdef HAVE_SYSDIR_H # include # endif #endif -#ifdef OF_WINDOWS -# include -#endif #ifdef OF_HAIKU # include #endif #ifdef OF_QNX # include @@ -99,14 +113,47 @@ NSSearchPathDirectory, NSSearchPathDomainMask); extern NSSearchPathEnumerationState NSGetNextSearchPathEnumeration( NSSearchPathEnumerationState, char *); #endif -#if defined(OF_X86_64) || defined(OF_X86) +#if defined(OF_AMD64) || defined(OF_X86) struct X86Regs { uint32_t eax, ebx, ecx, edx; }; + +static bool SSESupport; +static jmp_buf SSETestEnv; + +static void +SSETestSIGILLHandler(int signum) +{ + longjmp(SSETestEnv, 1); +} + +# ifndef __clang__ +# pragma GCC push_options +# pragma GCC target("sse") +# endif +static void +SSETest(void) +{ + void (*oldHandler)(int) = signal(SIGILL, SSETestSIGILLHandler); + + if (setjmp(SSETestEnv) == 0) { + __asm__ __volatile__ ( + "movaps %%xmm0, %%xmm0" + ::: "xmm0" /* clang is unhappy if we don't clobber it */ + ); + SSESupport = true; + } else + SSESupport = false; + + signal(SIGILL, oldHandler); +} +# ifndef __clang__ +# pragma GCC pop_options +# endif #endif static size_t pageSize = 4096; static size_t numberOfCPUs = 1; static OFString *operatingSystemName = nil; @@ -129,26 +176,32 @@ operatingSystemName = @"MorphOS"; #elif defined(OF_AMIGAOS4) operatingSystemName = @"AmigaOS 4"; #elif defined(OF_WII) operatingSystemName = @"Nintendo Wii"; +#elif defined(OF_WII_U) + operatingSystemName = @"Nintendo Wii U"; #elif defined(NINTENDO_3DS) operatingSystemName = @"Nintendo 3DS"; #elif defined(OF_NINTENDO_DS) operatingSystemName = @"Nintendo DS"; +#elif defined(OF_NINTENDO_SWITCH) + operatingSystemName = @"Nintendo Switch"; #elif defined(OF_PSP) operatingSystemName = @"PlayStation Portable"; -#elif defined(OF_MSDOS) - operatingSystemName = @"MS-DOS"; +#elif defined(OF_DJGPP) + operatingSystemName = [[OFString alloc] + initWithCString: _os_flavor + encoding: OFStringEncodingASCII]; #elif defined(HAVE_SYS_UTSNAME_H) && defined(HAVE_UNAME) - struct utsname utsname; + struct utsname name; - if (uname(&utsname) != 0) + if (uname(&name) == -1) return; operatingSystemName = [[OFString alloc] - initWithCString: utsname.sysname + initWithCString: name.sysname encoding: [OFLocale encoding]]; #endif } static void @@ -228,48 +281,55 @@ /* TODO */ #elif defined(OF_AMIGAOS) operatingSystemVersion = [[OFString alloc] initWithFormat: @"Kickstart %u.%u", SysBase->LibNode.lib_Version, SysBase->SoftVer]; +#elif defined(OF_DJGPP) + operatingSystemVersion = [[OFString alloc] + initWithFormat: @"%u.%u", _osmajor, _osminor]; #elif defined(OF_WII) || defined(NINTENDO_3DS) || defined(OF_NINTENDO_DS) || \ - defined(OF_PSP) || defined(OF_MSDOS) + defined(OF_PSP) /* Intentionally nothing */ #elif defined(HAVE_SYS_UTSNAME_H) && defined(HAVE_UNAME) - struct utsname utsname; + struct utsname name; - if (uname(&utsname) != 0) + if (uname(&name) == -1) return; operatingSystemVersion = [[OFString alloc] - initWithCString: utsname.release + initWithCString: name.release encoding: [OFLocale encoding]]; #endif } #ifdef OF_NINTENDO_SWITCH -static OFURI *tmpFSURI = nil; +static OFIRI *tmpFSIRI = nil; static void mountTmpFS(void) { if (R_SUCCEEDED(fsdevMountTemporaryStorage("tmpfs"))) - tmpFSURI = [[OFURI alloc] initFileURIWithPath: @"tmpfs:/" + tmpFSIRI = [[OFIRI alloc] initFileIRIWithPath: @"tmpfs:/" isDirectory: true]; } #endif -#if defined(OF_X86_64) || defined(OF_X86) +#if defined(OF_AMD64) || defined(OF_X86) static OF_INLINE struct X86Regs OF_CONST_FUNC x86CPUID(uint32_t eax, uint32_t ecx) { struct X86Regs regs; -# if defined(OF_X86_64) && defined(__GNUC__) +# if defined(OF_AMD64) && defined(__GNUC__) __asm__ ( "cpuid" - : "=a"(regs.eax), "=b"(regs.ebx), "=c"(regs.ecx), "=d"(regs.edx) - : "a"(eax), "c"(ecx) + : "=a" (regs.eax), + "=b" (regs.ebx), + "=c" (regs.ecx), + "=d" (regs.edx) + : "a" (eax), + "c" (ecx) ); # elif defined(OF_X86) && defined(__GNUC__) /* * This workaround is required by older GCC versions when using -fPIC, * as ebx is a special register in PIC code. Yes, GCC is indeed not @@ -278,16 +338,38 @@ */ __asm__ ( "xchgl %%ebx, %%edi\n\t" "cpuid\n\t" "xchgl %%edi, %%ebx" - : "=a"(regs.eax), "=D"(regs.ebx), "=c"(regs.ecx), "=d"(regs.edx) - : "a"(eax), "c"(ecx) + : "=a" (regs.eax), + "=D" (regs.ebx), + "=c" (regs.ecx), + "=d" (regs.edx) + : "a" (eax), + "c" (ecx) ); # else memset(®s, 0, sizeof(regs)); # endif + + return regs; +} + +static OF_INLINE struct X86Regs +x86XCR(uint32_t ecx) +{ + struct X86Regs regs = { 0 }; + + if (!(x86CPUID(1, 0).ecx & (1u << 27))) + return regs; + + __asm__ ( + "xgetbv" + : "=a" (regs.eax), + "=d" (regs.edx) + : "c" (ecx) + ); return regs; } #endif @@ -296,10 +378,19 @@ { long tmp; if (self != [OFSystemInfo class]) return; + +#if defined(OF_AMD64) || defined(OF_X86) + /* + * Do this as early as possible, as it involves signals. + * Required as cpuid can return SSE support while the OS has not + * enabled it. + */ + SSETest(); +#endif #if defined(OF_WINDOWS) SYSTEM_INFO si; GetSystemInfo(&si); pageSize = si.dwPageSize; @@ -366,11 +457,11 @@ OFOnce(&onceControl, initOperatingSystemVersion); return operatingSystemVersion; } -+ (OFURI *)userDataURI ++ (OFIRI *)userDataIRI { #ifdef OF_HAVE_FILES # if defined(OF_MACOS) || defined(OF_IOS) char pathC[PATH_MAX]; OFMutableString *path; @@ -408,59 +499,61 @@ [path insertString: home atIndex: 0]; } [path makeImmutable]; - return [OFURI fileURIWithPath: path isDirectory: true]; + return [OFIRI fileIRIWithPath: path isDirectory: true]; # elif defined(OF_WINDOWS) OFDictionary *env = [OFApplication environment]; OFString *appData; if ((appData = [env objectForKey: @"APPDATA"]) == nil) return nil; - return [OFURI fileURIWithPath: appData isDirectory: true]; + return [OFIRI fileIRIWithPath: appData isDirectory: true]; # elif defined(OF_HAIKU) char pathC[PATH_MAX]; if (find_directory(B_USER_SETTINGS_DIRECTORY, 0, false, pathC, PATH_MAX) != B_OK) return nil; - return [OFURI fileURIWithPath: [OFString stringWithUTF8String: pathC] + return [OFIRI fileIRIWithPath: [OFString stringWithUTF8String: pathC] isDirectory: true]; # elif defined(OF_AMIGAOS) - return [OFURI fileURIWithPath: @"PROGDIR:" isDirectory: true]; + return [OFIRI fileIRIWithPath: @"PROGDIR:" isDirectory: true]; +# elif defined(OF_WII) || defined(OF_NINTENDO_3DS) + return [[OFFileManager defaultManager] currentDirectoryIRI]; # else OFDictionary *env = [OFApplication environment]; OFString *var; - OFURI *URI; + OFIRI *IRI; void *pool; if ((var = [env objectForKey: @"XDG_DATA_HOME"]) != nil && var.length > 0) - return [OFURI fileURIWithPath: var isDirectory: true]; + return [OFIRI fileIRIWithPath: var isDirectory: true]; if ((var = [env objectForKey: @"HOME"]) == nil) return nil; pool = objc_autoreleasePoolPush(); var = [OFString pathWithComponents: [OFArray arrayWithObjects: var, @".local", @"share", nil]]; - URI = [[OFURI alloc] initFileURIWithPath: var isDirectory: true]; + IRI = [[OFIRI alloc] initFileIRIWithPath: var isDirectory: true]; objc_autoreleasePoolPop(pool); - return [URI autorelease]; + return [IRI autorelease]; # endif #else return nil; #endif } -+ (OFURI *)userConfigURI ++ (OFIRI *)userConfigIRI { #ifdef OF_HAVE_FILES # if defined(OF_MACOS) || defined(OF_IOS) char pathC[PATH_MAX]; OFMutableString *path; @@ -498,66 +591,68 @@ } [path appendString: @"/Preferences"]; [path makeImmutable]; - return [OFURI fileURIWithPath: path isDirectory: true]; + return [OFIRI fileIRIWithPath: path isDirectory: true]; # elif defined(OF_WINDOWS) OFDictionary *env = [OFApplication environment]; OFString *appData; if ((appData = [env objectForKey: @"APPDATA"]) == nil) return nil; - return [OFURI fileURIWithPath: appData isDirectory: true]; + return [OFIRI fileIRIWithPath: appData isDirectory: true]; # elif defined(OF_HAIKU) char pathC[PATH_MAX]; if (find_directory(B_USER_SETTINGS_DIRECTORY, 0, false, pathC, PATH_MAX) != B_OK) return nil; - return [OFURI fileURIWithPath: [OFString stringWithUTF8String: pathC] + return [OFIRI fileIRIWithPath: [OFString stringWithUTF8String: pathC] isDirectory: true]; # elif defined(OF_AMIGAOS) - return [OFURI fileURIWithPath: @"PROGDIR:" isDirectory: true]; + return [OFIRI fileIRIWithPath: @"PROGDIR:" isDirectory: true]; +# elif defined(OF_WII) || defined(OF_NINTENDO_3DS) + return [[OFFileManager defaultManager] currentDirectoryIRI]; # else OFDictionary *env = [OFApplication environment]; OFString *var; if ((var = [env objectForKey: @"XDG_CONFIG_HOME"]) != nil && var.length > 0) - return [OFURI fileURIWithPath: var isDirectory: true]; + return [OFIRI fileIRIWithPath: var isDirectory: true]; if ((var = [env objectForKey: @"HOME"]) == nil) return nil; var = [var stringByAppendingPathComponent: @".config"]; - return [OFURI fileURIWithPath: var isDirectory: true]; + return [OFIRI fileIRIWithPath: var isDirectory: true]; # endif #else return nil; #endif } -+ (OFURI *)temporaryDirectoryURI ++ (OFIRI *)temporaryDirectoryIRI { #ifdef OF_HAVE_FILES # if defined(OF_MACOS) || defined(OF_IOS) char buffer[PATH_MAX]; size_t length; OFString *path; if ((length = confstr(_CS_DARWIN_USER_TEMP_DIR, buffer, PATH_MAX)) == 0) - return [OFURI fileURIWithPath: @"/tmp" isDirectory: true]; + return [OFIRI fileIRIWithPath: @"/tmp" isDirectory: true]; path = [OFString stringWithCString: buffer encoding: [OFLocale encoding] length: length - 1]; - return [OFURI fileURIWithPath: path isDirectory: true]; + return [OFIRI fileIRIWithPath: path isDirectory: true]; # elif defined(OF_WINDOWS) OFString *path; if ([self isWindowsNT]) { wchar_t buffer[PATH_MAX]; @@ -574,53 +669,59 @@ path = [OFString stringWithCString: buffer encoding: [OFLocale encoding]]; } - return [OFURI fileURIWithPath: path isDirectory: true]; + return [OFIRI fileIRIWithPath: path isDirectory: true]; # elif defined(OF_HAIKU) char pathC[PATH_MAX]; if (find_directory(B_SYSTEM_TEMP_DIRECTORY, 0, false, pathC, PATH_MAX) != B_OK) return nil; - return [OFURI fileURIWithPath: [OFString stringWithUTF8String: pathC] + return [OFIRI fileIRIWithPath: [OFString stringWithUTF8String: pathC] isDirectory: true]; # elif defined(OF_AMIGAOS) - return [OFURI fileURIWithPath: @"T:" isDirectory: true]; + return [OFIRI fileIRIWithPath: @"T:" isDirectory: true]; # elif defined(OF_MSDOS) OFString *path = [[OFApplication environment] objectForKey: @"TEMP"]; if (path == nil) return nil; - return [OFURI fileURIWithPath: path isDirectory: true]; + return [OFIRI fileIRIWithPath: path isDirectory: true]; # elif defined(OF_MINT) - return [OFURI fileURIWithPath: @"u:\\tmp" isDirectory: true]; + return [OFIRI fileIRIWithPath: @"u:\\tmp" isDirectory: true]; +# elif defined(OF_WII) || defined(OF_NINTENDO_3DS) + return [[OFFileManager defaultManager] currentDirectoryIRI]; # elif defined(OF_NINTENDO_SWITCH) static OFOnceControl onceControl = OFOnceControlInitValue; OFOnce(&onceControl, mountTmpFS); - return tmpFSURI; + return tmpFSIRI; # else - OFString *path = - [[OFApplication environment] objectForKey: @"XDG_RUNTIME_DIR"]; + OFString *path; + + path = [[OFApplication environment] objectForKey: @"XDG_RUNTIME_DIR"]; + if (path != nil) + return [OFIRI fileIRIWithPath: path isDirectory: true]; + path = [[OFApplication environment] objectForKey: @"TMPDIR"]; if (path != nil) - return [OFURI fileURIWithPath: path]; + return [OFIRI fileIRIWithPath: path isDirectory: true]; - return [OFURI fileURIWithPath: @"/tmp"]; + return [OFIRI fileIRIWithPath: @"/tmp" isDirectory: true]; # endif #else return nil; #endif } + (OFString *)CPUVendor { -#if (defined(OF_X86_64) || defined(OF_X86)) && defined(__GNUC__) +#if (defined(OF_AMD64) || defined(OF_X86)) && defined(__GNUC__) struct X86Regs regs = x86CPUID(0, 0); uint32_t buffer[3]; if (regs.eax == 0) return nil; @@ -639,11 +740,11 @@ #endif } + (OFString *)CPUModel { -#if (defined(OF_X86_64) || defined(OF_X86)) && defined(__GNUC__) +#if (defined(OF_AMD64) || defined(OF_X86)) && defined(__GNUC__) struct X86Regs regs = x86CPUID(0x80000000, 0); uint32_t buffer[12]; size_t i; if (regs.eax < 0x80000004) @@ -698,64 +799,184 @@ #else return nil; #endif } -#if defined(OF_X86_64) || defined(OF_X86) +#if defined(OF_AMD64) || defined(OF_X86) + (bool)supportsMMX { - return (x86CPUID(1, 0).edx & (1u << 23)); + return (x86CPUID(0, 0).eax >= 1 && x86CPUID(1, 0).edx & (1u << 23)); +} + ++ (bool)supports3DNow +{ + return (x86CPUID(0x80000000, 0).eax >= 0x80000001 && + x86CPUID(0x80000001, 0).edx & (1u << 31)); +} + ++ (bool)supportsEnhanced3DNow +{ + return (x86CPUID(0x80000000, 0).eax >= 0x80000001 && + x86CPUID(0x80000001, 0).edx & (1u << 30)); } + (bool)supportsSSE { - return (x86CPUID(1, 0).edx & (1u << 25)); + return SSESupport && + (x86CPUID(0, 0).eax >= 1 && x86CPUID(1, 0).edx & (1u << 25)); } + (bool)supportsSSE2 { - return (x86CPUID(1, 0).edx & (1u << 26)); + return SSESupport && + (x86CPUID(0, 0).eax >= 1 && x86CPUID(1, 0).edx & (1u << 26)); } + (bool)supportsSSE3 { - return (x86CPUID(1, 0).ecx & (1u << 0)); + return SSESupport && + (x86CPUID(0, 0).eax >= 1 && x86CPUID(1, 0).ecx & (1u << 0)); } + (bool)supportsSSSE3 { - return (x86CPUID(1, 0).ecx & (1u << 9)); + return SSESupport && + (x86CPUID(0, 0).eax >= 1 && x86CPUID(1, 0).ecx & (1u << 9)); } + (bool)supportsSSE41 { - return (x86CPUID(1, 0).ecx & (1u << 19)); + return SSESupport && + (x86CPUID(0, 0).eax >= 1 && x86CPUID(1, 0).ecx & (1u << 19)); } + (bool)supportsSSE42 { - return (x86CPUID(1, 0).ecx & (1u << 20)); + return SSESupport && + (x86CPUID(0, 0).eax >= 1 && x86CPUID(1, 0).ecx & (1u << 20)); } + (bool)supportsAVX { - return (x86CPUID(1, 0).ecx & (1u << 28)); + return ((x86CPUID(0, 0).eax >= 1 && x86CPUID(1, 0).ecx & (1u << 28)) && + (x86XCR(0).eax & 0x6) == 0x6); } + (bool)supportsAVX2 { - return x86CPUID(0, 0).eax >= 7 && (x86CPUID(7, 0).ebx & (1u << 5)); + return ((x86CPUID(0, 0).eax >= 7 && (x86CPUID(7, 0).ebx & (1u << 5))) && + (x86XCR(0).eax & 0x6) == 0x6); } + (bool)supportsAESNI { - return (x86CPUID(1, 0).ecx & (1u << 25)); + return (x86CPUID(0, 0).eax >= 1 && x86CPUID(1, 0).ecx & (1u << 25)); } + (bool)supportsSHAExtensions { - return (x86CPUID(7, 0).ebx & (1u << 29)); + return (x86CPUID(0, 0).eax >= 7 && x86CPUID(7, 0).ebx & (1u << 29)); +} + ++ (bool)supportsFusedMultiplyAdd +{ + return (x86CPUID(0, 0).eax >= 1 && x86CPUID(1, 0).ecx & (1u << 12)); +} + ++ (bool)supportsF16C +{ + return (x86CPUID(0, 0).eax >= 1 && x86CPUID(1, 0).ecx & (1u << 29)); +} + ++ (bool)supportsAVX512Foundation +{ + return ((x86CPUID(0, 0).eax >= 7 && x86CPUID(7, 0).ebx & (1u << 16)) && + (x86XCR(0).eax & 0xE6) == 0xE6); +} + ++ (bool)supportsAVX512ConflictDetectionInstructions +{ + return ((x86CPUID(0, 0).eax >= 7 && x86CPUID(7, 0).ebx & (1u << 28)) && + (x86XCR(0).eax & 0xE6) == 0xE6); +} + ++ (bool)supportsAVX512ExponentialAndReciprocalInstructions +{ + return ((x86CPUID(0, 0).eax >= 7 && x86CPUID(7, 0).ebx & (1u << 27)) && + (x86XCR(0).eax & 0xE6) == 0xE6); +} + ++ (bool)supportsAVX512PrefetchInstructions +{ + return ((x86CPUID(0, 0).eax >= 7 && x86CPUID(7, 0).ebx & (1u << 26)) && + (x86XCR(0).eax & 0xE6) == 0xE6); +} + ++ (bool)supportsAVX512VectorLengthExtensions +{ + return ((x86CPUID(0, 0).eax >= 7 && x86CPUID(7, 0).ebx & (1u << 31)) && + (x86XCR(0).eax & 0xE6) == 0xE6); +} + ++ (bool)supportsAVX512DoublewordAndQuadwordInstructions +{ + return ((x86CPUID(0, 0).eax >= 7 && x86CPUID(7, 0).ebx & (1u << 17)) && + (x86XCR(0).eax & 0xE6) == 0xE6); +} + ++ (bool)supportsAVX512ByteAndWordInstructions +{ + return ((x86CPUID(0, 0).eax >= 7 && x86CPUID(7, 0).ebx & (1u << 30)) && + (x86XCR(0).eax & 0xE6) == 0xE6); +} + ++ (bool)supportsAVX512IntegerFusedMultiplyAdd +{ + return ((x86CPUID(0, 0).eax >= 7 && x86CPUID(7, 0).ebx & (1u << 21)) && + (x86XCR(0).eax & 0xE6) == 0xE6); +} + ++ (bool)supportsAVX512VectorByteManipulationInstructions +{ + return ((x86CPUID(0, 0).eax >= 7 && x86CPUID(7, 0).ecx & (1u << 1)) && + (x86XCR(0).eax & 0xE6) == 0xE6); +} + ++ (bool)supportsAVX512VectorPopulationCountInstruction +{ + return ((x86CPUID(0, 0).eax >= 7 && x86CPUID(7, 0).ecx & (1u << 14)) && + (x86XCR(0).eax & 0xE6) == 0xE6); +} + ++ (bool)supportsAVX512VectorNeuralNetworkInstructions +{ + return ((x86CPUID(0, 0).eax >= 7 && x86CPUID(7, 0).ecx & (1u << 11)) && + (x86XCR(0).eax & 0xE6) == 0xE6); +} + ++ (bool)supportsAVX512VectorByteManipulationInstructions2 +{ + return ((x86CPUID(0, 0).eax >= 7 && x86CPUID(7, 0).ecx & (1u << 6)) && + (x86XCR(0).eax & 0xE6) == 0xE6); +} + ++ (bool)supportsAVX512BitAlgorithms +{ + return ((x86CPUID(0, 0).eax >= 7 && x86CPUID(7, 0).ecx & (1u << 12)) && + (x86XCR(0).eax & 0xE6) == 0xE6); +} + ++ (bool)supportsAVX512Float16Instructions +{ + return ((x86CPUID(0, 0).eax >= 7 && x86CPUID(7, 0).edx & (1u << 23)) && + (x86XCR(0).eax & 0xE6) == 0xE6); +} + ++ (bool)supportsAVX512BFloat16Instructions +{ + return ((x86CPUID(0, 0).eax >= 7 && x86CPUID(7, 1).eax & (1u << 5)) && + (x86XCR(0).eax & 0xE6) == 0xE6); } #endif #if defined(OF_POWERPC) || defined(OF_POWERPC64) + (bool)supportsAltiVec Index: src/OFTCPSocket.h ================================================================== --- src/OFTCPSocket.h +++ src/OFTCPSocket.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -82,12 +82,12 @@ /** * @brief Whether the socket sends keep alives for the connection. * * @warning This is not available on the Wii or Nintendo 3DS! * + * @throw OFGetOptionFailedException The option could not be retrieved * @throw OFSetOptionFailedException The option could not be set - * @throw OFGetOptionFailedException The option could not be gotten */ @property (nonatomic) bool sendsKeepAlives; #endif #ifndef OF_WII @@ -95,12 +95,12 @@ * @brief Whether sending segments can be delayed. Setting this to `false` sets * TCP_NODELAY on the socket. * * @warning This is not available on the Wii! * + * @throw OFGetOptionFailedException The option could not be retrieved * @throw OFSetOptionFailedException The option could not be set - * @throw OFGetOptionFailedException The option could not be gotten */ @property (nonatomic) bool canDelaySendingSegments; #endif /** @@ -155,11 +155,11 @@ * @brief Connects the OFTCPSocket to the specified destination. * * @param host The host to connect to * @param port The port on the host to connect to * @throw OFConnectIPSocketFailedException Connecting failed - * @throw OFAlreadyConnectedException The socket is already connected or bound + * @throw OFAlreadyOpenException The socket is already connected or bound */ - (void)connectToHost: (OFString *)host port: (uint16_t)port; /** * @brief Asynchronously connects the OFTCPSocket to the specified destination. @@ -211,13 +211,13 @@ * * @param host The host to bind to. Use `@"0.0.0.0"` for IPv4 or `@"::"` for * IPv6 to bind to all. * @param port The port to bind to. If the port is 0, an unused port will be * chosen, which can be obtained using the return value. - * @return The port the socket was bound to + * @return The address the socket was bound to * @throw OFBindIPSocketFailedException Binding failed - * @throw OFAlreadyConnectedException The socket is already connected or bound + * @throw OFAlreadyOpenException The socket is already connected or bound */ -- (uint16_t)bindToHost: (OFString *)host port: (uint16_t)port; +- (OFSocketAddress)bindToHost: (OFString *)host port: (uint16_t)port; @end OF_ASSUME_NONNULL_END Index: src/OFTCPSocket.m ================================================================== --- src/OFTCPSocket.m +++ src/OFTCPSocket.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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 @@ #import "OFSocket+Private.h" #import "OFString.h" #import "OFTCPSocketSOCKS5Connector.h" #import "OFThread.h" -#import "OFAlreadyConnectedException.h" +#import "OFAlreadyOpenException.h" #import "OFBindIPSocketFailedException.h" #import "OFGetOptionFailedException.h" #import "OFNotImplementedException.h" #import "OFNotOpenException.h" #import "OFSetOptionFailedException.h" @@ -139,11 +139,11 @@ #if SOCK_CLOEXEC == 0 && defined(HAVE_FCNTL) && defined(FD_CLOEXEC) int flags; #endif if (_socket != OFInvalidSocketHandle) - @throw [OFAlreadyConnectedException exceptionWithSocket: self]; + @throw [OFAlreadyOpenException exceptionWithObject: self]; if ((_socket = socket( ((struct sockaddr *)&address->sockaddr)->sa_family, SOCK_STREAM | SOCK_CLOEXEC, 0)) == OFInvalidSocketHandle) { *errNo = OFSocketErrNo(); @@ -287,11 +287,11 @@ objc_autoreleasePoolPop(pool); } #endif -- (uint16_t)bindToHost: (OFString *)host port: (uint16_t)port +- (OFSocketAddress)bindToHost: (OFString *)host port: (uint16_t)port { const int one = 1; void *pool = objc_autoreleasePoolPush(); OFData *socketAddresses; OFSocketAddress address; @@ -298,11 +298,11 @@ #if SOCK_CLOEXEC == 0 && defined(HAVE_FCNTL) && defined(FD_CLOEXEC) int flags; #endif if (_socket != OFInvalidSocketHandle) - @throw [OFAlreadyConnectedException exceptionWithSocket: self]; + @throw [OFAlreadyOpenException exceptionWithObject: self]; if (_SOCKS5Host != nil) @throw [OFNotImplementedException exceptionWithSelector: _cmd object: self]; @@ -359,14 +359,12 @@ OFSocketAddressSetIPPort(&address, rnd); if ((ret = bind(_socket, (struct sockaddr *)&address.sockaddr, - address.length)) == 0) { - port = rnd; + address.length)) == 0) break; - } if (OFSocketErrNo() != EADDRINUSE) { int errNo = OFSocketErrNo(); closesocket(_socket); @@ -380,15 +378,10 @@ } } } #endif - objc_autoreleasePoolPop(pool); - - if (port > 0) - return port; - #if !defined(OF_HPUX) && !defined(OF_WII) && !defined(OF_NINTENDO_3DS) memset(&address, 0, sizeof(address)); address.length = (socklen_t)sizeof(address.sockaddr); if (OFGetSockName(_socket, (struct sockaddr *)&address.sockaddr, @@ -404,14 +397,16 @@ errNo: errNo]; } switch (((struct sockaddr *)&address.sockaddr)->sa_family) { case AF_INET: - return OFFromBigEndian16(address.sockaddr.in.sin_port); + address.family = OFSocketAddressFamilyIPv4; + break; # ifdef OF_HAVE_IPV6 case AF_INET6: - return OFFromBigEndian16(address.sockaddr.in6.sin6_port); + address.family = OFSocketAddressFamilyIPv6; + break; # endif default: closesocket(_socket); _socket = OFInvalidSocketHandle; @@ -419,18 +414,15 @@ exceptionWithHost: host port: port socket: self errNo: EAFNOSUPPORT]; } -#else - closesocket(_socket); - _socket = OFInvalidSocketHandle; - @throw [OFBindIPSocketFailedException exceptionWithHost: host - port: port - socket: self - errNo: EADDRNOTAVAIL]; #endif + + objc_autoreleasePoolPop(pool); + + return address; } #if !defined(OF_WII) && !defined(OF_NINTENDO_3DS) - (void)setSendsKeepAlives: (bool)sendsKeepAlives { Index: src/OFTCPSocketSOCKS5Connector.h ================================================================== --- src/OFTCPSocketSOCKS5Connector.h +++ src/OFTCPSocketSOCKS5Connector.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,11 +13,10 @@ * file. */ #include "config.h" -#include #include #import "OFTCPSocketSOCKS5Connector.h" #import "OFData.h" #import "OFRunLoop.h" @@ -266,11 +265,11 @@ [_socket asyncReadIntoBuffer: _buffer exactLength: addressLength[0] + 2 runLoopMode: runLoopMode]; return false; default: - assert(0); + OFAssert(0); return false; } } - (OFData *)stream: (OFStream *)sock @@ -303,10 +302,10 @@ [_socket asyncReadIntoBuffer: _buffer exactLength: 4 runLoopMode: runLoopMode]; return nil; default: - assert(0); + OFAssert(0); return nil; } } @end Index: src/OFTLSKey.h ================================================================== --- src/OFTLSKey.h +++ src/OFTLSKey.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFTLSStream.h ================================================================== --- src/OFTLSStream.h +++ src/OFTLSStream.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -59,17 +59,16 @@ * * 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. + * @ref lowlevelWriteBuffer:length:, + * @ref lowlevelHasDataInReadBuffer and + * @ref asyncPerformClientHandshakeWithHost:runLoopMode:. + * + * In order to get access to the underlying stream, @ref underlyingStream can + * be used. */ @interface OFTLSStream: OFStream { OFStream @@ -107,31 +106,34 @@ * @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; + OFReadyForWritingObserving> *)stream; /** * @brief Initializes the TLS stream with the specified stream as its * underlying stream. * + * @note The delegate of the specified stream will be changed to the TLS + * stream. You must not change this before the TLS session is completed. + * * @param stream The stream to use as underlying stream. Must not be closed * before the TLS stream is closed. * @return An initialized TLS stream */ - (instancetype)initWithStream: (OFStream *)stream + OFReadyForWritingObserving> *)stream OF_DESIGNATED_INITIALIZER; /** * @brief Asynchronously performs the TLS client handshake for the specified * host and calls the delegate afterwards. * * @param host The host to perform the handshake with * @throw OFTLSHandshakeFailedException The TLS handshake failed - * @throw OFAlreadyConnectedException The handshake was already performed + * @throw OFAlreadyOpenException The handshake was already performed */ - (void)asyncPerformClientHandshakeWithHost: (OFString *)host; /** * @brief Asynchronously performs the TLS client handshake for the specified @@ -138,21 +140,21 @@ * host and calls the delegate afterwards. * * @param host The host to perform the handshake with * @param runLoopMode The run loop mode in which to perform the async handshake * @throw OFTLSHandshakeFailedException The TLS handshake failed - * @throw OFAlreadyConnectedException The handshake was already performed + * @throw OFAlreadyOpenException The handshake was already performed */ - (void)asyncPerformClientHandshakeWithHost: (OFString *)host runLoopMode: (OFRunLoopMode)runLoopMode; /** * @brief Performs the TLS client handshake for the specified host. * * @param host The host to perform the handshake with * @throw OFTLSHandshakeFailedException The TLS handshake failed - * @throw OFAlreadyConnectedException The handshake was already performed + * @throw OFAlreadyOpenException The handshake was already performed */ - (void)performClientHandshakeWithHost: (OFString *)host; @end #ifdef __cplusplus Index: src/OFTLSStream.m ================================================================== --- src/OFTLSStream.m +++ src/OFTLSStream.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -139,16 +139,10 @@ - (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; } ADDED src/OFTaggedPointerColor.h Index: src/OFTaggedPointerColor.h ================================================================== --- /dev/null +++ src/OFTaggedPointerColor.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2008-2024 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#import "OFColor.h" + +OF_ASSUME_NONNULL_BEGIN + +@interface OFTaggedPointerColor: OFColor ++ (OFTaggedPointerColor *)colorWithRed: (uint8_t)red + green: (uint8_t)green + blue: (uint8_t)blue; +@end + +OF_ASSUME_NONNULL_END ADDED src/OFTaggedPointerColor.m Index: src/OFTaggedPointerColor.m ================================================================== --- /dev/null +++ src/OFTaggedPointerColor.m @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2008-2024 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#include "config.h" + +#import "OFTaggedPointerColor.h" + +static int colorTag; + +@implementation OFTaggedPointerColor ++ (void)initialize +{ + if (self == [OFTaggedPointerColor class]) + colorTag = objc_registerTaggedPointerClass(self); +} + ++ (OFTaggedPointerColor *)colorWithRed: (uint8_t)red + green: (uint8_t)green + blue: (uint8_t)blue +{ + return objc_createTaggedPointer(colorTag, + (uintptr_t)red << 16 | (uintptr_t)green << 8 | (uintptr_t)blue); +} + +- (void)getRed: (float *)red + green: (float *)green + blue: (float *)blue + alpha: (float *)alpha +{ + uintptr_t value = object_getTaggedPointerValue(self); + + *red = (float)(value >> 16) / 255; + *green = (float)((value >> 8) & 0xFF) / 255; + *blue = (float)(value & 0xFF) / 255; + + if (alpha != NULL) + *alpha = 1; +} + +OF_SINGLETON_METHODS +@end ADDED src/OFTaggedPointerDate.h Index: src/OFTaggedPointerDate.h ================================================================== --- /dev/null +++ src/OFTaggedPointerDate.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2008-2024 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#import "OFDate.h" + +OF_ASSUME_NONNULL_BEGIN + +#if UINTPTR_MAX == UINT64_MAX +@interface OFTaggedPointerDate: OFDate ++ (OFTaggedPointerDate *)dateWithUInt64TimeIntervalSince1970: (uint64_t)value; +@end +#endif + +OF_ASSUME_NONNULL_END ADDED src/OFTaggedPointerDate.m Index: src/OFTaggedPointerDate.m ================================================================== --- /dev/null +++ src/OFTaggedPointerDate.m @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2008-2024 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#import "OFTaggedPointerDate.h" + +#if UINTPTR_MAX == UINT64_MAX +static int dateTag; + +@implementation OFTaggedPointerDate ++ (void)initialize +{ + if (self == [OFTaggedPointerDate class]) + dateTag = objc_registerTaggedPointerClass(self); +} + ++ (OFTaggedPointerDate *)dateWithUInt64TimeIntervalSince1970: (uint64_t)value +{ + return objc_createTaggedPointer(dateTag, value & ~(UINT64_C(4) << 60)); +} + +- (OFTimeInterval)timeIntervalSince1970 +{ + uint64_t value = (uint64_t)object_getTaggedPointerValue(self); + + value |= UINT64_C(4) << 60; + + return OFFromBigEndianDouble(OFRawUInt64ToDouble(OFToBigEndian64( + value))); +} + +OF_SINGLETON_METHODS +@end +#endif ADDED src/OFTaggedPointerNumber.h Index: src/OFTaggedPointerNumber.h ================================================================== --- /dev/null +++ src/OFTaggedPointerNumber.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2008-2024 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#import "OFNumber.h" + +OF_ASSUME_NONNULL_BEGIN + +#define OFTaggedPointerNumberTagBits 4 + +@interface OFTaggedPointerNumber: OFNumber +@end + +OF_ASSUME_NONNULL_END ADDED src/OFTaggedPointerNumber.m Index: src/OFTaggedPointerNumber.m ================================================================== --- /dev/null +++ src/OFTaggedPointerNumber.m @@ -0,0 +1,198 @@ +/* + * Copyright (c) 2008-2024 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#include "config.h" + +#import "OFTaggedPointerNumber.h" + +#import "OFInvalidFormatException.h" + +enum Tag { + tagChar, + tagShort, + tagInt, + tagLong, + tagLongLong, + tagUnsignedChar, + tagUnsignedShort, + tagUnsignedInt, + tagUnsignedLong, + tagUnsignedLongLong, +}; +static const uintptr_t tagMask = (1 << OFTaggedPointerNumberTagBits) - 1; +static int numberTag; + +@implementation OFTaggedPointerNumber ++ (void)initialize +{ + if (self == [OFTaggedPointerNumber class]) + numberTag = objc_registerTaggedPointerClass(self); +} + ++ (OFTaggedPointerNumber *)numberWithChar: (signed char)value +{ + return objc_createTaggedPointer(numberTag, + ((uintptr_t)(unsigned char)value << OFTaggedPointerNumberTagBits) | + tagChar); +} + ++ (OFTaggedPointerNumber *)numberWithShort: (short)value +{ + return objc_createTaggedPointer(numberTag, + ((uintptr_t)(unsigned short)value << OFTaggedPointerNumberTagBits) | + tagShort); +} + ++ (OFTaggedPointerNumber *)numberWithInt: (int)value +{ + return objc_createTaggedPointer(numberTag, + ((uintptr_t)(unsigned int)value << OFTaggedPointerNumberTagBits) | + tagInt); +} + ++ (OFTaggedPointerNumber *)numberWithLong: (long)value +{ + return objc_createTaggedPointer(numberTag, + ((uintptr_t)(unsigned long)value << OFTaggedPointerNumberTagBits) | + tagLong); +} + ++ (OFTaggedPointerNumber *)numberWithLongLong: (long long)value +{ + return objc_createTaggedPointer(numberTag, + ((uintptr_t)(unsigned long long)value << + OFTaggedPointerNumberTagBits) | tagLongLong); +} + ++ (OFTaggedPointerNumber *)numberWithUnsignedChar: (unsigned char)value +{ + return objc_createTaggedPointer(numberTag, + ((uintptr_t)value << OFTaggedPointerNumberTagBits) | + tagUnsignedChar); +} + ++ (OFTaggedPointerNumber *)numberWithUnsignedShort: (unsigned short)value +{ + return objc_createTaggedPointer(numberTag, + ((uintptr_t)value << OFTaggedPointerNumberTagBits) | + tagUnsignedShort); +} + ++ (OFTaggedPointerNumber *)numberWithUnsignedInt: (unsigned int)value +{ + return objc_createTaggedPointer(numberTag, + ((uintptr_t)value << OFTaggedPointerNumberTagBits) | + tagUnsignedInt); +} + ++ (OFTaggedPointerNumber *)numberWithUnsignedLong: (unsigned long)value +{ + return objc_createTaggedPointer(numberTag, + ((uintptr_t)value << OFTaggedPointerNumberTagBits) | + tagUnsignedLong); +} + ++ (OFTaggedPointerNumber *)numberWithUnsignedLongLong: (unsigned long long)value +{ + return objc_createTaggedPointer(numberTag, + ((uintptr_t)value << OFTaggedPointerNumberTagBits) | + tagUnsignedLongLong); +} + +- (const char *)objCType +{ + uintptr_t value = object_getTaggedPointerValue(self); + + switch (value & tagMask) { + case tagChar: + return @encode(signed char); + case tagShort: + return @encode(short); + case tagInt: + return @encode(int); + case tagLong: + return @encode(long); + case tagLongLong: + return @encode(long long); + case tagUnsignedChar: + return @encode(unsigned char); + case tagUnsignedShort: + return @encode(unsigned short); + case tagUnsignedInt: + return @encode(unsigned int); + case tagUnsignedLong: + return @encode(unsigned long); + case tagUnsignedLongLong: + return @encode(unsigned long long); + default: + @throw [OFInvalidFormatException exception]; + } +} + +#define RETURN_VALUE \ + uintptr_t value = object_getTaggedPointerValue(self); \ + \ + switch (value & tagMask) { \ + case tagChar: \ + return (signed char)(unsigned char) \ + (value >> OFTaggedPointerNumberTagBits); \ + case tagShort: \ + return (short)(unsigned short) \ + (value >> OFTaggedPointerNumberTagBits); \ + case tagInt: \ + return (int)(unsigned int) \ + (value >> OFTaggedPointerNumberTagBits); \ + case tagLong: \ + return (long)(unsigned long) \ + (value >> OFTaggedPointerNumberTagBits); \ + case tagLongLong: \ + return (long long)(unsigned long long) \ + (value >> OFTaggedPointerNumberTagBits); \ + case tagUnsignedChar: \ + return (unsigned char) \ + (value >> OFTaggedPointerNumberTagBits); \ + case tagUnsignedShort: \ + return (unsigned short) \ + (value >> OFTaggedPointerNumberTagBits); \ + case tagUnsignedInt: \ + return (unsigned int) \ + (value >> OFTaggedPointerNumberTagBits); \ + case tagUnsignedLong: \ + return (unsigned long) \ + (value >> OFTaggedPointerNumberTagBits); \ + case tagUnsignedLongLong: \ + return (unsigned long long) \ + (value >> OFTaggedPointerNumberTagBits); \ + default: \ + @throw [OFInvalidFormatException exception]; \ + } +- (long long)longLongValue +{ + RETURN_VALUE +} + +- (unsigned long long)unsignedLongLongValue +{ + RETURN_VALUE +} + +- (double)doubleValue +{ + RETURN_VALUE +} +#undef RETURN_VALUE + +OF_SINGLETON_METHODS +@end Index: src/OFTarArchive.h ================================================================== --- src/OFTarArchive.h +++ src/OFTarArchive.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,12 +18,12 @@ #import "OFString.h" #import "OFTarArchiveEntry.h" OF_ASSUME_NONNULL_BEGIN +@class OFIRI; @class OFStream; -@class OFURI; /** * @class OFTarArchive OFTarArchive.h ObjFW/OFTarArchive.h * * @brief A class for accessing and manipulating tar archives. @@ -30,15 +30,11 @@ */ OF_SUBCLASSING_RESTRICTED @interface OFTarArchive: OFObject { OFStream *_stream; - enum OFTarArchiveMode { - OFTarArchiveModeRead, - OFTarArchiveModeWrite, - OFTarArchiveModeAppend - } _mode; + uint_least8_t _mode; OFStringEncoding _encoding; OFTarArchiveEntry *_Nullable _currentEntry; #ifdef OF_TAR_ARCHIVE_M @public #endif @@ -66,31 +62,31 @@ + (instancetype)archiveWithStream: (OFStream *)stream mode: (OFString *)mode; /** * @brief Creates a new OFTarArchive object with the specified file. * - * @param URI The URI to the tar archive + * @param IRI The IRI to the tar archive * @param mode The mode for the tar file. Valid modes are "r" for reading, * "w" for creating a new file and "a" for appending to an existing * archive. * @return A new, autoreleased OFTarArchive * @throw OFInvalidFormatException The archive has an invalid format * @throw OFSeekFailedException The archive was open in append mode and seeking * failed */ -+ (instancetype)archiveWithURI: (OFURI *)URI mode: (OFString *)mode; ++ (instancetype)archiveWithIRI: (OFIRI *)IRI mode: (OFString *)mode; /** - * @brief Creates a URI for accessing a the specified file within the specified - * tar archive. + * @brief Creates an IRI for accessing a the specified file within the + * specified tar archive. * * @param path The path of the file within the archive - * @param URI The URI of the archive - * @return A URI for accessing the specified file within the specified tar + * @param IRI The IRI of the archive + * @return An IRI for accessing the specified file within the specified tar * archive */ -+ (OFURI *)URIForFilePath: (OFString *)path inArchiveWithURI: (OFURI *)URI; ++ (OFIRI *)IRIForFilePath: (OFString *)path inArchiveWithIRI: (OFIRI *)IRI; - (instancetype)init OF_UNAVAILABLE; /** * @brief Initializes an already allocated OFTarArchive object with the @@ -111,20 +107,20 @@ /** * @brief Initializes an already allocated OFTarArchive object with the * specified file. * - * @param URI The URI to the tar archive + * @param IRI The IRI to the tar archive * @param mode The mode for the tar file. Valid modes are "r" for reading, * "w" for creating a new file and "a" for appending to an existing * archive. * @return An initialized OFTarArchive * @throw OFInvalidFormatException The archive has an invalid format * @throw OFSeekFailedException The archive was open in append mode and seeking * failed */ -- (instancetype)initWithURI: (OFURI *)URI mode: (OFString *)mode; +- (instancetype)initWithIRI: (OFIRI *)IRI mode: (OFString *)mode; /** * @brief Returns the next entry from the tar archive or `nil` if all entries * have been read. * Index: src/OFTarArchive.m ================================================================== --- src/OFTarArchive.m +++ src/OFTarArchive.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,23 +20,29 @@ #include #import "OFTarArchive.h" #import "OFTarArchiveEntry.h" #import "OFTarArchiveEntry+Private.h" -#import "OFArchiveURIHandler.h" +#import "OFArchiveIRIHandler.h" #import "OFDate.h" +#import "OFIRI.h" +#import "OFIRIHandler.h" #import "OFSeekableStream.h" #import "OFStream.h" -#import "OFURI.h" -#import "OFURIHandler.h" #import "OFInvalidArgumentException.h" #import "OFInvalidFormatException.h" #import "OFNotOpenException.h" #import "OFOutOfRangeException.h" #import "OFTruncatedDataException.h" #import "OFWriteFailedException.h" + +enum { + modeRead, + modeWrite, + modeAppend +}; OF_DIRECT_MEMBERS @interface OFTarArchiveFileReadStream: OFStream { OFTarArchive *_archive; @@ -72,18 +78,18 @@ + (instancetype)archiveWithStream: (OFStream *)stream mode: (OFString *)mode { return [[[self alloc] initWithStream: stream mode: mode] autorelease]; } -+ (instancetype)archiveWithURI: (OFURI *)URI mode: (OFString *)mode ++ (instancetype)archiveWithIRI: (OFIRI *)IRI mode: (OFString *)mode { - return [[[self alloc] initWithURI: URI mode: mode] autorelease]; + return [[[self alloc] initWithIRI: IRI mode: mode] autorelease]; } -+ (OFURI *)URIForFilePath: (OFString *)path inArchiveWithURI: (OFURI *)URI ++ (OFIRI *)IRIForFilePath: (OFString *)path inArchiveWithIRI: (OFIRI *)IRI { - return OFArchiveURIHandlerURIForFileInArchive(@"tar", path, URI); + return OFArchiveIRIHandlerIRIForFileInArchive(@"tar", path, IRI); } - (instancetype)init { OF_INVALID_INIT_METHOD @@ -95,19 +101,19 @@ @try { _stream = [stream retain]; if ([mode isEqual: @"r"]) - _mode = OFTarArchiveModeRead; + _mode = modeRead; else if ([mode isEqual: @"w"]) - _mode = OFTarArchiveModeWrite; + _mode = modeWrite; else if ([mode isEqual: @"a"]) - _mode = OFTarArchiveModeAppend; + _mode = modeAppend; else @throw [OFInvalidArgumentException exception]; - if (_mode == OFTarArchiveModeAppend) { + if (_mode == modeAppend) { uint32_t buffer[1024 / sizeof(uint32_t)]; bool empty = true; if (![_stream isKindOfClass: [OFSeekableStream class]]) @throw [OFInvalidArgumentException exception]; @@ -134,20 +140,20 @@ } return self; } -- (instancetype)initWithURI: (OFURI *)URI mode: (OFString *)mode +- (instancetype)initWithIRI: (OFIRI *)IRI mode: (OFString *)mode { void *pool = objc_autoreleasePoolPush(); OFStream *stream; @try { if ([mode isEqual: @"a"]) - stream = [OFURIHandler openItemAtURI: URI mode: @"r+"]; + stream = [OFIRIHandler openItemAtIRI: IRI mode: @"r+"]; else - stream = [OFURIHandler openItemAtURI: URI mode: mode]; + stream = [OFIRIHandler openItemAtIRI: IRI mode: mode]; } @catch (id e) { [self release]; @throw e; } @@ -170,12 +176,25 @@ - (OFTarArchiveEntry *)nextEntry { uint32_t buffer[512 / sizeof(uint32_t)]; bool empty = true; - if (_mode != OFTarArchiveModeRead) + if (_mode != modeRead) @throw [OFInvalidArgumentException exception]; + + if (_currentEntry != nil && _lastReturnedStream == nil) { + /* + * No read stream was created since the last call to + * -[nextEntry]. Create it so that we can properly skip the + * data. + */ + void *pool = objc_autoreleasePoolPush(); + + [self streamForReadingCurrentEntry]; + + objc_autoreleasePoolPop(pool); + } [_currentEntry release]; _currentEntry = nil; [(OFTarArchiveFileReadStream *)_lastReturnedStream of_skip]; @@ -212,11 +231,11 @@ return _currentEntry; } - (OFStream *)streamForReadingCurrentEntry { - if (_mode != OFTarArchiveModeRead) + if (_mode != modeRead) @throw [OFInvalidArgumentException exception]; if (_currentEntry == nil) @throw [OFInvalidArgumentException exception]; @@ -230,11 +249,11 @@ return _lastReturnedStream; } - (OFStream *)streamForWritingEntry: (OFTarArchiveEntry *)entry { - if (_mode != OFTarArchiveModeWrite && _mode != OFTarArchiveModeAppend) + if (_mode != modeWrite && _mode != modeAppend) @throw [OFInvalidArgumentException exception]; @try { [_lastReturnedStream close]; } @catch (OFNotOpenException *e) { @@ -262,11 +281,11 @@ } @catch (OFNotOpenException *e) { /* Might have already been closed by the user - that's fine. */ } _lastReturnedStream = nil; - if (_mode == OFTarArchiveModeWrite || _mode == OFTarArchiveModeAppend) { + if (_mode == modeWrite || _mode == modeAppend) { char buffer[1024]; memset(buffer, '\0', 1024); [_stream writeBuffer: buffer length: 1024]; } @@ -341,13 +360,13 @@ @throw [OFNotOpenException exceptionWithObject: self]; return _atEndOfStream; } -- (bool)hasDataInReadBuffer +- (bool)lowlevelHasDataInReadBuffer { - return (super.hasDataInReadBuffer || _stream.hasDataInReadBuffer); + return _stream.hasDataInReadBuffer; } - (int)fileDescriptorForReading { return ((id )_stream) Index: src/OFTarArchiveEntry+Private.h ================================================================== --- src/OFTarArchiveEntry+Private.h +++ src/OFTarArchiveEntry+Private.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,12 +30,14 @@ #include "unistd_wrapper.h" #include "platform.h" #ifdef OF_AMIGAOS +# define Class IntuitionClass # include # include +# undef Class #endif #ifdef OF_WII # define nanosleep ogc_nanosleep # include Index: src/OFTimer+Private.h ================================================================== --- src/OFTimer+Private.h +++ src/OFTimer+Private.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,8 +19,9 @@ OF_DIRECT_MEMBERS @interface OFTimer () - (void)of_setInRunLoop: (nullable OFRunLoop *)runLoop mode: (nullable OFRunLoopMode)mode; +- (void)of_reschedule; @end OF_ASSUME_NONNULL_END Index: src/OFTimer.h ================================================================== --- src/OFTimer.h +++ src/OFTimer.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -460,12 +460,13 @@ * @return The result of the comparison */ - (OFComparisonResult)compare: (OFTimer *)timer; /** - * @brief Fires the timer, meaning it will execute the specified selector on the - * target. + * @brief Fires the timer without changing its regular schedule. + * + * A non-repeating timer will be invalidated after firing. */ - (void)fire; /** * @brief Invalidates the timer, preventing it from firing. Index: src/OFTimer.m ================================================================== --- src/OFTimer.m +++ src/OFTimer.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,12 +15,10 @@ #include "config.h" #include -#include - #import "OFTimer.h" #import "OFTimer+Private.h" #import "OFDate.h" #import "OFRunLoop.h" #import "OFRunLoop+Private.h" @@ -485,12 +483,12 @@ { /* * The run loop references the timer, so it should never be deallocated * if it is still in a run loop. */ - assert(_inRunLoop == nil); - assert(_inRunLoopMode == nil); + OFAssert(_inRunLoop == nil); + OFAssert(_inRunLoopMode == nil); [_fireDate release]; [_target release]; [_object1 release]; [_object2 release]; @@ -523,90 +521,93 @@ [oldInRunLoop release]; _inRunLoopMode = [mode copy]; [oldInRunLoopMode release]; } + +- (void)of_reschedule +{ + long long missedIntervals; + OFTimeInterval newFireDate; + OFRunLoop *runLoop; + + if (!_repeats || !_valid) + return; + + missedIntervals = -_fireDate.timeIntervalSinceNow / _interval; + + /* In case the clock was changed backwards */ + if (missedIntervals < 0) + missedIntervals = 0; + + newFireDate = _fireDate.timeIntervalSince1970 + + (missedIntervals + 1) * _interval; + + [_fireDate release]; + _fireDate = nil; + _fireDate = [[OFDate alloc] + initWithTimeIntervalSince1970: newFireDate]; + + runLoop = [OFRunLoop currentRunLoop]; + [runLoop addTimer: self forMode: runLoop.currentMode]; +} - (void)fire { - void *pool = objc_autoreleasePoolPush(); - id target = [[_target retain] autorelease]; - id object1 = [[_object1 retain] autorelease]; - id object2 = [[_object2 retain] autorelease]; - id object3 = [[_object3 retain] autorelease]; - id object4 = [[_object4 retain] autorelease]; - OFEnsure(_arguments <= 4); - if (_repeats && _valid) { - int64_t missedIntervals = - -_fireDate.timeIntervalSinceNow / _interval; - OFTimeInterval newFireDate; - OFRunLoop *runLoop; - - /* In case the clock was changed backwards */ - if (missedIntervals < 0) - missedIntervals = 0; - - newFireDate = _fireDate.timeIntervalSince1970 + - (missedIntervals + 1) * _interval; - - [_fireDate release]; - _fireDate = [[OFDate alloc] - initWithTimeIntervalSince1970: newFireDate]; - - runLoop = [OFRunLoop currentRunLoop]; - [runLoop addTimer: self forMode: runLoop.currentMode]; - } else - [self invalidate]; + if (!_valid) + return; #ifdef OF_HAVE_BLOCKS if (_block != NULL) _block(self); else { #endif switch (_arguments) { case 0: - [target performSelector: _selector]; + [_target performSelector: _selector]; break; case 1: - [target performSelector: _selector withObject: object1]; + [_target performSelector: _selector + withObject: _object1]; break; case 2: - [target performSelector: _selector - withObject: object1 - withObject: object2]; + [_target performSelector: _selector + withObject: _object1 + withObject: _object2]; break; case 3: - [target performSelector: _selector - withObject: object1 - withObject: object2 - withObject: object3]; + [_target performSelector: _selector + withObject: _object1 + withObject: _object2 + withObject: _object3]; break; case 4: - [target performSelector: _selector - withObject: object1 - withObject: object2 - withObject: object3 - withObject: object4]; + [_target performSelector: _selector + withObject: _object1 + withObject: _object2 + withObject: _object3 + withObject: _object4]; break; } #ifdef OF_HAVE_BLOCKS } #endif + if (!_repeats) + [self invalidate]; + #ifdef OF_HAVE_THREADS [_condition lock]; @try { _done = true; [_condition signal]; } @finally { [_condition unlock]; } #endif - - objc_autoreleasePoolPop(pool); } - (OFDate *)fireDate { return _fireDate; @@ -635,10 +636,13 @@ - (void)invalidate { _valid = false; +#ifdef OF_HAVE_BLOCKS + [_block release]; +#endif [_target release]; [_object1 release]; [_object2 release]; [_object3 release]; [_object4 release]; Index: src/OFTriple.h ================================================================== --- src/OFTriple.h +++ src/OFTriple.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,9 @@ OF_ASSUME_NONNULL_BEGIN OF_DIRECT_MEMBERS @interface OFUDPSocket () -- (uint16_t)of_bindToAddress: (OFSocketAddress *)address - extraType: (int)extraType; +- (void)of_bindToAddress: (OFSocketAddress *)address extraType: (int)extraType; @end OF_ASSUME_NONNULL_END Index: src/OFUDPSocket.h ================================================================== --- src/OFUDPSocket.h +++ src/OFUDPSocket.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -69,13 +69,13 @@ * * @param host The host to bind to. Use `@"0.0.0.0"` for IPv4 or `@"::"` for * IPv6 to bind to all. * @param port The port to bind to. If the port is 0, an unused port will be * chosen, which can be obtained using the return value. - * @return The port the socket was bound to + * @return The address the socket was bound to * @throw OFBindIPSocketFailedException Binding failed - * @throw OFAlreadyConnectedException The socket is already bound + * @throw OFAlreadyOpenException The socket is already bound */ -- (uint16_t)bindToHost: (OFString *)host port: (uint16_t)port; +- (OFSocketAddress)bindToHost: (OFString *)host port: (uint16_t)port; @end OF_ASSUME_NONNULL_END Index: src/OFUDPSocket.m ================================================================== --- src/OFUDPSocket.m +++ src/OFUDPSocket.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,23 +32,25 @@ #import "OFData.h" #import "OFSocket.h" #import "OFSocket+Private.h" #import "OFThread.h" -#import "OFAlreadyConnectedException.h" +#import "OFAlreadyOpenException.h" #import "OFBindIPSocketFailedException.h" @implementation OFUDPSocket @dynamic delegate; -- (uint16_t)of_bindToAddress: (OFSocketAddress *)address - extraType: (int)extraType OF_DIRECT +- (void)of_bindToAddress: (OFSocketAddress *)address + extraType: (int)extraType OF_DIRECT { - void *pool = objc_autoreleasePoolPush(); - uint16_t port; #if SOCK_CLOEXEC == 0 && defined(HAVE_FCNTL) && defined(FD_CLOEXEC) int flags; +#endif +#if !defined(OF_HPUX) && !defined(OF_WII) && !defined(OF_NINTENDO_3DS) + OFString *host; + uint16_t port; #endif if ((_socket = socket( ((struct sockaddr *)&address->sockaddr)->sa_family, SOCK_DGRAM | SOCK_CLOEXEC | extraType, 0)) == OFInvalidSocketHandle) @@ -100,11 +102,11 @@ break; if (OFSocketErrNo() != EADDRINUSE) { int errNo = OFSocketErrNo(); OFString *host = OFSocketAddressString(address); - port = OFSocketAddressIPPort(address); + uint16_t port = OFSocketAddressIPPort(address); closesocket(_socket); _socket = OFInvalidSocketHandle; @throw [OFBindIPSocketFailedException @@ -115,16 +117,14 @@ } } } #endif - objc_autoreleasePoolPop(pool); - - if ((port = OFSocketAddressIPPort(address)) > 0) - return port; - #if !defined(OF_HPUX) && !defined(OF_WII) && !defined(OF_NINTENDO_3DS) + host = OFSocketAddressString(address); + port = OFSocketAddressIPPort(address); + memset(address, 0, sizeof(*address)); address->length = (socklen_t)sizeof(address->sockaddr); if (OFGetSockName(_socket, (struct sockaddr *)&address->sockaddr, &address->length) != 0) { @@ -131,64 +131,56 @@ int errNo = OFSocketErrNo(); closesocket(_socket); _socket = OFInvalidSocketHandle; - @throw [OFBindIPSocketFailedException - exceptionWithHost: OFSocketAddressString(address) - port: OFSocketAddressIPPort(address) - socket: self - errNo: errNo]; + @throw [OFBindIPSocketFailedException exceptionWithHost: host + port: port + socket: self + errNo: errNo]; } switch (((struct sockaddr *)&address->sockaddr)->sa_family) { case AF_INET: - return OFFromBigEndian16(address->sockaddr.in.sin_port); + address->family = OFSocketAddressFamilyIPv4; + break; # ifdef OF_HAVE_IPV6 case AF_INET6: - return OFFromBigEndian16(address->sockaddr.in6.sin6_port); + address->family = OFSocketAddressFamilyIPv6; + break; # endif default: closesocket(_socket); _socket = OFInvalidSocketHandle; @throw [OFBindIPSocketFailedException - exceptionWithHost: OFSocketAddressString(address) - port: OFSocketAddressIPPort(address) + exceptionWithHost: host + port: port socket: self errNo: EAFNOSUPPORT]; } -#else - closesocket(_socket); - _socket = OFInvalidSocketHandle; - - @throw [OFBindIPSocketFailedException - exceptionWithHost: OFSocketAddressString(address) - port: OFSocketAddressIPPort(address) - socket: self - errNo: EADDRNOTAVAIL]; #endif } -- (uint16_t)bindToHost: (OFString *)host port: (uint16_t)port +- (OFSocketAddress)bindToHost: (OFString *)host port: (uint16_t)port { void *pool = objc_autoreleasePoolPush(); OFData *socketAddresses; OFSocketAddress address; if (_socket != OFInvalidSocketHandle) - @throw [OFAlreadyConnectedException exceptionWithSocket: self]; + @throw [OFAlreadyOpenException exceptionWithObject: self]; socketAddresses = [[OFThread DNSResolver] resolveAddressesForHost: host addressFamily: OFSocketAddressFamilyAny]; address = *(OFSocketAddress *)[socketAddresses itemAtIndex: 0]; OFSocketAddressSetIPPort(&address, port); - port = [self of_bindToAddress: &address extraType: 0]; + [self of_bindToAddress: &address extraType: 0]; objc_autoreleasePoolPop(pool); - return port; + return address; } @end Index: src/OFUNIXDatagramSocket.h ================================================================== --- src/OFUNIXDatagramSocket.h +++ src/OFUNIXDatagramSocket.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,14 +61,15 @@ 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 + * @param path The path to bind to or `nil` for an anonymous socket + * @return The address on which this socket can be reached, if a path was + * specified * @throw OFBindUNIXSocketFailedException Binding failed - * @throw OFAlreadyConnectedException The socket is already bound + * @throw OFAlreadyOpenException The socket is already bound */ -- (OFSocketAddress)bindToPath: (OFString *)path; +- (OFSocketAddress)bindToPath: (nullable OFString *)path; @end OF_ASSUME_NONNULL_END Index: src/OFUNIXDatagramSocket.m ================================================================== --- src/OFUNIXDatagramSocket.m +++ src/OFUNIXDatagramSocket.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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 @@ #import "OFUNIXDatagramSocket.h" #import "OFSocket.h" #import "OFSocket+Private.h" #import "OFString.h" -#import "OFAlreadyConnectedException.h" +#import "OFAlreadyOpenException.h" #import "OFBindUNIXSocketFailedException.h" @implementation OFUNIXDatagramSocket @dynamic delegate; @@ -36,16 +36,21 @@ #if SOCK_CLOEXEC == 0 && defined(HAVE_FCNTL_H) && defined(FD_CLOEXEC) int flags; #endif if (_socket != OFInvalidSocketHandle) - @throw [OFAlreadyConnectedException exceptionWithSocket: self]; + @throw [OFAlreadyOpenException exceptionWithObject: self]; - address = OFSocketAddressMakeUNIX(path); + if (path != nil) + address = OFSocketAddressMakeUNIX(path); + else { + address.family = OFSocketAddressFamilyUnknown; + address.length = 0; + } - if ((_socket = socket(address.sockaddr.un.sun_family, - SOCK_DGRAM | SOCK_CLOEXEC, 0)) == OFInvalidSocketHandle) + if ((_socket = socket(AF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, 0)) == + OFInvalidSocketHandle) @throw [OFBindUNIXSocketFailedException exceptionWithPath: path socket: self errNo: OFSocketErrNo()]; @@ -54,21 +59,23 @@ #if SOCK_CLOEXEC == 0 && defined(HAVE_FCNTL_H) && defined(FD_CLOEXEC) if ((flags = fcntl(_socket, F_GETFD, 0)) != -1) fcntl(_socket, F_SETFD, flags | FD_CLOEXEC); #endif - if (bind(_socket, (struct sockaddr *)&address.sockaddr, - address.length) != 0) { - int errNo = OFSocketErrNo(); - - closesocket(_socket); - _socket = OFInvalidSocketHandle; - - @throw [OFBindUNIXSocketFailedException - exceptionWithPath: path - socket: self - errNo: errNo]; + if (path != nil) { + if (bind(_socket, (struct sockaddr *)&address.sockaddr, + address.length) != 0) { + int errNo = OFSocketErrNo(); + + closesocket(_socket); + _socket = OFInvalidSocketHandle; + + @throw [OFBindUNIXSocketFailedException + exceptionWithPath: path + socket: self + errNo: errNo]; + } } return address; } @end Index: src/OFUNIXStreamSocket.h ================================================================== --- src/OFUNIXStreamSocket.h +++ src/OFUNIXStreamSocket.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,20 +53,20 @@ /** * @brief Connects the OFUNIXStreamSocket to the specified destination. * * @param path The path to connect to * @throw OFConnectUNIXSocketFailedException Connecting failed - * @throw OFAlreadyConnectedException The socket is already connected or bound + * @throw OFAlreadyOpenException The socket is already connected or bound */ - (void)connectToPath: (OFString *)path; /** * @brief Binds the socket to the specified host and port. * * @param path The path to bind to * @throw OFBindUNIXSocketFailedException Binding failed - * @throw OFAlreadyConnectedException The socket is already connected or bound + * @throw OFAlreadyOpenException The socket is already connected or bound */ - (void)bindToPath: (OFString *)path; @end OF_ASSUME_NONNULL_END Index: src/OFUNIXStreamSocket.m ================================================================== --- src/OFUNIXStreamSocket.m +++ src/OFUNIXStreamSocket.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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 @@ #import "OFUNIXStreamSocket.h" #import "OFSocket.h" #import "OFSocket+Private.h" #import "OFString.h" -#import "OFAlreadyConnectedException.h" +#import "OFAlreadyOpenException.h" #import "OFBindUNIXSocketFailedException.h" #import "OFConnectUNIXSocketFailedException.h" @implementation OFUNIXStreamSocket @dynamic delegate; @@ -37,11 +37,11 @@ #if SOCK_CLOEXEC == 0 && defined(HAVE_FCNTL) && defined(FD_CLOEXEC) int flags; #endif if (_socket != OFInvalidSocketHandle) - @throw [OFAlreadyConnectedException exceptionWithSocket: self]; + @throw [OFAlreadyOpenException exceptionWithObject: self]; address = OFSocketAddressMakeUNIX(path); if ((_socket = socket(address.sockaddr.un.sun_family, SOCK_STREAM | SOCK_CLOEXEC, 0)) == OFInvalidSocketHandle) @@ -77,11 +77,11 @@ #if SOCK_CLOEXEC == 0 && defined(HAVE_FCNTL) && defined(FD_CLOEXEC) int flags; #endif if (_socket != OFInvalidSocketHandle) - @throw [OFAlreadyConnectedException exceptionWithSocket: self]; + @throw [OFAlreadyOpenException exceptionWithObject: self]; address = OFSocketAddressMakeUNIX(path); if ((_socket = socket(address.sockaddr.un.sun_family, SOCK_STREAM | SOCK_CLOEXEC, 0)) == OFInvalidSocketHandle) DELETED src/OFURI+Private.h Index: src/OFURI+Private.h ================================================================== --- src/OFURI+Private.h +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (c) 2008-2022 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#import "OFURI.h" - -OF_ASSUME_NONNULL_BEGIN - -@interface OFURI () -- (instancetype)of_init OF_METHOD_FAMILY(init); -@end - -OF_ASSUME_NONNULL_END DELETED src/OFURI.h Index: src/OFURI.h ================================================================== --- src/OFURI.h +++ /dev/null @@ -1,387 +0,0 @@ -/* - * Copyright (c) 2008-2022 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#import "OFObject.h" -#import "OFCharacterSet.h" -#import "OFSerialization.h" - -OF_ASSUME_NONNULL_BEGIN - -@class OFArray OF_GENERIC(ObjectType); -@class OFDictionary OF_GENERIC(KeyType, ObjectType); -@class OFNumber; -@class OFPair OF_GENERIC(FirstType, SecondType); -@class OFString; - -/** - * @class OFURI OFURI.h ObjFW/OFURI.h - * - * @brief A class for parsing URIs as per RFC 3986 and accessing parts of it. - */ -@interface OFURI: OFObject -{ - OFString *_scheme; - OFString *_Nullable _percentEncodedHost; - OFNumber *_Nullable _port; - OFString *_Nullable _percentEncodedUser; - OFString *_Nullable _percentEncodedPassword; - OFString *_percentEncodedPath; - OFString *_Nullable _percentEncodedQuery; - OFString *_Nullable _percentEncodedFragment; - OF_RESERVE_IVARS(OFURI, 4) -} - -/** - * @brief The scheme part of the URI. - */ -@property (readonly, copy, nonatomic) OFString *scheme; - -/** - * @brief The host part of the URI. - */ -@property OF_NULLABLE_PROPERTY (readonly, copy, nonatomic) OFString *host; - -/** - * @brief The host part of the URI in percent-encoded form. - */ -@property OF_NULLABLE_PROPERTY (readonly, copy, nonatomic) - OFString *percentEncodedHost; - -/** - * @brief The port part of the URI. - */ -@property OF_NULLABLE_PROPERTY (readonly, copy, nonatomic) OFNumber *port; - -/** - * @brief The user part of the URI. - */ -@property OF_NULLABLE_PROPERTY (readonly, copy, nonatomic) OFString *user; - -/** - * @brief The user part of the URI in percent-encoded form. - */ -@property OF_NULLABLE_PROPERTY (readonly, copy, nonatomic) - OFString *percentEncodedUser; - -/** - * @brief The password part of the URI. - */ -@property OF_NULLABLE_PROPERTY (readonly, copy, nonatomic) OFString *password; - -/** - * @brief The password part of the URI in percent-encoded form. - */ -@property OF_NULLABLE_PROPERTY (readonly, copy, nonatomic) - OFString *percentEncodedPassword; - -/** - * @brief The path part of the URI. - */ -@property (readonly, copy, nonatomic) OFString *path; - -/** - * @brief The path part of the URI in percent-encoded form. - */ -@property (readonly, copy, nonatomic) OFString *percentEncodedPath; - -/** - * @brief The path of the URI split into components. - * - * The first component must always be `/` to designate the root. - */ -@property (readonly, copy, nonatomic) - OFArray OF_GENERIC(OFString *) *pathComponents; - -/** - * @brief The last path component of the URI. - * - * Returns the empty string if the path is the root. - */ -@property (readonly, copy, nonatomic) OFString *lastPathComponent; - -/** - * @brief The query part of the URI. - */ -@property OF_NULLABLE_PROPERTY (readonly, copy, nonatomic) OFString *query; - -/** - * @brief The query part of the URI in percent-encoded form. - */ -@property OF_NULLABLE_PROPERTY (readonly, copy, nonatomic) - OFString *percentEncodedQuery; - -/** - * @brief The query part of the URI as an array. - * - * For example, a query like `key1=value1&key2=value2` would correspond to the - * following array: - * - * @[ - * [OFPair pairWithFirstObject: @"key1" secondObject: @"value1"], - * [OFPair pairWithFirstObject: @"key2" secondObject: @"value2"], - * ] - * - * @throw OFInvalidFormatException The query is not in the correct format - */ -@property OF_NULLABLE_PROPERTY (readonly, copy, nonatomic) - OFArray OF_GENERIC(OFPair OF_GENERIC(OFString *, OFString *) *) *queryItems; - -/** - * @brief The fragment part of the URI. - */ -@property OF_NULLABLE_PROPERTY (readonly, copy, nonatomic) OFString *fragment; - -/** - * @brief The fragment part of the URI in URI-encoded form. - */ -@property OF_NULLABLE_PROPERTY (readonly, copy, nonatomic) - OFString *percentEncodedFragment; - -/** - * @brief The URI as a string. - */ -@property (readonly, nonatomic) OFString *string; - -/** - * @brief The URI with relative subpaths resolved. - */ -@property (readonly, nonatomic) OFURI *URIByStandardizingPath; - -#ifdef OF_HAVE_FILES -/** - * @brief The local file system representation for a file URI. - * - * @note This only exists for URIs with the file scheme and throws an exception - * otherwise. - */ -@property OF_NULLABLE_PROPERTY (readonly, nonatomic) - OFString *fileSystemRepresentation; -#endif - -/** - * @brief Creates a new URI with the specified string. - * - * @param string A string describing a URI - * @return A new, autoreleased OFURI - * @throw OFInvalidFormatException The specified string is not a valid URI - * string - */ -+ (instancetype)URIWithString: (OFString *)string; - -/** - * @brief Creates a new URI with the specified string relative to the - * specified URI. - * - * @param string A string describing a relative or absolute URI - * @param URI An URI to which the string is relative - * @return A new, autoreleased OFURI - * @throw OFInvalidFormatException The specified string is not a valid URI - * string - */ -+ (instancetype)URIWithString: (OFString *)string relativeToURI: (OFURI *)URI; - -#ifdef OF_HAVE_FILES -/** - * @brief Creates a new URI with the specified local file path. - * - * If a directory exists at the specified path, a slash is appended if there is - * no slash yet. - * - * @param path The local file path - * @return A new, autoreleased OFURI - * @throw OFInvalidFormatException The specified path is not a valid path - */ -+ (instancetype)fileURIWithPath: (OFString *)path; - -/** - * @brief Creates a new URI with the specified local file path. - * - * @param path The local file path - * @param isDirectory Whether the path is a directory, in which case a slash is - * appened if there is no slash yet - * @return An initialized OFURI - */ -+ (instancetype)fileURIWithPath: (OFString *)path - isDirectory: (bool)isDirectory; -#endif - -/** - * @brief Initializes an already allocated OFURI with the specified string. - * - * @param string A string describing a URI - * @return An initialized OFURI - * @throw OFInvalidFormatException The specified string is not a valid URI - * string - */ -- (instancetype)initWithString: (OFString *)string; - -/** - * @brief Initializes an already allocated OFURI with the specified string and - * relative URI. - * - * @param string A string describing a relative or absolute URI - * @param URI A URI to which the string is relative - * @return An initialized OFURI - * @throw OFInvalidFormatException The specified string is not a valid URI - * string - */ -- (instancetype)initWithString: (OFString *)string relativeToURI: (OFURI *)URI; - -#ifdef OF_HAVE_FILES -/** - * @brief Initializes an already allocated OFURI with the specified local file - * path. - * - * If a directory exists at the specified path, a slash is appended if there is - * no slash yet. - * - * @param path The local file path - * @return An initialized OFURI - * @throw OFInvalidFormatException The specified path is not a valid path - */ -- (instancetype)initFileURIWithPath: (OFString *)path; - -/** - * @brief Initializes an already allocated OFURI with the specified local file - * path. - * - * @param path The local file path - * @param isDirectory Whether the path is a directory, in which case a slash is - * appened if there is no slash yet - * @return An initialized OFURI - */ -- (instancetype)initFileURIWithPath: (OFString *)path - isDirectory: (bool)isDirectory; -#endif - -- (instancetype)init OF_UNAVAILABLE; - -/** - * @brief Returns a new URI with the specified path component appended. - * - * If the URI is a file URI, the file system is queried whether the appended - * component is a directory. - * - * @param component The path component to append. If it starts with the slash, - * the component is not appended, but replaces the path - * instead. - * @return A new URI with the specified path component appended - */ -- (OFURI *)URIByAppendingPathComponent: (OFString *)component; - -/** - * @brief Returns a new URI with the specified path component appended. - * - * @param component The path component to append. If it starts with the slash, - * the component is not appended, but replaces the path - * instead. - * @param isDirectory Whether the appended component is a directory, meaning - * that the URI path should have a trailing slash - * @return A new URI with the specified path component appended - */ -- (OFURI *)URIByAppendingPathComponent: (OFString *)component - isDirectory: (bool)isDirectory; -@end - -@interface OFCharacterSet (URICharacterSets) -#ifdef OF_HAVE_CLASS_PROPERTIES -@property (class, readonly, nonatomic) - OFCharacterSet *URISchemeAllowedCharacterSet; -@property (class, readonly, nonatomic) - OFCharacterSet *URIHostAllowedCharacterSet; -@property (class, readonly, nonatomic) - OFCharacterSet *URIUserAllowedCharacterSet; -@property (class, readonly, nonatomic) - OFCharacterSet *URIPasswordAllowedCharacterSet; -@property (class, readonly, nonatomic) - OFCharacterSet *URIPathAllowedCharacterSet; -@property (class, readonly, nonatomic) - OFCharacterSet *URIQueryAllowedCharacterSet; -@property (class, readonly, nonatomic) - OFCharacterSet *URIQueryKeyValueAllowedCharacterSet; -@property (class, readonly, nonatomic) - OFCharacterSet *URIFragmentAllowedCharacterSet; -#endif - -/** - * @brief Returns the characters allowed in the scheme part of a URI. - * - * @return The characters allowed in the scheme part of a URI. - */ -+ (OFCharacterSet *)URISchemeAllowedCharacterSet; - -/** - * @brief Returns the characters allowed in the host part of a URI. - * - * @return The characters allowed in the host part of a URI. - */ -+ (OFCharacterSet *)URIHostAllowedCharacterSet; - -/** - * @brief Returns the characters allowed in the user part of a URI. - * - * @return The characters allowed in the user part of a URI. - */ -+ (OFCharacterSet *)URIUserAllowedCharacterSet; - -/** - * @brief Returns the characters allowed in the password part of a URI. - * - * @return The characters allowed in the password part of a URI. - */ -+ (OFCharacterSet *)URIPasswordAllowedCharacterSet; - -/** - * @brief Returns the characters allowed in the path part of a URI. - * - * @return The characters allowed in the path part of a URI. - */ -+ (OFCharacterSet *)URIPathAllowedCharacterSet; - -/** - * @brief Returns the characters allowed in the query part of a URI. - * - * @return The characters allowed in the query part of a URI. - */ -+ (OFCharacterSet *)URIQueryAllowedCharacterSet; - -/** - * @brief Returns the characters allowed in a key/value in the query part of a - * URI. - * - * @return The characters allowed in a key/value in the query part of a URI. - */ -+ (OFCharacterSet *)URIQueryKeyValueAllowedCharacterSet; - -/** - * @brief Returns the characters allowed in the fragment part of a URI. - * - * @return The characters allowed in the fragment part of a URI. - */ -+ (OFCharacterSet *)URIFragmentAllowedCharacterSet; -@end - -#ifdef __cplusplus -extern "C" { -#endif -extern bool OFURIIsIPv6Host(OFString *host); -extern void OFURIVerifyIsEscaped(OFString *, OFCharacterSet *, bool); -#ifdef __cplusplus -} -#endif - -OF_ASSUME_NONNULL_END - -#import "OFMutableURI.h" DELETED src/OFURI.m Index: src/OFURI.m ================================================================== --- src/OFURI.m +++ /dev/null @@ -1,1277 +0,0 @@ -/* - * Copyright (c) 2008-2022 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 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 - -#import "OFURI.h" -#import "OFArray.h" -#import "OFDictionary.h" -#ifdef OF_HAVE_FILES -# import "OFFileManager.h" -# import "OFFileURIHandler.h" -#endif -#import "OFNumber.h" -#import "OFOnce.h" -#import "OFPair.h" -#import "OFString.h" -#import "OFXMLElement.h" - -#import "OFInvalidArgumentException.h" -#import "OFInvalidFormatException.h" -#import "OFOutOfMemoryException.h" - -@interface OFURIAllowedCharacterSetBase: OFCharacterSet -@end - -@interface OFURIAllowedCharacterSet: OFURIAllowedCharacterSetBase -@end - -@interface OFURISchemeAllowedCharacterSet: OFURIAllowedCharacterSetBase -@end - -@interface OFURIPathAllowedCharacterSet: OFURIAllowedCharacterSetBase -@end - -@interface OFURIQueryOrFragmentAllowedCharacterSet: OFURIAllowedCharacterSetBase -@end - -@interface OFURIQueryKeyValueAllowedCharacterSet: OFURIAllowedCharacterSetBase -@end - -OF_DIRECT_MEMBERS -@interface OFInvertedCharacterSetWithoutPercent: OFCharacterSet -{ - OFCharacterSet *_characterSet; - bool (*_characterIsMember)(id, SEL, OFUnichar); -} - -- (instancetype)initWithCharacterSet: (OFCharacterSet *)characterSet; -@end - -static OFCharacterSet *URIAllowedCharacterSet = nil; -static OFCharacterSet *URISchemeAllowedCharacterSet = nil; -static OFCharacterSet *URIPathAllowedCharacterSet = nil; -static OFCharacterSet *URIQueryOrFragmentAllowedCharacterSet = nil; -static OFCharacterSet *URIQueryKeyValueAllowedCharacterSet = nil; - -static OFOnceControl URIAllowedCharacterSetOnce = OFOnceControlInitValue; -static OFOnceControl URIQueryOrFragmentAllowedCharacterSetOnce = - OFOnceControlInitValue; - -static void -initURIAllowedCharacterSet(void) -{ - URIAllowedCharacterSet = [[OFURIAllowedCharacterSet alloc] init]; -} - -static void -initURISchemeAllowedCharacterSet(void) -{ - URISchemeAllowedCharacterSet = - [[OFURISchemeAllowedCharacterSet alloc] init]; -} - -static void -initURIPathAllowedCharacterSet(void) -{ - URIPathAllowedCharacterSet = - [[OFURIPathAllowedCharacterSet alloc] init]; -} - -static void -initURIQueryOrFragmentAllowedCharacterSet(void) -{ - URIQueryOrFragmentAllowedCharacterSet = - [[OFURIQueryOrFragmentAllowedCharacterSet alloc] init]; -} - -static void -initURIQueryKeyValueAllowedCharacterSet(void) -{ - URIQueryKeyValueAllowedCharacterSet = - [[OFURIQueryKeyValueAllowedCharacterSet alloc] init]; -} - -bool -OFURIIsIPv6Host(OFString *host) -{ - const char *UTF8String = host.UTF8String; - bool hasColon = false; - - while (*UTF8String != '\0') { - if (!OFASCIIIsDigit(*UTF8String) && *UTF8String != ':' && - (*UTF8String < 'a' || *UTF8String > 'f') && - (*UTF8String < 'A' || *UTF8String > 'F')) - return false; - - if (*UTF8String == ':') - hasColon = true; - - UTF8String++; - } - - return hasColon; -} - -@implementation OFURIAllowedCharacterSetBase -- (instancetype)autorelease -{ - return self; -} - -- (instancetype)retain -{ - return self; -} - -- (void)release -{ -} - -- (unsigned int)retainCount -{ - return OFMaxRetainCount; -} -@end - -@implementation OFURIAllowedCharacterSet -- (bool)characterIsMember: (OFUnichar)character -{ - if (character < CHAR_MAX && OFASCIIIsAlnum(character)) - return true; - - switch (character) { - case '-': - case '.': - case '_': - case '~': - case '!': - case '$': - case '&': - case '\'': - case '(': - case ')': - case '*': - case '+': - case ',': - case ';': - case '=': - return true; - default: - return false; - } -} -@end - -@implementation OFURISchemeAllowedCharacterSet -- (bool)characterIsMember: (OFUnichar)character -{ - if (character < CHAR_MAX && OFASCIIIsAlnum(character)) - return true; - - switch (character) { - case '+': - case '-': - case '.': - return true; - default: - return false; - } -} -@end - -@implementation OFURIPathAllowedCharacterSet -- (bool)characterIsMember: (OFUnichar)character -{ - if (character < CHAR_MAX && OFASCIIIsAlnum(character)) - return true; - - switch (character) { - case '-': - case '.': - case '_': - case '~': - case '!': - case '$': - case '&': - case '\'': - case '(': - case ')': - case '*': - case '+': - case ',': - case ';': - case '=': - case ':': - case '@': - case '/': - return true; - default: - return false; - } -} -@end - -@implementation OFURIQueryOrFragmentAllowedCharacterSet -- (bool)characterIsMember: (OFUnichar)character -{ - if (character < CHAR_MAX && OFASCIIIsAlnum(character)) - return true; - - switch (character) { - case '-': - case '.': - case '_': - case '~': - case '!': - case '$': - case '&': - case '\'': - case '(': - case ')': - case '*': - case '+': - case ',': - case ';': - case '=': - case ':': - case '@': - case '/': - case '?': - return true; - default: - return false; - } -} -@end - -@implementation OFURIQueryKeyValueAllowedCharacterSet -- (bool)characterIsMember: (OFUnichar)character -{ - if (character < CHAR_MAX && OFASCIIIsAlnum(character)) - return true; - - switch (character) { - case '-': - case '.': - case '_': - case '~': - case '!': - case '$': - case '\'': - case '(': - case ')': - case '*': - case '+': - case ',': - case ';': - case ':': - case '@': - case '/': - case '?': - return true; - default: - return false; - } -} -@end - -@implementation OFInvertedCharacterSetWithoutPercent -- (instancetype)initWithCharacterSet: (OFCharacterSet *)characterSet -{ - self = [super init]; - - @try { - _characterSet = [characterSet retain]; - _characterIsMember = (bool (*)(id, SEL, OFUnichar)) - [_characterSet methodForSelector: - @selector(characterIsMember:)]; - } @catch (id e) { - [self release]; - @throw e; - } - - return self; -} - -- (void)dealloc -{ - [_characterSet release]; - - [super dealloc]; -} - -- (bool)characterIsMember: (OFUnichar)character -{ - return (character != '%' && !_characterIsMember(_characterSet, - @selector(characterIsMember:), character)); -} -@end - -void -OFURIVerifyIsEscaped(OFString *string, OFCharacterSet *characterSet, - bool allowPercent) -{ - void *pool = objc_autoreleasePoolPush(); - - if (allowPercent) - characterSet = [[[OFInvertedCharacterSetWithoutPercent alloc] - initWithCharacterSet: characterSet] autorelease]; - else - characterSet = characterSet.invertedSet; - - if ([string indexOfCharacterFromSet: characterSet] != OFNotFound) - @throw [OFInvalidFormatException exception]; - - objc_autoreleasePoolPop(pool); -} - -@implementation OFCharacterSet (URICharacterSets) -+ (OFCharacterSet *)URISchemeAllowedCharacterSet -{ - static OFOnceControl onceControl = OFOnceControlInitValue; - OFOnce(&onceControl, initURISchemeAllowedCharacterSet); - - return URISchemeAllowedCharacterSet; -} - -+ (OFCharacterSet *)URIHostAllowedCharacterSet -{ - OFOnce(&URIAllowedCharacterSetOnce, initURIAllowedCharacterSet); - - return URIAllowedCharacterSet; -} - -+ (OFCharacterSet *)URIUserAllowedCharacterSet -{ - OFOnce(&URIAllowedCharacterSetOnce, initURIAllowedCharacterSet); - - return URIAllowedCharacterSet; -} - -+ (OFCharacterSet *)URIPasswordAllowedCharacterSet -{ - OFOnce(&URIAllowedCharacterSetOnce, initURIAllowedCharacterSet); - - return URIAllowedCharacterSet; -} - -+ (OFCharacterSet *)URIPathAllowedCharacterSet -{ - static OFOnceControl onceControl = OFOnceControlInitValue; - OFOnce(&onceControl, initURIPathAllowedCharacterSet); - - return URIPathAllowedCharacterSet; -} - -+ (OFCharacterSet *)URIQueryAllowedCharacterSet -{ - OFOnce(&URIQueryOrFragmentAllowedCharacterSetOnce, - initURIQueryOrFragmentAllowedCharacterSet); - - return URIQueryOrFragmentAllowedCharacterSet; -} - -+ (OFCharacterSet *)URIQueryKeyValueAllowedCharacterSet -{ - static OFOnceControl onceControl = OFOnceControlInitValue; - OFOnce(&onceControl, initURIQueryKeyValueAllowedCharacterSet); - - return URIQueryKeyValueAllowedCharacterSet; -} - -+ (OFCharacterSet *)URIFragmentAllowedCharacterSet -{ - OFOnce(&URIQueryOrFragmentAllowedCharacterSetOnce, - initURIQueryOrFragmentAllowedCharacterSet); - - return URIQueryOrFragmentAllowedCharacterSet; -} -@end - -@implementation OFURI -+ (instancetype)URI -{ - return [[[self alloc] init] autorelease]; -} - -+ (instancetype)URIWithString: (OFString *)string -{ - return [[[self alloc] initWithString: string] autorelease]; -} - -+ (instancetype)URIWithString: (OFString *)string - relativeToURI: (OFURI *)URI -{ - return [[[self alloc] initWithString: string - relativeToURI: URI] autorelease]; -} - -#ifdef OF_HAVE_FILES -+ (instancetype)fileURIWithPath: (OFString *)path -{ - return [[[self alloc] initFileURIWithPath: path] autorelease]; -} - -+ (instancetype)fileURIWithPath: (OFString *)path - isDirectory: (bool)isDirectory -{ - return [[[self alloc] initFileURIWithPath: path - isDirectory: isDirectory] autorelease]; -} -#endif - -static void -parseUserInfo(OFURI *self, const char *UTF8String, size_t length) -{ - const char *colon; - - if ((colon = memchr(UTF8String, ':', length)) != NULL) { - self->_percentEncodedUser = [[OFString alloc] - initWithUTF8String: UTF8String - length: colon - UTF8String]; - self->_percentEncodedPassword = [[OFString alloc] - initWithUTF8String: colon + 1 - length: length - (colon - UTF8String) - 1]; - - OFURIVerifyIsEscaped(self->_percentEncodedPassword, - [OFCharacterSet URIPasswordAllowedCharacterSet], true); - } else - self->_percentEncodedUser = [[OFString alloc] - initWithUTF8String: UTF8String - length: length]; - - OFURIVerifyIsEscaped(self->_percentEncodedUser, - [OFCharacterSet URIUserAllowedCharacterSet], true); -} - -static void -parseHostPort(OFURI *self, const char *UTF8String, size_t length) -{ - OFString *portString; - - if (*UTF8String == '[') { - const char *end = memchr(UTF8String, ']', length); - - if (end == NULL) - @throw [OFInvalidFormatException exception]; - - for (const char *iter = UTF8String + 1; iter < end; iter++) - if (!OFASCIIIsDigit(*iter) && *iter != ':' && - (*iter < 'a' || *iter > 'f') && - (*iter < 'A' || *iter > 'F')) - @throw [OFInvalidFormatException exception]; - - self->_percentEncodedHost = [[OFString alloc] - initWithUTF8String: UTF8String - length: end - UTF8String + 1]; - - length -= (end - UTF8String) + 1; - UTF8String = end + 1; - } else { - const char *colon = memchr(UTF8String, ':', length); - - if (colon != NULL) { - self->_percentEncodedHost = [[OFString alloc] - initWithUTF8String: UTF8String - length: colon - UTF8String]; - - length -= colon - UTF8String; - UTF8String = colon; - } else { - self->_percentEncodedHost = [[OFString alloc] - initWithUTF8String: UTF8String - length: length]; - - UTF8String += length; - length = 0; - } - - OFURIVerifyIsEscaped(self->_percentEncodedHost, - [OFCharacterSet URIHostAllowedCharacterSet], true); - } - - if (length == 0) - return; - - if (length <= 1 || *UTF8String != ':') - @throw [OFInvalidFormatException exception]; - - UTF8String++; - length--; - - for (size_t i = 0; i < length; i++) - if (!OFASCIIIsDigit(UTF8String[i])) - @throw [OFInvalidFormatException exception]; - - portString = [OFString stringWithUTF8String: UTF8String length: length]; - - if (portString.unsignedLongLongValue > 65535) - @throw [OFInvalidFormatException exception]; - - self->_port = [[OFNumber alloc] initWithUnsignedShort: - (unsigned short)portString.unsignedLongLongValue]; -} - -static size_t -parseAuthority(OFURI *self, const char *UTF8String, size_t length) -{ - size_t ret; - const char *slash, *at; - - if ((slash = memchr(UTF8String, '/', length)) != NULL) - length = slash - UTF8String; - - ret = length; - - if ((at = memchr(UTF8String, '@', length)) != NULL) { - parseUserInfo(self, UTF8String, at - UTF8String); - - length -= at - UTF8String + 1; - UTF8String = at + 1; - } - - parseHostPort(self, UTF8String, length); - - return ret; -} - -static void -parsePathQueryFragment(const char *UTF8String, size_t length, - OFString **pathString, OFString **queryString, OFString **fragmentString) -{ - const char *fragment, *query; - - if ((fragment = memchr(UTF8String, '#', length)) != NULL) { - *fragmentString = [OFString - stringWithUTF8String: fragment + 1 - length: length - (fragment - UTF8String) - 1]; - - OFURIVerifyIsEscaped(*fragmentString, - [OFCharacterSet URIQueryAllowedCharacterSet], true); - - length = fragment - UTF8String; - } - - if ((query = memchr(UTF8String, '?', length)) != NULL) { - *queryString = [OFString - stringWithUTF8String: query + 1 - length: length - (query - UTF8String) - 1]; - - OFURIVerifyIsEscaped(*queryString, - [OFCharacterSet URIFragmentAllowedCharacterSet], true); - - length = query - UTF8String; - } - - *pathString = [OFString stringWithUTF8String: UTF8String - length: length]; - - OFURIVerifyIsEscaped(*pathString, - [OFCharacterSet URIQueryAllowedCharacterSet], true); -} - -- (instancetype)initWithString: (OFString *)string -{ - self = [super init]; - - @try { - void *pool = objc_autoreleasePoolPush(); - const char *UTF8String = string.UTF8String; - size_t length = string.UTF8StringLength; - const char *colon; - OFString *path, *query = nil, *fragment = nil; - - if ((colon = strchr(UTF8String, ':')) == NULL || - colon - UTF8String < 1 || !OFASCIIIsAlpha(UTF8String[0])) - @throw [OFInvalidFormatException exception]; - - _scheme = [[[OFString stringWithUTF8String: UTF8String - length: colon - UTF8String] - lowercaseString] copy]; - - OFURIVerifyIsEscaped(_scheme, - [OFCharacterSet URISchemeAllowedCharacterSet], false); - - length -= colon - UTF8String + 1; - UTF8String = colon + 1; - - if (length >= 2 && UTF8String[0] == '/' && - UTF8String[1] == '/') { - size_t authorityLength; - - UTF8String += 2; - length -= 2; - - authorityLength = parseAuthority(self, - UTF8String, length); - - UTF8String += authorityLength; - length -= authorityLength; - - if (length > 0) - OFEnsure(UTF8String[0] == '/'); - } - - parsePathQueryFragment(UTF8String, length, - &path, &query, &fragment); - _percentEncodedPath = [path copy]; - _percentEncodedQuery = [query copy]; - _percentEncodedFragment = [fragment copy]; - - objc_autoreleasePoolPop(pool); - } @catch (id e) { - [self release]; - @throw e; - } - - return self; -} - -static bool -isAbsolute(OFString *string) -{ - void *pool = objc_autoreleasePoolPush(); - - @try { - const char *UTF8String = string.UTF8String; - size_t length = string.UTF8StringLength; - - if (length < 1) - return false; - - if (!OFASCIIIsAlpha(UTF8String[0])) - return false; - - for (size_t i = 1; i < length; i++) { - if (UTF8String[i] == ':') - return true; - - if (!OFASCIIIsAlnum(UTF8String[i]) && - UTF8String[i] != '+' && UTF8String[i] != '-' && - UTF8String[i] != '.') - return false; - } - } @finally { - objc_autoreleasePoolPop(pool); - } - - return false; -} - -static OFString * -merge(OFString *base, OFString *path) -{ - OFMutableArray *components; - - if (base.length == 0) - base = @"/"; - - components = [[[base componentsSeparatedByString: @"/"] - mutableCopy] autorelease]; - - if (components.count == 1) - [components addObject: path]; - else - [components replaceObjectAtIndex: components.count - 1 - withObject: path]; - - return [components componentsJoinedByString: @"/"]; -} - -- (instancetype)initWithString: (OFString *)string relativeToURI: (OFURI *)URI -{ - bool absolute; - - @try { - absolute = isAbsolute(string); - } @catch (id e) { - [self release]; - @throw e; - } - - if (absolute) - return [self initWithString: string]; - - self = [super init]; - - @try { - void *pool = objc_autoreleasePoolPush(); - const char *UTF8String = string.UTF8String; - size_t length = string.UTF8StringLength; - bool hasAuthority = false; - OFString *path, *query = nil, *fragment = nil; - - _scheme = [URI->_scheme copy]; - - if (length >= 2 && UTF8String[0] == '/' && - UTF8String[1] == '/') { - size_t authorityLength; - - hasAuthority = true; - - UTF8String += 2; - length -= 2; - - authorityLength = parseAuthority(self, - UTF8String, length); - - UTF8String += authorityLength; - length -= authorityLength; - - if (length > 0) - OFEnsure(UTF8String[0] == '/'); - } else { - _percentEncodedHost = [URI->_percentEncodedHost copy]; - _port = [URI->_port copy]; - _percentEncodedUser = [URI->_percentEncodedUser copy]; - _percentEncodedPassword = - [URI->_percentEncodedPassword copy]; - } - - parsePathQueryFragment(UTF8String, length, - &path, &query, &fragment); - _percentEncodedFragment = [fragment copy]; - - if (hasAuthority) { - _percentEncodedPath = [path copy]; - _percentEncodedQuery = [query copy]; - } else { - if (path.length == 0) { - _percentEncodedPath = - [URI->_percentEncodedPath copy]; - _percentEncodedQuery = (query != nil - ? [query copy] - : [URI->_percentEncodedQuery copy]); - } else { - if ([path hasPrefix: @"/"]) - _percentEncodedPath = [path copy]; - else - _percentEncodedPath = [merge( - URI->_percentEncodedPath, path) - copy]; - - _percentEncodedQuery = [query copy]; - } - } - - objc_autoreleasePoolPop(pool); - } @catch (id e) { - [self release]; - @throw e; - } - - return self; -} - -#ifdef OF_HAVE_FILES -- (instancetype)initFileURIWithPath: (OFString *)path -{ - bool isDirectory; - - @try { - void *pool = objc_autoreleasePoolPush(); - isDirectory = [path of_isDirectoryPath]; - objc_autoreleasePoolPop(pool); - } @catch (id e) { - [self release]; - @throw e; - } - - self = [self initFileURIWithPath: path isDirectory: isDirectory]; - - return self; -} - -- (instancetype)initFileURIWithPath: (OFString *)path - isDirectory: (bool)isDirectory -{ - self = [super init]; - - @try { - void *pool = objc_autoreleasePoolPush(); - OFString *percentEncodedHost = nil; - - if (!path.absolutePath) { - OFString *currentDirectoryPath = [OFFileManager - defaultManager].currentDirectoryPath; - - path = [currentDirectoryPath - stringByAppendingPathComponent: path]; - path = path.stringByStandardizingPath; - } - - path = [path of_pathToURIPathWithPercentEncodedHost: - &percentEncodedHost]; - _percentEncodedHost = [percentEncodedHost copy]; - - if (isDirectory && ![path hasSuffix: @"/"]) - path = [path stringByAppendingString: @"/"]; - - _scheme = @"file"; - _percentEncodedPath = [[path - stringByAddingPercentEncodingWithAllowedCharacters: - [OFCharacterSet URIPathAllowedCharacterSet]] copy]; - - objc_autoreleasePoolPop(pool); - } @catch (id e) { - [self release]; - @throw e; - } - - return self; -} -#endif - -- (instancetype)init -{ - OF_INVALID_INIT_METHOD -} - -- (instancetype)of_init -{ - return [super init]; -} - -- (instancetype)initWithSerialization: (OFXMLElement *)element -{ - void *pool = objc_autoreleasePoolPush(); - OFString *stringValue; - - @try { - if (![element.name isEqual: self.className] || - ![element.namespace isEqual: OFSerializationNS]) - @throw [OFInvalidArgumentException exception]; - - stringValue = element.stringValue; - } @catch (id e) { - [self release]; - @throw e; - } - - self = [self initWithString: stringValue]; - - objc_autoreleasePoolPop(pool); - - return self; -} - -- (void)dealloc -{ - [_scheme release]; - [_percentEncodedHost release]; - [_port release]; - [_percentEncodedUser release]; - [_percentEncodedPassword release]; - [_percentEncodedPath release]; - [_percentEncodedQuery release]; - [_percentEncodedFragment release]; - - [super dealloc]; -} - -- (bool)isEqual: (id)object -{ - OFURI *URI; - - if (object == self) - return true; - - if (![object isKindOfClass: [OFURI class]]) - return false; - - URI = object; - - if (![URI->_scheme isEqual: _scheme]) - return false; - if (URI->_percentEncodedHost != _percentEncodedHost && - ![URI->_percentEncodedHost isEqual: _percentEncodedHost]) - return false; - if (URI->_port != _port && ![URI->_port isEqual: _port]) - return false; - if (URI->_percentEncodedUser != _percentEncodedUser && - ![URI->_percentEncodedUser isEqual: _percentEncodedUser]) - return false; - if (URI->_percentEncodedPassword != _percentEncodedPassword && - ![URI->_percentEncodedPassword isEqual: _percentEncodedPassword]) - return false; - if (![URI->_percentEncodedPath isEqual: _percentEncodedPath]) - return false; - if (URI->_percentEncodedQuery != _percentEncodedQuery && - ![URI->_percentEncodedQuery isEqual: _percentEncodedQuery]) - return false; - if (URI->_percentEncodedFragment != _percentEncodedFragment && - ![URI->_percentEncodedFragment isEqual: _percentEncodedFragment]) - return false; - - return true; -} - -- (unsigned long)hash -{ - unsigned long hash; - - OFHashInit(&hash); - - OFHashAddHash(&hash, _scheme.hash); - OFHashAddHash(&hash, _percentEncodedHost.hash); - OFHashAddHash(&hash, _port.hash); - OFHashAddHash(&hash, _percentEncodedUser.hash); - OFHashAddHash(&hash, _percentEncodedPassword.hash); - OFHashAddHash(&hash, _percentEncodedPath.hash); - OFHashAddHash(&hash, _percentEncodedQuery.hash); - OFHashAddHash(&hash, _percentEncodedFragment.hash); - - OFHashFinalize(&hash); - - return hash; -} - -- (OFString *)scheme -{ - return _scheme; -} - -- (OFString *)host -{ - if ([_percentEncodedHost hasPrefix: @"["] && - [_percentEncodedHost hasSuffix: @"]"]) { - OFString *host = [_percentEncodedHost substringWithRange: - OFMakeRange(1, _percentEncodedHost.length - 2)]; - - if (!OFURIIsIPv6Host(host)) - @throw [OFInvalidArgumentException exception]; - - return host; - } - - return _percentEncodedHost.stringByRemovingPercentEncoding; -} - -- (OFString *)percentEncodedHost -{ - return _percentEncodedHost; -} - -- (OFNumber *)port -{ - return _port; -} - -- (OFString *)user -{ - return _percentEncodedUser.stringByRemovingPercentEncoding; -} - -- (OFString *)percentEncodedUser -{ - return _percentEncodedUser; -} - -- (OFString *)password -{ - return _percentEncodedPassword.stringByRemovingPercentEncoding; -} - -- (OFString *)percentEncodedPassword -{ - return _percentEncodedPassword; -} - -- (OFString *)path -{ - return _percentEncodedPath.stringByRemovingPercentEncoding; -} - -- (OFString *)percentEncodedPath -{ - return _percentEncodedPath; -} - -- (OFArray *)pathComponents -{ - void *pool = objc_autoreleasePoolPush(); -#ifdef OF_HAVE_FILES - bool isFile = [_scheme isEqual: @"file"]; -#endif - OFMutableArray *ret; - size_t count; - -#ifdef OF_HAVE_FILES - if (isFile) { - OFString *path = [_percentEncodedPath - of_URIPathToPathWithPercentEncodedHost: nil]; - ret = [[path.pathComponents mutableCopy] autorelease]; - - if (![ret.firstObject isEqual: @"/"]) - [ret insertObject: @"/" atIndex: 0]; - } else -#endif - ret = [[[_percentEncodedPath componentsSeparatedByString: @"/"] - mutableCopy] autorelease]; - - count = ret.count; - - if (count > 0 && [ret.firstObject length] == 0) - [ret replaceObjectAtIndex: 0 withObject: @"/"]; - - for (size_t i = 0; i < count; i++) { - OFString *component = [ret objectAtIndex: i]; - -#ifdef OF_HAVE_FILES - if (isFile) - component = - [component of_pathComponentToURIPathComponent]; -#endif - - component = component.stringByRemovingPercentEncoding; - [ret replaceObjectAtIndex: i withObject: component]; - } - - [ret makeImmutable]; - [ret retain]; - - objc_autoreleasePoolPop(pool); - - return [ret autorelease]; -} - -- (OFString *)lastPathComponent -{ - void *pool = objc_autoreleasePoolPush(); - OFString *path = _percentEncodedPath; - const char *UTF8String, *lastComponent; - size_t length; - OFString *ret; - - if ([path isEqual: @"/"]) { - objc_autoreleasePoolPop(pool); - return @"/"; - } - - if ([path hasSuffix: @"/"]) - path = [path substringToIndex: path.length - 1]; - - UTF8String = lastComponent = path.UTF8String; - length = path.UTF8StringLength; - - for (size_t i = 1; i <= length; i++) { - if (UTF8String[length - i] == '/') { - lastComponent = UTF8String + (length - i) + 1; - break; - } - } - - ret = [OFString - stringWithUTF8String: lastComponent - length: length - (lastComponent - UTF8String)]; - ret = [ret.stringByRemovingPercentEncoding retain]; - - objc_autoreleasePoolPop(pool); - - return [ret autorelease]; -} - -- (OFString *)query -{ - return _percentEncodedQuery.stringByRemovingPercentEncoding; -} - -- (OFString *)percentEncodedQuery -{ - return _percentEncodedQuery; -} - -- (OFArray OF_GENERIC(OFPair OF_GENERIC(OFString *, OFString *) *) *)queryItems -{ - void *pool; - OFArray OF_GENERIC(OFString *) *pairs; - OFMutableArray OF_GENERIC(OFPair OF_GENERIC(OFString *, OFString *) *) - *ret; - - if (_percentEncodedQuery == nil) - return nil; - - pool = objc_autoreleasePoolPush(); - pairs = [_percentEncodedQuery componentsSeparatedByString: @"&"]; - ret = [OFMutableArray arrayWithCapacity: pairs.count]; - - for (OFString *pair in pairs) { - OFArray *parts = [pair componentsSeparatedByString: @"="]; - OFString *name, *value; - - if (parts.count != 2) - @throw [OFInvalidFormatException exception]; - - name = [[parts objectAtIndex: 0] - stringByRemovingPercentEncoding]; - value = [[parts objectAtIndex: 1] - stringByRemovingPercentEncoding]; - - [ret addObject: [OFPair pairWithFirstObject: name - secondObject: value]]; - } - - [ret makeImmutable]; - [ret retain]; - - objc_autoreleasePoolPop(pool); - - return [ret autorelease]; -} - -- (OFString *)fragment -{ - return _percentEncodedFragment.stringByRemovingPercentEncoding; -} - -- (OFString *)percentEncodedFragment -{ - return _percentEncodedFragment; -} - -- (id)copy -{ - return [self retain]; -} - -- (id)mutableCopy -{ - OFURI *copy = [[OFMutableURI alloc] initWithScheme: _scheme]; - - @try { - copy->_percentEncodedHost = [_percentEncodedHost copy]; - copy->_port = [_port copy]; - copy->_percentEncodedUser = [_percentEncodedUser copy]; - copy->_percentEncodedPassword = [_percentEncodedPassword copy]; - copy->_percentEncodedPath = [_percentEncodedPath copy]; - copy->_percentEncodedQuery = [_percentEncodedQuery copy]; - copy->_percentEncodedFragment = [_percentEncodedFragment copy]; - } @catch (id e) { - [copy release]; - @throw e; - } - - return copy; -} - -- (OFString *)string -{ - OFMutableString *ret = [OFMutableString string]; - - [ret appendFormat: @"%@:", _scheme]; - - if (_percentEncodedHost != nil || _port != nil || - _percentEncodedUser != nil || _percentEncodedPassword != nil) - [ret appendString: @"//"]; - - if (_percentEncodedUser != nil && _percentEncodedPassword != nil) - [ret appendFormat: @"%@:%@@", - _percentEncodedUser, - _percentEncodedPassword]; - else if (_percentEncodedUser != nil) - [ret appendFormat: @"%@@", _percentEncodedUser]; - - if (_percentEncodedHost != nil) - [ret appendString: _percentEncodedHost]; - if (_port != nil) - [ret appendFormat: @":%@", _port]; - - [ret appendString: _percentEncodedPath]; - - if (_percentEncodedQuery != nil) - [ret appendFormat: @"?%@", _percentEncodedQuery]; - - if (_percentEncodedFragment != nil) - [ret appendFormat: @"#%@", _percentEncodedFragment]; - - [ret makeImmutable]; - - return ret; -} - -#ifdef OF_HAVE_FILES -- (OFString *)fileSystemRepresentation -{ - void *pool = objc_autoreleasePoolPush(); - OFString *path; - - if (![_scheme isEqual: @"file"]) - @throw [OFInvalidArgumentException exception]; - - if (![_percentEncodedPath hasPrefix: @"/"]) - @throw [OFInvalidFormatException exception]; - - path = [self.path - of_URIPathToPathWithPercentEncodedHost: _percentEncodedHost]; - - [path retain]; - - objc_autoreleasePoolPop(pool); - - return [path autorelease]; -} -#endif - -- (OFURI *)URIByAppendingPathComponent: (OFString *)component -{ - OFMutableURI *URI = [[self mutableCopy] autorelease]; - [URI appendPathComponent: component]; - [URI makeImmutable]; - return URI; -} - -- (OFURI *)URIByAppendingPathComponent: (OFString *)component - isDirectory: (bool)isDirectory -{ - OFMutableURI *URI = [[self mutableCopy] autorelease]; - [URI appendPathComponent: component isDirectory: isDirectory]; - [URI makeImmutable]; - return URI; -} - -- (OFURI *)URIByStandardizingPath -{ - OFMutableURI *URI = [[self mutableCopy] autorelease]; - [URI standardizePath]; - [URI makeImmutable]; - return URI; -} - -- (OFString *)description -{ - return [OFString stringWithFormat: @"<%@: %@>", - self.class, self.string]; -} - -- (OFXMLElement *)XMLElementBySerializing -{ - void *pool = objc_autoreleasePoolPush(); - OFXMLElement *element; - - element = [OFXMLElement elementWithName: self.className - namespace: OFSerializationNS - stringValue: self.string]; - - [element retain]; - - objc_autoreleasePoolPop(pool); - - return [element autorelease]; -} -@end DELETED src/OFURIHandler.h Index: src/OFURIHandler.h ================================================================== --- src/OFURIHandler.h +++ /dev/null @@ -1,257 +0,0 @@ -/* - * Copyright (c) 2008-2022 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#import "OFFileManager.h" -#import "OFObject.h" -#import "OFString.h" - -OF_ASSUME_NONNULL_BEGIN - -@class OFArray OF_GENERIC(ObjectType); -@class OFDate; -@class OFStream; -@class OFURI; - -/** - * @class OFURIHandler OFURIHandler.h ObjFW/OFURIHandler.h - * - * @brief A handler for a URI scheme. - */ -@interface OFURIHandler: OFObject -{ - OFString *_scheme; - OF_RESERVE_IVARS(OFURIHandler, 4) -} - -/** - * @brief The scheme this OFURIHandler handles. - */ -@property (readonly, nonatomic) OFString *scheme; - -/** - * @brief Registers the specified class as the handler for the specified scheme. - * - * If the same class is specified for two schemes, one instance of it is - * created per scheme. - * - * @param class_ The class to register as the handler for the specified scheme - * @param scheme The scheme for which to register the handler - * @return Whether the class was successfully registered. If a handler for the - * same scheme is already registered, registration fails. - */ -+ (bool)registerClass: (Class)class_ forScheme: (OFString *)scheme; - -/** - * @brief Returns the handler for the specified URI. - * - * @return The handler for the specified URI. - * @throw OFUnsupportedProtocolException The specified URI is not supported - */ -+ (OFURIHandler *)handlerForURI: (OFURI *)URI; - -/** - * @brief Opens the item at the specified URI. - * - * @param URI The URI of the item which should be opened - * @param mode The mode in which the file should be opened.@n - * Possible modes are: - * @n - * Mode | Description - * ---------------|------------------------------------- - * `r` | Read-only - * `r+` | Read-write - * `w` | Write-only, create or truncate - * `wx` | Write-only, create or fail, exclusive - * `w+` | Read-write, create or truncate - * `w+x` | Read-write, create or fail, exclusive - * `a` | Write-only, create or append - * `a+` | Read-write, create or append - * @n - * The handler is allowed to not implement all modes and is also - * allowed to implement additional, scheme-specific modes. - * @return The opened stream if it was successfully opened - * @throw OFOpenItemFailedException Opening the item failed - * @throw OFUnsupportedProtocolException The specified URI is not supported - */ -+ (OFStream *)openItemAtURI: (OFURI *)URI mode: (OFString *)mode; - -- (instancetype)init OF_UNAVAILABLE; - -/** - * @brief Initializes the handler for the specified scheme. - * - * @param scheme The scheme to initialize for - * @return An initialized URI handler - */ -- (instancetype)initWithScheme: (OFString *)scheme OF_DESIGNATED_INITIALIZER; - -/** - * @brief Opens the item at the specified URI. - * - * @param URI The URI of the item which should be opened - * @param mode The mode in which the file should be opened.@n - * Possible modes are: - * @n - * Mode | Description - * ---------------|------------------------------------- - * `r` | Read-only - * `r+` | Read-write - * `w` | Write-only, create or truncate - * `wx` | Write-only, create or fail, exclusive - * `w+` | Read-write, create or truncate - * `w+x` | Read-write, create or fail, exclusive - * `a` | Write-only, create or append - * `a+` | Read-write, create or append - * @n - * The handler is allowed to not implement all modes and is also - * allowed to implement additional, scheme-specific modes. - * @return The opened stream if it was successfully opened - * @throw OFOpenItemFailedException Opening the item failed - * @throw OFUnsupportedProtocolException The specified URI is not supported by - * the handler - */ -- (OFStream *)openItemAtURI: (OFURI *)URI mode: (OFString *)mode; - -/** - * @brief Returns the attributes for the item at the specified URI. - * - * @param URI The URI to return the attributes for - * @return A dictionary of attributes for the specified URI, with the keys of - * type @ref OFFileAttributeKey - */ -- (OFFileAttributes)attributesOfItemAtURI: (OFURI *)URI; - -/** - * @brief Sets the attributes for the item at the specified URI. - * - * All attributes not part of the dictionary are left unchanged. - * - * @param attributes The attributes to set for the specified URI - * @param URI The URI of the item to set the attributes for - */ -- (void)setAttributes: (OFFileAttributes)attributes ofItemAtURI: (OFURI *)URI; - -/** - * @brief Checks whether a file exists at the specified URI. - * - * @param URI The URI to check - * @return A boolean whether there is a file at the specified URI - */ -- (bool)fileExistsAtURI: (OFURI *)URI; - -/** - * @brief Checks whether a directory exists at the specified URI. - * - * @param URI The URI to check - * @return A boolean whether there is a directory at the specified URI - */ -- (bool)directoryExistsAtURI: (OFURI *)URI; - -/** - * @brief Creates a directory at the specified URI. - * - * @param URI The URI of the directory to create - */ -- (void)createDirectoryAtURI: (OFURI *)URI; - -/** - * @brief Returns an array with the URIs of the items in the specified - * directory. - * - * @note `.` and `..` are not part of the returned array. - * - * @param URI The URI to the directory whose items should be returned - * @return An array with the URIs of the items in the specified directory - */ -- (OFArray OF_GENERIC(OFURI *) *)contentsOfDirectoryAtURI: (OFURI *)URI; - -/** - * @brief Removes the item at the specified URI. - * - * If the item at the specified URI is a directory, it is removed recursively. - * - * @param URI The URI to the item which should be removed - */ -- (void)removeItemAtURI: (OFURI *)URI; - -/** - * @brief Creates a hard link for the specified item. - * - * The destination URI must have a full path, which means it must include the - * name of the item. - * - * This method is not available for all URIs. - * - * @param source The URI to the item for which a link should be created - * @param destination The URI to the item which should link to the source - */ -- (void)linkItemAtURI: (OFURI *)source toURI: (OFURI *)destination; - -/** - * @brief Creates a symbolic link for an item. - * - * The destination URI must have a full path, which means it must include the - * name of the item. - * - * This method is not available for all URIs. - * - * @note On Windows, this requires at least Windows Vista and administrator - * privileges! - * - * @param URI The URI to the item which should symbolically link to the target - * @param target The target of the symbolic link - */ -- (void)createSymbolicLinkAtURI: (OFURI *)URI - withDestinationPath: (OFString *)target; - -/** - * @brief Tries to efficiently copy an item. If a copy would only be possible - * by reading the entire item and then writing it, it returns false. - * - * The destination URI must have a full path, which means it must include the - * name of the item. - * - * If an item already exists, the copy operation fails. This is also the case - * if a directory is copied and an item already exists in the destination - * directory. - * - * @param source The file, directory or symbolic link to copy - * @param destination The destination URI - * @return True if an efficient copy was performed, false if an efficient copy - * was not possible. Note that errors while performing a copy are - * reported via exceptions and not by returning false! - */ -- (bool)copyItemAtURI: (OFURI *)source toURI: (OFURI *)destination; - -/** - * @brief Tries to efficiently move an item. If a move would only be possible - * by copying the source and deleting it, it returns false. - * - * The destination URI must have a full path, which means it must include the - * name of the item. - * - * If the destination is on a different logical device or uses a different - * scheme, an efficient move is not possible and false is returned. - * - * @param source The item to rename - * @param destination The new name for the item - * @return True if an efficient move was performed, false if an efficient move - * was not possible. Note that errors while performing a move are - * reported via exceptions and not by returning false! - */ -- (bool)moveItemAtURI: (OFURI *)source toURI: (OFURI *)destination; -@end - -OF_ASSUME_NONNULL_END DELETED src/OFURIHandler.m Index: src/OFURIHandler.m ================================================================== --- src/OFURIHandler.m +++ /dev/null @@ -1,216 +0,0 @@ -/* - * Copyright (c) 2008-2022 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#include "config.h" - -#import "OFURIHandler.h" -#import "OFDictionary.h" -#import "OFNumber.h" -#import "OFURI.h" - -#ifdef OF_HAVE_THREADS -# import "OFMutex.h" -#endif - -#import "OFArchiveURIHandler.h" -#import "OFEmbeddedURIHandler.h" -#ifdef OF_HAVE_FILES -# import "OFFileURIHandler.h" -#endif -#if defined(OF_HAVE_SOCKETS) && defined(OF_HAVE_THREADS) -# import "OFHTTPURIHandler.h" -#endif - -#import "OFUnsupportedProtocolException.h" - -static OFMutableDictionary OF_GENERIC(OFString *, OFURIHandler *) *handlers; -#ifdef OF_HAVE_THREADS -static OFMutex *mutex; - -static void -releaseMutex(void) -{ - [mutex release]; -} -#endif - -@implementation OFURIHandler -@synthesize scheme = _scheme; - -+ (void)initialize -{ - if (self != [OFURIHandler class]) - return; - - handlers = [[OFMutableDictionary alloc] init]; -#ifdef OF_HAVE_THREADS - mutex = [[OFMutex alloc] init]; - atexit(releaseMutex); -#endif - - [self registerClass: [OFEmbeddedURIHandler class] - forScheme: @"embedded"]; -#ifdef OF_HAVE_FILES - [self registerClass: [OFFileURIHandler class] forScheme: @"file"]; -#endif -#if defined(OF_HAVE_SOCKETS) && defined(OF_HAVE_THREADS) - [self registerClass: [OFHTTPURIHandler class] forScheme: @"http"]; - [self registerClass: [OFHTTPURIHandler class] forScheme: @"https"]; -#endif - [self registerClass: [OFArchiveURIHandler class] forScheme: @"gzip"]; - [self registerClass: [OFArchiveURIHandler class] forScheme: @"lha"]; - [self registerClass: [OFArchiveURIHandler class] forScheme: @"tar"]; - [self registerClass: [OFArchiveURIHandler class] forScheme: @"zip"]; -} - -+ (bool)registerClass: (Class)class forScheme: (OFString *)scheme -{ -#ifdef OF_HAVE_THREADS - [mutex lock]; - @try { -#endif - OFURIHandler *handler; - - if ([handlers objectForKey: scheme] != nil) - return false; - - handler = [[class alloc] initWithScheme: scheme]; - @try { - [handlers setObject: handler forKey: scheme]; - } @finally { - [handler release]; - } -#ifdef OF_HAVE_THREADS - } @finally { - [mutex unlock]; - } -#endif - - return true; -} - -+ (OFURIHandler *)handlerForURI: (OFURI *)URI -{ - OF_KINDOF(OFURIHandler *) handler; - -#ifdef OF_HAVE_THREADS - [mutex lock]; - @try { -#endif - handler = [handlers objectForKey: URI.scheme]; -#ifdef OF_HAVE_THREADS - } @finally { - [mutex unlock]; - } -#endif - - if (handler == nil) - @throw [OFUnsupportedProtocolException exceptionWithURI: URI]; - - return handler; -} - -+ (OFStream *)openItemAtURI: (OFURI *)URI mode: (OFString *)mode -{ - return [[self handlerForURI: URI] openItemAtURI: URI mode: mode]; -} - -- (instancetype)init -{ - OF_INVALID_INIT_METHOD -} - -- (instancetype)initWithScheme: (OFString *)scheme -{ - self = [super init]; - - @try { - _scheme = [scheme copy]; - } @catch (id e) { - [self release]; - @throw e; - } - - return self; -} - -- (void)dealloc -{ - [_scheme release]; - - [super dealloc]; -} - -- (OFStream *)openItemAtURI: (OFURI *)URI mode: (OFString *)mode -{ - OF_UNRECOGNIZED_SELECTOR -} - -- (OFFileAttributes)attributesOfItemAtURI: (OFURI *)URI -{ - OF_UNRECOGNIZED_SELECTOR -} - -- (void)setAttributes: (OFFileAttributes)attributes ofItemAtURI: (OFURI *)URI -{ - OF_UNRECOGNIZED_SELECTOR -} - -- (bool)fileExistsAtURI: (OFURI *)URI -{ - OF_UNRECOGNIZED_SELECTOR -} - -- (bool)directoryExistsAtURI: (OFURI *)URI -{ - OF_UNRECOGNIZED_SELECTOR -} - -- (void)createDirectoryAtURI: (OFURI *)URI -{ - OF_UNRECOGNIZED_SELECTOR -} - -- (OFArray OF_GENERIC(OFURI *) *)contentsOfDirectoryAtURI: (OFURI *)URI -{ - OF_UNRECOGNIZED_SELECTOR -} - -- (void)removeItemAtURI: (OFURI *)URI -{ - OF_UNRECOGNIZED_SELECTOR -} - -- (void)linkItemAtURI: (OFURI *)source toURI: (OFURI *)destination -{ - OF_UNRECOGNIZED_SELECTOR -} - -- (void)createSymbolicLinkAtURI: (OFURI *)destination - withDestinationPath: (OFString *)source -{ - OF_UNRECOGNIZED_SELECTOR -} - -- (bool)copyItemAtURI: (OFURI *)source toURI: (OFURI *)destination -{ - return false; -} - -- (bool)moveItemAtURI: (OFURI *)source toURI: (OFURI *)destination -{ - return false; -} -@end Index: src/OFUTF8String+Private.h ================================================================== --- src/OFUTF8String+Private.h +++ src/OFUTF8String+Private.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFUUID.h ================================================================== --- src/OFUUID.h +++ src/OFUUID.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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 "OFObject.h" -#import "OFSerialization.h" OF_ASSUME_NONNULL_BEGIN @class OFString; @@ -24,11 +23,11 @@ * @class OFUUID OFUUID.h ObjFW/OFUUID.h * * @brief A UUID conforming to RFC 4122. */ OF_SUBCLASSING_RESTRICTED -@interface OFUUID: OFObject +@interface OFUUID: OFObject { unsigned char _bytes[16]; } /** Index: src/OFUUID.m ================================================================== --- src/OFUUID.m +++ src/OFUUID.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,11 +16,10 @@ #include "config.h" #import "OFUUID.h" #import "OFArray.h" #import "OFString.h" -#import "OFXMLElement.h" #import "OFInvalidArgumentException.h" #import "OFInvalidFormatException.h" #import "OFOutOfRangeException.h" @@ -143,33 +142,10 @@ } 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]]) @@ -233,20 +209,6 @@ - (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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,14 +21,10 @@ * @class OFValue OFValue.h ObjFW/OFValue.h * * @brief A class for storing arbitrary values in an object. */ @interface OFValue: OFObject -{ - OF_RESERVE_IVARS(OFValue, 4) -} - /** * @brief The ObjC type encoding of the value. */ @property (readonly, nonatomic) const char *objCType; @@ -66,16 +62,30 @@ * @throw OFOutOfRangeException The value is not OFSize-sized */ @property (readonly, nonatomic) OFSize sizeValue; /** - * @brief The value as a OFRect. + * @brief The value as an OFRect. * * @throw OFOutOfRangeException The value is not OFRect-sized */ @property (readonly, nonatomic) OFRect rectValue; +/** + * @brief The value as an OFVector3D. + * + * @throw OFOutOfRangeException The value is not OFVector3D-sized + */ +@property (readonly, nonatomic) OFVector3D vector3DValue; + +/** + * @brief The value as an OFVector4D. + * + * @throw OFOutOfRangeException The value is not OFVector4D-sized + */ +@property (readonly, nonatomic) OFVector4D vector4DValue; + /** * @brief Creates a new, autorelease OFValue with the specified bytes of the * specified type. * * @param bytes The bytes containing the value @@ -138,20 +148,40 @@ * @param rect The rectangle the OFValue should contain * @return A new, autoreleased OFValue */ + (instancetype)valueWithRect: (OFRect)rect; +/** + * @brief Creates a new, autoreleased OFValue containing the specified + * 3D vector. + * + * @param vector3D The 3D vector the OFValue should contain + * @return A new, autoreleased OFValue + */ ++ (instancetype)valueWithVector3D: (OFVector3D)vector3D; + +/** + * @brief Creates a new, autoreleased OFValue containing the specified + * 4D vector. + * + * @param vector4D The 4D vector the OFValue should contain + * @return A new, autoreleased OFValue + */ ++ (instancetype)valueWithVector4D: (OFVector4D)vector4D; + /** * @brief Initializes an already allocated OFValue with the specified bytes of * the specified type. * * @param bytes The bytes containing the value * @param objCType The ObjC type encoding for the value * @return An initialized OFValue */ - (instancetype)initWithBytes: (const void *)bytes - objCType: (const char *)objCType; + objCType: (const char *)objCType OF_DESIGNATED_INITIALIZER; + +- (instancetype)init OF_UNAVAILABLE; /** * @brief Gets the value. * * @param value The buffer to copy the value into Index: src/OFValue.m ================================================================== --- src/OFValue.m +++ src/OFValue.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,71 +14,134 @@ */ #include "config.h" #import "OFValue.h" -#import "OFBytesValue.h" +#import "OFConcreteValue.h" #import "OFMethodSignature.h" -#import "OFNonretainedObjectValue.h" -#import "OFPointValue.h" -#import "OFPointerValue.h" -#import "OFRangeValue.h" -#import "OFRectValue.h" -#import "OFSizeValue.h" #import "OFString.h" #import "OFOutOfMemoryException.h" + +static struct { + Class isa; +} placeholder; + +@interface OFPlaceholderValue: OFValue +@end + +@implementation OFPlaceholderValue +#ifdef __clang__ +/* We intentionally don't call into super, so silence the warning. */ +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wunknown-pragmas" +# pragma clang diagnostic ignored "-Wobjc-designated-initializers" +#endif +- (instancetype)initWithBytes: (const void *)bytes + objCType: (const char *)objCType +{ + return (id)[[OFConcreteValue alloc] initWithBytes: bytes + objCType: objCType]; +} +#ifdef __clang__ +# pragma clang diagnostic pop +#endif + +OF_SINGLETON_METHODS +@end @implementation OFValue ++ (void)initialize +{ + if (self == [OFValue class]) + object_setClass((id)&placeholder, [OFPlaceholderValue class]); +} + + (instancetype)alloc { if (self == [OFValue class]) - return [OFBytesValue alloc]; + return (id)&placeholder; return [super alloc]; } + (instancetype)valueWithBytes: (const void *)bytes objCType: (const char *)objCType { - return [[[OFBytesValue alloc] initWithBytes: bytes - objCType: objCType] autorelease]; + return [[[OFValue alloc] initWithBytes: bytes + objCType: objCType] autorelease]; } + (instancetype)valueWithPointer: (const void *)pointer { - return [[[OFPointerValue alloc] initWithPointer: pointer] autorelease]; + return [[[OFValue alloc] + initWithBytes: &pointer + objCType: @encode(const void *)] autorelease]; } + (instancetype)valueWithNonretainedObject: (id)object { - return [[[OFNonretainedObjectValue alloc] - initWithNonretainedObject: object] autorelease]; + return [[[OFValue alloc] initWithBytes: &object + objCType: @encode(id)] autorelease]; } + (instancetype)valueWithRange: (OFRange)range { - return [[[OFRangeValue alloc] initWithRange: range] autorelease]; + return [[[OFValue alloc] initWithBytes: &range + objCType: @encode(OFRange)] autorelease]; } + (instancetype)valueWithPoint: (OFPoint)point { - return [[[OFPointValue alloc] initWithPoint: point] autorelease]; + return [[[OFValue alloc] initWithBytes: &point + objCType: @encode(OFPoint)] autorelease]; } + (instancetype)valueWithSize: (OFSize)size { - return [[[OFSizeValue alloc] initWithSize: size] autorelease]; + return [[[OFValue alloc] initWithBytes: &size + objCType: @encode(OFSize)] autorelease]; } + (instancetype)valueWithRect: (OFRect)rect { - return [[[OFRectValue alloc] initWithRect: rect] autorelease]; + return [[[OFValue alloc] initWithBytes: &rect + objCType: @encode(OFRect)] autorelease]; +} + ++ (instancetype)valueWithVector3D: (OFVector3D)vector3D +{ + return [[[OFValue alloc] + initWithBytes: &vector3D + objCType: @encode(OFVector3D)] autorelease]; +} + ++ (instancetype)valueWithVector4D: (OFVector4D)vector4D +{ + return [[[OFValue alloc] + initWithBytes: &vector4D + objCType: @encode(OFVector4D)] autorelease]; } - (instancetype)initWithBytes: (const void *)bytes objCType: (const char *)objCType +{ + if ([self isMemberOfClass: [OFValue class]]) { + @try { + [self doesNotRecognizeSelector: _cmd]; + } @catch (id e) { + [self release]; + @throw e; + } + + abort(); + } + + return [super init]; +} + +- (instancetype)init { OF_INVALID_INIT_METHOD } - (bool)isEqual: (id)object @@ -198,18 +261,80 @@ { OFRect ret; [self getValue: &ret size: sizeof(ret)]; return ret; } + +- (OFVector3D)vector3DValue +{ + OFVector3D ret; + [self getValue: &ret size: sizeof(ret)]; + return ret; +} + +- (OFVector4D)vector4DValue +{ + OFVector4D ret; + [self getValue: &ret size: sizeof(ret)]; + return ret; +} - (OFString *)description { - OFMutableString *ret = - [OFMutableString stringWithString: @"", + rangeValue.location, rangeValue.length]; + } else if (strcmp(objCType, @encode(OFPoint)) == 0 || + strcmp(objCType, @encode(const OFPoint)) == 0) { + OFPoint pointValue; + [self getValue: &pointValue size: sizeof(pointValue)]; + return [OFString stringWithFormat: + @"", + pointValue.x, pointValue.y]; + } else if (strcmp(objCType, @encode(OFSize)) == 0 || + strcmp(objCType, @encode(const OFSize)) == 0) { + OFSize sizeValue; + [self getValue: &sizeValue size: sizeof(sizeValue)]; + return [OFString stringWithFormat: + @"", + sizeValue.width, sizeValue.height]; + } else if (strcmp(objCType, @encode(OFRect)) == 0 || + strcmp(objCType, @encode(const OFRect)) == 0) { + OFRect rectValue; + [self getValue: &rectValue size: sizeof(rectValue)]; + return [OFString stringWithFormat: + @"", + rectValue.origin.x, rectValue.origin.y, + rectValue.size.width, rectValue.size.height]; + } else if (strcmp(objCType, @encode(OFVector3D)) == 0 || + strcmp(objCType, @encode(const OFVector3D)) == 0) { + OFVector3D vector3DValue; + [self getValue: &vector3DValue size: sizeof(vector3DValue)]; + return [OFString stringWithFormat: + @"", + vector3DValue.x, vector3DValue.y, vector3DValue.z]; + } else if (strcmp(objCType, @encode(OFVector4D)) == 0 || + strcmp(objCType, @encode(const OFVector4D)) == 0) { + OFVector4D vector4DValue; + [self getValue: &vector4DValue size: sizeof(vector4DValue)]; + return [OFString stringWithFormat: + @"", + vector4DValue.x, vector4DValue.y, vector4DValue.z, + vector4DValue.w]; + } + + ret = [OFMutableString stringWithString: @" + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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.m ================================================================== --- src/OFWindowsRegistryKey.m +++ src/OFWindowsRegistryKey.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/OFXMLAttribute.h ================================================================== --- src/OFXMLAttribute.h +++ src/OFXMLAttribute.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -90,10 +90,8 @@ * @return An initialized OFXMLAttribute with the specified parameters */ - (instancetype)initWithName: (OFString *)name namespace: (nullable OFString *)nameSpace stringValue: (OFString *)stringValue OF_DESIGNATED_INITIALIZER; - -- (instancetype)initWithSerialization: (OFXMLElement *)element; @end OF_ASSUME_NONNULL_END Index: src/OFXMLAttribute.m ================================================================== --- src/OFXMLAttribute.m +++ src/OFXMLAttribute.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,10 @@ #import "OFXMLAttribute.h" #import "OFXMLNode+Private.h" #import "OFString.h" #import "OFDictionary.h" -#import "OFXMLElement.h" #import "OFInvalidArgumentException.h" @implementation OFXMLAttribute @synthesize name = _name, namespace = _namespace; @@ -63,46 +62,10 @@ } @catch (id e) { [self release]; @throw e; } - return self; -} - -- (instancetype)initWithSerialization: (OFXMLElement *)element -{ - void *pool; - OFString *name, *namespace, *stringValue; - - @try { - pool = objc_autoreleasePoolPush(); - - if (![element.name isEqual: self.className] || - ![element.namespace isEqual: OFSerializationNS]) - @throw [OFInvalidArgumentException exception]; - - name = [element attributeForName: @"name"].stringValue; - namespace = [element attributeForName: @"namespace"] - .stringValue; - stringValue = [element attributeForName: @"stringValue"] - .stringValue; - } @catch (id e) { - [self release]; - @throw e; - } - - self = [self initWithName: name - namespace: namespace - stringValue: stringValue]; - - @try { - objc_autoreleasePoolPop(pool); - } @catch (id e) { - [self release]; - @throw e; - } - return self; } - (void)dealloc { @@ -161,36 +124,13 @@ OFHashFinalize(&hash); return hash; } -- (OFXMLElement *)XMLElementBySerializing -{ - void *pool = objc_autoreleasePoolPush(); - OFXMLElement *element; - - element = [OFXMLElement elementWithName: self.className - namespace: OFSerializationNS]; - [element addAttributeWithName: @"name" stringValue: _name]; - - if (_namespace != nil) - [element addAttributeWithName: @"namespace" - stringValue: _namespace]; - - [element addAttributeWithName: @"stringValue" - stringValue: _stringValue]; - - [element retain]; - - objc_autoreleasePoolPop(pool); - - return [element autorelease]; -} - - (OFString *)description { return [OFString stringWithFormat: @"<%@: name=%@, namespace=%@, " @"stringValue=%@>", self.class, _name, _namespace, _stringValue]; } @end Index: src/OFXMLCDATA.h ================================================================== --- src/OFXMLCDATA.h +++ src/OFXMLCDATA.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,10 +41,8 @@ * * @param string The string value for the CDATA * @return An initialized OFXMLCDATA */ - (instancetype)initWithString: (OFString *)string; - -- (instancetype)initWithSerialization: (OFXMLElement *)element; @end OF_ASSUME_NONNULL_END Index: src/OFXMLCDATA.m ================================================================== --- src/OFXMLCDATA.m +++ src/OFXMLCDATA.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,11 +16,10 @@ #include "config.h" #import "OFXMLCDATA.h" #import "OFXMLNode+Private.h" #import "OFString.h" -#import "OFXMLElement.h" #import "OFInvalidArgumentException.h" @implementation OFXMLCDATA + (instancetype)CDATAWithString: (OFString *)string @@ -37,32 +36,10 @@ } @catch (id e) { [self release]; @throw e; } - return self; -} - -- (instancetype)initWithSerialization: (OFXMLElement *)element -{ - self = [super of_init]; - - @try { - void *pool = objc_autoreleasePoolPush(); - - if (![element.name isEqual: self.className] || - ![element.namespace isEqual: OFSerializationNS]) - @throw [OFInvalidArgumentException exception]; - - _CDATA = [element.stringValue copy]; - - objc_autoreleasePoolPop(pool); - } @catch (id e) { - [self release]; - @throw e; - } - return self; } - (void)dealloc { @@ -118,16 +95,6 @@ - (OFString *)description { return self.XMLString; } - -- (OFXMLElement *)XMLElementBySerializing -{ - OFXMLElement *element = - [OFXMLElement elementWithName: self.className - namespace: OFSerializationNS]; - [element addChild: self]; - - return element; -} @end Index: src/OFXMLCharacters.h ================================================================== --- src/OFXMLCharacters.h +++ src/OFXMLCharacters.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,8 @@ * * @param string The string value for the characters * @return An initialized OFXMLCharacters */ - (instancetype)initWithString: (OFString *)string; - -- (instancetype)initWithSerialization: (OFXMLElement *)element; @end OF_ASSUME_NONNULL_END Index: src/OFXMLCharacters.m ================================================================== --- src/OFXMLCharacters.m +++ src/OFXMLCharacters.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,11 +16,10 @@ #include "config.h" #import "OFXMLCharacters.h" #import "OFXMLNode+Private.h" #import "OFString.h" -#import "OFXMLElement.h" #import "OFInvalidArgumentException.h" @implementation OFXMLCharacters + (instancetype)charactersWithString: (OFString *)string @@ -37,32 +36,10 @@ } @catch (id e) { [self release]; @throw e; } - return self; -} - -- (instancetype)initWithSerialization: (OFXMLElement *)element -{ - self = [super of_init]; - - @try { - void *pool = objc_autoreleasePoolPush(); - - if (![element.name isEqual: self.className] || - ![element.namespace isEqual: OFSerializationNS]) - @throw [OFInvalidArgumentException exception]; - - _characters = [element.stringValue copy]; - - objc_autoreleasePoolPop(pool); - } @catch (id e) { - [self release]; - @throw e; - } - return self; } - (void)dealloc { @@ -110,13 +87,6 @@ - (OFString *)description { return self.XMLString; } - -- (OFXMLElement *)XMLElementBySerializing -{ - return [OFXMLElement elementWithName: self.className - namespace: OFSerializationNS - stringValue: _characters]; -} @end Index: src/OFXMLComment.h ================================================================== --- src/OFXMLComment.h +++ src/OFXMLComment.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,10 +47,8 @@ * * @param text The text for the comment * @return An initialized OFXMLComment */ - (instancetype)initWithText: (OFString *)text; - -- (instancetype)initWithSerialization: (OFXMLElement *)element; @end OF_ASSUME_NONNULL_END Index: src/OFXMLComment.m ================================================================== --- src/OFXMLComment.m +++ src/OFXMLComment.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,11 +18,10 @@ #include #import "OFXMLComment.h" #import "OFXMLNode+Private.h" #import "OFString.h" -#import "OFXMLElement.h" #import "OFInvalidArgumentException.h" @implementation OFXMLComment @synthesize text = _text; @@ -41,32 +40,10 @@ } @catch (id e) { [self release]; @throw e; } - return self; -} - -- (instancetype)initWithSerialization: (OFXMLElement *)element -{ - self = [super of_init]; - - @try { - void *pool = objc_autoreleasePoolPush(); - - if (![element.name isEqual: self.className] || - ![element.namespace isEqual: OFSerializationNS]) - @throw [OFInvalidArgumentException exception]; - - _text = [element.stringValue copy]; - - objc_autoreleasePoolPop(pool); - } @catch (id e) { - [self release]; - @throw e; - } - return self; } - (void)dealloc { @@ -107,13 +84,6 @@ - (OFString *)description { return self.XMLString; } - -- (OFXMLElement *)XMLElementBySerializing -{ - return [OFXMLElement elementWithName: self.className - namespace: OFSerializationNS - stringValue: _text]; -} @end DELETED src/OFXMLElement+Serialization.h Index: src/OFXMLElement+Serialization.h ================================================================== --- src/OFXMLElement+Serialization.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2008-2022 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#import "OFXMLElement.h" - -OF_ASSUME_NONNULL_BEGIN - -#ifdef __cplusplus -extern "C" { -#endif -extern int _OFXMLElement_Serialization_reference; -#ifdef __cplusplus -} -#endif - -@interface OFXMLElement (OFSerialization) -/** - * @brief The XML element interpreted as serialization and parsed into an - * object. - */ -@property (readonly, nonatomic) id objectByDeserializing; -@end - -OF_ASSUME_NONNULL_END DELETED src/OFXMLElement+Serialization.m Index: src/OFXMLElement+Serialization.m ================================================================== --- src/OFXMLElement+Serialization.m +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) 2008-2022 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#include "config.h" - -#import "OFXMLElement.h" -#import "OFXMLElement+Serialization.h" -#import "OFSerialization.h" -#import "OFString.h" - -#import "OFInvalidArgumentException.h" - -int _OFXMLElement_Serialization_reference; - -@implementation OFXMLElement (Serialization) -- (id)objectByDeserializing -{ - void *pool = objc_autoreleasePoolPush(); - Class class; - id object; - - if ((class = objc_getClass([_name cStringWithEncoding: - OFStringEncodingASCII])) == Nil) - @throw [OFInvalidArgumentException exception]; - - if (![class conformsToProtocol: @protocol(OFSerialization)]) - @throw [OFInvalidArgumentException exception]; - - object = [[class alloc] initWithSerialization: self]; - - objc_autoreleasePoolPop(pool); - - return [object autorelease]; -} -@end Index: src/OFXMLElement.h ================================================================== --- src/OFXMLElement.h +++ src/OFXMLElement.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -432,7 +432,5 @@ - (OFString *)XMLStringWithDefaultNamespace: (OFString *)defaultNS indentation: (unsigned int)indentation; @end OF_ASSUME_NONNULL_END - -#import "OFXMLElement+Serialization.h" Index: src/OFXMLElement.m ================================================================== --- src/OFXMLElement.m +++ src/OFXMLElement.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,12 +18,10 @@ #define OF_XML_ELEMENT_M #include #include -#include - #import "OFXMLElement.h" #import "OFArray.h" #import "OFData.h" #import "OFDictionary.h" #import "OFStream.h" @@ -38,17 +36,10 @@ #import "OFInvalidArgumentException.h" #import "OFInvalidFormatException.h" #import "OFMalformedXMLException.h" #import "OFUnboundNamespaceException.h" -/* References for static linking */ -void -_references_to_categories_of_OFXMLElement(void) -{ - _OFXMLElement_Serialization_reference = 1; -} - @interface OFXMLElementElementBuilderDelegate: OFObject { @public OFXMLElement *_element; @@ -267,108 +258,10 @@ [_namespaces release]; _namespaces = [element->_namespaces retain]; [_children release]; _children = [element->_children retain]; - objc_autoreleasePoolPop(pool); - } @catch (id e) { - [self release]; - @throw e; - } - - return self; -} - -- (instancetype)initWithSerialization: (OFXMLElement *)element -{ - void *pool; - OFString *name, *namespace; - - @try { - pool = objc_autoreleasePoolPush(); - - if (![element.name isEqual: self.className] || - ![element.namespace isEqual: OFSerializationNS]) - @throw [OFInvalidArgumentException exception]; - - name = [element attributeForName: @"name"].stringValue; - namespace = - [element attributeForName: @"namespace"].stringValue; - } @catch (id e) { - [self release]; - @throw e; - } - - self = [self initWithName: name namespace: namespace]; - - @try { - OFXMLElement *attributesElement, *namespacesElement; - OFXMLElement *childrenElement; - OFEnumerator *keyEnumerator, *objectEnumerator; - OFString *key, *object; - - attributesElement = [[element - elementForName: @"attributes" - namespace: OFSerializationNS] - elementsForNamespace: OFSerializationNS].firstObject; - namespacesElement = [[element - elementForName: @"namespaces" - namespace: OFSerializationNS] - elementsForNamespace: OFSerializationNS].firstObject; - childrenElement = [[element - elementForName: @"children" - namespace: OFSerializationNS] - elementsForNamespace: OFSerializationNS].firstObject; - - [_attributes release]; - _attributes = nil; - _attributes = [attributesElement.objectByDeserializing - mutableCopy]; - - [_namespaces release]; - _namespaces = nil; - _namespaces = [namespacesElement.objectByDeserializing - mutableCopy]; - - [_children release]; - _children = nil; - _children = [childrenElement.objectByDeserializing - mutableCopy]; - - /* Sanity checks */ - if ((_attributes != nil && ![_attributes isKindOfClass: - [OFMutableArray class]]) || (_namespaces != nil && - ![_namespaces isKindOfClass: - [OFMutableDictionary class]]) || (_children != nil && - ![_children isKindOfClass: [OFMutableArray class]])) - @throw [OFInvalidArgumentException exception]; - - for (OFXMLAttribute *attribute in _attributes) - if (![attribute isKindOfClass: [OFXMLAttribute class]]) - @throw [OFInvalidArgumentException exception]; - - keyEnumerator = [_namespaces keyEnumerator]; - objectEnumerator = [_namespaces objectEnumerator]; - while ((key = [keyEnumerator nextObject]) != nil && - (object = [objectEnumerator nextObject]) != nil) - if (![key isKindOfClass: [OFString class]] || - ![object isKindOfClass: [OFString class]]) - @throw [OFInvalidArgumentException exception]; - - for (object in _children) - if (![object isKindOfClass: [OFXMLNode class]]) - @throw [OFInvalidArgumentException exception]; - - if (_namespaces == nil) - _namespaces = [[OFMutableDictionary alloc] init]; - - [_namespaces - setObject: @"xml" - forKey: @"http://www.w3.org/XML/1998/namespace"]; - [_namespaces setObject: @"xmlns" - forKey: @"http://www.w3.org/2000/xmlns/"]; - objc_autoreleasePoolPop(pool); } @catch (id e) { [self release]; @throw e; } @@ -631,11 +524,11 @@ i += _name.UTF8StringLength; } else cString[i++] = '/'; cString[i++] = '>'; - assert(i == length); + OFAssert(i == length); objc_autoreleasePoolPop(pool); ret = [OFString stringWithUTF8String: cString length: length]; @@ -668,73 +561,10 @@ namespaces: nil indentation: indentation level: 0]; } -- (OFXMLElement *)XMLElementBySerializing -{ - void *pool = objc_autoreleasePoolPush(); - OFXMLElement *element; - - element = [OFXMLElement elementWithName: self.className - namespace: OFSerializationNS]; - - if (_name != nil) - [element addAttributeWithName: @"name" stringValue: _name]; - - if (_namespace != nil) - [element addAttributeWithName: @"namespace" - stringValue: _namespace]; - - if (_attributes != nil) { - OFXMLElement *attributesElement; - - attributesElement = - [OFXMLElement elementWithName: @"attributes" - namespace: OFSerializationNS]; - [attributesElement addChild: - _attributes.XMLElementBySerializing]; - [element addChild: attributesElement]; - } - - if (_namespaces != nil) { - OFXMLElement *namespacesElement; - OFMutableDictionary *namespacesCopy = - [[_namespaces mutableCopy] autorelease]; - - [namespacesCopy removeObjectForKey: - @"http://www.w3.org/XML/1998/namespace"]; - [namespacesCopy removeObjectForKey: - @"http://www.w3.org/2000/xmlns/"]; - - if (namespacesCopy.count > 0) { - namespacesElement = - [OFXMLElement elementWithName: @"namespaces" - namespace: OFSerializationNS]; - [namespacesElement addChild: - namespacesCopy.XMLElementBySerializing]; - [element addChild: namespacesElement]; - } - } - - if (_children != nil) { - OFXMLElement *childrenElement; - - childrenElement = - [OFXMLElement elementWithName: @"children" - namespace: OFSerializationNS]; - [childrenElement addChild: _children.XMLElementBySerializing]; - [element addChild: childrenElement]; - } - - [element retain]; - - objc_autoreleasePoolPop(pool); - - return [element autorelease]; -} - - (void)addAttribute: (OFXMLAttribute *)attribute { if (![attribute isKindOfClass: [OFXMLAttribute class]]) @throw [OFInvalidArgumentException exception]; Index: src/OFXMLElementBuilder.h ================================================================== --- src/OFXMLElementBuilder.h +++ src/OFXMLElementBuilder.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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.m ================================================================== --- src/OFXMLElementBuilder.m +++ src/OFXMLElementBuilder.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,22 +12,19 @@ * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this * file. */ #import "OFObject.h" -#import "OFSerialization.h" OF_ASSUME_NONNULL_BEGIN -@class OFXMLElement; - /** * @class OFXMLNode OFXMLNode.h ObjFW/OFXMLNode.h * * @brief A class which stores an XML element. */ -@interface OFXMLNode: OFObject +@interface OFXMLNode: OFObject { OF_RESERVE_IVARS(OFXMLNode, 4) } /** @@ -75,11 +72,10 @@ * needs a prefix */ @property (readonly, nonatomic) OFString *XMLString; - (instancetype)init OF_UNAVAILABLE; -- (instancetype)initWithSerialization: (OFXMLElement *)element OF_UNAVAILABLE; /** * @brief The contents of the receiver as a `long long` value in the specified * base. * Index: src/OFXMLNode.m ================================================================== --- src/OFXMLNode.m +++ src/OFXMLNode.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,15 +24,10 @@ return [super init]; } - (instancetype)init { - OF_INVALID_INIT_METHOD -} - -- (instancetype)initWithSerialization: (OFXMLElement *)element -{ OF_INVALID_INIT_METHOD } - (OFString *)stringValue { @@ -82,15 +77,10 @@ - (OFString *)description { return self.XMLString; } -- (OFXMLElement *)XMLElementBySerializing -{ - OF_UNRECOGNIZED_SELECTOR -} - - (id)copy { return [self retain]; } @end Index: src/OFXMLParser.h ================================================================== --- src/OFXMLParser.h +++ src/OFXMLParser.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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 @@ * @param target The target of the processing instruction * @param text The text of the processing instruction */ - (void)parser: (OFXMLParser *)parser foundProcessingInstructionWithTarget: (OFString *)target - text: (OFString *)text; + text: (nullable OFString *)text; /** * @brief This callback is called when the XML parser found the start of a new * tag. * Index: src/OFXMLParser.m ================================================================== --- src/OFXMLParser.m +++ src/OFXMLParser.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -58,10 +58,8 @@ * @param text The text for the processing instruction * @return An initialized OFXMLProcessingInstruction */ - (instancetype)initWithTarget: (OFString *)target text: (OFString *)text OF_DESIGNATED_INITIALIZER; - -- (instancetype)initWithSerialization: (OFXMLElement *)element; @end OF_ASSUME_NONNULL_END Index: src/OFXMLProcessingInstruction.m ================================================================== --- src/OFXMLProcessingInstruction.m +++ src/OFXMLProcessingInstruction.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,11 +18,10 @@ #include #import "OFXMLProcessingInstruction.h" #import "OFString.h" #import "OFXMLAttribute.h" -#import "OFXMLElement.h" #import "OFXMLNode+Private.h" #import "OFInvalidArgumentException.h" @implementation OFXMLProcessingInstruction @@ -46,37 +45,10 @@ } @catch (id e) { [self release]; @throw e; } - return self; -} - -- (instancetype)initWithSerialization: (OFXMLElement *)element -{ - @try { - void *pool = objc_autoreleasePoolPush(); - OFXMLAttribute *targetAttr; - - if (![element.name isEqual: self.className] || - ![element.namespace isEqual: OFSerializationNS]) - @throw [OFInvalidArgumentException exception]; - - targetAttr = [element attributeForName: @"target" - namespace: OFSerializationNS]; - if (targetAttr.stringValue.length == 0) - @throw [OFInvalidArgumentException exception]; - - self = [self initWithTarget: targetAttr.stringValue - text: element.stringValue]; - - objc_autoreleasePoolPop(pool); - } @catch (id e) { - [self release]; - @throw e; - } - return self; } - (void)dealloc { @@ -136,21 +108,6 @@ - (OFString *)description { return self.XMLString; } - -- (OFXMLElement *)XMLElementBySerializing -{ - OFXMLElement *ret = [OFXMLElement elementWithName: self.className - namespace: OFSerializationNS - stringValue: _text]; - void *pool = objc_autoreleasePoolPush(); - - [ret addAttribute: [OFXMLAttribute attributeWithName: @"target" - stringValue: _target]]; - - objc_autoreleasePoolPop(pool); - - return ret; -} @end Index: src/OFZIPArchive.h ================================================================== --- src/OFZIPArchive.h +++ src/OFZIPArchive.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,28 +20,53 @@ OF_ASSUME_NONNULL_BEGIN @class OFArray OF_GENERIC(ObjectType); @class OFMutableArray OF_GENERIC(ObjectType); @class OFMutableDictionary OF_GENERIC(KeyType, ObjectType); +@class OFSeekableStream; @class OFStream; +@class OFZIPArchive; + +/** + * @protocol OFZIPArchiveDelegate OFZIPArchive.h ObjFW/OFZIPArchive.h + * + * @brief A delegate for OFZIPArchive. + */ +@protocol OFZIPArchiveDelegate +@optional +/** + * @brief A callback that is called when an @ref OFZIPArchive wants to read a + * different archive part. + * + * @param archive The archive that wants to read another part + * @param partNumber The number of the part the archive wants to read + * @param lastPartNumber The number of the last archive part + * @return The stream to read the needed part, or `nil` if no such part exists + */ +- (nullable OFSeekableStream *)archive: (OFZIPArchive *)archive + wantsPartNumbered: (unsigned int)partNumber + lastPartNumber: (unsigned int)lastPartNumber; +@end /** * @class OFZIPArchive OFZIPArchive.h ObjFW/OFZIPArchive.h * * @brief A class for accessing and manipulating ZIP files. */ OF_SUBCLASSING_RESTRICTED @interface OFZIPArchive: OFObject { - OFStream *_stream; #ifdef OF_ZIP_ARCHIVE_M @public #endif + OFObject *_Nullable _delegate; + OF_KINDOF(OFStream *) _stream; int64_t _offset; -@protected uint_least8_t _mode; - uint32_t _diskNumber, _centralDirectoryDisk; + uint32_t _diskNumber, _lastDiskNumber; +@protected + uint32_t _centralDirectoryDisk; uint64_t _centralDirectoryEntriesInDisk, _centralDirectoryEntries; uint64_t _centralDirectorySize; int64_t _centralDirectoryOffset; OFString *_Nullable _archiveComment; #ifdef OF_ZIP_ARCHIVE_M @@ -51,10 +76,16 @@ OFMutableDictionary OF_GENERIC(OFString *, OFZIPArchiveEntry *) *_pathToEntryMap; OFStream *_Nullable _lastReturnedStream; } +/** + * @brief The delegate of the ZIP archive. + */ +@property OF_NULLABLE_PROPERTY (assign, nonatomic) + OFObject *delegate; + /** * @brief The archive comment. */ @property OF_NULLABLE_PROPERTY (copy, nonatomic) OFString *archiveComment; @@ -83,29 +114,29 @@ + (instancetype)archiveWithStream: (OFStream *)stream mode: (OFString *)mode; /** * @brief Creates a new OFZIPArchive object with the specified file. * - * @param URI The URI to the ZIP file + * @param IRI The IRI to the ZIP file * @param mode The mode for the ZIP file. Valid modes are "r" for reading, * "w" for creating a new file and "a" for appending to an existing * archive. * @return A new, autoreleased OFZIPArchive * @throw OFInvalidFormatException The format is not that of a valid ZIP archive */ -+ (instancetype)archiveWithURI: (OFURI *)URI mode: (OFString *)mode; ++ (instancetype)archiveWithIRI: (OFIRI *)IRI mode: (OFString *)mode; /** - * @brief Creates a URI for accessing a the specified file within the specified - * ZIP archive. + * @brief Creates an IRI for accessing a the specified file within the + * specified ZIP archive. * * @param path The path of the file within the archive - * @param URI The URI of the archive - * @return A URI for accessing the specified file within the specified ZIP + * @param IRI The IRI of the archive + * @return An IRI for accessing the specified file within the specified ZIP * archive */ -+ (OFURI *)URIForFilePath: (OFString *)path inArchiveWithURI: (OFURI *)URI; ++ (OFIRI *)IRIForFilePath: (OFString *)path inArchiveWithIRI: (OFIRI *)IRI; - (instancetype)init OF_UNAVAILABLE; /** * @brief Initializes an already allocated OFZIPArchive object with the @@ -124,18 +155,18 @@ /** * @brief Initializes an already allocated OFZIPArchive object with the * specified file. * - * @param URI The URI to the ZIP file + * @param IRI The IRI to the ZIP file * @param mode The mode for the ZIP file. Valid modes are "r" for reading, * "w" for creating a new file and "a" for appending to an existing * archive. * @return An initialized OFZIPArchive * @throw OFInvalidFormatException The format is not that of a valid ZIP archive */ -- (instancetype)initWithURI: (OFURI *)URI mode: (OFString *)mode; +- (instancetype)initWithIRI: (OFIRI *)IRI mode: (OFString *)mode; /** * @brief Returns a stream for reading the specified file from the archive. * * @note This method is only available in read mode. @@ -186,13 +217,15 @@ * * Bit 3 and 11 of the general purpose bit flag. * @return A stream for writing the specified entry to the archive * @throw OFNotOpenException The archive is not open * @throw OFInvalidArgumentException The archive is not in write mode * @throw OFOpenItemFailedException Opening the specified file within the - * archive failed. If @ref errNo is `EEXIST`, - * because there is already a file with the - * same name in the archive. + * archive failed. If + * @ref OFOpenItemFailedException#errNo is + * `EEXIST`, it failed because there is + * already a file with the same name in the + * archive. * @throw OFNotImplementedException The desired compression method is not * implemented */ - (OFStream *)streamForWritingEntry: (OFZIPArchiveEntry *)entry; Index: src/OFZIPArchive.m ================================================================== --- src/OFZIPArchive.m +++ src/OFZIPArchive.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,21 +20,21 @@ #include #import "OFZIPArchive.h" #import "OFZIPArchiveEntry.h" #import "OFZIPArchiveEntry+Private.h" -#import "OFArchiveURIHandler.h" +#import "OFArchiveIRIHandler.h" #import "OFArray.h" #import "OFCRC32.h" #import "OFData.h" #import "OFDictionary.h" +#import "OFIRI.h" +#import "OFIRIHandler.h" #import "OFInflate64Stream.h" #import "OFInflateStream.h" #import "OFSeekableStream.h" #import "OFStream.h" -#import "OFURI.h" -#import "OFURIHandler.h" #import "OFChecksumMismatchException.h" #import "OFInvalidArgumentException.h" #import "OFInvalidFormatException.h" #import "OFNotImplementedException.h" @@ -45,12 +45,11 @@ #import "OFTruncatedDataException.h" #import "OFUnsupportedVersionException.h" #import "OFWriteFailedException.h" /* - * FIXME: Current limitations: - * - Split archives are not supported. + * TODO: Current limitations: * - Encrypted files cannot be read. */ enum { modeRead, @@ -83,11 +82,12 @@ OF_DIRECT_MEMBERS @interface OFZIPArchiveFileReadStream: OFStream { OFZIPArchive *_archive; - OFStream *_stream, *_decompressedStream; + OFZIPArchiveEntryCompressionMethod _compressionMethod; + OF_KINDOF(OFStream *) _decompressedStream; OFZIPArchiveEntry *_entry; unsigned long long _toRead; uint32_t _CRC32; bool _atEndOfStream; } @@ -99,20 +99,23 @@ OF_DIRECT_MEMBERS @interface OFZIPArchiveFileWriteStream: OFStream { OFZIPArchive *_archive; - OFStream *_stream; + OF_KINDOF(OFStream *) _stream; uint32_t _CRC32; + OFStreamOffset _CRC32Offset, _size64Offset; @public unsigned long long _bytesWritten; OFMutableZIPArchiveEntry *_entry; } - (instancetype)of_initWithArchive: (OFZIPArchive *)archive stream: (OFStream *)stream - entry: (OFMutableZIPArchiveEntry *)entry; + entry: (OFMutableZIPArchiveEntry *)entry + CRC32Offset: (OFStreamOffset)CRC32Offset + size64Offset: (OFStreamOffset)size64Offset; @end uint32_t OFZIPArchiveReadField32(const uint8_t **data, uint16_t *size) { @@ -145,40 +148,60 @@ *size -= 8; return field; } +@implementation OFZIPArchive +@synthesize delegate = _delegate, archiveComment = _archiveComment; + static void -seekOrThrowInvalidFormat(OFSeekableStream *stream, +seekOrThrowInvalidFormat(OFZIPArchive *archive, const uint32_t *diskNumber, OFStreamOffset offset, OFSeekWhence whence) { + if (diskNumber != NULL && *diskNumber != archive->_diskNumber) { + OFStream *oldStream = archive->_stream; + OFSeekableStream *stream; + + if (archive->_mode != modeRead || + *diskNumber > archive->_lastDiskNumber) + @throw [OFInvalidFormatException exception]; + + stream = [archive->_delegate archive: archive + wantsPartNumbered: *diskNumber + lastPartNumber: archive->_lastDiskNumber]; + + if (stream == nil) + @throw [OFInvalidFormatException exception]; + + archive->_diskNumber = *diskNumber; + archive->_stream = [stream retain]; + [oldStream release]; + } + @try { - [stream seekToOffset: offset whence: whence]; + [archive->_stream seekToOffset: offset whence: whence]; } @catch (OFSeekFailedException *e) { if (e.errNo == EINVAL) @throw [OFInvalidFormatException exception]; @throw e; } } -@implementation OFZIPArchive -@synthesize archiveComment = _archiveComment; - + (instancetype)archiveWithStream: (OFStream *)stream mode: (OFString *)mode { return [[[self alloc] initWithStream: stream mode: mode] autorelease]; } -+ (instancetype)archiveWithURI: (OFURI *)URI mode: (OFString *)mode ++ (instancetype)archiveWithIRI: (OFIRI *)IRI mode: (OFString *)mode { - return [[[self alloc] initWithURI: URI mode: mode] autorelease]; + return [[[self alloc] initWithIRI: IRI mode: mode] autorelease]; } -+ (OFURI *)URIForFilePath: (OFString *)path inArchiveWithURI: (OFURI *)URI ++ (OFIRI *)IRIForFilePath: (OFString *)path inArchiveWithIRI: (OFIRI *)IRI { - return OFArchiveURIHandlerURIForFileInArchive(@"zip", path, URI); + return OFArchiveIRIHandlerIRIForFileInArchive(@"zip", path, IRI); } - (instancetype)init { OF_INVALID_INIT_METHOD @@ -210,11 +233,11 @@ [self of_readEntries]; } if (_mode == modeAppend) { _offset = _centralDirectoryOffset; - seekOrThrowInvalidFormat((OFSeekableStream *)_stream, + seekOrThrowInvalidFormat(self, NULL, (OFStreamOffset)_offset, OFSeekSet); } } @catch (id e) { /* * If we are in write or append mode, we do not want -[close] @@ -229,20 +252,20 @@ } return self; } -- (instancetype)initWithURI: (OFURI *)URI mode: (OFString *)mode +- (instancetype)initWithIRI: (OFIRI *)IRI mode: (OFString *)mode { void *pool = objc_autoreleasePoolPush(); OFStream *stream; @try { if ([mode isEqual: @"a"]) - stream = [OFURIHandler openItemAtURI: URI mode: @"r+"]; + stream = [OFIRIHandler openItemAtIRI: IRI mode: @"r+"]; else - stream = [OFURIHandler openItemAtURI: URI mode: mode]; + stream = [OFIRIHandler openItemAtIRI: IRI mode: mode]; } @catch (id e) { [self release]; @throw e; } @@ -272,12 +295,11 @@ uint16_t commentLength; OFStreamOffset offset = -22; bool valid = false; do { - seekOrThrowInvalidFormat((OFSeekableStream *)_stream, - offset, OFSeekEnd); + seekOrThrowInvalidFormat(self, NULL, offset, OFSeekEnd); if ([_stream readLittleEndianInt32] == 0x06054B50) { valid = true; break; } @@ -284,11 +306,11 @@ } while (--offset >= -65557); if (!valid) @throw [OFInvalidFormatException exception]; - _diskNumber = [_stream readLittleEndianInt16]; + _diskNumber = _lastDiskNumber = [_stream readLittleEndianInt16]; _centralDirectoryDisk = [_stream readLittleEndianInt16]; _centralDirectoryEntriesInDisk = [_stream readLittleEndianInt16]; _centralDirectoryEntries = [_stream readLittleEndianInt16]; _centralDirectorySize = [_stream readLittleEndianInt32]; _centralDirectoryOffset = [_stream readLittleEndianInt32]; @@ -296,21 +318,21 @@ commentLength = [_stream readLittleEndianInt16]; _archiveComment = [[_stream readStringWithLength: commentLength encoding: OFStringEncodingCodepage437] copy]; - if (_diskNumber == 0xFFFF || + if (_lastDiskNumber == 0xFFFF || _centralDirectoryDisk == 0xFFFF || _centralDirectoryEntriesInDisk == 0xFFFF || _centralDirectoryEntries == 0xFFFF || _centralDirectorySize == 0xFFFFFFFF || _centralDirectoryOffset == 0xFFFFFFFF) { + uint32_t diskNumber; int64_t offset64; uint64_t size; - seekOrThrowInvalidFormat((OFSeekableStream *)_stream, - offset - 20, OFSeekEnd); + seekOrThrowInvalidFormat(self, NULL, offset - 20, OFSeekEnd); if ([_stream readLittleEndianInt32] != 0x07064B50) { objc_autoreleasePoolPop(pool); return; } @@ -317,17 +339,21 @@ /* * FIXME: Handle number of the disk containing ZIP64 end of * central directory record. */ - [_stream readLittleEndianInt32]; + diskNumber = [_stream readLittleEndianInt32]; offset64 = [_stream readLittleEndianInt64]; + _lastDiskNumber = [_stream readLittleEndianInt32]; + if (_lastDiskNumber == 0) + @throw [OFInvalidFormatException exception]; + _lastDiskNumber--; if (offset64 < 0 || (OFStreamOffset)offset64 != offset64) @throw [OFOutOfRangeException exception]; - seekOrThrowInvalidFormat((OFSeekableStream *)_stream, + seekOrThrowInvalidFormat(self, &diskNumber, (OFStreamOffset)offset64, OFSeekSet); if ([_stream readLittleEndianInt32] != 0x06064B50) @throw [OFInvalidFormatException exception]; @@ -338,11 +364,13 @@ /* version made by */ [_stream readLittleEndianInt16]; /* version needed to extract */ [_stream readLittleEndianInt16]; - _diskNumber = [_stream readLittleEndianInt32]; + if ([_stream readLittleEndianInt32] != _diskNumber) + @throw [OFInvalidFormatException exception]; + _centralDirectoryDisk = [_stream readLittleEndianInt32]; _centralDirectoryEntriesInDisk = [_stream readLittleEndianInt64]; _centralDirectoryEntries = [_stream readLittleEndianInt64]; _centralDirectorySize = [_stream readLittleEndianInt64]; @@ -363,15 +391,48 @@ if (_centralDirectoryOffset < 0 || (OFStreamOffset)_centralDirectoryOffset != _centralDirectoryOffset) @throw [OFOutOfRangeException exception]; - seekOrThrowInvalidFormat((OFSeekableStream *)_stream, + seekOrThrowInvalidFormat(self, &_centralDirectoryDisk, (OFStreamOffset)_centralDirectoryOffset, OFSeekSet); for (size_t i = 0; i < _centralDirectoryEntries; i++) { - OFZIPArchiveEntry *entry = [[[OFZIPArchiveEntry alloc] + OFZIPArchiveEntry *entry; + char buffer; + + /* + * The stream might have 0 bytes left to read, but might not + * realize that before a read is attempted, where it will then + * return a length of 0. But OFZIPArchiveEntry expects to be + * able to read the entire entry and will then throw an + * OFTruncatedDataException. Therefore, try to peek one byte to + * make sure the stream realizes that it's at the end. + */ + if ([_stream readIntoBuffer: &buffer length: 1] == 1) + [_stream unreadFromBuffer: &buffer length: 1]; + + if ([_stream isAtEndOfStream]) { + OFStream *oldStream = _stream; + OFSeekableStream *stream; + + if (_diskNumber >= _lastDiskNumber) + @throw [OFTruncatedDataException exception]; + + stream = [_delegate archive: self + wantsPartNumbered: _diskNumber + 1 + lastPartNumber: _lastDiskNumber]; + + if (stream == nil) + @throw [OFInvalidFormatException exception]; + + _diskNumber++; + _stream = [stream retain]; + [oldStream release]; + } + + entry = [[[OFZIPArchiveEntry alloc] of_initWithStream: _stream] autorelease]; if ([_pathToEntryMap objectForKey: entry.fileName] != nil) @throw [OFInvalidFormatException exception]; @@ -410,10 +471,11 @@ - (OFStream *)streamForReadingFile: (OFString *)path { void *pool = objc_autoreleasePoolPush(); OFZIPArchiveEntry *entry; OFZIPArchiveLocalFileHeader *localFileHeader; + uint32_t startDiskNumber; int64_t offset64; if (_stream == nil) @throw [OFNotOpenException exceptionWithObject: self]; @@ -430,15 +492,16 @@ } @catch (OFNotOpenException *e) { /* Might have already been closed by the user - that's fine. */ } _lastReturnedStream = nil; + startDiskNumber = entry.of_startDiskNumber; offset64 = entry.of_localFileHeaderOffset; if (offset64 < 0 || (OFStreamOffset)offset64 != offset64) @throw [OFOutOfRangeException exception]; - seekOrThrowInvalidFormat((OFSeekableStream *)_stream, + seekOrThrowInvalidFormat(self, &startDiskNumber, (OFStreamOffset)offset64, OFSeekSet); localFileHeader = [[[OFZIPArchiveLocalFileHeader alloc] initWithStream: _stream] autorelease]; if (![localFileHeader matchesEntry: entry]) @@ -463,15 +526,16 @@ return _lastReturnedStream; } - (OFStream *)streamForWritingEntry: (OFZIPArchiveEntry *)entry_ { - /* TODO: Avoid data descriptor when _stream is an OFSeekableStream */ int64_t offsetAdd = 0; void *pool; OFMutableZIPArchiveEntry *entry; OFString *fileName; + bool seekable; + OFStreamOffset CRC32Offset = 0, size64Offset = 0; OFData *extraField; uint16_t fileNameLength, extraFieldLength; if (_stream == nil) @throw [OFNotOpenException exceptionWithObject: self]; @@ -505,25 +569,29 @@ extraFieldLength = extraField.count; if (UINT16_MAX - extraFieldLength < 20) @throw [OFOutOfRangeException exception]; + seekable = [_stream isKindOfClass: [OFSeekableStream class]]; + entry.versionMadeBy = (entry.versionMadeBy & 0xFF00) | 45; entry.minVersionNeeded = (entry.minVersionNeeded & 0xFF00) | 45; entry.compressedSize = 0; entry.uncompressedSize = 0; entry.CRC32 = 0; - entry.generalPurposeBitFlag |= (1u << 3) | (1u << 11); + entry.generalPurposeBitFlag |= (seekable ? 0 : (1u << 3)) | (1u << 11); entry.of_localFileHeaderOffset = _offset; [_stream writeLittleEndianInt32: 0x04034B50]; [_stream writeLittleEndianInt16: entry.minVersionNeeded]; [_stream writeLittleEndianInt16: entry.generalPurposeBitFlag]; [_stream writeLittleEndianInt16: entry.compressionMethod]; [_stream writeLittleEndianInt16: entry.of_lastModifiedFileTime]; [_stream writeLittleEndianInt16: entry.of_lastModifiedFileDate]; - /* We use the data descriptor */ + /* Written later or data descriptor used instead */ + if (seekable) + CRC32Offset = [_stream seekToOffset: 0 whence: OFSeekCurrent]; [_stream writeLittleEndianInt32: 0]; /* We use ZIP64 */ [_stream writeLittleEndianInt32: 0xFFFFFFFF]; [_stream writeLittleEndianInt32: 0xFFFFFFFF]; [_stream writeLittleEndianInt16: fileNameLength]; @@ -533,11 +601,13 @@ [_stream writeString: fileName]; offsetAdd += fileNameLength; [_stream writeLittleEndianInt16: OFZIPArchiveEntryExtraFieldTagZIP64]; [_stream writeLittleEndianInt16: 16]; - /* We use the data descriptor */ + /* Written later or data descriptor used instead */ + if (seekable) + size64Offset = [_stream seekToOffset: 0 whence: OFSeekCurrent]; [_stream writeLittleEndianInt64: 0]; [_stream writeLittleEndianInt64: 0]; offsetAdd += (2 * 2) + (2 * 8); if (extraField != nil) @@ -550,11 +620,13 @@ _offset += offsetAdd; _lastReturnedStream = [[OFZIPArchiveFileWriteStream alloc] of_initWithArchive: self stream: _stream - entry: entry]; + entry: entry + CRC32Offset: CRC32Offset + size64Offset: size64Offset]; objc_autoreleasePoolPop(pool); return [_lastReturnedStream autorelease]; } @@ -734,23 +806,23 @@ { self = [super init]; @try { _archive = [archive retain]; - _stream = [stream retain]; + _compressionMethod = entry.compressionMethod; - switch (entry.compressionMethod) { + switch (_compressionMethod) { case OFZIPArchiveEntryCompressionMethodNone: - _decompressedStream = [stream retain]; + _decompressedStream = [_archive->_stream retain]; break; case OFZIPArchiveEntryCompressionMethodDeflate: _decompressedStream = [[OFInflateStream alloc] - initWithStream: stream]; + initWithStream: _archive->_stream]; break; case OFZIPArchiveEntryCompressionMethodDeflate64: _decompressedStream = [[OFInflate64Stream alloc] - initWithStream: stream]; + initWithStream: _archive->_stream]; break; default: @throw [OFNotImplementedException exceptionWithSelector: _cmd object: nil]; @@ -767,11 +839,11 @@ return self; } - (void)dealloc { - if (_stream != nil || _decompressedStream != nil) + if (_decompressedStream != nil) [self close]; [_entry release]; if (_archive->_lastReturnedStream == self) @@ -782,28 +854,63 @@ [super dealloc]; } - (bool)lowlevelIsAtEndOfStream { - if (_stream == nil) + if (_decompressedStream == nil) @throw [OFNotOpenException exceptionWithObject: self]; return _atEndOfStream; } - (size_t)lowlevelReadIntoBuffer: (void *)buffer length: (size_t)length { size_t ret; - if (_stream == nil) + if (_decompressedStream == nil) @throw [OFNotOpenException exceptionWithObject: self]; if (_atEndOfStream) return 0; - if (_stream.atEndOfStream && !_decompressedStream.hasDataInReadBuffer) - @throw [OFTruncatedDataException exception]; + if ([_archive->_stream isAtEndOfStream] && + ![_decompressedStream hasDataInReadBuffer]) { + OFStream *oldStream = _archive->_stream, *oldDecompressedStream; + OFSeekableStream *stream; + + if (_archive->_diskNumber >= _archive->_lastDiskNumber) + @throw [OFTruncatedDataException exception]; + + stream = [_archive->_delegate + archive: _archive + wantsPartNumbered: _archive->_diskNumber + 1 + lastPartNumber: _archive->_lastDiskNumber]; + + if (stream == nil) + @throw [OFInvalidFormatException exception]; + + _archive->_diskNumber++; + _archive->_stream = [stream retain]; + [oldStream release]; + + switch (_compressionMethod) { + case OFZIPArchiveEntryCompressionMethodNone: + oldDecompressedStream = _decompressedStream; + _decompressedStream = [_archive->_stream retain]; + [oldDecompressedStream release]; + break; + case OFZIPArchiveEntryCompressionMethodDeflate: + case OFZIPArchiveEntryCompressionMethodDeflate64: + [_decompressedStream + setUnderlyingStream: _archive->_stream]; + break; + default: + @throw [OFNotImplementedException + exceptionWithSelector: _cmd + object: nil]; + } + } #if SIZE_MAX >= UINT64_MAX if (length > UINT64_MAX) @throw [OFOutOfRangeException exception]; #endif @@ -832,14 +939,13 @@ } return ret; } -- (bool)hasDataInReadBuffer +- (bool)lowlevelHasDataInReadBuffer { - return (super.hasDataInReadBuffer || - _decompressedStream.hasDataInReadBuffer); + return ((OFStream *)_decompressedStream).hasDataInReadBuffer; } - (int)fileDescriptorForReading { return ((id )_decompressedStream) @@ -846,16 +952,13 @@ .fileDescriptorForReading; } - (void)close { - if (_stream == nil || _decompressedStream == nil) + if (_decompressedStream == nil) @throw [OFNotOpenException exceptionWithObject: self]; - [_stream release]; - _stream = nil; - [_decompressedStream release]; _decompressedStream = nil; [super close]; } @@ -863,17 +966,21 @@ @implementation OFZIPArchiveFileWriteStream - (instancetype)of_initWithArchive: (OFZIPArchive *)archive stream: (OFStream *)stream entry: (OFMutableZIPArchiveEntry *)entry + CRC32Offset: (OFStreamOffset)CRC32Offset + size64Offset: (OFStreamOffset)size64Offset { self = [super init]; _archive = [archive retain]; _stream = [stream retain]; _entry = [entry retain]; _CRC32 = ~0; + _CRC32Offset = CRC32Offset; + _size64Offset = size64Offset; return self; } - (void)dealloc @@ -921,30 +1028,48 @@ return length; } - (void)close { + bool seekable; + if (_stream == nil) @throw [OFNotOpenException exceptionWithObject: self]; if (_bytesWritten > UINT64_MAX) @throw [OFOutOfRangeException exception]; - [_stream writeLittleEndianInt32: 0x08074B50]; - [_stream writeLittleEndianInt32: _CRC32]; - [_stream writeLittleEndianInt64: (uint64_t)_bytesWritten]; - [_stream writeLittleEndianInt64: (uint64_t)_bytesWritten]; + seekable = [_stream isKindOfClass: [OFSeekableStream class]]; + + if (seekable) { + OFStreamOffset offset = [_stream seekToOffset: 0 + whence: OFSeekCurrent]; + + [_stream seekToOffset: _CRC32Offset whence: OFSeekSet]; + [_stream writeLittleEndianInt32: ~_CRC32]; + [_stream seekToOffset: _size64Offset whence: OFSeekSet]; + [_stream writeLittleEndianInt64: (uint64_t)_bytesWritten]; + [_stream writeLittleEndianInt64: (uint64_t)_bytesWritten]; + + [_stream seekToOffset: offset whence: OFSeekSet]; + } else { + [_stream writeLittleEndianInt32: 0x08074B50]; + [_stream writeLittleEndianInt32: ~_CRC32]; + [_stream writeLittleEndianInt64: (uint64_t)_bytesWritten]; + [_stream writeLittleEndianInt64: (uint64_t)_bytesWritten]; + } [_stream release]; _stream = nil; _entry.CRC32 = ~_CRC32; _entry.compressedSize = _bytesWritten; _entry.uncompressedSize = _bytesWritten; [_entry makeImmutable]; - _bytesWritten += (2 * 4 + 2 * 8); + if (!seekable) + _bytesWritten += (2 * 4 + 2 * 8); [_archive->_entries addObject: _entry]; [_archive->_pathToEntryMap setObject: _entry forKey: _entry.fileName]; if (ULLONG_MAX - _archive->_offset < _bytesWritten) Index: src/OFZIPArchiveEntry+Private.h ================================================================== --- src/OFZIPArchiveEntry+Private.h +++ src/OFZIPArchiveEntry+Private.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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 @@ OF_ASSUME_NONNULL_BEGIN @interface OFZIPArchiveEntry () @property (readonly, nonatomic) uint16_t of_lastModifiedFileTime, of_lastModifiedFileDate; +@property (readonly, nonatomic) uint32_t of_startDiskNumber; @property (readonly, nonatomic) int64_t of_localFileHeaderOffset; - (instancetype)of_init OF_METHOD_FAMILY(init); - (instancetype)of_initWithStream: (OFStream *)stream OF_METHOD_FAMILY(init) OF_DIRECT; Index: src/OFZIPArchiveEntry.h ================================================================== --- src/OFZIPArchiveEntry.h +++ src/OFZIPArchiveEntry.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -405,10 +405,15 @@ - (uint16_t)of_lastModifiedFileDate { return _lastModifiedFileDate; } + +- (uint32_t)of_startDiskNumber +{ + return _startDiskNumber; +} - (int64_t)of_localFileHeaderOffset { return _localFileHeaderOffset; } Index: src/ObjFW.h ================================================================== --- src/ObjFW.h +++ src/ObjFW.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,13 +43,13 @@ #import "OFMethodSignature.h" #import "OFInvocation.h" #import "OFNumber.h" #import "OFDate.h" +#import "OFIRI.h" +#import "OFIRIHandler.h" #import "OFUUID.h" -#import "OFURI.h" -#import "OFURIHandler.h" #import "OFColor.h" #import "OFNotification.h" #import "OFNotificationCenter.h" @@ -136,10 +136,12 @@ #import "OFLocale.h" #import "OFOptionsParser.h" #import "OFTimer.h" #import "OFRunLoop.h" +#import "OFMatrix4x4.h" + #ifdef OF_WINDOWS # import "OFWindowsRegistryKey.h" #endif #import "OFASN1BitString.h" @@ -153,10 +155,11 @@ #import "OFASN1PrintableString.h" #import "OFASN1UTF8String.h" #import "OFASN1Value.h" #import "OFAllocFailedException.h" +#import "OFAlreadyOpenException.h" #import "OFException.h" #import "OFChangeCurrentDirectoryFailedException.h" #import "OFChecksumMismatchException.h" #import "OFCopyItemFailedException.h" #import "OFCreateDirectoryFailedException.h" @@ -203,11 +206,10 @@ #import "OFUnsupportedProtocolException.h" #import "OFUnsupportedVersionException.h" #import "OFWriteFailedException.h" #ifdef OF_HAVE_SOCKETS # import "OFAcceptSocketFailedException.h" -# import "OFAlreadyConnectedException.h" # import "OFBindIPSocketFailedException.h" # import "OFBindSocketFailedException.h" # import "OFConnectIPSocketFailedException.h" # import "OFConnectSocketFailedException.h" # import "OFDNSQueryFailedException.h" Index: src/bridge/Makefile ================================================================== --- src/bridge/Makefile +++ src/bridge/Makefile @@ -3,12 +3,13 @@ DISTCLEAN = Info.plist SHARED_LIB = ${OBJFWBRIDGE_SHARED_LIB} STATIC_LIB = ${OBJFWBRIDGE_STATIC_LIB} FRAMEWORK = ${OBJFWBRIDGE_FRAMEWORK} -LIB_MAJOR = ${OBJFW_LIB_MAJOR} -LIB_MINOR = ${OBJFW_LIB_MINOR} +LIB_MAJOR = ${OBJFWBRIDGE_LIB_MAJOR} +LIB_MINOR = ${OBJFWBRIDGE_LIB_MINOR} +LIB_PATCH = ${OBJFWBRIDGE_LIB_PATCH} SRCS = OFArray+NSObject.m \ OFEnumerator+NSObject.m \ OFException+Swift.m \ OFDictionary+NSObject.m \ Index: src/bridge/NSArray+OFObject.h ================================================================== --- src/bridge/NSArray+OFObject.h +++ src/bridge/NSArray+OFObject.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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 @@ -2,10 +2,11 @@ STATIC_PIC_LIB_NOINST = ${EXCEPTIONS_LIB_A} STATIC_LIB_NOINST = ${EXCEPTIONS_A} SRCS = OFAllocFailedException.m \ + OFAlreadyOpenException.m \ OFChecksumMismatchException.m \ OFCopyItemFailedException.m \ OFCreateDirectoryFailedException.m \ OFCreateSymbolicLinkFailedException.m \ OFEnumerationMutationException.m \ @@ -52,11 +53,10 @@ ${USE_SRCS_WINDOWS} SRCS_FILES = OFChangeCurrentDirectoryFailedException.m \ OFGetCurrentDirectoryFailedException.m SRCS_PLUGINS = OFLoadPluginFailedException.m SRCS_SOCKETS = OFAcceptSocketFailedException.m \ - OFAlreadyConnectedException.m \ OFBindIPSocketFailedException.m \ OFBindSocketFailedException.m \ OFConnectIPSocketFailedException.m \ OFConnectSocketFailedException.m \ OFDNSQueryFailedException.m \ Index: src/exceptions/OFAcceptSocketFailedException.h ================================================================== --- src/exceptions/OFAcceptSocketFailedException.h +++ src/exceptions/OFAcceptSocketFailedException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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/OFAcceptSocketFailedException.m ================================================================== --- src/exceptions/OFAcceptSocketFailedException.m +++ src/exceptions/OFAcceptSocketFailedException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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/OFActivateSandboxFailedException.h ================================================================== --- src/exceptions/OFActivateSandboxFailedException.h +++ src/exceptions/OFActivateSandboxFailedException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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/OFActivateSandboxFailedException.m ================================================================== --- src/exceptions/OFActivateSandboxFailedException.m +++ src/exceptions/OFActivateSandboxFailedException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,34 +32,12 @@ - (instancetype)init { OF_INVALID_INIT_METHOD } -- (instancetype)retain -{ - return self; -} - -- (instancetype)autorelease -{ - return self; -} - -- (unsigned int)retainCount -{ - return OFMaxRetainCount; -} - -- (void)release -{ -} - -- (void)dealloc -{ - OF_DEALLOC_UNSUPPORTED -} +OF_SINGLETON_METHODS - (OFString *)description { return @"Allocating an object failed!"; } @end DELETED src/exceptions/OFAlreadyConnectedException.h Index: src/exceptions/OFAlreadyConnectedException.h ================================================================== --- src/exceptions/OFAlreadyConnectedException.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (c) 2008-2022 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#import "OFException.h" - -#ifndef OF_HAVE_SOCKETS -# error No sockets available! -#endif - -OF_ASSUME_NONNULL_BEGIN - -/** - * @class OFAlreadyConnectedException \ - * OFAlreadyConnectedException.h ObjFW/OFAlreadyConnectedException.h - * - * @brief An exception indicating an attempt to connect or bind an already - * connected or bound socket. - */ -@interface OFAlreadyConnectedException: OFException -{ - id _socket; - OF_RESERVE_IVARS(OFAlreadyConnectedException, 4) -} - -/** - * @brief The socket which is already connected. - */ -@property OF_NULLABLE_PROPERTY (readonly, nonatomic) id socket; - -/** - * @brief Creates a new, autoreleased already connected exception. - * - * @param socket The socket which is already connected - * @return A new, autoreleased already connected exception - */ -+ (instancetype)exceptionWithSocket: (nullable id)socket; - -/** - * @brief Initializes an already allocated already connected exception. - * - * @param socket The socket which is already connected - * @return An initialized already connected exception - */ -- (instancetype)initWithSocket: (nullable id)socket OF_DESIGNATED_INITIALIZER; -@end - -OF_ASSUME_NONNULL_END DELETED src/exceptions/OFAlreadyConnectedException.m Index: src/exceptions/OFAlreadyConnectedException.m ================================================================== --- src/exceptions/OFAlreadyConnectedException.m +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2008-2022 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#include "config.h" - -#import "OFAlreadyConnectedException.h" -#import "OFString.h" - -@implementation OFAlreadyConnectedException -@synthesize socket = _socket; - -+ (instancetype)exceptionWithSocket: (id)sock -{ - return [[[self alloc] initWithSocket: sock] autorelease]; -} - -- (instancetype)init -{ - return [self initWithSocket: nil]; -} - -- (instancetype)initWithSocket: (id)sock -{ - self = [super init]; - - _socket = [sock retain]; - - return self; -} - -- (void)dealloc -{ - [_socket release]; - - [super dealloc]; -} - -- (OFString *)description -{ - if (_socket) - return [OFString stringWithFormat: - @"The socket of type %@ is already connected or bound and " - @"thus can't be connected or bound again!", - [_socket class]]; - else - return @"A connection has already been established!"; -} -@end ADDED src/exceptions/OFAlreadyOpenException.h Index: src/exceptions/OFAlreadyOpenException.h ================================================================== --- /dev/null +++ src/exceptions/OFAlreadyOpenException.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2008-2024 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#import "OFException.h" + +OF_ASSUME_NONNULL_BEGIN + +/** + * @class OFAlreadyOpenException \ + * OFAlreadyOpenException.h ObjFW/OFAlreadyOpenException.h + * + * @brief An exception indicating that an object is already open and thus + * cannot be opened again. + */ +@interface OFAlreadyOpenException: OFException +{ + id _object; + OF_RESERVE_IVARS(OFAlreadyOpenException, 4) +} + +/** + * @brief The object which is already open. + */ +@property (readonly, nonatomic) id object; + +/** + * @brief Creates a new, autoreleased already open exception. + * + * @param object The object which is already open + * @return A new, autoreleased already open exception + */ ++ (instancetype)exceptionWithObject: (id)object; + ++ (instancetype)exception OF_UNAVAILABLE; + +/** + * @brief Initializes an already allocated already open exception. + * + * @param object The object which is already open + * @return An initialized already open exception + */ +- (instancetype)initWithObject: (id)object OF_DESIGNATED_INITIALIZER; + +- (instancetype)init OF_UNAVAILABLE; +@end + +OF_ASSUME_NONNULL_END ADDED src/exceptions/OFAlreadyOpenException.m Index: src/exceptions/OFAlreadyOpenException.m ================================================================== --- /dev/null +++ src/exceptions/OFAlreadyOpenException.m @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2008-2024 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#include "config.h" + +#import "OFAlreadyOpenException.h" +#import "OFString.h" + +@implementation OFAlreadyOpenException +@synthesize object = _object; + ++ (instancetype)exceptionWithObject: (id)object +{ + return [[[self alloc] initWithObject: object] autorelease]; +} + ++ (instancetype)exception +{ + OF_UNRECOGNIZED_SELECTOR +} + +- (instancetype)initWithObject: (id)object +{ + self = [super init]; + + _object = [object retain]; + + return self; +} + +- (instancetype)init +{ + OF_INVALID_INIT_METHOD +} + +- (void)dealloc +{ + [_object release]; + + [super dealloc]; +} + +- (OFString *)description +{ + return [OFString stringWithFormat: + @"An object of type %@ is already open and thus cannot be opened " + @"again!", + [_object class]]; +} +@end Index: src/exceptions/OFBindDDPSocketFailedException.h ================================================================== --- src/exceptions/OFBindDDPSocketFailedException.h +++ src/exceptions/OFBindDDPSocketFailedException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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/OFBindDDPSocketFailedException.m ================================================================== --- src/exceptions/OFBindDDPSocketFailedException.m +++ src/exceptions/OFBindDDPSocketFailedException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -72,11 +72,11 @@ - (OFString *)description { return [OFString stringWithFormat: @"Binding to port %" @PRIx8 @" of node %" @PRIx8 @" on network " - @"%" PRIx16 @" with protocol type %" @PRIx8 @" failed in socket of " - @"type %@: %@", + @"%" PRIx16 @" with protocol type 0x%" @PRIX8 @" failed in socket " + @"of type %@: %@", _port, _node, _network, _protocolType, [_socket class], OFStrError(_errNo)]; } @end Index: src/exceptions/OFBindIPSocketFailedException.h ================================================================== --- src/exceptions/OFBindIPSocketFailedException.h +++ src/exceptions/OFBindIPSocketFailedException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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/OFBindIPSocketFailedException.m ================================================================== --- src/exceptions/OFBindIPSocketFailedException.m +++ src/exceptions/OFBindIPSocketFailedException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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/OFBindIPXSocketFailedException.h ================================================================== --- src/exceptions/OFBindIPXSocketFailedException.h +++ src/exceptions/OFBindIPXSocketFailedException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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/OFBindIPXSocketFailedException.m ================================================================== --- src/exceptions/OFBindIPXSocketFailedException.m +++ src/exceptions/OFBindIPXSocketFailedException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,14 +78,13 @@ memcpy(node, _node, sizeof(_node)); } - (OFString *)description { - OFData *node = [OFData dataWithItems: _node count: sizeof(_node)]; - return [OFString stringWithFormat: - @"Binding to network %" @PRIx16 " on node %@ with port %" @PRIx16 - @" failed for packet type %" @PRIx8 " in socket of type %@: %@", - _network, node, _port, _packetType, [_socket class], - OFStrError(_errNo)]; + @"Binding to network %" @PRIx16 " on node " + @"%02X:%02X:%02X:%02X:%02X:%02X with port %" @PRIx16 @" failed for " + @"packet type %" @PRIx8 " in socket of type %@: %@", + _network, _node[0], _node[1], _node[2], _node[3], _node[4], + _node[5], _port, _packetType, [_socket class], OFStrError(_errNo)]; } @end Index: src/exceptions/OFBindSocketFailedException.h ================================================================== --- src/exceptions/OFBindSocketFailedException.h +++ src/exceptions/OFBindSocketFailedException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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/OFBindSocketFailedException.m ================================================================== --- src/exceptions/OFBindSocketFailedException.m +++ src/exceptions/OFBindSocketFailedException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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/OFBindUNIXSocketFailedException.h ================================================================== --- src/exceptions/OFBindUNIXSocketFailedException.h +++ src/exceptions/OFBindUNIXSocketFailedException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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 @@ * @param path The path on which binding failed * @param socket The socket which could not be bound * @param errNo The errno of the error that occurred * @return A new, autoreleased bind UNIX socket failed exception */ -+ (instancetype)exceptionWithPath: (OFString *)path ++ (instancetype)exceptionWithPath: (nullable OFString *)path socket: (id)socket errNo: (int)errNo; + (instancetype)exceptionWithSocket: (id)socket errNo: (int)errNo OF_UNAVAILABLE; @@ -56,13 +56,13 @@ * @param path The path on which binding failed * @param socket The socket which could not be bound * @param errNo The errno of the error that occurred * @return An initialized bind UNIX socket failed exception */ -- (instancetype)initWithPath: (OFString *)path +- (instancetype)initWithPath: (nullable OFString *)path socket: (id)socket errNo: (int)errNo OF_DESIGNATED_INITIALIZER; - (instancetype)initWithSocket: (id)socket errNo: (int)errNo OF_UNAVAILABLE; @end OF_ASSUME_NONNULL_END Index: src/exceptions/OFBindUNIXSocketFailedException.m ================================================================== --- src/exceptions/OFBindUNIXSocketFailedException.m +++ src/exceptions/OFBindUNIXSocketFailedException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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/OFBroadcastConditionFailedException.h ================================================================== --- src/exceptions/OFBroadcastConditionFailedException.h +++ src/exceptions/OFBroadcastConditionFailedException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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/OFBroadcastConditionFailedException.m ================================================================== --- src/exceptions/OFBroadcastConditionFailedException.m +++ src/exceptions/OFBroadcastConditionFailedException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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/OFChangeCurrentDirectoryFailedException.h ================================================================== --- src/exceptions/OFChangeCurrentDirectoryFailedException.h +++ src/exceptions/OFChangeCurrentDirectoryFailedException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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/OFChangeCurrentDirectoryFailedException.m ================================================================== --- src/exceptions/OFChangeCurrentDirectoryFailedException.m +++ src/exceptions/OFChangeCurrentDirectoryFailedException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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.h ================================================================== --- src/exceptions/OFChecksumMismatchException.h +++ src/exceptions/OFChecksumMismatchException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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/OFConditionStillWaitingException.h ================================================================== --- src/exceptions/OFConditionStillWaitingException.h +++ src/exceptions/OFConditionStillWaitingException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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/OFConditionStillWaitingException.m ================================================================== --- src/exceptions/OFConditionStillWaitingException.m +++ src/exceptions/OFConditionStillWaitingException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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/OFConnectIPSocketFailedException.h ================================================================== --- src/exceptions/OFConnectIPSocketFailedException.h +++ src/exceptions/OFConnectIPSocketFailedException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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/OFConnectIPSocketFailedException.m ================================================================== --- src/exceptions/OFConnectIPSocketFailedException.m +++ src/exceptions/OFConnectIPSocketFailedException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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/OFConnectSPXSocketFailedException.h ================================================================== --- src/exceptions/OFConnectSPXSocketFailedException.h +++ src/exceptions/OFConnectSPXSocketFailedException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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/OFConnectSPXSocketFailedException.m ================================================================== --- src/exceptions/OFConnectSPXSocketFailedException.m +++ src/exceptions/OFConnectSPXSocketFailedException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -72,13 +72,13 @@ memcpy(node, _node, sizeof(_node)); } - (OFString *)description { - OFData *node = [OFData dataWithItems: _node count: sizeof(_node)]; - return [OFString stringWithFormat: - @"A connection to %@ port %" @PRIu16 @" on network %" @PRIX32 - " could not be established in socket of type %@: %@", - node, _port, _network, [_socket class], OFStrError(_errNo)]; + @"A connection to %02X:%02X:%02X:%02X:%02X:%02X port %" @PRIu16 + @" on network %" @PRIX32 " could not be established in socket of " + @"type %@: %@", + _node[0], _node[1], _node[2], _node[3], _node[4], _node[5], _port, + _network, [_socket class], OFStrError(_errNo)]; } @end Index: src/exceptions/OFConnectSocketFailedException.h ================================================================== --- src/exceptions/OFConnectSocketFailedException.h +++ src/exceptions/OFConnectSocketFailedException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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/OFConnectSocketFailedException.m ================================================================== --- src/exceptions/OFConnectSocketFailedException.m +++ src/exceptions/OFConnectSocketFailedException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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/OFConnectUNIXSocketFailedException.h ================================================================== --- src/exceptions/OFConnectUNIXSocketFailedException.h +++ src/exceptions/OFConnectUNIXSocketFailedException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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/OFConnectUNIXSocketFailedException.m ================================================================== --- src/exceptions/OFConnectUNIXSocketFailedException.m +++ src/exceptions/OFConnectUNIXSocketFailedException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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/OFCopyItemFailedException.h ================================================================== --- src/exceptions/OFCopyItemFailedException.h +++ src/exceptions/OFCopyItemFailedException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,65 +15,65 @@ #import "OFException.h" OF_ASSUME_NONNULL_BEGIN -@class OFURI; +@class OFIRI; /** * @class OFCopyItemFailedException \ * OFCopyItemFailedException.h ObjFW/OFCopyItemFailedException.h * * @brief An exception indicating that copying a item failed. */ @interface OFCopyItemFailedException: OFException { - OFURI *_sourceURI, *_destinationURI; + OFIRI *_sourceIRI, *_destinationIRI; int _errNo; OF_RESERVE_IVARS(OFCopyItemFailedException, 4) } /** - * @brief The URI of the source item. + * @brief The IRI of the source item. */ -@property (readonly, nonatomic) OFURI *sourceURI; +@property (readonly, nonatomic) OFIRI *sourceIRI; /** - * @brief The destination URI. + * @brief The destination IRI. */ -@property (readonly, nonatomic) OFURI *destinationURI; +@property (readonly, nonatomic) OFIRI *destinationIRI; /** * @brief The errno of the error that occurred. */ @property (readonly, nonatomic) int errNo; /** * @brief Creates a new, autoreleased copy item failed exception. * - * @param sourceURI The URI of the source item - * @param destinationURI The destination URI + * @param sourceIRI The IRI of the source item + * @param destinationIRI The destination IRI * @param errNo The errno of the error that occurred * @return A new, autoreleased copy item failed exception */ -+ (instancetype)exceptionWithSourceURI: (OFURI *)sourceURI - destinationURI: (OFURI *)destinationURI ++ (instancetype)exceptionWithSourceIRI: (OFIRI *)sourceIRI + destinationIRI: (OFIRI *)destinationIRI errNo: (int)errNo; + (instancetype)exception OF_UNAVAILABLE; /** * @brief Initializes an already allocated copy item failed exception. * - * @param sourceURI The URI of the source item - * @param destinationURI The destination URI + * @param sourceIRI The IRI of the source item + * @param destinationIRI The destination IRI * @param errNo The errno of the error that occurred * @return An initialized copy item failed exception */ -- (instancetype)initWithSourceURI: (OFURI *)sourceURI - destinationURI: (OFURI *)destinationURI +- (instancetype)initWithSourceIRI: (OFIRI *)sourceIRI + destinationIRI: (OFIRI *)destinationIRI errNo: (int)errNo OF_DESIGNATED_INITIALIZER; - (instancetype)init OF_UNAVAILABLE; @end OF_ASSUME_NONNULL_END Index: src/exceptions/OFCopyItemFailedException.m ================================================================== --- src/exceptions/OFCopyItemFailedException.m +++ src/exceptions/OFCopyItemFailedException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,45 +14,45 @@ */ #include "config.h" #import "OFCopyItemFailedException.h" +#import "OFIRI.h" #import "OFString.h" -#import "OFURI.h" @implementation OFCopyItemFailedException -@synthesize sourceURI = _sourceURI, destinationURI = _destinationURI; +@synthesize sourceIRI = _sourceIRI, destinationIRI = _destinationIRI; @synthesize errNo = _errNo; + (instancetype)exception { OF_UNRECOGNIZED_SELECTOR } -+ (instancetype)exceptionWithSourceURI: (OFURI *)sourceURI - destinationURI: (OFURI *)destinationURI ++ (instancetype)exceptionWithSourceIRI: (OFIRI *)sourceIRI + destinationIRI: (OFIRI *)destinationIRI errNo: (int)errNo { - return [[[self alloc] initWithSourceURI: sourceURI - destinationURI: destinationURI + return [[[self alloc] initWithSourceIRI: sourceIRI + destinationIRI: destinationIRI errNo: errNo] autorelease]; } - (instancetype)init { OF_INVALID_INIT_METHOD } -- (instancetype)initWithSourceURI: (OFURI *)sourceURI - destinationURI: (OFURI *)destinationURI +- (instancetype)initWithSourceIRI: (OFIRI *)sourceIRI + destinationIRI: (OFIRI *)destinationIRI errNo: (int)errNo { self = [super init]; @try { - _sourceURI = [sourceURI copy]; - _destinationURI = [destinationURI copy]; + _sourceIRI = [sourceIRI copy]; + _destinationIRI = [destinationIRI copy]; _errNo = errNo; } @catch (id e) { [self release]; @throw e; } @@ -60,17 +60,17 @@ return self; } - (void)dealloc { - [_sourceURI release]; - [_destinationURI release]; + [_sourceIRI release]; + [_destinationIRI release]; [super dealloc]; } - (OFString *)description { return [OFString stringWithFormat: @"Failed to copy item %@ to %@: %@", - _sourceURI, _destinationURI, OFStrError(_errNo)]; + _sourceIRI, _destinationIRI, OFStrError(_errNo)]; } @end Index: src/exceptions/OFCreateDirectoryFailedException.h ================================================================== --- src/exceptions/OFCreateDirectoryFailedException.h +++ src/exceptions/OFCreateDirectoryFailedException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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 "OFException.h" OF_ASSUME_NONNULL_BEGIN -@class OFURI; +@class OFIRI; /** * @class OFCreateDirectoryFailedException \ * OFCreateDirectoryFailedException.h \ * ObjFW/OFCreateDirectoryFailedException.h @@ -26,45 +26,45 @@ * * @brief An exception indicating a directory couldn't be created. */ @interface OFCreateDirectoryFailedException: OFException { - OFURI *_URI; + OFIRI *_IRI; int _errNo; OF_RESERVE_IVARS(OFCreateDirectoryFailedException, 4) } /** - * @brief The URI of the directory which couldn't be created. + * @brief The IRI of the directory which couldn't be created. */ -@property (readonly, nonatomic) OFURI *URI; +@property (readonly, nonatomic) OFIRI *IRI; /** * @brief The errno of the error that occurred. */ @property (readonly, nonatomic) int errNo; /** * @brief Creates a new, autoreleased create directory failed exception. * - * @param URI The URI of the directory which could not be created + * @param IRI The IRI of the directory which could not be created * @param errNo The errno of the error that occurred * @return A new, autoreleased create directory failed exception */ -+ (instancetype)exceptionWithURI: (OFURI *)URI errNo: (int)errNo; ++ (instancetype)exceptionWithIRI: (OFIRI *)IRI errNo: (int)errNo; + (instancetype)exception OF_UNAVAILABLE; /** * @brief Initializes an already allocated create directory failed exception. * - * @param URI The URI of the directory which could not be created + * @param IRI The IRI of the directory which could not be created * @param errNo The errno of the error that occurred * @return An initialized create directory failed exception */ -- (instancetype)initWithURI: (OFURI *)URI +- (instancetype)initWithIRI: (OFIRI *)IRI errNo: (int)errNo OF_DESIGNATED_INITIALIZER; - (instancetype)init OF_UNAVAILABLE; @end OF_ASSUME_NONNULL_END Index: src/exceptions/OFCreateDirectoryFailedException.m ================================================================== --- src/exceptions/OFCreateDirectoryFailedException.m +++ src/exceptions/OFCreateDirectoryFailedException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,37 +14,37 @@ */ #include "config.h" #import "OFCreateDirectoryFailedException.h" +#import "OFIRI.h" #import "OFString.h" -#import "OFURI.h" @implementation OFCreateDirectoryFailedException -@synthesize URI = _URI, errNo = _errNo; +@synthesize IRI = _IRI, errNo = _errNo; + (instancetype)exception { OF_UNRECOGNIZED_SELECTOR } -+ (instancetype)exceptionWithURI: (OFURI *)URI errNo: (int)errNo ++ (instancetype)exceptionWithIRI: (OFIRI *)IRI errNo: (int)errNo { - return [[[self alloc] initWithURI: URI errNo: errNo] autorelease]; + return [[[self alloc] initWithIRI: IRI errNo: errNo] autorelease]; } - (instancetype)init { OF_INVALID_INIT_METHOD } -- (instancetype)initWithURI: (OFURI *)URI errNo: (int)errNo +- (instancetype)initWithIRI: (OFIRI *)IRI errNo: (int)errNo { self = [super init]; @try { - _URI = [URI copy]; + _IRI = [IRI copy]; _errNo = errNo; } @catch (id e) { [self release]; @throw e; } @@ -52,16 +52,16 @@ return self; } - (void)dealloc { - [_URI release]; + [_IRI release]; [super dealloc]; } - (OFString *)description { return [OFString stringWithFormat: - @"Failed to create directory %@: %@", _URI, OFStrError(_errNo)]; + @"Failed to create directory %@: %@", _IRI, OFStrError(_errNo)]; } @end Index: src/exceptions/OFCreateSymbolicLinkFailedException.h ================================================================== --- src/exceptions/OFCreateSymbolicLinkFailedException.h +++ src/exceptions/OFCreateSymbolicLinkFailedException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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 "OFException.h" OF_ASSUME_NONNULL_BEGIN -@class OFURI; +@class OFIRI; /** * @class OFCreateSymbolicLinkFailedException \ * OFCreateSymbolicLinkFailedException.h \ * ObjFW/OFCreateSymbolicLinkFailedException.h @@ -26,20 +26,20 @@ * * @brief An exception indicating that creating a symbolic link failed. */ @interface OFCreateSymbolicLinkFailedException: OFException { - OFURI *_URI; + OFIRI *_IRI; OFString *_target; int _errNo; OF_RESERVE_IVARS(OFCreateSymbolicLinkFailedException, 4) } /** - * @brief The URI at which the symlink should have been created. + * @brief The IRI at which the symlink should have been created. */ -@property (readonly, nonatomic) OFURI *URI; +@property (readonly, nonatomic) OFIRI *IRI; /** * @brief The target for the symlink. */ @property (readonly, nonatomic) OFString *target; @@ -50,33 +50,33 @@ @property (readonly, nonatomic) int errNo; /** * @brief Creates a new, autoreleased create symbolic link failed exception. * - * @param URI The URI where the symlink should have been created + * @param IRI The IRI where the symlink should have been created * @param target The target for the symbolic link * @param errNo The errno of the error that occurred * @return A new, autoreleased create symbolic link failed exception */ -+ (instancetype)exceptionWithURI: (OFURI *)URI ++ (instancetype)exceptionWithIRI: (OFIRI *)IRI target: (OFString *)target errNo: (int)errNo; + (instancetype)exception OF_UNAVAILABLE; /** * @brief Initializes an already allocated create symbolic link failed * exception. * - * @param URI The URI where the symlink should have been created + * @param IRI The IRI where the symlink should have been created * @param target The target for the symbolic link * @param errNo The errno of the error that occurred * @return An initialized create symbolic link failed exception */ -- (instancetype)initWithURI: (OFURI *)URI +- (instancetype)initWithIRI: (OFIRI *)IRI target: (OFString *)target errNo: (int)errNo OF_DESIGNATED_INITIALIZER; - (instancetype)init OF_UNAVAILABLE; @end OF_ASSUME_NONNULL_END Index: src/exceptions/OFCreateSymbolicLinkFailedException.m ================================================================== --- src/exceptions/OFCreateSymbolicLinkFailedException.m +++ src/exceptions/OFCreateSymbolicLinkFailedException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,43 +14,43 @@ */ #include "config.h" #import "OFCreateSymbolicLinkFailedException.h" +#import "OFIRI.h" #import "OFString.h" -#import "OFURI.h" @implementation OFCreateSymbolicLinkFailedException -@synthesize URI = _URI, target = _target, errNo = _errNo; +@synthesize IRI = _IRI, target = _target, errNo = _errNo; + (instancetype)exception { OF_UNRECOGNIZED_SELECTOR } -+ (instancetype)exceptionWithURI: (OFURI *)URI ++ (instancetype)exceptionWithIRI: (OFIRI *)IRI target: (OFString *)target errNo: (int)errNo { - return [[[self alloc] initWithURI: URI + return [[[self alloc] initWithIRI: IRI target: target errNo: errNo] autorelease]; } - (instancetype)init { OF_INVALID_INIT_METHOD } -- (instancetype)initWithURI: (OFURI *)URI +- (instancetype)initWithIRI: (OFIRI *)IRI target: (OFString *)target errNo: (int)errNo { self = [super init]; @try { - _URI = [URI copy]; + _IRI = [IRI copy]; _target = [target copy]; _errNo = errNo; } @catch (id e) { [self release]; @throw e; @@ -59,18 +59,18 @@ return self; } - (void)dealloc { - [_URI release]; + [_IRI release]; [_target release]; [super dealloc]; } - (OFString *)description { return [OFString stringWithFormat: @"Failed to create symbolic link %@ with target %@: %@", - _URI, _target, OFStrError(_errNo)]; + _IRI, _target, OFStrError(_errNo)]; } @end Index: src/exceptions/OFCreateWindowsRegistryKeyFailedException.h ================================================================== --- src/exceptions/OFCreateWindowsRegistryKeyFailedException.h +++ src/exceptions/OFCreateWindowsRegistryKeyFailedException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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.m ================================================================== --- src/exceptions/OFDNSQueryFailedException.m +++ src/exceptions/OFDNSQueryFailedException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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.h ================================================================== --- src/exceptions/OFDeleteWindowsRegistryKeyFailedException.h +++ src/exceptions/OFDeleteWindowsRegistryKeyFailedException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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.m ================================================================== --- src/exceptions/OFEnumerationMutationException.m +++ src/exceptions/OFEnumerationMutationException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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.m ================================================================== --- src/exceptions/OFException.m +++ src/exceptions/OFException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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/OFGetCurrentDirectoryFailedException.h ================================================================== --- src/exceptions/OFGetCurrentDirectoryFailedException.h +++ src/exceptions/OFGetCurrentDirectoryFailedException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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/OFGetCurrentDirectoryFailedException.m ================================================================== --- src/exceptions/OFGetCurrentDirectoryFailedException.m +++ src/exceptions/OFGetCurrentDirectoryFailedException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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/OFGetItemAttributesFailedException.h ================================================================== --- src/exceptions/OFGetItemAttributesFailedException.h +++ src/exceptions/OFGetItemAttributesFailedException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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 "OFException.h" OF_ASSUME_NONNULL_BEGIN -@class OFURI; +@class OFIRI; /** * @class OFGetItemAttributesFailedException \ * OFGetItemAttributesFailedException.h \ * ObjFW/OFGetItemAttributesFailedException.h @@ -26,46 +26,46 @@ * * @brief An exception indicating an item's attributes could not be retrieved. */ @interface OFGetItemAttributesFailedException: OFException { - OFURI *_URI; + OFIRI *_IRI; int _errNo; OF_RESERVE_IVARS(OFGetItemAttributesFailedException, 4) } /** - * @brief The URI of the item whose attributes could not be retrieved. + * @brief The IRI of the item whose attributes could not be retrieved. */ -@property (readonly, nonatomic) OFURI *URI; +@property (readonly, nonatomic) OFIRI *IRI; /** * @brief The errno of the error that occurred. */ @property (readonly, nonatomic) int errNo; /** * @brief Creates a new, autoreleased retrieve item attributes failed exception. * - * @param URI The URI of the item whose attributes could not be retrieved + * @param IRI The IRI of the item whose attributes could not be retrieved * @param errNo The errno of the error that occurred * @return A new, autoreleased retrieve item attributes failed exception */ -+ (instancetype)exceptionWithURI: (OFURI *)URI errNo: (int)errNo; ++ (instancetype)exceptionWithIRI: (OFIRI *)IRI errNo: (int)errNo; + (instancetype)exception OF_UNAVAILABLE; /** * @brief Initializes an already allocated retrieve item attributes failed * exception. * - * @param URI The URI of the item whose attributes could not be retrieved + * @param IRI The IRI of the item whose attributes could not be retrieved * @param errNo The errno of the error that occurred * @return An initialized retrieve item attributes failed exception */ -- (instancetype)initWithURI: (OFURI *)URI +- (instancetype)initWithIRI: (OFIRI *)IRI errNo: (int)errNo OF_DESIGNATED_INITIALIZER; - (instancetype)init OF_UNAVAILABLE; @end OF_ASSUME_NONNULL_END Index: src/exceptions/OFGetItemAttributesFailedException.m ================================================================== --- src/exceptions/OFGetItemAttributesFailedException.m +++ src/exceptions/OFGetItemAttributesFailedException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,37 +14,37 @@ */ #include "config.h" #import "OFGetItemAttributesFailedException.h" +#import "OFIRI.h" #import "OFString.h" -#import "OFURI.h" @implementation OFGetItemAttributesFailedException -@synthesize URI = _URI, errNo = _errNo; +@synthesize IRI = _IRI, errNo = _errNo; + (instancetype)exception { OF_UNRECOGNIZED_SELECTOR } -+ (instancetype)exceptionWithURI: (OFURI *)URI errNo: (int)errNo ++ (instancetype)exceptionWithIRI: (OFIRI *)IRI errNo: (int)errNo { - return [[[self alloc] initWithURI: URI errNo: errNo] autorelease]; + return [[[self alloc] initWithIRI: IRI errNo: errNo] autorelease]; } - (instancetype)init { OF_INVALID_INIT_METHOD } -- (instancetype)initWithURI: (OFURI *)URI errNo: (int)errNo +- (instancetype)initWithIRI: (OFIRI *)IRI errNo: (int)errNo { self = [super init]; @try { - _URI = [URI copy]; + _IRI = [IRI copy]; _errNo = errNo; } @catch (id e) { [self release]; @throw e; } @@ -52,17 +52,17 @@ return self; } - (void)dealloc { - [_URI release]; + [_IRI release]; [super dealloc]; } - (OFString *)description { return [OFString stringWithFormat: @"Failed to get attributes for item %@: %@", - _URI, OFStrError(_errNo)]; + _IRI, OFStrError(_errNo)]; } @end Index: src/exceptions/OFGetOptionFailedException.h ================================================================== --- src/exceptions/OFGetOptionFailedException.h +++ src/exceptions/OFGetOptionFailedException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -23,19 +23,19 @@ * * @brief An exception indicating that getting an option for an object failed. */ @interface OFGetOptionFailedException: OFException { - id _object; + id _Nullable _object; int _errNo; OF_RESERVE_IVARS(OFGetOptionFailedException, 4) } /** * @brief The object for which the option could not be retrieved. */ -@property (readonly, nonatomic) id object; +@property OF_NULLABLE_PROPERTY (readonly, nonatomic) id object; /** * @brief The errno of the error that occurred. */ @property (readonly, nonatomic) int errNo; @@ -45,11 +45,11 @@ * * @param object The object for which the option could not be retrieved * @param errNo The errno of the error that occurred * @return A new, autoreleased get option failed exception */ -+ (instancetype)exceptionWithObject: (id)object errNo: (int)errNo; ++ (instancetype)exceptionWithObject: (nullable id)object errNo: (int)errNo; + (instancetype)exception OF_UNAVAILABLE; /** * @brief Initializes an already allocated get option failed exception. @@ -56,12 +56,12 @@ * * @param object The object for which the option could not be retrieved * @param errNo The errno of the error that occurred * @return An initialized get option failed exception */ -- (instancetype)initWithObject: (id)object +- (instancetype)initWithObject: (nullable id)object errNo: (int)errNo OF_DESIGNATED_INITIALIZER; - (instancetype)init OF_UNAVAILABLE; @end OF_ASSUME_NONNULL_END Index: src/exceptions/OFGetOptionFailedException.m ================================================================== --- src/exceptions/OFGetOptionFailedException.m +++ src/exceptions/OFGetOptionFailedException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,10 +53,14 @@ [super dealloc]; } - (OFString *)description { - return [OFString stringWithFormat: - @"Getting an option in an object of type %@ failed: %@", - [_object class], OFStrError(_errNo)]; + if (_object != nil) + return [OFString stringWithFormat: + @"Getting an option in an object of type %@ failed: %@", + [_object class], OFStrError(_errNo)]; + else + return [OFString stringWithFormat: + @"Getting an option failed: %@", OFStrError(_errNo)]; } @end Index: src/exceptions/OFGetWindowsRegistryValueFailedException.h ================================================================== --- src/exceptions/OFGetWindowsRegistryValueFailedException.h +++ src/exceptions/OFGetWindowsRegistryValueFailedException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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.m ================================================================== --- src/exceptions/OFGetWindowsRegistryValueFailedException.m +++ src/exceptions/OFGetWindowsRegistryValueFailedException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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/OFHTTPRequestFailedException.h ================================================================== --- src/exceptions/OFHTTPRequestFailedException.h +++ src/exceptions/OFHTTPRequestFailedException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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/OFHTTPRequestFailedException.m ================================================================== --- src/exceptions/OFHTTPRequestFailedException.m +++ src/exceptions/OFHTTPRequestFailedException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -59,12 +59,12 @@ [super dealloc]; } - (OFString *)description { - const char *method = OFHTTPRequestMethodName(_request.method); + OFString *method = OFHTTPRequestMethodString(_request.method); return [OFString stringWithFormat: - @"An HTTP %s request with URI %@ failed with code %hd!", method, - _request.URI, _response.statusCode]; + @"An HTTP %@ request with IRI %@ failed with code %hd!", method, + _request.IRI, _response.statusCode]; } @end Index: src/exceptions/OFHashAlreadyCalculatedException.h ================================================================== --- src/exceptions/OFHashAlreadyCalculatedException.h +++ src/exceptions/OFHashAlreadyCalculatedException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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/OFHashAlreadyCalculatedException.m ================================================================== --- src/exceptions/OFHashAlreadyCalculatedException.m +++ src/exceptions/OFHashAlreadyCalculatedException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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/OFHashNotCalculatedException.h ================================================================== --- src/exceptions/OFHashNotCalculatedException.h +++ src/exceptions/OFHashNotCalculatedException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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/OFHashNotCalculatedException.m ================================================================== --- src/exceptions/OFHashNotCalculatedException.m +++ src/exceptions/OFHashNotCalculatedException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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.h ================================================================== --- src/exceptions/OFInitializationFailedException.h +++ src/exceptions/OFInitializationFailedException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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.m ================================================================== --- src/exceptions/OFInvalidJSONException.m +++ src/exceptions/OFInvalidJSONException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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/OFInvalidServerResponseException.h ================================================================== --- src/exceptions/OFInvalidServerResponseException.h +++ src/exceptions/OFInvalidServerResponseException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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/OFInvalidServerResponseException.m ================================================================== --- src/exceptions/OFInvalidServerResponseException.m +++ src/exceptions/OFInvalidServerResponseException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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/OFJoinThreadFailedException.h ================================================================== --- src/exceptions/OFJoinThreadFailedException.h +++ src/exceptions/OFJoinThreadFailedException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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/OFJoinThreadFailedException.m ================================================================== --- src/exceptions/OFJoinThreadFailedException.m +++ src/exceptions/OFJoinThreadFailedException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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/OFLinkItemFailedException.h ================================================================== --- src/exceptions/OFLinkItemFailedException.h +++ src/exceptions/OFLinkItemFailedException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,65 +15,65 @@ #import "OFException.h" OF_ASSUME_NONNULL_BEGIN -@class OFURI; +@class OFIRI; /** * @class OFLinkItemFailedException \ * OFLinkItemFailedException.h ObjFW/OFLinkItemFailedException.h * * @brief An exception indicating that creating a link failed. */ @interface OFLinkItemFailedException: OFException { - OFURI *_sourceURI, *_destinationURI; + OFIRI *_sourceIRI, *_destinationIRI; int _errNo; OF_RESERVE_IVARS(OFLinkItemFailedException, 4) } /** - * @brief A URI with the source for the link. + * @brief An IRI with the source for the link. */ -@property (readonly, nonatomic) OFURI *sourceURI; +@property (readonly, nonatomic) OFIRI *sourceIRI; /** - * @brief A URI with the destination for the link. + * @brief An IRI with the destination for the link. */ -@property (readonly, nonatomic) OFURI *destinationURI; +@property (readonly, nonatomic) OFIRI *destinationIRI; /** * @brief The errno of the error that occurred. */ @property (readonly, nonatomic) int errNo; /** * @brief Creates a new, autoreleased link failed exception. * - * @param sourceURI The source for the link - * @param destinationURI The destination for the link + * @param sourceIRI The source for the link + * @param destinationIRI The destination for the link * @param errNo The errno of the error that occurred * @return A new, autoreleased link failed exception */ -+ (instancetype)exceptionWithSourceURI: (OFURI *)sourceURI - destinationURI: (OFURI *)destinationURI ++ (instancetype)exceptionWithSourceIRI: (OFIRI *)sourceIRI + destinationIRI: (OFIRI *)destinationIRI errNo: (int)errNo; + (instancetype)exception OF_UNAVAILABLE; /** * @brief Initializes an already allocated link failed exception. * - * @param sourceURI The source for the link - * @param destinationURI The destination for the link + * @param sourceIRI The source for the link + * @param destinationIRI The destination for the link * @param errNo The errno of the error that occurred * @return An initialized link failed exception */ -- (instancetype)initWithSourceURI: (OFURI*)sourceURI - destinationURI: (OFURI *)destinationURI +- (instancetype)initWithSourceIRI: (OFIRI*)sourceIRI + destinationIRI: (OFIRI *)destinationIRI errNo: (int)errNo OF_DESIGNATED_INITIALIZER; - (instancetype)init OF_UNAVAILABLE; @end OF_ASSUME_NONNULL_END Index: src/exceptions/OFLinkItemFailedException.m ================================================================== --- src/exceptions/OFLinkItemFailedException.m +++ src/exceptions/OFLinkItemFailedException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,45 +14,45 @@ */ #include "config.h" #import "OFLinkItemFailedException.h" +#import "OFIRI.h" #import "OFString.h" -#import "OFURI.h" @implementation OFLinkItemFailedException -@synthesize sourceURI = _sourceURI, destinationURI = _destinationURI; +@synthesize sourceIRI = _sourceIRI, destinationIRI = _destinationIRI; @synthesize errNo = _errNo; + (instancetype)exception { OF_UNRECOGNIZED_SELECTOR } -+ (instancetype)exceptionWithSourceURI: (OFURI *)sourceURI - destinationURI: (OFURI *)destinationURI ++ (instancetype)exceptionWithSourceIRI: (OFIRI *)sourceIRI + destinationIRI: (OFIRI *)destinationIRI errNo: (int)errNo { - return [[[self alloc] initWithSourceURI: sourceURI - destinationURI: destinationURI + return [[[self alloc] initWithSourceIRI: sourceIRI + destinationIRI: destinationIRI errNo: errNo] autorelease]; } - (instancetype)init { OF_INVALID_INIT_METHOD } -- (instancetype)initWithSourceURI: (OFURI *)sourceURI - destinationURI: (OFURI *)destinationURI +- (instancetype)initWithSourceIRI: (OFIRI *)sourceIRI + destinationIRI: (OFIRI *)destinationIRI errNo: (int)errNo { self = [super init]; @try { - _sourceURI = [sourceURI copy]; - _destinationURI = [destinationURI copy]; + _sourceIRI = [sourceIRI copy]; + _destinationIRI = [destinationIRI copy]; _errNo = errNo; } @catch (id e) { [self release]; @throw e; } @@ -60,17 +60,17 @@ return self; } - (void)dealloc { - [_sourceURI release]; - [_destinationURI release]; + [_sourceIRI release]; + [_destinationIRI release]; [super dealloc]; } - (OFString *)description { return [OFString stringWithFormat: @"Failed to link file %@ to %@: %@", - _sourceURI, _destinationURI, OFStrError(_errNo)]; + _sourceIRI, _destinationIRI, OFStrError(_errNo)]; } @end Index: src/exceptions/OFListenOnSocketFailedException.h ================================================================== --- src/exceptions/OFListenOnSocketFailedException.h +++ src/exceptions/OFListenOnSocketFailedException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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/OFListenOnSocketFailedException.m ================================================================== --- src/exceptions/OFListenOnSocketFailedException.m +++ src/exceptions/OFListenOnSocketFailedException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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.m ================================================================== --- src/exceptions/OFLoadPluginFailedException.m +++ src/exceptions/OFLoadPluginFailedException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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/OFLockFailedException.h ================================================================== --- src/exceptions/OFLockFailedException.h +++ src/exceptions/OFLockFailedException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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/OFLockFailedException.m ================================================================== --- src/exceptions/OFLockFailedException.m +++ src/exceptions/OFLockFailedException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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.h ================================================================== --- src/exceptions/OFMalformedXMLException.h +++ src/exceptions/OFMalformedXMLException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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/OFMoveItemFailedException.h ================================================================== --- src/exceptions/OFMoveItemFailedException.h +++ src/exceptions/OFMoveItemFailedException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,65 +15,65 @@ #import "OFException.h" OF_ASSUME_NONNULL_BEGIN -@class OFURI; +@class OFIRI; /** * @class OFMoveItemFailedException \ * OFMoveItemFailedException.h ObjFW/OFMoveItemFailedException.h * * @brief An exception indicating that moving an item failed. */ @interface OFMoveItemFailedException: OFException { - OFURI *_sourceURI, *_destinationURI; + OFIRI *_sourceIRI, *_destinationIRI; int _errNo; OF_RESERVE_IVARS(OFMoveItemFailedException, 4) } /** - * @brief The original URI. + * @brief The original IRI. */ -@property (readonly, nonatomic) OFURI *sourceURI; +@property (readonly, nonatomic) OFIRI *sourceIRI; /** - * @brief The new URI. + * @brief The new IRI. */ -@property (readonly, nonatomic) OFURI *destinationURI; +@property (readonly, nonatomic) OFIRI *destinationIRI; /** * @brief The errno of the error that occurred. */ @property (readonly, nonatomic) int errNo; /** * @brief Creates a new, autoreleased move item failed exception. * - * @param sourceURI The original URI - * @param destinationURI The new URI + * @param sourceIRI The original IRI + * @param destinationIRI The new IRI * @param errNo The errno of the error that occurred * @return A new, autoreleased move item failed exception */ -+ (instancetype)exceptionWithSourceURI: (OFURI *)sourceURI - destinationURI: (OFURI *)destinationURI ++ (instancetype)exceptionWithSourceIRI: (OFIRI *)sourceIRI + destinationIRI: (OFIRI *)destinationIRI errNo: (int)errNo; + (instancetype)exception OF_UNAVAILABLE; /** * @brief Initializes an already allocated move item failed exception. * - * @param sourceURI The original URI - * @param destinationURI The new URI + * @param sourceIRI The original IRI + * @param destinationIRI The new IRI * @param errNo The errno of the error that occurred * @return An initialized move item failed exception */ -- (instancetype)initWithSourceURI: (OFURI *)sourceURI - destinationURI: (OFURI *)destinationURI +- (instancetype)initWithSourceIRI: (OFIRI *)sourceIRI + destinationIRI: (OFIRI *)destinationIRI errNo: (int)errNo OF_DESIGNATED_INITIALIZER; - (instancetype)init OF_UNAVAILABLE; @end OF_ASSUME_NONNULL_END Index: src/exceptions/OFMoveItemFailedException.m ================================================================== --- src/exceptions/OFMoveItemFailedException.m +++ src/exceptions/OFMoveItemFailedException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,45 +14,45 @@ */ #include "config.h" #import "OFMoveItemFailedException.h" +#import "OFIRI.h" #import "OFString.h" -#import "OFURI.h" @implementation OFMoveItemFailedException -@synthesize sourceURI = _sourceURI, destinationURI = _destinationURI; +@synthesize sourceIRI = _sourceIRI, destinationIRI = _destinationIRI; @synthesize errNo = _errNo; + (instancetype)exception { OF_UNRECOGNIZED_SELECTOR } -+ (instancetype)exceptionWithSourceURI: (OFURI *)sourceURI - destinationURI: (OFURI *)destinationURI ++ (instancetype)exceptionWithSourceIRI: (OFIRI *)sourceIRI + destinationIRI: (OFIRI *)destinationIRI errNo: (int)errNo { - return [[[self alloc] initWithSourceURI: sourceURI - destinationURI: destinationURI + return [[[self alloc] initWithSourceIRI: sourceIRI + destinationIRI: destinationIRI errNo: errNo] autorelease]; } - (instancetype)init { OF_INVALID_INIT_METHOD } -- (instancetype)initWithSourceURI: (OFURI *)sourceURI - destinationURI: (OFURI *)destinationURI +- (instancetype)initWithSourceIRI: (OFIRI *)sourceIRI + destinationIRI: (OFIRI *)destinationIRI errNo: (int)errNo { self = [super init]; @try { - _sourceURI = [sourceURI copy]; - _destinationURI = [destinationURI copy]; + _sourceIRI = [sourceIRI copy]; + _destinationIRI = [destinationIRI copy]; _errNo = errNo; } @catch (id e) { [self release]; @throw e; } @@ -60,18 +60,18 @@ return self; } - (void)dealloc { - [_sourceURI release]; - [_destinationURI release]; + [_sourceIRI release]; + [_destinationIRI release]; [super dealloc]; } - (OFString *)description { return [OFString stringWithFormat: @"Failed to move item at %@ to %@: %@", - _sourceURI, _destinationURI, OFStrError(_errNo)]; + _sourceIRI, _destinationIRI, OFStrError(_errNo)]; } @end Index: src/exceptions/OFNotImplementedException.h ================================================================== --- src/exceptions/OFNotImplementedException.h +++ src/exceptions/OFNotImplementedException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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.m ================================================================== --- src/exceptions/OFNotImplementedException.m +++ src/exceptions/OFNotImplementedException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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.m ================================================================== --- src/exceptions/OFNotOpenException.m +++ src/exceptions/OFNotOpenException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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/OFObserveKernelEventsFailedException.h ================================================================== --- src/exceptions/OFObserveKernelEventsFailedException.h +++ src/exceptions/OFObserveKernelEventsFailedException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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/OFObserveKernelEventsFailedException.m ================================================================== --- src/exceptions/OFObserveKernelEventsFailedException.m +++ src/exceptions/OFObserveKernelEventsFailedException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,31 +15,31 @@ #import "OFException.h" OF_ASSUME_NONNULL_BEGIN -@class OFURI; +@class OFIRI; /** * @class OFOpenItemFailedException \ * OFOpenItemFailedException.h ObjFW/OFOpenItemFailedException.h * * @brief An exception indicating an item could not be opened. */ @interface OFOpenItemFailedException: OFException { - OFURI *_Nullable _URI; + OFIRI *_Nullable _IRI; OFString *_Nullable _path; OFString *_mode; int _errNo; OF_RESERVE_IVARS(OFOpenItemFailedException, 4) } /** - * @brief The URI of the item which could not be opened. + * @brief The IRI of the item which could not be opened. */ -@property OF_NULLABLE_PROPERTY (readonly, nonatomic) OFURI *URI; +@property OF_NULLABLE_PROPERTY (readonly, nonatomic) OFIRI *IRI; /** * @brief The path of the item which could not be opened. */ @property OF_NULLABLE_PROPERTY (readonly, nonatomic) OFString *path; @@ -55,16 +55,16 @@ @property (readonly, nonatomic) int errNo; /** * @brief Creates a new, autoreleased open item failed exception. * - * @param URI The URI of the item which could not be opened + * @param IRI The IRI of the item which could not be opened * @param mode A string with the mode in which the item should have been opened * @param errNo The errno of the error that occurred * @return A new, autoreleased open item failed exception */ -+ (instancetype)exceptionWithURI: (OFURI *)URI ++ (instancetype)exceptionWithIRI: (OFIRI *)IRI mode: (nullable OFString *)mode errNo: (int)errNo; /** * @brief Creates a new, autoreleased open item failed exception. @@ -81,16 +81,16 @@ + (instancetype)exception OF_UNAVAILABLE; /** * @brief Initializes an already allocated open item failed exception. * - * @param URI The URI of the item which could not be opened + * @param IRI The IRI of the item which could not be opened * @param mode A string with the mode in which the item should have been opened * @param errNo The errno of the error that occurred * @return An initialized open item failed exception */ -- (instancetype)initWithURI: (OFURI *)URI +- (instancetype)initWithIRI: (OFIRI *)IRI mode: (nullable OFString *)mode errNo: (int)errNo; /** * @brief Initializes an already allocated open item failed exception. Index: src/exceptions/OFOpenItemFailedException.m ================================================================== --- src/exceptions/OFOpenItemFailedException.m +++ src/exceptions/OFOpenItemFailedException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,21 +14,21 @@ */ #include "config.h" #import "OFOpenItemFailedException.h" +#import "OFIRI.h" #import "OFString.h" -#import "OFURI.h" @implementation OFOpenItemFailedException -@synthesize URI = _URI, path = _path, mode = _mode, errNo = _errNo; +@synthesize IRI = _IRI, path = _path, mode = _mode, errNo = _errNo; -+ (instancetype)exceptionWithURI: (OFURI *)URI ++ (instancetype)exceptionWithIRI: (OFIRI *)IRI mode: (OFString *)mode errNo: (int)errNo { - return [[[self alloc] initWithURI: URI + return [[[self alloc] initWithIRI: IRI mode: mode errNo: errNo] autorelease]; } + (instancetype)exceptionWithPath: (OFString *)path @@ -43,18 +43,18 @@ + (instancetype)exception { OF_UNRECOGNIZED_SELECTOR } -- (instancetype)initWithURI: (OFURI *)URI +- (instancetype)initWithIRI: (OFIRI *)IRI mode: (OFString *)mode errNo: (int)errNo { self = [super init]; @try { - _URI = [URI copy]; + _IRI = [IRI copy]; _mode = [mode copy]; _errNo = errNo; } @catch (id e) { [self release]; @throw e; @@ -86,11 +86,11 @@ OF_INVALID_INIT_METHOD } - (void)dealloc { - [_URI release]; + [_IRI release]; [_path release]; [_mode release]; [super dealloc]; } @@ -97,12 +97,12 @@ - (OFString *)description { id item = nil; - if (_URI != nil) - item = _URI; + if (_IRI != nil) + item = _IRI; else if (_path != nil) item = _path; if (_mode != nil) return [OFString stringWithFormat: Index: src/exceptions/OFOpenWindowsRegistryKeyFailedException.h ================================================================== --- src/exceptions/OFOpenWindowsRegistryKeyFailedException.h +++ src/exceptions/OFOpenWindowsRegistryKeyFailedException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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/OFOpenWindowsRegistryKeyFailedException.m ================================================================== --- src/exceptions/OFOpenWindowsRegistryKeyFailedException.m +++ src/exceptions/OFOpenWindowsRegistryKeyFailedException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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.h ================================================================== --- src/exceptions/OFOutOfMemoryException.h +++ src/exceptions/OFOutOfMemoryException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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.h ================================================================== --- src/exceptions/OFReadOrWriteFailedException.h +++ src/exceptions/OFReadOrWriteFailedException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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/OFRemoveItemFailedException.h ================================================================== --- src/exceptions/OFRemoveItemFailedException.h +++ src/exceptions/OFRemoveItemFailedException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,55 +15,55 @@ #import "OFException.h" OF_ASSUME_NONNULL_BEGIN -@class OFURI; +@class OFIRI; /** * @class OFRemoveItemFailedException \ * OFRemoveItemFailedException.h ObjFW/OFRemoveItemFailedException.h * * @brief An exception indicating that removing an item failed. */ @interface OFRemoveItemFailedException: OFException { - OFURI *_URI; + OFIRI *_IRI; int _errNo; OF_RESERVE_IVARS(OFRemoveItemFailedException, 4) } /** - * @brief The URI of the item which could not be removed. + * @brief The IRI of the item which could not be removed. */ -@property (readonly, nonatomic) OFURI *URI; +@property (readonly, nonatomic) OFIRI *IRI; /** * @brief The errno of the error that occurred. */ @property (readonly, nonatomic) int errNo; /** * @brief Creates a new, autoreleased remove failed exception. * - * @param URI The URI of the item which could not be removed + * @param IRI The IRI of the item which could not be removed * @param errNo The errno of the error that occurred * @return A new, autoreleased remove item failed exception */ -+ (instancetype)exceptionWithURI: (OFURI *)URI errNo: (int)errNo; ++ (instancetype)exceptionWithIRI: (OFIRI *)IRI errNo: (int)errNo; + (instancetype)exception OF_UNAVAILABLE; /** * @brief Initializes an already allocated remove failed exception. * - * @param URI The URI of the item which could not be removed + * @param IRI The IRI of the item which could not be removed * @param errNo The errno of the error that occurred * @return An initialized remove item failed exception */ -- (instancetype)initWithURI: (OFURI *)URI +- (instancetype)initWithIRI: (OFIRI *)IRI errNo: (int)errNo OF_DESIGNATED_INITIALIZER; - (instancetype)init OF_UNAVAILABLE; @end OF_ASSUME_NONNULL_END Index: src/exceptions/OFRemoveItemFailedException.m ================================================================== --- src/exceptions/OFRemoveItemFailedException.m +++ src/exceptions/OFRemoveItemFailedException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,37 +14,37 @@ */ #include "config.h" #import "OFRemoveItemFailedException.h" +#import "OFIRI.h" #import "OFString.h" -#import "OFURI.h" @implementation OFRemoveItemFailedException -@synthesize URI = _URI, errNo = _errNo; +@synthesize IRI = _IRI, errNo = _errNo; + (instancetype)exception { OF_UNRECOGNIZED_SELECTOR } -+ (instancetype)exceptionWithURI: (OFURI *)URI errNo: (int)errNo ++ (instancetype)exceptionWithIRI: (OFIRI *)IRI errNo: (int)errNo { - return [[[self alloc] initWithURI: URI errNo: errNo] autorelease]; + return [[[self alloc] initWithIRI: IRI errNo: errNo] autorelease]; } - (instancetype)init { OF_INVALID_INIT_METHOD } -- (instancetype)initWithURI: (OFURI *)URI errNo: (int)errNo +- (instancetype)initWithIRI: (OFIRI *)IRI errNo: (int)errNo { self = [super init]; @try { - _URI = [URI copy]; + _IRI = [IRI copy]; _errNo = errNo; } @catch (id e) { [self release]; @throw e; } @@ -52,16 +52,16 @@ return self; } - (void)dealloc { - [_URI release]; + [_IRI release]; [super dealloc]; } - (OFString *)description { return [OFString stringWithFormat: - @"Failed to remove item at URI %@: %@", _URI, OFStrError(_errNo)]; + @"Failed to remove item at IRI %@: %@", _IRI, OFStrError(_errNo)]; } @end Index: src/exceptions/OFResolveHostFailedException.h ================================================================== --- src/exceptions/OFResolveHostFailedException.h +++ src/exceptions/OFResolveHostFailedException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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.m ================================================================== --- src/exceptions/OFResolveHostFailedException.m +++ src/exceptions/OFResolveHostFailedException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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.m ================================================================== --- src/exceptions/OFSeekFailedException.m +++ src/exceptions/OFSeekFailedException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,15 +12,15 @@ * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this * file. */ #import "OFException.h" -#import "OFURIHandler.h" +#import "OFIRIHandler.h" OF_ASSUME_NONNULL_BEGIN -@class OFURI; +@class OFIRI; /** * @class OFSetItemAttributesFailedException \ * OFSetItemAttributesFailedException.h \ * ObjFW/OFSetItemAttributesFailedException.h @@ -27,21 +27,21 @@ * * @brief An exception indicating an item's attributes could not be set. */ @interface OFSetItemAttributesFailedException: OFException { - OFURI *_URI; + OFIRI *_IRI; OFFileAttributes _attributes; OFFileAttributeKey _failedAttribute; int _errNo; OF_RESERVE_IVARS(OFSetItemAttributesFailedException, 4) } /** - * @brief The URI of the item whose attributes could not be set. + * @brief The IRI of the item whose attributes could not be set. */ -@property (readonly, nonatomic) OFURI *URI; +@property (readonly, nonatomic) OFIRI *IRI; /** * @brief The errno of the error that occurred. */ @property (readonly, nonatomic) int errNo; @@ -57,38 +57,38 @@ @property (readonly, nonatomic) OFFileAttributeKey failedAttribute; /** * @brief Creates a new, autoreleased set item attributes failed exception. * - * @param URI The URI of the item whose attributes could not be set + * @param IRI The IRI of the item whose attributes could not be set * @param attributes The attributes that should have been set for the specified * item. * @param failedAttribute The first attribute that could not be set * @param errNo The errno of the error that occurred * @return A new, autoreleased set item attributes failed exception */ -+ (instancetype)exceptionWithURI: (OFURI *)URI ++ (instancetype)exceptionWithIRI: (OFIRI *)IRI attributes: (OFFileAttributes)attributes failedAttribute: (OFFileAttributeKey)failedAttribute errNo: (int)errNo; + (instancetype)exception OF_UNAVAILABLE; /** * @brief Initializes an already allocated set item attributes failed exception. * - * @param URI The URI of the item whose attributes could not be set + * @param IRI The IRI of the item whose attributes could not be set * @param attributes The attributes that should have been set for the specified * item. * @param failedAttribute The first attribute that could not be set * @param errNo The errno of the error that occurred * @return An initialized set item attributes failed exception */ -- (instancetype)initWithURI: (OFURI *)URI +- (instancetype)initWithIRI: (OFIRI *)IRI attributes: (OFFileAttributes)attributes failedAttribute: (OFFileAttributeKey)failedAttribute errNo: (int)errNo OF_DESIGNATED_INITIALIZER; - (instancetype)init OF_UNAVAILABLE; @end OF_ASSUME_NONNULL_END Index: src/exceptions/OFSetItemAttributesFailedException.m ================================================================== --- src/exceptions/OFSetItemAttributesFailedException.m +++ src/exceptions/OFSetItemAttributesFailedException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,28 +14,28 @@ */ #include "config.h" #import "OFSetItemAttributesFailedException.h" +#import "OFIRI.h" #import "OFString.h" -#import "OFURI.h" @implementation OFSetItemAttributesFailedException -@synthesize URI = _URI, attributes = _attributes; +@synthesize IRI = _IRI, attributes = _attributes; @synthesize failedAttribute = _failedAttribute, errNo = _errNo; + (instancetype)exception { OF_UNRECOGNIZED_SELECTOR } -+ (instancetype)exceptionWithURI: (OFURI *)URI ++ (instancetype)exceptionWithIRI: (OFIRI *)IRI attributes: (OFFileAttributes)attributes failedAttribute: (OFFileAttributeKey)failedAttribute errNo: (int)errNo { - return [[[self alloc] initWithURI: URI + return [[[self alloc] initWithIRI: IRI attributes: attributes failedAttribute: failedAttribute errNo: errNo] autorelease]; } @@ -42,19 +42,19 @@ - (instancetype)init { OF_INVALID_INIT_METHOD } -- (instancetype)initWithURI: (OFURI *)URI +- (instancetype)initWithIRI: (OFIRI *)IRI attributes: (OFFileAttributes)attributes failedAttribute: (OFFileAttributeKey)failedAttribute errNo: (int)errNo { self = [super init]; @try { - _URI = [URI copy]; + _IRI = [IRI copy]; _attributes = [attributes copy]; _failedAttribute = [failedAttribute copy]; _errNo = errNo; } @catch (id e) { [self release]; @@ -64,11 +64,11 @@ return self; } - (void)dealloc { - [_URI release]; + [_IRI release]; [_attributes release]; [_failedAttribute release]; [super dealloc]; } @@ -75,8 +75,8 @@ - (OFString *)description { return [OFString stringWithFormat: @"Failed to set attribute %@ for item %@: %@", - _failedAttribute, _URI, OFStrError(_errNo)]; + _failedAttribute, _IRI, OFStrError(_errNo)]; } @end Index: src/exceptions/OFSetOptionFailedException.h ================================================================== --- src/exceptions/OFSetOptionFailedException.h +++ src/exceptions/OFSetOptionFailedException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -23,19 +23,19 @@ * * @brief An exception indicating that setting an option for an object failed. */ @interface OFSetOptionFailedException: OFException { - id _object; + id _Nullable _object; int _errNo; OF_RESERVE_IVARS(OFSetOptionFailedException, 4) } /** * @brief The object for which the option could not be set. */ -@property (readonly, nonatomic) id object; +@property OF_NULLABLE_PROPERTY (readonly, nonatomic) id object; /** * @brief The errno of the error that occurred. */ @property (readonly, nonatomic) int errNo; @@ -45,11 +45,11 @@ * * @param object The object for which the option could not be set * @param errNo The errno of the error that occurred * @return A new, autoreleased set option failed exception */ -+ (instancetype)exceptionWithObject: (id)object errNo: (int)errNo; ++ (instancetype)exceptionWithObject: (nullable id)object errNo: (int)errNo; + (instancetype)exception OF_UNAVAILABLE; /** * @brief Initializes an already allocated set option failed exception. @@ -56,12 +56,12 @@ * * @param object The object for which the option could not be set * @param errNo The errno of the error that occurred * @return An initialized set option failed exception */ -- (instancetype)initWithObject: (id)object +- (instancetype)initWithObject: (nullable id)object errNo: (int)errNo OF_DESIGNATED_INITIALIZER; - (instancetype)init OF_UNAVAILABLE; @end OF_ASSUME_NONNULL_END Index: src/exceptions/OFSetOptionFailedException.m ================================================================== --- src/exceptions/OFSetOptionFailedException.m +++ src/exceptions/OFSetOptionFailedException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,10 +53,14 @@ [super dealloc]; } - (OFString *)description { - return [OFString stringWithFormat: - @"Setting an option in an object of type %@ failed: %@", - [_object class], OFStrError(_errNo)]; + if (_object != nil) + return [OFString stringWithFormat: + @"Setting an option in an object of type %@ failed: %@", + [_object class], OFStrError(_errNo)]; + else + return [OFString stringWithFormat: + @"Setting an option failed: %@", OFStrError(_errNo)]; } @end Index: src/exceptions/OFSetWindowsRegistryValueFailedException.h ================================================================== --- src/exceptions/OFSetWindowsRegistryValueFailedException.h +++ src/exceptions/OFSetWindowsRegistryValueFailedException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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/OFSignalConditionFailedException.h ================================================================== --- src/exceptions/OFSignalConditionFailedException.h +++ src/exceptions/OFSignalConditionFailedException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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/OFSignalConditionFailedException.m ================================================================== --- src/exceptions/OFSignalConditionFailedException.m +++ src/exceptions/OFSignalConditionFailedException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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/OFStartThreadFailedException.h ================================================================== --- src/exceptions/OFStartThreadFailedException.h +++ src/exceptions/OFStartThreadFailedException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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/OFStartThreadFailedException.m ================================================================== --- src/exceptions/OFStartThreadFailedException.m +++ src/exceptions/OFStartThreadFailedException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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.m ================================================================== --- src/exceptions/OFStillLockedException.m +++ src/exceptions/OFStillLockedException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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/OFTLSHandshakeFailedException.h ================================================================== --- src/exceptions/OFTLSHandshakeFailedException.h +++ src/exceptions/OFTLSHandshakeFailedException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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/OFTLSHandshakeFailedException.m ================================================================== --- src/exceptions/OFTLSHandshakeFailedException.m +++ src/exceptions/OFTLSHandshakeFailedException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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/OFThreadStillRunningException.h ================================================================== --- src/exceptions/OFThreadStillRunningException.h +++ src/exceptions/OFThreadStillRunningException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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/OFThreadStillRunningException.m ================================================================== --- src/exceptions/OFThreadStillRunningException.m +++ src/exceptions/OFThreadStillRunningException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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.m ================================================================== --- src/exceptions/OFUnboundNamespaceException.m +++ src/exceptions/OFUnboundNamespaceException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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.m ================================================================== --- src/exceptions/OFUnboundPrefixException.m +++ src/exceptions/OFUnboundPrefixException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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.m ================================================================== --- src/exceptions/OFUndefinedKeyException.m +++ src/exceptions/OFUndefinedKeyException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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.m ================================================================== --- src/exceptions/OFUnknownXMLEntityException.m +++ src/exceptions/OFUnknownXMLEntityException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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/OFUnlockFailedException.h ================================================================== --- src/exceptions/OFUnlockFailedException.h +++ src/exceptions/OFUnlockFailedException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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/OFUnlockFailedException.m ================================================================== --- src/exceptions/OFUnlockFailedException.m +++ src/exceptions/OFUnlockFailedException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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/OFUnsupportedProtocolException.h ================================================================== --- src/exceptions/OFUnsupportedProtocolException.h +++ src/exceptions/OFUnsupportedProtocolException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,44 +15,44 @@ #import "OFException.h" OF_ASSUME_NONNULL_BEGIN -@class OFURI; +@class OFIRI; /** * @class OFUnsupportedProtocolException \ * OFUnsupportedProtocolException.h \ * ObjFW/OFUnsupportedProtocolException.h * - * @brief An exception indicating that the protocol specified by the URI is not + * @brief An exception indicating that the protocol specified by the IRI is not * supported. */ @interface OFUnsupportedProtocolException: OFException { - OFURI *_Nullable _URI; + OFIRI *_Nullable _IRI; OF_RESERVE_IVARS(OFUnsupportedProtocolException, 4) } /** - * @brief The URI whose protocol is unsupported. + * @brief The IRI whose protocol is unsupported. */ -@property OF_NULLABLE_PROPERTY (readonly, nonatomic) OFURI *URI; +@property OF_NULLABLE_PROPERTY (readonly, nonatomic) OFIRI *IRI; /** * @brief Creates a new, autoreleased unsupported protocol exception. * - * @param URI The URI whose protocol is unsupported + * @param IRI The IRI whose protocol is unsupported * @return A new, autoreleased unsupported protocol exception */ -+ (instancetype)exceptionWithURI: (nullable OFURI*)URI; ++ (instancetype)exceptionWithIRI: (nullable OFIRI*)IRI; /** * @brief Initializes an already allocated unsupported protocol exception * - * @param URI The URI whose protocol is unsupported + * @param IRI The IRI whose protocol is unsupported * @return An initialized unsupported protocol exception */ -- (instancetype)initWithURI: (nullable OFURI*)URI OF_DESIGNATED_INITIALIZER; +- (instancetype)initWithIRI: (nullable OFIRI*)IRI OF_DESIGNATED_INITIALIZER; @end OF_ASSUME_NONNULL_END Index: src/exceptions/OFUnsupportedProtocolException.m ================================================================== --- src/exceptions/OFUnsupportedProtocolException.m +++ src/exceptions/OFUnsupportedProtocolException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,41 +14,41 @@ */ #include "config.h" #import "OFUnsupportedProtocolException.h" +#import "OFIRI.h" #import "OFString.h" -#import "OFURI.h" @implementation OFUnsupportedProtocolException -@synthesize URI = _URI; +@synthesize IRI = _IRI; -+ (instancetype)exceptionWithURI: (OFURI *)URI ++ (instancetype)exceptionWithIRI: (OFIRI *)IRI { - return [[[self alloc] initWithURI: URI] autorelease]; + return [[[self alloc] initWithIRI: IRI] autorelease]; } -- (instancetype)initWithURI: (OFURI *)URI +- (instancetype)initWithIRI: (OFIRI *)IRI { self = [super init]; - _URI = [URI retain]; + _IRI = [IRI retain]; return self; } - (void)dealloc { - [_URI release]; + [_IRI release]; [super dealloc]; } - (OFString *)description { - if (_URI != nil) + if (_IRI != nil) return [OFString stringWithFormat: - @"The protocol of URI %@ is not supported!", _URI]; + @"The protocol of IRI %@ is not supported!", _IRI]; else return @"The requested protocol is unsupported!"; } @end Index: src/exceptions/OFUnsupportedVersionException.h ================================================================== --- src/exceptions/OFUnsupportedVersionException.h +++ src/exceptions/OFUnsupportedVersionException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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.m ================================================================== --- src/exceptions/OFUnsupportedVersionException.m +++ src/exceptions/OFUnsupportedVersionException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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/OFWaitForConditionFailedException.h ================================================================== --- src/exceptions/OFWaitForConditionFailedException.h +++ src/exceptions/OFWaitForConditionFailedException.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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/OFWaitForConditionFailedException.m ================================================================== --- src/exceptions/OFWaitForConditionFailedException.m +++ src/exceptions/OFWaitForConditionFailedException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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.m ================================================================== --- src/exceptions/OFWriteFailedException.m +++ src/exceptions/OFWriteFailedException.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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/forwarding/apple-forwarding-amd64.S Index: src/forwarding/apple-forwarding-amd64.S ================================================================== --- /dev/null +++ src/forwarding/apple-forwarding-amd64.S @@ -0,0 +1,178 @@ +/* + * Copyright (c) 2008-2024 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#include "config.h" + +.globl _OFForward +.globl _OFForward_stret + +.section __TEXT, __objc_methname, cstring_literals +Lstr_forwardingTargetForSelector_: + .asciz "forwardingTargetForSelector:" + +.section __DATA, __objc_selrefs, literal_pointers, no_dead_strip +Lsel_forwardingTargetForSelector_: + .quad Lstr_forwardingTargetForSelector_ + +.section __DATA, __objc_imageinfo, regular, no_dead_strip + .long 0, 0 + +.section __TEXT, __text, regular, pure_instructions +_OFForward: + pushq %rbp + movq %rsp, %rbp + + /* Save all arguments */ + subq $0xC0, %rsp /* 16-byte alignment */ + movq %rax, -0x8(%rbp) + movq %rdi, -0x10(%rbp) + movq %rsi, -0x18(%rbp) + movq %rdx, -0x20(%rbp) + movq %rcx, -0x28(%rbp) + movq %r8, -0x30(%rbp) + movq %r9, -0x38(%rbp) + movaps %xmm0, -0x50(%rbp) + movaps %xmm1, -0x60(%rbp) + movaps %xmm2, -0x70(%rbp) + movaps %xmm3, -0x80(%rbp) + movaps %xmm4, -0x90(%rbp) + movaps %xmm5, -0xA0(%rbp) + movaps %xmm6, -0xB0(%rbp) + movaps %xmm7, -0xC0(%rbp) + + call _object_getClass + + movq %rax, %rdi + movq Lsel_forwardingTargetForSelector_(%rip), %rsi + call _class_respondsToSelector + + testq %rax, %rax + jz 0f + + movq -0x10(%rbp), %rdi + movq Lsel_forwardingTargetForSelector_(%rip), %rsi + movq -0x18(%rbp), %rdx + call _objc_msgSend + + testq %rax, %rax + jz 0f + cmpq -0x10(%rbp), %rax + je 0f + + movq %rax, %rdi + + /* Restore all arguments, except %rdi */ + movaps -0xC0(%rbp), %xmm7 + movaps -0xB0(%rbp), %xmm6 + movaps -0xA0(%rbp), %xmm5 + movaps -0x90(%rbp), %xmm4 + movaps -0x80(%rbp), %xmm3 + movaps -0x70(%rbp), %xmm2 + movaps -0x60(%rbp), %xmm1 + movaps -0x50(%rbp), %xmm0 + movq -0x38(%rbp), %r9 + movq -0x30(%rbp), %r8 + movq -0x28(%rbp), %rcx + movq -0x20(%rbp), %rdx + movq -0x18(%rbp), %rsi + movq -0x8(%rbp), %rax + + movq %rbp, %rsp + popq %rbp + + jmp _objc_msgSend + +0: + movq -0x10(%rbp), %rdi + movq -0x18(%rbp), %rsi + + movq %rbp, %rsp + popq %rbp + + jmp _OFMethodNotFound + +_OFForward_stret: + pushq %rbp + movq %rsp, %rbp + + /* Save all arguments */ + subq $0xC0, %rsp /* 16-byte alignment */ + movq %rax, -0x8(%rbp) + movq %rdi, -0x10(%rbp) + movq %rsi, -0x18(%rbp) + movq %rdx, -0x20(%rbp) + movq %rcx, -0x28(%rbp) + movq %r8, -0x30(%rbp) + movq %r9, -0x38(%rbp) + movaps %xmm0, -0x50(%rbp) + movaps %xmm1, -0x60(%rbp) + movaps %xmm2, -0x70(%rbp) + movaps %xmm3, -0x80(%rbp) + movaps %xmm4, -0x90(%rbp) + movaps %xmm5, -0xA0(%rbp) + movaps %xmm6, -0xB0(%rbp) + movaps %xmm7, -0xC0(%rbp) + + movq %rsi, %rdi + call _object_getClass + + movq %rax, %rdi + movq Lsel_forwardingTargetForSelector_(%rip), %rsi + call _class_respondsToSelector + testq %rax, %rax + jz 0f + + movq -0x18(%rbp), %rdi + movq Lsel_forwardingTargetForSelector_(%rip), %rsi + movq -0x20(%rbp), %rdx + call _objc_msgSend + + testq %rax, %rax + jz 0f + cmpq -0x18(%rbp), %rax + je 0f + + movq %rax, %rsi + + /* Restore all arguments, except %rsi */ + movaps -0xC0(%rbp), %xmm7 + movaps -0xB0(%rbp), %xmm6 + movaps -0xA0(%rbp), %xmm5 + movaps -0x90(%rbp), %xmm4 + movaps -0x80(%rbp), %xmm3 + movaps -0x70(%rbp), %xmm2 + movaps -0x60(%rbp), %xmm1 + movaps -0x50(%rbp), %xmm0 + movq -0x38(%rbp), %r9 + movq -0x30(%rbp), %r8 + movq -0x28(%rbp), %rcx + movq -0x20(%rbp), %rdx + movq -0x10(%rbp), %rdi + movq -0x8(%rbp), %rax + + movq %rbp, %rsp + popq %rbp + + jmp _objc_msgSend_stret + +0: + movq -0x10(%rbp), %rdi + movq -0x18(%rbp), %rsi + movq -0x20(%rbp), %rdx + + movq %rbp, %rsp + popq %rbp + + jmp _OFMethodNotFound_stret 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,15 +17,15 @@ .globl _OFForward .globl _OFForward_stret .section __TEXT, __objc_methname, cstring_literals -str_forwardingTargetForSelector_: +Lstr_forwardingTargetForSelector_: .asciz "forwardingTargetForSelector:" .section __DATA, __objc_selrefs, literal_pointers, no_dead_strip -sel_forwardingTargetForSelector_: +Lsel_forwardingTargetForSelector_: .long str_forwardingTargetForSelector_ .section __DATA, __objc_imageinfo, regular, no_dead_strip .long 0, 0 @@ -34,11 +34,11 @@ .align 2 _OFForward: stmfd sp!, {r0-r4, lr} vstmdb sp!, {d0-d7} - ldr r4, sel_forwardingTargetForSelector_$indirect_L0 + ldr r4, Lsel_forwardingTargetForSelector_$indirect_L0 L0: ldr r4, [pc, r4] blx _object_getClass @@ -69,20 +69,20 @@ vldmia sp!, {d0-d7} ldmfd sp!, {r0-r4, lr} b _OFMethodNotFound .data_region -sel_forwardingTargetForSelector_$indirect_L0: - .long sel_forwardingTargetForSelector_-(L0+8) +Lsel_forwardingTargetForSelector_$indirect_L0: + .long Lsel_forwardingTargetForSelector_-(L0+8) .end_data_region .align 2 _OFForward_stret: stmfd sp!, {r0-r4, lr} vstmdb sp!, {d0-d7} - ldr r4, sel_forwardingTargetForSelector_$indirect_L1 + ldr r4, Lsel_forwardingTargetForSelector_$indirect_L1 L1: ldr r4, [pc, r4] mov r0, r1 blx _object_getClass @@ -117,8 +117,8 @@ vldmia sp!, {d0-d7} ldmfd sp!, {r0-r4, lr} b _OFMethodNotFound_stret .data_region -sel_forwardingTargetForSelector_$indirect_L1: - .long sel_forwardingTargetForSelector_-(L1+8) +Lsel_forwardingTargetForSelector_$indirect_L1: + .long Lsel_forwardingTargetForSelector_-(L1+8) .end_data_region 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,16 +17,16 @@ .globl _OFForward .globl _OFForward_stret .section __TEXT, __objc_methname, cstring_literals -str_forwardingTargetForSelector_: +Lstr_forwardingTargetForSelector_: .asciz "forwardingTargetForSelector:" .section __DATA, __objc_selrefs, literal_pointers, no_dead_strip -sel_forwardingTargetForSelector_: - .quad str_forwardingTargetForSelector_ +Lsel_forwardingTargetForSelector_: + .quad Lstr_forwardingTargetForSelector_ .section __DATA, __objc_imageinfo, regular, no_dead_strip .long 0, 0 .section __TEXT, __text, regular, pure_instructions @@ -50,12 +50,12 @@ stp q4, q5, [sp, #144] stp q6, q7, [sp, #176] bl _object_getClass - adrp x19, sel_forwardingTargetForSelector_@PAGE - add x19, x19, sel_forwardingTargetForSelector_@PAGEOFF + adrp x19, Lsel_forwardingTargetForSelector_@PAGE + add x19, x19, Lsel_forwardingTargetForSelector_@PAGEOFF ldr x19, [x19] mov x1, x19 bl _class_respondsToSelector DELETED src/forwarding/apple-forwarding-i386.S Index: src/forwarding/apple-forwarding-i386.S ================================================================== --- src/forwarding/apple-forwarding-i386.S +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright (c) 2008-2022 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#include "config.h" - -.globl _OFForward -.globl _OFForward_stret - -.section __TEXT, __cstring, cstring_literals -str_forwardingTargetForSelector_: - .asciz "forwardingTargetForSelector:" - -.section __OBJC, __message_refs, literal_pointers, no_dead_strip -sel_forwardingTargetForSelector_: - .long str_forwardingTargetForSelector_ - -.section __OBJC, __image_info - .long 0, 0 - -.section __TEXT, __text, regular, pure_instructions -_OFForward: - pushl %ebp - movl %esp, %ebp - - pushl %ebx - subl $20, %esp - - call get_eip -0: - - movl 8(%ebp), %eax - movl %eax, (%esp) - call _object_getClass - - movl %eax, (%esp) - movl sel_forwardingTargetForSelector_-0b(%ebx), %eax - movl %eax, 4(%esp) - call _class_respondsToSelector - - testl %eax, %eax - jz 0f - - movl 8(%ebp), %eax - movl %eax, (%esp) - movl sel_forwardingTargetForSelector_-0b(%ebx), %eax - movl %eax, 4(%esp) - movl 12(%ebp), %eax - movl %eax, 8(%esp) - call _objc_msgSend - - testl %eax, %eax - jz 0f - cmpl 8(%ebp), %eax - je 0f - - movl %eax, 8(%ebp) - - addl $20, %esp - popl %ebx - popl %ebp - - jmp _objc_msgSend - -0: - addl $20, %esp - popl %ebx - popl %ebp - - jmp _OFMethodNotFound - -_OFForward_stret: - pushl %ebp - movl %esp, %ebp - - pushl %ebx - subl $20, %esp - - call get_eip -0: - - movl 12(%ebp), %eax - movl %eax, (%esp) - call _object_getClass - - movl %eax, (%esp) - movl sel_forwardingTargetForSelector_-0b(%ebx), %eax - movl %eax, 4(%esp) - call _class_respondsToSelector - - testl %eax, %eax - jz 0f - - movl 12(%ebp), %eax - movl %eax, (%esp) - movl sel_forwardingTargetForSelector_-0b(%ebx), %eax - movl %eax, 4(%esp) - movl 16(%ebp), %eax - movl %eax, 8(%esp) - call _objc_msgSend - - testl %eax, %eax - jz 0f - cmpl 12(%ebp), %eax - je 0f - - movl %eax, 12(%ebp) - - addl $20, %esp - popl %ebx - popl %ebp - - jmp _objc_msgSend_stret - -0: - addl $20, %esp - popl %ebx - popl %ebp - - jmp _OFMethodNotFound_stret - -get_eip: - movl (%esp), %ebx - ret 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,16 +17,16 @@ .globl _OFForward .globl _OFForward_stret .section __TEXT, __cstring, cstring_literals -str_forwardingTargetForSelector_: +Lstr_forwardingTargetForSelector_: .asciz "forwardingTargetForSelector:" .section __OBJC, __message_refs -sel_forwardingTargetForSelector_: - .long str_forwardingTargetForSelector_ +Lsel_forwardingTargetForSelector_: + .long Lstr_forwardingTargetForSelector_ .section __OBJC, __image_info .long 0, 0 .section __TEXT, __text, regular, pure_instructions @@ -69,12 +69,12 @@ bl _object_getClass bl 0f 0: mflr r13 - addis r13, r13, ha16(sel_forwardingTargetForSelector_-0b) - lwz r13, lo16(sel_forwardingTargetForSelector_-0b)(r13) + addis r13, r13, ha16(Lsel_forwardingTargetForSelector_-0b) + lwz r13, lo16(Lsel_forwardingTargetForSelector_-0b)(r13) mr r4, r13 bl _class_respondsToSelector cmpwi r3, 0 @@ -172,12 +172,12 @@ bl _object_getClass bl 0f 0: mflr r13 - addis r13, r13, ha16(sel_forwardingTargetForSelector_-0b) - lwz r13, lo16(sel_forwardingTargetForSelector_-0b)(r13) + addis r13, r13, ha16(Lsel_forwardingTargetForSelector_-0b) + lwz r13, lo16(Lsel_forwardingTargetForSelector_-0b)(r13) mr r4, r13 bl _class_respondsToSelector cmpwi r3, 0 ADDED src/forwarding/apple-forwarding-x86.S Index: src/forwarding/apple-forwarding-x86.S ================================================================== --- /dev/null +++ src/forwarding/apple-forwarding-x86.S @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2008-2024 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#include "config.h" + +.globl _OFForward +.globl _OFForward_stret + +.section __TEXT, __cstring, cstring_literals +Lstr_forwardingTargetForSelector_: + .asciz "forwardingTargetForSelector:" + +.section __OBJC, __message_refs, literal_pointers, no_dead_strip +Lsel_forwardingTargetForSelector_: + .long Lstr_forwardingTargetForSelector_ + +.section __OBJC, __image_info + .long 0, 0 + +.section __TEXT, __text, regular, pure_instructions +_OFForward: + pushl %ebp + movl %esp, %ebp + + pushl %ebx + subl $20, %esp + + call LgetEIP +0: + + movl 8(%ebp), %eax + movl %eax, (%esp) + call _object_getClass + + movl %eax, (%esp) + movl Lsel_forwardingTargetForSelector_-0b(%ebx), %eax + movl %eax, 4(%esp) + call _class_respondsToSelector + + testl %eax, %eax + jz 0f + + movl 8(%ebp), %eax + movl %eax, (%esp) + movl Lsel_forwardingTargetForSelector_-0b(%ebx), %eax + movl %eax, 4(%esp) + movl 12(%ebp), %eax + movl %eax, 8(%esp) + call _objc_msgSend + + testl %eax, %eax + jz 0f + cmpl 8(%ebp), %eax + je 0f + + movl %eax, 8(%ebp) + + addl $20, %esp + popl %ebx + popl %ebp + + jmp _objc_msgSend + +0: + addl $20, %esp + popl %ebx + popl %ebp + + jmp _OFMethodNotFound + +_OFForward_stret: + pushl %ebp + movl %esp, %ebp + + pushl %ebx + subl $20, %esp + + call LgetEIP +0: + + movl 12(%ebp), %eax + movl %eax, (%esp) + call _object_getClass + + movl %eax, (%esp) + movl Lsel_forwardingTargetForSelector_-0b(%ebx), %eax + movl %eax, 4(%esp) + call _class_respondsToSelector + + testl %eax, %eax + jz 0f + + movl 12(%ebp), %eax + movl %eax, (%esp) + movl Lsel_forwardingTargetForSelector_-0b(%ebx), %eax + movl %eax, 4(%esp) + movl 16(%ebp), %eax + movl %eax, 8(%esp) + call _objc_msgSend + + testl %eax, %eax + jz 0f + cmpl 12(%ebp), %eax + je 0f + + movl %eax, 12(%ebp) + + addl $20, %esp + popl %ebx + popl %ebp + + jmp _objc_msgSend_stret + +0: + addl $20, %esp + popl %ebx + popl %ebp + + jmp _OFMethodNotFound_stret + +LgetEIP: + movl (%esp), %ebx + ret DELETED src/forwarding/apple-forwarding-x86_64.S Index: src/forwarding/apple-forwarding-x86_64.S ================================================================== --- src/forwarding/apple-forwarding-x86_64.S +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Copyright (c) 2008-2022 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#include "config.h" - -.globl _OFForward -.globl _OFForward_stret - -.section __TEXT, __objc_methname, cstring_literals -str_forwardingTargetForSelector_: - .asciz "forwardingTargetForSelector:" - -.section __DATA, __objc_selrefs, literal_pointers, no_dead_strip -sel_forwardingTargetForSelector_: - .quad str_forwardingTargetForSelector_ - -.section __DATA, __objc_imageinfo, regular, no_dead_strip - .long 0, 0 - -.section __TEXT, __text, regular, pure_instructions -_OFForward: - pushq %rbp - movq %rsp, %rbp - - /* Save all arguments */ - subq $0xC0, %rsp /* 16-byte alignment */ - movq %rax, -0x8(%rbp) - movq %rdi, -0x10(%rbp) - movq %rsi, -0x18(%rbp) - movq %rdx, -0x20(%rbp) - movq %rcx, -0x28(%rbp) - movq %r8, -0x30(%rbp) - movq %r9, -0x38(%rbp) - movaps %xmm0, -0x50(%rbp) - movaps %xmm1, -0x60(%rbp) - movaps %xmm2, -0x70(%rbp) - movaps %xmm3, -0x80(%rbp) - movaps %xmm4, -0x90(%rbp) - movaps %xmm5, -0xA0(%rbp) - movaps %xmm6, -0xB0(%rbp) - movaps %xmm7, -0xC0(%rbp) - - call _object_getClass - - movq %rax, %rdi - movq sel_forwardingTargetForSelector_(%rip), %rsi - call _class_respondsToSelector - - testq %rax, %rax - jz 0f - - movq -0x10(%rbp), %rdi - movq sel_forwardingTargetForSelector_(%rip), %rsi - movq -0x18(%rbp), %rdx - call _objc_msgSend - - testq %rax, %rax - jz 0f - cmpq -0x10(%rbp), %rax - je 0f - - movq %rax, %rdi - - /* Restore all arguments, except %rdi */ - movaps -0xC0(%rbp), %xmm7 - movaps -0xB0(%rbp), %xmm6 - movaps -0xA0(%rbp), %xmm5 - movaps -0x90(%rbp), %xmm4 - movaps -0x80(%rbp), %xmm3 - movaps -0x70(%rbp), %xmm2 - movaps -0x60(%rbp), %xmm1 - movaps -0x50(%rbp), %xmm0 - movq -0x38(%rbp), %r9 - movq -0x30(%rbp), %r8 - movq -0x28(%rbp), %rcx - movq -0x20(%rbp), %rdx - movq -0x18(%rbp), %rsi - movq -0x8(%rbp), %rax - - movq %rbp, %rsp - popq %rbp - - jmp _objc_msgSend - -0: - movq -0x10(%rbp), %rdi - movq -0x18(%rbp), %rsi - - movq %rbp, %rsp - popq %rbp - - jmp _OFMethodNotFound - -_OFForward_stret: - pushq %rbp - movq %rsp, %rbp - - /* Save all arguments */ - subq $0xC0, %rsp /* 16-byte alignment */ - movq %rax, -0x8(%rbp) - movq %rdi, -0x10(%rbp) - movq %rsi, -0x18(%rbp) - movq %rdx, -0x20(%rbp) - movq %rcx, -0x28(%rbp) - movq %r8, -0x30(%rbp) - movq %r9, -0x38(%rbp) - movaps %xmm0, -0x50(%rbp) - movaps %xmm1, -0x60(%rbp) - movaps %xmm2, -0x70(%rbp) - movaps %xmm3, -0x80(%rbp) - movaps %xmm4, -0x90(%rbp) - movaps %xmm5, -0xA0(%rbp) - movaps %xmm6, -0xB0(%rbp) - movaps %xmm7, -0xC0(%rbp) - - movq %rsi, %rdi - call _object_getClass - - movq %rax, %rdi - movq sel_forwardingTargetForSelector_(%rip), %rsi - call _class_respondsToSelector - testq %rax, %rax - jz 0f - - movq -0x18(%rbp), %rdi - movq sel_forwardingTargetForSelector_(%rip), %rsi - movq -0x20(%rbp), %rdx - call _objc_msgSend - - testq %rax, %rax - jz 0f - cmpq -0x18(%rbp), %rax - je 0f - - movq %rax, %rsi - - /* Restore all arguments, except %rsi */ - movaps -0xC0(%rbp), %xmm7 - movaps -0xB0(%rbp), %xmm6 - movaps -0xA0(%rbp), %xmm5 - movaps -0x90(%rbp), %xmm4 - movaps -0x80(%rbp), %xmm3 - movaps -0x70(%rbp), %xmm2 - movaps -0x60(%rbp), %xmm1 - movaps -0x50(%rbp), %xmm0 - movq -0x38(%rbp), %r9 - movq -0x30(%rbp), %r8 - movq -0x28(%rbp), %rcx - movq -0x20(%rbp), %rdx - movq -0x10(%rbp), %rdi - movq -0x8(%rbp), %rax - - movq %rbp, %rsp - popq %rbp - - jmp _objc_msgSend_stret - -0: - movq -0x10(%rbp), %rdi - movq -0x18(%rbp), %rsi - movq -0x20(%rbp), %rdx - - movq %rbp, %rsp - popq %rbp - - jmp _OFMethodNotFound_stret ADDED src/forwarding/forwarding-amd64-elf.S Index: src/forwarding/forwarding-amd64-elf.S ================================================================== --- /dev/null +++ src/forwarding/forwarding-amd64-elf.S @@ -0,0 +1,225 @@ +/* + * Copyright (c) 2008-2024 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#include "config.h" + +#include "platform.h" + +.globl OFForward +.globl OFForward_stret + +.section .text +OFForward: + pushq %rbp + movq %rsp, %rbp + + /* Save all arguments */ + subq $0xC0, %rsp /* 16-byte alignment */ + movq %rax, -0x8(%rbp) + movq %rdi, -0x10(%rbp) + movq %rsi, -0x18(%rbp) + movq %rdx, -0x20(%rbp) + movq %rcx, -0x28(%rbp) + movq %r8, -0x30(%rbp) + movq %r9, -0x38(%rbp) + movaps %xmm0, -0x50(%rbp) + movaps %xmm1, -0x60(%rbp) + movaps %xmm2, -0x70(%rbp) + movaps %xmm3, -0x80(%rbp) + movaps %xmm4, -0x90(%rbp) + movaps %xmm5, -0xA0(%rbp) + movaps %xmm6, -0xB0(%rbp) + movaps %xmm7, -0xC0(%rbp) + + call object_getClass@PLT + + movq %rax, %rdi + leaq .Lsel_forwardingTargetForSelector_(%rip), %rsi + call class_respondsToSelector@PLT + + testq %rax, %rax + jz 0f + + movq -0x10(%rbp), %rdi + leaq .Lsel_forwardingTargetForSelector_(%rip), %rsi + call objc_msg_lookup@PLT + + movq -0x10(%rbp), %rdi + leaq .Lsel_forwardingTargetForSelector_(%rip), %rsi + movq -0x18(%rbp), %rdx + call *%rax + + testq %rax, %rax + jz 0f + cmpq -0x10(%rbp), %rax + je 0f + + movq %rax, -0x10(%rbp) + + movq %rax, %rdi + movq -0x18(%rbp), %rsi + call objc_msg_lookup@PLT + movq %rax, %r11 + + /* Restore all arguments */ + movaps -0xC0(%rbp), %xmm7 + movaps -0xB0(%rbp), %xmm6 + movaps -0xA0(%rbp), %xmm5 + movaps -0x90(%rbp), %xmm4 + movaps -0x80(%rbp), %xmm3 + movaps -0x70(%rbp), %xmm2 + movaps -0x60(%rbp), %xmm1 + movaps -0x50(%rbp), %xmm0 + movq -0x38(%rbp), %r9 + movq -0x30(%rbp), %r8 + movq -0x28(%rbp), %rcx + movq -0x20(%rbp), %rdx + movq -0x18(%rbp), %rsi + movq -0x10(%rbp), %rdi + movq -0x8(%rbp), %rax + + movq %rbp, %rsp + popq %rbp + + jmpq *%r11 + +0: + movq -0x10(%rbp), %rdi + movq -0x18(%rbp), %rsi + + movq %rbp, %rsp + popq %rbp + + jmp OFMethodNotFound@PLT +.type OFForward, %function +.size OFForward, .-OFForward + +OFForward_stret: + pushq %rbp + movq %rsp, %rbp + + /* Save all arguments */ + subq $0xC0, %rsp /* 16-byte alignment */ + movq %rax, -0x8(%rbp) + movq %rdi, -0x10(%rbp) + movq %rsi, -0x18(%rbp) + movq %rdx, -0x20(%rbp) + movq %rcx, -0x28(%rbp) + movq %r8, -0x30(%rbp) + movq %r9, -0x38(%rbp) + movaps %xmm0, -0x50(%rbp) + movaps %xmm1, -0x60(%rbp) + movaps %xmm2, -0x70(%rbp) + movaps %xmm3, -0x80(%rbp) + movaps %xmm4, -0x90(%rbp) + movaps %xmm5, -0xA0(%rbp) + movaps %xmm6, -0xB0(%rbp) + movaps %xmm7, -0xC0(%rbp) + + movq %rsi, %rdi + call object_getClass@PLT + + movq %rax, %rdi + leaq .Lsel_forwardingTargetForSelector_(%rip), %rsi + call class_respondsToSelector@PLT + + testq %rax, %rax + jz 0f + + movq -0x18(%rbp), %rdi + leaq .Lsel_forwardingTargetForSelector_(%rip), %rsi + call objc_msg_lookup@PLT + + movq -0x18(%rbp), %rdi + leaq .Lsel_forwardingTargetForSelector_(%rip), %rsi + movq -0x20(%rbp), %rdx + call *%rax + + testq %rax, %rax + jz 0f + cmpq -0x18(%rbp), %rax + je 0f + + movq %rax, -0x18(%rbp) + + movq %rax, %rdi + movq -0x20(%rbp), %rsi + call objc_msg_lookup_stret@PLT + movq %rax, %r11 + + /* Restore all arguments */ + movaps -0xC0(%rbp), %xmm7 + movaps -0xB0(%rbp), %xmm6 + movaps -0xA0(%rbp), %xmm5 + movaps -0x90(%rbp), %xmm4 + movaps -0x80(%rbp), %xmm3 + movaps -0x70(%rbp), %xmm2 + movaps -0x60(%rbp), %xmm1 + movaps -0x50(%rbp), %xmm0 + movq -0x38(%rbp), %r9 + movq -0x30(%rbp), %r8 + movq -0x28(%rbp), %rcx + movq -0x20(%rbp), %rdx + movq -0x18(%rbp), %rsi + movq -0x10(%rbp), %rdi + movq -0x8(%rbp), %rax + + movq %rbp, %rsp + popq %rbp + + jmpq *%r11 + +0: + movq -0x10(%rbp), %rdi + movq -0x18(%rbp), %rsi + movq -0x20(%rbp), %rdx + + movq %rbp, %rsp + popq %rbp + + jmp OFMethodNotFound_stret@PLT +.type OFForward_stret, %function +.size OFForward_stret, .-OFForward_stret + +.Linit: + leaq .Lmodule(%rip), %rdi + jmp __objc_exec_class@PLT + +#ifdef OF_SOLARIS +.section .init_array, "aw" +#else +.section .ctors, "aw", %progbits +#endif + .quad .Linit + +.section .rodata +.Lstr_forwardingTargetForSelector_: + .asciz "forwardingTargetForSelector:" + +.section .data +.Lsel_forwardingTargetForSelector_: + .quad .Lstr_forwardingTargetForSelector_, 0 + .quad 0, 0 +.Lsymtab: + .quad 0, .Lsel_forwardingTargetForSelector_ + .short 0, 0 + .long 0 + .quad 0 +.Lmodule: + .quad 8, 32, 0, .Lsymtab + +#if defined(OF_LINUX) || defined(OF_HAIKU) || defined(OF_HURD) +.section .note.GNU-stack, "", %progbits +#endif ADDED src/forwarding/forwarding-amd64-macho.S Index: src/forwarding/forwarding-amd64-macho.S ================================================================== --- /dev/null +++ src/forwarding/forwarding-amd64-macho.S @@ -0,0 +1,213 @@ +/* + * Copyright (c) 2008-2024 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#include "config.h" + +#include "platform.h" + +.globl _OFForward +.globl _OFForward_stret + +.section __TEXT, __text, regular, pure_instructions +_OFForward: + pushq %rbp + movq %rsp, %rbp + + /* Save all arguments */ + subq $0xC0, %rsp /* 16-byte alignment */ + movq %rax, -0x8(%rbp) + movq %rdi, -0x10(%rbp) + movq %rsi, -0x18(%rbp) + movq %rdx, -0x20(%rbp) + movq %rcx, -0x28(%rbp) + movq %r8, -0x30(%rbp) + movq %r9, -0x38(%rbp) + movaps %xmm0, -0x50(%rbp) + movaps %xmm1, -0x60(%rbp) + movaps %xmm2, -0x70(%rbp) + movaps %xmm3, -0x80(%rbp) + movaps %xmm4, -0x90(%rbp) + movaps %xmm5, -0xA0(%rbp) + movaps %xmm6, -0xB0(%rbp) + movaps %xmm7, -0xC0(%rbp) + + call _object_getClass + + movq %rax, %rdi + leaq Lsel_forwardingTargetForSelector_(%rip), %rsi + call _class_respondsToSelector + + testq %rax, %rax + jz 0f + + movq -0x10(%rbp), %rdi + leaq Lsel_forwardingTargetForSelector_(%rip), %rsi + call _objc_msg_lookup + + movq -0x10(%rbp), %rdi + leaq Lsel_forwardingTargetForSelector_(%rip), %rsi + movq -0x18(%rbp), %rdx + call *%rax + + testq %rax, %rax + jz 0f + cmpq -0x10(%rbp), %rax + je 0f + + movq %rax, -0x10(%rbp) + + movq %rax, %rdi + movq -0x18(%rbp), %rsi + call _objc_msg_lookup + movq %rax, %r11 + + /* Restore all arguments */ + movaps -0xC0(%rbp), %xmm7 + movaps -0xB0(%rbp), %xmm6 + movaps -0xA0(%rbp), %xmm5 + movaps -0x90(%rbp), %xmm4 + movaps -0x80(%rbp), %xmm3 + movaps -0x70(%rbp), %xmm2 + movaps -0x60(%rbp), %xmm1 + movaps -0x50(%rbp), %xmm0 + movq -0x38(%rbp), %r9 + movq -0x30(%rbp), %r8 + movq -0x28(%rbp), %rcx + movq -0x20(%rbp), %rdx + movq -0x18(%rbp), %rsi + movq -0x10(%rbp), %rdi + movq -0x8(%rbp), %rax + + movq %rbp, %rsp + popq %rbp + + jmpq *%r11 + +0: + movq -0x10(%rbp), %rdi + movq -0x18(%rbp), %rsi + + movq %rbp, %rsp + popq %rbp + + jmp _OFMethodNotFound + +_OFForward_stret: + pushq %rbp + movq %rsp, %rbp + + /* Save all arguments */ + subq $0xC0, %rsp /* 16-byte alignment */ + movq %rax, -0x8(%rbp) + movq %rdi, -0x10(%rbp) + movq %rsi, -0x18(%rbp) + movq %rdx, -0x20(%rbp) + movq %rcx, -0x28(%rbp) + movq %r8, -0x30(%rbp) + movq %r9, -0x38(%rbp) + movaps %xmm0, -0x50(%rbp) + movaps %xmm1, -0x60(%rbp) + movaps %xmm2, -0x70(%rbp) + movaps %xmm3, -0x80(%rbp) + movaps %xmm4, -0x90(%rbp) + movaps %xmm5, -0xA0(%rbp) + movaps %xmm6, -0xB0(%rbp) + movaps %xmm7, -0xC0(%rbp) + + movq %rsi, %rdi + call _object_getClass + + movq %rax, %rdi + leaq Lsel_forwardingTargetForSelector_(%rip), %rsi + call _class_respondsToSelector + + testq %rax, %rax + jz 0f + + movq -0x18(%rbp), %rdi + leaq Lsel_forwardingTargetForSelector_(%rip), %rsi + call _objc_msg_lookup + + movq -0x18(%rbp), %rdi + leaq Lsel_forwardingTargetForSelector_(%rip), %rsi + movq -0x20(%rbp), %rdx + call *%rax + + testq %rax, %rax + jz 0f + cmpq -0x18(%rbp), %rax + je 0f + + movq %rax, -0x18(%rbp) + + movq %rax, %rdi + movq -0x20(%rbp), %rsi + call _objc_msg_lookup_stret + movq %rax, %r11 + + /* Restore all arguments */ + movaps -0xC0(%rbp), %xmm7 + movaps -0xB0(%rbp), %xmm6 + movaps -0xA0(%rbp), %xmm5 + movaps -0x90(%rbp), %xmm4 + movaps -0x80(%rbp), %xmm3 + movaps -0x70(%rbp), %xmm2 + movaps -0x60(%rbp), %xmm1 + movaps -0x50(%rbp), %xmm0 + movq -0x38(%rbp), %r9 + movq -0x30(%rbp), %r8 + movq -0x28(%rbp), %rcx + movq -0x20(%rbp), %rdx + movq -0x18(%rbp), %rsi + movq -0x10(%rbp), %rdi + movq -0x8(%rbp), %rax + + movq %rbp, %rsp + popq %rbp + + jmpq *%r11 + +0: + movq -0x10(%rbp), %rdi + movq -0x18(%rbp), %rsi + movq -0x20(%rbp), %rdx + + movq %rbp, %rsp + popq %rbp + + jmp _OFMethodNotFound_stret + +Linit: + leaq Lmodule(%rip), %rdi + jmp ___objc_exec_class + +.section __DATA, __mod_init_func, mod_init_funcs + .quad Linit + +.section __TEXT, __cstring, cstring_literals +Lstr_forwardingTargetForSelector_: + .asciz "forwardingTargetForSelector:" + +.section __DATA, __data +Lsel_forwardingTargetForSelector_: + .quad Lstr_forwardingTargetForSelector_, 0 + .quad 0, 0 +Lsymtab: + .quad 0, Lsel_forwardingTargetForSelector_ + .short 0, 0 + .long 0 + .quad 0 +Lmodule: + .quad 8, 32, 0, Lsymtab ADDED src/forwarding/forwarding-amd64-win64.S Index: src/forwarding/forwarding-amd64-win64.S ================================================================== --- /dev/null +++ src/forwarding/forwarding-amd64-win64.S @@ -0,0 +1,197 @@ +/* + * Copyright (c) 2008-2024 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#include "config.h" + +.globl OFForward +.globl OFForward_stret + +.section .text +OFForward: + pushq %rbp + movq %rsp, %rbp + + /* Save all arguments */ + subq $0x90, %rsp /* 16-byte alignment */ + movq %rax, -0x28(%rbp) + movq %rcx, -0x30(%rbp) + movq %rdx, -0x38(%rbp) + movq %r8, -0x40(%rbp) + movq %r9, -0x48(%rbp) + movaps %xmm0, -0x60(%rbp) + movaps %xmm1, -0x70(%rbp) + movaps %xmm2, -0x80(%rbp) + movaps %xmm3, -0x90(%rbp) + + call object_getClass + + movq %rax, %rcx + leaq .Lsel_forwardingTargetForSelector_(%rip), %rdx + call class_respondsToSelector + + testq %rax, %rax + jz 0f + + movq -0x30(%rbp), %rcx + leaq .Lsel_forwardingTargetForSelector_(%rip), %rdx + call objc_msg_lookup + + movq -0x30(%rbp), %rcx + leaq .Lsel_forwardingTargetForSelector_(%rip), %rdx + movq -0x38(%rbp), %r8 + call *%rax + + testq %rax, %rax + jz 0f + cmpq -0x30(%rbp), %rax + je 0f + + movq %rax, -0x30(%rbp) + + movq %rax, %rcx + movq -0x38(%rbp), %rdx + call objc_msg_lookup + movq %rax, %r11 + + /* Restore all arguments */ + movaps -0x90(%rbp), %xmm3 + movaps -0x80(%rbp), %xmm2 + movaps -0x70(%rbp), %xmm1 + movaps -0x60(%rbp), %xmm0 + movq -0x48(%rbp), %r9 + movq -0x40(%rbp), %r8 + movq -0x38(%rbp), %rdx + movq -0x30(%rbp), %rcx + movq -0x28(%rbp), %rax + + movq %rbp, %rsp + popq %rbp + + jmpq *%r11 + +0: + movq -0x30(%rbp), %rcx + movq -0x38(%rbp), %rdx + + movq %rbp, %rsp + popq %rbp + + jmp OFMethodNotFound +.def OFForward +.scl 2 +.type 32 +.endef + +OFForward_stret: + pushq %rbp + movq %rsp, %rbp + + /* Save all arguments */ + subq $0x90, %rsp /* 16-byte alignment */ + movq %rax, -0x28(%rbp) + movq %rcx, -0x30(%rbp) + movq %rdx, -0x38(%rbp) + movq %r8, -0x40(%rbp) + movq %r9, -0x48(%rbp) + movaps %xmm0, -0x60(%rbp) + movaps %xmm1, -0x70(%rbp) + movaps %xmm2, -0x80(%rbp) + movaps %xmm3, -0x90(%rbp) + + movq %rdx, %rcx + call object_getClass + + movq %rax, %rcx + leaq .Lsel_forwardingTargetForSelector_(%rip), %rdx + call class_respondsToSelector + + testq %rax, %rax + jz 0f + + movq -0x38(%rbp), %rcx + leaq .Lsel_forwardingTargetForSelector_(%rip), %rdx + call objc_msg_lookup + + movq -0x38(%rbp), %rcx + leaq .Lsel_forwardingTargetForSelector_(%rip), %rdx + movq -0x40(%rbp), %r8 + call *%rax + + testq %rax, %rax + jz 0f + cmpq -0x38(%rbp), %rax + je 0f + + movq %rax, -0x38(%rbp) + + movq %rax, %rcx + movq -0x40(%rbp), %rdx + call objc_msg_lookup_stret + movq %rax, %r11 + + /* Restore all arguments */ + movaps -0x90(%rbp), %xmm3 + movaps -0x80(%rbp), %xmm2 + movaps -0x70(%rbp), %xmm1 + movaps -0x60(%rbp), %xmm0 + movq -0x48(%rbp), %r9 + movq -0x40(%rbp), %r8 + movq -0x38(%rbp), %rdx + movq -0x30(%rbp), %rcx + movq -0x28(%rbp), %rax + + movq %rbp, %rsp + popq %rbp + + jmpq *%r11 + +0: + movq -0x30(%rbp), %rcx + movq -0x38(%rbp), %rdx + movq -0x40(%rbp), %r8 + + movq %rbp, %rsp + popq %rbp + + jmp OFMethodNotFound_stret +.def OFForward_stret +.scl 2 +.type 32 +.endef + +.Linit: + leaq .Lmodule(%rip), %rcx + jmp __objc_exec_class + +.section .ctors, "aw" + .quad .Linit + +.section .rodata +.Lstr_forwardingTargetForSelector_: + .asciz "forwardingTargetForSelector:" + +.section .data +.Lsel_forwardingTargetForSelector_: + .quad .Lstr_forwardingTargetForSelector_, 0 + .quad 0, 0 +.Lsymtab: + .long 0, 0 + .quad .Lsel_forwardingTargetForSelector_ + .short 0, 0 + .long 0 + .quad 0 +.Lmodule: + .long 8, 32 + .quad 0, .Lsymtab 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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 @@ #ifdef HAVE_VFP2 vstmdb sp!, {d0-d7} #endif stmfd sp!, {r0-r4, lr} - ldr r4, sel_forwardingTargetForSelector_$indirect_.L0 + ldr r4, .Lsel_forwardingTargetForSelector_$indirect_.L0 .L0: add r4, pc bl object_getClass(PLT) @@ -84,11 +84,11 @@ #ifdef HAVE_VFP2 vstmdb sp!, {d0-d7} #endif stmfd sp!, {r0-r4, lr} - ldr r4, sel_forwardingTargetForSelector_$indirect_.L1 + ldr r4, .Lsel_forwardingTargetForSelector_$indirect_.L1 .L1: add r4, pc mov r0, r1 bl object_getClass(PLT) @@ -134,40 +134,40 @@ #endif b OFMethodNotFound_stret(PLT) .type OFForward_stret, %function .size OFForward_stret, .-OFForward_stret -init: - ldr r0, module$indirect_.L2 +.Linit: + ldr r0, .Lmodule$indirect_.L2 .L2: add r0, pc b __objc_exec_class(PLT) -sel_forwardingTargetForSelector_$indirect_.L0: - .long sel_forwardingTargetForSelector_-(.L0+8) -sel_forwardingTargetForSelector_$indirect_.L1: - .long sel_forwardingTargetForSelector_-(.L1+8) -module$indirect_.L2: - .long module-(.L2+8) +.Lsel_forwardingTargetForSelector_$indirect_.L0: + .long .Lsel_forwardingTargetForSelector_-(.L0+8) +.Lsel_forwardingTargetForSelector_$indirect_.L1: + .long .Lsel_forwardingTargetForSelector_-(.L1+8) +.Lmodule$indirect_.L2: + .long .Lmodule-(.L2+8) .section .init_array, "aw", %init_array - .long init + .long .Linit .section .rodata -str_forwardingTargetForSelector_: +.Lstr_forwardingTargetForSelector_: .asciz "forwardingTargetForSelector:" .section .data -sel_forwardingTargetForSelector_: - .long str_forwardingTargetForSelector_, 0 +.Lsel_forwardingTargetForSelector_: + .long .Lstr_forwardingTargetForSelector_, 0 .long 0, 0 -symtab: - .long 0, sel_forwardingTargetForSelector_ +.Lsymtab: + .long 0, .Lsel_forwardingTargetForSelector_ .short 0, 0 .long 0 .long 0 -module: - .long 8, 16, 0, symtab +.Lmodule: + .long 8, 16, 0, .Lsymtab -#ifdef OF_LINUX +#if defined(OF_LINUX) || defined(OF_HAIKU) || defined(OF_HURD) .section .note.GNU-stack, "", %progbits #endif 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,12 @@ stp q4, q5, [sp, #144] stp q6, q7, [sp, #176] bl object_getClass - adrp x19, sel_forwardingTargetForSelector_ - add x19, x19, :lo12:sel_forwardingTargetForSelector_ + adrp x19, .Lsel_forwardingTargetForSelector_ + add x19, x19, :lo12:.Lsel_forwardingTargetForSelector_ mov x1, x19 bl class_respondsToSelector cbz x0, 0f @@ -100,32 +100,32 @@ .type OFForward, %function .size OFForward, .-OFForward .type OFForward_stret, %function .size OFForward_stret, .-OFForward_stret -init: - adrp x0, module - add x0, x0, :lo12:module +.Linit: + adrp x0, .Lmodule + add x0, x0, :lo12:.Lmodule b __objc_exec_class .section .init_array, "aw", %init_array - .xword init + .xword .Linit .section .rodata -str_forwardingTargetForSelector_: +.Lstr_forwardingTargetForSelector_: .asciz "forwardingTargetForSelector:" .section .data -sel_forwardingTargetForSelector_: - .xword str_forwardingTargetForSelector_, 0 +.Lsel_forwardingTargetForSelector_: + .xword .Lstr_forwardingTargetForSelector_, 0 .xword 0, 0 -symtab: - .xword 0, sel_forwardingTargetForSelector_ +.Lsymtab: + .xword 0, .Lsel_forwardingTargetForSelector_ .short 0, 0 .long 4 .xword 0 -module: - .xword 8, 32, 0, symtab +.Lmodule: + .xword 8, 32, 0, .Lsymtab -#ifdef OF_LINUX +#if defined(OF_LINUX) || defined(OF_HAIKU) || defined(OF_HURD) .section .note.GNU-stack, "", %progbits #endif 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,15 +80,15 @@ swc1 $f19, 88($sp) #endif move $s0, $gp #ifdef OF_PIC - lw $s1, %got(sel_forwardingTargetForSelector_)($gp) + lw $s1, %got(.Lsel_forwardingTargetForSelector_)($gp) #else - lui $s1, %hi(sel_forwardingTargetForSelector_) + lui $s1, %hi(.Lsel_forwardingTargetForSelector_) #endif - addiu $s1, $s1, %lo(sel_forwardingTargetForSelector_) + addiu $s1, $s1, %lo(.Lsel_forwardingTargetForSelector_) jal_pic object_getClass move $gp, $s0 move $a0, $v0 @@ -204,15 +204,15 @@ swc1 $f19, 88($sp) #endif move $s0, $gp #ifdef OF_PIC - lw $s1, %got(sel_forwardingTargetForSelector_)($gp) + lw $s1, %got(.Lsel_forwardingTargetForSelector_)($gp) #else - lui $s1, %hi(sel_forwardingTargetForSelector_) + lui $s1, %hi(.Lsel_forwardingTargetForSelector_) #endif - addiu $s1, $s1, %lo(sel_forwardingTargetForSelector_) + addiu $s1, $s1, %lo(.Lsel_forwardingTargetForSelector_) move $a0, $a1 jal_pic object_getClass move $gp, $s0 @@ -287,43 +287,43 @@ j_pic of_method_not_found_stret .type OFForward_stret, %function .size OFForward_stret, .-OFForward_stret -init: +.Linit: #ifdef OF_PIC lui $gp, %hi(_gp_disp) addiu $gp, $gp, %lo(_gp_disp) addu $gp, $gp, $t9 - lw $a0, %got(module)($gp) - addiu $a0, $a0, %lo(module) + lw $a0, %got(.Lmodule)($gp) + addiu $a0, $a0, %lo(.Lmodule) lw $t9, %call16(__objc_exec_class)($gp) jr $t9 #else - lui $a0, %hi(module) - addiu $a0, $a0, %lo(module) + lui $a0, %hi(.Lmodule) + addiu $a0, $a0, %lo(.Lmodule) j __objc_exec_class #endif .section .ctors, "aw", %progbits - .long init + .long .Linit .section .rodata -str_forwardingTargetForSelector_: +.Lstr_forwardingTargetForSelector_: .asciz "forwardingTargetForSelector:" .section .data -sel_forwardingTargetForSelector_: - .long str_forwardingTargetForSelector_, 0 +.Lsel_forwardingTargetForSelector_: + .long .Lstr_forwardingTargetForSelector_, 0 .long 0, 0 -symtab: - .long 0, sel_forwardingTargetForSelector_ +.Lsymtab: + .long 0, .Lsel_forwardingTargetForSelector_ .short 0, 0 .long 0 .long 0 -module: - .long 8, 16, 0, symtab +.Lmodule: + .long 8, 16, 0, .Lsymtab -#ifdef OF_LINUX +#if defined(OF_LINUX) || defined(OF_HAIKU) || defined(OF_HURD) .section .note.GNU-stack, "", %progbits #endif 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,12 +61,12 @@ lwz %r4, .Lgot_sel_forwardingTargetForSelector_-.Lbiased_got2(%r30) bl class_respondsToSelector+0x8000@plt #else bl object_getClass - lis %r4, sel_forwardingTargetForSelector_@ha - la %r4, sel_forwardingTargetForSelector_@l(%r4) + lis %r4, .Lsel_forwardingTargetForSelector_@ha + la %r4, .Lsel_forwardingTargetForSelector_@l(%r4) bl class_respondsToSelector #endif cmpwi %r3, 0 beq- 0f @@ -74,22 +74,22 @@ lwz %r3, 8(%r1) #ifdef OF_PIC lwz %r4, .Lgot_sel_forwardingTargetForSelector_-.Lbiased_got2(%r30) bl objc_msg_lookup+0x8000@plt #else - lis %r4, sel_forwardingTargetForSelector_@ha - la %r4, sel_forwardingTargetForSelector_@l(%r4) + lis %r4, .Lsel_forwardingTargetForSelector_@ha + la %r4, .Lsel_forwardingTargetForSelector_@l(%r4) bl objc_msg_lookup #endif mtctr %r3 lwz %r3, 8(%r1) #ifdef OF_PIC lwz %r4, .Lgot_sel_forwardingTargetForSelector_-.Lbiased_got2(%r30) #else - lis %r4, sel_forwardingTargetForSelector_@ha - la %r4, sel_forwardingTargetForSelector_@l(%r4) + lis %r4, .Lsel_forwardingTargetForSelector_@ha + la %r4, .Lsel_forwardingTargetForSelector_@l(%r4) #endif lwz %r5, 12(%r1) bctrl cmpwi %r3, 0 @@ -199,12 +199,12 @@ lwz %r4, .Lgot_sel_forwardingTargetForSelector_-.Lbiased_got2(%r30) bl class_respondsToSelector+0x8000@plt #else bl object_getClass - lis %r4, sel_forwardingTargetForSelector_@ha - la %r4, sel_forwardingTargetForSelector_@l(%r4) + lis %r4, .Lsel_forwardingTargetForSelector_@ha + la %r4, .Lsel_forwardingTargetForSelector_@l(%r4) bl class_respondsToSelector #endif cmpwi %r3, 0 beq- 0f @@ -212,22 +212,22 @@ lwz %r3, 12(%r1) #ifdef OF_PIC lwz %r4, .Lgot_sel_forwardingTargetForSelector_-.Lbiased_got2(%r30) bl objc_msg_lookup+0x8000@plt #else - lis %r4, sel_forwardingTargetForSelector_@ha - la %r4, sel_forwardingTargetForSelector_@l(%r4) + lis %r4, .Lsel_forwardingTargetForSelector_@ha + la %r4, .Lsel_forwardingTargetForSelector_@l(%r4) bl objc_msg_lookup #endif mtctr %r3 lwz %r3, 12(%r1) #ifdef OF_PIC lwz %r4, .Lgot_sel_forwardingTargetForSelector_-.Lbiased_got2(%r30) #else - lis %r4, sel_forwardingTargetForSelector_@ha - la %r4, sel_forwardingTargetForSelector_@l(%r4) + lis %r4, .Lsel_forwardingTargetForSelector_@ha + la %r4, .Lsel_forwardingTargetForSelector_@l(%r4) #endif lwz %r5, 16(%r1) bctrl cmpwi %r3, 0 @@ -295,11 +295,11 @@ b OFMethodNotFound_stret #endif .type OFForward_stret, @function .size OFForward_stret, .-OFForward_stret -init: +.Linit: stwu %r1, -16(%r1) mflr %r0 stw %r0, 20(%r1) #ifdef OF_PIC stw %r30, 8(%r1) @@ -313,50 +313,50 @@ lwz %r3, .Lgot_module-.Lbiased_got2(%r30) bl __objc_exec_class+0x8000@plt lwz %r30, 8(%r1) #else - lis %r3, module@ha - la %r3, module@l(%r3) + lis %r3, .Lmodule@ha + la %r3, .Lmodule@l(%r3) bl __objc_exec_class #endif lwz %r0, 20(%r1) addi %r1, %r1, 16 mtlr %r0 blr .section .ctors, "aw", @progbits - .long init + .long .Linit .section .rodata -str_forwardingTargetForSelector_: +.Lstr_forwardingTargetForSelector_: .asciz "forwardingTargetForSelector:" .section .data -sel_forwardingTargetForSelector_: - .long str_forwardingTargetForSelector_, 0 +.Lsel_forwardingTargetForSelector_: + .long .Lstr_forwardingTargetForSelector_, 0 .long 0, 0 -symtab: - .long 0, sel_forwardingTargetForSelector_ +.Lsymtab: + .long 0, .Lsel_forwardingTargetForSelector_ .short 0, 0 .long 0 .long 0 -module: - .long 8, 16, 0, symtab +.Lmodule: + .long 8, 16, 0, .Lsymtab #ifdef OF_PIC .section .got2, "aw" .Lbiased_got2 = .+0x8000 .Lgot_module: - .long module + .long .Lmodule .Lgot_sel_forwardingTargetForSelector_: - .long sel_forwardingTargetForSelector_ + .long .Lsel_forwardingTargetForSelector_ .Lgot_OFMethodNotFound: .long OFMethodNotFound .Lgot_OFMethodNotFound_stret: .long OFMethodNotFound_stret #endif -#ifdef OF_LINUX +#if defined(OF_LINUX) || defined(OF_HAIKU) || defined(OF_HURD) .section .note.GNU-stack, "", @progbits #endif 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,12 @@ mov %i0, %o0 call object_getClass nop - sethi %hi(sel_forwardingTargetForSelector_), %o1 - or %o1, %lo(sel_forwardingTargetForSelector_), %o1 + sethi %hi(.Lsel_forwardingTargetForSelector_), %o1 + or %o1, %lo(.Lsel_forwardingTargetForSelector_), %o1 #ifdef OF_PIC ld [%l7 + %o1], %o1 #endif call class_respondsToSelector nop @@ -44,22 +44,22 @@ cmp %o0, 0 be 0f mov %i0, %o0 - sethi %hi(sel_forwardingTargetForSelector_), %o1 - or %o1, %lo(sel_forwardingTargetForSelector_), %o1 + sethi %hi(.Lsel_forwardingTargetForSelector_), %o1 + or %o1, %lo(.Lsel_forwardingTargetForSelector_), %o1 #ifdef OF_PIC ld [%l7 + %o1], %o1 #endif call objc_msg_lookup nop mov %o0, %l0 mov %i0, %o0 - sethi %hi(sel_forwardingTargetForSelector_), %o1 - or %o1, %lo(sel_forwardingTargetForSelector_), %o1 + sethi %hi(.Lsel_forwardingTargetForSelector_), %o1 + or %o1, %lo(.Lsel_forwardingTargetForSelector_), %o1 #ifdef OF_PIC ld [%l7 + %o1], %o1 #endif jmpl %l0, %o7 mov %i1, %o2 @@ -93,12 +93,12 @@ mov %i1, %o0 call object_getClass nop - sethi %hi(sel_forwardingTargetForSelector_), %o1 - or %o1, %lo(sel_forwardingTargetForSelector_), %o1 + sethi %hi(.Lsel_forwardingTargetForSelector_), %o1 + or %o1, %lo(.Lsel_forwardingTargetForSelector_), %o1 #ifdef OF_PIC ld [%l7 + %o1], %o1 #endif call class_respondsToSelector nop @@ -105,22 +105,22 @@ cmp %o0, 0 be 0f mov %i1, %o0 - sethi %hi(sel_forwardingTargetForSelector_), %o1 - or %o1, %lo(sel_forwardingTargetForSelector_), %o1 + sethi %hi(.Lsel_forwardingTargetForSelector_), %o1 + or %o1, %lo(.Lsel_forwardingTargetForSelector_), %o1 #ifdef OF_PIC ld [%l7 + %o1], %o1 #endif call objc_msg_lookup nop mov %o0, %l0 mov %i1, %o0 - sethi %hi(sel_forwardingTargetForSelector_), %o1 - or %o1, %lo(sel_forwardingTargetForSelector_), %o1 + sethi %hi(.Lsel_forwardingTargetForSelector_), %o1 + or %o1, %lo(.Lsel_forwardingTargetForSelector_), %o1 #ifdef OF_PIC ld [%l7 + %o1], %o1 #endif jmpl %l0, %o7 mov %i2, %o2 @@ -141,21 +141,21 @@ call OFMethodNotFound_stret restore .type OFForward_stret, %function .size OFForward_stret, .-OFForward_stret -init: +.Linit: save %sp, -96, %sp #ifdef OF_PIC sethi %hi(_GLOBAL_OFFSET_TABLE_ - 4), %l7 call add_pc add %l7, %lo(_GLOBAL_OFFSET_TABLE_ + 4), %l7 #endif - sethi %hi(module), %i0 - or %i0, %lo(module), %i0 + sethi %hi(.Lmodule), %i0 + or %i0, %lo(.Lmodule), %i0 #ifdef OF_PIC ld [%l7 + %i0], %i0 #endif call __objc_exec_class @@ -170,26 +170,26 @@ #ifdef OF_SOLARIS .section .init_array, "aw" #else .section .ctors, "aw", %progbits #endif - .word init + .word .Linit .section .rodata -str_forwardingTargetForSelector_: +.Lstr_forwardingTargetForSelector_: .asciz "forwardingTargetForSelector:" .section .data -sel_forwardingTargetForSelector_: - .word str_forwardingTargetForSelector_, 0 +.Lsel_forwardingTargetForSelector_: + .word .Lstr_forwardingTargetForSelector_, 0 .word 0, 0 -symtab: - .word 0, sel_forwardingTargetForSelector_ +.Lsymtab: + .word 0, .Lsel_forwardingTargetForSelector_ .half 0, 0 .word 0 .word 0 -module: - .word 8, 16, 0, symtab +.Lmodule: + .word 8, 16, 0, .Lsymtab -#ifdef OF_LINUX +#if defined(OF_LINUX) || defined(OF_HAIKU) || defined(OF_HURD) .section .note.GNU-stack, "", %progbits #endif 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,36 +46,36 @@ std %f26, [%sp + BIAS + 280] std %f28, [%sp + BIAS + 288] std %f30, [%sp + BIAS + 296] sethi %hi(_GLOBAL_OFFSET_TABLE_ - 4), %l7 - call add_pc + call .LaddPC add %l7, %lo(_GLOBAL_OFFSET_TABLE_ + 4), %l7 mov %i0, %o0 call object_getClass nop - sethi %hi(sel_forwardingTargetForSelector_), %o1 - or %o1, %lo(sel_forwardingTargetForSelector_), %o1 + sethi %hi(.Lsel_forwardingTargetForSelector_), %o1 + or %o1, %lo(.Lsel_forwardingTargetForSelector_), %o1 ldx [%l7 + %o1], %o1 call class_respondsToSelector nop brz,pn %o0, 0f mov %i0, %o0 - sethi %hi(sel_forwardingTargetForSelector_), %o1 - or %o1, %lo(sel_forwardingTargetForSelector_), %o1 + sethi %hi(.Lsel_forwardingTargetForSelector_), %o1 + or %o1, %lo(.Lsel_forwardingTargetForSelector_), %o1 ldx [%l7 + %o1], %o1 call objc_msg_lookup nop mov %o0, %l0 mov %i0, %o0 - sethi %hi(sel_forwardingTargetForSelector_), %o1 - or %o1, %lo(sel_forwardingTargetForSelector_), %o1 + sethi %hi(.Lsel_forwardingTargetForSelector_), %o1 + or %o1, %lo(.Lsel_forwardingTargetForSelector_), %o1 ldx [%l7 + %o1], %o1 jmpl %l0, %o7 mov %i1, %o2 brz,pn %o0, 0f @@ -139,36 +139,36 @@ std %f26, [%sp + BIAS + 280] std %f28, [%sp + BIAS + 288] std %f30, [%sp + BIAS + 296] sethi %hi(_GLOBAL_OFFSET_TABLE_ - 4), %l7 - call add_pc + call .LaddPC add %l7, %lo(_GLOBAL_OFFSET_TABLE_ + 4), %l7 mov %i1, %o0 call object_getClass nop - sethi %hi(sel_forwardingTargetForSelector_), %o1 - or %o1, %lo(sel_forwardingTargetForSelector_), %o1 + sethi %hi(.Lsel_forwardingTargetForSelector_), %o1 + or %o1, %lo(.Lsel_forwardingTargetForSelector_), %o1 ldx [%l7 + %o1], %o1 call class_respondsToSelector nop brz,pn %o0, 0f mov %i1, %o0 - sethi %hi(sel_forwardingTargetForSelector_), %o1 - or %o1, %lo(sel_forwardingTargetForSelector_), %o1 + sethi %hi(.Lsel_forwardingTargetForSelector_), %o1 + or %o1, %lo(.Lsel_forwardingTargetForSelector_), %o1 ldx [%l7 + %o1], %o1 call objc_msg_lookup nop mov %o0, %l0 mov %i1, %o0 - sethi %hi(sel_forwardingTargetForSelector_), %o1 - or %o1, %lo(sel_forwardingTargetForSelector_), %o1 + sethi %hi(.Lsel_forwardingTargetForSelector_), %o1 + or %o1, %lo(.Lsel_forwardingTargetForSelector_), %o1 ldx [%l7 + %o1], %o1 jmpl %l0, %o7 mov %i2, %o2 brz,pn %o0, 0f @@ -207,49 +207,49 @@ call OFMethodNotFound_stret restore .type OFForward_stret, %function .size OFForward_stret, .-OFForward_stret -init: +.Linit: save %sp, -176, %sp sethi %hi(_GLOBAL_OFFSET_TABLE_ - 4), %l7 - call add_pc + call .LaddPC add %l7, %lo(_GLOBAL_OFFSET_TABLE_ + 4), %l7 - sethi %hi(module), %i0 - or %i0, %lo(module), %i0 + sethi %hi(.Lmodule), %i0 + or %i0, %lo(.Lmodule), %i0 ldx [%l7 + %i0], %i0 call __objc_exec_class restore -add_pc: +.LaddPC: jmp %o7 + 8 add %l7, %o7, %l7 #ifdef OF_SOLARIS .section .init_array, "aw" #else .section .ctors, "aw", %progbits #endif - .xword init + .xword .Linit .section .rodata -str_forwardingTargetForSelector_: +.Lstr_forwardingTargetForSelector_: .asciz "forwardingTargetForSelector:" .section .data -sel_forwardingTargetForSelector_: - .xword str_forwardingTargetForSelector_, 0 +.Lsel_forwardingTargetForSelector_: + .xword .Lstr_forwardingTargetForSelector_, 0 .xword 0, 0 -symtab: - .xword 0, sel_forwardingTargetForSelector_ +.Lsymtab: + .xword 0, .Lsel_forwardingTargetForSelector_ .half 0, 0 .word 0 .xword 0 -module: - .xword 8, 32, 0, symtab +.Lmodule: + .xword 8, 32, 0, .Lsymtab -#ifdef OF_LINUX +#if defined(OF_LINUX) || defined(OF_HAIKU) || defined(OF_HURD) .section .note.GNU-stack, "", %progbits #endif 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,34 +26,34 @@ movl %esp, %ebp pushl %ebx subl $20, %esp - call get_eip + call .LgetEIP addl $_GLOBAL_OFFSET_TABLE_, %ebx movl 8(%ebp), %eax movl %eax, (%esp) call object_getClass@PLT movl %eax, (%esp) - leal sel_forwardingTargetForSelector_@GOTOFF(%ebx), %eax + leal .Lsel_forwardingTargetForSelector_@GOTOFF(%ebx), %eax movl %eax, 4(%esp) call class_respondsToSelector@PLT testl %eax, %eax jz 0f movl 8(%ebp), %eax movl %eax, (%esp) - leal sel_forwardingTargetForSelector_@GOTOFF(%ebx), %eax + leal .Lsel_forwardingTargetForSelector_@GOTOFF(%ebx), %eax movl %eax, 4(%esp) call objc_msg_lookup@PLT movl 8(%ebp), %edx movl %edx, (%esp) - leal sel_forwardingTargetForSelector_@GOTOFF(%ebx), %edx + leal .Lsel_forwardingTargetForSelector_@GOTOFF(%ebx), %edx movl %edx, 4(%esp) movl 12(%ebp), %edx movl %edx, 8(%esp) call *%eax @@ -73,11 +73,11 @@ popl %ebp jmp *%eax 0: - leal OFMethodNotFound@GOTOFF(%ebx), %eax + movl OFMethodNotFound@GOT(%ebx), %eax addl $20, %esp popl %ebx popl %ebp @@ -90,34 +90,34 @@ movl %esp, %ebp pushl %ebx subl $20, %esp - call get_eip + call .LgetEIP addl $_GLOBAL_OFFSET_TABLE_, %ebx movl 12(%ebp), %eax movl %eax, (%esp) call object_getClass@PLT movl %eax, (%esp) - leal sel_forwardingTargetForSelector_@GOTOFF(%ebx), %eax + leal .Lsel_forwardingTargetForSelector_@GOTOFF(%ebx), %eax movl %eax, 4(%esp) call class_respondsToSelector@PLT testl %eax, %eax jz 0f movl 12(%ebp), %eax movl %eax, (%esp) - leal sel_forwardingTargetForSelector_@GOTOFF(%ebx), %eax + leal .Lsel_forwardingTargetForSelector_@GOTOFF(%ebx), %eax movl %eax, 4(%esp) call objc_msg_lookup@PLT movl 12(%ebp), %edx movl %edx, (%esp) - leal sel_forwardingTargetForSelector_@GOTOFF(%ebx), %edx + leal .Lsel_forwardingTargetForSelector_@GOTOFF(%ebx), %edx movl %edx, 4(%esp) movl 16(%ebp), %edx movl %edx, 8(%esp) call *%eax @@ -137,64 +137,64 @@ popl %ebp jmp *%eax 0: - leal OFMethodNotFound_stret@GOTOFF(%ebx), %eax + movl OFMethodNotFound_stret@GOT(%ebx), %eax addl $20, %esp popl %ebx popl %ebp jmp *%eax .type OFForward_stret, %function .size OFForward_stret, .-OFForward_stret -init: +.Linit: pushl %ebp movl %esp, %ebp pushl %ebx subl $4, %esp - call get_eip + call .LgetEIP addl $_GLOBAL_OFFSET_TABLE_, %ebx - leal module@GOTOFF(%ebx), %eax + leal .Lmodule@GOTOFF(%ebx), %eax movl %eax, (%esp) call __objc_exec_class@PLT addl $4, %esp popl %ebx popl %ebp ret -get_eip: +.LgetEIP: movl (%esp), %ebx ret #ifdef OF_SOLARIS .section .init_array, "aw" #else .section .ctors, "aw", %progbits #endif - .long init + .long .Linit .section .rodata -str_forwardingTargetForSelector_: +.Lstr_forwardingTargetForSelector_: .asciz "forwardingTargetForSelector:" .section .data -sel_forwardingTargetForSelector_: - .long str_forwardingTargetForSelector_, 0 +.Lsel_forwardingTargetForSelector_: + .long .Lstr_forwardingTargetForSelector_, 0 .long 0, 0 -symtab: - .long 0, sel_forwardingTargetForSelector_ +.Lsymtab: + .long 0, .Lsel_forwardingTargetForSelector_ .short 0, 0 .long 0 .long 0 -module: - .long 8, 16, 0, symtab +.Lmodule: + .long 8, 16, 0, .Lsymtab -#ifdef OF_LINUX +#if defined(OF_LINUX) || defined(OF_HAIKU) || defined(OF_HURD) .section .note.GNU-stack, "", %progbits #endif 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,26 +29,26 @@ movl 8(%ebp), %eax movl %eax, (%esp) call _object_getClass movl %eax, (%esp) - movl $sel_forwardingTargetForSelector_, %eax + movl $.Lsel_forwardingTargetForSelector_, %eax movl %eax, 4(%esp) call _class_respondsToSelector testl %eax, %eax jz 0f movl 8(%ebp), %eax movl %eax, (%esp) - movl $sel_forwardingTargetForSelector_, %eax + movl $.Lsel_forwardingTargetForSelector_, %eax movl %eax, 4(%esp) call _objc_msg_lookup movl 8(%ebp), %edx movl %edx, (%esp) - movl $sel_forwardingTargetForSelector_, %edx + movl $.Lsel_forwardingTargetForSelector_, %edx movl %edx, 4(%esp) movl 12(%ebp), %edx movl %edx, 8(%esp) call *%eax @@ -90,26 +90,26 @@ movl 12(%ebp), %eax movl %eax, (%esp) call _object_getClass movl %eax, (%esp) - movl $sel_forwardingTargetForSelector_, %eax + movl $.Lsel_forwardingTargetForSelector_, %eax movl %eax, 4(%esp) call _class_respondsToSelector testl %eax, %eax jz 0f movl 12(%ebp), %eax movl %eax, (%esp) - movl $sel_forwardingTargetForSelector_, %eax + movl $.Lsel_forwardingTargetForSelector_, %eax movl %eax, 4(%esp) call _objc_msg_lookup movl 12(%ebp), %edx movl %edx, (%esp) - movl $sel_forwardingTargetForSelector_, %edx + movl $.Lsel_forwardingTargetForSelector_, %edx movl %edx, 4(%esp) movl 16(%ebp), %edx movl %edx, 8(%esp) call *%eax @@ -139,39 +139,39 @@ .def _OFForward_stret .scl 2 .type 32 .endef -init: +.Linit: pushl %ebp movl %esp, %ebp pushl %ebx subl $4, %esp - movl $module, %eax + movl $.Lmodule, %eax movl %eax, (%esp) call ___objc_exec_class addl $4, %esp popl %ebx popl %ebp ret .section .ctors, "aw" - .long init + .long .Linit .section .rodata -str_forwardingTargetForSelector_: +.Lstr_forwardingTargetForSelector_: .asciz "forwardingTargetForSelector:" .section .data -sel_forwardingTargetForSelector_: - .long str_forwardingTargetForSelector_, 0 +.Lsel_forwardingTargetForSelector_: + .long .Lstr_forwardingTargetForSelector_, 0 .long 0, 0 -symtab: - .long 0, sel_forwardingTargetForSelector_ +.Lsymtab: + .long 0, .Lsel_forwardingTargetForSelector_ .short 0, 0 .long 0 .long 0 -module: - .long 8, 16, 0, symtab +.Lmodule: + .long 8, 16, 0, .Lsymtab DELETED src/forwarding/forwarding-x86_64-elf.S Index: src/forwarding/forwarding-x86_64-elf.S ================================================================== --- src/forwarding/forwarding-x86_64-elf.S +++ /dev/null @@ -1,225 +0,0 @@ -/* - * Copyright (c) 2008-2022 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#include "config.h" - -#include "platform.h" - -.globl OFForward -.globl OFForward_stret - -.section .text -OFForward: - pushq %rbp - movq %rsp, %rbp - - /* Save all arguments */ - subq $0xC0, %rsp /* 16-byte alignment */ - movq %rax, -0x8(%rbp) - movq %rdi, -0x10(%rbp) - movq %rsi, -0x18(%rbp) - movq %rdx, -0x20(%rbp) - movq %rcx, -0x28(%rbp) - movq %r8, -0x30(%rbp) - movq %r9, -0x38(%rbp) - movaps %xmm0, -0x50(%rbp) - movaps %xmm1, -0x60(%rbp) - movaps %xmm2, -0x70(%rbp) - movaps %xmm3, -0x80(%rbp) - movaps %xmm4, -0x90(%rbp) - movaps %xmm5, -0xA0(%rbp) - movaps %xmm6, -0xB0(%rbp) - movaps %xmm7, -0xC0(%rbp) - - call object_getClass@PLT - - movq %rax, %rdi - leaq sel_forwardingTargetForSelector_(%rip), %rsi - call class_respondsToSelector@PLT - - testq %rax, %rax - jz 0f - - movq -0x10(%rbp), %rdi - leaq sel_forwardingTargetForSelector_(%rip), %rsi - call objc_msg_lookup@PLT - - movq -0x10(%rbp), %rdi - leaq sel_forwardingTargetForSelector_(%rip), %rsi - movq -0x18(%rbp), %rdx - call *%rax - - testq %rax, %rax - jz 0f - cmpq -0x10(%rbp), %rax - je 0f - - movq %rax, -0x10(%rbp) - - movq %rax, %rdi - movq -0x18(%rbp), %rsi - call objc_msg_lookup@PLT - movq %rax, %r11 - - /* Restore all arguments */ - movaps -0xC0(%rbp), %xmm7 - movaps -0xB0(%rbp), %xmm6 - movaps -0xA0(%rbp), %xmm5 - movaps -0x90(%rbp), %xmm4 - movaps -0x80(%rbp), %xmm3 - movaps -0x70(%rbp), %xmm2 - movaps -0x60(%rbp), %xmm1 - movaps -0x50(%rbp), %xmm0 - movq -0x38(%rbp), %r9 - movq -0x30(%rbp), %r8 - movq -0x28(%rbp), %rcx - movq -0x20(%rbp), %rdx - movq -0x18(%rbp), %rsi - movq -0x10(%rbp), %rdi - movq -0x8(%rbp), %rax - - movq %rbp, %rsp - popq %rbp - - jmpq *%r11 - -0: - movq -0x10(%rbp), %rdi - movq -0x18(%rbp), %rsi - - movq %rbp, %rsp - popq %rbp - - jmp OFMethodNotFound@PLT -.type OFForward, %function -.size OFForward, .-OFForward - -OFForward_stret: - pushq %rbp - movq %rsp, %rbp - - /* Save all arguments */ - subq $0xC0, %rsp /* 16-byte alignment */ - movq %rax, -0x8(%rbp) - movq %rdi, -0x10(%rbp) - movq %rsi, -0x18(%rbp) - movq %rdx, -0x20(%rbp) - movq %rcx, -0x28(%rbp) - movq %r8, -0x30(%rbp) - movq %r9, -0x38(%rbp) - movaps %xmm0, -0x50(%rbp) - movaps %xmm1, -0x60(%rbp) - movaps %xmm2, -0x70(%rbp) - movaps %xmm3, -0x80(%rbp) - movaps %xmm4, -0x90(%rbp) - movaps %xmm5, -0xA0(%rbp) - movaps %xmm6, -0xB0(%rbp) - movaps %xmm7, -0xC0(%rbp) - - movq %rsi, %rdi - call object_getClass@PLT - - movq %rax, %rdi - leaq sel_forwardingTargetForSelector_(%rip), %rsi - call class_respondsToSelector@PLT - - testq %rax, %rax - jz 0f - - movq -0x18(%rbp), %rdi - leaq sel_forwardingTargetForSelector_(%rip), %rsi - call objc_msg_lookup@PLT - - movq -0x18(%rbp), %rdi - leaq sel_forwardingTargetForSelector_(%rip), %rsi - movq -0x20(%rbp), %rdx - call *%rax - - testq %rax, %rax - jz 0f - cmpq -0x18(%rbp), %rax - je 0f - - movq %rax, -0x18(%rbp) - - movq %rax, %rdi - movq -0x20(%rbp), %rsi - call objc_msg_lookup_stret@PLT - movq %rax, %r11 - - /* Restore all arguments */ - movaps -0xC0(%rbp), %xmm7 - movaps -0xB0(%rbp), %xmm6 - movaps -0xA0(%rbp), %xmm5 - movaps -0x90(%rbp), %xmm4 - movaps -0x80(%rbp), %xmm3 - movaps -0x70(%rbp), %xmm2 - movaps -0x60(%rbp), %xmm1 - movaps -0x50(%rbp), %xmm0 - movq -0x38(%rbp), %r9 - movq -0x30(%rbp), %r8 - movq -0x28(%rbp), %rcx - movq -0x20(%rbp), %rdx - movq -0x18(%rbp), %rsi - movq -0x10(%rbp), %rdi - movq -0x8(%rbp), %rax - - movq %rbp, %rsp - popq %rbp - - jmpq *%r11 - -0: - movq -0x10(%rbp), %rdi - movq -0x18(%rbp), %rsi - movq -0x20(%rbp), %rdx - - movq %rbp, %rsp - popq %rbp - - jmp OFMethodNotFound_stret@PLT -.type OFForward_stret, %function -.size OFForward_stret, .-OFForward_stret - -init: - leaq module(%rip), %rdi - jmp __objc_exec_class@PLT - -#ifdef OF_SOLARIS -.section .init_array, "aw" -#else -.section .ctors, "aw", %progbits -#endif - .quad init - -.section .rodata -str_forwardingTargetForSelector_: - .asciz "forwardingTargetForSelector:" - -.section .data -sel_forwardingTargetForSelector_: - .quad str_forwardingTargetForSelector_, 0 - .quad 0, 0 -symtab: - .quad 0, sel_forwardingTargetForSelector_ - .short 0, 0 - .long 0 - .quad 0 -module: - .quad 8, 32, 0, symtab - -#ifdef OF_LINUX -.section .note.GNU-stack, "", %progbits -#endif DELETED src/forwarding/forwarding-x86_64-macho.S Index: src/forwarding/forwarding-x86_64-macho.S ================================================================== --- src/forwarding/forwarding-x86_64-macho.S +++ /dev/null @@ -1,213 +0,0 @@ -/* - * Copyright (c) 2008-2022 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#include "config.h" - -#include "platform.h" - -.globl _OFForward -.globl _OFForward_stret - -.section __TEXT, __text, regular, pure_instructions -_OFForward: - pushq %rbp - movq %rsp, %rbp - - /* Save all arguments */ - subq $0xC0, %rsp /* 16-byte alignment */ - movq %rax, -0x8(%rbp) - movq %rdi, -0x10(%rbp) - movq %rsi, -0x18(%rbp) - movq %rdx, -0x20(%rbp) - movq %rcx, -0x28(%rbp) - movq %r8, -0x30(%rbp) - movq %r9, -0x38(%rbp) - movaps %xmm0, -0x50(%rbp) - movaps %xmm1, -0x60(%rbp) - movaps %xmm2, -0x70(%rbp) - movaps %xmm3, -0x80(%rbp) - movaps %xmm4, -0x90(%rbp) - movaps %xmm5, -0xA0(%rbp) - movaps %xmm6, -0xB0(%rbp) - movaps %xmm7, -0xC0(%rbp) - - call _object_getClass - - movq %rax, %rdi - leaq sel_forwardingTargetForSelector_(%rip), %rsi - call _class_respondsToSelector - - testq %rax, %rax - jz 0f - - movq -0x10(%rbp), %rdi - leaq sel_forwardingTargetForSelector_(%rip), %rsi - call _objc_msg_lookup - - movq -0x10(%rbp), %rdi - leaq sel_forwardingTargetForSelector_(%rip), %rsi - movq -0x18(%rbp), %rdx - call *%rax - - testq %rax, %rax - jz 0f - cmpq -0x10(%rbp), %rax - je 0f - - movq %rax, -0x10(%rbp) - - movq %rax, %rdi - movq -0x18(%rbp), %rsi - call _objc_msg_lookup - movq %rax, %r11 - - /* Restore all arguments */ - movaps -0xC0(%rbp), %xmm7 - movaps -0xB0(%rbp), %xmm6 - movaps -0xA0(%rbp), %xmm5 - movaps -0x90(%rbp), %xmm4 - movaps -0x80(%rbp), %xmm3 - movaps -0x70(%rbp), %xmm2 - movaps -0x60(%rbp), %xmm1 - movaps -0x50(%rbp), %xmm0 - movq -0x38(%rbp), %r9 - movq -0x30(%rbp), %r8 - movq -0x28(%rbp), %rcx - movq -0x20(%rbp), %rdx - movq -0x18(%rbp), %rsi - movq -0x10(%rbp), %rdi - movq -0x8(%rbp), %rax - - movq %rbp, %rsp - popq %rbp - - jmpq *%r11 - -0: - movq -0x10(%rbp), %rdi - movq -0x18(%rbp), %rsi - - movq %rbp, %rsp - popq %rbp - - jmp _OFMethodNotFound - -_OFForward_stret: - pushq %rbp - movq %rsp, %rbp - - /* Save all arguments */ - subq $0xC0, %rsp /* 16-byte alignment */ - movq %rax, -0x8(%rbp) - movq %rdi, -0x10(%rbp) - movq %rsi, -0x18(%rbp) - movq %rdx, -0x20(%rbp) - movq %rcx, -0x28(%rbp) - movq %r8, -0x30(%rbp) - movq %r9, -0x38(%rbp) - movaps %xmm0, -0x50(%rbp) - movaps %xmm1, -0x60(%rbp) - movaps %xmm2, -0x70(%rbp) - movaps %xmm3, -0x80(%rbp) - movaps %xmm4, -0x90(%rbp) - movaps %xmm5, -0xA0(%rbp) - movaps %xmm6, -0xB0(%rbp) - movaps %xmm7, -0xC0(%rbp) - - movq %rsi, %rdi - call _object_getClass - - movq %rax, %rdi - leaq sel_forwardingTargetForSelector_(%rip), %rsi - call _class_respondsToSelector - - testq %rax, %rax - jz 0f - - movq -0x18(%rbp), %rdi - leaq sel_forwardingTargetForSelector_(%rip), %rsi - call _objc_msg_lookup - - movq -0x18(%rbp), %rdi - leaq sel_forwardingTargetForSelector_(%rip), %rsi - movq -0x20(%rbp), %rdx - call *%rax - - testq %rax, %rax - jz 0f - cmpq -0x18(%rbp), %rax - je 0f - - movq %rax, -0x18(%rbp) - - movq %rax, %rdi - movq -0x20(%rbp), %rsi - call _objc_msg_lookup_stret - movq %rax, %r11 - - /* Restore all arguments */ - movaps -0xC0(%rbp), %xmm7 - movaps -0xB0(%rbp), %xmm6 - movaps -0xA0(%rbp), %xmm5 - movaps -0x90(%rbp), %xmm4 - movaps -0x80(%rbp), %xmm3 - movaps -0x70(%rbp), %xmm2 - movaps -0x60(%rbp), %xmm1 - movaps -0x50(%rbp), %xmm0 - movq -0x38(%rbp), %r9 - movq -0x30(%rbp), %r8 - movq -0x28(%rbp), %rcx - movq -0x20(%rbp), %rdx - movq -0x18(%rbp), %rsi - movq -0x10(%rbp), %rdi - movq -0x8(%rbp), %rax - - movq %rbp, %rsp - popq %rbp - - jmpq *%r11 - -0: - movq -0x10(%rbp), %rdi - movq -0x18(%rbp), %rsi - movq -0x20(%rbp), %rdx - - movq %rbp, %rsp - popq %rbp - - jmp _OFMethodNotFound_stret - -init: - leaq module(%rip), %rdi - jmp ___objc_exec_class - -.section __DATA, __mod_init_func, mod_init_funcs - .quad init - -.section __TEXT, __cstring, cstring_literals -str_forwardingTargetForSelector_: - .asciz "forwardingTargetForSelector:" - -.section __DATA, __data -sel_forwardingTargetForSelector_: - .quad str_forwardingTargetForSelector_, 0 - .quad 0, 0 -symtab: - .quad 0, sel_forwardingTargetForSelector_ - .short 0, 0 - .long 0 - .quad 0 -module: - .quad 8, 32, 0, symtab DELETED src/forwarding/forwarding-x86_64-win64.S Index: src/forwarding/forwarding-x86_64-win64.S ================================================================== --- src/forwarding/forwarding-x86_64-win64.S +++ /dev/null @@ -1,197 +0,0 @@ -/* - * Copyright (c) 2008-2022 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#include "config.h" - -.globl OFForward -.globl OFForward_stret - -.section .text -OFForward: - pushq %rbp - movq %rsp, %rbp - - /* Save all arguments */ - subq $0x90, %rsp /* 16-byte alignment */ - movq %rax, -0x28(%rbp) - movq %rcx, -0x30(%rbp) - movq %rdx, -0x38(%rbp) - movq %r8, -0x40(%rbp) - movq %r9, -0x48(%rbp) - movaps %xmm0, -0x60(%rbp) - movaps %xmm1, -0x70(%rbp) - movaps %xmm2, -0x80(%rbp) - movaps %xmm3, -0x90(%rbp) - - call object_getClass - - movq %rax, %rcx - leaq sel_forwardingTargetForSelector_(%rip), %rdx - call class_respondsToSelector - - testq %rax, %rax - jz 0f - - movq -0x30(%rbp), %rcx - leaq sel_forwardingTargetForSelector_(%rip), %rdx - call objc_msg_lookup - - movq -0x30(%rbp), %rcx - leaq sel_forwardingTargetForSelector_(%rip), %rdx - movq -0x38(%rbp), %r8 - call *%rax - - testq %rax, %rax - jz 0f - cmpq -0x30(%rbp), %rax - je 0f - - movq %rax, -0x30(%rbp) - - movq %rax, %rcx - movq -0x38(%rbp), %rdx - call objc_msg_lookup - movq %rax, %r11 - - /* Restore all arguments */ - movaps -0x90(%rbp), %xmm3 - movaps -0x80(%rbp), %xmm2 - movaps -0x70(%rbp), %xmm1 - movaps -0x60(%rbp), %xmm0 - movq -0x48(%rbp), %r9 - movq -0x40(%rbp), %r8 - movq -0x38(%rbp), %rdx - movq -0x30(%rbp), %rcx - movq -0x28(%rbp), %rax - - movq %rbp, %rsp - popq %rbp - - jmpq *%r11 - -0: - movq -0x30(%rbp), %rcx - movq -0x38(%rbp), %rdx - - movq %rbp, %rsp - popq %rbp - - jmp OFMethodNotFound -.def OFForward -.scl 2 -.type 32 -.endef - -OFForward_stret: - pushq %rbp - movq %rsp, %rbp - - /* Save all arguments */ - subq $0x90, %rsp /* 16-byte alignment */ - movq %rax, -0x28(%rbp) - movq %rcx, -0x30(%rbp) - movq %rdx, -0x38(%rbp) - movq %r8, -0x40(%rbp) - movq %r9, -0x48(%rbp) - movaps %xmm0, -0x60(%rbp) - movaps %xmm1, -0x70(%rbp) - movaps %xmm2, -0x80(%rbp) - movaps %xmm3, -0x90(%rbp) - - movq %rdx, %rcx - call object_getClass - - movq %rax, %rcx - leaq sel_forwardingTargetForSelector_(%rip), %rdx - call class_respondsToSelector - - testq %rax, %rax - jz 0f - - movq -0x38(%rbp), %rcx - leaq sel_forwardingTargetForSelector_(%rip), %rdx - call objc_msg_lookup - - movq -0x38(%rbp), %rcx - leaq sel_forwardingTargetForSelector_(%rip), %rdx - movq -0x40(%rbp), %r8 - call *%rax - - testq %rax, %rax - jz 0f - cmpq -0x38(%rbp), %rax - je 0f - - movq %rax, -0x38(%rbp) - - movq %rax, %rcx - movq -0x40(%rbp), %rdx - call objc_msg_lookup_stret - movq %rax, %r11 - - /* Restore all arguments */ - movaps -0x90(%rbp), %xmm3 - movaps -0x80(%rbp), %xmm2 - movaps -0x70(%rbp), %xmm1 - movaps -0x60(%rbp), %xmm0 - movq -0x48(%rbp), %r9 - movq -0x40(%rbp), %r8 - movq -0x38(%rbp), %rdx - movq -0x30(%rbp), %rcx - movq -0x28(%rbp), %rax - - movq %rbp, %rsp - popq %rbp - - jmpq *%r11 - -0: - movq -0x30(%rbp), %rcx - movq -0x38(%rbp), %rdx - movq -0x40(%rbp), %r8 - - movq %rbp, %rsp - popq %rbp - - jmp OFMethodNotFound_stret -.def OFForward_stret -.scl 2 -.type 32 -.endef - -init: - leaq module(%rip), %rcx - jmp __objc_exec_class - -.section .ctors, "aw" - .quad init - -.section .rodata -str_forwardingTargetForSelector_: - .asciz "forwardingTargetForSelector:" - -.section .data -sel_forwardingTargetForSelector_: - .quad str_forwardingTargetForSelector_, 0 - .quad 0, 0 -symtab: - .long 0, 0 - .quad sel_forwardingTargetForSelector_ - .short 0, 0 - .long 0 - .quad 0 -module: - .long 8, 32 - .quad 0, symtab Index: src/forwarding/forwarding.S ================================================================== --- src/forwarding/forwarding.S +++ src/forwarding/forwarding.S @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,25 +16,25 @@ #include "config.h" #include "platform.h" #ifdef OF_APPLE_RUNTIME -# if defined(OF_X86_64) -# include "apple-forwarding-x86_64.S" +# if defined(OF_AMD64) +# include "apple-forwarding-amd64.S" # elif defined(OF_X86) -# include "apple-forwarding-i386.S" +# include "apple-forwarding-x86.S" # elif defined(OF_ARM64) # include "apple-forwarding-arm64.S" # elif defined(OF_ARM) # include "apple-forwarding-arm.S" # elif defined(OF_POWERPC) # include "apple-forwarding-powerpc.S" # endif #else # if defined(OF_ELF) -# if defined(OF_X86_64) -# include "forwarding-x86_64-elf.S" +# if defined(OF_AMD64) +# include "forwarding-amd64-elf.S" # elif defined(OF_X86) # include "forwarding-x86-elf.S" # elif defined(OF_ARM64) # include "forwarding-arm64-elf.S" # elif defined(OF_ARM) @@ -47,16 +47,16 @@ # include "forwarding-sparc64-elf.S" # elif defined(OF_SPARC) # include "forwarding-sparc-elf.S" # endif # elif defined(OF_MACH_O) -# if defined(OF_X86_64) -# include "forwarding-x86_64-macho.S" +# if defined(OF_AMD64) +# include "forwarding-amd64-macho.S" # endif # elif defined(OF_WINDOWS) -# if defined(OF_X86_64) -# include "forwarding-x86_64-win64.S" +# if defined(OF_AMD64) +# include "forwarding-amd64-win64.S" # elif defined(OF_X86) # include "forwarding-x86-win32.S" # endif # endif #endif Index: src/libbases.m ================================================================== --- src/libbases.m +++ src/libbases.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,11 +13,13 @@ * file. */ #include "config.h" +#define Class IntuitionClass #include +#undef Class #import "OFInitializationFailedException.h" #import "macros.h" Index: src/macros.h ================================================================== --- src/macros.h +++ src/macros.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -99,17 +99,21 @@ # define OF_UNLIKELY(cond) (cond) # define OF_CONST_FUNC # define OF_NO_RETURN_FUNC # define OF_WEAK_REF(sym) #endif + +#ifdef __GNUC__ +# define OF_ALIGN(alignment) __attribute__((__aligned__(alignment))) +#endif #if __STDC_VERSION__ >= 201112L # define OF_ALIGNOF(type) _Alignof(type) # define OF_ALIGNAS(type) _Alignas(type) #else # define OF_ALIGNOF(type) __alignof__(type) -# define OF_ALIGNAS(type) __attribute__((__aligned__(__alignof__(type)))) +# define OF_ALIGNAS(type) OF_ALIGN(OF_ALIGNOF(type)) #endif #if __STDC_VERSION__ >= 201112L && defined(OF_HAVE_MAX_ALIGN_T) # define OF_BIGGEST_ALIGNMENT _Alignof(max_align_t) #else @@ -289,10 +293,21 @@ # define OF_DESIGNATED_INITIALIZER \ __attribute__((__objc_designated_initializer__)) #else # define OF_DESIGNATED_INITIALIZER #endif + +#if defined(__clang__) || OF_GCC_VERSION >= 405 +# define OF_DEPRECATED(project, major, minor, msg) \ + __attribute__((__deprecated__("Deprecated in " #project " " \ + #major "." #minor ": " msg))) +#elif defined(__GNUC__) +# define OF_DEPRECATED(project, major, minor, msg) \ + __attribute__((__deprecated__)) +#else +# define OF_DEPRECATED(project, major, minor, msg) +#endif #if __has_attribute(__objc_boxable__) # define OF_BOXABLE __attribute__((__objc_boxable__)) #else # define OF_BOXABLE @@ -314,34 +329,34 @@ #else # define OF_DIRECT_MEMBERS #endif #ifdef OF_APPLE_RUNTIME -# if defined(OF_X86_64) || defined(OF_X86) || defined(OF_ARM64) || \ +# if defined(OF_AMD64) || defined(OF_X86) || defined(OF_ARM64) || \ defined(OF_ARM) || defined(OF_POWERPC) # define OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR # define OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR_STRET # endif #else # if defined(OF_ELF) -# if defined(OF_X86_64) || defined(OF_X86) || \ +# if defined(OF_AMD64) || defined(OF_X86) || \ defined(OF_ARM64) || defined(OF_ARM) || defined(OF_POWERPC) || \ defined(OF_MIPS) || defined(OF_SPARC64) || defined(OF_SPARC) # define OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR # if __OBJFW_RUNTIME_ABI__ >= 800 # define OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR_STRET # endif # endif # elif defined(OF_MACH_O) -# if defined(OF_X86_64) +# if defined(OF_AMD64) # define OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR # if __OBJFW_RUNTIME_ABI__ >= 800 # define OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR_STRET # endif # endif # elif defined(OF_WINDOWS) -# if defined(OF_X86_64) || defined(OF_X86) +# if defined(OF_AMD64) || defined(OF_X86) # define OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR # if __OBJFW_RUNTIME_ABI__ >= 800 # define OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR_STRET # endif # endif @@ -357,20 +372,33 @@ objc_error("ObjFWRT @ " __FILE__ ":" \ OF_STRINGIFY(__LINE__), \ "Failed to ensure condition:\n" #cond); \ } while(0) #else +@class OFConstantString; +# ifdef __cplusplus +extern "C" { +# endif +extern void OFLog(OFConstantString *_Nonnull, ...); +# ifdef __cplusplus +} +# endif # define OFEnsure(cond) \ do { \ if OF_UNLIKELY (!(cond)) { \ - fprintf(stderr, "Failed to ensure condition " \ - "in " __FILE__ ":%d:\n" #cond "\n", \ - __LINE__); \ + OFLog(@"Failed to ensure condition in " \ + @__FILE__ ":%d: " @#cond, __LINE__); \ abort(); \ } \ } while (0) #endif + +#ifndef NDEBUG +# define OFAssert(...) OFEnsure(__VA_ARGS__) +#else +# define OFAssert(...) +#endif #define OF_UNRECOGNIZED_SELECTOR OFMethodNotFound(self, _cmd); #if __has_feature(objc_arc) # define OF_INVALID_INIT_METHOD OFMethodNotFound(self, _cmd); #else @@ -400,10 +428,34 @@ \ abort(); \ \ [super dealloc]; /* Get rid of a stupid warning */ #endif +#define OF_SINGLETON_METHODS \ + - (instancetype)autorelease \ + { \ + return self; \ + } \ + \ + - (instancetype)retain \ + { \ + return self; \ + } \ + \ + - (void)release \ + { \ + } \ + \ + - (unsigned int)retainCount \ + { \ + return OFMaxRetainCount; \ + } \ + \ + - (void)dealloc \ + { \ + OF_DEALLOC_UNSUPPORTED \ + } #define OF_CONSTRUCTOR(prio) \ static void __attribute__((__constructor__(prio))) \ OF_PREPROCESSOR_CONCAT(constructor, __LINE__)(void) #define OF_DESTRUCTOR(prio) \ @@ -441,27 +493,28 @@ static OF_INLINE uint16_t OF_CONST_FUNC OFByteSwap16NonConst(uint16_t i) { #if defined(OF_HAVE_BUILTIN_BSWAP16) return __builtin_bswap16(i); -#elif (defined(OF_X86_64) || defined(OF_X86)) && defined(__GNUC__) +#elif (defined(OF_AMD64) || defined(OF_X86)) && defined(__GNUC__) __asm__ ( - "xchgb %h0, %b0" - : "=Q"(i) - : "0"(i) + "xchg{b} { %h0, %b0 | %b0, %h0 }" + : "=Q" (i) + : "0" (i) ); #elif defined(OF_POWERPC) && defined(__GNUC__) __asm__ ( "lhbrx %0, 0, %1" - : "=r"(i) - : "r"(&i), "m"(i) + : "=r" (i) + : "r" (&i), + "m" (i) ); #elif defined(OF_ARMV6) && defined(__GNUC__) __asm__ ( "rev16 %0, %0" - : "=r"(i) - : "0"(i) + : "=r" (i) + : "0" (i) ); #else i = (i & UINT16_C(0xFF00)) >> 8 | (i & UINT16_C(0x00FF)) << 8; #endif @@ -471,27 +524,28 @@ static OF_INLINE uint32_t OF_CONST_FUNC OFByteSwap32NonConst(uint32_t i) { #if defined(OF_HAVE_BUILTIN_BSWAP32) return __builtin_bswap32(i); -#elif (defined(OF_X86_64) || defined(OF_X86)) && defined(__GNUC__) +#elif (defined(OF_AMD64) || defined(OF_X86)) && defined(__GNUC__) __asm__ ( "bswap %0" - : "=q"(i) - : "0"(i) + : "=q" (i) + : "0" (i) ); #elif defined(OF_POWERPC) && defined(__GNUC__) __asm__ ( "lwbrx %0, 0, %1" - : "=r"(i) - : "r"(&i), "m"(i) + : "=r" (i) + : "r" (&i), + "m" (i) ); #elif defined(OF_ARMV6) && defined(__GNUC__) __asm__ ( "rev %0, %0" - : "=r"(i) - : "0"(i) + : "=r" (i) + : "0" (i) ); #else i = (i & UINT32_C(0xFF000000)) >> 24 | (i & UINT32_C(0x00FF0000)) >> 8 | (i & UINT32_C(0x0000FF00)) << 8 | @@ -503,23 +557,23 @@ static OF_INLINE uint64_t OF_CONST_FUNC OFByteSwap64NonConst(uint64_t i) { #if defined(OF_HAVE_BUILTIN_BSWAP64) return __builtin_bswap64(i); -#elif defined(OF_X86_64) && defined(__GNUC__) +#elif defined(OF_AMD64) && defined(__GNUC__) __asm__ ( "bswap %0" - : "=r"(i) - : "0"(i) + : "=r" (i) + : "0" (i) ); #elif defined(OF_X86) && defined(__GNUC__) __asm__ ( - "bswap %%eax\n\t" - "bswap %%edx\n\t" - "xchgl %%eax, %%edx" - : "=A"(i) - : "0"(i) + "bswap {%%}eax\n\t" + "bswap {%%}edx\n\t" + "xchg{l} { %%eax, %%edx | edx, eax }" + : "=A" (i) + : "0" (i) ); #else i = (uint64_t)OFByteSwap32NonConst( (uint32_t)(i & UINT32_C(0xFFFFFFFF))) << 32 | OFByteSwap32NonConst((uint32_t)(i >> 32)); Index: src/objfw-defs.h.in ================================================================== --- src/objfw-defs.h.in +++ src/objfw-defs.h.in @@ -1,7 +1,8 @@ #undef OF_APPLE_RUNTIME #undef OF_BIG_ENDIAN +#undef OF_CLASSIC_MACOS #undef OF_FLOAT_BIG_ENDIAN #undef OF_HAVE_AFUNIX_H #undef OF_HAVE_APPLETALK #undef OF_HAVE_ATOMIC_BUILTINS #undef OF_HAVE_ATOMIC_OPS @@ -29,10 +30,11 @@ #undef OF_HAVE_PLUGINS #undef OF_HAVE_PTHREADS #undef OF_HAVE_PTHREAD_SPINLOCKS #undef OF_HAVE_RECURSIVE_PTHREAD_MUTEXES #undef OF_HAVE_SCHED_YIELD +#undef OF_HAVE_SOCKADDR_STORAGE #undef OF_HAVE_SOCKETS #undef OF_HAVE_STDNORETURN #undef OF_HAVE_SUBPROCESSES #undef OF_HAVE_SYMLINK #undef OF_HAVE_SYNC_BUILTINS Index: src/platform.h ================================================================== --- src/platform.h +++ src/platform.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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 @@ # error OF_UNIVERSAL defined, but neither __BIG_ENDIAN__ nor __LITTLE_ENDIAN__! # endif #endif #if defined(__x86_64__) || defined(__amd64__) -# define OF_X86_64 +# define OF_AMD64 #elif defined(__i386__) # define OF_X86 #elif defined(__powerpc64__) || defined(__ppc64__) || defined(__PPC64__) # define OF_POWERPC64 #elif defined(__powerpc__) || defined(__ppc__) || defined(__PPC__) @@ -149,10 +149,16 @@ # define OF_MSDOS #elif defined(__riscos__) # define OF_ACORN_RISC_OS #elif defined(__MINT__) # define OF_MINT +#elif defined(__gnu_hurd__) +# define OF_HURD +#endif + +#ifdef __GLIBC__ +# define OF_GLIBC #endif #if defined(__ELF__) # define OF_ELF #elif defined(__MACH__) Index: src/platform/AmigaOS/OFPlainCondition.m ================================================================== --- src/platform/AmigaOS/OFPlainCondition.m +++ src/platform/AmigaOS/OFPlainCondition.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,15 +17,17 @@ #include #import "OFPlainCondition.h" +#define Class IntuitionClass #include #include #ifndef OF_AMIGAOS4 # include #endif +#undef Class int OFPlainConditionNew(OFPlainCondition *condition) { condition->waitingTasks = NULL; Index: src/platform/AmigaOS/OFPlainMutex.m ================================================================== --- src/platform/AmigaOS/OFPlainMutex.m +++ src/platform/AmigaOS/OFPlainMutex.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,13 @@ #include #import "OFPlainMutex.h" +#define Class IntuitionClass #include +#undef Class int OFPlainMutexNew(OFPlainMutex *mutex) { InitSemaphore(mutex); Index: src/platform/AmigaOS/OFPlainThread.m ================================================================== --- src/platform/AmigaOS/OFPlainThread.m +++ src/platform/AmigaOS/OFPlainThread.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,20 +13,22 @@ * file. */ #include "config.h" -#include #include #import "OFPlainThread.h" #import "OFData.h" +#import "OFString.h" #import "OFTLSKey.h" +#define Class IntuitionClass #include #include #include +#undef Class #ifndef OF_MORPHOS extern void OFTLSKeyThreadExited(void); #endif static OFTLSKey threadKey; @@ -191,11 +193,11 @@ } Wait(1ul << thread->joinSigBit); FreeSignal(thread->joinSigBit); - assert(thread->done); + OFAssert(thread->done); free(thread); return 0; } 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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 @@ #include "config.h" #import "OFString+PathAdditions.h" #import "OFArray.h" -#import "OFFileURIHandler.h" +#import "OFFileIRIHandler.h" #import "OFOutOfRangeException.h" int _OFString_PathAdditions_reference; @@ -253,10 +253,13 @@ return [ret autorelease]; } - (OFString *)stringByAppendingPathComponent: (OFString *)component { + if (self.length == 0) + return component; + if ([self hasSuffix: @"/"] || [self hasSuffix: @":"]) return [self stringByAppendingString: component]; else { OFMutableString *ret = [[self mutableCopy] autorelease]; @@ -291,14 +294,14 @@ } - (bool)of_isDirectoryPath { return ([self hasSuffix: @"/"] || [self hasSuffix: @":"] || - [OFFileURIHandler of_directoryExistsAtPath: self]); + [OFFileIRIHandler of_directoryExistsAtPath: self]); } -- (OFString *)of_pathToURIPathWithPercentEncodedHost: +- (OFString *)of_pathToIRIPathWithPercentEncodedHost: (OFString **)percentEncodedHost { OFArray OF_GENERIC(OFString *) *components = self.pathComponents; OFMutableString *ret = [OFMutableString string]; @@ -317,11 +320,11 @@ [ret makeImmutable]; return ret; } -- (OFString *)of_URIPathToPathWithPercentEncodedHost: +- (OFString *)of_IRIPathToPathWithPercentEncodedHost: (OFString *)percentEncodedHost { OFString *path = self; if (path.length > 1 && [path hasSuffix: @"/"]) @@ -351,10 +354,10 @@ } return [OFString pathWithComponents: components]; } -- (OFString *)of_pathComponentToURIPathComponent +- (OFString *)of_pathComponentToIRIPathComponent { return self; } @end Index: src/platform/AmigaOS/OFTLSKey.m ================================================================== --- src/platform/AmigaOS/OFTLSKey.m +++ src/platform/AmigaOS/OFTLSKey.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,12 +15,14 @@ #include "config.h" #import "OFTLSKey.h" +#define Class IntuitionClass #include #include +#undef Class /* * As we use this file in both the runtime and ObjFW, and since AmigaOS always * has the runtime, use the hashtable from the runtime. */ 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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 @@ #include "config.h" #import "OFString+PathAdditions.h" #import "OFArray.h" -#import "OFFileURIHandler.h" +#import "OFFileIRIHandler.h" #import "OFOutOfRangeException.h" int _OFString_PathAdditions_reference; @@ -298,10 +298,13 @@ return [ret autorelease]; } - (OFString *)stringByAppendingPathComponent: (OFString *)component { + if (self.length == 0) + return component; + if ([self hasSuffix: @"/"]) return [self stringByAppendingString: component]; else { OFMutableString *ret = [[self mutableCopy] autorelease]; @@ -336,20 +339,20 @@ } - (bool)of_isDirectoryPath { return ([self hasSuffix: @"/"] || - [OFFileURIHandler of_directoryExistsAtPath: self]); + [OFFileIRIHandler of_directoryExistsAtPath: self]); } -- (OFString *)of_pathToURIPathWithPercentEncodedHost: +- (OFString *)of_pathToIRIPathWithPercentEncodedHost: (OFString **)percentEncodedHost { return self; } -- (OFString *)of_URIPathToPathWithPercentEncodedHost: +- (OFString *)of_IRIPathToPathWithPercentEncodedHost: (OFString *)percentEncodedHost { OFString *path = self; if (path.length > 1 && [path hasSuffix: @"/"]) @@ -356,10 +359,10 @@ path = [path substringToIndex: path.length - 1]; return path; } -- (OFString *)of_pathComponentToURIPathComponent +- (OFString *)of_pathComponentToIRIPathComponent { return self; } @end Index: src/platform/POSIX/OFSubprocess.m ================================================================== --- src/platform/POSIX/OFSubprocess.m +++ src/platform/POSIX/OFSubprocess.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,11 +39,11 @@ #import "OFNotOpenException.h" #import "OFOutOfRangeException.h" #import "OFReadFailedException.h" #import "OFWriteFailedException.h" -#ifndef HAVE_POSIX_SPAWNP +#if !defined(HAVE_POSIX_SPAWNP) || !defined(HAVE_SPAWN_H) extern char **environ; #endif @interface OFSubprocess () - (void)of_getArgv: (char ***)argv @@ -141,11 +141,11 @@ forProgramName: programName andArguments: arguments]; @try { env = [self of_environmentForDictionary: environment]; -#ifdef HAVE_POSIX_SPAWNP +#if defined(HAVE_POSIX_SPAWNP) && defined(HAVE_SPAWN_H) posix_spawn_file_actions_t actions; posix_spawnattr_t attr; if (posix_spawn_file_actions_init(&actions) != 0) @throw [OFInitializationFailedException ADDED src/platform/POSIX/OFSystemInfo+NetworkInterfaces.m Index: src/platform/POSIX/OFSystemInfo+NetworkInterfaces.m ================================================================== --- /dev/null +++ src/platform/POSIX/OFSystemInfo+NetworkInterfaces.m @@ -0,0 +1,742 @@ +/* + * Copyright (c) 2008-2024 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#include "config.h" + +#ifdef HAVE_SYS_IOCTL_H +# include +#endif +#ifdef OF_HAVE_SYS_SOCKET_H +# include +#endif +#ifdef HAVE_SYS_SOCKIO_H +# include +#endif +#ifdef HAVE_NET_IF_H +# include +#endif +#ifdef HAVE_NET_IF_ARP_H +# include +#endif +#ifdef HAVE_NET_IF_DL_H +# include +#endif +#ifdef HAVE_NET_IF_TYPES_H +# include +#endif + +#import "OFSystemInfo.h" +#import "OFSystemInfo+NetworkInterfaces.h" +#import "OFArray.h" +#import "OFData.h" +#import "OFDictionary.h" +#ifdef OF_HAVE_FILES + #import "OFFile.h" +#endif +#import "OFLocale.h" +#import "OFNumber.h" +#import "OFSocket.h" +#import "OFSocket+Private.h" +#import "OFString.h" + +#import "OFInvalidFormatException.h" +#import "OFOpenItemFailedException.h" + +@implementation OFSystemInfo (NetworkInterfaces) +static bool +queryNetworkInterfaceIndices(OFMutableDictionary *ret) +{ +#ifdef HAVE_IF_NAMEINDEX + OFStringEncoding encoding = [OFLocale encoding]; + struct if_nameindex *nameindex = if_nameindex(); + + if (nameindex == NULL) + return false; + + @try { + for (size_t i = 0; nameindex[i].if_index != 0; i++) { + OFString *name = [OFString + stringWithCString: nameindex[i].if_name + encoding: encoding]; + OFNumber *idx = [OFNumber + numberWithUnsignedInt: nameindex[i].if_index]; + OFMutableDictionary *interface = + [ret objectForKey: name]; + + if (interface == nil) { + interface = [OFMutableDictionary dictionary]; + [ret setObject: interface forKey: name]; + } + + [interface setObject: idx + forKey: OFNetworkInterfaceIndex]; + } + } @finally { + if_freenameindex(nameindex); + } + + return true; +#else + return false; +#endif +} + +#if defined(HAVE_IOCTL) && defined(HAVE_NET_IF_H) +static bool +queryNetworkInterfaceAddresses(OFMutableDictionary *ret, + OFNetworkInterfaceKey key, OFSocketAddressFamily addressFamily, int family, + size_t sockaddrSize) +{ + OFStringEncoding encoding = [OFLocale encoding]; + int sock = socket(family, SOCK_DGRAM, 0); + OFMutableDictionary *interface; + OFEnumerator *enumerator; + + if (sock < 0) + return false; + +# if defined(HAVE_STRUCT_LIFCONF) && defined(SIOCGLIFCONF) + struct lifconf lifc; + struct lifreq *lifrs; + + if ((lifrs = malloc(128 * sizeof(struct lifreq))) == NULL) { + closesocket(sock); + return false; + } + + @try { + char *buffer; + + memset(&lifc, 0, sizeof(lifc)); + lifc.lifc_buf = (void *)lifrs; + lifc.lifc_len = 128 * sizeof(struct lifreq); + if (ioctl(sock, SIOCGLIFCONF, &lifc) < 0) + return false; + + for (buffer = lifc.lifc_buf; + buffer < (char *)lifc.lifc_buf + lifc.lifc_len; + buffer += sizeof(struct lifreq)) { + struct lifreq *current = + (struct lifreq *)(void *)buffer; + OFString *name; + OFMutableData *addresses; + OFSocketAddress address; + + if (current->lifr_addr.ss_family != family) + continue; + + name = [OFString stringWithCString: current->lifr_name + encoding: encoding]; + if ((interface = [ret objectForKey: name]) == nil) { + interface = [OFMutableDictionary dictionary]; + [ret setObject: interface forKey: name]; + } + + addresses = [interface objectForKey: key]; + if (addresses == nil) { + addresses = [OFMutableData + dataWithItemSize: sizeof(OFSocketAddress)]; + [interface setObject: addresses forKey: key]; + } + + memset(&address, 0, sizeof(address)); + address.family = addressFamily; + memcpy(&address.sockaddr.in, ¤t->lifr_addr, + sockaddrSize); + +# if defined(OF_HAVE_IPV6) && defined(HAVE_IF_NAMETOINDEX) + if (address.sockaddr.in6.sin6_family == AF_INET6 && + address.sockaddr.in6.sin6_addr.s6_addr[0] == 0xFE && + (address.sockaddr.in6.sin6_addr.s6_addr[1] & 0xC0) + == 0x80) + address.sockaddr.in6.sin6_scope_id = + if_nametoindex( + [name cStringWithEncoding: encoding]); +# endif + + [addresses addItem: &address]; + } + } @finally { + free(lifrs); + closesocket(sock); + } +# else + struct ifconf ifc; + struct ifreq *ifrs; + + if (sock < 0) + return false; + + if ((ifrs = malloc(128 * sizeof(struct ifreq))) == NULL) { + closesocket(sock); + return false; + } + + @try { + char *buffer; + + memset(&ifc, 0, sizeof(ifc)); + ifc.ifc_buf = (void *)ifrs; + ifc.ifc_len = 128 * sizeof(struct ifreq); + if (ioctl(sock, SIOCGIFCONF, &ifc) < 0) + return false; + + buffer = ifc.ifc_buf; + while (buffer < (char *)ifc.ifc_buf + ifc.ifc_len) { + struct ifreq *current = (struct ifreq *)(void *)buffer; + OFString *name; + OFMutableData *addresses; + OFSocketAddress address; + + if (current->ifr_addr.sa_family != family) + goto next; + + name = [OFString stringWithCString: current->ifr_name + encoding: encoding]; + if ((interface = [ret objectForKey: name]) == nil) { + interface = [OFMutableDictionary dictionary]; + [ret setObject: interface forKey: name]; + } + + addresses = [interface objectForKey: key]; + if (addresses == nil) { + addresses = [OFMutableData + dataWithItemSize: sizeof(OFSocketAddress)]; + [interface setObject: addresses forKey: key]; + } + + memset(&address, 0, sizeof(address)); + address.family = addressFamily; + memcpy(&address.sockaddr.in, ¤t->ifr_addr, + sockaddrSize); + +# if defined(OF_HAVE_IPV6) && defined(HAVE_IF_NAMETOINDEX) + if (address.sockaddr.in6.sin6_family == AF_INET6 && + address.sockaddr.in6.sin6_addr.s6_addr[0] == 0xFE && + (address.sockaddr.in6.sin6_addr.s6_addr[1] & 0xC0) + == 0x80) { +# if defined(__KAME__) +# define addr6 address.sockaddr.in6.sin6_addr.s6_addr + address.sockaddr.in6.sin6_scope_id = + (addr6[2] << 8) | addr6[3]; + addr6[2] = addr6[3] = 0; +# undef addr6 +# elif defined(HAVE_IF_NAMETOINDEX) + address.sockaddr.in6.sin6_scope_id = + if_nametoindex( + [name cStringWithEncoding: encoding]); +# endif + } +# endif + + [addresses addItem: &address]; + +next: +# ifdef HAVE_STRUCT_SOCKADDR_SA_LEN + if (current->ifr_addr.sa_len > sizeof(struct sockaddr)) + buffer += sizeof(struct ifreq) - + sizeof(struct sockaddr) + + current->ifr_addr.sa_len; + else +# endif + buffer += sizeof(struct ifreq); + } + } @finally { + free(ifrs); + closesocket(sock); + } +# endif + + enumerator = [ret objectEnumerator]; + while ((interface = [enumerator nextObject]) != nil) + [[interface objectForKey: key] makeImmutable]; + + return true; +} +#endif + +static bool +queryNetworkInterfaceIPv4Addresses(OFMutableDictionary *ret) +{ +#if defined(HAVE_IOCTL) && defined(HAVE_NET_IF_H) + return queryNetworkInterfaceAddresses(ret, + OFNetworkInterfaceIPv4Addresses, OFSocketAddressFamilyIPv4, + AF_INET, sizeof(struct sockaddr_in)); +#else + return false; +#endif +} + +#ifdef OF_HAVE_IPV6 +static bool +queryNetworkInterfaceIPv6Addresses(OFMutableDictionary *ret) +{ +# if defined(OF_LINUX) && defined(OF_HAVE_FILES) +# ifdef HAVE_IF_NAMETOINDEX + OFStringEncoding encoding = [OFLocale encoding]; +# endif + OFFile *file; + OFString *line; + OFMutableDictionary *interface; + OFEnumerator *enumerator; + + @try { + file = [OFFile fileWithPath: @"/proc/net/if_inet6" mode: @"r"]; + } @catch (OFOpenItemFailedException *e) { + return false; + } + + while ((line = [file readLine]) != nil) { + OFArray *components = [line + componentsSeparatedByString: @" " + options: OFStringSkipEmptyComponents]; + OFString *addressString, *name; + OFSocketAddress address; + OFMutableData *addresses; + + if (components.count < 6) + continue; + + addressString = [components objectAtIndex: 0]; + name = [components objectAtIndex: 5]; + + if (addressString.length != 32) + continue; + + if ((interface = [ret objectForKey: name]) == nil) { + interface = [OFMutableDictionary dictionary]; + [ret setObject: interface forKey: name]; + } + + memset(&address, 0, sizeof(address)); + address.family = OFSocketAddressFamilyIPv6; + address.sockaddr.in6.sin6_family = AF_INET6; + + for (size_t i = 0; i < 32; i += 2) { + unsigned long long byte; + + @try { + byte = [[addressString + substringWithRange: OFMakeRange(i, 2)] + unsignedLongLongValueWithBase: 16]; + } @catch (OFInvalidFormatException *e) { + goto next_line; + } + + if (byte > 0xFF) + goto next_line; + + address.sockaddr.in6.sin6_addr.s6_addr[i / 2] = + (unsigned char)byte; + } + +# ifdef HAVE_IF_NAMETOINDEX + if (address.sockaddr.in6.sin6_addr.s6_addr[0] == 0xFE && + (address.sockaddr.in6.sin6_addr.s6_addr[1] & 0xC0) == 0x80) + address.sockaddr.in6.sin6_scope_id = if_nametoindex( + [name cStringWithEncoding: encoding]); +# endif + + if ((addresses = [interface + objectForKey: OFNetworkInterfaceIPv6Addresses]) == nil) { + addresses = [OFMutableData + dataWithItemSize: sizeof(OFSocketAddress)]; + [interface setObject: addresses + forKey: OFNetworkInterfaceIPv6Addresses]; + } + + [addresses addItem: &address]; + +next_line: + continue; + } + + enumerator = [ret objectEnumerator]; + while ((interface = [enumerator nextObject]) != nil) + [[interface objectForKey: OFNetworkInterfaceIPv6Addresses] + makeImmutable]; + + return false; +# elif defined(HAVE_IOCTL) && defined(HAVE_NET_IF_H) + return queryNetworkInterfaceAddresses(ret, + OFNetworkInterfaceIPv6Addresses, OFSocketAddressFamilyIPv6, + AF_INET6, sizeof(struct sockaddr_in6)); +# else + return false; +# endif +} +#endif + +#ifdef OF_HAVE_IPX +static bool +queryNetworkInterfaceIPXAddresses(OFMutableDictionary *ret) +{ +# if defined(OF_LINUX) && defined(OF_HAVE_FILES) + OFFile *file; + OFString *line; + OFMutableDictionary *interface; + OFEnumerator *enumerator; + + @try { + file = [OFFile fileWithPath: @"/proc/net/ipx/interface" + mode: @"r"]; + } @catch (OFOpenItemFailedException *e) { + return false; + } + + /* First line is "Network Node_Address Primary Device Frame_Type" */ + if (![[file readLine] hasPrefix: @"Network "]) + return false; + + while ((line = [file readLine]) != nil) { + OFArray *components = [line + componentsSeparatedByString: @" " + options: OFStringSkipEmptyComponents]; + OFString *name; + unsigned long long network, nodeLong; + unsigned char node[IPX_NODE_LEN]; + OFSocketAddress address; + OFMutableData *addresses; + + if (components.count < 5) + continue; + + name = [components objectAtIndex: 3]; + + if ((interface = [ret objectForKey: name]) == nil) { + interface = [OFMutableDictionary dictionary]; + [ret setObject: interface forKey: name]; + } + + @try { + network = [[components objectAtIndex: 0] + unsignedLongLongValueWithBase: 16]; + nodeLong = [[components objectAtIndex: 1] + unsignedLongLongValueWithBase: 16]; + } @catch (OFInvalidFormatException *e) { + continue; + } + + if (network > 0xFFFFFFFF || nodeLong > 0xFFFFFFFFFFFF) + continue; + + node[0] = (nodeLong >> 40) & 0xFF; + node[1] = (nodeLong >> 32) & 0xFF; + node[2] = (nodeLong >> 24) & 0xFF; + node[3] = (nodeLong >> 16) & 0xFF; + node[4] = (nodeLong >> 8) & 0xFF; + node[5] = nodeLong & 0xFF; + + address = OFSocketAddressMakeIPX((uint32_t)network, node, 0); + + if ((addresses = [interface objectForKey: + OFNetworkInterfaceIPXAddresses]) == nil) { + addresses = [OFMutableData + dataWithItemSize: sizeof(OFSocketAddress)]; + [interface setObject: addresses + forKey: OFNetworkInterfaceIPXAddresses]; + } + + [addresses addItem: &address]; + } + + enumerator = [ret objectEnumerator]; + while ((interface = [enumerator nextObject]) != nil) + [[interface objectForKey: OFNetworkInterfaceIPXAddresses] + makeImmutable]; + + return false; +# elif defined(HAVE_IOCTL) && defined(HAVE_NET_IF_H) + return queryNetworkInterfaceAddresses(ret, + OFNetworkInterfaceIPXAddresses, OFSocketAddressFamilyIPX, + AF_IPX, sizeof(struct sockaddr_ipx)); +# else + return false; +# endif +} +#endif + +#ifdef OF_HAVE_APPLETALK +static bool +queryNetworkInterfaceAppleTalkAddresses(OFMutableDictionary *ret) +{ +# if defined(OF_LINUX) && defined(OF_HAVE_FILES) + OFFile *file; + OFString *line; + OFMutableDictionary *interface; + OFEnumerator *enumerator; + + @try { + file = [OFFile fileWithPath: @"/proc/net/atalk/interface" + mode: @"r"]; + } @catch (OFOpenItemFailedException *e) { + return false; + } + + /* First line is "Interface Address Networks Status" */ + if (![[file readLine] hasPrefix: @"Interface "]) + return false; + + while ((line = [file readLine]) != nil) { + OFArray *components = [line + componentsSeparatedByString: @" " + options: OFStringSkipEmptyComponents]; + OFString *addressString, *name; + unsigned long long network, node; + OFSocketAddress address; + OFMutableData *addresses; + + if (components.count < 4) + continue; + + name = [components objectAtIndex: 0]; + addressString = [components objectAtIndex: 1]; + + if (addressString.length != 7 || + [addressString characterAtIndex: 4] != ':') + continue; + + if ((interface = [ret objectForKey: name]) == nil) { + interface = [OFMutableDictionary dictionary]; + [ret setObject: interface forKey: name]; + } + + @try { + network = [[addressString + substringWithRange: OFMakeRange(0, 4)] + unsignedLongLongValueWithBase: 16]; + node = [[addressString + substringWithRange: OFMakeRange(5, 2)] + unsignedLongLongValueWithBase: 16]; + } @catch (OFInvalidFormatException *e) { + continue; + } + + if (network > 0xFFFF || node > 0xFF) + continue; + + address = OFSocketAddressMakeAppleTalk( + (uint16_t)network, (uint8_t)node, 0); + + if ((addresses = [interface objectForKey: + OFNetworkInterfaceAppleTalkAddresses]) == nil) { + addresses = [OFMutableData + dataWithItemSize: sizeof(OFSocketAddress)]; + [interface + setObject: addresses + forKey: OFNetworkInterfaceAppleTalkAddresses]; + } + + [addresses addItem: &address]; + } + + enumerator = [ret objectEnumerator]; + while ((interface = [enumerator nextObject]) != nil) + [[interface objectForKey: OFNetworkInterfaceAppleTalkAddresses] + makeImmutable]; + + return false; +# elif defined(HAVE_IOCTL) && defined(HAVE_NET_IF_H) + return queryNetworkInterfaceAddresses(ret, + OFNetworkInterfaceAppleTalkAddresses, + OFSocketAddressFamilyAppleTalk, AF_APPLETALK, + sizeof(struct sockaddr_at)); +# else + return false; +# endif +} +#endif + +static bool +queryNetworkInterfaceHardwareAddress(OFMutableDictionary *ret) +{ +#if defined(HAVE_IOCTL) && defined(HAVE_NET_IF_H) && defined(SIOCGLIFHWADDR) + OFStringEncoding encoding = [OFLocale encoding]; + int sock = socket(AF_INET, SOCK_DGRAM, 0); + + if (sock < 0) + return false; + + for (OFString *name in ret) { + size_t nameLength = [name cStringLengthWithEncoding: encoding]; + struct lifreq lifr; + struct sockaddr_dl *sdl; + OFData *hardwareAddress; + + if (nameLength > IFNAMSIZ) + continue; + + memset(&lifr, 0, sizeof(lifr)); + memcpy(&lifr.lifr_name, [name cStringWithEncoding: encoding], + nameLength); + + if (ioctl(sock, SIOCGLIFHWADDR, &lifr) < 0) + continue; + + if (lifr.lifr_addr.ss_family != AF_LINK) + continue; + + sdl = (struct sockaddr_dl *)(void *)&lifr.lifr_addr; + hardwareAddress = [OFData dataWithItems: LLADDR(sdl) + count: sdl->sdl_alen]; + [[ret objectForKey: name] + setObject: hardwareAddress + forKey: OFNetworkInterfaceHardwareAddress]; + } + + return true; +#elif defined(HAVE_IOCTL) && defined(HAVE_NET_IF_H) && \ + defined(SIOCGIFHWADDR) && defined(HAVE_STRUCT_IFREQ_IFR_HWADDR) + OFStringEncoding encoding = [OFLocale encoding]; + int sock = socket(AF_INET, SOCK_DGRAM, 0); + + if (sock < 0) + return false; + + for (OFString *name in ret) { + size_t nameLength = [name cStringLengthWithEncoding: encoding]; + struct ifreq ifr; + OFData *hardwareAddress; + + if (nameLength > IFNAMSIZ) + continue; + + memset(&ifr, 0, sizeof(ifr)); + memcpy(&ifr.ifr_name, [name cStringWithEncoding: encoding], + nameLength); + + if (ioctl(sock, SIOCGIFHWADDR, &ifr) < 0) + continue; + + if (ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER) + continue; + + hardwareAddress = [OFData dataWithItems: ifr.ifr_hwaddr.sa_data + count: 6]; + [[ret objectForKey: name] + setObject: hardwareAddress + forKey: OFNetworkInterfaceHardwareAddress]; + } + + return true; +#elif defined(HAVE_IOCTL) && defined(HAVE_NET_IF_H) && \ + defined(HAVE_STRUCT_SOCKADDR_DL) + OFStringEncoding encoding = [OFLocale encoding]; + int sock = socket(AF_INET, SOCK_DGRAM, 0); + struct ifconf ifc; + struct ifreq *ifrs; + + if (sock < 0) + return false; + + ifrs = malloc(128 * sizeof(struct ifreq)); + if (ifrs == NULL) { + closesocket(sock); + return false; + } + + @try { + char *buffer; + + memset(&ifc, 0, sizeof(ifc)); + ifc.ifc_buf = (void *)ifrs; + ifc.ifc_len = 128 * sizeof(struct ifreq); + if (ioctl(sock, SIOCGIFCONF, &ifc) < 0) + return false; + + buffer = ifc.ifc_buf; + while (buffer < (char *)ifc.ifc_buf + ifc.ifc_len) { + struct ifreq *current = (struct ifreq *)(void *)buffer; + struct sockaddr_dl *sdl; + OFString *name; + OFMutableDictionary *interface; + OFData *hardwareAddress; + + if (current->ifr_addr.sa_family != AF_LINK) + goto next; + + sdl = (struct sockaddr_dl *)(void *)¤t->ifr_addr; + if (sdl->sdl_type != IFT_ETHER) + goto next; + + name = [OFString stringWithCString: current->ifr_name + encoding: encoding]; + if ((interface = [ret objectForKey: name]) == nil) { + interface = [OFMutableDictionary dictionary]; + [ret setObject: interface forKey: name]; + } + + hardwareAddress = [OFData dataWithItems: LLADDR(sdl) + count: sdl->sdl_alen]; + [interface + setObject: hardwareAddress + forKey: OFNetworkInterfaceHardwareAddress]; + +next: +# ifdef _SIZEOF_ADDR_IFREQ + buffer += _SIZEOF_ADDR_IFREQ(*current); +# else + buffer += sizeof(struct ifreq); +# endif + } + } @finally { + free(ifrs); + closesocket(sock); + } + + return true; +#else + return false; +#endif +} + ++ (OFDictionary OF_GENERIC(OFString *, OFNetworkInterface) *)networkInterfaces +{ + void *pool = objc_autoreleasePoolPush(); + OFMutableDictionary *ret = [OFMutableDictionary dictionary]; + bool success = false; + OFEnumerator *enumerator; + OFMutableDictionary *interface; + + success |= queryNetworkInterfaceIndices(ret); + success |= queryNetworkInterfaceIPv4Addresses(ret); +#ifdef OF_HAVE_IPV6 + success |= queryNetworkInterfaceIPv6Addresses(ret); +#endif +#ifdef OF_HAVE_IPX + success |= queryNetworkInterfaceIPXAddresses(ret); +#endif +#ifdef OF_HAVE_APPLETALK + success |= queryNetworkInterfaceAppleTalkAddresses(ret); +#endif + success |= queryNetworkInterfaceHardwareAddress(ret); + + if (!success) { + objc_autoreleasePoolPop(pool); + return nil; + } + + enumerator = [ret objectEnumerator]; + while ((interface = [enumerator nextObject]) != nil) + [interface makeImmutable]; + + [ret makeImmutable]; + [ret retain]; + + objc_autoreleasePoolPop(pool); + + return [ret autorelease]; +} +@end Index: src/platform/POSIX/OFTLSKey.m ================================================================== --- src/platform/POSIX/OFTLSKey.m +++ src/platform/POSIX/OFTLSKey.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,12 +20,13 @@ "0:\n\t" "lwarx %0, 0, %2\n\t" "add %0, %0, %1\n\t" "stwcx. %0, 0, %2\n\t" "bne- 0b" - : "=&r"(i) - : "r"(i), "r"(p) + : "=&r" (i) + : "r" (i), + "r" (p) : "cc", "memory" ); return i; } @@ -37,12 +38,13 @@ "0:\n\t" "lwarx %0, 0, %2\n\t" "add %0, %0, %1\n\t" "stwcx. %0, 0, %2\n\t" "bne- 0b" - : "=&r"(i) - : "r"(i), "r"(p) + : "=&r" (i) + : "r" (i), + "r" (p) : "cc", "memory" ); return i; } @@ -54,12 +56,13 @@ "0:\n\t" "lwarx %0, 0, %2\n\t" "add %0, %0, %1\n\t" "stwcx. %0, 0, %2\n\t" "bne- 0b" - : "=&r"(i) - : "r"(i), "r"(p) + : "=&r" (i) + : "r" (i), + "r" (p) : "cc", "memory" ); return (void *)i; } @@ -71,12 +74,13 @@ "0:\n\t" "lwarx %0, 0, %2\n\t" "sub %0, %0, %1\n\t" "stwcx. %0, 0, %2\n\t" "bne- 0b" - : "=&r"(i) - : "r"(i), "r"(p) + : "=&r" (i) + : "r" (i), + "r" (p) : "cc", "memory" ); return i; } @@ -88,12 +92,13 @@ "0:\n\t" "lwarx %0, 0, %2\n\t" "sub %0, %0, %1\n\t" "stwcx. %0, 0, %2\n\t" "bne- 0b" - : "=&r"(i) - : "r"(i), "r"(p) + : "=&r" (i) + : "r" (i), + "r" (p) : "cc", "memory" ); return i; } @@ -105,12 +110,13 @@ "0:\n\t" "lwarx %0, 0, %2\n\t" "sub %0, %0, %1\n\t" "stwcx. %0, 0, %2\n\t" "bne- 0b" - : "=&r"(i) - : "r"(i), "r"(p) + : "=&r" (i) + : "r" (i), + "r" (p) : "cc", "memory" ); return (void *)i; } @@ -124,12 +130,12 @@ "0:\n\t" "lwarx %0, 0, %1\n\t" "addi %0, %0, 1\n\t" "stwcx. %0, 0, %1\n\t" "bne- 0b" - : "=&r"(i) - : "r"(p) + : "=&r" (i) + : "r" (p) : "cc", "memory" ); return i; } @@ -143,12 +149,12 @@ "0:\n\t" "lwarx %0, 0, %1\n\t" "addi %0, %0, 1\n\t" "stwcx. %0, 0, %1\n\t" "bne- 0b" - : "=&r"(i) - : "r"(p) + : "=&r" (i) + : "r" (p) : "cc", "memory" ); return i; } @@ -162,12 +168,12 @@ "0:\n\t" "lwarx %0, 0, %1\n\t" "subi %0, %0, 1\n\t" "stwcx. %0, 0, %1\n\t" "bne- 0b" - : "=&r"(i) - : "r"(p) + : "=&r" (i) + : "r" (p) : "cc", "memory" ); return i; } @@ -181,12 +187,12 @@ "0:\n\t" "lwarx %0, 0, %1\n\t" "subi %0, %0, 1\n\t" "stwcx. %0, 0, %1\n\t" "bne- 0b" - : "=&r"(i) - : "r"(p) + : "=&r" (i) + : "r" (p) : "cc", "memory" ); return i; } @@ -198,12 +204,13 @@ "0:\n\t" "lwarx %0, 0, %2\n\t" "or %0, %0, %1\n\t" "stwcx. %0, 0, %2\n\t" "bne- 0b" - : "=&r"(i) - : "r"(i), "r"(p) + : "=&r" (i) + : "r" (i), + "r" (p) : "cc", "memory" ); return i; } @@ -215,12 +222,13 @@ "0:\n\t" "lwarx %0, 0, %2\n\t" "or %0, %0, %1\n\t" "stwcx. %0, 0, %2\n\t" "bne- 0b" - : "=&r"(i) - : "r"(i), "r"(p) + : "=&r" (i) + : "r" (i), + "r" (p) : "cc", "memory" ); return i; } @@ -232,12 +240,13 @@ "0:\n\t" "lwarx %0, 0, %2\n\t" "and %0, %0, %1\n\t" "stwcx. %0, 0, %2\n\t" "bne- 0b" - : "=&r"(i) - : "r"(i), "r"(p) + : "=&r" (i) + : "r" (i), + "r" (p) : "cc", "memory" ); return i; } @@ -249,12 +258,13 @@ "0:\n\t" "lwarx %0, 0, %2\n\t" "and %0, %0, %1\n\t" "stwcx. %0, 0, %2\n\t" "bne- 0b" - : "=&r"(i) - : "r"(i), "r"(p) + : "=&r" (i) + : "r" (i), + "r" (p) : "cc", "memory" ); return i; } @@ -266,12 +276,13 @@ "0:\n\t" "lwarx %0, 0, %2\n\t" "xor %0, %0, %1\n\t" "stwcx. %0, 0, %2\n\t" "bne- 0b" - : "=&r"(i) - : "r"(i), "r"(p) + : "=&r" (i) + : "r" (i), + "r" (p) : "cc", "memory" ); return i; } @@ -283,12 +294,13 @@ "0:\n\t" "lwarx %0, 0, %2\n\t" "xor %0, %0, %1\n\t" "stwcx. %0, 0, %2\n\t" "bne- 0b" - : "=&r"(i) - : "r"(i), "r"(p) + : "=&r" (i) + : "r" (i), + "r" (p) : "cc", "memory" ); return i; } @@ -309,12 +321,14 @@ "b 2f\n\t" "1:\n\t" "stwcx. %0, 0, %3\n\t" "li %0, 0\n\t" "2:" - : "=&r"(r) - : "r"(o), "r"(n), "r"(p) + : "=&r" (r) + : "r" (o), + "r" (n), + "r" (p) : "cc", "memory" ); return r; } @@ -335,12 +349,14 @@ "b 2f\n\t" "1:\n\t" "stwcx. %0, 0, %3\n\t" "li %0, 0\n\t" "2:" - : "=&r"(r) - : "r"(o), "r"(n), "r"(p) + : "=&r" (r) + : "r" (o), + "r" (n), + "r" (p) : "cc", "memory" ); return r; } @@ -362,12 +378,14 @@ "b 2f\n\t" "1:\n\t" "stwcx. %0, 0, %3\n\t" "li %0, 0\n\t" "2:" - : "=&r"(r) - : "r"(o), "r"(n), "r"(p) + : "=&r" (r) + : "r" (o), + "r" (n), + "r" (p) : "cc", "memory" ); return r; } Index: src/platform/Windows/OFPlainCondition.m ================================================================== --- src/platform/Windows/OFPlainCondition.m +++ src/platform/Windows/OFPlainCondition.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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 "OFPlainCondition.h" +#import "OFConstantString.h" #include int OFPlainConditionNew(OFPlainCondition *condition) Index: src/platform/Windows/OFPlainMutex.m ================================================================== --- src/platform/Windows/OFPlainMutex.m +++ src/platform/Windows/OFPlainMutex.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,12 +16,11 @@ #include "config.h" #include #import "OFPlainThread.h" - -#import "macros.h" +#import "OFConstantString.h" #include struct ThreadContext { void (*function)(id); 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,12 +20,12 @@ #include "config.h" #import "OFString+PathAdditions.h" #import "OFArray.h" -#import "OFFileURIHandler.h" -#import "OFURI.h" +#import "OFFileIRIHandler.h" +#import "OFIRI.h" #import "OFInvalidFormatException.h" #import "OFOutOfRangeException.h" int _OFString_PathAdditions_reference; @@ -303,10 +303,13 @@ return [ret autorelease]; } - (OFString *)stringByAppendingPathComponent: (OFString *)component { + if (self.length == 0) + return component; + if ([self hasSuffix: @"\\"] || [self hasSuffix: @"/"]) return [self stringByAppendingString: component]; else { OFMutableString *ret = [[self mutableCopy] autorelease]; @@ -341,14 +344,14 @@ } - (bool)of_isDirectoryPath { return ([self hasSuffix: @"\\"] || [self hasSuffix: @"/"] || - [OFFileURIHandler of_directoryExistsAtPath: self]); + [OFFileIRIHandler of_directoryExistsAtPath: self]); } -- (OFString *)of_pathToURIPathWithPercentEncodedHost: +- (OFString *)of_pathToIRIPathWithPercentEncodedHost: (OFString **)percentEncodedHost { OFString *path = self; if ([path hasPrefix: @"\\\\"]) { @@ -357,11 +360,11 @@ if (components.count < 2) @throw [OFInvalidFormatException exception]; *percentEncodedHost = [[components objectAtIndex: 1] stringByAddingPercentEncodingWithAllowedCharacters: - [OFCharacterSet URIHostAllowedCharacterSet]]; + [OFCharacterSet IRIHostAllowedCharacterSet]]; path = [OFString pathWithComponents: [components objectsInRange: OFMakeRange(2, components.count - 2)]]; } path = [path stringByReplacingOccurrencesOfString: @"\\" @@ -369,11 +372,11 @@ path = [@"/" stringByAppendingString: path]; return path; } -- (OFString *)of_URIPathToPathWithPercentEncodedHost: +- (OFString *)of_IRIPathToPathWithPercentEncodedHost: (OFString *)percentEncodedHost { OFString *path = self; if (path.length > 1 && [path hasSuffix: @"/"] && @@ -396,11 +399,11 @@ } return path; } -- (OFString *)of_pathComponentToURIPathComponent +- (OFString *)of_pathComponentToIRIPathComponent { return [self stringByReplacingOccurrencesOfString: @"\\" withString: @"/"]; } @end Index: src/platform/Windows/OFSubprocess.m ================================================================== --- src/platform/Windows/OFSubprocess.m +++ src/platform/Windows/OFSubprocess.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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/platform/Windows/OFSystemInfo+NetworkInterfaces.m Index: src/platform/Windows/OFSystemInfo+NetworkInterfaces.m ================================================================== --- /dev/null +++ src/platform/Windows/OFSystemInfo+NetworkInterfaces.m @@ -0,0 +1,266 @@ +/* + * Copyright (c) 2008-2024 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#include "config.h" + +#import "OFSystemInfo.h" +#import "OFSystemInfo+NetworkInterfaces.h" +#import "OFData.h" +#import "OFDictionary.h" +#import "OFLocale.h" +#import "OFNumber.h" +#import "OFOnce.h" +#import "OFSocket.h" +#import "OFString.h" + +#include +#define interface struct +#include +#undef interface + +static WINAPI ULONG (*GetAdaptersAddressesFuncPtr)(ULONG, ULONG, PVOID, + PIP_ADAPTER_ADDRESSES, PULONG); + +static void +init(void) +{ + HMODULE module; + + if ((module = GetModuleHandle("iphlpapi.dll")) != NULL) + GetAdaptersAddressesFuncPtr = (WINAPI ULONG (*)(ULONG, ULONG, + PVOID, PIP_ADAPTER_ADDRESSES, PULONG)) + GetProcAddress(module, "GetAdaptersAddresses"); + +} + +static OFMutableDictionary OF_GENERIC(OFString *, OFNetworkInterface) * +networkInterfacesFromGetAdaptersAddresses(void) +{ + OFMutableDictionary *ret = [OFMutableDictionary dictionary]; + ULONG adapterAddressesSize = sizeof(IP_ADAPTER_ADDRESSES); + PIP_ADAPTER_ADDRESSES adapterAddresses; + + if ((adapterAddresses = malloc(adapterAddressesSize)) == NULL) + return nil; + + @try { + ULONG error = GetAdaptersAddressesFuncPtr(AF_UNSPEC, 0, NULL, + adapterAddresses, &adapterAddressesSize); + + if (error == ERROR_BUFFER_OVERFLOW) { + PIP_ADAPTER_ADDRESSES newAdapterAddresses = + realloc(adapterAddresses, adapterAddressesSize); + + if (newAdapterAddresses == NULL) + return nil; + + adapterAddresses = newAdapterAddresses; + error = GetAdaptersAddressesFuncPtr(AF_UNSPEC, 0, NULL, + adapterAddresses, &adapterAddressesSize); + } + + if (error != ERROR_SUCCESS) + return nil; + + for (PIP_ADAPTER_ADDRESSES iter = adapterAddresses; + iter != NULL; iter = iter->Next) { + OFString *name; + OFMutableDictionary *interface; + OFNumber *index; + + name = [OFString stringWithFormat: @"%lu", + iter->IfIndex]; + + if ((interface = [ret objectForKey: name]) == nil) { + interface = [OFMutableDictionary dictionary]; + [ret setObject: interface forKey: name]; + } + + index = [OFNumber numberWithUnsignedInt: iter->IfIndex]; + [interface setObject: index + forKey: OFNetworkInterfaceIndex]; + + if (iter->PhysicalAddressLength > 0) { + const OFNetworkInterfaceKey key = + OFNetworkInterfaceHardwareAddress; + OFData *address = [OFData + dataWithItems: iter->PhysicalAddress + count: iter->PhysicalAddressLength]; + [interface setObject: address forKey: key]; + } + + for (PIP_ADAPTER_UNICAST_ADDRESS_LH addrIter = + iter->FirstUnicastAddress; addrIter != NULL; + addrIter = addrIter->Next) { + OFSocketAddress address; + int length; + OFNetworkInterfaceKey key; + OFMutableData *addresses; + + length = (int)sizeof(address.sockaddr); + if (length > addrIter->Address.iSockaddrLength) + length = + addrIter->Address.iSockaddrLength; + + memset(&address, 0, sizeof(OFSocketAddress)); + memcpy(&address.sockaddr, + addrIter->Address.lpSockaddr, + (size_t)length); + + switch (address.sockaddr.in.sin_family) { + case AF_INET: + address.family = + OFSocketAddressFamilyIPv4; + key = OFNetworkInterfaceIPv4Addresses; + break; + case AF_INET6: + address.family = + OFSocketAddressFamilyIPv6; + key = OFNetworkInterfaceIPv6Addresses; + break; + default: + continue; + } + + addresses = [interface objectForKey: key]; + if (addresses == nil) { + addresses = [OFMutableData + dataWithItemSize: + sizeof(OFSocketAddress)]; + [interface setObject: addresses + forKey: key]; + } + + [addresses addItem: &address]; + } + + [[interface objectForKey: + OFNetworkInterfaceIPv4Addresses] makeImmutable]; + [[interface objectForKey: + OFNetworkInterfaceIPv6Addresses] makeImmutable]; + } + } @finally { + free(adapterAddresses); + } + + return ret; +} + +static OFMutableDictionary OF_GENERIC(OFString *, OFNetworkInterface) * +networkInterfacesFromGetAdaptersInfo(void) +{ + OFMutableDictionary *ret = [OFMutableDictionary dictionary]; + OFStringEncoding encoding = [OFLocale encoding]; + ULONG adapterInfoSize = sizeof(IP_ADAPTER_INFO); + PIP_ADAPTER_INFO adapterInfo; + + if ((adapterInfo = malloc(adapterInfoSize)) == NULL) + return nil; + + @try { + ULONG error = GetAdaptersInfo(adapterInfo, &adapterInfoSize); + + if (error == ERROR_BUFFER_OVERFLOW) { + PIP_ADAPTER_INFO newAdapterInfo = + realloc(adapterInfo, adapterInfoSize); + + if (newAdapterInfo == NULL) + return nil; + + adapterInfo = newAdapterInfo; + error = GetAdaptersInfo(adapterInfo, &adapterInfoSize); + } + + if (error != ERROR_SUCCESS) + return nil; + + for (PIP_ADAPTER_INFO iter = adapterInfo; iter != NULL; + iter = iter->Next) { + OFMutableDictionary *interface; + OFString *name, *IPString; + OFNumber *index; + OFSocketAddress IPv4Address; + OFData *addresses; + + name = [OFString stringWithFormat: @"%u", iter->Index]; + + if ((interface = [ret objectForKey: name]) == nil) { + interface = [OFMutableDictionary dictionary]; + [ret setObject: interface forKey: name]; + } + + index = [OFNumber numberWithUnsignedInt: iter->Index]; + [interface setObject: index + forKey: OFNetworkInterfaceIndex]; + + if (iter->AddressLength > 0) { + const OFNetworkInterfaceKey key = + OFNetworkInterfaceHardwareAddress; + OFData *address = [OFData + dataWithItems: iter->Address + count: iter->AddressLength]; + [interface setObject: address forKey: key]; + } + + IPString = [OFString + stringWithCString: iter->IpAddressList.IpAddress + .String + encoding: encoding]; + + if ([IPString isEqual: @"0.0.0.0"]) + continue; + + IPv4Address = OFSocketAddressParseIPv4(IPString, 0); + addresses = [OFData dataWithItems: &IPv4Address + count: 1 + itemSize: sizeof(IPv4Address)]; + [interface setObject: addresses + forKey: OFNetworkInterfaceIPv4Addresses]; + } + } @finally { + free(adapterInfo); + } + + return ret; +} + +@implementation OFSystemInfo (NetworkInterfaces) ++ (OFDictionary OF_GENERIC(OFString *, OFNetworkInterface) *)networkInterfaces +{ + static OFOnceControl onceControl = OFOnceControlInitValue; + void *pool = objc_autoreleasePoolPush(); + OFMutableDictionary *ret; + OFEnumerator *enumerator; + OFMutableDictionary *interface; + + OFOnce(&onceControl, init); + + if (GetAdaptersAddressesFuncPtr != NULL) + ret = networkInterfacesFromGetAdaptersAddresses(); + else + ret = networkInterfacesFromGetAdaptersInfo(); + + enumerator = [ret objectEnumerator]; + while ((interface = [enumerator nextObject]) != nil) + [interface makeImmutable]; + + [ret makeImmutable]; + [ret retain]; + + objc_autoreleasePoolPop(pool); + + return [ret autorelease]; +} +@end Index: src/platform/Windows/OFTLSKey.m ================================================================== --- src/platform/Windows/OFTLSKey.m +++ src/platform/Windows/OFTLSKey.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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/OFWin32ConsoleStdIOStream.m ================================================================== --- src/platform/Windows/OFWin32ConsoleStdIOStream.m +++ src/platform/Windows/OFWin32ConsoleStdIOStream.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,10 @@ * writing binary), it checks that the handle is indeed a console. */ #include "config.h" -#include #include #include #import "OFWin32ConsoleStdIOStream.h" #import "OFColor.h" @@ -293,11 +292,11 @@ UTF8Len = OFUTF8StringDecode( _incompleteUTF8Surrogate, _incompleteUTF8SurrogateLen, &c); if (UTF8Len <= 0 || c > 0x10FFFF) { - assert(UTF8Len == 0 || UTF8Len < -4); + OFAssert(UTF8Len == 0 || UTF8Len < -4); UTF16[0] = 0xFFFD; UTF16Len = 1; } else { if (c > 0xFFFF) { 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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 @@ #include "config.h" #import "OFString+PathAdditions.h" #import "OFArray.h" -#import "OFFileURIHandler.h" +#import "OFFileIRIHandler.h" #import "OFOutOfRangeException.h" int _OFString_PathAdditions_reference; @@ -299,10 +299,13 @@ return [ret autorelease]; } - (OFString *)stringByAppendingPathComponent: (OFString *)component { + if (self.length == 0) + return component; + if ([self hasSuffix: @"/"]) return [self stringByAppendingString: component]; else { OFMutableString *ret = [[self mutableCopy] autorelease]; @@ -337,20 +340,20 @@ } - (bool)of_isDirectoryPath { return ([self hasSuffix: @"/"] || - [OFFileURIHandler of_directoryExistsAtPath: self]); + [OFFileIRIHandler of_directoryExistsAtPath: self]); } -- (OFString *)of_pathToURIPathWithPercentEncodedHost: +- (OFString *)of_pathToIRIPathWithPercentEncodedHost: (OFString **)percentEncodedHost { return [@"/" stringByAppendingString: self]; } -- (OFString *)of_URIPathToPathWithPercentEncodedHost: +- (OFString *)of_IRIPathToPathWithPercentEncodedHost: (OFString *)percentEncodedHost { OFString *path = self; if (path.length > 1 && [path hasSuffix: @"/"]) @@ -357,10 +360,10 @@ path = [path substringToIndex: path.length - 1]; return [path substringFromIndex: 1]; } -- (OFString *)of_pathComponentToURIPathComponent +- (OFString *)of_pathComponentToIRIPathComponent { return self; } @end Index: src/platform/macOS/OFAtomic.h ================================================================== --- src/platform/macOS/OFAtomic.h +++ src/platform/macOS/OFAtomic.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,225 +13,179 @@ * file. */ OF_ASSUME_NONNULL_BEGIN -static OF_INLINE int -OFAtomicIntAdd(volatile int *_Nonnull p, int i) -{ - if (sizeof(int) == 4) - __asm__ __volatile__ ( - "lock\n\t" - "xaddl %0, %2\n\t" - "addl %1, %0" - : "+&r"(i) - : "r"(i), "m"(*p) - ); -#ifdef OF_X86_64 - else if (sizeof(int) == 8) - __asm__ __volatile__ ( - "lock\n\t" - "xaddq %0, %2\n\t" - "addq %1, %0" - : "+&r"(i) - : "r"(i), "m"(*p) - ); -#endif - else - abort(); - - return i; -} - static OF_INLINE int32_t OFAtomicInt32Add(volatile int32_t *_Nonnull p, int32_t i) { __asm__ __volatile__ ( "lock\n\t" - "xaddl %0, %2\n\t" - "addl %1, %0" - : "+&r"(i) - : "r"(i), "m"(*p) + "xadd{l} { %0, %2 | %2, %0 }\n\t" + "add{l} { %1, %0 | %0, %1 }" + : "+&r" (i) + : "r" (i), + "m" (*p) ); + + return i; +} + +static OF_INLINE int +OFAtomicIntAdd(volatile int *_Nonnull p, int i) +{ + if (sizeof(int) == 4) + return OFAtomicInt32Add(p, i); +#ifdef OF_AMD64 + else if (sizeof(int) == 8) + __asm__ __volatile__ ( + "lock\n\t" + "xadd{q} { %0, %2 | %2, %0 }\n\t" + "add{q} { %1, %0 | %0, %1 }" + : "+&r" (i) + : "r" (i), + "m" (*p) + ); +#endif + else + abort(); return i; } static OF_INLINE void *_Nullable OFAtomicPointerAdd(void *volatile _Nullable *_Nonnull p, intptr_t i) { -#if defined(OF_X86_64) +#if defined(OF_AMD64) __asm__ __volatile__ ( "lock\n\t" - "xaddq %0, %2\n\t" - "addq %1, %0" - : "+&r"(i) - : "r"(i), "m"(*p) + "xadd{q} { %0, %2 | %2, %0 }\n\t" + "add{q} { %1, %0 | %0, %1 }" + : "+&r" (i) + : "r" (i), + "m" (*p) ); return (void *)i; #elif defined(OF_X86) __asm__ __volatile__ ( "lock\n\t" - "xaddl %0, %2\n\t" - "addl %1, %0" - : "+&r"(i) - : "r"(i), "m"(*p) + "xadd{l} { %0, %2 | %2, %0 }\n\t" + "add{l} { %1, %0 | %0, %1 }" + : "+&r" (i) + : "r" (i), + "m" (*p) ); return (void *)i; #endif } + +static OF_INLINE int32_t +OFAtomicInt32Subtract(volatile int32_t *_Nonnull p, int32_t i) +{ + __asm__ __volatile__ ( + "neg{l} %0\n\t" + "lock\n\t" + "xadd{l} { %0, %2 | %2, %0 }\n\t" + "sub{l} { %1, %0 | %0, %1 }" + : "+&r" (i) + : "r" (i), + "m" (*p) + ); + + return i; +} static OF_INLINE int OFAtomicIntSubtract(volatile int *_Nonnull p, int i) { if (sizeof(int) == 4) - __asm__ __volatile__ ( - "negl %0\n\t" - "lock\n\t" - "xaddl %0, %2\n\t" - "subl %1, %0" - : "+&r"(i) - : "r"(i), "m"(*p) - ); -#ifdef OF_X86_64 + return OFAtomicInt32Subtract(p, i); +#ifdef OF_AMD64 else if (sizeof(int) == 8) __asm__ __volatile__ ( - "negq %0\n\t" + "neg{q} %0\n\t" "lock\n\t" - "xaddq %0, %2\n\t" - "subq %1, %0" - : "+&r"(i) - : "r"(i), "m"(*p) + "xadd{q} { %0, %2 | %2, %0 }\n\t" + "sub{q} { %1, %0 | %0, %1 }" + : "+&r" (i) + : "r" (i), + "m" (*p) ); #endif else abort(); return i; } -static OF_INLINE int32_t -OFAtomicInt32Subtract(volatile int32_t *_Nonnull p, int32_t i) -{ - __asm__ __volatile__ ( - "negl %0\n\t" - "lock\n\t" - "xaddl %0, %2\n\t" - "subl %1, %0" - : "+&r"(i) - : "r"(i), "m"(*p) - ); - - return i; -} - static OF_INLINE void *_Nullable OFAtomicPointerSubtract(void *volatile _Nullable *_Nonnull p, intptr_t i) { -#if defined(OF_X86_64) +#if defined(OF_AMD64) __asm__ __volatile__ ( - "negq %0\n\t" + "neg{q} %0\n\t" "lock\n\t" - "xaddq %0, %2\n\t" - "subq %1, %0" - : "+&r"(i) - : "r"(i), "m"(*p) + "xadd{q} { %0, %2 | %2, %0 }\n\t" + "sub{q} { %1, %0 | %0, %1 }" + : "+&r" (i) + : "r" (i), + "m" (*p) ); return (void *)i; #elif defined(OF_X86) __asm__ __volatile__ ( - "negl %0\n\t" + "neg{l} %0\n\t" "lock\n\t" - "xaddl %0, %2\n\t" - "subl %1, %0" - : "+&r"(i) - : "r"(i), "m"(*p) + "xadd{l} { %0, %2 | %2, %0 }\n\t" + "sub{l} { %1, %0 | %0, %1 }" + : "+&r" (i) + : "r" (i), + "m" (*p) ); return (void *)i; #endif } + +static OF_INLINE int32_t +OFAtomicInt32Increase(volatile int32_t *_Nonnull p) +{ + int32_t i; + + __asm__ __volatile__ ( + "xor{l} %0, %0\n\t" + "inc{l} %0\n\t" + "lock\n\t" + "xadd{l} { %0, %1 | %1, %0 }\n\t" + "inc{l} %0" + : "=&r" (i) + : "m" (*p) + ); + + return i; +} static OF_INLINE int OFAtomicIntIncrease(volatile int *_Nonnull p) { int i; if (sizeof(int) == 4) - __asm__ __volatile__ ( - "xorl %0, %0\n\t" - "incl %0\n\t" - "lock\n\t" - "xaddl %0, %1\n\t" - "incl %0" - : "=&r"(i) - : "m"(*p) - ); -#ifdef OF_X86_64 - else if (sizeof(int) == 8) - __asm__ __volatile__ ( - "xorq %0, %0\n\t" - "incq %0\n\t" - "lock\n\t" - "xaddq %0, %1\n\t" - "incq %0" - : "=&r"(i) - : "m"(*p) - ); -#endif - else - abort(); - - return i; -} - -static OF_INLINE int32_t -OFAtomicInt32Increase(volatile int32_t *_Nonnull p) -{ - int32_t i; - - __asm__ __volatile__ ( - "xorl %0, %0\n\t" - "incl %0\n\t" - "lock\n\t" - "xaddl %0, %1\n\t" - "incl %0" - : "=&r"(i) - : "m"(*p) - ); - - return i; -} - -static OF_INLINE int -OFAtomicIntDecrease(volatile int *_Nonnull p) -{ - int i; - - if (sizeof(int) == 4) - __asm__ __volatile__ ( - "xorl %0, %0\n\t" - "decl %0\n\t" - "lock\n\t" - "xaddl %0, %1\n\t" - "decl %0" - : "=&r"(i) - : "m"(*p) - ); -#ifdef OF_X86_64 - else if (sizeof(int) == 8) - __asm__ __volatile__ ( - "xorq %0, %0\n\t" - "decq %0\n\t" - "lock\n\t" - "xaddq %0, %1\n\t" - "decq %0" - : "=&r"(i) - : "m"(*p) + return OFAtomicInt32Increase(p); +#ifdef OF_AMD64 + else if (sizeof(int) == 8) + __asm__ __volatile__ ( + "xor{q} %0, %0\n\t" + "inc{q} %0\n\t" + "lock\n\t" + "xadd{q} { %0, %1 | %1, %0 }\n\t" + "inc{q} %0" + : "=&r" (i) + : "m" (*p) ); #endif else abort(); @@ -242,51 +196,39 @@ OFAtomicInt32Decrease(volatile int32_t *_Nonnull p) { int32_t i; __asm__ __volatile__ ( - "xorl %0, %0\n\t" - "decl %0\n\t" + "xor{l} %0, %0\n\t" + "dec{l} %0\n\t" "lock\n\t" - "xaddl %0, %1\n\t" - "decl %0" - : "=&r"(i) - : "m"(*p) + "xadd{l} { %0, %1 | %1, %0 }\n\t" + "dec{l} %0" + : "=&r" (i) + : "m" (*p) ); return i; } -static OF_INLINE unsigned int -OFAtomicIntOr(volatile unsigned int *_Nonnull p, unsigned int i) +static OF_INLINE int +OFAtomicIntDecrease(volatile int *_Nonnull p) { + int i; + if (sizeof(int) == 4) - __asm__ __volatile__ ( - "0:\n\t" - "movl %2, %0\n\t" - "movl %0, %%eax\n\t" - "orl %1, %0\n\t" - "lock\n\t" - "cmpxchg %0, %2\n\t" - "jne 0b" - : "=&r"(i) - : "r"(i), "m"(*p) - : "eax", "cc" - ); -#ifdef OF_X86_64 + return OFAtomicInt32Decrease(p); +#ifdef OF_AMD64 else if (sizeof(int) == 8) __asm__ __volatile__ ( - "0:\n\t" - "movq %2, %0\n\t" - "movq %0, %%rax\n\t" - "orq %1, %0\n\t" + "xor{q} %0, %0\n\t" + "dec{q} %0\n\t" "lock\n\t" - "cmpxchg %0, %2\n\t" - "jne 0b" - : "=&r"(i) - : "r"(i), "m"(*p) - : "rax", "cc" + "xadd{q} { %0, %1 | %1, %0 }\n\t" + "dec{q} %0" + : "=&r" (i) + : "m" (*p) ); #endif else abort(); @@ -296,52 +238,43 @@ static OF_INLINE uint32_t OFAtomicInt32Or(volatile uint32_t *_Nonnull p, uint32_t i) { __asm__ __volatile__ ( "0:\n\t" - "movl %2, %0\n\t" - "movl %0, %%eax\n\t" - "orl %1, %0\n\t" + "mov{l} { %2, %0 | %0, %2 }\n\t" + "mov{l} { %0, %%eax | eax, %0 }\n\t" + "or{l} { %1, %0 | %0, %1 }\n\t" "lock\n\t" - "cmpxchg %0, %2\n\t" + "cmpxchg{l} { %0, %2 | %2, %0 }\n\t" "jne 0b" - : "=&r"(i) - : "r"(i), "m"(*p) + : "=&r" (i) + : "r" (i), + "m" (*p) : "eax", "cc" ); return i; } static OF_INLINE unsigned int -OFAtomicIntAnd(volatile unsigned int *_Nonnull p, unsigned int i) +OFAtomicIntOr(volatile unsigned int *_Nonnull p, unsigned int i) { if (sizeof(int) == 4) - __asm__ __volatile__ ( - "0:\n\t" - "movl %2, %0\n\t" - "movl %0, %%eax\n\t" - "andl %1, %0\n\t" - "lock\n\t" - "cmpxchg %0, %2\n\t" - "jne 0b" - : "=&r"(i) - : "r"(i), "m"(*p) - : "eax", "cc" - ); -#ifdef OF_X86_64 + return OFAtomicInt32Or(p, i); +#ifdef OF_AMD64 else if (sizeof(int) == 8) __asm__ __volatile__ ( "0:\n\t" - "movq %2, %0\n\t" - "movq %0, %%rax\n\t" - "andq %1, %0\n\t" + "mov{q} { %2, %0 | %0, %2 }\n\t" + "mov{q} { %0, %%rax | rax, %0 }\n\t" + "or{q} { %1, %0 | %0, %1 }\n\t" "lock\n\t" - "cmpxchg %0, %2\n\t" + "cmpxchg{q} { %0, %2 | %2, %0 }\n\t" "jne 0b" - : "=&r"(i) - : "r"(i), "m"(*p) + : "=&r" (i) + : "r" (i), + "m" (*p) : "rax", "cc" ); #endif else abort(); @@ -352,52 +285,43 @@ static OF_INLINE uint32_t OFAtomicInt32And(volatile uint32_t *_Nonnull p, uint32_t i) { __asm__ __volatile__ ( "0:\n\t" - "movl %2, %0\n\t" - "movl %0, %%eax\n\t" - "andl %1, %0\n\t" + "mov{l} { %2, %0 | %0, %2 }\n\t" + "mov{l} { %0, %%eax | eax, %0 }\n\t" + "and{l} { %1, %0 | %0, %1 }\n\t" "lock\n\t" - "cmpxchg %0, %2\n\t" + "cmpxchg{l} { %0, %2 | %2, %0 }\n\t" "jne 0b" - : "=&r"(i) - : "r"(i), "m"(*p) + : "=&r" (i) + : "r" (i), + "m" (*p) : "eax", "cc" ); return i; } static OF_INLINE unsigned int -OFAtomicIntXor(volatile unsigned int *_Nonnull p, unsigned int i) +OFAtomicIntAnd(volatile unsigned int *_Nonnull p, unsigned int i) { if (sizeof(int) == 4) - __asm__ __volatile__ ( - "0:\n\t" - "movl %2, %0\n\t" - "movl %0, %%eax\n\t" - "xorl %1, %0\n\t" - "lock\n\t" - "cmpxchg %0, %2\n\t" - "jne 0b" - : "=&r"(i) - : "r"(i), "m"(*p) - : "eax", "cc" - ); -#ifdef OF_X86_64 + return OFAtomicInt32And(p, i); +#ifdef OF_AMD64 else if (sizeof(int) == 8) __asm__ __volatile__ ( "0:\n\t" - "movq %2, %0\n\t" - "movq %0, %%rax\n\t" - "xorq %1, %0\n\t" + "mov{q} { %2, %0 | %0, %2 }\n\t" + "mov{q} { %0, %%rax | rax, %0 }\n\t" + "and{q} { %1, %0 | %0, %1 }\n\t" "lock\n\t" - "cmpxchg %0, %2\n\t" + "cmpxchg{q} { %0, %2 | %2, %0 }\n\t" "jne 0b" - : "=&r"(i) - : "r"(i), "m"(*p) + : "=&r" (i) + : "r" (i), + "m" (*p) : "rax", "cc" ); #endif else abort(); @@ -408,54 +332,86 @@ static OF_INLINE uint32_t OFAtomicInt32Xor(volatile uint32_t *_Nonnull p, uint32_t i) { __asm__ __volatile__ ( "0:\n\t" - "movl %2, %0\n\t" - "movl %0, %%eax\n\t" - "xorl %1, %0\n\t" + "mov{l} { %2, %0 | %0, %2 }\n\t" + "mov{l} { %0, %%eax | eax, %0 }\n\t" + "xor{l} { %1, %0 | %0, %1 }\n\t" "lock\n\t" - "cmpxchgl %0, %2\n\t" + "cmpxchg{l} { %0, %2 | %2, %0 }\n\t" "jne 0b" - : "=&r"(i) - : "r"(i), "m"(*p) + : "=&r" (i) + : "r" (i), + "m" (*p) : "eax", "cc" ); return i; } -static OF_INLINE bool -OFAtomicIntCompareAndSwap(volatile int *_Nonnull p, int o, int n) -{ - int r; - - __asm__ __volatile__ ( - "lock\n\t" - "cmpxchg %2, %3\n\t" - "sete %b0\n\t" - "movzbl %b0, %0" - : "=&d"(r), "+a"(o) /* use d instead of r to avoid a gcc bug */ - : "r"(n), "m"(*p) - : "cc" - ); - - return r; +static OF_INLINE unsigned int +OFAtomicIntXor(volatile unsigned int *_Nonnull p, unsigned int i) +{ + if (sizeof(int) == 4) + return OFAtomicInt32Xor(p, i); +#ifdef OF_AMD64 + else if (sizeof(int) == 8) + __asm__ __volatile__ ( + "0:\n\t" + "mov{q} { %2, %0 | %0, %2 }\n\t" + "mov{q} { %0, %%rax | rax, %0 }\n\t" + "xor{q} { %1, %0 | %0, %1 }\n\t" + "lock\n\t" + "cmpxchg{q} { %0, %2 | %2, %0 }\n\t" + "jne 0b" + : "=&r" (i) + : "r" (i), + "m" (*p) + : "rax", "cc" + ); +#endif + else + abort(); + + return i; } static OF_INLINE bool OFAtomicInt32CompareAndSwap(volatile int32_t *_Nonnull p, int32_t o, int32_t n) { int r; __asm__ __volatile__ ( "lock\n\t" - "cmpxchg %2, %3\n\t" + "cmpxchg{l} { %2, %3 | %3, %2 }\n\t" + "sete %b0\n\t" + "movz{bl|x} { %b0, %0 | %0, %b0 }" + : "=&d" (r), /* use d instead of r to avoid a gcc bug */ + "+a" (o) + : "r" (n), + "m" (*p) + : "cc" + ); + + return r; +} + +static OF_INLINE bool +OFAtomicIntCompareAndSwap(volatile int *_Nonnull p, int o, int n) +{ + int r; + + __asm__ __volatile__ ( + "lock\n\t" + "cmpxchg { %2, %3 | %3, %2 }\n\t" "sete %b0\n\t" - "movzbl %b0, %0" - : "=&d"(r), "+a"(o) /* use d instead of r to avoid a gcc bug */ - : "r"(n), "m"(*p) + "movz{bl|x} { %b0, %0 | %0, %b0 }" + : "=&d" (r), /* use d instead of r to avoid a gcc bug */ + "+a" (o) + : "r" (n), + "m" (*p) : "cc" ); return r; } @@ -466,27 +422,35 @@ { int r; __asm__ __volatile__ ( "lock\n\t" - "cmpxchg %2, %3\n\t" + "cmpxchg { %2, %3 | %3, %2 }\n\t" "sete %b0\n\t" - "movzbl %b0, %0" - : "=&d"(r), "+a"(o) /* use d instead of r to avoid a gcc bug */ - : "r"(n), "m"(*p) + "movz{bl|x} { %b0, %0 | %0, %b0 }" + : "=&d" (r), /* use d instead of r to avoid a gcc bug */ + "+a" (o) + : "r" (n), + "m" (*p) : "cc" ); return r; } static OF_INLINE void OFMemoryBarrier(void) { +#ifdef OF_AMD64 + __asm__ __volatile__ ( + "lock or{q} { $0, (%%rsp) | [rsp], 0 }" ::: "memory", "cc" + ); +#else __asm__ __volatile__ ( - "mfence" ::: "memory" + "lock or{l} { $0, (%%esp) | [esp], 0 }" ::: "memory", "cc" ); +#endif } static OF_INLINE void OFAcquireMemoryBarrier(void) { Index: src/runtime/Makefile ================================================================== --- src/runtime/Makefile +++ src/runtime/Makefile @@ -1,17 +1,16 @@ include ../../extra.mk SUBDIRS = lookup-asm -SUBDIRS_AFTER = ${LINKLIB} DISTCLEAN = Info.plist SHARED_LIB = ${OBJFWRT_SHARED_LIB} STATIC_LIB = ${OBJFWRT_STATIC_LIB} FRAMEWORK = ${OBJFWRT_FRAMEWORK} -AMIGA_LIB = ${OBJFWRT_AMIGA_LIB} LIB_MAJOR = ${OBJFWRT_LIB_MAJOR} LIB_MINOR = ${OBJFWRT_LIB_MINOR} +LIB_PATCH = ${OBJFWRT_LIB_PATCH} SRCS = arc.m \ autorelease.m \ category.m \ class.m \ @@ -41,25 +40,19 @@ INCLUDES = ObjFWRT.h includesubdir = ObjFWRT OBJS_EXTRA = lookup-asm/lookup-asm.a LIB_OBJS_EXTRA = lookup-asm/lookup-asm.lib.a -AMIGA_LIB_OBJS_START = amiga-library.amigalib.o -AMIGA_LIB_OBJS_EXTRA = amiga-glue.amigalib.o \ - lookup-asm/lookup-asm.amigalib.a \ - amiga-end.amigalib.o include ../../buildsys.mk CPPFLAGS += -I. -I.. -I../.. \ -DOBJC_COMPILING_RUNTIME \ - -DOBJFWRT_AMIGA_LIB=\"${OBJFWRT_AMIGA_LIB}\" \ -DOBJFWRT_LIB_MAJOR=${OBJFWRT_LIB_MAJOR} \ -DOBJFWRT_LIB_MINOR=${OBJFWRT_LIB_MINOR} -AMIGA_LIB_CFLAGS += -DOBJC_COMPILING_AMIGA_LIBRARY LD = ${OBJC} FRAMEWORK_LIBS = ${LIBS} RCFLAGS = --use-temp-file \ -DOBJFWRT_LIB_MAJOR=${OBJFWRT_LIB_MAJOR} \ -DOBJFWRT_LIB_MINOR=${OBJFWRT_LIB_MINOR} \ -DOBJFWRT_LIB_VERSION=\"${OBJFWRT_LIB_MAJOR}.${OBJFWRT_LIB_MINOR}\" \ -DOBJFWRT_SHARED_LIB=\"${OBJFWRT_SHARED_LIB}\" Index: src/runtime/OFOnce.m ================================================================== --- src/runtime/OFOnce.m +++ src/runtime/OFOnce.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -614,14 +614,14 @@ extern void objc_setTaggedPointerSecret(uintptr_t secret); /** * @brief Registers a class for tagged pointers. * - * @param class The class to register for tagged pointers + * @param class_ The class to register for tagged pointers * @return The tagged pointer ID for the registered class */ -extern int objc_registerTaggedPointerClass(Class _Nonnull class); +extern int objc_registerTaggedPointerClass(Class _Nonnull class_); /** * @brief Returns whether the specified object is a tagged pointer. * * @param object The object to inspect @@ -638,15 +638,15 @@ extern uintptr_t object_getTaggedPointerValue(id _Nonnull object); /** * @brief Creates a new tagged pointer. * - * @param class The tag ID for the tagged pointer class to use + * @param class_ The tag ID for the tagged pointer class to use * @param value The value the tagged pointer should have * @return A tagged pointer, or `nil` if it could not be created */ -extern id _Nullable objc_createTaggedPointer(int class, uintptr_t value); +extern id _Nullable objc_createTaggedPointer(int class_, uintptr_t value); /* * Used by the compiler, but can also be called manually. * * These declarations are also required to prevent Clang's implicit DELETED src/runtime/amiga-end.m Index: src/runtime/amiga-end.m ================================================================== --- src/runtime/amiga-end.m +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (c) 2008-2022 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#include "config.h" - -#include "platform.h" - -#ifdef OF_MORPHOS -__asm__ ( - ".section .eh_frame, \"aw\"\n" - " .long 0\n" - ".section .ctors, \"aw\"\n" - " .long 0" -); -#else -__asm__ ( - "" -); -#endif DELETED src/runtime/amiga-funcarray.inc Index: src/runtime/amiga-funcarray.inc ================================================================== --- src/runtime/amiga-funcarray.inc +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright (c) 2008-2022 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -/* This file is automatically generated from amiga-library.xml */ - -(CONST_APTR)glue_objc_init, -(CONST_APTR)glue___objc_exec_class, -(CONST_APTR)glue_objc_msg_lookup, -(CONST_APTR)glue_objc_msg_lookup_stret, -(CONST_APTR)glue_objc_msg_lookup_super, -(CONST_APTR)glue_objc_msg_lookup_super_stret, -(CONST_APTR)glue_objc_lookUpClass, -(CONST_APTR)glue_objc_getClass, -(CONST_APTR)glue_objc_getRequiredClass, -(CONST_APTR)glue_objc_lookup_class, -(CONST_APTR)glue_objc_get_class, -(CONST_APTR)glue_objc_exception_throw, -(CONST_APTR)glue_objc_sync_enter, -(CONST_APTR)glue_objc_sync_exit, -(CONST_APTR)glue_objc_getProperty, -(CONST_APTR)glue_objc_setProperty, -(CONST_APTR)glue_objc_getPropertyStruct, -(CONST_APTR)glue_objc_setPropertyStruct, -(CONST_APTR)glue_objc_enumerationMutation, -(CONST_APTR)glue___gnu_objc_personality, -(CONST_APTR)glue_objc_retain, -(CONST_APTR)glue_objc_retainBlock, -(CONST_APTR)glue_objc_retainAutorelease, -(CONST_APTR)glue_objc_release, -(CONST_APTR)glue_objc_autorelease, -(CONST_APTR)glue_objc_autoreleaseReturnValue, -(CONST_APTR)glue_objc_retainAutoreleaseReturnValue, -(CONST_APTR)glue_objc_retainAutoreleasedReturnValue, -(CONST_APTR)glue_objc_storeStrong, -(CONST_APTR)glue_objc_storeWeak, -(CONST_APTR)glue_objc_loadWeakRetained, -(CONST_APTR)glue_objc_initWeak, -(CONST_APTR)glue_objc_destroyWeak, -(CONST_APTR)glue_objc_loadWeak, -(CONST_APTR)glue_objc_copyWeak, -(CONST_APTR)glue_objc_moveWeak, -(CONST_APTR)glue_sel_registerName, -(CONST_APTR)glue_sel_getName, -(CONST_APTR)glue_sel_isEqual, -(CONST_APTR)glue_objc_allocateClassPair, -(CONST_APTR)glue_objc_registerClassPair, -(CONST_APTR)glue_objc_getClassList, -(CONST_APTR)glue_objc_copyClassList, -(CONST_APTR)glue_class_isMetaClass, -(CONST_APTR)glue_class_getName, -(CONST_APTR)glue_class_getSuperclass, -(CONST_APTR)glue_class_getInstanceSize, -(CONST_APTR)glue_class_respondsToSelector, -(CONST_APTR)glue_class_conformsToProtocol, -(CONST_APTR)glue_class_getMethodImplementation, -(CONST_APTR)glue_class_getMethodImplementation_stret, -(CONST_APTR)glue_class_getInstanceMethod, -(CONST_APTR)glue_class_addMethod, -(CONST_APTR)glue_class_replaceMethod, -(CONST_APTR)glue_object_getClass, -(CONST_APTR)glue_object_setClass, -(CONST_APTR)glue_object_getClassName, -(CONST_APTR)glue_protocol_getName, -(CONST_APTR)glue_protocol_isEqual, -(CONST_APTR)glue_protocol_conformsToProtocol, -(CONST_APTR)glue_objc_setUncaughtExceptionHandler, -(CONST_APTR)glue_objc_setForwardHandler, -(CONST_APTR)glue_objc_setEnumerationMutationHandler, -(CONST_APTR)glue_objc_constructInstance, -(CONST_APTR)glue_objc_deinit, -(CONST_APTR)glue_class_copyIvarList, -(CONST_APTR)glue_ivar_getName, -(CONST_APTR)glue_ivar_getTypeEncoding, -(CONST_APTR)glue_ivar_getOffset, -(CONST_APTR)glue_class_copyMethodList, -(CONST_APTR)glue_method_getName, -(CONST_APTR)glue_method_getTypeEncoding, -(CONST_APTR)glue_class_copyPropertyList, -(CONST_APTR)glue_property_getName, -(CONST_APTR)glue_property_copyAttributeValue, -(CONST_APTR)glue_objc_destructInstance, -(CONST_APTR)glue_objc_autoreleasePoolPush, -(CONST_APTR)glue_objc_autoreleasePoolPop, -(CONST_APTR)glue__objc_rootAutorelease, -(CONST_APTR)glue_objc_hashtable_new, -(CONST_APTR)glue_objc_hashtable_set, -(CONST_APTR)glue_objc_hashtable_get, -(CONST_APTR)glue_objc_hashtable_delete, -(CONST_APTR)glue_objc_hashtable_free, -(CONST_APTR)glue_objc_setTaggedPointerSecret, -(CONST_APTR)glue_objc_registerTaggedPointerClass, -(CONST_APTR)glue_object_isTaggedPointer, -(CONST_APTR)glue_object_getTaggedPointerValue, -(CONST_APTR)glue_objc_createTaggedPointer, DELETED src/runtime/amiga-glue.h Index: src/runtime/amiga-glue.h ================================================================== --- src/runtime/amiga-glue.h +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright (c) 2008-2022 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -/* This file is automatically generated from amiga-library.xml */ - -#import "ObjFWRT.h" -#import "private.h" - -#ifdef OF_AMIGAOS_M68K -# define PPC_PARAMS(...) (void) -# define M68K_ARG(type, name, reg) \ - register type reg##name __asm__(#reg); \ - type name = reg##name; -#else -# define PPC_PARAMS(...) (__VA_ARGS__) -# define M68K_ARG(...) -#endif - -extern bool glue_objc_init PPC_PARAMS(unsigned int version, struct objc_libc *libc); -extern void glue___objc_exec_class PPC_PARAMS(struct objc_module *_Nonnull module); -extern IMP _Nonnull glue_objc_msg_lookup PPC_PARAMS(id _Nullable object, SEL _Nonnull selector); -extern IMP _Nonnull glue_objc_msg_lookup_stret PPC_PARAMS(id _Nullable object, SEL _Nonnull selector); -extern IMP _Nonnull glue_objc_msg_lookup_super PPC_PARAMS(struct objc_super *_Nonnull super, SEL _Nonnull selector); -extern IMP _Nonnull glue_objc_msg_lookup_super_stret PPC_PARAMS(struct objc_super *_Nonnull super, SEL _Nonnull selector); -extern Class _Nullable glue_objc_lookUpClass PPC_PARAMS(const char *_Nonnull name); -extern Class _Nullable glue_objc_getClass PPC_PARAMS(const char *_Nonnull name); -extern Class _Nonnull glue_objc_getRequiredClass PPC_PARAMS(const char *_Nonnull name); -extern Class _Nullable glue_objc_lookup_class PPC_PARAMS(const char *_Nonnull name); -extern Class _Nonnull glue_objc_get_class PPC_PARAMS(const char *_Nonnull name); -extern void glue_objc_exception_throw PPC_PARAMS(id _Nonnull object); -extern int glue_objc_sync_enter PPC_PARAMS(id _Nullable object); -extern int glue_objc_sync_exit PPC_PARAMS(id _Nullable object); -extern id _Nullable glue_objc_getProperty PPC_PARAMS(id _Nonnull self, SEL _Nonnull _cmd, ptrdiff_t offset, bool atomic); -extern void glue_objc_setProperty PPC_PARAMS(id _Nonnull self, SEL _Nonnull _cmd, ptrdiff_t offset, id _Nullable value, bool atomic, signed char copy); -extern void glue_objc_getPropertyStruct PPC_PARAMS(void *_Nonnull dest, const void *_Nonnull src, ptrdiff_t size, bool atomic, bool strong); -extern void glue_objc_setPropertyStruct PPC_PARAMS(void *_Nonnull dest, const void *_Nonnull src, ptrdiff_t size, bool atomic, bool strong); -extern void glue_objc_enumerationMutation PPC_PARAMS(id _Nonnull object); -extern int glue___gnu_objc_personality PPC_PARAMS(int version, int actions, uint64_t *_Nonnull exClass, void *_Nonnull ex, void *_Nonnull ctx); -extern id _Nullable glue_objc_retain PPC_PARAMS(id _Nullable object); -extern id _Nullable glue_objc_retainBlock PPC_PARAMS(id _Nullable block); -extern id _Nullable glue_objc_retainAutorelease PPC_PARAMS(id _Nullable object); -extern void glue_objc_release PPC_PARAMS(id _Nullable object); -extern id _Nullable glue_objc_autorelease PPC_PARAMS(id _Nullable object); -extern id _Nullable glue_objc_autoreleaseReturnValue PPC_PARAMS(id _Nullable object); -extern id _Nullable glue_objc_retainAutoreleaseReturnValue PPC_PARAMS(id _Nullable object); -extern id _Nullable glue_objc_retainAutoreleasedReturnValue PPC_PARAMS(id _Nullable object); -extern id _Nullable glue_objc_storeStrong PPC_PARAMS(id _Nullable *_Nonnull object, id _Nullable value); -extern id _Nullable glue_objc_storeWeak PPC_PARAMS(id _Nullable *_Nonnull object, id _Nullable value); -extern id _Nullable glue_objc_loadWeakRetained PPC_PARAMS(id _Nullable *_Nonnull object); -extern id _Nullable glue_objc_initWeak PPC_PARAMS(id _Nullable *_Nonnull object, id _Nullable value); -extern void glue_objc_destroyWeak PPC_PARAMS(id _Nullable *_Nonnull object); -extern id _Nullable glue_objc_loadWeak PPC_PARAMS(id _Nullable *_Nonnull object); -extern void glue_objc_copyWeak PPC_PARAMS(id _Nullable *_Nonnull dest, id _Nullable *_Nonnull src); -extern void glue_objc_moveWeak PPC_PARAMS(id _Nullable *_Nonnull dest, id _Nullable *_Nonnull src); -extern SEL _Nonnull glue_sel_registerName PPC_PARAMS(const char *_Nonnull name); -extern const char *_Nonnull glue_sel_getName PPC_PARAMS(SEL _Nonnull selector); -extern bool glue_sel_isEqual PPC_PARAMS(SEL _Nonnull selector1, SEL _Nonnull selector2); -extern Class _Nonnull glue_objc_allocateClassPair PPC_PARAMS(Class _Nullable superclass, const char *_Nonnull name, size_t extraBytes); -extern void glue_objc_registerClassPair PPC_PARAMS(Class _Nonnull class); -extern unsigned int glue_objc_getClassList PPC_PARAMS(Class _Nonnull *_Nullable buffer, unsigned int count); -extern Class _Nonnull *_Nonnull glue_objc_copyClassList PPC_PARAMS(unsigned int *_Nullable length); -extern bool glue_class_isMetaClass PPC_PARAMS(Class _Nullable class); -extern const char *_Nullable glue_class_getName PPC_PARAMS(Class _Nullable class); -extern Class _Nullable glue_class_getSuperclass PPC_PARAMS(Class _Nullable class); -extern unsigned long glue_class_getInstanceSize PPC_PARAMS(Class _Nullable class); -extern bool glue_class_respondsToSelector PPC_PARAMS(Class _Nullable class, SEL _Nonnull selector); -extern bool glue_class_conformsToProtocol PPC_PARAMS(Class _Nullable class, Protocol *_Nonnull p); -extern IMP _Nullable glue_class_getMethodImplementation PPC_PARAMS(Class _Nullable class, SEL _Nonnull selector); -extern IMP _Nullable glue_class_getMethodImplementation_stret PPC_PARAMS(Class _Nullable class, SEL _Nonnull selector); -extern Method _Nullable glue_class_getInstanceMethod PPC_PARAMS(Class _Nullable class, SEL _Nonnull selector); -extern bool glue_class_addMethod PPC_PARAMS(Class _Nonnull class, SEL _Nonnull selector, IMP _Nonnull implementation, const char *_Nullable typeEncoding); -extern IMP _Nullable glue_class_replaceMethod PPC_PARAMS(Class _Nonnull class, SEL _Nonnull selector, IMP _Nonnull implementation, const char *_Nullable typeEncoding); -extern Class _Nullable glue_object_getClass PPC_PARAMS(id _Nullable object); -extern Class _Nullable glue_object_setClass PPC_PARAMS(id _Nullable object, Class _Nonnull class); -extern const char *_Nullable glue_object_getClassName PPC_PARAMS(id _Nullable object); -extern const char *_Nonnull glue_protocol_getName PPC_PARAMS(Protocol *_Nonnull protocol); -extern bool glue_protocol_isEqual PPC_PARAMS(Protocol *_Nonnull protocol1, Protocol *_Nonnull protocol2); -extern bool glue_protocol_conformsToProtocol PPC_PARAMS(Protocol *_Nonnull protocol1, Protocol *_Nonnull protocol2); -extern _Nullable objc_uncaught_exception_handler glue_objc_setUncaughtExceptionHandler PPC_PARAMS(objc_uncaught_exception_handler _Nullable handler); -extern void glue_objc_setForwardHandler PPC_PARAMS(IMP _Nullable forward, IMP _Nullable stretForward); -extern void glue_objc_setEnumerationMutationHandler PPC_PARAMS(objc_enumeration_mutation_handler _Nullable hadler); -extern id _Nullable glue_objc_constructInstance PPC_PARAMS(Class _Nullable class, void *_Nullable bytes); -extern void glue_objc_deinit(void); -extern Ivar _Nullable *_Nullable glue_class_copyIvarList PPC_PARAMS(Class _Nullable class, unsigned int *_Nullable outCount); -extern const char *_Nonnull glue_ivar_getName PPC_PARAMS(Ivar _Nonnull ivar); -extern const char *_Nonnull glue_ivar_getTypeEncoding PPC_PARAMS(Ivar _Nonnull ivar); -extern ptrdiff_t glue_ivar_getOffset PPC_PARAMS(Ivar _Nonnull ivar); -extern Method _Nullable *_Nullable glue_class_copyMethodList PPC_PARAMS(Class _Nullable class, unsigned int *_Nullable outCount); -extern SEL _Nonnull glue_method_getName PPC_PARAMS(Method _Nonnull method); -extern const char *_Nullable glue_method_getTypeEncoding PPC_PARAMS(Method _Nonnull method); -extern objc_property_t _Nullable *_Nullable glue_class_copyPropertyList PPC_PARAMS(Class _Nullable class, unsigned int *_Nullable outCount); -extern const char *_Nonnull glue_property_getName PPC_PARAMS(objc_property_t _Nonnull property); -extern char *_Nullable glue_property_copyAttributeValue PPC_PARAMS(objc_property_t _Nonnull property, const char *_Nonnull name); -extern void *_Nullable glue_objc_destructInstance PPC_PARAMS(id _Nullable object); -extern void *_Null_unspecified glue_objc_autoreleasePoolPush(void); -extern void glue_objc_autoreleasePoolPop PPC_PARAMS(void *_Null_unspecified pool); -extern id _Nullable glue__objc_rootAutorelease PPC_PARAMS(id _Nullable object); -extern struct objc_hashtable *_Nonnull glue_objc_hashtable_new PPC_PARAMS(objc_hashtable_hash_func hash, objc_hashtable_equal_func equal, uint32_t size); -extern void glue_objc_hashtable_set PPC_PARAMS(struct objc_hashtable *_Nonnull table, const void *_Nonnull key, const void *_Nonnull object); -extern void *_Nullable glue_objc_hashtable_get PPC_PARAMS(struct objc_hashtable *_Nonnull table, const void *_Nonnull key); -extern void glue_objc_hashtable_delete PPC_PARAMS(struct objc_hashtable *_Nonnull table, const void *_Nonnull key); -extern void glue_objc_hashtable_free PPC_PARAMS(struct objc_hashtable *_Nonnull table); -extern void glue_objc_setTaggedPointerSecret PPC_PARAMS(uintptr_t secret); -extern int glue_objc_registerTaggedPointerClass PPC_PARAMS(Class _Nonnull class); -extern bool glue_object_isTaggedPointer PPC_PARAMS(id _Nullable object); -extern uintptr_t glue_object_getTaggedPointerValue PPC_PARAMS(id _Nonnull object); -extern id _Nullable glue_objc_createTaggedPointer PPC_PARAMS(int class, uintptr_t value); DELETED src/runtime/amiga-glue.m Index: src/runtime/amiga-glue.m ================================================================== --- src/runtime/amiga-glue.m +++ /dev/null @@ -1,800 +0,0 @@ -/* - * Copyright (c) 2008-2022 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -/* This file is automatically generated from amiga-library.xml */ - -#include "config.h" - -#import "amiga-glue.h" - -#ifdef OF_MORPHOS -/* All __saveds functions in this file need to use the SysV ABI */ -__asm__ ( - ".section .text\n" - ".align 2\n" - "__restore_r13:\n" - " lwz %r13, 44(%r12)\n" - " blr\n" -); -#endif - -bool __saveds -glue_objc_init PPC_PARAMS(unsigned int version, struct objc_libc *libc) -{ - M68K_ARG(unsigned int, version, d0) - M68K_ARG(struct objc_libc *, libc, a0) - - return objc_init(version, libc); -} - -void __saveds -glue___objc_exec_class PPC_PARAMS(struct objc_module *_Nonnull module) -{ - M68K_ARG(struct objc_module *_Nonnull, module, a0) - - __objc_exec_class(module); -} - -IMP _Nonnull __saveds -glue_objc_msg_lookup PPC_PARAMS(id _Nullable object, SEL _Nonnull selector) -{ - M68K_ARG(id _Nullable, object, a0) - M68K_ARG(SEL _Nonnull, selector, a1) - - return objc_msg_lookup(object, selector); -} - -IMP _Nonnull __saveds -glue_objc_msg_lookup_stret PPC_PARAMS(id _Nullable object, SEL _Nonnull selector) -{ - M68K_ARG(id _Nullable, object, a0) - M68K_ARG(SEL _Nonnull, selector, a1) - - return objc_msg_lookup_stret(object, selector); -} - -IMP _Nonnull __saveds -glue_objc_msg_lookup_super PPC_PARAMS(struct objc_super *_Nonnull super, SEL _Nonnull selector) -{ - M68K_ARG(struct objc_super *_Nonnull, super, a0) - M68K_ARG(SEL _Nonnull, selector, a1) - - return objc_msg_lookup_super(super, selector); -} - -IMP _Nonnull __saveds -glue_objc_msg_lookup_super_stret PPC_PARAMS(struct objc_super *_Nonnull super, SEL _Nonnull selector) -{ - M68K_ARG(struct objc_super *_Nonnull, super, a0) - M68K_ARG(SEL _Nonnull, selector, a1) - - return objc_msg_lookup_super_stret(super, selector); -} - -Class _Nullable __saveds -glue_objc_lookUpClass PPC_PARAMS(const char *_Nonnull name) -{ - M68K_ARG(const char *_Nonnull, name, a0) - - return objc_lookUpClass(name); -} - -Class _Nullable __saveds -glue_objc_getClass PPC_PARAMS(const char *_Nonnull name) -{ - M68K_ARG(const char *_Nonnull, name, a0) - - return objc_getClass(name); -} - -Class _Nonnull __saveds -glue_objc_getRequiredClass PPC_PARAMS(const char *_Nonnull name) -{ - M68K_ARG(const char *_Nonnull, name, a0) - - return objc_getRequiredClass(name); -} - -Class _Nullable __saveds -glue_objc_lookup_class PPC_PARAMS(const char *_Nonnull name) -{ - M68K_ARG(const char *_Nonnull, name, a0) - - return objc_lookup_class(name); -} - -Class _Nonnull __saveds -glue_objc_get_class PPC_PARAMS(const char *_Nonnull name) -{ - M68K_ARG(const char *_Nonnull, name, a0) - - return objc_get_class(name); -} - -void __saveds -glue_objc_exception_throw PPC_PARAMS(id _Nonnull object) -{ - M68K_ARG(id _Nonnull, object, a0) - - objc_exception_throw(object); -} - -int __saveds -glue_objc_sync_enter PPC_PARAMS(id _Nullable object) -{ - M68K_ARG(id _Nullable, object, a0) - - return objc_sync_enter(object); -} - -int __saveds -glue_objc_sync_exit PPC_PARAMS(id _Nullable object) -{ - M68K_ARG(id _Nullable, object, a0) - - return objc_sync_exit(object); -} - -id _Nullable __saveds -glue_objc_getProperty PPC_PARAMS(id _Nonnull self, SEL _Nonnull _cmd, ptrdiff_t offset, bool atomic) -{ - M68K_ARG(id _Nonnull, self, a0) - M68K_ARG(SEL _Nonnull, _cmd, a1) - M68K_ARG(ptrdiff_t, offset, d0) - M68K_ARG(bool, atomic, d1) - - return objc_getProperty(self, _cmd, offset, atomic); -} - -void __saveds -glue_objc_setProperty PPC_PARAMS(id _Nonnull self, SEL _Nonnull _cmd, ptrdiff_t offset, id _Nullable value, bool atomic, signed char copy) -{ - M68K_ARG(id _Nonnull, self, a0) - M68K_ARG(SEL _Nonnull, _cmd, a1) - M68K_ARG(ptrdiff_t, offset, d0) - M68K_ARG(id _Nullable, value, a2) - M68K_ARG(bool, atomic, d1) - M68K_ARG(signed char, copy, d2) - - objc_setProperty(self, _cmd, offset, value, atomic, copy); -} - -void __saveds -glue_objc_getPropertyStruct PPC_PARAMS(void *_Nonnull dest, const void *_Nonnull src, ptrdiff_t size, bool atomic, bool strong) -{ - M68K_ARG(void *_Nonnull, dest, a0) - M68K_ARG(const void *_Nonnull, src, a1) - M68K_ARG(ptrdiff_t, size, d0) - M68K_ARG(bool, atomic, d1) - M68K_ARG(bool, strong, d2) - - objc_getPropertyStruct(dest, src, size, atomic, strong); -} - -void __saveds -glue_objc_setPropertyStruct PPC_PARAMS(void *_Nonnull dest, const void *_Nonnull src, ptrdiff_t size, bool atomic, bool strong) -{ - M68K_ARG(void *_Nonnull, dest, a0) - M68K_ARG(const void *_Nonnull, src, a1) - M68K_ARG(ptrdiff_t, size, d0) - M68K_ARG(bool, atomic, d1) - M68K_ARG(bool, strong, d2) - - objc_setPropertyStruct(dest, src, size, atomic, strong); -} - -void __saveds -glue_objc_enumerationMutation PPC_PARAMS(id _Nonnull object) -{ - M68K_ARG(id _Nonnull, object, a0) - - objc_enumerationMutation(object); -} - -int __saveds -glue___gnu_objc_personality PPC_PARAMS(int version, int actions, uint64_t *_Nonnull exClass, void *_Nonnull ex, void *_Nonnull ctx) -{ - M68K_ARG(int, version, d0) - M68K_ARG(int, actions, d1) - M68K_ARG(uint64_t *_Nonnull, exClass, d2) - M68K_ARG(void *_Nonnull, ex, a0) - M68K_ARG(void *_Nonnull, ctx, a1) - - return __gnu_objc_personality(version, actions, exClass, ex, ctx); -} - -id _Nullable __saveds -glue_objc_retain PPC_PARAMS(id _Nullable object) -{ - M68K_ARG(id _Nullable, object, a0) - - return objc_retain(object); -} - -id _Nullable __saveds -glue_objc_retainBlock PPC_PARAMS(id _Nullable block) -{ - M68K_ARG(id _Nullable, block, a0) - - return objc_retainBlock(block); -} - -id _Nullable __saveds -glue_objc_retainAutorelease PPC_PARAMS(id _Nullable object) -{ - M68K_ARG(id _Nullable, object, a0) - - return objc_retainAutorelease(object); -} - -void __saveds -glue_objc_release PPC_PARAMS(id _Nullable object) -{ - M68K_ARG(id _Nullable, object, a0) - - objc_release(object); -} - -id _Nullable __saveds -glue_objc_autorelease PPC_PARAMS(id _Nullable object) -{ - M68K_ARG(id _Nullable, object, a0) - - return objc_autorelease(object); -} - -id _Nullable __saveds -glue_objc_autoreleaseReturnValue PPC_PARAMS(id _Nullable object) -{ - M68K_ARG(id _Nullable, object, a0) - - return objc_autoreleaseReturnValue(object); -} - -id _Nullable __saveds -glue_objc_retainAutoreleaseReturnValue PPC_PARAMS(id _Nullable object) -{ - M68K_ARG(id _Nullable, object, a0) - - return objc_retainAutoreleaseReturnValue(object); -} - -id _Nullable __saveds -glue_objc_retainAutoreleasedReturnValue PPC_PARAMS(id _Nullable object) -{ - M68K_ARG(id _Nullable, object, a0) - - return objc_retainAutoreleasedReturnValue(object); -} - -id _Nullable __saveds -glue_objc_storeStrong PPC_PARAMS(id _Nullable *_Nonnull object, id _Nullable value) -{ - M68K_ARG(id _Nullable *_Nonnull, object, a0) - M68K_ARG(id _Nullable, value, a1) - - return objc_storeStrong(object, value); -} - -id _Nullable __saveds -glue_objc_storeWeak PPC_PARAMS(id _Nullable *_Nonnull object, id _Nullable value) -{ - M68K_ARG(id _Nullable *_Nonnull, object, a0) - M68K_ARG(id _Nullable, value, a1) - - return objc_storeWeak(object, value); -} - -id _Nullable __saveds -glue_objc_loadWeakRetained PPC_PARAMS(id _Nullable *_Nonnull object) -{ - M68K_ARG(id _Nullable *_Nonnull, object, a0) - - return objc_loadWeakRetained(object); -} - -id _Nullable __saveds -glue_objc_initWeak PPC_PARAMS(id _Nullable *_Nonnull object, id _Nullable value) -{ - M68K_ARG(id _Nullable *_Nonnull, object, a0) - M68K_ARG(id _Nullable, value, a1) - - return objc_initWeak(object, value); -} - -void __saveds -glue_objc_destroyWeak PPC_PARAMS(id _Nullable *_Nonnull object) -{ - M68K_ARG(id _Nullable *_Nonnull, object, a0) - - objc_destroyWeak(object); -} - -id _Nullable __saveds -glue_objc_loadWeak PPC_PARAMS(id _Nullable *_Nonnull object) -{ - M68K_ARG(id _Nullable *_Nonnull, object, a0) - - return objc_loadWeak(object); -} - -void __saveds -glue_objc_copyWeak PPC_PARAMS(id _Nullable *_Nonnull dest, id _Nullable *_Nonnull src) -{ - M68K_ARG(id _Nullable *_Nonnull, dest, a0) - M68K_ARG(id _Nullable *_Nonnull, src, a1) - - objc_copyWeak(dest, src); -} - -void __saveds -glue_objc_moveWeak PPC_PARAMS(id _Nullable *_Nonnull dest, id _Nullable *_Nonnull src) -{ - M68K_ARG(id _Nullable *_Nonnull, dest, a0) - M68K_ARG(id _Nullable *_Nonnull, src, a1) - - objc_moveWeak(dest, src); -} - -SEL _Nonnull __saveds -glue_sel_registerName PPC_PARAMS(const char *_Nonnull name) -{ - M68K_ARG(const char *_Nonnull, name, a0) - - return sel_registerName(name); -} - -const char *_Nonnull __saveds -glue_sel_getName PPC_PARAMS(SEL _Nonnull selector) -{ - M68K_ARG(SEL _Nonnull, selector, a0) - - return sel_getName(selector); -} - -bool __saveds -glue_sel_isEqual PPC_PARAMS(SEL _Nonnull selector1, SEL _Nonnull selector2) -{ - M68K_ARG(SEL _Nonnull, selector1, a0) - M68K_ARG(SEL _Nonnull, selector2, a1) - - return sel_isEqual(selector1, selector2); -} - -Class _Nonnull __saveds -glue_objc_allocateClassPair PPC_PARAMS(Class _Nullable superclass, const char *_Nonnull name, size_t extraBytes) -{ - M68K_ARG(Class _Nullable, superclass, a0) - M68K_ARG(const char *_Nonnull, name, a1) - M68K_ARG(size_t, extraBytes, d0) - - return objc_allocateClassPair(superclass, name, extraBytes); -} - -void __saveds -glue_objc_registerClassPair PPC_PARAMS(Class _Nonnull class) -{ - M68K_ARG(Class _Nonnull, class, a0) - - objc_registerClassPair(class); -} - -unsigned int __saveds -glue_objc_getClassList PPC_PARAMS(Class _Nonnull *_Nullable buffer, unsigned int count) -{ - M68K_ARG(Class _Nonnull *_Nullable, buffer, a0) - M68K_ARG(unsigned int, count, d0) - - return objc_getClassList(buffer, count); -} - -Class _Nonnull *_Nonnull __saveds -glue_objc_copyClassList PPC_PARAMS(unsigned int *_Nullable length) -{ - M68K_ARG(unsigned int *_Nullable, length, a0) - - return objc_copyClassList(length); -} - -bool __saveds -glue_class_isMetaClass PPC_PARAMS(Class _Nullable class) -{ - M68K_ARG(Class _Nullable, class, a0) - - return class_isMetaClass(class); -} - -const char *_Nullable __saveds -glue_class_getName PPC_PARAMS(Class _Nullable class) -{ - M68K_ARG(Class _Nullable, class, a0) - - return class_getName(class); -} - -Class _Nullable __saveds -glue_class_getSuperclass PPC_PARAMS(Class _Nullable class) -{ - M68K_ARG(Class _Nullable, class, a0) - - return class_getSuperclass(class); -} - -unsigned long __saveds -glue_class_getInstanceSize PPC_PARAMS(Class _Nullable class) -{ - M68K_ARG(Class _Nullable, class, a0) - - return class_getInstanceSize(class); -} - -bool __saveds -glue_class_respondsToSelector PPC_PARAMS(Class _Nullable class, SEL _Nonnull selector) -{ - M68K_ARG(Class _Nullable, class, a0) - M68K_ARG(SEL _Nonnull, selector, a1) - - return class_respondsToSelector(class, selector); -} - -bool __saveds -glue_class_conformsToProtocol PPC_PARAMS(Class _Nullable class, Protocol *_Nonnull p) -{ - M68K_ARG(Class _Nullable, class, a0) - M68K_ARG(Protocol *_Nonnull, p, a1) - - return class_conformsToProtocol(class, p); -} - -IMP _Nullable __saveds -glue_class_getMethodImplementation PPC_PARAMS(Class _Nullable class, SEL _Nonnull selector) -{ - M68K_ARG(Class _Nullable, class, a0) - M68K_ARG(SEL _Nonnull, selector, a1) - - return class_getMethodImplementation(class, selector); -} - -IMP _Nullable __saveds -glue_class_getMethodImplementation_stret PPC_PARAMS(Class _Nullable class, SEL _Nonnull selector) -{ - M68K_ARG(Class _Nullable, class, a0) - M68K_ARG(SEL _Nonnull, selector, a1) - - return class_getMethodImplementation_stret(class, selector); -} - -Method _Nullable __saveds -glue_class_getInstanceMethod PPC_PARAMS(Class _Nullable class, SEL _Nonnull selector) -{ - M68K_ARG(Class _Nullable, class, a0) - M68K_ARG(SEL _Nonnull, selector, a1) - - return class_getInstanceMethod(class, selector); -} - -bool __saveds -glue_class_addMethod PPC_PARAMS(Class _Nonnull class, SEL _Nonnull selector, IMP _Nonnull implementation, const char *_Nullable typeEncoding) -{ - M68K_ARG(Class _Nonnull, class, a0) - M68K_ARG(SEL _Nonnull, selector, a1) - M68K_ARG(IMP _Nonnull, implementation, a2) - M68K_ARG(const char *_Nullable, typeEncoding, a3) - - return class_addMethod(class, selector, implementation, typeEncoding); -} - -IMP _Nullable __saveds -glue_class_replaceMethod PPC_PARAMS(Class _Nonnull class, SEL _Nonnull selector, IMP _Nonnull implementation, const char *_Nullable typeEncoding) -{ - M68K_ARG(Class _Nonnull, class, a0) - M68K_ARG(SEL _Nonnull, selector, a1) - M68K_ARG(IMP _Nonnull, implementation, a2) - M68K_ARG(const char *_Nullable, typeEncoding, a3) - - return class_replaceMethod(class, selector, implementation, typeEncoding); -} - -Class _Nullable __saveds -glue_object_getClass PPC_PARAMS(id _Nullable object) -{ - M68K_ARG(id _Nullable, object, a0) - - return object_getClass(object); -} - -Class _Nullable __saveds -glue_object_setClass PPC_PARAMS(id _Nullable object, Class _Nonnull class) -{ - M68K_ARG(id _Nullable, object, a0) - M68K_ARG(Class _Nonnull, class, a1) - - return object_setClass(object, class); -} - -const char *_Nullable __saveds -glue_object_getClassName PPC_PARAMS(id _Nullable object) -{ - M68K_ARG(id _Nullable, object, a0) - - return object_getClassName(object); -} - -const char *_Nonnull __saveds -glue_protocol_getName PPC_PARAMS(Protocol *_Nonnull protocol) -{ - M68K_ARG(Protocol *_Nonnull, protocol, a0) - - return protocol_getName(protocol); -} - -bool __saveds -glue_protocol_isEqual PPC_PARAMS(Protocol *_Nonnull protocol1, Protocol *_Nonnull protocol2) -{ - M68K_ARG(Protocol *_Nonnull, protocol1, a0) - M68K_ARG(Protocol *_Nonnull, protocol2, a1) - - return protocol_isEqual(protocol1, protocol2); -} - -bool __saveds -glue_protocol_conformsToProtocol PPC_PARAMS(Protocol *_Nonnull protocol1, Protocol *_Nonnull protocol2) -{ - M68K_ARG(Protocol *_Nonnull, protocol1, a0) - M68K_ARG(Protocol *_Nonnull, protocol2, a1) - - return protocol_conformsToProtocol(protocol1, protocol2); -} - -_Nullable objc_uncaught_exception_handler __saveds -glue_objc_setUncaughtExceptionHandler PPC_PARAMS(objc_uncaught_exception_handler _Nullable handler) -{ - M68K_ARG(objc_uncaught_exception_handler _Nullable, handler, a0) - - return objc_setUncaughtExceptionHandler(handler); -} - -void __saveds -glue_objc_setForwardHandler PPC_PARAMS(IMP _Nullable forward, IMP _Nullable stretForward) -{ - M68K_ARG(IMP _Nullable, forward, a0) - M68K_ARG(IMP _Nullable, stretForward, a1) - - objc_setForwardHandler(forward, stretForward); -} - -void __saveds -glue_objc_setEnumerationMutationHandler PPC_PARAMS(objc_enumeration_mutation_handler _Nullable hadler) -{ - M68K_ARG(objc_enumeration_mutation_handler _Nullable, hadler, a0) - - objc_setEnumerationMutationHandler(hadler); -} - -id _Nullable __saveds -glue_objc_constructInstance PPC_PARAMS(Class _Nullable class, void *_Nullable bytes) -{ - M68K_ARG(Class _Nullable, class, a0) - M68K_ARG(void *_Nullable, bytes, a1) - - return objc_constructInstance(class, bytes); -} - -void __saveds -glue_objc_deinit(void) -{ - objc_deinit(); -} - -Ivar _Nullable *_Nullable __saveds -glue_class_copyIvarList PPC_PARAMS(Class _Nullable class, unsigned int *_Nullable outCount) -{ - M68K_ARG(Class _Nullable, class, a0) - M68K_ARG(unsigned int *_Nullable, outCount, a1) - - return class_copyIvarList(class, outCount); -} - -const char *_Nonnull __saveds -glue_ivar_getName PPC_PARAMS(Ivar _Nonnull ivar) -{ - M68K_ARG(Ivar _Nonnull, ivar, a0) - - return ivar_getName(ivar); -} - -const char *_Nonnull __saveds -glue_ivar_getTypeEncoding PPC_PARAMS(Ivar _Nonnull ivar) -{ - M68K_ARG(Ivar _Nonnull, ivar, a0) - - return ivar_getTypeEncoding(ivar); -} - -ptrdiff_t __saveds -glue_ivar_getOffset PPC_PARAMS(Ivar _Nonnull ivar) -{ - M68K_ARG(Ivar _Nonnull, ivar, a0) - - return ivar_getOffset(ivar); -} - -Method _Nullable *_Nullable __saveds -glue_class_copyMethodList PPC_PARAMS(Class _Nullable class, unsigned int *_Nullable outCount) -{ - M68K_ARG(Class _Nullable, class, a0) - M68K_ARG(unsigned int *_Nullable, outCount, a1) - - return class_copyMethodList(class, outCount); -} - -SEL _Nonnull __saveds -glue_method_getName PPC_PARAMS(Method _Nonnull method) -{ - M68K_ARG(Method _Nonnull, method, a0) - - return method_getName(method); -} - -const char *_Nullable __saveds -glue_method_getTypeEncoding PPC_PARAMS(Method _Nonnull method) -{ - M68K_ARG(Method _Nonnull, method, a0) - - return method_getTypeEncoding(method); -} - -objc_property_t _Nullable *_Nullable __saveds -glue_class_copyPropertyList PPC_PARAMS(Class _Nullable class, unsigned int *_Nullable outCount) -{ - M68K_ARG(Class _Nullable, class, a0) - M68K_ARG(unsigned int *_Nullable, outCount, a1) - - return class_copyPropertyList(class, outCount); -} - -const char *_Nonnull __saveds -glue_property_getName PPC_PARAMS(objc_property_t _Nonnull property) -{ - M68K_ARG(objc_property_t _Nonnull, property, a0) - - return property_getName(property); -} - -char *_Nullable __saveds -glue_property_copyAttributeValue PPC_PARAMS(objc_property_t _Nonnull property, const char *_Nonnull name) -{ - M68K_ARG(objc_property_t _Nonnull, property, a0) - M68K_ARG(const char *_Nonnull, name, a1) - - return property_copyAttributeValue(property, name); -} - -void *_Nullable __saveds -glue_objc_destructInstance PPC_PARAMS(id _Nullable object) -{ - M68K_ARG(id _Nullable, object, a0) - - return objc_destructInstance(object); -} - -void *_Null_unspecified __saveds -glue_objc_autoreleasePoolPush(void) -{ - return objc_autoreleasePoolPush(); -} - -void __saveds -glue_objc_autoreleasePoolPop PPC_PARAMS(void *_Null_unspecified pool) -{ - M68K_ARG(void *_Null_unspecified, pool, a0) - - objc_autoreleasePoolPop(pool); -} - -id _Nullable __saveds -glue__objc_rootAutorelease PPC_PARAMS(id _Nullable object) -{ - M68K_ARG(id _Nullable, object, a0) - - return _objc_rootAutorelease(object); -} - -struct objc_hashtable *_Nonnull __saveds -glue_objc_hashtable_new PPC_PARAMS(objc_hashtable_hash_func hash, objc_hashtable_equal_func equal, uint32_t size) -{ - M68K_ARG(objc_hashtable_hash_func, hash, a0) - M68K_ARG(objc_hashtable_equal_func, equal, a1) - M68K_ARG(uint32_t, size, d0) - - return objc_hashtable_new(hash, equal, size); -} - -void __saveds -glue_objc_hashtable_set PPC_PARAMS(struct objc_hashtable *_Nonnull table, const void *_Nonnull key, const void *_Nonnull object) -{ - M68K_ARG(struct objc_hashtable *_Nonnull, table, a0) - M68K_ARG(const void *_Nonnull, key, a1) - M68K_ARG(const void *_Nonnull, object, a2) - - objc_hashtable_set(table, key, object); -} - -void *_Nullable __saveds -glue_objc_hashtable_get PPC_PARAMS(struct objc_hashtable *_Nonnull table, const void *_Nonnull key) -{ - M68K_ARG(struct objc_hashtable *_Nonnull, table, a0) - M68K_ARG(const void *_Nonnull, key, a1) - - return objc_hashtable_get(table, key); -} - -void __saveds -glue_objc_hashtable_delete PPC_PARAMS(struct objc_hashtable *_Nonnull table, const void *_Nonnull key) -{ - M68K_ARG(struct objc_hashtable *_Nonnull, table, a0) - M68K_ARG(const void *_Nonnull, key, a1) - - objc_hashtable_delete(table, key); -} - -void __saveds -glue_objc_hashtable_free PPC_PARAMS(struct objc_hashtable *_Nonnull table) -{ - M68K_ARG(struct objc_hashtable *_Nonnull, table, a0) - - objc_hashtable_free(table); -} - -void __saveds -glue_objc_setTaggedPointerSecret PPC_PARAMS(uintptr_t secret) -{ - M68K_ARG(uintptr_t, secret, d0) - - objc_setTaggedPointerSecret(secret); -} - -int __saveds -glue_objc_registerTaggedPointerClass PPC_PARAMS(Class _Nonnull class) -{ - M68K_ARG(Class _Nonnull, class, a0) - - return objc_registerTaggedPointerClass(class); -} - -bool __saveds -glue_object_isTaggedPointer PPC_PARAMS(id _Nullable object) -{ - M68K_ARG(id _Nullable, object, a0) - - return object_isTaggedPointer(object); -} - -uintptr_t __saveds -glue_object_getTaggedPointerValue PPC_PARAMS(id _Nonnull object) -{ - M68K_ARG(id _Nonnull, object, a0) - - return object_getTaggedPointerValue(object); -} - -id _Nullable __saveds -glue_objc_createTaggedPointer PPC_PARAMS(int class, uintptr_t value) -{ - M68K_ARG(int, class, d0) - M68K_ARG(uintptr_t, value, d1) - - return objc_createTaggedPointer(class, value); -} DELETED src/runtime/amiga-library.m Index: src/runtime/amiga-library.m ================================================================== --- src/runtime/amiga-library.m +++ /dev/null @@ -1,588 +0,0 @@ -/* - * Copyright (c) 2008-2022 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#include "config.h" - -#import "ObjFWRT.h" -#import "private.h" - -#import "amiga-glue.h" - -#include -#include -#include -#include - -#define CONCAT_VERSION2(major, minor) #major "." #minor -#define CONCAT_VERSION(major, minor) CONCAT_VERSION2(major, minor) -#define VERSION_STRING CONCAT_VERSION(OBJFWRT_LIB_MAJOR, OBJFWRT_LIB_MINOR) - -#if defined(OF_AMIGAOS_M68K) -# define DATA_OFFSET 0x7FFE -#elif defined(OF_MORPHOS) -# define DATA_OFFSET 0x8000 -#endif - -#ifdef OF_AMIGAOS_M68K -# define OBJC_M68K_REG(reg) __asm__(#reg) -#else -# define OBJC_M68K_REG(reg) -#endif - -/* This always needs to be the first thing in the file. */ -int -_start(void) -{ - return -1; -} - -#ifdef OF_AMIGAOS_M68K -void -__init_eh(void) -{ -} -#endif - -struct ObjFWRTBase { - struct Library library; - void *segList; - struct ObjFWRTBase *parent; - char *dataSeg; - bool initialized; -}; - -#ifdef OF_AMIGAOS_M68K -extern uintptr_t __CTOR_LIST__[]; -extern const void *_EH_FRAME_BEGINS__; -extern void *_EH_FRAME_OBJECTS__; -#endif - -#ifdef OF_MORPHOS -const ULONG __abox__ = 1; -#endif -struct ExecBase *SysBase; -struct objc_libc libc; - -#if defined(OF_AMIGAOS_M68K) -__asm__ ( - ".text\n" - ".globl ___restore_a4\n" - ".align 1\n" - "___restore_a4:\n" - " movea.l 42(a6), a4\n" - " rts" -); -#elif defined(OF_MORPHOS) -/* All __saveds functions in this file need to use the M68K ABI */ -__asm__ ( - ".section .text\n" - ".align 2\n" - "__restore_r13:\n" - " lwz %r13, 56(%r2)\n" - " lwz %r13, 44(%r13)\n" - " blr\n" -); -#endif - -static OF_INLINE char * -getDataSeg(void) -{ - char *dataSeg; - -#if defined(OF_AMIGAOS_M68K) - __asm__ ( - "move.l #___a4_init, %0" - : "=r"(dataSeg) - ); -#elif defined(OF_MORPHOS) - __asm__ ( - "lis %0, __r13_init@ha\n\t" - "la %0, __r13_init@l(%0)" - : "=r"(dataSeg) - ); -#endif - - return dataSeg; -} - -static OF_INLINE size_t -getDataSize(void) -{ - size_t dataSize; - -#if defined(OF_AMIGAOS_M68K) - __asm__ ( - "move.l #___data_size, %0\n\t" - "add.l #___bss_size, %0" - : "=r"(dataSize) - ); -#elif defined(OF_MORPHOS) - __asm__ ( - "lis %0, __sdata_size@ha\n\t" - "la %0, __sdata_size@l(%0)\n\t" - "lis %%r9, __sbss_size@ha\n\t" - "la %%r9, __sbss_size@l(%%r9)\n\t" - "add %0, %0, %%r9" - : "=r"(dataSize) - :: "r9" - ); -#endif - - return dataSize; -} - -static OF_INLINE size_t * -getDataDataRelocs(void) -{ - size_t *dataDataRelocs; - -#if defined(OF_AMIGAOS_M68K) - __asm__ ( - "move.l #___datadata_relocs, %0" - : "=r"(dataDataRelocs) - ); -#elif defined(OF_MORPHOS) - __asm__ ( - "lis %0, __datadata_relocs@ha\n\t" - "la %0, __datadata_relocs@l(%0)\n\t" - : "=r"(dataDataRelocs) - ); -#endif - - return dataDataRelocs; -} - -static struct Library * -lib_init(struct ObjFWRTBase *base OBJC_M68K_REG(d0), - void *segList OBJC_M68K_REG(a0), struct ExecBase *sysBase OBJC_M68K_REG(a6)) -{ -#if defined(OF_AMIGAOS_M68K) - __asm__ __volatile__ ( - "move.l a6, _SysBase" - :: "a"(sysBase) - ); -#elif defined(OF_MORPHOS) - __asm__ __volatile__ ( - "lis %%r9, SysBase@ha\n\t" - "stw %0, SysBase@l(%%r9)" - :: "r"(sysBase) : "r9" - ); -#endif - - base->segList = segList; - base->parent = NULL; - base->dataSeg = getDataSeg(); - - return &base->library; -} - -struct Library *__saveds -lib_open(void) -{ - OBJC_M68K_ARG(struct ObjFWRTBase *, base, a6) - - struct ObjFWRTBase *child; - size_t dataSize, *dataDataRelocs; - ptrdiff_t displacement; - - if (base->parent != NULL) - return NULL; - - base->library.lib_OpenCnt++; - base->library.lib_Flags &= ~LIBF_DELEXP; - - /* - * We cannot use malloc here, as that depends on the libc passed from - * the application. - */ - if ((child = AllocMem(base->library.lib_NegSize + - base->library.lib_PosSize, MEMF_ANY)) == NULL) { - base->library.lib_OpenCnt--; - return NULL; - } - - memcpy(child, (char *)base - base->library.lib_NegSize, - base->library.lib_NegSize + base->library.lib_PosSize); - - child = (struct ObjFWRTBase *) - ((char *)child + base->library.lib_NegSize); - child->library.lib_OpenCnt = 1; - child->parent = base; - - dataSize = getDataSize(); - - if ((child->dataSeg = AllocMem(dataSize, MEMF_ANY)) == NULL) { - FreeMem((char *)child - child->library.lib_NegSize, - child->library.lib_NegSize + child->library.lib_PosSize); - base->library.lib_OpenCnt--; - return NULL; - } - - memcpy(child->dataSeg, base->dataSeg - DATA_OFFSET, dataSize); - - dataDataRelocs = getDataDataRelocs(); - displacement = child->dataSeg - (base->dataSeg - DATA_OFFSET); - - for (size_t i = 1; i <= dataDataRelocs[0]; i++) - *(long *)(child->dataSeg + dataDataRelocs[i]) += displacement; - - child->dataSeg += DATA_OFFSET; - - return &child->library; -} - -static void * -expunge(struct ObjFWRTBase *base, struct ExecBase *sysBase) -{ -#define SysBase sysBase - void *segList; - - if (base->parent != NULL) { - base->parent->library.lib_Flags |= LIBF_DELEXP; - return 0; - } - - if (base->library.lib_OpenCnt > 0) { - base->library.lib_Flags |= LIBF_DELEXP; - return 0; - } - - segList = base->segList; - - Remove(&base->library.lib_Node); - FreeMem((char *)base - base->library.lib_NegSize, - base->library.lib_NegSize + base->library.lib_PosSize); - - return segList; -#undef SysBase -} - -static void *__saveds -lib_expunge(void) -{ - OBJC_M68K_ARG(struct ObjFWRTBase *, base, a6) - - return expunge(base, SysBase); -} - -static void *__saveds -lib_close(void) -{ - /* - * SysBase becomes invalid during this function, so we store it in - * sysBase and add a define to make the inlines use the right one. - */ - struct ExecBase *sysBase = SysBase; -#define SysBase sysBase - - OBJC_M68K_ARG(struct ObjFWRTBase *, base, a6) - - if (base->parent != NULL) { - struct ObjFWRTBase *parent; - -#ifdef OF_AMIGAOS_M68K - if (base->initialized) - for (void *const *frame = _EH_FRAME_BEGINS__; - *frame != NULL;) - libc.__deregister_frame_info(*frame++); -#endif - - parent = base->parent; - - FreeMem(base->dataSeg - DATA_OFFSET, getDataSize()); - FreeMem((char *)base - base->library.lib_NegSize, - base->library.lib_NegSize + base->library.lib_PosSize); - - base = parent; - } - - if (--base->library.lib_OpenCnt == 0 && - (base->library.lib_Flags & LIBF_DELEXP)) - return expunge(base, sysBase); - - return NULL; -#undef SysBase -} - -static void * -lib_null(void) -{ - return NULL; -} - -bool -objc_init(unsigned int version, struct objc_libc *libc_) -{ -#ifdef OF_AMIGAOS_M68K - OBJC_M68K_ARG(struct ObjFWRTBase *, base, a6) -#else - register struct ObjFWRTBase *r12 __asm__("r12"); - struct ObjFWRTBase *base = r12; -#endif -#ifdef OF_MORPHOS - void *frame; -#endif - uintptr_t *iter, *iter0; - - if (version > 1) - return false; - - memcpy(&libc, libc_, sizeof(libc)); - -#ifdef OF_AMIGAOS_M68K - for (void *const *frame = _EH_FRAME_OBJECTS__, - **object = _EH_FRAME_OBJECTS__; *frame != NULL;) - libc.__register_frame_info(*frame++, *object++); - - iter0 = &__CTOR_LIST__[1]; -#elif defined(OF_MORPHOS) - __asm__ ( - "lis %0, __EH_FRAME_BEGIN__@ha\n\t" - "la %0, __EH_FRAME_BEGIN__@l(%0)\n\t" - "lis %1, __CTOR_LIST__@ha\n\t" - "la %1, __CTOR_LIST__@l(%1)\n\t" - : "=r"(frame), "=r"(iter0) - ); - - libc.__register_frame(frame); -#endif - - for (iter = iter0; *iter != 0; iter++); - - while (iter > iter0) { - void (*ctor)(void) = (void (*)(void))*--iter; - ctor(); - } - - base->initialized = true; - - return true; -} - -void * -malloc(size_t size) -{ - return libc.malloc(size); -} - -void * -calloc(size_t count, size_t size) -{ - return libc.calloc(count, size); -} - -void * -realloc(void *ptr, size_t size) -{ - return libc.realloc(ptr, size); -} - -void -free(void *ptr) -{ - libc.free(ptr); -} - -#ifdef HAVE_SJLJ_EXCEPTIONS -int -_Unwind_SjLj_RaiseException(void *ex) -{ - return libc._Unwind_SjLj_RaiseException(ex); -} -#else -int -_Unwind_RaiseException(void *ex) -{ - return libc._Unwind_RaiseException(ex); -} -#endif - -void -_Unwind_DeleteException(void *ex) -{ - libc._Unwind_DeleteException(ex); -} - -void * -_Unwind_GetLanguageSpecificData(void *ctx) -{ - return libc._Unwind_GetLanguageSpecificData(ctx); -} - -uintptr_t -_Unwind_GetRegionStart(void *ctx) -{ - return libc._Unwind_GetRegionStart(ctx); -} - -uintptr_t -_Unwind_GetDataRelBase(void *ctx) -{ - return libc._Unwind_GetDataRelBase(ctx); -} - -uintptr_t -_Unwind_GetTextRelBase(void *ctx) -{ - return libc._Unwind_GetTextRelBase(ctx); -} - -uintptr_t -_Unwind_GetIP(void *ctx) -{ - return libc._Unwind_GetIP(ctx); -} - -uintptr_t -_Unwind_GetGR(void *ctx, int gr) -{ - return libc._Unwind_GetGR(ctx, gr); -} - -void -_Unwind_SetIP(void *ctx, uintptr_t ip) -{ - libc._Unwind_SetIP(ctx, ip); -} - -void -_Unwind_SetGR(void *ctx, int gr, uintptr_t value) -{ - libc._Unwind_SetGR(ctx, gr, value); -} - -#ifdef HAVE_SJLJ_EXCEPTIONS -void -_Unwind_SjLj_Resume(void *ex) -{ - libc._Unwind_SjLj_Resume(ex); -} -#else -void -_Unwind_Resume(void *ex) -{ - libc._Unwind_Resume(ex); -} -#endif - -#ifdef OF_AMIGAOS_M68K -int -snprintf(char *restrict str, size_t size, const char *restrict fmt, ...) -{ - va_list args; - int ret; - - va_start(args, fmt); - ret = vsnprintf(str, size, fmt, args); - va_end(args); - - return ret; -} - -int -vsnprintf(char *restrict str, size_t size, const char *restrict fmt, - va_list args) -{ - return libc.vsnprintf(str, size, fmt, args); -} -#endif - -int -atexit(void (*function)(void)) -{ - return libc.atexit(function); -} - -void -exit(int status) -{ - libc.exit(status); - - OF_UNREACHABLE -} - -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wpedantic" -static CONST_APTR functionTable[] = { -#ifdef OF_MORPHOS - (CONST_APTR)FUNCARRAY_BEGIN, - (CONST_APTR)FUNCARRAY_32BIT_NATIVE, -#endif - (CONST_APTR)lib_open, - (CONST_APTR)lib_close, - (CONST_APTR)lib_expunge, - (CONST_APTR)lib_null, -#ifdef OF_MORPHOS - (CONST_APTR)-1, - (CONST_APTR)FUNCARRAY_32BIT_SYSTEMV, -#endif -#include "amiga-funcarray.inc" - (CONST_APTR)-1, -#ifdef OF_MORPHOS - (CONST_APTR)FUNCARRAY_END -#endif -}; -#pragma GCC diagnostic pop - -static struct { - ULONG dataSize; - CONST_APTR *functionTable; - ULONG *dataTable; - struct Library *(*initFunc)( - struct ObjFWRTBase *base OBJC_M68K_REG(d0), - void *segList OBJC_M68K_REG(a0), - struct ExecBase *execBase OBJC_M68K_REG(a6)); -} init_table = { - sizeof(struct ObjFWRTBase), - functionTable, - NULL, - lib_init -}; - -struct Resident resident = { - .rt_MatchWord = RTC_MATCHWORD, - .rt_MatchTag = &resident, - .rt_EndSkip = &resident + 1, - .rt_Flags = RTF_AUTOINIT -#ifdef OF_MORPHOS - | RTF_PPC | RTF_EXTENDED -#endif - , - .rt_Version = OBJFWRT_LIB_MAJOR, - .rt_Type = NT_LIBRARY, - .rt_Pri = 0, - .rt_Name = (char *)OBJFWRT_AMIGA_LIB, - .rt_IdString = (char *)"ObjFWRT " VERSION_STRING - " \xA9 2008-2022 Jonathan Schleifer", - .rt_Init = &init_table, -#ifdef OF_MORPHOS - .rt_Revision = OBJFWRT_LIB_MINOR, - .rt_Tags = NULL, -#endif -}; - -#ifdef OF_MORPHOS -__asm__ ( - ".section .eh_frame, \"aw\"\n" - ".globl __EH_FRAME_BEGIN__\n" - ".type __EH_FRAME_BEGIN__, @object\n" - "__EH_FRAME_BEGIN__:\n" - ".section .ctors, \"aw\"\n" - ".globl __CTOR_LIST__\n" - ".type __CTOR_LIST__, @object\n" - "__CTOR_LIST__:\n" - ".section .text" -); -#endif DELETED src/runtime/amiga-library.xml Index: src/runtime/amiga-library.xml ================================================================== --- src/runtime/amiga-library.xml +++ /dev/null @@ -1,345 +0,0 @@ - - ObjFWRT.h - private.h - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Index: src/runtime/arc.m ================================================================== --- src/runtime/arc.m +++ src/runtime/arc.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -186,19 +186,17 @@ id objc_loadWeakRetained(id *object) { id value = nil; - struct WeakRef *ref; #ifdef OF_HAVE_THREADS if (OFSpinlockLock(&spinlock) != 0) OBJC_ERROR("Failed to lock spinlock!"); #endif - if (*object != nil && - (ref = objc_hashtable_get(hashtable, *object)) != NULL) + if (*object != nil && objc_hashtable_get(hashtable, *object) != NULL) value = *object; #ifdef OF_HAVE_THREADS if (OFSpinlockUnlock(&spinlock) != 0) OBJC_ERROR("Failed to unlock spinlock!"); Index: src/runtime/autorelease.m ================================================================== --- src/runtime/autorelease.m +++ src/runtime/autorelease.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,18 +56,18 @@ objc_globalMutex_lock(); if (classes == NULL) { objc_globalMutex_unlock(); - return NO; + return false; } objc_hashtable_set(classes, name, (Class)((uintptr_t)class | 1)); objc_globalMutex_unlock(); - return YES; + return true; } static void registerSelectors(Class class) { @@ -90,25 +90,25 @@ /* * Fast path * * Instead of looking up the string in a dictionary, which needs * locking, we use a sparse array to look up the pointer. If - * objc_classname_to_class() gets called a lot, it is most likely that + * objc_classnameToClass() gets called a lot, it is most likely that * the GCC ABI is used, which always calls into objc_lookup_class(), or * that it is used in a loop by the user. In both cases, it is very * likely that the same string pointer is passed again and again. * - * This is not used before objc_classname_to_class() has been called a + * This is not used before objc_classnameToClass() has been called a * certain amount of times, so that no memory is wasted if it is only * used rarely, for example if the ObjFW ABI is used and the user does * not call it in a loop. * * Runtime internal usage does not use the fast path and does not count - * as a call into objc_classname_to_class(). The reason for this is - * that if the runtime calls into objc_classname_to_class(), it already - * has the lock and thus the performance gain would be small, but it - * would waste memory. + * as a call into objc_classnameToClass(). The reason for this is that + * if the runtime calls into objc_classnameToClass(), it already has + * the lock and thus the performance gain would be small, but it would + * waste memory. */ if (cache && fastPath != NULL) { class = objc_sparsearray_get(fastPath, (uintptr_t)name); if (class != Nil) @@ -778,11 +778,12 @@ objc_updateDTable(class); } Method -#if defined(__clang__) && __clang_major__ == 3 && __clang_minor__ <= 7 +#if defined(__clang__) && __has_attribute(__optnone__) && \ + __clang_major__ == 3 && __clang_minor__ <= 7 /* Work around an ICE in Clang 3.7.0 on Windows/x86 */ __attribute__((__optnone__)) #endif class_getInstanceMethod(Class class, SEL selector) { Index: src/runtime/dtable.m ================================================================== --- src/runtime/dtable.m +++ src/runtime/dtable.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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 @@ #import "ObjFWRT.h" #import "private.h" #import "macros.h" #ifdef OF_HAVE_THREADS -# include "OFPlainMutex.h" +# import "OFPlainMutex.h" #endif #ifdef HAVE_SEH_EXCEPTIONS # include #endif Index: src/runtime/hashtable.m ================================================================== --- src/runtime/hashtable.m +++ src/runtime/hashtable.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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/runtime/linklib/Makefile Index: src/runtime/linklib/Makefile ================================================================== --- src/runtime/linklib/Makefile +++ /dev/null @@ -1,13 +0,0 @@ -include ../../../extra.mk - -STATIC_LIB = libobjfwrt.library.a -SRCS = init.m \ - linklib.m - -include ../../../buildsys.mk - -CPPFLAGS += -I.. -I../.. -I../../.. \ - -DOBJC_COMPILING_AMIGA_LINKLIB \ - -DOBJFWRT_AMIGA_LIB=\"${OBJFWRT_AMIGA_LIB}\" \ - -DOBJFWRT_LIB_MINOR=${OBJFWRT_LIB_MINOR} -LD = ${OBJC} DELETED src/runtime/linklib/init.m Index: src/runtime/linklib/init.m ================================================================== --- src/runtime/linklib/init.m +++ /dev/null @@ -1,188 +0,0 @@ -/* - * Copyright (c) 2008-2022 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#include "config.h" - -#import "ObjFWRT.h" -#import "private.h" -#import "macros.h" - -#include -#include - -struct ObjFWRTBase; - -#include -#include - -#if defined(OF_AMIGAOS_M68K) -# include -#elif defined(OF_MORPHOS) -# include -#endif - -#ifdef HAVE_SJLJ_EXCEPTIONS -extern int _Unwind_SjLj_RaiseException(void *); -#else -extern int _Unwind_RaiseException(void *); -#endif -extern void _Unwind_DeleteException(void *); -extern void *_Unwind_GetLanguageSpecificData(void *); -extern uintptr_t _Unwind_GetRegionStart(void *); -extern uintptr_t _Unwind_GetDataRelBase(void *); -extern uintptr_t _Unwind_GetTextRelBase(void *); -extern uintptr_t _Unwind_GetIP(void *); -extern uintptr_t _Unwind_GetGR(void *, int); -extern void _Unwind_SetIP(void *, uintptr_t); -extern void _Unwind_SetGR(void *, int, uintptr_t); -#ifdef HAVE_SJLJ_EXCEPTIONS -extern void _Unwind_SjLj_Resume(void *); -#else -extern void _Unwind_Resume(void *); -#endif -#ifdef OF_AMIGAOS_M68K -extern void __register_frame_info(const void *, void *); -extern void *__deregister_frame_info(const void *); -#endif -#ifdef OF_MORPHOS -extern void __register_frame(void *); -extern void __deregister_frame(void *); -#endif - -struct Library *ObjFWRTBase; -void *__objc_class_name_Protocol; - -extern bool objc_init(unsigned int version, struct objc_libc *libc); - -static void -error(const char *string, ULONG arg) -{ - struct Library *IntuitionBase = OpenLibrary("intuition.library", 0); - - if (IntuitionBase != NULL) { - struct EasyStruct easy = { - .es_StructSize = sizeof(easy), - .es_Flags = 0, - .es_Title = (void *)NULL, - .es_TextFormat = (void *)string, - (void *)"OK" - }; - - EasyRequest(NULL, &easy, NULL, arg); - - CloseLibrary(IntuitionBase); - } - - exit(EXIT_FAILURE); -} - -static void __attribute__((__used__)) -ctor(void) -{ - static bool initialized = false; - struct objc_libc libc = { - .malloc = malloc, - .calloc = calloc, - .realloc = realloc, - .free = free, -#ifdef HAVE_SJLJ_EXCEPTIONS - ._Unwind_SjLj_RaiseException = _Unwind_SjLj_RaiseException, -#else - ._Unwind_RaiseException = _Unwind_RaiseException, -#endif - ._Unwind_DeleteException = _Unwind_DeleteException, - ._Unwind_GetLanguageSpecificData = - _Unwind_GetLanguageSpecificData, - ._Unwind_GetRegionStart = _Unwind_GetRegionStart, - ._Unwind_GetDataRelBase = _Unwind_GetDataRelBase, - ._Unwind_GetTextRelBase = _Unwind_GetTextRelBase, - ._Unwind_GetIP = _Unwind_GetIP, - ._Unwind_GetGR = _Unwind_GetGR, - ._Unwind_SetIP = _Unwind_SetIP, - ._Unwind_SetGR = _Unwind_SetGR, -#ifdef HAVE_SJLJ_EXCEPTIONS - ._Unwind_SjLj_Resume = _Unwind_SjLj_Resume, -#else - ._Unwind_Resume = _Unwind_Resume, -#endif -#ifdef OF_AMIGAOS_M68K - .__register_frame_info = __register_frame_info, - .__deregister_frame_info = __deregister_frame_info, -#endif -#ifdef OF_MORPHOS - .__register_frame = __register_frame, - .__deregister_frame = __deregister_frame, -#endif -#ifdef OF_AMIGAOS_M68K - .vsnprintf = vsnprintf, -#endif - .atexit = atexit, - .exit = exit, - }; - - if (initialized) - return; - - if ((ObjFWRTBase = OpenLibrary(OBJFWRT_AMIGA_LIB, - OBJFWRT_LIB_MINOR)) == NULL) - error("Failed to open " OBJFWRT_AMIGA_LIB " version %lu!", - OBJFWRT_LIB_MINOR); - - if (!objc_init(1, &libc)) - error("Failed to initialize " OBJFWRT_AMIGA_LIB "!", 0); - - initialized = true; -} - -static void __attribute__((__used__)) -dtor(void) -{ - CloseLibrary(ObjFWRTBase); -} - -#if defined(OF_AMIGAOS_M68K) -ADD2INIT(ctor, -5) -ADD2EXIT(dtor, -5) -#elif defined(OF_MORPHOS) -CONSTRUCTOR_P(ObjFWRT, 4000) -{ - ctor(); - - return 0; -} - -DESTRUCTOR_P(ObjFWRT, 0) -{ - dtor(); -} -#endif - -extern int __gnu_objc_personality(int version, int actions, uint64_t *exClass, - void *ex, void *ctx); - -int -#ifdef HAVE_SJLJ_EXCEPTIONS -__gnu_objc_personality_sj0( -#else -__gnu_objc_personality_v0( -#endif - int version, int actions, uint64_t exClass, void *ex, void *ctx) -{ -#ifdef OF_AMIGAOS_M68K - return __gnu_objc_personality(version, actions, &exClass, ex, ctx); -#else - return __gnu_objc_personality(version, actions, &exClass, ex, ctx); -#endif -} DELETED src/runtime/linklib/linklib.m Index: src/runtime/linklib/linklib.m ================================================================== --- src/runtime/linklib/linklib.m +++ /dev/null @@ -1,1538 +0,0 @@ -/* - * Copyright (c) 2008-2022 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -/* This file is automatically generated from amiga-library.xml */ - -#include "config.h" - -#import "ObjFWRT.h" -#import "private.h" - -extern struct Library *ObjFWRTBase; - -bool -objc_init(unsigned int version, struct objc_libc *libc) -{ -#if defined(OF_AMIGAOS_M68K) - register struct Library *a6 __asm__("a6") = ObjFWRTBase; - (void)a6; - return ((bool (*)(unsigned int __asm__("d0"), struct objc_libc *__asm__("a0")))(((uintptr_t)ObjFWRTBase) - 30))(version, libc); -#elif defined(OF_MORPHOS) - __asm__ __volatile__ ( - "mr %%r12, %0" - :: "r"(ObjFWRTBase) : "r12" - ); - - return __extension__ ((bool (*)(unsigned int, struct objc_libc *))*(void **)(((uintptr_t)ObjFWRTBase) - 28))(version, libc); -#endif -} - -void -__objc_exec_class(struct objc_module *_Nonnull module) -{ -#if defined(OF_AMIGAOS_M68K) - register struct Library *a6 __asm__("a6") = ObjFWRTBase; - (void)a6; - ((void (*)(struct objc_module *_Nonnull __asm__("a0")))(((uintptr_t)ObjFWRTBase) - 36))(module); -#elif defined(OF_MORPHOS) - __asm__ __volatile__ ( - "mr %%r12, %0" - :: "r"(ObjFWRTBase) : "r12" - ); - - __extension__ ((void (*)(struct objc_module *_Nonnull))*(void **)(((uintptr_t)ObjFWRTBase) - 34))(module); -#endif -} - -IMP _Nonnull -objc_msg_lookup(id _Nullable object, SEL _Nonnull selector) -{ -#if defined(OF_AMIGAOS_M68K) - register struct Library *a6 __asm__("a6") = ObjFWRTBase; - (void)a6; - return ((IMP _Nonnull (*)(id _Nullable __asm__("a0"), SEL _Nonnull __asm__("a1")))(((uintptr_t)ObjFWRTBase) - 42))(object, selector); -#elif defined(OF_MORPHOS) - __asm__ __volatile__ ( - "mr %%r12, %0" - :: "r"(ObjFWRTBase) : "r12" - ); - - return __extension__ ((IMP _Nonnull (*)(id _Nullable, SEL _Nonnull))*(void **)(((uintptr_t)ObjFWRTBase) - 40))(object, selector); -#endif -} - -IMP _Nonnull -objc_msg_lookup_stret(id _Nullable object, SEL _Nonnull selector) -{ -#if defined(OF_AMIGAOS_M68K) - register struct Library *a6 __asm__("a6") = ObjFWRTBase; - (void)a6; - return ((IMP _Nonnull (*)(id _Nullable __asm__("a0"), SEL _Nonnull __asm__("a1")))(((uintptr_t)ObjFWRTBase) - 48))(object, selector); -#elif defined(OF_MORPHOS) - __asm__ __volatile__ ( - "mr %%r12, %0" - :: "r"(ObjFWRTBase) : "r12" - ); - - return __extension__ ((IMP _Nonnull (*)(id _Nullable, SEL _Nonnull))*(void **)(((uintptr_t)ObjFWRTBase) - 46))(object, selector); -#endif -} - -IMP _Nonnull -objc_msg_lookup_super(struct objc_super *_Nonnull super, SEL _Nonnull selector) -{ -#if defined(OF_AMIGAOS_M68K) - register struct Library *a6 __asm__("a6") = ObjFWRTBase; - (void)a6; - return ((IMP _Nonnull (*)(struct objc_super *_Nonnull __asm__("a0"), SEL _Nonnull __asm__("a1")))(((uintptr_t)ObjFWRTBase) - 54))(super, selector); -#elif defined(OF_MORPHOS) - __asm__ __volatile__ ( - "mr %%r12, %0" - :: "r"(ObjFWRTBase) : "r12" - ); - - return __extension__ ((IMP _Nonnull (*)(struct objc_super *_Nonnull, SEL _Nonnull))*(void **)(((uintptr_t)ObjFWRTBase) - 52))(super, selector); -#endif -} - -IMP _Nonnull -objc_msg_lookup_super_stret(struct objc_super *_Nonnull super, SEL _Nonnull selector) -{ -#if defined(OF_AMIGAOS_M68K) - register struct Library *a6 __asm__("a6") = ObjFWRTBase; - (void)a6; - return ((IMP _Nonnull (*)(struct objc_super *_Nonnull __asm__("a0"), SEL _Nonnull __asm__("a1")))(((uintptr_t)ObjFWRTBase) - 60))(super, selector); -#elif defined(OF_MORPHOS) - __asm__ __volatile__ ( - "mr %%r12, %0" - :: "r"(ObjFWRTBase) : "r12" - ); - - return __extension__ ((IMP _Nonnull (*)(struct objc_super *_Nonnull, SEL _Nonnull))*(void **)(((uintptr_t)ObjFWRTBase) - 58))(super, selector); -#endif -} - -Class _Nullable -objc_lookUpClass(const char *_Nonnull name) -{ -#if defined(OF_AMIGAOS_M68K) - register struct Library *a6 __asm__("a6") = ObjFWRTBase; - (void)a6; - return ((Class _Nullable (*)(const char *_Nonnull __asm__("a0")))(((uintptr_t)ObjFWRTBase) - 66))(name); -#elif defined(OF_MORPHOS) - __asm__ __volatile__ ( - "mr %%r12, %0" - :: "r"(ObjFWRTBase) : "r12" - ); - - return __extension__ ((Class _Nullable (*)(const char *_Nonnull))*(void **)(((uintptr_t)ObjFWRTBase) - 64))(name); -#endif -} - -Class _Nullable -objc_getClass(const char *_Nonnull name) -{ -#if defined(OF_AMIGAOS_M68K) - register struct Library *a6 __asm__("a6") = ObjFWRTBase; - (void)a6; - return ((Class _Nullable (*)(const char *_Nonnull __asm__("a0")))(((uintptr_t)ObjFWRTBase) - 72))(name); -#elif defined(OF_MORPHOS) - __asm__ __volatile__ ( - "mr %%r12, %0" - :: "r"(ObjFWRTBase) : "r12" - ); - - return __extension__ ((Class _Nullable (*)(const char *_Nonnull))*(void **)(((uintptr_t)ObjFWRTBase) - 70))(name); -#endif -} - -Class _Nonnull -objc_getRequiredClass(const char *_Nonnull name) -{ -#if defined(OF_AMIGAOS_M68K) - register struct Library *a6 __asm__("a6") = ObjFWRTBase; - (void)a6; - return ((Class _Nonnull (*)(const char *_Nonnull __asm__("a0")))(((uintptr_t)ObjFWRTBase) - 78))(name); -#elif defined(OF_MORPHOS) - __asm__ __volatile__ ( - "mr %%r12, %0" - :: "r"(ObjFWRTBase) : "r12" - ); - - return __extension__ ((Class _Nonnull (*)(const char *_Nonnull))*(void **)(((uintptr_t)ObjFWRTBase) - 76))(name); -#endif -} - -Class _Nullable -objc_lookup_class(const char *_Nonnull name) -{ -#if defined(OF_AMIGAOS_M68K) - register struct Library *a6 __asm__("a6") = ObjFWRTBase; - (void)a6; - return ((Class _Nullable (*)(const char *_Nonnull __asm__("a0")))(((uintptr_t)ObjFWRTBase) - 84))(name); -#elif defined(OF_MORPHOS) - __asm__ __volatile__ ( - "mr %%r12, %0" - :: "r"(ObjFWRTBase) : "r12" - ); - - return __extension__ ((Class _Nullable (*)(const char *_Nonnull))*(void **)(((uintptr_t)ObjFWRTBase) - 82))(name); -#endif -} - -Class _Nonnull -objc_get_class(const char *_Nonnull name) -{ -#if defined(OF_AMIGAOS_M68K) - register struct Library *a6 __asm__("a6") = ObjFWRTBase; - (void)a6; - return ((Class _Nonnull (*)(const char *_Nonnull __asm__("a0")))(((uintptr_t)ObjFWRTBase) - 90))(name); -#elif defined(OF_MORPHOS) - __asm__ __volatile__ ( - "mr %%r12, %0" - :: "r"(ObjFWRTBase) : "r12" - ); - - return __extension__ ((Class _Nonnull (*)(const char *_Nonnull))*(void **)(((uintptr_t)ObjFWRTBase) - 88))(name); -#endif -} - -void -objc_exception_throw(id _Nonnull object) -{ -#if defined(OF_AMIGAOS_M68K) - register struct Library *a6 __asm__("a6") = ObjFWRTBase; - (void)a6; - ((void (*)(id _Nonnull __asm__("a0")))(((uintptr_t)ObjFWRTBase) - 96))(object); -#elif defined(OF_MORPHOS) - __asm__ __volatile__ ( - "mr %%r12, %0" - :: "r"(ObjFWRTBase) : "r12" - ); - - __extension__ ((void (*)(id _Nonnull))*(void **)(((uintptr_t)ObjFWRTBase) - 94))(object); -#endif - - OF_UNREACHABLE -} - -int -objc_sync_enter(id _Nullable object) -{ -#if defined(OF_AMIGAOS_M68K) - register struct Library *a6 __asm__("a6") = ObjFWRTBase; - (void)a6; - return ((int (*)(id _Nullable __asm__("a0")))(((uintptr_t)ObjFWRTBase) - 102))(object); -#elif defined(OF_MORPHOS) - __asm__ __volatile__ ( - "mr %%r12, %0" - :: "r"(ObjFWRTBase) : "r12" - ); - - return __extension__ ((int (*)(id _Nullable))*(void **)(((uintptr_t)ObjFWRTBase) - 100))(object); -#endif -} - -int -objc_sync_exit(id _Nullable object) -{ -#if defined(OF_AMIGAOS_M68K) - register struct Library *a6 __asm__("a6") = ObjFWRTBase; - (void)a6; - return ((int (*)(id _Nullable __asm__("a0")))(((uintptr_t)ObjFWRTBase) - 108))(object); -#elif defined(OF_MORPHOS) - __asm__ __volatile__ ( - "mr %%r12, %0" - :: "r"(ObjFWRTBase) : "r12" - ); - - return __extension__ ((int (*)(id _Nullable))*(void **)(((uintptr_t)ObjFWRTBase) - 106))(object); -#endif -} - -id _Nullable -objc_getProperty(id _Nonnull self, SEL _Nonnull _cmd, ptrdiff_t offset, bool atomic) -{ -#if defined(OF_AMIGAOS_M68K) - register struct Library *a6 __asm__("a6") = ObjFWRTBase; - (void)a6; - return ((id _Nullable (*)(id _Nonnull __asm__("a0"), SEL _Nonnull __asm__("a1"), ptrdiff_t __asm__("d0"), bool __asm__("d1")))(((uintptr_t)ObjFWRTBase) - 114))(self, _cmd, offset, atomic); -#elif defined(OF_MORPHOS) - __asm__ __volatile__ ( - "mr %%r12, %0" - :: "r"(ObjFWRTBase) : "r12" - ); - - return __extension__ ((id _Nullable (*)(id _Nonnull, SEL _Nonnull, ptrdiff_t, bool))*(void **)(((uintptr_t)ObjFWRTBase) - 112))(self, _cmd, offset, atomic); -#endif -} - -void -objc_setProperty(id _Nonnull self, SEL _Nonnull _cmd, ptrdiff_t offset, id _Nullable value, bool atomic, signed char copy) -{ -#if defined(OF_AMIGAOS_M68K) - register struct Library *a6 __asm__("a6") = ObjFWRTBase; - (void)a6; - ((void (*)(id _Nonnull __asm__("a0"), SEL _Nonnull __asm__("a1"), ptrdiff_t __asm__("d0"), id _Nullable __asm__("a2"), bool __asm__("d1"), signed char __asm__("d2")))(((uintptr_t)ObjFWRTBase) - 120))(self, _cmd, offset, value, atomic, copy); -#elif defined(OF_MORPHOS) - __asm__ __volatile__ ( - "mr %%r12, %0" - :: "r"(ObjFWRTBase) : "r12" - ); - - __extension__ ((void (*)(id _Nonnull, SEL _Nonnull, ptrdiff_t, id _Nullable, bool, signed char))*(void **)(((uintptr_t)ObjFWRTBase) - 118))(self, _cmd, offset, value, atomic, copy); -#endif -} - -void -objc_getPropertyStruct(void *_Nonnull dest, const void *_Nonnull src, ptrdiff_t size, bool atomic, bool strong) -{ -#if defined(OF_AMIGAOS_M68K) - register struct Library *a6 __asm__("a6") = ObjFWRTBase; - (void)a6; - ((void (*)(void *_Nonnull __asm__("a0"), const void *_Nonnull __asm__("a1"), ptrdiff_t __asm__("d0"), bool __asm__("d1"), bool __asm__("d2")))(((uintptr_t)ObjFWRTBase) - 126))(dest, src, size, atomic, strong); -#elif defined(OF_MORPHOS) - __asm__ __volatile__ ( - "mr %%r12, %0" - :: "r"(ObjFWRTBase) : "r12" - ); - - __extension__ ((void (*)(void *_Nonnull, const void *_Nonnull, ptrdiff_t, bool, bool))*(void **)(((uintptr_t)ObjFWRTBase) - 124))(dest, src, size, atomic, strong); -#endif -} - -void -objc_setPropertyStruct(void *_Nonnull dest, const void *_Nonnull src, ptrdiff_t size, bool atomic, bool strong) -{ -#if defined(OF_AMIGAOS_M68K) - register struct Library *a6 __asm__("a6") = ObjFWRTBase; - (void)a6; - ((void (*)(void *_Nonnull __asm__("a0"), const void *_Nonnull __asm__("a1"), ptrdiff_t __asm__("d0"), bool __asm__("d1"), bool __asm__("d2")))(((uintptr_t)ObjFWRTBase) - 132))(dest, src, size, atomic, strong); -#elif defined(OF_MORPHOS) - __asm__ __volatile__ ( - "mr %%r12, %0" - :: "r"(ObjFWRTBase) : "r12" - ); - - __extension__ ((void (*)(void *_Nonnull, const void *_Nonnull, ptrdiff_t, bool, bool))*(void **)(((uintptr_t)ObjFWRTBase) - 130))(dest, src, size, atomic, strong); -#endif -} - -void -objc_enumerationMutation(id _Nonnull object) -{ -#if defined(OF_AMIGAOS_M68K) - register struct Library *a6 __asm__("a6") = ObjFWRTBase; - (void)a6; - ((void (*)(id _Nonnull __asm__("a0")))(((uintptr_t)ObjFWRTBase) - 138))(object); -#elif defined(OF_MORPHOS) - __asm__ __volatile__ ( - "mr %%r12, %0" - :: "r"(ObjFWRTBase) : "r12" - ); - - __extension__ ((void (*)(id _Nonnull))*(void **)(((uintptr_t)ObjFWRTBase) - 136))(object); -#endif -} - -int -__gnu_objc_personality(int version, int actions, uint64_t *_Nonnull exClass, void *_Nonnull ex, void *_Nonnull ctx) -{ -#if defined(OF_AMIGAOS_M68K) - register struct Library *a6 __asm__("a6") = ObjFWRTBase; - (void)a6; - return ((int (*)(int __asm__("d0"), int __asm__("d1"), uint64_t *_Nonnull __asm__("d2"), void *_Nonnull __asm__("a0"), void *_Nonnull __asm__("a1")))(((uintptr_t)ObjFWRTBase) - 144))(version, actions, exClass, ex, ctx); -#elif defined(OF_MORPHOS) - __asm__ __volatile__ ( - "mr %%r12, %0" - :: "r"(ObjFWRTBase) : "r12" - ); - - return __extension__ ((int (*)(int, int, uint64_t *_Nonnull, void *_Nonnull, void *_Nonnull))*(void **)(((uintptr_t)ObjFWRTBase) - 142))(version, actions, exClass, ex, ctx); -#endif -} - -id _Nullable -objc_retain(id _Nullable object) -{ -#if defined(OF_AMIGAOS_M68K) - register struct Library *a6 __asm__("a6") = ObjFWRTBase; - (void)a6; - return ((id _Nullable (*)(id _Nullable __asm__("a0")))(((uintptr_t)ObjFWRTBase) - 150))(object); -#elif defined(OF_MORPHOS) - __asm__ __volatile__ ( - "mr %%r12, %0" - :: "r"(ObjFWRTBase) : "r12" - ); - - return __extension__ ((id _Nullable (*)(id _Nullable))*(void **)(((uintptr_t)ObjFWRTBase) - 148))(object); -#endif -} - -id _Nullable -objc_retainBlock(id _Nullable block) -{ -#if defined(OF_AMIGAOS_M68K) - register struct Library *a6 __asm__("a6") = ObjFWRTBase; - (void)a6; - return ((id _Nullable (*)(id _Nullable __asm__("a0")))(((uintptr_t)ObjFWRTBase) - 156))(block); -#elif defined(OF_MORPHOS) - __asm__ __volatile__ ( - "mr %%r12, %0" - :: "r"(ObjFWRTBase) : "r12" - ); - - return __extension__ ((id _Nullable (*)(id _Nullable))*(void **)(((uintptr_t)ObjFWRTBase) - 154))(block); -#endif -} - -id _Nullable -objc_retainAutorelease(id _Nullable object) -{ -#if defined(OF_AMIGAOS_M68K) - register struct Library *a6 __asm__("a6") = ObjFWRTBase; - (void)a6; - return ((id _Nullable (*)(id _Nullable __asm__("a0")))(((uintptr_t)ObjFWRTBase) - 162))(object); -#elif defined(OF_MORPHOS) - __asm__ __volatile__ ( - "mr %%r12, %0" - :: "r"(ObjFWRTBase) : "r12" - ); - - return __extension__ ((id _Nullable (*)(id _Nullable))*(void **)(((uintptr_t)ObjFWRTBase) - 160))(object); -#endif -} - -void -objc_release(id _Nullable object) -{ -#if defined(OF_AMIGAOS_M68K) - register struct Library *a6 __asm__("a6") = ObjFWRTBase; - (void)a6; - ((void (*)(id _Nullable __asm__("a0")))(((uintptr_t)ObjFWRTBase) - 168))(object); -#elif defined(OF_MORPHOS) - __asm__ __volatile__ ( - "mr %%r12, %0" - :: "r"(ObjFWRTBase) : "r12" - ); - - __extension__ ((void (*)(id _Nullable))*(void **)(((uintptr_t)ObjFWRTBase) - 166))(object); -#endif -} - -id _Nullable -objc_autorelease(id _Nullable object) -{ -#if defined(OF_AMIGAOS_M68K) - register struct Library *a6 __asm__("a6") = ObjFWRTBase; - (void)a6; - return ((id _Nullable (*)(id _Nullable __asm__("a0")))(((uintptr_t)ObjFWRTBase) - 174))(object); -#elif defined(OF_MORPHOS) - __asm__ __volatile__ ( - "mr %%r12, %0" - :: "r"(ObjFWRTBase) : "r12" - ); - - return __extension__ ((id _Nullable (*)(id _Nullable))*(void **)(((uintptr_t)ObjFWRTBase) - 172))(object); -#endif -} - -id _Nullable -objc_autoreleaseReturnValue(id _Nullable object) -{ -#if defined(OF_AMIGAOS_M68K) - register struct Library *a6 __asm__("a6") = ObjFWRTBase; - (void)a6; - return ((id _Nullable (*)(id _Nullable __asm__("a0")))(((uintptr_t)ObjFWRTBase) - 180))(object); -#elif defined(OF_MORPHOS) - __asm__ __volatile__ ( - "mr %%r12, %0" - :: "r"(ObjFWRTBase) : "r12" - ); - - return __extension__ ((id _Nullable (*)(id _Nullable))*(void **)(((uintptr_t)ObjFWRTBase) - 178))(object); -#endif -} - -id _Nullable -objc_retainAutoreleaseReturnValue(id _Nullable object) -{ -#if defined(OF_AMIGAOS_M68K) - register struct Library *a6 __asm__("a6") = ObjFWRTBase; - (void)a6; - return ((id _Nullable (*)(id _Nullable __asm__("a0")))(((uintptr_t)ObjFWRTBase) - 186))(object); -#elif defined(OF_MORPHOS) - __asm__ __volatile__ ( - "mr %%r12, %0" - :: "r"(ObjFWRTBase) : "r12" - ); - - return __extension__ ((id _Nullable (*)(id _Nullable))*(void **)(((uintptr_t)ObjFWRTBase) - 184))(object); -#endif -} - -id _Nullable -objc_retainAutoreleasedReturnValue(id _Nullable object) -{ -#if defined(OF_AMIGAOS_M68K) - register struct Library *a6 __asm__("a6") = ObjFWRTBase; - (void)a6; - return ((id _Nullable (*)(id _Nullable __asm__("a0")))(((uintptr_t)ObjFWRTBase) - 192))(object); -#elif defined(OF_MORPHOS) - __asm__ __volatile__ ( - "mr %%r12, %0" - :: "r"(ObjFWRTBase) : "r12" - ); - - return __extension__ ((id _Nullable (*)(id _Nullable))*(void **)(((uintptr_t)ObjFWRTBase) - 190))(object); -#endif -} - -id _Nullable -objc_storeStrong(id _Nullable *_Nonnull object, id _Nullable value) -{ -#if defined(OF_AMIGAOS_M68K) - register struct Library *a6 __asm__("a6") = ObjFWRTBase; - (void)a6; - return ((id _Nullable (*)(id _Nullable *_Nonnull __asm__("a0"), id _Nullable __asm__("a1")))(((uintptr_t)ObjFWRTBase) - 198))(object, value); -#elif defined(OF_MORPHOS) - __asm__ __volatile__ ( - "mr %%r12, %0" - :: "r"(ObjFWRTBase) : "r12" - ); - - return __extension__ ((id _Nullable (*)(id _Nullable *_Nonnull, id _Nullable))*(void **)(((uintptr_t)ObjFWRTBase) - 196))(object, value); -#endif -} - -id _Nullable -objc_storeWeak(id _Nullable *_Nonnull object, id _Nullable value) -{ -#if defined(OF_AMIGAOS_M68K) - register struct Library *a6 __asm__("a6") = ObjFWRTBase; - (void)a6; - return ((id _Nullable (*)(id _Nullable *_Nonnull __asm__("a0"), id _Nullable __asm__("a1")))(((uintptr_t)ObjFWRTBase) - 204))(object, value); -#elif defined(OF_MORPHOS) - __asm__ __volatile__ ( - "mr %%r12, %0" - :: "r"(ObjFWRTBase) : "r12" - ); - - return __extension__ ((id _Nullable (*)(id _Nullable *_Nonnull, id _Nullable))*(void **)(((uintptr_t)ObjFWRTBase) - 202))(object, value); -#endif -} - -id _Nullable -objc_loadWeakRetained(id _Nullable *_Nonnull object) -{ -#if defined(OF_AMIGAOS_M68K) - register struct Library *a6 __asm__("a6") = ObjFWRTBase; - (void)a6; - return ((id _Nullable (*)(id _Nullable *_Nonnull __asm__("a0")))(((uintptr_t)ObjFWRTBase) - 210))(object); -#elif defined(OF_MORPHOS) - __asm__ __volatile__ ( - "mr %%r12, %0" - :: "r"(ObjFWRTBase) : "r12" - ); - - return __extension__ ((id _Nullable (*)(id _Nullable *_Nonnull))*(void **)(((uintptr_t)ObjFWRTBase) - 208))(object); -#endif -} - -id _Nullable -objc_initWeak(id _Nullable *_Nonnull object, id _Nullable value) -{ -#if defined(OF_AMIGAOS_M68K) - register struct Library *a6 __asm__("a6") = ObjFWRTBase; - (void)a6; - return ((id _Nullable (*)(id _Nullable *_Nonnull __asm__("a0"), id _Nullable __asm__("a1")))(((uintptr_t)ObjFWRTBase) - 216))(object, value); -#elif defined(OF_MORPHOS) - __asm__ __volatile__ ( - "mr %%r12, %0" - :: "r"(ObjFWRTBase) : "r12" - ); - - return __extension__ ((id _Nullable (*)(id _Nullable *_Nonnull, id _Nullable))*(void **)(((uintptr_t)ObjFWRTBase) - 214))(object, value); -#endif -} - -void -objc_destroyWeak(id _Nullable *_Nonnull object) -{ -#if defined(OF_AMIGAOS_M68K) - register struct Library *a6 __asm__("a6") = ObjFWRTBase; - (void)a6; - ((void (*)(id _Nullable *_Nonnull __asm__("a0")))(((uintptr_t)ObjFWRTBase) - 222))(object); -#elif defined(OF_MORPHOS) - __asm__ __volatile__ ( - "mr %%r12, %0" - :: "r"(ObjFWRTBase) : "r12" - ); - - __extension__ ((void (*)(id _Nullable *_Nonnull))*(void **)(((uintptr_t)ObjFWRTBase) - 220))(object); -#endif -} - -id _Nullable -objc_loadWeak(id _Nullable *_Nonnull object) -{ -#if defined(OF_AMIGAOS_M68K) - register struct Library *a6 __asm__("a6") = ObjFWRTBase; - (void)a6; - return ((id _Nullable (*)(id _Nullable *_Nonnull __asm__("a0")))(((uintptr_t)ObjFWRTBase) - 228))(object); -#elif defined(OF_MORPHOS) - __asm__ __volatile__ ( - "mr %%r12, %0" - :: "r"(ObjFWRTBase) : "r12" - ); - - return __extension__ ((id _Nullable (*)(id _Nullable *_Nonnull))*(void **)(((uintptr_t)ObjFWRTBase) - 226))(object); -#endif -} - -void -objc_copyWeak(id _Nullable *_Nonnull dest, id _Nullable *_Nonnull src) -{ -#if defined(OF_AMIGAOS_M68K) - register struct Library *a6 __asm__("a6") = ObjFWRTBase; - (void)a6; - ((void (*)(id _Nullable *_Nonnull __asm__("a0"), id _Nullable *_Nonnull __asm__("a1")))(((uintptr_t)ObjFWRTBase) - 234))(dest, src); -#elif defined(OF_MORPHOS) - __asm__ __volatile__ ( - "mr %%r12, %0" - :: "r"(ObjFWRTBase) : "r12" - ); - - __extension__ ((void (*)(id _Nullable *_Nonnull, id _Nullable *_Nonnull))*(void **)(((uintptr_t)ObjFWRTBase) - 232))(dest, src); -#endif -} - -void -objc_moveWeak(id _Nullable *_Nonnull dest, id _Nullable *_Nonnull src) -{ -#if defined(OF_AMIGAOS_M68K) - register struct Library *a6 __asm__("a6") = ObjFWRTBase; - (void)a6; - ((void (*)(id _Nullable *_Nonnull __asm__("a0"), id _Nullable *_Nonnull __asm__("a1")))(((uintptr_t)ObjFWRTBase) - 240))(dest, src); -#elif defined(OF_MORPHOS) - __asm__ __volatile__ ( - "mr %%r12, %0" - :: "r"(ObjFWRTBase) : "r12" - ); - - __extension__ ((void (*)(id _Nullable *_Nonnull, id _Nullable *_Nonnull))*(void **)(((uintptr_t)ObjFWRTBase) - 238))(dest, src); -#endif -} - -SEL _Nonnull -sel_registerName(const char *_Nonnull name) -{ -#if defined(OF_AMIGAOS_M68K) - register struct Library *a6 __asm__("a6") = ObjFWRTBase; - (void)a6; - return ((SEL _Nonnull (*)(const char *_Nonnull __asm__("a0")))(((uintptr_t)ObjFWRTBase) - 246))(name); -#elif defined(OF_MORPHOS) - __asm__ __volatile__ ( - "mr %%r12, %0" - :: "r"(ObjFWRTBase) : "r12" - ); - - return __extension__ ((SEL _Nonnull (*)(const char *_Nonnull))*(void **)(((uintptr_t)ObjFWRTBase) - 244))(name); -#endif -} - -const char *_Nonnull -sel_getName(SEL _Nonnull selector) -{ -#if defined(OF_AMIGAOS_M68K) - register struct Library *a6 __asm__("a6") = ObjFWRTBase; - (void)a6; - return ((const char *_Nonnull (*)(SEL _Nonnull __asm__("a0")))(((uintptr_t)ObjFWRTBase) - 252))(selector); -#elif defined(OF_MORPHOS) - __asm__ __volatile__ ( - "mr %%r12, %0" - :: "r"(ObjFWRTBase) : "r12" - ); - - return __extension__ ((const char *_Nonnull (*)(SEL _Nonnull))*(void **)(((uintptr_t)ObjFWRTBase) - 250))(selector); -#endif -} - -bool -sel_isEqual(SEL _Nonnull selector1, SEL _Nonnull selector2) -{ -#if defined(OF_AMIGAOS_M68K) - register struct Library *a6 __asm__("a6") = ObjFWRTBase; - (void)a6; - return ((bool (*)(SEL _Nonnull __asm__("a0"), SEL _Nonnull __asm__("a1")))(((uintptr_t)ObjFWRTBase) - 258))(selector1, selector2); -#elif defined(OF_MORPHOS) - __asm__ __volatile__ ( - "mr %%r12, %0" - :: "r"(ObjFWRTBase) : "r12" - ); - - return __extension__ ((bool (*)(SEL _Nonnull, SEL _Nonnull))*(void **)(((uintptr_t)ObjFWRTBase) - 256))(selector1, selector2); -#endif -} - -Class _Nonnull -objc_allocateClassPair(Class _Nullable superclass, const char *_Nonnull name, size_t extraBytes) -{ -#if defined(OF_AMIGAOS_M68K) - register struct Library *a6 __asm__("a6") = ObjFWRTBase; - (void)a6; - return ((Class _Nonnull (*)(Class _Nullable __asm__("a0"), const char *_Nonnull __asm__("a1"), size_t __asm__("d0")))(((uintptr_t)ObjFWRTBase) - 264))(superclass, name, extraBytes); -#elif defined(OF_MORPHOS) - __asm__ __volatile__ ( - "mr %%r12, %0" - :: "r"(ObjFWRTBase) : "r12" - ); - - return __extension__ ((Class _Nonnull (*)(Class _Nullable, const char *_Nonnull, size_t))*(void **)(((uintptr_t)ObjFWRTBase) - 262))(superclass, name, extraBytes); -#endif -} - -void -objc_registerClassPair(Class _Nonnull class) -{ -#if defined(OF_AMIGAOS_M68K) - register struct Library *a6 __asm__("a6") = ObjFWRTBase; - (void)a6; - ((void (*)(Class _Nonnull __asm__("a0")))(((uintptr_t)ObjFWRTBase) - 270))(class); -#elif defined(OF_MORPHOS) - __asm__ __volatile__ ( - "mr %%r12, %0" - :: "r"(ObjFWRTBase) : "r12" - ); - - __extension__ ((void (*)(Class _Nonnull))*(void **)(((uintptr_t)ObjFWRTBase) - 268))(class); -#endif -} - -unsigned int -objc_getClassList(Class _Nonnull *_Nullable buffer, unsigned int count) -{ -#if defined(OF_AMIGAOS_M68K) - register struct Library *a6 __asm__("a6") = ObjFWRTBase; - (void)a6; - return ((unsigned int (*)(Class _Nonnull *_Nullable __asm__("a0"), unsigned int __asm__("d0")))(((uintptr_t)ObjFWRTBase) - 276))(buffer, count); -#elif defined(OF_MORPHOS) - __asm__ __volatile__ ( - "mr %%r12, %0" - :: "r"(ObjFWRTBase) : "r12" - ); - - return __extension__ ((unsigned int (*)(Class _Nonnull *_Nullable, unsigned int))*(void **)(((uintptr_t)ObjFWRTBase) - 274))(buffer, count); -#endif -} - -Class _Nonnull *_Nonnull -objc_copyClassList(unsigned int *_Nullable length) -{ -#if defined(OF_AMIGAOS_M68K) - register struct Library *a6 __asm__("a6") = ObjFWRTBase; - (void)a6; - return ((Class _Nonnull *_Nonnull (*)(unsigned int *_Nullable __asm__("a0")))(((uintptr_t)ObjFWRTBase) - 282))(length); -#elif defined(OF_MORPHOS) - __asm__ __volatile__ ( - "mr %%r12, %0" - :: "r"(ObjFWRTBase) : "r12" - ); - - return __extension__ ((Class _Nonnull *_Nonnull (*)(unsigned int *_Nullable))*(void **)(((uintptr_t)ObjFWRTBase) - 280))(length); -#endif -} - -bool -class_isMetaClass(Class _Nullable class) -{ -#if defined(OF_AMIGAOS_M68K) - register struct Library *a6 __asm__("a6") = ObjFWRTBase; - (void)a6; - return ((bool (*)(Class _Nullable __asm__("a0")))(((uintptr_t)ObjFWRTBase) - 288))(class); -#elif defined(OF_MORPHOS) - __asm__ __volatile__ ( - "mr %%r12, %0" - :: "r"(ObjFWRTBase) : "r12" - ); - - return __extension__ ((bool (*)(Class _Nullable))*(void **)(((uintptr_t)ObjFWRTBase) - 286))(class); -#endif -} - -const char *_Nullable -class_getName(Class _Nullable class) -{ -#if defined(OF_AMIGAOS_M68K) - register struct Library *a6 __asm__("a6") = ObjFWRTBase; - (void)a6; - return ((const char *_Nullable (*)(Class _Nullable __asm__("a0")))(((uintptr_t)ObjFWRTBase) - 294))(class); -#elif defined(OF_MORPHOS) - __asm__ __volatile__ ( - "mr %%r12, %0" - :: "r"(ObjFWRTBase) : "r12" - ); - - return __extension__ ((const char *_Nullable (*)(Class _Nullable))*(void **)(((uintptr_t)ObjFWRTBase) - 292))(class); -#endif -} - -Class _Nullable -class_getSuperclass(Class _Nullable class) -{ -#if defined(OF_AMIGAOS_M68K) - register struct Library *a6 __asm__("a6") = ObjFWRTBase; - (void)a6; - return ((Class _Nullable (*)(Class _Nullable __asm__("a0")))(((uintptr_t)ObjFWRTBase) - 300))(class); -#elif defined(OF_MORPHOS) - __asm__ __volatile__ ( - "mr %%r12, %0" - :: "r"(ObjFWRTBase) : "r12" - ); - - return __extension__ ((Class _Nullable (*)(Class _Nullable))*(void **)(((uintptr_t)ObjFWRTBase) - 298))(class); -#endif -} - -unsigned long -class_getInstanceSize(Class _Nullable class) -{ -#if defined(OF_AMIGAOS_M68K) - register struct Library *a6 __asm__("a6") = ObjFWRTBase; - (void)a6; - return ((unsigned long (*)(Class _Nullable __asm__("a0")))(((uintptr_t)ObjFWRTBase) - 306))(class); -#elif defined(OF_MORPHOS) - __asm__ __volatile__ ( - "mr %%r12, %0" - :: "r"(ObjFWRTBase) : "r12" - ); - - return __extension__ ((unsigned long (*)(Class _Nullable))*(void **)(((uintptr_t)ObjFWRTBase) - 304))(class); -#endif -} - -bool -class_respondsToSelector(Class _Nullable class, SEL _Nonnull selector) -{ -#if defined(OF_AMIGAOS_M68K) - register struct Library *a6 __asm__("a6") = ObjFWRTBase; - (void)a6; - return ((bool (*)(Class _Nullable __asm__("a0"), SEL _Nonnull __asm__("a1")))(((uintptr_t)ObjFWRTBase) - 312))(class, selector); -#elif defined(OF_MORPHOS) - __asm__ __volatile__ ( - "mr %%r12, %0" - :: "r"(ObjFWRTBase) : "r12" - ); - - return __extension__ ((bool (*)(Class _Nullable, SEL _Nonnull))*(void **)(((uintptr_t)ObjFWRTBase) - 310))(class, selector); -#endif -} - -bool -class_conformsToProtocol(Class _Nullable class, Protocol *_Nonnull p) -{ -#if defined(OF_AMIGAOS_M68K) - register struct Library *a6 __asm__("a6") = ObjFWRTBase; - (void)a6; - return ((bool (*)(Class _Nullable __asm__("a0"), Protocol *_Nonnull __asm__("a1")))(((uintptr_t)ObjFWRTBase) - 318))(class, p); -#elif defined(OF_MORPHOS) - __asm__ __volatile__ ( - "mr %%r12, %0" - :: "r"(ObjFWRTBase) : "r12" - ); - - return __extension__ ((bool (*)(Class _Nullable, Protocol *_Nonnull))*(void **)(((uintptr_t)ObjFWRTBase) - 316))(class, p); -#endif -} - -IMP _Nullable -class_getMethodImplementation(Class _Nullable class, SEL _Nonnull selector) -{ -#if defined(OF_AMIGAOS_M68K) - register struct Library *a6 __asm__("a6") = ObjFWRTBase; - (void)a6; - return ((IMP _Nullable (*)(Class _Nullable __asm__("a0"), SEL _Nonnull __asm__("a1")))(((uintptr_t)ObjFWRTBase) - 324))(class, selector); -#elif defined(OF_MORPHOS) - __asm__ __volatile__ ( - "mr %%r12, %0" - :: "r"(ObjFWRTBase) : "r12" - ); - - return __extension__ ((IMP _Nullable (*)(Class _Nullable, SEL _Nonnull))*(void **)(((uintptr_t)ObjFWRTBase) - 322))(class, selector); -#endif -} - -IMP _Nullable -class_getMethodImplementation_stret(Class _Nullable class, SEL _Nonnull selector) -{ -#if defined(OF_AMIGAOS_M68K) - register struct Library *a6 __asm__("a6") = ObjFWRTBase; - (void)a6; - return ((IMP _Nullable (*)(Class _Nullable __asm__("a0"), SEL _Nonnull __asm__("a1")))(((uintptr_t)ObjFWRTBase) - 330))(class, selector); -#elif defined(OF_MORPHOS) - __asm__ __volatile__ ( - "mr %%r12, %0" - :: "r"(ObjFWRTBase) : "r12" - ); - - return __extension__ ((IMP _Nullable (*)(Class _Nullable, SEL _Nonnull))*(void **)(((uintptr_t)ObjFWRTBase) - 328))(class, selector); -#endif -} - -Method _Nullable -class_getInstanceMethod(Class _Nullable class, SEL _Nonnull selector) -{ -#if defined(OF_AMIGAOS_M68K) - register struct Library *a6 __asm__("a6") = ObjFWRTBase; - (void)a6; - return ((Method _Nullable (*)(Class _Nullable __asm__("a0"), SEL _Nonnull __asm__("a1")))(((uintptr_t)ObjFWRTBase) - 336))(class, selector); -#elif defined(OF_MORPHOS) - __asm__ __volatile__ ( - "mr %%r12, %0" - :: "r"(ObjFWRTBase) : "r12" - ); - - return __extension__ ((Method _Nullable (*)(Class _Nullable, SEL _Nonnull))*(void **)(((uintptr_t)ObjFWRTBase) - 334))(class, selector); -#endif -} - -bool -class_addMethod(Class _Nonnull class, SEL _Nonnull selector, IMP _Nonnull implementation, const char *_Nullable typeEncoding) -{ -#if defined(OF_AMIGAOS_M68K) - register struct Library *a6 __asm__("a6") = ObjFWRTBase; - (void)a6; - return ((bool (*)(Class _Nonnull __asm__("a0"), SEL _Nonnull __asm__("a1"), IMP _Nonnull __asm__("a2"), const char *_Nullable __asm__("a3")))(((uintptr_t)ObjFWRTBase) - 342))(class, selector, implementation, typeEncoding); -#elif defined(OF_MORPHOS) - __asm__ __volatile__ ( - "mr %%r12, %0" - :: "r"(ObjFWRTBase) : "r12" - ); - - return __extension__ ((bool (*)(Class _Nonnull, SEL _Nonnull, IMP _Nonnull, const char *_Nullable))*(void **)(((uintptr_t)ObjFWRTBase) - 340))(class, selector, implementation, typeEncoding); -#endif -} - -IMP _Nullable -class_replaceMethod(Class _Nonnull class, SEL _Nonnull selector, IMP _Nonnull implementation, const char *_Nullable typeEncoding) -{ -#if defined(OF_AMIGAOS_M68K) - register struct Library *a6 __asm__("a6") = ObjFWRTBase; - (void)a6; - return ((IMP _Nullable (*)(Class _Nonnull __asm__("a0"), SEL _Nonnull __asm__("a1"), IMP _Nonnull __asm__("a2"), const char *_Nullable __asm__("a3")))(((uintptr_t)ObjFWRTBase) - 348))(class, selector, implementation, typeEncoding); -#elif defined(OF_MORPHOS) - __asm__ __volatile__ ( - "mr %%r12, %0" - :: "r"(ObjFWRTBase) : "r12" - ); - - return __extension__ ((IMP _Nullable (*)(Class _Nonnull, SEL _Nonnull, IMP _Nonnull, const char *_Nullable))*(void **)(((uintptr_t)ObjFWRTBase) - 346))(class, selector, implementation, typeEncoding); -#endif -} - -Class _Nullable -object_getClass(id _Nullable object) -{ -#if defined(OF_AMIGAOS_M68K) - register struct Library *a6 __asm__("a6") = ObjFWRTBase; - (void)a6; - return ((Class _Nullable (*)(id _Nullable __asm__("a0")))(((uintptr_t)ObjFWRTBase) - 354))(object); -#elif defined(OF_MORPHOS) - __asm__ __volatile__ ( - "mr %%r12, %0" - :: "r"(ObjFWRTBase) : "r12" - ); - - return __extension__ ((Class _Nullable (*)(id _Nullable))*(void **)(((uintptr_t)ObjFWRTBase) - 352))(object); -#endif -} - -Class _Nullable -object_setClass(id _Nullable object, Class _Nonnull class) -{ -#if defined(OF_AMIGAOS_M68K) - register struct Library *a6 __asm__("a6") = ObjFWRTBase; - (void)a6; - return ((Class _Nullable (*)(id _Nullable __asm__("a0"), Class _Nonnull __asm__("a1")))(((uintptr_t)ObjFWRTBase) - 360))(object, class); -#elif defined(OF_MORPHOS) - __asm__ __volatile__ ( - "mr %%r12, %0" - :: "r"(ObjFWRTBase) : "r12" - ); - - return __extension__ ((Class _Nullable (*)(id _Nullable, Class _Nonnull))*(void **)(((uintptr_t)ObjFWRTBase) - 358))(object, class); -#endif -} - -const char *_Nullable -object_getClassName(id _Nullable object) -{ -#if defined(OF_AMIGAOS_M68K) - register struct Library *a6 __asm__("a6") = ObjFWRTBase; - (void)a6; - return ((const char *_Nullable (*)(id _Nullable __asm__("a0")))(((uintptr_t)ObjFWRTBase) - 366))(object); -#elif defined(OF_MORPHOS) - __asm__ __volatile__ ( - "mr %%r12, %0" - :: "r"(ObjFWRTBase) : "r12" - ); - - return __extension__ ((const char *_Nullable (*)(id _Nullable))*(void **)(((uintptr_t)ObjFWRTBase) - 364))(object); -#endif -} - -const char *_Nonnull -protocol_getName(Protocol *_Nonnull protocol) -{ -#if defined(OF_AMIGAOS_M68K) - register struct Library *a6 __asm__("a6") = ObjFWRTBase; - (void)a6; - return ((const char *_Nonnull (*)(Protocol *_Nonnull __asm__("a0")))(((uintptr_t)ObjFWRTBase) - 372))(protocol); -#elif defined(OF_MORPHOS) - __asm__ __volatile__ ( - "mr %%r12, %0" - :: "r"(ObjFWRTBase) : "r12" - ); - - return __extension__ ((const char *_Nonnull (*)(Protocol *_Nonnull))*(void **)(((uintptr_t)ObjFWRTBase) - 370))(protocol); -#endif -} - -bool -protocol_isEqual(Protocol *_Nonnull protocol1, Protocol *_Nonnull protocol2) -{ -#if defined(OF_AMIGAOS_M68K) - register struct Library *a6 __asm__("a6") = ObjFWRTBase; - (void)a6; - return ((bool (*)(Protocol *_Nonnull __asm__("a0"), Protocol *_Nonnull __asm__("a1")))(((uintptr_t)ObjFWRTBase) - 378))(protocol1, protocol2); -#elif defined(OF_MORPHOS) - __asm__ __volatile__ ( - "mr %%r12, %0" - :: "r"(ObjFWRTBase) : "r12" - ); - - return __extension__ ((bool (*)(Protocol *_Nonnull, Protocol *_Nonnull))*(void **)(((uintptr_t)ObjFWRTBase) - 376))(protocol1, protocol2); -#endif -} - -bool -protocol_conformsToProtocol(Protocol *_Nonnull protocol1, Protocol *_Nonnull protocol2) -{ -#if defined(OF_AMIGAOS_M68K) - register struct Library *a6 __asm__("a6") = ObjFWRTBase; - (void)a6; - return ((bool (*)(Protocol *_Nonnull __asm__("a0"), Protocol *_Nonnull __asm__("a1")))(((uintptr_t)ObjFWRTBase) - 384))(protocol1, protocol2); -#elif defined(OF_MORPHOS) - __asm__ __volatile__ ( - "mr %%r12, %0" - :: "r"(ObjFWRTBase) : "r12" - ); - - return __extension__ ((bool (*)(Protocol *_Nonnull, Protocol *_Nonnull))*(void **)(((uintptr_t)ObjFWRTBase) - 382))(protocol1, protocol2); -#endif -} - -_Nullable objc_uncaught_exception_handler -objc_setUncaughtExceptionHandler(objc_uncaught_exception_handler _Nullable handler) -{ -#if defined(OF_AMIGAOS_M68K) - register struct Library *a6 __asm__("a6") = ObjFWRTBase; - (void)a6; - return ((_Nullable objc_uncaught_exception_handler (*)(objc_uncaught_exception_handler _Nullable __asm__("a0")))(((uintptr_t)ObjFWRTBase) - 390))(handler); -#elif defined(OF_MORPHOS) - __asm__ __volatile__ ( - "mr %%r12, %0" - :: "r"(ObjFWRTBase) : "r12" - ); - - return __extension__ ((_Nullable objc_uncaught_exception_handler (*)(objc_uncaught_exception_handler _Nullable))*(void **)(((uintptr_t)ObjFWRTBase) - 388))(handler); -#endif -} - -void -objc_setForwardHandler(IMP _Nullable forward, IMP _Nullable stretForward) -{ -#if defined(OF_AMIGAOS_M68K) - register struct Library *a6 __asm__("a6") = ObjFWRTBase; - (void)a6; - ((void (*)(IMP _Nullable __asm__("a0"), IMP _Nullable __asm__("a1")))(((uintptr_t)ObjFWRTBase) - 396))(forward, stretForward); -#elif defined(OF_MORPHOS) - __asm__ __volatile__ ( - "mr %%r12, %0" - :: "r"(ObjFWRTBase) : "r12" - ); - - __extension__ ((void (*)(IMP _Nullable, IMP _Nullable))*(void **)(((uintptr_t)ObjFWRTBase) - 394))(forward, stretForward); -#endif -} - -void -objc_setEnumerationMutationHandler(objc_enumeration_mutation_handler _Nullable hadler) -{ -#if defined(OF_AMIGAOS_M68K) - register struct Library *a6 __asm__("a6") = ObjFWRTBase; - (void)a6; - ((void (*)(objc_enumeration_mutation_handler _Nullable __asm__("a0")))(((uintptr_t)ObjFWRTBase) - 402))(hadler); -#elif defined(OF_MORPHOS) - __asm__ __volatile__ ( - "mr %%r12, %0" - :: "r"(ObjFWRTBase) : "r12" - ); - - __extension__ ((void (*)(objc_enumeration_mutation_handler _Nullable))*(void **)(((uintptr_t)ObjFWRTBase) - 400))(hadler); -#endif -} - -id _Nullable -objc_constructInstance(Class _Nullable class, void *_Nullable bytes) -{ -#if defined(OF_AMIGAOS_M68K) - register struct Library *a6 __asm__("a6") = ObjFWRTBase; - (void)a6; - return ((id _Nullable (*)(Class _Nullable __asm__("a0"), void *_Nullable __asm__("a1")))(((uintptr_t)ObjFWRTBase) - 408))(class, bytes); -#elif defined(OF_MORPHOS) - __asm__ __volatile__ ( - "mr %%r12, %0" - :: "r"(ObjFWRTBase) : "r12" - ); - - return __extension__ ((id _Nullable (*)(Class _Nullable, void *_Nullable))*(void **)(((uintptr_t)ObjFWRTBase) - 406))(class, bytes); -#endif -} - -void -objc_deinit() -{ -#if defined(OF_AMIGAOS_M68K) - register struct Library *a6 __asm__("a6") = ObjFWRTBase; - (void)a6; - ((void (*)())(((uintptr_t)ObjFWRTBase) - 414))(); -#elif defined(OF_MORPHOS) - __asm__ __volatile__ ( - "mr %%r12, %0" - :: "r"(ObjFWRTBase) : "r12" - ); - - __extension__ ((void (*)())*(void **)(((uintptr_t)ObjFWRTBase) - 412))(); -#endif -} - -Ivar _Nullable *_Nullable -class_copyIvarList(Class _Nullable class, unsigned int *_Nullable outCount) -{ -#if defined(OF_AMIGAOS_M68K) - register struct Library *a6 __asm__("a6") = ObjFWRTBase; - (void)a6; - return ((Ivar _Nullable *_Nullable (*)(Class _Nullable __asm__("a0"), unsigned int *_Nullable __asm__("a1")))(((uintptr_t)ObjFWRTBase) - 420))(class, outCount); -#elif defined(OF_MORPHOS) - __asm__ __volatile__ ( - "mr %%r12, %0" - :: "r"(ObjFWRTBase) : "r12" - ); - - return __extension__ ((Ivar _Nullable *_Nullable (*)(Class _Nullable, unsigned int *_Nullable))*(void **)(((uintptr_t)ObjFWRTBase) - 418))(class, outCount); -#endif -} - -const char *_Nonnull -ivar_getName(Ivar _Nonnull ivar) -{ -#if defined(OF_AMIGAOS_M68K) - register struct Library *a6 __asm__("a6") = ObjFWRTBase; - (void)a6; - return ((const char *_Nonnull (*)(Ivar _Nonnull __asm__("a0")))(((uintptr_t)ObjFWRTBase) - 426))(ivar); -#elif defined(OF_MORPHOS) - __asm__ __volatile__ ( - "mr %%r12, %0" - :: "r"(ObjFWRTBase) : "r12" - ); - - return __extension__ ((const char *_Nonnull (*)(Ivar _Nonnull))*(void **)(((uintptr_t)ObjFWRTBase) - 424))(ivar); -#endif -} - -const char *_Nonnull -ivar_getTypeEncoding(Ivar _Nonnull ivar) -{ -#if defined(OF_AMIGAOS_M68K) - register struct Library *a6 __asm__("a6") = ObjFWRTBase; - (void)a6; - return ((const char *_Nonnull (*)(Ivar _Nonnull __asm__("a0")))(((uintptr_t)ObjFWRTBase) - 432))(ivar); -#elif defined(OF_MORPHOS) - __asm__ __volatile__ ( - "mr %%r12, %0" - :: "r"(ObjFWRTBase) : "r12" - ); - - return __extension__ ((const char *_Nonnull (*)(Ivar _Nonnull))*(void **)(((uintptr_t)ObjFWRTBase) - 430))(ivar); -#endif -} - -ptrdiff_t -ivar_getOffset(Ivar _Nonnull ivar) -{ -#if defined(OF_AMIGAOS_M68K) - register struct Library *a6 __asm__("a6") = ObjFWRTBase; - (void)a6; - return ((ptrdiff_t (*)(Ivar _Nonnull __asm__("a0")))(((uintptr_t)ObjFWRTBase) - 438))(ivar); -#elif defined(OF_MORPHOS) - __asm__ __volatile__ ( - "mr %%r12, %0" - :: "r"(ObjFWRTBase) : "r12" - ); - - return __extension__ ((ptrdiff_t (*)(Ivar _Nonnull))*(void **)(((uintptr_t)ObjFWRTBase) - 436))(ivar); -#endif -} - -Method _Nullable *_Nullable -class_copyMethodList(Class _Nullable class, unsigned int *_Nullable outCount) -{ -#if defined(OF_AMIGAOS_M68K) - register struct Library *a6 __asm__("a6") = ObjFWRTBase; - (void)a6; - return ((Method _Nullable *_Nullable (*)(Class _Nullable __asm__("a0"), unsigned int *_Nullable __asm__("a1")))(((uintptr_t)ObjFWRTBase) - 444))(class, outCount); -#elif defined(OF_MORPHOS) - __asm__ __volatile__ ( - "mr %%r12, %0" - :: "r"(ObjFWRTBase) : "r12" - ); - - return __extension__ ((Method _Nullable *_Nullable (*)(Class _Nullable, unsigned int *_Nullable))*(void **)(((uintptr_t)ObjFWRTBase) - 442))(class, outCount); -#endif -} - -SEL _Nonnull -method_getName(Method _Nonnull method) -{ -#if defined(OF_AMIGAOS_M68K) - register struct Library *a6 __asm__("a6") = ObjFWRTBase; - (void)a6; - return ((SEL _Nonnull (*)(Method _Nonnull __asm__("a0")))(((uintptr_t)ObjFWRTBase) - 450))(method); -#elif defined(OF_MORPHOS) - __asm__ __volatile__ ( - "mr %%r12, %0" - :: "r"(ObjFWRTBase) : "r12" - ); - - return __extension__ ((SEL _Nonnull (*)(Method _Nonnull))*(void **)(((uintptr_t)ObjFWRTBase) - 448))(method); -#endif -} - -const char *_Nullable -method_getTypeEncoding(Method _Nonnull method) -{ -#if defined(OF_AMIGAOS_M68K) - register struct Library *a6 __asm__("a6") = ObjFWRTBase; - (void)a6; - return ((const char *_Nullable (*)(Method _Nonnull __asm__("a0")))(((uintptr_t)ObjFWRTBase) - 456))(method); -#elif defined(OF_MORPHOS) - __asm__ __volatile__ ( - "mr %%r12, %0" - :: "r"(ObjFWRTBase) : "r12" - ); - - return __extension__ ((const char *_Nullable (*)(Method _Nonnull))*(void **)(((uintptr_t)ObjFWRTBase) - 454))(method); -#endif -} - -objc_property_t _Nullable *_Nullable -class_copyPropertyList(Class _Nullable class, unsigned int *_Nullable outCount) -{ -#if defined(OF_AMIGAOS_M68K) - register struct Library *a6 __asm__("a6") = ObjFWRTBase; - (void)a6; - return ((objc_property_t _Nullable *_Nullable (*)(Class _Nullable __asm__("a0"), unsigned int *_Nullable __asm__("a1")))(((uintptr_t)ObjFWRTBase) - 462))(class, outCount); -#elif defined(OF_MORPHOS) - __asm__ __volatile__ ( - "mr %%r12, %0" - :: "r"(ObjFWRTBase) : "r12" - ); - - return __extension__ ((objc_property_t _Nullable *_Nullable (*)(Class _Nullable, unsigned int *_Nullable))*(void **)(((uintptr_t)ObjFWRTBase) - 460))(class, outCount); -#endif -} - -const char *_Nonnull -property_getName(objc_property_t _Nonnull property) -{ -#if defined(OF_AMIGAOS_M68K) - register struct Library *a6 __asm__("a6") = ObjFWRTBase; - (void)a6; - return ((const char *_Nonnull (*)(objc_property_t _Nonnull __asm__("a0")))(((uintptr_t)ObjFWRTBase) - 468))(property); -#elif defined(OF_MORPHOS) - __asm__ __volatile__ ( - "mr %%r12, %0" - :: "r"(ObjFWRTBase) : "r12" - ); - - return __extension__ ((const char *_Nonnull (*)(objc_property_t _Nonnull))*(void **)(((uintptr_t)ObjFWRTBase) - 466))(property); -#endif -} - -char *_Nullable -property_copyAttributeValue(objc_property_t _Nonnull property, const char *_Nonnull name) -{ -#if defined(OF_AMIGAOS_M68K) - register struct Library *a6 __asm__("a6") = ObjFWRTBase; - (void)a6; - return ((char *_Nullable (*)(objc_property_t _Nonnull __asm__("a0"), const char *_Nonnull __asm__("a1")))(((uintptr_t)ObjFWRTBase) - 474))(property, name); -#elif defined(OF_MORPHOS) - __asm__ __volatile__ ( - "mr %%r12, %0" - :: "r"(ObjFWRTBase) : "r12" - ); - - return __extension__ ((char *_Nullable (*)(objc_property_t _Nonnull, const char *_Nonnull))*(void **)(((uintptr_t)ObjFWRTBase) - 472))(property, name); -#endif -} - -void *_Nullable -objc_destructInstance(id _Nullable object) -{ -#if defined(OF_AMIGAOS_M68K) - register struct Library *a6 __asm__("a6") = ObjFWRTBase; - (void)a6; - return ((void *_Nullable (*)(id _Nullable __asm__("a0")))(((uintptr_t)ObjFWRTBase) - 480))(object); -#elif defined(OF_MORPHOS) - __asm__ __volatile__ ( - "mr %%r12, %0" - :: "r"(ObjFWRTBase) : "r12" - ); - - return __extension__ ((void *_Nullable (*)(id _Nullable))*(void **)(((uintptr_t)ObjFWRTBase) - 478))(object); -#endif -} - -void *_Null_unspecified -objc_autoreleasePoolPush() -{ -#if defined(OF_AMIGAOS_M68K) - register struct Library *a6 __asm__("a6") = ObjFWRTBase; - (void)a6; - return ((void *_Null_unspecified (*)())(((uintptr_t)ObjFWRTBase) - 486))(); -#elif defined(OF_MORPHOS) - __asm__ __volatile__ ( - "mr %%r12, %0" - :: "r"(ObjFWRTBase) : "r12" - ); - - return __extension__ ((void *_Null_unspecified (*)())*(void **)(((uintptr_t)ObjFWRTBase) - 484))(); -#endif -} - -void -objc_autoreleasePoolPop(void *_Null_unspecified pool) -{ -#if defined(OF_AMIGAOS_M68K) - register struct Library *a6 __asm__("a6") = ObjFWRTBase; - (void)a6; - ((void (*)(void *_Null_unspecified __asm__("a0")))(((uintptr_t)ObjFWRTBase) - 492))(pool); -#elif defined(OF_MORPHOS) - __asm__ __volatile__ ( - "mr %%r12, %0" - :: "r"(ObjFWRTBase) : "r12" - ); - - __extension__ ((void (*)(void *_Null_unspecified))*(void **)(((uintptr_t)ObjFWRTBase) - 490))(pool); -#endif -} - -id _Nullable -_objc_rootAutorelease(id _Nullable object) -{ -#if defined(OF_AMIGAOS_M68K) - register struct Library *a6 __asm__("a6") = ObjFWRTBase; - (void)a6; - return ((id _Nullable (*)(id _Nullable __asm__("a0")))(((uintptr_t)ObjFWRTBase) - 498))(object); -#elif defined(OF_MORPHOS) - __asm__ __volatile__ ( - "mr %%r12, %0" - :: "r"(ObjFWRTBase) : "r12" - ); - - return __extension__ ((id _Nullable (*)(id _Nullable))*(void **)(((uintptr_t)ObjFWRTBase) - 496))(object); -#endif -} - -struct objc_hashtable *_Nonnull -objc_hashtable_new(objc_hashtable_hash_func hash, objc_hashtable_equal_func equal, uint32_t size) -{ -#if defined(OF_AMIGAOS_M68K) - register struct Library *a6 __asm__("a6") = ObjFWRTBase; - (void)a6; - return ((struct objc_hashtable *_Nonnull (*)(objc_hashtable_hash_func __asm__("a0"), objc_hashtable_equal_func __asm__("a1"), uint32_t __asm__("d0")))(((uintptr_t)ObjFWRTBase) - 504))(hash, equal, size); -#elif defined(OF_MORPHOS) - __asm__ __volatile__ ( - "mr %%r12, %0" - :: "r"(ObjFWRTBase) : "r12" - ); - - return __extension__ ((struct objc_hashtable *_Nonnull (*)(objc_hashtable_hash_func, objc_hashtable_equal_func, uint32_t))*(void **)(((uintptr_t)ObjFWRTBase) - 502))(hash, equal, size); -#endif -} - -void -objc_hashtable_set(struct objc_hashtable *_Nonnull table, const void *_Nonnull key, const void *_Nonnull object) -{ -#if defined(OF_AMIGAOS_M68K) - register struct Library *a6 __asm__("a6") = ObjFWRTBase; - (void)a6; - ((void (*)(struct objc_hashtable *_Nonnull __asm__("a0"), const void *_Nonnull __asm__("a1"), const void *_Nonnull __asm__("a2")))(((uintptr_t)ObjFWRTBase) - 510))(table, key, object); -#elif defined(OF_MORPHOS) - __asm__ __volatile__ ( - "mr %%r12, %0" - :: "r"(ObjFWRTBase) : "r12" - ); - - __extension__ ((void (*)(struct objc_hashtable *_Nonnull, const void *_Nonnull, const void *_Nonnull))*(void **)(((uintptr_t)ObjFWRTBase) - 508))(table, key, object); -#endif -} - -void *_Nullable -objc_hashtable_get(struct objc_hashtable *_Nonnull table, const void *_Nonnull key) -{ -#if defined(OF_AMIGAOS_M68K) - register struct Library *a6 __asm__("a6") = ObjFWRTBase; - (void)a6; - return ((void *_Nullable (*)(struct objc_hashtable *_Nonnull __asm__("a0"), const void *_Nonnull __asm__("a1")))(((uintptr_t)ObjFWRTBase) - 516))(table, key); -#elif defined(OF_MORPHOS) - __asm__ __volatile__ ( - "mr %%r12, %0" - :: "r"(ObjFWRTBase) : "r12" - ); - - return __extension__ ((void *_Nullable (*)(struct objc_hashtable *_Nonnull, const void *_Nonnull))*(void **)(((uintptr_t)ObjFWRTBase) - 514))(table, key); -#endif -} - -void -objc_hashtable_delete(struct objc_hashtable *_Nonnull table, const void *_Nonnull key) -{ -#if defined(OF_AMIGAOS_M68K) - register struct Library *a6 __asm__("a6") = ObjFWRTBase; - (void)a6; - ((void (*)(struct objc_hashtable *_Nonnull __asm__("a0"), const void *_Nonnull __asm__("a1")))(((uintptr_t)ObjFWRTBase) - 522))(table, key); -#elif defined(OF_MORPHOS) - __asm__ __volatile__ ( - "mr %%r12, %0" - :: "r"(ObjFWRTBase) : "r12" - ); - - __extension__ ((void (*)(struct objc_hashtable *_Nonnull, const void *_Nonnull))*(void **)(((uintptr_t)ObjFWRTBase) - 520))(table, key); -#endif -} - -void -objc_hashtable_free(struct objc_hashtable *_Nonnull table) -{ -#if defined(OF_AMIGAOS_M68K) - register struct Library *a6 __asm__("a6") = ObjFWRTBase; - (void)a6; - ((void (*)(struct objc_hashtable *_Nonnull __asm__("a0")))(((uintptr_t)ObjFWRTBase) - 528))(table); -#elif defined(OF_MORPHOS) - __asm__ __volatile__ ( - "mr %%r12, %0" - :: "r"(ObjFWRTBase) : "r12" - ); - - __extension__ ((void (*)(struct objc_hashtable *_Nonnull))*(void **)(((uintptr_t)ObjFWRTBase) - 526))(table); -#endif -} - -void -objc_setTaggedPointerSecret(uintptr_t secret) -{ -#if defined(OF_AMIGAOS_M68K) - register struct Library *a6 __asm__("a6") = ObjFWRTBase; - (void)a6; - ((void (*)(uintptr_t __asm__("d0")))(((uintptr_t)ObjFWRTBase) - 534))(secret); -#elif defined(OF_MORPHOS) - __asm__ __volatile__ ( - "mr %%r12, %0" - :: "r"(ObjFWRTBase) : "r12" - ); - - __extension__ ((void (*)(uintptr_t))*(void **)(((uintptr_t)ObjFWRTBase) - 532))(secret); -#endif -} - -int -objc_registerTaggedPointerClass(Class _Nonnull class) -{ -#if defined(OF_AMIGAOS_M68K) - register struct Library *a6 __asm__("a6") = ObjFWRTBase; - (void)a6; - return ((int (*)(Class _Nonnull __asm__("a0")))(((uintptr_t)ObjFWRTBase) - 540))(class); -#elif defined(OF_MORPHOS) - __asm__ __volatile__ ( - "mr %%r12, %0" - :: "r"(ObjFWRTBase) : "r12" - ); - - return __extension__ ((int (*)(Class _Nonnull))*(void **)(((uintptr_t)ObjFWRTBase) - 538))(class); -#endif -} - -bool -object_isTaggedPointer(id _Nullable object) -{ -#if defined(OF_AMIGAOS_M68K) - register struct Library *a6 __asm__("a6") = ObjFWRTBase; - (void)a6; - return ((bool (*)(id _Nullable __asm__("a0")))(((uintptr_t)ObjFWRTBase) - 546))(object); -#elif defined(OF_MORPHOS) - __asm__ __volatile__ ( - "mr %%r12, %0" - :: "r"(ObjFWRTBase) : "r12" - ); - - return __extension__ ((bool (*)(id _Nullable))*(void **)(((uintptr_t)ObjFWRTBase) - 544))(object); -#endif -} - -uintptr_t -object_getTaggedPointerValue(id _Nonnull object) -{ -#if defined(OF_AMIGAOS_M68K) - register struct Library *a6 __asm__("a6") = ObjFWRTBase; - (void)a6; - return ((uintptr_t (*)(id _Nonnull __asm__("a0")))(((uintptr_t)ObjFWRTBase) - 552))(object); -#elif defined(OF_MORPHOS) - __asm__ __volatile__ ( - "mr %%r12, %0" - :: "r"(ObjFWRTBase) : "r12" - ); - - return __extension__ ((uintptr_t (*)(id _Nonnull))*(void **)(((uintptr_t)ObjFWRTBase) - 550))(object); -#endif -} - -id _Nullable -objc_createTaggedPointer(int class, uintptr_t value) -{ -#if defined(OF_AMIGAOS_M68K) - register struct Library *a6 __asm__("a6") = ObjFWRTBase; - (void)a6; - return ((id _Nullable (*)(int __asm__("d0"), uintptr_t __asm__("d1")))(((uintptr_t)ObjFWRTBase) - 558))(class, value); -#elif defined(OF_MORPHOS) - __asm__ __volatile__ ( - "mr %%r12, %0" - :: "r"(ObjFWRTBase) : "r12" - ); - - return __extension__ ((id _Nullable (*)(int, uintptr_t))*(void **)(((uintptr_t)ObjFWRTBase) - 556))(class, value); -#endif -} Index: src/runtime/lookup-asm/Makefile ================================================================== --- src/runtime/lookup-asm/Makefile +++ src/runtime/lookup-asm/Makefile @@ -1,12 +1,10 @@ include ../../../extra.mk STATIC_PIC_LIB_NOINST = ${LOOKUP_ASM_LIB_A} -STATIC_AMIGA_LIB_NOINST = ${LOOKUP_ASM_AMIGALIB_A} STATIC_LIB_NOINST = ${LOOKUP_ASM_A} SRCS = lookup-asm.S include ../../../buildsys.mk ASFLAGS += -I../../.. -I../.. -ASFLAGS_lookup-asm.amigalib.o += -DOF_BASEREL ADDED src/runtime/lookup-asm/lookup-asm-amd64-elf.S Index: src/runtime/lookup-asm/lookup-asm-amd64-elf.S ================================================================== --- /dev/null +++ src/runtime/lookup-asm/lookup-asm-amd64-elf.S @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2008-2024 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#include "config.h" + +#include "platform.h" + +.globl objc_msg_lookup +.globl objc_msg_lookup_stret +.globl objc_msg_lookup_super +.globl objc_msg_lookup_super_stret + +.section .text +.macro GENERATE_LOOKUP name notFound +\name: + testq %rdi, %rdi + jz .LreturnNilMethod + + testb $1, %dil + jnz .LtaggedPointer_\name + + movq (%rdi), %r8 + movq 64(%r8), %r8 + +.Lmain_\name: + movq (%rsi), %rax + movzbl %ah, %ecx + movzbl %al, %edx +#ifdef OF_SELUID24 + shrl $16, %eax + + movq (%r8,%rax,8), %r8 +#endif + movq (%r8,%rcx,8), %r8 + movq (%r8,%rdx,8), %rax + + testq %rax, %rax + jz \notFound@PLT + + ret + +.LtaggedPointer_\name: + movq objc_taggedPointerSecret@GOTPCREL(%rip), %rax + xorq (%rax), %rdi + andb $0xE, %dil + movzbl %dil, %r8d + + movq objc_taggedPointerClasses@GOTPCREL(%rip), %rax + movq (%rax,%r8,4), %r8 + movq 64(%r8), %r8 + + jmp .Lmain_\name +.type \name, %function +.size \name, .-\name +.endm + +.macro GENERATE_LOOKUP_SUPER name lookup +\name: + movq %rdi, %r8 + movq (%rdi), %rdi + testq %rdi, %rdi + jz .LreturnNilMethod + + movq 8(%r8), %r8 + movq 64(%r8), %r8 + jmp .Lmain_\lookup +.type \name, %function +.size \name, .-\name +.endm + +GENERATE_LOOKUP objc_msg_lookup objc_methodNotFound +GENERATE_LOOKUP objc_msg_lookup_stret objc_methodNotFound_stret +GENERATE_LOOKUP_SUPER objc_msg_lookup_super objc_msg_lookup +GENERATE_LOOKUP_SUPER objc_msg_lookup_super_stret objc_msg_lookup_stret + +.LreturnNilMethod: + leaq .LnilMethod(%rip), %rax + ret + +.LnilMethod: + xorq %rax, %rax + ret + +#if defined(OF_LINUX) || defined(OF_HAIKU) || defined(OF_HURD) +.section .note.GNU-stack, "", %progbits +#endif ADDED src/runtime/lookup-asm/lookup-asm-amd64-macho.S Index: src/runtime/lookup-asm/lookup-asm-amd64-macho.S ================================================================== --- /dev/null +++ src/runtime/lookup-asm/lookup-asm-amd64-macho.S @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2008-2024 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#include "config.h" + +.globl _objc_msg_lookup +.globl _objc_msg_lookup_stret +.globl _objc_msg_lookup_super +.globl _objc_msg_lookup_super_stret + +.section __TEXT, __text, regular, pure_instructions +.macro GENERATE_LOOKUP +$0: + testq %rdi, %rdi + jz LreturnNilMethod + + testb $$1, %dil + jnz LtaggedPointer_$0 + + movq (%rdi), %r8 + movq 64(%r8), %r8 + +Lmain_$0: + movq (%rsi), %rax + movzbl %ah, %ecx + movzbl %al, %edx +#ifdef OF_SELUID24 + shrl $$16, %eax + + movq (%r8,%rax,8), %r8 +#endif + movq (%r8,%rcx,8), %r8 + movq (%r8,%rdx,8), %rax + + testq %rax, %rax + jz $1 + + ret + +LtaggedPointer_$0: + movq _objc_taggedPointerSecret@GOTPCREL(%rip), %rax + xorq (%rax), %rdi + andb $$0xE, %dil + movzbl %dil, %r8d + + movq _objc_taggedPointerClasses@GOTPCREL(%rip), %rax + movq (%rax,%r8,4), %r8 + movq 64(%r8), %r8 + + jmp Lmain_$0 +.endmacro + +.macro GENERATE_LOOKUP_SUPER +$0: + movq %rdi, %r8 + movq (%rdi), %rdi + testq %rdi, %rdi + jz LreturnNilMethod + + movq 8(%r8), %r8 + movq 64(%r8), %r8 + jmp Lmain_$1 +.endmacro + +GENERATE_LOOKUP _objc_msg_lookup, _objc_methodNotFound +GENERATE_LOOKUP _objc_msg_lookup_stret, _objc_methodNotFound_stret +GENERATE_LOOKUP_SUPER _objc_msg_lookup_super, _objc_msg_lookup +GENERATE_LOOKUP_SUPER _objc_msg_lookup_super_stret, _objc_msg_lookup_stret + +LreturnNilMethod: + leaq LnilMethod(%rip), %rax + ret + +LnilMethod: + xorq %rax, %rax + ret ADDED src/runtime/lookup-asm/lookup-asm-amd64-win64.S Index: src/runtime/lookup-asm/lookup-asm-amd64-win64.S ================================================================== --- /dev/null +++ src/runtime/lookup-asm/lookup-asm-amd64-win64.S @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2008-2024 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#include "config.h" + +.globl objc_msg_lookup +.globl objc_msg_lookup_stret +.globl objc_msg_lookup_super +.globl objc_msg_lookup_super_stret + +.section .text +.macro GENERATE_LOOKUP name notFound +\name: + testq %rcx, %rcx + jz .LreturnNilMethod + + testb $1, %cl + jnz .LtaggedPointer_\name + + movq (%rcx), %r8 + movq 56(%r8), %r8 + +.Lmain_\name: + movq %rcx, %r10 + movq %rdx, %r11 + + movq (%rdx), %rax + movzbl %ah, %ecx + movzbl %al, %edx +#ifdef OF_SELUID24 + shrl $16, %eax + + movq (%r8,%rax,8), %r8 +#endif + movq (%r8,%rcx,8), %r8 + movq (%r8,%rdx,8), %rax + + testq %rax, %rax + jz 0f + + ret + +0: + movq %r10, %rcx + movq %r11, %rdx + jmp \notFound + +.LtaggedPointer_\name: + xorq objc_taggedPointerSecret(%rip), %rcx + andb $0xE, %cl + movzbl %cl, %r8d + + leaq objc_taggedPointerClasses(%rip), %rax + movq (%rax,%r8,4), %r8 + movq 56(%r8), %r8 + + jmp .Lmain_\name +.def \name +.scl 2 +.type 32 +.endef +.endm + +.macro GENERATE_LOOKUP_SUPER name lookup +\name: + movq %rcx, %r8 + movq (%rcx), %rcx + testq %rcx, %rcx + jz .LreturnNilMethod + + movq 8(%r8), %r8 + movq 56(%r8), %r8 + jmp .Lmain_\lookup +.def \name +.scl 2 +.type 32 +.endef +.endm + +GENERATE_LOOKUP objc_msg_lookup objc_methodNotFound +GENERATE_LOOKUP objc_msg_lookup_stret objc_methodNotFound_stret +GENERATE_LOOKUP_SUPER objc_msg_lookup_super objc_msg_lookup +GENERATE_LOOKUP_SUPER objc_msg_lookup_super_stret objc_msg_lookup_stret + +.LreturnNilMethod: + leaq .LnilMethod(%rip), %rax + ret + +.LnilMethod: + xorq %rax, %rax + ret 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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 @@ .section .text .macro GENERATE_LOOKUP name notFound \name: cmp r0, #0 - beq returnNilMethod + beq .LreturnNilMethod tst r0, #1 bne .LtaggedPointer_\name ldr r2, [r0, #0] @@ -90,11 +90,11 @@ .macro GENERATE_LOOKUP_SUPER name lookup \name: mov r2, r0 ldr r0, [r0, #0] cmp r0, #0 - beq returnNilMethod + beq .LreturnNilMethod ldr r2, [r2, #4] ldr r2, [r2, #32] b .Lmain_\lookup @@ -105,16 +105,16 @@ GENERATE_LOOKUP objc_msg_lookup objc_methodNotFound GENERATE_LOOKUP objc_msg_lookup_stret objc_methodNotFound_stret GENERATE_LOOKUP_SUPER objc_msg_lookup_super objc_msg_lookup GENERATE_LOOKUP_SUPER objc_msg_lookup_super_stret objc_msg_lookup_stret -returnNilMethod: - adr r0, nilMethod +.LreturnNilMethod: + adr r0, .LnilMethod bx lr -nilMethod: +.LnilMethod: mov r0, #0 bx lr -#ifdef OF_LINUX +#if defined(OF_LINUX) || defined(OF_HAIKU) || defined(OF_HURD) .section .note.GNU-stack, "", %progbits #endif 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -23,11 +23,11 @@ .globl objc_msg_lookup_super_stret .section .text .macro GENERATE_LOOKUP name notFound \name: - cbz x0, returnNilMethod + cbz x0, .LreturnNilMethod tst x0, #1 b.ne .LtaggedPointer_\name ldr x2, [x0] @@ -68,11 +68,11 @@ .macro GENERATE_LOOKUP_SUPER name lookup \name: mov x2, x0 ldr x0, [x0] - cbz x0, returnNilMethod + cbz x0, .LreturnNilMethod ldr x2, [x2, #8] ldr x2, [x2, #64] b .Lmain_\lookup @@ -83,16 +83,16 @@ GENERATE_LOOKUP objc_msg_lookup objc_methodNotFound GENERATE_LOOKUP objc_msg_lookup_stret objc_methodNotFound_stret GENERATE_LOOKUP_SUPER objc_msg_lookup_super objc_msg_lookup GENERATE_LOOKUP_SUPER objc_msg_lookup_super_stret objc_msg_lookup_stret -returnNilMethod: - adr x0, nilMethod +.LreturnNilMethod: + adr x0, .LnilMethod ret -nilMethod: +.LnilMethod: mov x0, #0 ret -#ifdef OF_LINUX +#if defined(OF_LINUX) || defined(OF_HAIKU) || defined(OF_HURD) .section .note.GNU-stack, "", %progbits #endif 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -72,13 +72,13 @@ move $v0, $t0 jr $ra 0: #ifdef OF_PIC - addiu $v0, $t9, nilMethod-\name + addiu $v0, $t9, .LnilMethod-\name #else - la $v0, nilMethod + la $v0, .LnilMethod #endif jr $ra #ifdef OF_PIC 1: @@ -134,13 +134,13 @@ addiu $t9, $t9, \lookup-\name b .Lmain_\lookup 0: #ifdef OF_PIC - addiu $v0, $t9, nilMethod-\name + addiu $v0, $t9, .LnilMethod-\name #else - la $v0, nilMethod + la $v0, .LnilMethod #endif jr $ra .type \name, %function .size \name, .-\name .endm @@ -148,12 +148,12 @@ GENERATE_LOOKUP objc_msg_lookup objc_methodNotFound GENERATE_LOOKUP objc_msg_lookup_stret objc_methodNotFound_stret GENERATE_LOOKUP_SUPER objc_msg_lookup_super objc_msg_lookup GENERATE_LOOKUP_SUPER objc_msg_lookup_super_stret objc_msg_lookup_stret -nilMethod: +.LnilMethod: move $v0, $zero jr $ra -#ifdef OF_LINUX +#if defined(OF_LINUX) || defined(OF_HAIKU) || defined(OF_HURD) .section .note.GNU-stack, "", %progbits #endif 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -70,11 +70,11 @@ 0: lui $v0, %hi(%neg(%gp_rel(\name))) daddiu $v0, $v0, %lo(%neg(%gp_rel(\name))) daddu $v0, $v0, $t9 - ld $v0, %got_disp(nilMethod)($v0) + ld $v0, %got_disp(.LnilMethod)($v0) jr $ra 1: lui $t0, %hi(%neg(%gp_rel(\name))) daddiu $t0, $t0, %lo(%neg(%gp_rel(\name))) @@ -117,11 +117,11 @@ 0: lui $v0, %hi(%neg(%gp_rel(\name))) daddiu $v0, $v0, %lo(%neg(%gp_rel(\name))) daddu $v0, $v0, $t9 - ld $v0, %got_disp(nilMethod)($v0) + ld $v0, %got_disp(.LnilMethod)($v0) jr $ra .type \name, %function .size \name, .-\name .endm @@ -128,12 +128,12 @@ GENERATE_LOOKUP objc_msg_lookup objc_methodNotFound GENERATE_LOOKUP objc_msg_lookup_stret objc_methodNotFound_stret GENERATE_LOOKUP_SUPER objc_msg_lookup_super objc_msg_lookup GENERATE_LOOKUP_SUPER objc_msg_lookup_super_stret objc_msg_lookup_stret -nilMethod: +.LnilMethod: move $v0, $zero jr $ra -#ifdef OF_LINUX +#if defined(OF_LINUX) || defined(OF_HAIKU) || defined(OF_HURD) .section .note.GNU-stack, "", %progbits #endif 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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 @@ .section .text .macro GENERATE_LOOKUP name notFound \name: cmpwi %r3, 0 - beq- returnNilMethod + beq- .LreturnNilMethod andi. %r0, %r3, 1 bne- .LtaggedPointer_\name lwz %r5, 0(%r3) @@ -122,11 +122,11 @@ .macro GENERATE_LOOKUP_SUPER name lookup \name: mr %r5, %r3 lwz %r3, 0(%r3) cmpwi %r3, 0 - beq- returnNilMethod + beq- .LreturnNilMethod lwz %r5, 4(%r5) lwz %r5, 32(%r5) b .Lmain_\lookup @@ -137,23 +137,23 @@ GENERATE_LOOKUP objc_msg_lookup objc_methodNotFound GENERATE_LOOKUP objc_msg_lookup_stret objc_methodNotFound_stret GENERATE_LOOKUP_SUPER objc_msg_lookup_super objc_msg_lookup GENERATE_LOOKUP_SUPER objc_msg_lookup_super_stret objc_msg_lookup_stret -returnNilMethod: +.LreturnNilMethod: mflr %r0 - bl getPC + bl .LgetPC mtlr %r0 0: - addi %r3, %r3, nilMethod-0b + addi %r3, %r3, .LnilMethod-0b blr -nilMethod: +.LnilMethod: li %r3, 0 blr -getPC: +.LgetPC: mflr %r3 blr #ifdef OF_PIC .section .got2, "aw" @@ -166,8 +166,8 @@ .long objc_taggedPointerSecret .Lgot_objc_taggedPointerClasses: .long objc_taggedPointerClasses #endif -#ifdef OF_LINUX +#if defined(OF_LINUX) || defined(OF_HAIKU) || defined(OF_HURD) .section .note.GNU-stack, "", @progbits #endif 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,32 +132,32 @@ GENERATE_LOOKUP objc_msg_lookup_stret objc_methodNotFound_stret GENERATE_LOOKUP_SUPER objc_msg_lookup_super objc_msg_lookup GENERATE_LOOKUP_SUPER objc_msg_lookup_super_stret objc_msg_lookup_stret .LreturnNilMethod: - addis %r3, %r2, nilMethod@toc@ha - addi %r3, %r3, nilMethod@toc@l + addis %r3, %r2, .LnilMethod@toc@ha + addi %r3, %r3, .LnilMethod@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 +.LnilMethod: + addis %r2, %r12, .TOC.-.LnilMethod@ha + addi %r2, %r2, .TOC.-.LnilMethod@l +.localentry .LnilMethod, .-.LnilMethod #else .section .opd, "aw", @progbits -nilMethod: +.LnilMethod: .p2align 3 .quad .Lbegin_nilMethod .quad .TOC.@tocbase .quad 0 .section .text #endif .Lbegin_nilMethod: li %r3, 0 blr -.type nilMethod, @function -.size nilMethod, .-.Lbegin_nilMethod +.type .LnilMethod, @function +.size .LnilMethod, .-.Lbegin_nilMethod -#ifdef OF_LINUX +#if defined(OF_LINUX) || defined(OF_HAIKU) || defined(OF_HURD) .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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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 @@ .section .text .macro GENERATE_LOOKUP name notFound \name: tst %o0 - bz returnNilMethod + bz .LreturnNilMethod btst 1, %o0 bnz .LtaggedPointer_\name nop ld [%o0], %o2 @@ -102,11 +102,11 @@ .macro GENERATE_LOOKUP_SUPER name lookup \name: mov %o0, %o2 ld [%o0], %o0 cmp %o0, 0 - be returnNilMethod + be .LreturnNilMethod nop ld [%o2 + 4], %o2 ba .Lmain_\lookup ld [%o2 + 32], %o2 @@ -117,33 +117,33 @@ GENERATE_LOOKUP objc_msg_lookup objc_methodNotFound GENERATE_LOOKUP objc_msg_lookup_stret objc_methodNotFound_stret GENERATE_LOOKUP_SUPER objc_msg_lookup_super objc_msg_lookup GENERATE_LOOKUP_SUPER objc_msg_lookup_super_stret objc_msg_lookup_stret -returnNilMethod: +.LreturnNilMethod: #ifdef OF_PIC mov %o7, %g1 sethi %hi(_GLOBAL_OFFSET_TABLE_ - 4), %o1 call 0f add %o1, %lo(_GLOBAL_OFFSET_TABLE_ + 4), %o1 0: add %o7, %o1, %o1 - sethi %hi(nilMethod), %o0 - or %o0, %lo(nilMethod), %o0 + sethi %hi(.LnilMethod), %o0 + or %o0, %lo(.LnilMethod), %o0 jmpl %g1 + 8, %g0 ld [%o1 + %o0], %o0 #else - sethi %hi(nilMethod), %o0 + sethi %hi(.LnilMethod), %o0 retl - or %o0, %lo(nilMethod), %o0 + or %o0, %lo(.LnilMethod), %o0 #endif -nilMethod: +.LnilMethod: retl clr %o0 -#ifdef OF_LINUX +#if defined(OF_LINUX) || defined(OF_HAIKU) || defined(OF_HURD) .section .note.GNU-stack, "", %progbits #endif 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -23,11 +23,11 @@ .globl objc_msg_lookup_super_stret .section .text .macro GENERATE_LOOKUP name notFound \name: - brz,pn %o0, returnNilMethod + brz,pn %o0, .LreturnNilMethod and %o0, 1, %o2 brnz,pn %o2, .LtaggedPointer_\name nop ldx [%o0], %o2 @@ -99,11 +99,11 @@ .macro GENERATE_LOOKUP_SUPER name lookup \name: mov %o0, %o2 ldx [%o0], %o0 - brz,pn %o0, returnNilMethod + brz,pn %o0, .LreturnNilMethod nop ldx [%o2 + 8], %o2 ba .Lmain_\lookup ldx [%o2 + 64], %o2 @@ -114,33 +114,33 @@ GENERATE_LOOKUP objc_msg_lookup objc_methodNotFound GENERATE_LOOKUP objc_msg_lookup_stret objc_methodNotFound_stret GENERATE_LOOKUP_SUPER objc_msg_lookup_super objc_msg_lookup GENERATE_LOOKUP_SUPER objc_msg_lookup_super_stret objc_msg_lookup_stret -returnNilMethod: +.LreturnNilMethod: #ifdef OF_PIC mov %o7, %g1 sethi %hi(_GLOBAL_OFFSET_TABLE_ - 4), %o1 call 0f or %o1, %lo(_GLOBAL_OFFSET_TABLE_ + 4), %o1 0: add %o7, %o1, %o1 - sethi %hi(nilMethod), %o0 - or %o0, %lo(nilMethod), %o0 + sethi %hi(.LnilMethod), %o0 + or %o0, %lo(.LnilMethod), %o0 jmpl %g1 + 8, %g0 ldx [%o1 + %o0], %o0 #else - sethi %hi(nilMethod), %o0 + sethi %hi(.LnilMethod), %o0 retl - or %o0, %lo(nilMethod), %o0 + or %o0, %lo(.LnilMethod), %o0 #endif -nilMethod: +.LnilMethod: retl clr %o0 -#ifdef OF_LINUX +#if defined(OF_LINUX) || defined(OF_HAIKU) || defined(OF_HURD) .section .note.GNU-stack, "", %progbits #endif 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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 @@ .section .text .macro GENERATE_LOOKUP name notFound \name: movl 4(%esp), %edx testl %edx, %edx - jz returnNilMethod + jz .LreturnNilMethod testb $1, %dl jnz .LtaggedPointer_\name movl (%edx), %edx @@ -51,25 +51,25 @@ jz 0f ret 0: - call getEIP + call .LgetEIP addl $_GLOBAL_OFFSET_TABLE_, %eax - lea \notFound@GOTOFF(%eax), %eax + movl \notFound@GOT(%eax), %eax jmp *%eax .LtaggedPointer_\name: - call getEIP + call .LgetEIP addl $_GLOBAL_OFFSET_TABLE_, %eax - leal objc_taggedPointerSecret@GOTOFF(%eax), %ecx + movl objc_taggedPointerSecret@GOT(%eax), %ecx xorl (%ecx), %edx andb $0xE, %dl movzbl %dl, %edx - leal objc_taggedPointerClasses@GOTOFF(%eax), %eax + movl objc_taggedPointerClasses@GOT(%eax), %eax movl (%eax,%edx,2), %edx movl 32(%edx), %edx jmp .Lmain_\name .type \name, %function @@ -79,11 +79,11 @@ .macro GENERATE_LOOKUP_SUPER name lookup \name: movl 4(%esp), %edx movl (%edx), %eax testl %eax, %eax - jz returnNilMethod + jz .LreturnNilMethod movl %eax, 4(%esp) mov 4(%edx), %edx mov 32(%edx), %edx jmp .Lmain_\lookup @@ -94,22 +94,22 @@ GENERATE_LOOKUP objc_msg_lookup objc_methodNotFound GENERATE_LOOKUP objc_msg_lookup_stret objc_methodNotFound_stret GENERATE_LOOKUP_SUPER objc_msg_lookup_super objc_msg_lookup GENERATE_LOOKUP_SUPER objc_msg_lookup_super_stret objc_msg_lookup_stret -returnNilMethod: - call getEIP +.LreturnNilMethod: + call .LgetEIP addl $_GLOBAL_OFFSET_TABLE_, %eax - leal nilMethod@GOTOFF(%eax), %eax + leal .LnilMethod@GOTOFF(%eax), %eax ret -nilMethod: +.LnilMethod: xorl %eax, %eax ret -getEIP: +.LgetEIP: movl (%esp), %eax ret -#ifdef OF_LINUX +#if defined(OF_LINUX) || defined(OF_HAIKU) || defined(OF_HURD) .section .note.GNU-stack, "", %progbits #endif 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -23,11 +23,11 @@ .section .text .macro GENERATE_LOOKUP name notFound \name: movl 4(%esp), %edx testl %edx, %edx - jz returnNilMethod + jz .LreturnNilMethod testb $1, %dl jnz .LtaggedPointer_\name movl (%edx), %edx @@ -68,11 +68,11 @@ .macro GENERATE_LOOKUP_SUPER name lookup \name: movl 4(%esp), %edx movl (%edx), %eax test %eax, %eax - jz returnNilMethod + jz .LreturnNilMethod movl %eax, 4(%esp) movl 4(%edx), %edx movl 32(%edx), %edx jmp .Lmain_\lookup @@ -85,12 +85,12 @@ GENERATE_LOOKUP _objc_msg_lookup _objc_methodNotFound GENERATE_LOOKUP _objc_msg_lookup_stret _objc_methodNotFound_stret GENERATE_LOOKUP_SUPER _objc_msg_lookup_super _objc_msg_lookup GENERATE_LOOKUP_SUPER _objc_msg_lookup_super_stret _objc_msg_lookup_stret -returnNilMethod: - movl $nilMethod, %eax +.LreturnNilMethod: + movl $.LnilMethod, %eax ret -nilMethod: +.LnilMethod: xorl %eax, %eax ret DELETED src/runtime/lookup-asm/lookup-asm-x86_64-elf.S Index: src/runtime/lookup-asm/lookup-asm-x86_64-elf.S ================================================================== --- src/runtime/lookup-asm/lookup-asm-x86_64-elf.S +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (c) 2008-2022 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#include "config.h" - -#include "platform.h" - -.globl objc_msg_lookup -.globl objc_msg_lookup_stret -.globl objc_msg_lookup_super -.globl objc_msg_lookup_super_stret - -.section .text -.macro GENERATE_LOOKUP name notFound -\name: - testq %rdi, %rdi - jz returnNilMethod - - testb $1, %dil - jnz .LtaggedPointer_\name - - movq (%rdi), %r8 - movq 64(%r8), %r8 - -.Lmain_\name: - movq (%rsi), %rax - movzbl %ah, %ecx - movzbl %al, %edx -#ifdef OF_SELUID24 - shrl $16, %eax - - movq (%r8,%rax,8), %r8 -#endif - movq (%r8,%rcx,8), %r8 - movq (%r8,%rdx,8), %rax - - testq %rax, %rax - jz \notFound@PLT - - ret - -.LtaggedPointer_\name: - movq objc_taggedPointerSecret@GOTPCREL(%rip), %rax - xorq (%rax), %rdi - andb $0xE, %dil - movzbl %dil, %r8d - - movq objc_taggedPointerClasses@GOTPCREL(%rip), %rax - movq (%rax,%r8,4), %r8 - movq 64(%r8), %r8 - - jmp .Lmain_\name -.type \name, %function -.size \name, .-\name -.endm - -.macro GENERATE_LOOKUP_SUPER name lookup -\name: - movq %rdi, %r8 - movq (%rdi), %rdi - testq %rdi, %rdi - jz returnNilMethod - - movq 8(%r8), %r8 - movq 64(%r8), %r8 - jmp .Lmain_\lookup -.type \name, %function -.size \name, .-\name -.endm - -GENERATE_LOOKUP objc_msg_lookup objc_methodNotFound -GENERATE_LOOKUP objc_msg_lookup_stret objc_methodNotFound_stret -GENERATE_LOOKUP_SUPER objc_msg_lookup_super objc_msg_lookup -GENERATE_LOOKUP_SUPER objc_msg_lookup_super_stret objc_msg_lookup_stret - -returnNilMethod: - leaq nilMethod(%rip), %rax - ret - -nilMethod: - xorq %rax, %rax - ret - -#ifdef OF_LINUX -.section .note.GNU-stack, "", %progbits -#endif DELETED src/runtime/lookup-asm/lookup-asm-x86_64-macho.S Index: src/runtime/lookup-asm/lookup-asm-x86_64-macho.S ================================================================== --- src/runtime/lookup-asm/lookup-asm-x86_64-macho.S +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (c) 2008-2022 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#include "config.h" - -.globl _objc_msg_lookup -.globl _objc_msg_lookup_stret -.globl _objc_msg_lookup_super -.globl _objc_msg_lookup_super_stret - -.section __TEXT, __text, regular, pure_instructions -.macro GENERATE_LOOKUP -$0: - testq %rdi, %rdi - jz returnNilMethod - - testb $$1, %dil - jnz LtaggedPointer_$0 - - movq (%rdi), %r8 - movq 64(%r8), %r8 - -Lmain_$0: - movq (%rsi), %rax - movzbl %ah, %ecx - movzbl %al, %edx -#ifdef OF_SELUID24 - shrl $$16, %eax - - movq (%r8,%rax,8), %r8 -#endif - movq (%r8,%rcx,8), %r8 - movq (%r8,%rdx,8), %rax - - testq %rax, %rax - jz $1 - - ret - -LtaggedPointer_$0: - movq _objc_taggedPointerSecret@GOTPCREL(%rip), %rax - xorq (%rax), %rdi - andb $$0xE, %dil - movzbl %dil, %r8d - - movq _objc_taggedPointerClasses@GOTPCREL(%rip), %rax - movq (%rax,%r8,4), %r8 - movq 64(%r8), %r8 - - jmp Lmain_$0 -.endmacro - -.macro GENERATE_LOOKUP_SUPER -$0: - movq %rdi, %r8 - movq (%rdi), %rdi - testq %rdi, %rdi - jz returnNilMethod - - movq 8(%r8), %r8 - movq 64(%r8), %r8 - jmp Lmain_$1 -.endmacro - -GENERATE_LOOKUP _objc_msg_lookup, _objc_methodNotFound -GENERATE_LOOKUP _objc_msg_lookup_stret, _objc_methodNotFound_stret -GENERATE_LOOKUP_SUPER _objc_msg_lookup_super, _objc_msg_lookup -GENERATE_LOOKUP_SUPER _objc_msg_lookup_super_stret, _objc_msg_lookup_stret - -returnNilMethod: - leaq nilMethod(%rip), %rax - ret - -nilMethod: - xorq %rax, %rax - ret DELETED src/runtime/lookup-asm/lookup-asm-x86_64-win64.S Index: src/runtime/lookup-asm/lookup-asm-x86_64-win64.S ================================================================== --- src/runtime/lookup-asm/lookup-asm-x86_64-win64.S +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright (c) 2008-2022 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#include "config.h" - -.globl objc_msg_lookup -.globl objc_msg_lookup_stret -.globl objc_msg_lookup_super -.globl objc_msg_lookup_super_stret - -.section .text -.macro GENERATE_LOOKUP name notFound -\name: - testq %rcx, %rcx - jz returnNilMethod - - testb $1, %cl - jnz .LtaggedPointer_\name - - movq (%rcx), %r8 - movq 56(%r8), %r8 - -.Lmain_\name: - movq %rcx, %r10 - movq %rdx, %r11 - - movq (%rdx), %rax - movzbl %ah, %ecx - movzbl %al, %edx -#ifdef OF_SELUID24 - shrl $16, %eax - - movq (%r8,%rax,8), %r8 -#endif - movq (%r8,%rcx,8), %r8 - movq (%r8,%rdx,8), %rax - - testq %rax, %rax - jz 0f - - ret - -0: - movq %r10, %rcx - movq %r11, %rdx - jmp \notFound - -.LtaggedPointer_\name: - xorq objc_taggedPointerSecret(%rip), %rcx - andb $0xE, %cl - movzbl %cl, %r8d - - leaq objc_taggedPointerClasses(%rip), %rax - movq (%rax,%r8,4), %r8 - movq 56(%r8), %r8 - - jmp .Lmain_\name -.def \name -.scl 2 -.type 32 -.endef -.endm - -.macro GENERATE_LOOKUP_SUPER name lookup -\name: - movq %rcx, %r8 - movq (%rcx), %rcx - testq %rcx, %rcx - jz returnNilMethod - - movq 8(%r8), %r8 - movq 56(%r8), %r8 - jmp .Lmain_\lookup -.def \name -.scl 2 -.type 32 -.endef -.endm - -GENERATE_LOOKUP objc_msg_lookup objc_methodNotFound -GENERATE_LOOKUP objc_msg_lookup_stret objc_methodNotFound_stret -GENERATE_LOOKUP_SUPER objc_msg_lookup_super objc_msg_lookup -GENERATE_LOOKUP_SUPER objc_msg_lookup_super_stret objc_msg_lookup_stret - -returnNilMethod: - leaq nilMethod(%rip), %rax - ret - -nilMethod: - xorq %rax, %rax - ret 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,12 +16,12 @@ #include "config.h" #include "platform.h" #if defined(OF_ELF) -# if defined(OF_X86_64) -# include "lookup-asm-x86_64-elf.S" +# if defined(OF_AMD64) +# include "lookup-asm-amd64-elf.S" # elif defined(OF_X86) # include "lookup-asm-x86-elf.S" # elif defined(OF_ARM64) # include "lookup-asm-arm64-elf.S" # elif defined(OF_ARM) @@ -38,15 +38,15 @@ # include "lookup-asm-sparc64-elf.S" # elif defined(OF_SPARC) # include "lookup-asm-sparc-elf.S" # endif #elif defined(OF_MACH_O) -# if defined(OF_X86_64) -# include "lookup-asm-x86_64-macho.S" +# if defined(OF_AMD64) +# include "lookup-asm-amd64-macho.S" # endif #elif defined(OF_WINDOWS) -# if defined(OF_X86_64) -# include "lookup-asm-x86_64-win64.S" +# if defined(OF_AMD64) +# include "lookup-asm-amd64-win64.S" # elif defined(OF_X86) # include "lookup-asm-x86-win32.S" # endif #endif Index: src/runtime/lookup.m ================================================================== --- src/runtime/lookup.m +++ src/runtime/lookup.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,18 +25,18 @@ #ifdef OF_WINDOWS # include #endif #ifdef OF_AMIGAOS +# define Class IntuitionClass # define USE_INLINE_STDARG # include # include # define __NOLIBBASE__ -# define Class IntuitionClass # include -# undef Class # undef __NOLIBBASE__ +# undef Class #endif static objc_enumeration_mutation_handler enumerationMutationHandler = NULL; void Index: src/runtime/private.h ================================================================== --- src/runtime/private.h +++ src/runtime/private.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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 @@ unsigned long version; unsigned long info; long instanceSize; struct objc_ivar_list *_Nullable ivars; struct objc_method_list *_Nullable methodList; - struct objc_dtable *_Nonnull dTable; + struct objc_dtable *_Nullable dTable; Class _Nullable *_Nullable subclassList; void *_Nullable siblingClass; struct objc_protocol_list *_Nullable protocols; void *_Nullable GCObjectType; unsigned long ABIVersion; @@ -213,75 +213,10 @@ IMP _Nullable buckets[256]; #endif } *_Nonnull buckets[256]; }; -#if defined(OBJC_COMPILING_AMIGA_LIBRARY) || \ - defined(OBJC_COMPILING_AMIGA_LINKLIB) -struct objc_libc { - void *_Nullable (*_Nonnull malloc)(size_t); - void *_Nullable (*_Nonnull calloc)(size_t, size_t); - void *_Nullable (*_Nonnull realloc)(void *_Nullable, size_t); - void (*_Nonnull free)(void *_Nullable); -# ifdef HAVE_SJLJ_EXCEPTIONS - int (*_Nonnull _Unwind_SjLj_RaiseException)(void *_Nonnull); -# else - int (*_Nonnull _Unwind_RaiseException)(void *_Nonnull); -# endif - void (*_Nonnull _Unwind_DeleteException)(void *_Nonnull); - void *_Nullable (*_Nonnull _Unwind_GetLanguageSpecificData)( - void *_Nonnull); - uintptr_t (*_Nonnull _Unwind_GetRegionStart)(void *_Nonnull); - uintptr_t (*_Nonnull _Unwind_GetDataRelBase)(void *_Nonnull); - uintptr_t (*_Nonnull _Unwind_GetTextRelBase)(void *_Nonnull); - uintptr_t (*_Nonnull _Unwind_GetIP)(void *_Nonnull); - uintptr_t (*_Nonnull _Unwind_GetGR)(void *_Nonnull, int); - void (*_Nonnull _Unwind_SetIP)(void *_Nonnull, uintptr_t); - void (*_Nonnull _Unwind_SetGR)(void *_Nonnull, int, uintptr_t); -# ifdef HAVE_SJLJ_EXCEPTIONS - void (*_Nonnull _Unwind_SjLj_Resume)(void *_Nonnull); -# else - void (*_Nonnull _Unwind_Resume)(void *_Nonnull); -# endif -# ifdef OF_AMIGAOS_M68K - void (*_Nonnull __register_frame_info)(const void *_Nonnull, - void *_Nonnull); - void *(*_Nonnull __deregister_frame_info)(const void *_Nonnull); -# endif -# ifdef OF_MORPHOS - void (*_Nonnull __register_frame)(void *_Nonnull); - void (*_Nonnull __deregister_frame)(void *_Nonnull); -# endif -# ifdef OF_AMIGAOS_M68K - int (*_Nonnull vsnprintf)(char *restrict _Nonnull str, size_t size, - const char *_Nonnull restrict fmt, va_list args); -# endif - int (*_Nonnull atexit)(void (*_Nonnull)(void)); - void (*_Nonnull exit)(int); -}; -#endif - -#ifdef OBJC_COMPILING_AMIGA_LIBRARY -# if defined(__MORPHOS__) -# include -# define OBJC_M68K_ARG(type, name, reg) type name = (type)REG_##reg; -# else -# define OBJC_M68K_ARG(type, name, reg) \ - register type reg_##name __asm__(#reg); \ - type name = reg_##name; -# endif - -extern bool objc_init(unsigned int, struct objc_libc *); -# ifdef HAVE_SJLJ_EXCEPTIONS -# define __gnu_objc_personality(version, actions, exClass, ex, ctx) \ - __gnu_objc_personality_sj0(version, actions, *exClass, ex, ctx) -# else -# define __gnu_objc_personality(version, actions, exClass, ex, ctx) \ - __gnu_objc_personality_v0(version, actions, *exClass, ex, ctx) -# endif -#endif - extern void objc_registerAllCategories(struct objc_symtab *_Nonnull); extern struct objc_category *_Nullable *_Nullable objc_categoriesForClass(Class _Nonnull); extern void objc_unregisterAllCategories(void); extern void objc_initializeClass(Class _Nonnull); @@ -355,23 +290,23 @@ #define OBJC_ERROR(...) \ objc_error("ObjFWRT @ " __FILE__ ":" OF_STRINGIFY(__LINE__), \ __VA_ARGS__) #if defined(OF_ELF) -# if defined(OF_X86_64) || defined(OF_X86) || \ +# if defined(OF_AMD64) || defined(OF_X86) || \ defined(OF_POWERPC64) || defined(OF_POWERPC) || \ defined(OF_ARM64) || defined(OF_ARM) || \ defined(OF_MIPS64_N64) || defined(OF_MIPS) || \ defined(OF_SPARC64) || defined(OF_SPARC) # define OF_ASM_LOOKUP # endif #elif defined(OF_MACH_O) -# if defined(OF_X86_64) +# if defined(OF_AMD64) # define OF_ASM_LOOKUP # endif #elif defined(OF_WINDOWS) -# if defined(OF_X86_64) || defined(OF_X86) +# if defined(OF_AMD64) || defined(OF_X86) # define OF_ASM_LOOKUP # endif #endif @interface DummyObject Index: src/runtime/property.m ================================================================== --- src/runtime/property.m +++ src/runtime/property.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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/versioninfo.rc ================================================================== --- src/runtime/versioninfo.rc +++ src/runtime/versioninfo.rc @@ -12,11 +12,11 @@ VALUE "ProductName", "ObjFW Runtime" VALUE "ProductVersion", PACKAGE_VERSION VALUE "FileVersion", OBJFWRT_LIB_VERSION VALUE "FileDescription", "Objective-C runtime" VALUE "LegalCopyright", - "(c) 2008-2022 Jonathan Schleifer" + "(c) 2008-2024 Jonathan Schleifer" VALUE "InternalName", "ObjFWRT" VALUE "OriginalFilename", OBJFWRT_SHARED_LIB } } Index: src/tls/Makefile ================================================================== --- src/tls/Makefile +++ src/tls/Makefile @@ -3,15 +3,17 @@ 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} +LIB_MAJOR = ${OBJFWTLS_LIB_MAJOR} +LIB_MINOR = ${OBJFWTLS_LIB_MINOR} +LIB_PATCH = ${OBJFWTLS_LIB_PATCH} INCLUDES := ObjFWTLS.h SRCS = ${OF_GNUTLS_TLS_STREAM_M} \ + ${OF_MBEDTLS_TLS_STREAM_M} \ ${OF_OPENSSL_TLS_STREAM_M} \ ${OF_SECURE_TRANSPORT_TLS_STREAM_M} includesubdir = ObjFWTLS Index: src/tls/OFGnuTLSTLSStream.h ================================================================== --- src/tls/OFGnuTLSTLSStream.h +++ src/tls/OFGnuTLSTLSStream.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/tls/OFGnuTLSTLSStream.m ================================================================== --- src/tls/OFGnuTLSTLSStream.m +++ src/tls/OFGnuTLSTLSStream.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,11 +18,11 @@ #include #import "OFGnuTLSTLSStream.h" #import "OFData.h" -#import "OFAlreadyConnectedException.h" +#import "OFAlreadyOpenException.h" #import "OFInitializationFailedException.h" #import "OFNotOpenException.h" #import "OFReadFailedException.h" #import "OFTLSHandshakeFailedException.h" #import "OFWriteFailedException.h" @@ -125,11 +125,11 @@ if (_handshakeDone) gnutls_bye(_session, GNUTLS_SHUT_WR); gnutls_deinit(_session); - _initialized = false; + _initialized = _handshakeDone = false; [_host release]; _host = nil; [super close]; @@ -183,16 +183,14 @@ } return ret; } -- (bool)hasDataInReadBuffer +- (bool)lowlevelHasDataInReadBuffer { - if (gnutls_record_check_pending(_session) > 0) - return true; - - return super.hasDataInReadBuffer; + return (_underlyingStream.hasDataInReadBuffer || + gnutls_record_check_pending(_session) > 0); } - (void)asyncPerformClientHandshakeWithHost: (OFString *)host runLoopMode: (OFRunLoopMode)runLoopMode { @@ -200,11 +198,11 @@ OFTLSStreamErrorCodeInitializationFailed; id exception = nil; int status; if (_initialized) - @throw [OFAlreadyConnectedException exceptionWithSocket: self]; + @throw [OFAlreadyOpenException exceptionWithObject: self]; if (gnutls_init(&_session, GNUTLS_CLIENT | GNUTLS_NONBLOCK | GNUTLS_SAFE_PADDING_CHECK) != GNUTLS_E_SUCCESS) @throw [OFTLSHandshakeFailedException exceptionWithStream: self @@ -239,13 +237,12 @@ 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]; + [_underlyingStream asyncWriteData: [OFData data] + runLoopMode: runLoopMode]; else [_underlyingStream asyncReadIntoBuffer: (void *)"" length: 0 runLoopMode: runLoopMode]; @@ -270,23 +267,21 @@ } - (bool)stream: (OFStream *)stream didReadIntoBuffer: (void *)buffer length: (size_t)length - exception: (nullable id)exception + 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) { - OFData *data = [OFData dataWithItems: "" - count: 0]; OFRunLoopMode runLoopMode = [OFRunLoop currentRunLoop].currentMode; - [_underlyingStream asyncWriteData: data + [_underlyingStream asyncWriteData: [OFData data] runLoopMode: runLoopMode]; return false; } else return true; } ADDED src/tls/OFMbedTLSTLSStream.h Index: src/tls/OFMbedTLSTLSStream.h ================================================================== --- /dev/null +++ src/tls/OFMbedTLSTLSStream.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2008-2024 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either 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 OFMbedTLSTLSStream: OFTLSStream +{ + bool _initialized, _handshakeDone; + mbedtls_ssl_config _config; + mbedtls_ssl_context _SSL; + OFString *_host; +} +@end + +OF_ASSUME_NONNULL_END ADDED src/tls/OFMbedTLSTLSStream.m Index: src/tls/OFMbedTLSTLSStream.m ================================================================== --- /dev/null +++ src/tls/OFMbedTLSTLSStream.m @@ -0,0 +1,359 @@ +/* + * Copyright (c) 2008-2024 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 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 "OFMbedTLSTLSStream.h" +#import "OFData.h" + +#import "OFAlreadyOpenException.h" +#import "OFInitializationFailedException.h" +#import "OFNotOpenException.h" +#import "OFOutOfRangeException.h" +#import "OFReadFailedException.h" +#import "OFTLSHandshakeFailedException.h" +#import "OFWriteFailedException.h" + +#include +#include + +int _ObjFWTLS_reference; +static mbedtls_entropy_context entropy; +static mbedtls_ctr_drbg_context CTRDRBG; +static mbedtls_x509_crt CAChain; + +@implementation OFMbedTLSTLSStream +static int +readFunc(void *ctx, unsigned char *buffer, size_t length) +{ + OFMbedTLSTLSStream *stream = (OFMbedTLSTLSStream *)ctx; + + @try { + length = [stream.underlyingStream readIntoBuffer: buffer + length: length]; + } @catch (OFReadFailedException *e) { + return -1; + } + + if (length == 0 && !stream.underlyingStream.atEndOfStream) + return MBEDTLS_ERR_SSL_WANT_READ; + + if (length > INT_MAX) + @throw [OFOutOfRangeException exception]; + + return (int)length; +} + +static int +writeFunc(void *ctx, const unsigned char *buffer, size_t length) +{ + OFMbedTLSTLSStream *stream = (OFMbedTLSTLSStream *)ctx; + + @try { + [stream.underlyingStream writeBuffer: buffer length: length]; + } @catch (OFWriteFailedException *e) { + if (e.errNo == EWOULDBLOCK || e.errNo == EAGAIN) { + size_t bytesWritten = e.bytesWritten; + + if (bytesWritten > INT_MAX) + @throw [OFOutOfRangeException exception]; + + return (bytesWritten > 0 + ? (int)bytesWritten : MBEDTLS_ERR_SSL_WANT_WRITE); + } + + return -1; + } + + if (length > INT_MAX) + @throw [OFOutOfRangeException exception]; + + return (int)length; +} + ++ (void)load +{ + if (OFTLSStreamImplementation == Nil) + OFTLSStreamImplementation = self; +} + ++ (void)initialize +{ + if (self != [OFMbedTLSTLSStream class]) + return; + + mbedtls_entropy_init(&entropy); + if (mbedtls_ctr_drbg_seed(&CTRDRBG, mbedtls_entropy_func, &entropy, + NULL, 0) != 0) + @throw [OFInitializationFailedException + exceptionWithClass: self]; + + mbedtls_x509_crt_init(&CAChain); + if (mbedtls_x509_crt_parse_file(&CAChain, OF_MBEDTLS_CA_PATH) != 0) + @throw [OFInitializationFailedException + exceptionWithClass: self]; +} + +- (instancetype)initWithStream: (OFStream *)stream +{ + self = [super initWithStream: stream]; + + @try { + _underlyingStream.delegate = self; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (void)dealloc +{ + if (_initialized) + [self close]; + + [_host release]; + + [super dealloc]; +} + +- (void)close +{ + if (!_initialized) + @throw [OFNotOpenException exceptionWithObject: self]; + + if (_handshakeDone) + mbedtls_ssl_close_notify(&_SSL); + + mbedtls_ssl_free(&_SSL); + mbedtls_ssl_config_free(&_config); + _initialized = _handshakeDone = false; + + [_host release]; + _host = nil; + + [super close]; +} + +- (size_t)lowlevelReadIntoBuffer: (void *)buffer length: (size_t)length +{ + int ret; + + if (!_handshakeDone) + @throw [OFNotOpenException exceptionWithObject: self]; + + if ((ret = mbedtls_ssl_read(&_SSL, buffer, length)) < 0) { + /* + * The underlying stream might have had data ready, but not + * enough for MbedTLS to return decrypted data. This means the + * caller might have observed the TLS stream for reading, got a + * ready signal and read - and expects the read to succeed, not + * to fail with EWOULDBLOCK/EAGAIN, as it was signaled ready. + * Therefore, return 0, as we could read 0 decrypted bytes, but + * cleared the ready signal of the underlying stream. + */ + if (ret == MBEDTLS_ERR_SSL_WANT_READ || + ret == MBEDTLS_ERR_SSL_WANT_WRITE) + return 0; + + /* FIXME: Translate error to errNo */ + @throw [OFReadFailedException exceptionWithObject: self + requestedLength: length + errNo: 0]; + } + + return ret; +} + +- (size_t)lowlevelWriteBuffer: (const void *)buffer length: (size_t)length +{ + int ret; + + if (!_handshakeDone) + @throw [OFNotOpenException exceptionWithObject: self]; + + if ((ret = mbedtls_ssl_write(&_SSL, buffer, length)) < 0) { + if (ret == MBEDTLS_ERR_SSL_WANT_READ || + ret == MBEDTLS_ERR_SSL_WANT_WRITE) + return 0; + + /* FIXME: Translate error to errNo */ + @throw [OFWriteFailedException exceptionWithObject: self + requestedLength: length + bytesWritten: ret + errNo: 0]; + } + + return ret; +} + +- (bool)lowlevelHasDataInReadBuffer +{ + return (_underlyingStream.hasDataInReadBuffer || + mbedtls_ssl_get_bytes_avail(&_SSL)); +} + +- (void)asyncPerformClientHandshakeWithHost: (OFString *)host + runLoopMode: (OFRunLoopMode)runLoopMode +{ + static const OFTLSStreamErrorCode initFailedErrorCode = + OFTLSStreamErrorCodeInitializationFailed; + id exception = nil; + int status; + + if (_initialized) + @throw [OFAlreadyOpenException exceptionWithObject: self]; + + if (mbedtls_ssl_config_defaults(&_config, MBEDTLS_SSL_IS_CLIENT, + MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT) != 0) + @throw [OFTLSHandshakeFailedException + exceptionWithStream: self + host: host + errorCode: initFailedErrorCode]; + + mbedtls_ssl_conf_rng(&_config, mbedtls_ctr_drbg_random, &CTRDRBG); + mbedtls_ssl_conf_authmode(&_config, (_verifiesCertificates + ? MBEDTLS_SSL_VERIFY_REQUIRED : MBEDTLS_SSL_VERIFY_NONE)); + mbedtls_ssl_conf_ca_chain(&_config, &CAChain, NULL); + + mbedtls_ssl_init(&_SSL); + if (mbedtls_ssl_setup(&_SSL, &_config) != 0) + @throw [OFTLSHandshakeFailedException + exceptionWithStream: self + host: host + errorCode: initFailedErrorCode]; + + mbedtls_ssl_set_bio(&_SSL, self, writeFunc, readFunc, NULL); + + _host = [host copy]; + + if (mbedtls_ssl_set_hostname(&_SSL, _host.UTF8String) != 0) + @throw [OFTLSHandshakeFailedException + exceptionWithStream: self + host: host + errorCode: initFailedErrorCode]; + + status = mbedtls_ssl_handshake(&_SSL); + + if (status == MBEDTLS_ERR_SSL_WANT_READ) { + [_underlyingStream asyncReadIntoBuffer: (void *)"" + length: 0 + runLoopMode: runLoopMode]; + [_delegate retain]; + return; + } else if (status == MBEDTLS_ERR_SSL_WANT_WRITE) { + [_underlyingStream asyncWriteData: [OFData data] + runLoopMode: runLoopMode]; + [_delegate retain]; + return; + } + + if (status == 0) + _handshakeDone = true; + else + /* FIXME: Map to better errors */ + exception = [OFTLSHandshakeFailedException + exceptionWithStream: self + host: host + errorCode: OFTLSStreamErrorCodeUnknown]; + + if ([_delegate respondsToSelector: + @selector(stream:didPerformClientHandshakeWithHost:exception:)]) + [_delegate stream: self + didPerformClientHandshakeWithHost: host + exception: exception]; +} + +- (bool)stream: (OFStream *)stream + didReadIntoBuffer: (void *)buffer + length: (size_t)length + exception: (id)exception +{ + if (exception == nil) { + int status = mbedtls_ssl_handshake_step(&_SSL); + + if (status == MBEDTLS_ERR_SSL_WANT_READ) + return true; + else if (status == MBEDTLS_ERR_SSL_WANT_WRITE) { + OFRunLoopMode runLoopMode = + [OFRunLoop currentRunLoop].currentMode; + [_underlyingStream asyncWriteData: [OFData data] + runLoopMode: runLoopMode]; + return false; + } + + if (status == 0) + _handshakeDone = true; + else + exception = [OFTLSHandshakeFailedException + exceptionWithStream: self + host: _host + errorCode: OFTLSStreamErrorCodeUnknown]; + } + + if ([_delegate respondsToSelector: + @selector(stream:didPerformClientHandshakeWithHost:exception:)]) + [_delegate stream: self + didPerformClientHandshakeWithHost: _host + exception: exception]; + + [_delegate release]; + + return false; +} + +- (OFData *)stream: (OFStream *)stream + didWriteData: (OFData *)data + bytesWritten: (size_t)bytesWritten + exception: (id)exception +{ + if (exception == nil) { + int status = mbedtls_ssl_handshake_step(&_SSL); + + if (status == MBEDTLS_ERR_SSL_WANT_WRITE) + return data; + else if (status == MBEDTLS_ERR_SSL_WANT_READ) { + OFRunLoopMode runLoopMode = + [OFRunLoop currentRunLoop].currentMode; + [_underlyingStream asyncReadIntoBuffer: (void *)"" + length: 0 + runLoopMode: runLoopMode]; + return nil; + } + + if (status == 0) + _handshakeDone = true; + else + exception = [OFTLSHandshakeFailedException + exceptionWithStream: self + host: _host + errorCode: OFTLSStreamErrorCodeUnknown]; + } + + if ([_delegate respondsToSelector: + @selector(stream:didPerformClientHandshakeWithHost:exception:)]) + [_delegate stream: self + didPerformClientHandshakeWithHost: _host + exception: exception]; + + [_delegate release]; + + return nil; +} +@end Index: src/tls/OFOpenSSLTLSStream.h ================================================================== --- src/tls/OFOpenSSLTLSStream.h +++ src/tls/OFOpenSSLTLSStream.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/tls/OFOpenSSLTLSStream.m ================================================================== --- src/tls/OFOpenSSLTLSStream.m +++ src/tls/OFOpenSSLTLSStream.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,11 +18,11 @@ #include #import "OFOpenSSLTLSStream.h" #import "OFData.h" -#import "OFAlreadyConnectedException.h" +#import "OFAlreadyOpenException.h" #import "OFInitializationFailedException.h" #import "OFNotOpenException.h" #import "OFReadFailedException.h" #import "OFTLSHandshakeFailedException.h" #import "OFWriteFailedException.h" @@ -92,10 +92,12 @@ SSL_shutdown(_SSL); SSL_free(_SSL); _SSL = NULL; + _handshakeDone = false; + [_host release]; _host = nil; [super close]; } @@ -106,26 +108,10 @@ 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); @@ -133,30 +119,52 @@ [_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 (ret == 1) + return bytesRead; + + if (SSL_get_error(_SSL, ret) == SSL_ERROR_WANT_READ) { + if (BIO_ctrl_pending(_readBIO) < 1) { + @try { + size_t tmp = [_underlyingStream + readIntoBuffer: _buffer + length: bufferSize]; + + OFEnsure(tmp <= INT_MAX); + /* Writing to a memory BIO must never fail. */ + OFEnsure(BIO_write(_readBIO, _buffer, + (int)tmp) == (int)tmp); + } @catch (OFReadFailedException *e) { + if (e.errNo == EWOULDBLOCK || e.errNo != EAGAIN) + return 0; + } + } + + ret = SSL_read_ex(_SSL, buffer, length, &bytesRead); + + while (BIO_ctrl_pending(_writeBIO) > 0) { + int tmp = BIO_read(_writeBIO, _buffer, bufferSize); + + OFEnsure(tmp >= 0); + + [_underlyingStream writeBuffer: _buffer length: tmp]; + [_underlyingStream flushWriteBuffer]; + } + + if (ret == 1) + return bytesRead; + if (SSL_get_error(_SSL, ret) == SSL_ERROR_WANT_READ) return 0; - - /* FIXME: Translate error to errNo */ - @throw [OFReadFailedException exceptionWithObject: self - requestedLength: length - errNo: 0]; } - return bytesRead; + /* FIXME: Translate error to errNo */ + @throw [OFReadFailedException exceptionWithObject: self + requestedLength: length + errNo: 0]; } - (size_t)lowlevelWriteBuffer: (const void *)buffer length: (size_t)length { int ret; @@ -188,16 +196,19 @@ } return bytesWritten; } -- (bool)hasDataInReadBuffer +- (bool)lowlevelHasDataInReadBuffer { - if (SSL_pending(_SSL) > 0 || BIO_ctrl_pending(_readBIO) > 0) - return true; - - return super.hasDataInReadBuffer; +#ifdef HAVE_SSL_HAS_PENDING + return (_underlyingStream.hasDataInReadBuffer || + SSL_has_pending(_SSL) || BIO_ctrl_pending(_readBIO) > 0); +#else + return (_underlyingStream.hasDataInReadBuffer || + SSL_pending(_SSL) > 0 || BIO_ctrl_pending(_readBIO) > 0); +#endif } - (void)asyncPerformClientHandshakeWithHost: (OFString *)host runLoopMode: (OFRunLoopMode)runLoopMode { @@ -205,11 +216,11 @@ OFTLSStreamErrorCodeInitializationFailed; id exception = nil; int status; if (_SSL != NULL) - @throw [OFAlreadyConnectedException exceptionWithSocket: self]; + @throw [OFAlreadyOpenException exceptionWithObject: self]; if ((_readBIO = BIO_new(BIO_s_mem())) == NULL) @throw [OFTLSHandshakeFailedException exceptionWithStream: self host: host @@ -276,13 +287,12 @@ length: bufferSize runLoopMode: runLoopMode]; [_delegate retain]; return; case SSL_ERROR_WANT_WRITE: - [_underlyingStream - asyncWriteData: [OFData dataWithItems: "" count: 0] - runLoopMode: runLoopMode]; + [_underlyingStream asyncWriteData: [OFData data] + runLoopMode: runLoopMode]; [_delegate retain]; return; default: /* FIXME: Map to better errors */ exception = [OFTLSHandshakeFailedException @@ -307,11 +317,10 @@ { 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); @@ -330,15 +339,14 @@ _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]; + case SSL_ERROR_WANT_WRITE:; OFRunLoopMode runLoopMode = [OFRunLoop currentRunLoop].currentMode; - [_underlyingStream asyncWriteData: data + [_underlyingStream asyncWriteData: [OFData data] runLoopMode: runLoopMode]; return false; default: exception = [OFTLSHandshakeFailedException exceptionWithStream: self Index: src/tls/OFSecureTransportTLSStream.h ================================================================== --- src/tls/OFSecureTransportTLSStream.h +++ src/tls/OFSecureTransportTLSStream.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/tls/OFSecureTransportTLSStream.m ================================================================== --- src/tls/OFSecureTransportTLSStream.m +++ src/tls/OFSecureTransportTLSStream.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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 @@ #include #import "OFSecureTransportTLSStream.h" -#import "OFAlreadyConnectedException.h" +#import "OFAlreadyOpenException.h" #import "OFNotOpenException.h" #import "OFReadFailedException.h" #import "OFTLSHandshakeFailedException.h" #import "OFWriteFailedException.h" @@ -166,19 +166,17 @@ errNo: 0]; return bytesWritten; } -- (bool)hasDataInReadBuffer +- (bool)lowlevelHasDataInReadBuffer { size_t bufferSize; - if (SSLGetBufferedReadSize(_context, &bufferSize) == noErr && - bufferSize > 0) - return true; - - return super.hasDataInReadBuffer; + return (_underlyingStream.hasDataInReadBuffer || + (SSLGetBufferedReadSize(_context, &bufferSize) == noErr && + bufferSize > 0)); } - (void)asyncPerformClientHandshakeWithHost: (OFString *)host runLoopMode: (OFRunLoopMode)runLoopMode { @@ -186,11 +184,11 @@ OFTLSStreamErrorCodeInitializationFailed; id exception = nil; OSStatus status; if (_context != NULL) - @throw [OFAlreadyConnectedException exceptionWithSocket: self]; + @throw [OFAlreadyOpenException exceptionWithObject: self]; #ifdef HAVE_SSLCREATECONTEXT if ((_context = SSLCreateContext(kCFAllocatorDefault, kSSLClientSide, kSSLStreamType)) == NULL) #else Index: src/tls/ObjFWTLS.h ================================================================== --- src/tls/ObjFWTLS.h +++ src/tls/ObjFWTLS.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be 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.h ================================================================== --- src/unicode.h +++ src/unicode.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,12 +17,10 @@ #define OFUnicodeUppercaseTableSize 0x1EA #define OFUnicodeLowercaseTableSize 0x1EA #define OFUnicodeTitlecaseTableSize 0x1EA #define OFUnicodeCaseFoldingTableSize 0x1EA -#define OFUnicodeDecompositionTableSize 0x2FB -#define OFUnicodeDecompositionCompatTableSize 0x2FB #ifdef __cplusplus extern "C" { #endif extern const OFUnichar *const _Nonnull @@ -31,12 +29,8 @@ OFUnicodeLowercaseTable[OFUnicodeLowercaseTableSize]; extern const OFUnichar *const _Nonnull OFUnicodeTitlecaseTable[OFUnicodeTitlecaseTableSize]; extern const OFUnichar *const _Nonnull OFUnicodeCaseFoldingTable[OFUnicodeCaseFoldingTableSize]; -extern const char *const _Nullable *const _Nonnull - OFUnicodeDecompositionTable[OFUnicodeDecompositionTableSize]; -extern const char *const _Nullable *const _Nonnull - OFUnicodeDecompositionCompatTable[OFUnicodeDecompositionCompatTableSize]; #ifdef __cplusplus } #endif Index: src/unicode.m ================================================================== --- src/unicode.m +++ src/unicode.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,11 +16,10 @@ #include "config.h" #import "OFString.h" static const OFUnichar emptyPage[0x100] = { 0 }; -static const char *emptyDecompositionPage[0x100] = { NULL }; static const OFUnichar uppercasePage0[0x100] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -520,11 +519,11 @@ 11264, 11265, 11266, 11267, 11268, 11269, 11270, 11271, 11272, 11273, 11274, 11275, 11276, 11277, 11278, 11279, 11280, 11281, 11282, 11283, 11284, 11285, 11286, 11287, 11288, 11289, 11290, 11291, 11292, 11293, 11294, 11295, 11296, 11297, 11298, 11299, 11300, 11301, 11302, 11303, - 11304, 11305, 11306, 11307, 11308, 11309, 11310, 0, + 11304, 11305, 11306, 11307, 11308, 11309, 11310, 11311, 0, 11360, 0, 0, 0, 570, 574, 0, 11367, 0, 11369, 0, 11371, 0, 0, 0, 0, 0, 0, 11378, 0, 0, 11381, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11392, 0, 11394, 0, 11396, 0, 11398, @@ -638,14 +637,14 @@ 0, 42904, 0, 42906, 0, 42908, 0, 42910, 0, 42912, 0, 42914, 0, 42916, 0, 42918, 0, 42920, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42932, 0, 42934, 0, 42936, 0, 42938, 0, 42940, 0, 42942, - 0, 0, 0, 42946, 0, 0, 0, 0, + 0, 42944, 0, 42946, 0, 0, 0, 0, 42951, 0, 42953, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, + 0, 42960, 0, 0, 0, 0, 0, 42966, + 0, 42968, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42997, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; @@ -752,10 +751,45 @@ 66744, 66745, 66746, 66747, 66748, 66749, 66750, 66751, 66752, 66753, 66754, 66755, 66756, 66757, 66758, 66759, 66760, 66761, 66762, 66763, 66764, 66765, 66766, 66767, 66768, 66769, 66770, 66771, 0, 0, 0, 0, }; + +static const OFUnichar uppercasePage261[0x100] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 66928, + 66929, 66930, 66931, 66932, 66933, 66934, 66935, 66936, + 66937, 66938, 0, 66940, 66941, 66942, 66943, 66944, + 66945, 66946, 66947, 66948, 66949, 66950, 66951, 66952, + 66953, 66954, 0, 66956, 66957, 66958, 66959, 66960, + 66961, 66962, 0, 66964, 66965, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; static const OFUnichar uppercasePage268[0x100] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -1354,11 +1388,11 @@ 11312, 11313, 11314, 11315, 11316, 11317, 11318, 11319, 11320, 11321, 11322, 11323, 11324, 11325, 11326, 11327, 11328, 11329, 11330, 11331, 11332, 11333, 11334, 11335, 11336, 11337, 11338, 11339, 11340, 11341, 11342, 11343, 11344, 11345, 11346, 11347, 11348, 11349, 11350, 11351, - 11352, 11353, 11354, 11355, 11356, 11357, 11358, 0, + 11352, 11353, 11354, 11355, 11356, 11357, 11358, 11359, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -1443,14 +1477,14 @@ 42905, 0, 42907, 0, 42909, 0, 42911, 0, 42913, 0, 42915, 0, 42917, 0, 42919, 0, 42921, 0, 614, 604, 609, 620, 618, 0, 670, 647, 669, 43859, 42933, 0, 42935, 0, 42937, 0, 42939, 0, 42941, 0, 42943, 0, - 0, 0, 42947, 0, 42900, 642, 7566, 42952, + 42945, 0, 42947, 0, 42900, 642, 7566, 42952, 0, 42954, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, + 42961, 0, 0, 0, 0, 0, 42967, 0, + 42969, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42998, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; @@ -1516,10 +1550,45 @@ 66776, 66777, 66778, 66779, 66780, 66781, 66782, 66783, 66784, 66785, 66786, 66787, 66788, 66789, 66790, 66791, 66792, 66793, 66794, 66795, 66796, 66797, 66798, 66799, 66800, 66801, 66802, 66803, 66804, 66805, 66806, 66807, 66808, 66809, 66810, 66811, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const OFUnichar lowercasePage261[0x100] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 66967, 66968, 66969, 66970, 66971, 66972, 66973, 66974, + 66975, 66976, 66977, 0, 66979, 66980, 66981, 66982, + 66983, 66984, 66985, 66986, 66987, 66988, 66989, 66990, + 66991, 66992, 66993, 0, 66995, 66996, 66997, 66998, + 66999, 67000, 67001, 0, 67003, 67004, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -1970,13 +2039,13 @@ 8096, 8097, 8098, 8099, 8100, 8101, 8102, 8103, 0, 0, 0, 0, 0, 0, 0, 0, 8112, 8113, 8048, 8049, 8115, 0, 953, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8050, 8051, 8052, 8053, 8131, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 912, 0, 0, 0, 0, 8144, 8145, 8054, 8055, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 944, 0, 0, 0, 0, 8160, 8161, 8058, 8059, 8165, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8056, 8057, 8060, 8061, 8179, 0, 0, 0, }; @@ -2013,10357 +2082,43 @@ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; -static const char *const decompositionPage0[0x100] = { - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\x41\xCC\x80", "\x41\xCC\x81", - "\x41\xCC\x82", "\x41\xCC\x83", - "\x41\xCC\x88", "\x41\xCC\x8A", - NULL, "\x43\xCC\xA7", - "\x45\xCC\x80", "\x45\xCC\x81", - "\x45\xCC\x82", "\x45\xCC\x88", - "\x49\xCC\x80", "\x49\xCC\x81", - "\x49\xCC\x82", "\x49\xCC\x88", - NULL, "\x4E\xCC\x83", - "\x4F\xCC\x80", "\x4F\xCC\x81", - "\x4F\xCC\x82", "\x4F\xCC\x83", - "\x4F\xCC\x88", NULL, - NULL, "\x55\xCC\x80", - "\x55\xCC\x81", "\x55\xCC\x82", - "\x55\xCC\x88", "\x59\xCC\x81", - NULL, NULL, - "\x61\xCC\x80", "\x61\xCC\x81", - "\x61\xCC\x82", "\x61\xCC\x83", - "\x61\xCC\x88", "\x61\xCC\x8A", - NULL, "\x63\xCC\xA7", - "\x65\xCC\x80", "\x65\xCC\x81", - "\x65\xCC\x82", "\x65\xCC\x88", - "\x69\xCC\x80", "\x69\xCC\x81", - "\x69\xCC\x82", "\x69\xCC\x88", - NULL, "\x6E\xCC\x83", - "\x6F\xCC\x80", "\x6F\xCC\x81", - "\x6F\xCC\x82", "\x6F\xCC\x83", - "\x6F\xCC\x88", NULL, - NULL, "\x75\xCC\x80", - "\x75\xCC\x81", "\x75\xCC\x82", - "\x75\xCC\x88", "\x79\xCC\x81", - NULL, "\x79\xCC\x88", -}; - -static const char *const decompositionPage1[0x100] = { - "\x41\xCC\x84", "\x61\xCC\x84", - "\x41\xCC\x86", "\x61\xCC\x86", - "\x41\xCC\xA8", "\x61\xCC\xA8", - "\x43\xCC\x81", "\x63\xCC\x81", - "\x43\xCC\x82", "\x63\xCC\x82", - "\x43\xCC\x87", "\x63\xCC\x87", - "\x43\xCC\x8C", "\x63\xCC\x8C", - "\x44\xCC\x8C", "\x64\xCC\x8C", - NULL, NULL, - "\x45\xCC\x84", "\x65\xCC\x84", - "\x45\xCC\x86", "\x65\xCC\x86", - "\x45\xCC\x87", "\x65\xCC\x87", - "\x45\xCC\xA8", "\x65\xCC\xA8", - "\x45\xCC\x8C", "\x65\xCC\x8C", - "\x47\xCC\x82", "\x67\xCC\x82", - "\x47\xCC\x86", "\x67\xCC\x86", - "\x47\xCC\x87", "\x67\xCC\x87", - "\x47\xCC\xA7", "\x67\xCC\xA7", - "\x48\xCC\x82", "\x68\xCC\x82", - NULL, NULL, - "\x49\xCC\x83", "\x69\xCC\x83", - "\x49\xCC\x84", "\x69\xCC\x84", - "\x49\xCC\x86", "\x69\xCC\x86", - "\x49\xCC\xA8", "\x69\xCC\xA8", - "\x49\xCC\x87", NULL, - NULL, NULL, - "\x4A\xCC\x82", "\x6A\xCC\x82", - "\x4B\xCC\xA7", "\x6B\xCC\xA7", - NULL, "\x4C\xCC\x81", - "\x6C\xCC\x81", "\x4C\xCC\xA7", - "\x6C\xCC\xA7", "\x4C\xCC\x8C", - "\x6C\xCC\x8C", NULL, - NULL, NULL, - NULL, "\x4E\xCC\x81", - "\x6E\xCC\x81", "\x4E\xCC\xA7", - "\x6E\xCC\xA7", "\x4E\xCC\x8C", - "\x6E\xCC\x8C", NULL, - NULL, NULL, - "\x4F\xCC\x84", "\x6F\xCC\x84", - "\x4F\xCC\x86", "\x6F\xCC\x86", - "\x4F\xCC\x8B", "\x6F\xCC\x8B", - NULL, NULL, - "\x52\xCC\x81", "\x72\xCC\x81", - "\x52\xCC\xA7", "\x72\xCC\xA7", - "\x52\xCC\x8C", "\x72\xCC\x8C", - "\x53\xCC\x81", "\x73\xCC\x81", - "\x53\xCC\x82", "\x73\xCC\x82", - "\x53\xCC\xA7", "\x73\xCC\xA7", - "\x53\xCC\x8C", "\x73\xCC\x8C", - "\x54\xCC\xA7", "\x74\xCC\xA7", - "\x54\xCC\x8C", "\x74\xCC\x8C", - NULL, NULL, - "\x55\xCC\x83", "\x75\xCC\x83", - "\x55\xCC\x84", "\x75\xCC\x84", - "\x55\xCC\x86", "\x75\xCC\x86", - "\x55\xCC\x8A", "\x75\xCC\x8A", - "\x55\xCC\x8B", "\x75\xCC\x8B", - "\x55\xCC\xA8", "\x75\xCC\xA8", - "\x57\xCC\x82", "\x77\xCC\x82", - "\x59\xCC\x82", "\x79\xCC\x82", - "\x59\xCC\x88", "\x5A\xCC\x81", - "\x7A\xCC\x81", "\x5A\xCC\x87", - "\x7A\xCC\x87", "\x5A\xCC\x8C", - "\x7A\xCC\x8C", NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\x4F\xCC\x9B", "\x6F\xCC\x9B", - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, "\x55\xCC\x9B", - "\x75\xCC\x9B", NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, "\x41\xCC\x8C", - "\x61\xCC\x8C", "\x49\xCC\x8C", - "\x69\xCC\x8C", "\x4F\xCC\x8C", - "\x6F\xCC\x8C", "\x55\xCC\x8C", - "\x75\xCC\x8C", "\x55\xCC\x88\xCC\x84", - "\x75\xCC\x88\xCC\x84", "\x55\xCC\x88\xCC\x81", - "\x75\xCC\x88\xCC\x81", "\x55\xCC\x88\xCC\x8C", - "\x75\xCC\x88\xCC\x8C", "\x55\xCC\x88\xCC\x80", - "\x75\xCC\x88\xCC\x80", NULL, - "\x41\xCC\x88\xCC\x84", "\x61\xCC\x88\xCC\x84", - "\x41\xCC\x87\xCC\x84", "\x61\xCC\x87\xCC\x84", - "\xC3\x86\xCC\x84", "\xC3\xA6\xCC\x84", - NULL, NULL, - "\x47\xCC\x8C", "\x67\xCC\x8C", - "\x4B\xCC\x8C", "\x6B\xCC\x8C", - "\x4F\xCC\xA8", "\x6F\xCC\xA8", - "\x4F\xCC\xA8\xCC\x84", "\x6F\xCC\xA8\xCC\x84", - "\xC6\xB7\xCC\x8C", "\xCA\x92\xCC\x8C", - "\x6A\xCC\x8C", NULL, - NULL, NULL, - "\x47\xCC\x81", "\x67\xCC\x81", - NULL, NULL, - "\x4E\xCC\x80", "\x6E\xCC\x80", - "\x41\xCC\x8A\xCC\x81", "\x61\xCC\x8A\xCC\x81", - "\xC3\x86\xCC\x81", "\xC3\xA6\xCC\x81", - "\xC3\x98\xCC\x81", "\xC3\xB8\xCC\x81", -}; - -static const char *const decompositionPage2[0x100] = { - "\x41\xCC\x8F", "\x61\xCC\x8F", - "\x41\xCC\x91", "\x61\xCC\x91", - "\x45\xCC\x8F", "\x65\xCC\x8F", - "\x45\xCC\x91", "\x65\xCC\x91", - "\x49\xCC\x8F", "\x69\xCC\x8F", - "\x49\xCC\x91", "\x69\xCC\x91", - "\x4F\xCC\x8F", "\x6F\xCC\x8F", - "\x4F\xCC\x91", "\x6F\xCC\x91", - "\x52\xCC\x8F", "\x72\xCC\x8F", - "\x52\xCC\x91", "\x72\xCC\x91", - "\x55\xCC\x8F", "\x75\xCC\x8F", - "\x55\xCC\x91", "\x75\xCC\x91", - "\x53\xCC\xA6", "\x73\xCC\xA6", - "\x54\xCC\xA6", "\x74\xCC\xA6", - NULL, NULL, - "\x48\xCC\x8C", "\x68\xCC\x8C", - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\x41\xCC\x87", "\x61\xCC\x87", - "\x45\xCC\xA7", "\x65\xCC\xA7", - "\x4F\xCC\x88\xCC\x84", "\x6F\xCC\x88\xCC\x84", - "\x4F\xCC\x83\xCC\x84", "\x6F\xCC\x83\xCC\x84", - "\x4F\xCC\x87", "\x6F\xCC\x87", - "\x4F\xCC\x87\xCC\x84", "\x6F\xCC\x87\xCC\x84", - "\x59\xCC\x84", "\x79\xCC\x84", - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, -}; - -static const char *const decompositionPage3[0x100] = { - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\xCC\x80", "\xCC\x81", - NULL, "\xCC\x93", - "\xCC\x88\xCC\x81", NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\xCA\xB9", NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\x3B", NULL, - NULL, NULL, - NULL, NULL, - NULL, "\xC2\xA8\xCC\x81", - "\xCE\x91\xCC\x81", "\xC2\xB7", - "\xCE\x95\xCC\x81", "\xCE\x97\xCC\x81", - "\xCE\x99\xCC\x81", NULL, - "\xCE\x9F\xCC\x81", NULL, - "\xCE\xA5\xCC\x81", "\xCE\xA9\xCC\x81", - "\xCE\xB9\xCC\x88\xCC\x81", NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\xCE\x99\xCC\x88", "\xCE\xA5\xCC\x88", - "\xCE\xB1\xCC\x81", "\xCE\xB5\xCC\x81", - "\xCE\xB7\xCC\x81", "\xCE\xB9\xCC\x81", - "\xCF\x85\xCC\x88\xCC\x81", NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\xCE\xB9\xCC\x88", "\xCF\x85\xCC\x88", - "\xCE\xBF\xCC\x81", "\xCF\x85\xCC\x81", - "\xCF\x89\xCC\x81", NULL, - NULL, NULL, - NULL, "\xCF\x92\xCC\x81", - "\xCF\x92\xCC\x88", NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, -}; - -static const char *const decompositionPage4[0x100] = { - "\xD0\x95\xCC\x80", "\xD0\x95\xCC\x88", - NULL, "\xD0\x93\xCC\x81", - NULL, NULL, - NULL, "\xD0\x86\xCC\x88", - NULL, NULL, - NULL, NULL, - "\xD0\x9A\xCC\x81", "\xD0\x98\xCC\x80", - "\xD0\xA3\xCC\x86", NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, "\xD0\x98\xCC\x86", - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, "\xD0\xB8\xCC\x86", - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\xD0\xB5\xCC\x80", "\xD0\xB5\xCC\x88", - NULL, "\xD0\xB3\xCC\x81", - NULL, NULL, - NULL, "\xD1\x96\xCC\x88", - NULL, NULL, - NULL, NULL, - "\xD0\xBA\xCC\x81", "\xD0\xB8\xCC\x80", - "\xD1\x83\xCC\x86", NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\xD1\xB4\xCC\x8F", "\xD1\xB5\xCC\x8F", - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, "\xD0\x96\xCC\x86", - "\xD0\xB6\xCC\x86", NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\xD0\x90\xCC\x86", "\xD0\xB0\xCC\x86", - "\xD0\x90\xCC\x88", "\xD0\xB0\xCC\x88", - NULL, NULL, - "\xD0\x95\xCC\x86", "\xD0\xB5\xCC\x86", - NULL, NULL, - "\xD3\x98\xCC\x88", "\xD3\x99\xCC\x88", - "\xD0\x96\xCC\x88", "\xD0\xB6\xCC\x88", - "\xD0\x97\xCC\x88", "\xD0\xB7\xCC\x88", - NULL, NULL, - "\xD0\x98\xCC\x84", "\xD0\xB8\xCC\x84", - "\xD0\x98\xCC\x88", "\xD0\xB8\xCC\x88", - "\xD0\x9E\xCC\x88", "\xD0\xBE\xCC\x88", - NULL, NULL, - "\xD3\xA8\xCC\x88", "\xD3\xA9\xCC\x88", - "\xD0\xAD\xCC\x88", "\xD1\x8D\xCC\x88", - "\xD0\xA3\xCC\x84", "\xD1\x83\xCC\x84", - "\xD0\xA3\xCC\x88", "\xD1\x83\xCC\x88", - "\xD0\xA3\xCC\x8B", "\xD1\x83\xCC\x8B", - "\xD0\xA7\xCC\x88", "\xD1\x87\xCC\x88", - NULL, NULL, - "\xD0\xAB\xCC\x88", "\xD1\x8B\xCC\x88", - NULL, NULL, - NULL, NULL, - NULL, NULL, -}; - -static const char *const decompositionPage6[0x100] = { - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\xD8\xA7\xD9\x93", "\xD8\xA7\xD9\x94", - "\xD9\x88\xD9\x94", "\xD8\xA7\xD9\x95", - "\xD9\x8A\xD9\x94", NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\xDB\x95\xD9\x94", NULL, - "\xDB\x81\xD9\x94", NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, "\xDB\x92\xD9\x94", - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, -}; - -static const char *const decompositionPage9[0x100] = { - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, "\xE0\xA4\xA8\xE0\xA4\xBC", - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, "\xE0\xA4\xB0\xE0\xA4\xBC", - NULL, NULL, - "\xE0\xA4\xB3\xE0\xA4\xBC", NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\xE0\xA4\x95\xE0\xA4\xBC", "\xE0\xA4\x96\xE0\xA4\xBC", - "\xE0\xA4\x97\xE0\xA4\xBC", "\xE0\xA4\x9C\xE0\xA4\xBC", - "\xE0\xA4\xA1\xE0\xA4\xBC", "\xE0\xA4\xA2\xE0\xA4\xBC", - "\xE0\xA4\xAB\xE0\xA4\xBC", "\xE0\xA4\xAF\xE0\xA4\xBC", - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, "\xE0\xA7\x87\xE0\xA6\xBE", - "\xE0\xA7\x87\xE0\xA7\x97", NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\xE0\xA6\xA1\xE0\xA6\xBC", "\xE0\xA6\xA2\xE0\xA6\xBC", - NULL, "\xE0\xA6\xAF\xE0\xA6\xBC", - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, -}; - -static const char *const decompositionPage10[0x100] = { - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, "\xE0\xA8\xB2\xE0\xA8\xBC", - NULL, NULL, - "\xE0\xA8\xB8\xE0\xA8\xBC", NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, "\xE0\xA8\x96\xE0\xA8\xBC", - "\xE0\xA8\x97\xE0\xA8\xBC", "\xE0\xA8\x9C\xE0\xA8\xBC", - NULL, NULL, - "\xE0\xA8\xAB\xE0\xA8\xBC", NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, -}; - -static const char *const decompositionPage11[0x100] = { - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\xE0\xAD\x87\xE0\xAD\x96", NULL, - NULL, "\xE0\xAD\x87\xE0\xAC\xBE", - "\xE0\xAD\x87\xE0\xAD\x97", NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\xE0\xAC\xA1\xE0\xAC\xBC", "\xE0\xAC\xA2\xE0\xAC\xBC", - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\xE0\xAE\x92\xE0\xAF\x97", NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\xE0\xAF\x86\xE0\xAE\xBE", "\xE0\xAF\x87\xE0\xAE\xBE", - "\xE0\xAF\x86\xE0\xAF\x97", NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, -}; - -static const char *const decompositionPage12[0x100] = { - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\xE0\xB1\x86\xE0\xB1\x96", NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\xE0\xB2\xBF\xE0\xB3\x95", NULL, - NULL, NULL, - NULL, NULL, - NULL, "\xE0\xB3\x86\xE0\xB3\x95", - "\xE0\xB3\x86\xE0\xB3\x96", NULL, - "\xE0\xB3\x86\xE0\xB3\x82", "\xE0\xB3\x86\xE0\xB3\x82\xE0\xB3\x95", - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, -}; - -static const char *const decompositionPage13[0x100] = { - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\xE0\xB5\x86\xE0\xB4\xBE", "\xE0\xB5\x87\xE0\xB4\xBE", - "\xE0\xB5\x86\xE0\xB5\x97", NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\xE0\xB7\x99\xE0\xB7\x8A", NULL, - "\xE0\xB7\x99\xE0\xB7\x8F", "\xE0\xB7\x99\xE0\xB7\x8F\xE0\xB7\x8A", - "\xE0\xB7\x99\xE0\xB7\x9F", NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, -}; - -static const char *const decompositionPage15[0x100] = { - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, "\xE0\xBD\x82\xE0\xBE\xB7", - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, "\xE0\xBD\x8C\xE0\xBE\xB7", - NULL, NULL, - NULL, NULL, - "\xE0\xBD\x91\xE0\xBE\xB7", NULL, - NULL, NULL, - NULL, "\xE0\xBD\x96\xE0\xBE\xB7", - NULL, NULL, - NULL, NULL, - "\xE0\xBD\x9B\xE0\xBE\xB7", NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, "\xE0\xBD\x80\xE0\xBE\xB5", - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, "\xE0\xBD\xB1\xE0\xBD\xB2", - NULL, "\xE0\xBD\xB1\xE0\xBD\xB4", - "\xE0\xBE\xB2\xE0\xBE\x80", NULL, - "\xE0\xBE\xB3\xE0\xBE\x80", NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, "\xE0\xBD\xB1\xE0\xBE\x80", - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, "\xE0\xBE\x92\xE0\xBE\xB7", - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, "\xE0\xBE\x9C\xE0\xBE\xB7", - NULL, NULL, - NULL, NULL, - "\xE0\xBE\xA1\xE0\xBE\xB7", NULL, - NULL, NULL, - NULL, "\xE0\xBE\xA6\xE0\xBE\xB7", - NULL, NULL, - NULL, NULL, - "\xE0\xBE\xAB\xE0\xBE\xB7", NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, "\xE0\xBE\x90\xE0\xBE\xB5", - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, -}; - -static const char *const decompositionPage16[0x100] = { - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\xE1\x80\xA5\xE1\x80\xAE", NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, -}; - -static const char *const decompositionPage27[0x100] = { - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\xE1\xAC\x85\xE1\xAC\xB5", NULL, - "\xE1\xAC\x87\xE1\xAC\xB5", NULL, - "\xE1\xAC\x89\xE1\xAC\xB5", NULL, - "\xE1\xAC\x8B\xE1\xAC\xB5", NULL, - "\xE1\xAC\x8D\xE1\xAC\xB5", NULL, - NULL, NULL, - "\xE1\xAC\x91\xE1\xAC\xB5", NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, "\xE1\xAC\xBA\xE1\xAC\xB5", - NULL, "\xE1\xAC\xBC\xE1\xAC\xB5", - NULL, NULL, - "\xE1\xAC\xBE\xE1\xAC\xB5", "\xE1\xAC\xBF\xE1\xAC\xB5", - NULL, "\xE1\xAD\x82\xE1\xAC\xB5", - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, -}; - -static const char *const decompositionPage30[0x100] = { - "\x41\xCC\xA5", "\x61\xCC\xA5", - "\x42\xCC\x87", "\x62\xCC\x87", - "\x42\xCC\xA3", "\x62\xCC\xA3", - "\x42\xCC\xB1", "\x62\xCC\xB1", - "\x43\xCC\xA7\xCC\x81", "\x63\xCC\xA7\xCC\x81", - "\x44\xCC\x87", "\x64\xCC\x87", - "\x44\xCC\xA3", "\x64\xCC\xA3", - "\x44\xCC\xB1", "\x64\xCC\xB1", - "\x44\xCC\xA7", "\x64\xCC\xA7", - "\x44\xCC\xAD", "\x64\xCC\xAD", - "\x45\xCC\x84\xCC\x80", "\x65\xCC\x84\xCC\x80", - "\x45\xCC\x84\xCC\x81", "\x65\xCC\x84\xCC\x81", - "\x45\xCC\xAD", "\x65\xCC\xAD", - "\x45\xCC\xB0", "\x65\xCC\xB0", - "\x45\xCC\xA7\xCC\x86", "\x65\xCC\xA7\xCC\x86", - "\x46\xCC\x87", "\x66\xCC\x87", - "\x47\xCC\x84", "\x67\xCC\x84", - "\x48\xCC\x87", "\x68\xCC\x87", - "\x48\xCC\xA3", "\x68\xCC\xA3", - "\x48\xCC\x88", "\x68\xCC\x88", - "\x48\xCC\xA7", "\x68\xCC\xA7", - "\x48\xCC\xAE", "\x68\xCC\xAE", - "\x49\xCC\xB0", "\x69\xCC\xB0", - "\x49\xCC\x88\xCC\x81", "\x69\xCC\x88\xCC\x81", - "\x4B\xCC\x81", "\x6B\xCC\x81", - "\x4B\xCC\xA3", "\x6B\xCC\xA3", - "\x4B\xCC\xB1", "\x6B\xCC\xB1", - "\x4C\xCC\xA3", "\x6C\xCC\xA3", - "\x4C\xCC\xA3\xCC\x84", "\x6C\xCC\xA3\xCC\x84", - "\x4C\xCC\xB1", "\x6C\xCC\xB1", - "\x4C\xCC\xAD", "\x6C\xCC\xAD", - "\x4D\xCC\x81", "\x6D\xCC\x81", - "\x4D\xCC\x87", "\x6D\xCC\x87", - "\x4D\xCC\xA3", "\x6D\xCC\xA3", - "\x4E\xCC\x87", "\x6E\xCC\x87", - "\x4E\xCC\xA3", "\x6E\xCC\xA3", - "\x4E\xCC\xB1", "\x6E\xCC\xB1", - "\x4E\xCC\xAD", "\x6E\xCC\xAD", - "\x4F\xCC\x83\xCC\x81", "\x6F\xCC\x83\xCC\x81", - "\x4F\xCC\x83\xCC\x88", "\x6F\xCC\x83\xCC\x88", - "\x4F\xCC\x84\xCC\x80", "\x6F\xCC\x84\xCC\x80", - "\x4F\xCC\x84\xCC\x81", "\x6F\xCC\x84\xCC\x81", - "\x50\xCC\x81", "\x70\xCC\x81", - "\x50\xCC\x87", "\x70\xCC\x87", - "\x52\xCC\x87", "\x72\xCC\x87", - "\x52\xCC\xA3", "\x72\xCC\xA3", - "\x52\xCC\xA3\xCC\x84", "\x72\xCC\xA3\xCC\x84", - "\x52\xCC\xB1", "\x72\xCC\xB1", - "\x53\xCC\x87", "\x73\xCC\x87", - "\x53\xCC\xA3", "\x73\xCC\xA3", - "\x53\xCC\x81\xCC\x87", "\x73\xCC\x81\xCC\x87", - "\x53\xCC\x8C\xCC\x87", "\x73\xCC\x8C\xCC\x87", - "\x53\xCC\xA3\xCC\x87", "\x73\xCC\xA3\xCC\x87", - "\x54\xCC\x87", "\x74\xCC\x87", - "\x54\xCC\xA3", "\x74\xCC\xA3", - "\x54\xCC\xB1", "\x74\xCC\xB1", - "\x54\xCC\xAD", "\x74\xCC\xAD", - "\x55\xCC\xA4", "\x75\xCC\xA4", - "\x55\xCC\xB0", "\x75\xCC\xB0", - "\x55\xCC\xAD", "\x75\xCC\xAD", - "\x55\xCC\x83\xCC\x81", "\x75\xCC\x83\xCC\x81", - "\x55\xCC\x84\xCC\x88", "\x75\xCC\x84\xCC\x88", - "\x56\xCC\x83", "\x76\xCC\x83", - "\x56\xCC\xA3", "\x76\xCC\xA3", - "\x57\xCC\x80", "\x77\xCC\x80", - "\x57\xCC\x81", "\x77\xCC\x81", - "\x57\xCC\x88", "\x77\xCC\x88", - "\x57\xCC\x87", "\x77\xCC\x87", - "\x57\xCC\xA3", "\x77\xCC\xA3", - "\x58\xCC\x87", "\x78\xCC\x87", - "\x58\xCC\x88", "\x78\xCC\x88", - "\x59\xCC\x87", "\x79\xCC\x87", - "\x5A\xCC\x82", "\x7A\xCC\x82", - "\x5A\xCC\xA3", "\x7A\xCC\xA3", - "\x5A\xCC\xB1", "\x7A\xCC\xB1", - "\x68\xCC\xB1", "\x74\xCC\x88", - "\x77\xCC\x8A", "\x79\xCC\x8A", - NULL, "\xC5\xBF\xCC\x87", - NULL, NULL, - NULL, NULL, - "\x41\xCC\xA3", "\x61\xCC\xA3", - "\x41\xCC\x89", "\x61\xCC\x89", - "\x41\xCC\x82\xCC\x81", "\x61\xCC\x82\xCC\x81", - "\x41\xCC\x82\xCC\x80", "\x61\xCC\x82\xCC\x80", - "\x41\xCC\x82\xCC\x89", "\x61\xCC\x82\xCC\x89", - "\x41\xCC\x82\xCC\x83", "\x61\xCC\x82\xCC\x83", - "\x41\xCC\xA3\xCC\x82", "\x61\xCC\xA3\xCC\x82", - "\x41\xCC\x86\xCC\x81", "\x61\xCC\x86\xCC\x81", - "\x41\xCC\x86\xCC\x80", "\x61\xCC\x86\xCC\x80", - "\x41\xCC\x86\xCC\x89", "\x61\xCC\x86\xCC\x89", - "\x41\xCC\x86\xCC\x83", "\x61\xCC\x86\xCC\x83", - "\x41\xCC\xA3\xCC\x86", "\x61\xCC\xA3\xCC\x86", - "\x45\xCC\xA3", "\x65\xCC\xA3", - "\x45\xCC\x89", "\x65\xCC\x89", - "\x45\xCC\x83", "\x65\xCC\x83", - "\x45\xCC\x82\xCC\x81", "\x65\xCC\x82\xCC\x81", - "\x45\xCC\x82\xCC\x80", "\x65\xCC\x82\xCC\x80", - "\x45\xCC\x82\xCC\x89", "\x65\xCC\x82\xCC\x89", - "\x45\xCC\x82\xCC\x83", "\x65\xCC\x82\xCC\x83", - "\x45\xCC\xA3\xCC\x82", "\x65\xCC\xA3\xCC\x82", - "\x49\xCC\x89", "\x69\xCC\x89", - "\x49\xCC\xA3", "\x69\xCC\xA3", - "\x4F\xCC\xA3", "\x6F\xCC\xA3", - "\x4F\xCC\x89", "\x6F\xCC\x89", - "\x4F\xCC\x82\xCC\x81", "\x6F\xCC\x82\xCC\x81", - "\x4F\xCC\x82\xCC\x80", "\x6F\xCC\x82\xCC\x80", - "\x4F\xCC\x82\xCC\x89", "\x6F\xCC\x82\xCC\x89", - "\x4F\xCC\x82\xCC\x83", "\x6F\xCC\x82\xCC\x83", - "\x4F\xCC\xA3\xCC\x82", "\x6F\xCC\xA3\xCC\x82", - "\x4F\xCC\x9B\xCC\x81", "\x6F\xCC\x9B\xCC\x81", - "\x4F\xCC\x9B\xCC\x80", "\x6F\xCC\x9B\xCC\x80", - "\x4F\xCC\x9B\xCC\x89", "\x6F\xCC\x9B\xCC\x89", - "\x4F\xCC\x9B\xCC\x83", "\x6F\xCC\x9B\xCC\x83", - "\x4F\xCC\x9B\xCC\xA3", "\x6F\xCC\x9B\xCC\xA3", - "\x55\xCC\xA3", "\x75\xCC\xA3", - "\x55\xCC\x89", "\x75\xCC\x89", - "\x55\xCC\x9B\xCC\x81", "\x75\xCC\x9B\xCC\x81", - "\x55\xCC\x9B\xCC\x80", "\x75\xCC\x9B\xCC\x80", - "\x55\xCC\x9B\xCC\x89", "\x75\xCC\x9B\xCC\x89", - "\x55\xCC\x9B\xCC\x83", "\x75\xCC\x9B\xCC\x83", - "\x55\xCC\x9B\xCC\xA3", "\x75\xCC\x9B\xCC\xA3", - "\x59\xCC\x80", "\x79\xCC\x80", - "\x59\xCC\xA3", "\x79\xCC\xA3", - "\x59\xCC\x89", "\x79\xCC\x89", - "\x59\xCC\x83", "\x79\xCC\x83", - NULL, NULL, - NULL, NULL, - NULL, NULL, -}; - -static const char *const decompositionPage31[0x100] = { - "\xCE\xB1\xCC\x93", "\xCE\xB1\xCC\x94", - "\xCE\xB1\xCC\x93\xCC\x80", "\xCE\xB1\xCC\x94\xCC\x80", - "\xCE\xB1\xCC\x93\xCC\x81", "\xCE\xB1\xCC\x94\xCC\x81", - "\xCE\xB1\xCC\x93\xCD\x82", "\xCE\xB1\xCC\x94\xCD\x82", - "\xCE\x91\xCC\x93", "\xCE\x91\xCC\x94", - "\xCE\x91\xCC\x93\xCC\x80", "\xCE\x91\xCC\x94\xCC\x80", - "\xCE\x91\xCC\x93\xCC\x81", "\xCE\x91\xCC\x94\xCC\x81", - "\xCE\x91\xCC\x93\xCD\x82", "\xCE\x91\xCC\x94\xCD\x82", - "\xCE\xB5\xCC\x93", "\xCE\xB5\xCC\x94", - "\xCE\xB5\xCC\x93\xCC\x80", "\xCE\xB5\xCC\x94\xCC\x80", - "\xCE\xB5\xCC\x93\xCC\x81", "\xCE\xB5\xCC\x94\xCC\x81", - NULL, NULL, - "\xCE\x95\xCC\x93", "\xCE\x95\xCC\x94", - "\xCE\x95\xCC\x93\xCC\x80", "\xCE\x95\xCC\x94\xCC\x80", - "\xCE\x95\xCC\x93\xCC\x81", "\xCE\x95\xCC\x94\xCC\x81", - NULL, NULL, - "\xCE\xB7\xCC\x93", "\xCE\xB7\xCC\x94", - "\xCE\xB7\xCC\x93\xCC\x80", "\xCE\xB7\xCC\x94\xCC\x80", - "\xCE\xB7\xCC\x93\xCC\x81", "\xCE\xB7\xCC\x94\xCC\x81", - "\xCE\xB7\xCC\x93\xCD\x82", "\xCE\xB7\xCC\x94\xCD\x82", - "\xCE\x97\xCC\x93", "\xCE\x97\xCC\x94", - "\xCE\x97\xCC\x93\xCC\x80", "\xCE\x97\xCC\x94\xCC\x80", - "\xCE\x97\xCC\x93\xCC\x81", "\xCE\x97\xCC\x94\xCC\x81", - "\xCE\x97\xCC\x93\xCD\x82", "\xCE\x97\xCC\x94\xCD\x82", - "\xCE\xB9\xCC\x93", "\xCE\xB9\xCC\x94", - "\xCE\xB9\xCC\x93\xCC\x80", "\xCE\xB9\xCC\x94\xCC\x80", - "\xCE\xB9\xCC\x93\xCC\x81", "\xCE\xB9\xCC\x94\xCC\x81", - "\xCE\xB9\xCC\x93\xCD\x82", "\xCE\xB9\xCC\x94\xCD\x82", - "\xCE\x99\xCC\x93", "\xCE\x99\xCC\x94", - "\xCE\x99\xCC\x93\xCC\x80", "\xCE\x99\xCC\x94\xCC\x80", - "\xCE\x99\xCC\x93\xCC\x81", "\xCE\x99\xCC\x94\xCC\x81", - "\xCE\x99\xCC\x93\xCD\x82", "\xCE\x99\xCC\x94\xCD\x82", - "\xCE\xBF\xCC\x93", "\xCE\xBF\xCC\x94", - "\xCE\xBF\xCC\x93\xCC\x80", "\xCE\xBF\xCC\x94\xCC\x80", - "\xCE\xBF\xCC\x93\xCC\x81", "\xCE\xBF\xCC\x94\xCC\x81", - NULL, NULL, - "\xCE\x9F\xCC\x93", "\xCE\x9F\xCC\x94", - "\xCE\x9F\xCC\x93\xCC\x80", "\xCE\x9F\xCC\x94\xCC\x80", - "\xCE\x9F\xCC\x93\xCC\x81", "\xCE\x9F\xCC\x94\xCC\x81", - NULL, NULL, - "\xCF\x85\xCC\x93", "\xCF\x85\xCC\x94", - "\xCF\x85\xCC\x93\xCC\x80", "\xCF\x85\xCC\x94\xCC\x80", - "\xCF\x85\xCC\x93\xCC\x81", "\xCF\x85\xCC\x94\xCC\x81", - "\xCF\x85\xCC\x93\xCD\x82", "\xCF\x85\xCC\x94\xCD\x82", - NULL, "\xCE\xA5\xCC\x94", - NULL, "\xCE\xA5\xCC\x94\xCC\x80", - NULL, "\xCE\xA5\xCC\x94\xCC\x81", - NULL, "\xCE\xA5\xCC\x94\xCD\x82", - "\xCF\x89\xCC\x93", "\xCF\x89\xCC\x94", - "\xCF\x89\xCC\x93\xCC\x80", "\xCF\x89\xCC\x94\xCC\x80", - "\xCF\x89\xCC\x93\xCC\x81", "\xCF\x89\xCC\x94\xCC\x81", - "\xCF\x89\xCC\x93\xCD\x82", "\xCF\x89\xCC\x94\xCD\x82", - "\xCE\xA9\xCC\x93", "\xCE\xA9\xCC\x94", - "\xCE\xA9\xCC\x93\xCC\x80", "\xCE\xA9\xCC\x94\xCC\x80", - "\xCE\xA9\xCC\x93\xCC\x81", "\xCE\xA9\xCC\x94\xCC\x81", - "\xCE\xA9\xCC\x93\xCD\x82", "\xCE\xA9\xCC\x94\xCD\x82", - "\xCE\xB1\xCC\x80", "\xCE\xB1\xCC\x81", - "\xCE\xB5\xCC\x80", "\xCE\xB5\xCC\x81", - "\xCE\xB7\xCC\x80", "\xCE\xB7\xCC\x81", - "\xCE\xB9\xCC\x80", "\xCE\xB9\xCC\x81", - "\xCE\xBF\xCC\x80", "\xCE\xBF\xCC\x81", - "\xCF\x85\xCC\x80", "\xCF\x85\xCC\x81", - "\xCF\x89\xCC\x80", "\xCF\x89\xCC\x81", - NULL, NULL, - "\xCE\xB1\xCC\x93\xCD\x85", "\xCE\xB1\xCC\x94\xCD\x85", - "\xCE\xB1\xCC\x93\xCC\x80\xCD\x85", "\xCE\xB1\xCC\x94\xCC\x80\xCD\x85", - "\xCE\xB1\xCC\x93\xCC\x81\xCD\x85", "\xCE\xB1\xCC\x94\xCC\x81\xCD\x85", - "\xCE\xB1\xCC\x93\xCD\x82\xCD\x85", "\xCE\xB1\xCC\x94\xCD\x82\xCD\x85", - "\xCE\x91\xCC\x93\xCD\x85", "\xCE\x91\xCC\x94\xCD\x85", - "\xCE\x91\xCC\x93\xCC\x80\xCD\x85", "\xCE\x91\xCC\x94\xCC\x80\xCD\x85", - "\xCE\x91\xCC\x93\xCC\x81\xCD\x85", "\xCE\x91\xCC\x94\xCC\x81\xCD\x85", - "\xCE\x91\xCC\x93\xCD\x82\xCD\x85", "\xCE\x91\xCC\x94\xCD\x82\xCD\x85", - "\xCE\xB7\xCC\x93\xCD\x85", "\xCE\xB7\xCC\x94\xCD\x85", - "\xCE\xB7\xCC\x93\xCC\x80\xCD\x85", "\xCE\xB7\xCC\x94\xCC\x80\xCD\x85", - "\xCE\xB7\xCC\x93\xCC\x81\xCD\x85", "\xCE\xB7\xCC\x94\xCC\x81\xCD\x85", - "\xCE\xB7\xCC\x93\xCD\x82\xCD\x85", "\xCE\xB7\xCC\x94\xCD\x82\xCD\x85", - "\xCE\x97\xCC\x93\xCD\x85", "\xCE\x97\xCC\x94\xCD\x85", - "\xCE\x97\xCC\x93\xCC\x80\xCD\x85", "\xCE\x97\xCC\x94\xCC\x80\xCD\x85", - "\xCE\x97\xCC\x93\xCC\x81\xCD\x85", "\xCE\x97\xCC\x94\xCC\x81\xCD\x85", - "\xCE\x97\xCC\x93\xCD\x82\xCD\x85", "\xCE\x97\xCC\x94\xCD\x82\xCD\x85", - "\xCF\x89\xCC\x93\xCD\x85", "\xCF\x89\xCC\x94\xCD\x85", - "\xCF\x89\xCC\x93\xCC\x80\xCD\x85", "\xCF\x89\xCC\x94\xCC\x80\xCD\x85", - "\xCF\x89\xCC\x93\xCC\x81\xCD\x85", "\xCF\x89\xCC\x94\xCC\x81\xCD\x85", - "\xCF\x89\xCC\x93\xCD\x82\xCD\x85", "\xCF\x89\xCC\x94\xCD\x82\xCD\x85", - "\xCE\xA9\xCC\x93\xCD\x85", "\xCE\xA9\xCC\x94\xCD\x85", - "\xCE\xA9\xCC\x93\xCC\x80\xCD\x85", "\xCE\xA9\xCC\x94\xCC\x80\xCD\x85", - "\xCE\xA9\xCC\x93\xCC\x81\xCD\x85", "\xCE\xA9\xCC\x94\xCC\x81\xCD\x85", - "\xCE\xA9\xCC\x93\xCD\x82\xCD\x85", "\xCE\xA9\xCC\x94\xCD\x82\xCD\x85", - "\xCE\xB1\xCC\x86", "\xCE\xB1\xCC\x84", - "\xCE\xB1\xCC\x80\xCD\x85", "\xCE\xB1\xCD\x85", - "\xCE\xB1\xCC\x81\xCD\x85", NULL, - "\xCE\xB1\xCD\x82", "\xCE\xB1\xCD\x82\xCD\x85", - "\xCE\x91\xCC\x86", "\xCE\x91\xCC\x84", - "\xCE\x91\xCC\x80", "\xCE\x91\xCC\x81", - "\xCE\x91\xCD\x85", NULL, - "\xCE\xB9", NULL, - NULL, "\xC2\xA8\xCD\x82", - "\xCE\xB7\xCC\x80\xCD\x85", "\xCE\xB7\xCD\x85", - "\xCE\xB7\xCC\x81\xCD\x85", NULL, - "\xCE\xB7\xCD\x82", "\xCE\xB7\xCD\x82\xCD\x85", - "\xCE\x95\xCC\x80", "\xCE\x95\xCC\x81", - "\xCE\x97\xCC\x80", "\xCE\x97\xCC\x81", - "\xCE\x97\xCD\x85", "\xE1\xBE\xBF\xCC\x80", - "\xE1\xBE\xBF\xCC\x81", "\xE1\xBE\xBF\xCD\x82", - "\xCE\xB9\xCC\x86", "\xCE\xB9\xCC\x84", - "\xCE\xB9\xCC\x88\xCC\x80", "\xCE\xB9\xCC\x88\xCC\x81", - NULL, NULL, - "\xCE\xB9\xCD\x82", "\xCE\xB9\xCC\x88\xCD\x82", - "\xCE\x99\xCC\x86", "\xCE\x99\xCC\x84", - "\xCE\x99\xCC\x80", "\xCE\x99\xCC\x81", - NULL, "\xE1\xBF\xBE\xCC\x80", - "\xE1\xBF\xBE\xCC\x81", "\xE1\xBF\xBE\xCD\x82", - "\xCF\x85\xCC\x86", "\xCF\x85\xCC\x84", - "\xCF\x85\xCC\x88\xCC\x80", "\xCF\x85\xCC\x88\xCC\x81", - "\xCF\x81\xCC\x93", "\xCF\x81\xCC\x94", - "\xCF\x85\xCD\x82", "\xCF\x85\xCC\x88\xCD\x82", - "\xCE\xA5\xCC\x86", "\xCE\xA5\xCC\x84", - "\xCE\xA5\xCC\x80", "\xCE\xA5\xCC\x81", - "\xCE\xA1\xCC\x94", "\xC2\xA8\xCC\x80", - "\xC2\xA8\xCC\x81", "\x60", - NULL, NULL, - "\xCF\x89\xCC\x80\xCD\x85", "\xCF\x89\xCD\x85", - "\xCF\x89\xCC\x81\xCD\x85", NULL, - "\xCF\x89\xCD\x82", "\xCF\x89\xCD\x82\xCD\x85", - "\xCE\x9F\xCC\x80", "\xCE\x9F\xCC\x81", - "\xCE\xA9\xCC\x80", "\xCE\xA9\xCC\x81", - "\xCE\xA9\xCD\x85", "\xC2\xB4", - NULL, NULL, -}; - -static const char *const decompositionPage32[0x100] = { - "\xE2\x80\x82", "\xE2\x80\x83", - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, -}; - -static const char *const decompositionPage33[0x100] = { - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\xCE\xA9", NULL, - NULL, NULL, - "\x4B", "\x41\xCC\x8A", - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\xE2\x86\x90\xCC\xB8", "\xE2\x86\x92\xCC\xB8", - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\xE2\x86\x94\xCC\xB8", NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, "\xE2\x87\x90\xCC\xB8", - "\xE2\x87\x94\xCC\xB8", "\xE2\x87\x92\xCC\xB8", - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, -}; - -static const char *const decompositionPage34[0x100] = { - NULL, NULL, - NULL, NULL, - "\xE2\x88\x83\xCC\xB8", NULL, - NULL, NULL, - NULL, "\xE2\x88\x88\xCC\xB8", - NULL, NULL, - "\xE2\x88\x8B\xCC\xB8", NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\xE2\x88\xA3\xCC\xB8", NULL, - "\xE2\x88\xA5\xCC\xB8", NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, "\xE2\x88\xBC\xCC\xB8", - NULL, NULL, - "\xE2\x89\x83\xCC\xB8", NULL, - NULL, "\xE2\x89\x85\xCC\xB8", - NULL, "\xE2\x89\x88\xCC\xB8", - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\x3D\xCC\xB8", NULL, - "\xE2\x89\xA1\xCC\xB8", NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, "\xE2\x89\x8D\xCC\xB8", - "\x3C\xCC\xB8", "\x3E\xCC\xB8", - "\xE2\x89\xA4\xCC\xB8", "\xE2\x89\xA5\xCC\xB8", - NULL, NULL, - "\xE2\x89\xB2\xCC\xB8", "\xE2\x89\xB3\xCC\xB8", - NULL, NULL, - "\xE2\x89\xB6\xCC\xB8", "\xE2\x89\xB7\xCC\xB8", - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\xE2\x89\xBA\xCC\xB8", "\xE2\x89\xBB\xCC\xB8", - NULL, NULL, - "\xE2\x8A\x82\xCC\xB8", "\xE2\x8A\x83\xCC\xB8", - NULL, NULL, - "\xE2\x8A\x86\xCC\xB8", "\xE2\x8A\x87\xCC\xB8", - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\xE2\x8A\xA2\xCC\xB8", "\xE2\x8A\xA8\xCC\xB8", - "\xE2\x8A\xA9\xCC\xB8", "\xE2\x8A\xAB\xCC\xB8", - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\xE2\x89\xBC\xCC\xB8", "\xE2\x89\xBD\xCC\xB8", - "\xE2\x8A\x91\xCC\xB8", "\xE2\x8A\x92\xCC\xB8", - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\xE2\x8A\xB2\xCC\xB8", "\xE2\x8A\xB3\xCC\xB8", - "\xE2\x8A\xB4\xCC\xB8", "\xE2\x8A\xB5\xCC\xB8", - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, -}; - -static const char *const decompositionPage35[0x100] = { - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, "\xE3\x80\x88", - "\xE3\x80\x89", NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, -}; - -static const char *const decompositionPage42[0x100] = { - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\xE2\xAB\x9D\xCC\xB8", NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, -}; - -static const char *const decompositionPage48[0x100] = { - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\xE3\x81\x8B\xE3\x82\x99", NULL, - "\xE3\x81\x8D\xE3\x82\x99", NULL, - "\xE3\x81\x8F\xE3\x82\x99", NULL, - "\xE3\x81\x91\xE3\x82\x99", NULL, - "\xE3\x81\x93\xE3\x82\x99", NULL, - "\xE3\x81\x95\xE3\x82\x99", NULL, - "\xE3\x81\x97\xE3\x82\x99", NULL, - "\xE3\x81\x99\xE3\x82\x99", NULL, - "\xE3\x81\x9B\xE3\x82\x99", NULL, - "\xE3\x81\x9D\xE3\x82\x99", NULL, - "\xE3\x81\x9F\xE3\x82\x99", NULL, - "\xE3\x81\xA1\xE3\x82\x99", NULL, - NULL, "\xE3\x81\xA4\xE3\x82\x99", - NULL, "\xE3\x81\xA6\xE3\x82\x99", - NULL, "\xE3\x81\xA8\xE3\x82\x99", - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\xE3\x81\xAF\xE3\x82\x99", "\xE3\x81\xAF\xE3\x82\x9A", - NULL, "\xE3\x81\xB2\xE3\x82\x99", - "\xE3\x81\xB2\xE3\x82\x9A", NULL, - "\xE3\x81\xB5\xE3\x82\x99", "\xE3\x81\xB5\xE3\x82\x9A", - NULL, "\xE3\x81\xB8\xE3\x82\x99", - "\xE3\x81\xB8\xE3\x82\x9A", NULL, - "\xE3\x81\xBB\xE3\x82\x99", "\xE3\x81\xBB\xE3\x82\x9A", - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\xE3\x81\x86\xE3\x82\x99", NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\xE3\x82\x9D\xE3\x82\x99", NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\xE3\x82\xAB\xE3\x82\x99", NULL, - "\xE3\x82\xAD\xE3\x82\x99", NULL, - "\xE3\x82\xAF\xE3\x82\x99", NULL, - "\xE3\x82\xB1\xE3\x82\x99", NULL, - "\xE3\x82\xB3\xE3\x82\x99", NULL, - "\xE3\x82\xB5\xE3\x82\x99", NULL, - "\xE3\x82\xB7\xE3\x82\x99", NULL, - "\xE3\x82\xB9\xE3\x82\x99", NULL, - "\xE3\x82\xBB\xE3\x82\x99", NULL, - "\xE3\x82\xBD\xE3\x82\x99", NULL, - "\xE3\x82\xBF\xE3\x82\x99", NULL, - "\xE3\x83\x81\xE3\x82\x99", NULL, - NULL, "\xE3\x83\x84\xE3\x82\x99", - NULL, "\xE3\x83\x86\xE3\x82\x99", - NULL, "\xE3\x83\x88\xE3\x82\x99", - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\xE3\x83\x8F\xE3\x82\x99", "\xE3\x83\x8F\xE3\x82\x9A", - NULL, "\xE3\x83\x92\xE3\x82\x99", - "\xE3\x83\x92\xE3\x82\x9A", NULL, - "\xE3\x83\x95\xE3\x82\x99", "\xE3\x83\x95\xE3\x82\x9A", - NULL, "\xE3\x83\x98\xE3\x82\x99", - "\xE3\x83\x98\xE3\x82\x9A", NULL, - "\xE3\x83\x9B\xE3\x82\x99", "\xE3\x83\x9B\xE3\x82\x9A", - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\xE3\x82\xA6\xE3\x82\x99", NULL, - NULL, "\xE3\x83\xAF\xE3\x82\x99", - "\xE3\x83\xB0\xE3\x82\x99", "\xE3\x83\xB1\xE3\x82\x99", - "\xE3\x83\xB2\xE3\x82\x99", NULL, - NULL, NULL, - "\xE3\x83\xBD\xE3\x82\x99", NULL, -}; - -static const char *const decompositionPage249[0x100] = { - "\xE8\xB1\x88", "\xE6\x9B\xB4", - "\xE8\xBB\x8A", "\xE8\xB3\x88", - "\xE6\xBB\x91", "\xE4\xB8\xB2", - "\xE5\x8F\xA5", "\xE9\xBE\x9C", - "\xE9\xBE\x9C", "\xE5\xA5\x91", - "\xE9\x87\x91", "\xE5\x96\x87", - "\xE5\xA5\x88", "\xE6\x87\xB6", - "\xE7\x99\xA9", "\xE7\xBE\x85", - "\xE8\x98\xBF", "\xE8\x9E\xBA", - "\xE8\xA3\xB8", "\xE9\x82\x8F", - "\xE6\xA8\x82", "\xE6\xB4\x9B", - "\xE7\x83\x99", "\xE7\x8F\x9E", - "\xE8\x90\xBD", "\xE9\x85\xAA", - "\xE9\xA7\xB1", "\xE4\xBA\x82", - "\xE5\x8D\xB5", "\xE6\xAC\x84", - "\xE7\x88\x9B", "\xE8\x98\xAD", - "\xE9\xB8\x9E", "\xE5\xB5\x90", - "\xE6\xBF\xAB", "\xE8\x97\x8D", - "\xE8\xA5\xA4", "\xE6\x8B\x89", - "\xE8\x87\x98", "\xE8\xA0\x9F", - "\xE5\xBB\x8A", "\xE6\x9C\x97", - "\xE6\xB5\xAA", "\xE7\x8B\xBC", - "\xE9\x83\x8E", "\xE4\xBE\x86", - "\xE5\x86\xB7", "\xE5\x8B\x9E", - "\xE6\x93\x84", "\xE6\xAB\x93", - "\xE7\x88\x90", "\xE7\x9B\xA7", - "\xE8\x80\x81", "\xE8\x98\x86", - "\xE8\x99\x9C", "\xE8\xB7\xAF", - "\xE9\x9C\xB2", "\xE9\xAD\xAF", - "\xE9\xB7\xBA", "\xE7\xA2\x8C", - "\xE7\xA5\xBF", "\xE7\xB6\xA0", - "\xE8\x8F\x89", "\xE9\x8C\x84", - "\xE9\xB9\xBF", "\xE8\xAB\x96", - "\xE5\xA3\x9F", "\xE5\xBC\x84", - "\xE7\xB1\xA0", "\xE8\x81\xBE", - "\xE7\x89\xA2", "\xE7\xA3\x8A", - "\xE8\xB3\x82", "\xE9\x9B\xB7", - "\xE5\xA3\x98", "\xE5\xB1\xA2", - "\xE6\xA8\x93", "\xE6\xB7\x9A", - "\xE6\xBC\x8F", "\xE7\xB4\xAF", - "\xE7\xB8\xB7", "\xE9\x99\x8B", - "\xE5\x8B\x92", "\xE8\x82\x8B", - "\xE5\x87\x9C", "\xE5\x87\x8C", - "\xE7\xA8\x9C", "\xE7\xB6\xBE", - "\xE8\x8F\xB1", "\xE9\x99\xB5", - "\xE8\xAE\x80", "\xE6\x8B\x8F", - "\xE6\xA8\x82", "\xE8\xAB\xBE", - "\xE4\xB8\xB9", "\xE5\xAF\xA7", - "\xE6\x80\x92", "\xE7\x8E\x87", - "\xE7\x95\xB0", "\xE5\x8C\x97", - "\xE7\xA3\xBB", "\xE4\xBE\xBF", - "\xE5\xBE\xA9", "\xE4\xB8\x8D", - "\xE6\xB3\x8C", "\xE6\x95\xB8", - "\xE7\xB4\xA2", "\xE5\x8F\x83", - "\xE5\xA1\x9E", "\xE7\x9C\x81", - "\xE8\x91\x89", "\xE8\xAA\xAA", - "\xE6\xAE\xBA", "\xE8\xBE\xB0", - "\xE6\xB2\x88", "\xE6\x8B\xBE", - "\xE8\x8B\xA5", "\xE6\x8E\xA0", - "\xE7\x95\xA5", "\xE4\xBA\xAE", - "\xE5\x85\xA9", "\xE5\x87\x89", - "\xE6\xA2\x81", "\xE7\xB3\xA7", - "\xE8\x89\xAF", "\xE8\xAB\x92", - "\xE9\x87\x8F", "\xE5\x8B\xB5", - "\xE5\x91\x82", "\xE5\xA5\xB3", - "\xE5\xBB\xAC", "\xE6\x97\x85", - "\xE6\xBF\xBE", "\xE7\xA4\xAA", - "\xE9\x96\xAD", "\xE9\xA9\xAA", - "\xE9\xBA\x97", "\xE9\xBB\x8E", - "\xE5\x8A\x9B", "\xE6\x9B\x86", - "\xE6\xAD\xB7", "\xE8\xBD\xA2", - "\xE5\xB9\xB4", "\xE6\x86\x90", - "\xE6\x88\x80", "\xE6\x92\x9A", - "\xE6\xBC\xA3", "\xE7\x85\x89", - "\xE7\x92\x89", "\xE7\xA7\x8A", - "\xE7\xB7\xB4", "\xE8\x81\xAF", - "\xE8\xBC\xA6", "\xE8\x93\xAE", - "\xE9\x80\xA3", "\xE9\x8D\x8A", - "\xE5\x88\x97", "\xE5\x8A\xA3", - "\xE5\x92\xBD", "\xE7\x83\x88", - "\xE8\xA3\x82", "\xE8\xAA\xAA", - "\xE5\xBB\x89", "\xE5\xBF\xB5", - "\xE6\x8D\xBB", "\xE6\xAE\xAE", - "\xE7\xB0\xBE", "\xE7\x8D\xB5", - "\xE4\xBB\xA4", "\xE5\x9B\xB9", - "\xE5\xAF\xA7", "\xE5\xB6\xBA", - "\xE6\x80\x9C", "\xE7\x8E\xB2", - "\xE7\x91\xA9", "\xE7\xBE\x9A", - "\xE8\x81\x86", "\xE9\x88\xB4", - "\xE9\x9B\xB6", "\xE9\x9D\x88", - "\xE9\xA0\x98", "\xE4\xBE\x8B", - "\xE7\xA6\xAE", "\xE9\x86\xB4", - "\xE9\x9A\xB8", "\xE6\x83\xA1", - "\xE4\xBA\x86", "\xE5\x83\x9A", - "\xE5\xAF\xAE", "\xE5\xB0\xBF", - "\xE6\x96\x99", "\xE6\xA8\x82", - "\xE7\x87\x8E", "\xE7\x99\x82", - "\xE8\x93\xBC", "\xE9\x81\xBC", - "\xE9\xBE\x8D", "\xE6\x9A\x88", - "\xE9\x98\xAE", "\xE5\x8A\x89", - "\xE6\x9D\xBB", "\xE6\x9F\xB3", - "\xE6\xB5\x81", "\xE6\xBA\x9C", - "\xE7\x90\x89", "\xE7\x95\x99", - "\xE7\xA1\xAB", "\xE7\xB4\x90", - "\xE9\xA1\x9E", "\xE5\x85\xAD", - "\xE6\x88\xAE", "\xE9\x99\xB8", - "\xE5\x80\xAB", "\xE5\xB4\x99", - "\xE6\xB7\xAA", "\xE8\xBC\xAA", - "\xE5\xBE\x8B", "\xE6\x85\x84", - "\xE6\xA0\x97", "\xE7\x8E\x87", - "\xE9\x9A\x86", "\xE5\x88\xA9", - "\xE5\x90\x8F", "\xE5\xB1\xA5", - "\xE6\x98\x93", "\xE6\x9D\x8E", - "\xE6\xA2\xA8", "\xE6\xB3\xA5", - "\xE7\x90\x86", "\xE7\x97\xA2", - "\xE7\xBD\xB9", "\xE8\xA3\x8F", - "\xE8\xA3\xA1", "\xE9\x87\x8C", - "\xE9\x9B\xA2", "\xE5\x8C\xBF", - "\xE6\xBA\xBA", "\xE5\x90\x9D", - "\xE7\x87\x90", "\xE7\x92\x98", - "\xE8\x97\xBA", "\xE9\x9A\xA3", - "\xE9\xB1\x97", "\xE9\xBA\x9F", - "\xE6\x9E\x97", "\xE6\xB7\x8B", - "\xE8\x87\xA8", "\xE7\xAB\x8B", - "\xE7\xAC\xA0", "\xE7\xB2\x92", - "\xE7\x8B\x80", "\xE7\x82\x99", - "\xE8\xAD\x98", "\xE4\xBB\x80", - "\xE8\x8C\xB6", "\xE5\x88\xBA", -}; - -static const char *const decompositionPage250[0x100] = { - "\xE5\x88\x87", "\xE5\xBA\xA6", - "\xE6\x8B\x93", "\xE7\xB3\x96", - "\xE5\xAE\x85", "\xE6\xB4\x9E", - "\xE6\x9A\xB4", "\xE8\xBC\xBB", - "\xE8\xA1\x8C", "\xE9\x99\x8D", - "\xE8\xA6\x8B", "\xE5\xBB\x93", - "\xE5\x85\x80", "\xE5\x97\x80", - NULL, NULL, - "\xE5\xA1\x9A", NULL, - "\xE6\x99\xB4", NULL, - NULL, "\xE5\x87\x9E", - "\xE7\x8C\xAA", "\xE7\x9B\x8A", - "\xE7\xA4\xBC", "\xE7\xA5\x9E", - "\xE7\xA5\xA5", "\xE7\xA6\x8F", - "\xE9\x9D\x96", "\xE7\xB2\xBE", - "\xE7\xBE\xBD", NULL, - "\xE8\x98\x92", NULL, - "\xE8\xAB\xB8", NULL, - NULL, "\xE9\x80\xB8", - "\xE9\x83\xBD", NULL, - NULL, NULL, - "\xE9\xA3\xAF", "\xE9\xA3\xBC", - "\xE9\xA4\xA8", "\xE9\xB6\xB4", - "\xE9\x83\x9E", "\xE9\x9A\xB7", - "\xE4\xBE\xAE", "\xE5\x83\xA7", - "\xE5\x85\x8D", "\xE5\x8B\x89", - "\xE5\x8B\xA4", "\xE5\x8D\x91", - "\xE5\x96\x9D", "\xE5\x98\x86", - "\xE5\x99\xA8", "\xE5\xA1\x80", - "\xE5\xA2\xA8", "\xE5\xB1\xA4", - "\xE5\xB1\xAE", "\xE6\x82\x94", - "\xE6\x85\xA8", "\xE6\x86\x8E", - "\xE6\x87\xB2", "\xE6\x95\x8F", - "\xE6\x97\xA2", "\xE6\x9A\x91", - "\xE6\xA2\x85", "\xE6\xB5\xB7", - "\xE6\xB8\x9A", "\xE6\xBC\xA2", - "\xE7\x85\xAE", "\xE7\x88\xAB", - "\xE7\x90\xA2", "\xE7\xA2\x91", - "\xE7\xA4\xBE", "\xE7\xA5\x89", - "\xE7\xA5\x88", "\xE7\xA5\x90", - "\xE7\xA5\x96", "\xE7\xA5\x9D", - "\xE7\xA6\x8D", "\xE7\xA6\x8E", - "\xE7\xA9\x80", "\xE7\xAA\x81", - "\xE7\xAF\x80", "\xE7\xB7\xB4", - "\xE7\xB8\x89", "\xE7\xB9\x81", - "\xE7\xBD\xB2", "\xE8\x80\x85", - "\xE8\x87\xAD", "\xE8\x89\xB9", - "\xE8\x89\xB9", "\xE8\x91\x97", - "\xE8\xA4\x90", "\xE8\xA6\x96", - "\xE8\xAC\x81", "\xE8\xAC\xB9", - "\xE8\xB3\x93", "\xE8\xB4\x88", - "\xE8\xBE\xB6", "\xE9\x80\xB8", - "\xE9\x9B\xA3", "\xE9\x9F\xBF", - "\xE9\xA0\xBB", "\xE6\x81\xB5", - "\xF0\xA4\x8B\xAE", "\xE8\x88\x98", - NULL, NULL, - "\xE4\xB8\xA6", "\xE5\x86\xB5", - "\xE5\x85\xA8", "\xE4\xBE\x80", - "\xE5\x85\x85", "\xE5\x86\x80", - "\xE5\x8B\x87", "\xE5\x8B\xBA", - "\xE5\x96\x9D", "\xE5\x95\x95", - "\xE5\x96\x99", "\xE5\x97\xA2", - "\xE5\xA1\x9A", "\xE5\xA2\xB3", - "\xE5\xA5\x84", "\xE5\xA5\x94", - "\xE5\xA9\xA2", "\xE5\xAC\xA8", - "\xE5\xBB\x92", "\xE5\xBB\x99", - "\xE5\xBD\xA9", "\xE5\xBE\xAD", - "\xE6\x83\x98", "\xE6\x85\x8E", - "\xE6\x84\x88", "\xE6\x86\x8E", - "\xE6\x85\xA0", "\xE6\x87\xB2", - "\xE6\x88\xB4", "\xE6\x8F\x84", - "\xE6\x90\x9C", "\xE6\x91\x92", - "\xE6\x95\x96", "\xE6\x99\xB4", - "\xE6\x9C\x97", "\xE6\x9C\x9B", - "\xE6\x9D\x96", "\xE6\xAD\xB9", - "\xE6\xAE\xBA", "\xE6\xB5\x81", - "\xE6\xBB\x9B", "\xE6\xBB\x8B", - "\xE6\xBC\xA2", "\xE7\x80\x9E", - "\xE7\x85\xAE", "\xE7\x9E\xA7", - "\xE7\x88\xB5", "\xE7\x8A\xAF", - "\xE7\x8C\xAA", "\xE7\x91\xB1", - "\xE7\x94\x86", "\xE7\x94\xBB", - "\xE7\x98\x9D", "\xE7\x98\x9F", - "\xE7\x9B\x8A", "\xE7\x9B\x9B", - "\xE7\x9B\xB4", "\xE7\x9D\x8A", - "\xE7\x9D\x80", "\xE7\xA3\x8C", - "\xE7\xAA\xB1", "\xE7\xAF\x80", - "\xE7\xB1\xBB", "\xE7\xB5\x9B", - "\xE7\xB7\xB4", "\xE7\xBC\xBE", - "\xE8\x80\x85", "\xE8\x8D\x92", - "\xE8\x8F\xAF", "\xE8\x9D\xB9", - "\xE8\xA5\x81", "\xE8\xA6\x86", - "\xE8\xA6\x96", "\xE8\xAA\xBF", - "\xE8\xAB\xB8", "\xE8\xAB\x8B", - "\xE8\xAC\x81", "\xE8\xAB\xBE", - "\xE8\xAB\xAD", "\xE8\xAC\xB9", - "\xE8\xAE\x8A", "\xE8\xB4\x88", - "\xE8\xBC\xB8", "\xE9\x81\xB2", - "\xE9\x86\x99", "\xE9\x89\xB6", - "\xE9\x99\xBC", "\xE9\x9B\xA3", - "\xE9\x9D\x96", "\xE9\x9F\x9B", - "\xE9\x9F\xBF", "\xE9\xA0\x8B", - "\xE9\xA0\xBB", "\xE9\xAC\x92", - "\xE9\xBE\x9C", "\xF0\xA2\xA1\x8A", - "\xF0\xA2\xA1\x84", "\xF0\xA3\x8F\x95", - "\xE3\xAE\x9D", "\xE4\x80\x98", - "\xE4\x80\xB9", "\xF0\xA5\x89\x89", - "\xF0\xA5\xB3\x90", "\xF0\xA7\xBB\x93", - "\xE9\xBD\x83", "\xE9\xBE\x8E", - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, -}; - -static const char *const decompositionPage251[0x100] = { - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, "\xD7\x99\xD6\xB4", - NULL, "\xD7\xB2\xD6\xB7", - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\xD7\xA9\xD7\x81", "\xD7\xA9\xD7\x82", - "\xD7\xA9\xD6\xBC\xD7\x81", "\xD7\xA9\xD6\xBC\xD7\x82", - "\xD7\x90\xD6\xB7", "\xD7\x90\xD6\xB8", - "\xD7\x90\xD6\xBC", "\xD7\x91\xD6\xBC", - "\xD7\x92\xD6\xBC", "\xD7\x93\xD6\xBC", - "\xD7\x94\xD6\xBC", "\xD7\x95\xD6\xBC", - "\xD7\x96\xD6\xBC", NULL, - "\xD7\x98\xD6\xBC", "\xD7\x99\xD6\xBC", - "\xD7\x9A\xD6\xBC", "\xD7\x9B\xD6\xBC", - "\xD7\x9C\xD6\xBC", NULL, - "\xD7\x9E\xD6\xBC", NULL, - "\xD7\xA0\xD6\xBC", "\xD7\xA1\xD6\xBC", - NULL, "\xD7\xA3\xD6\xBC", - "\xD7\xA4\xD6\xBC", NULL, - "\xD7\xA6\xD6\xBC", "\xD7\xA7\xD6\xBC", - "\xD7\xA8\xD6\xBC", "\xD7\xA9\xD6\xBC", - "\xD7\xAA\xD6\xBC", "\xD7\x95\xD6\xB9", - "\xD7\x91\xD6\xBF", "\xD7\x9B\xD6\xBF", - "\xD7\xA4\xD6\xBF", NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, -}; - -static const char *const decompositionPage272[0x100] = { - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\xF0\x91\x82\x99\xF0\x91\x82\xBA", NULL, - "\xF0\x91\x82\x9B\xF0\x91\x82\xBA", NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, "\xF0\x91\x82\xA5\xF0\x91\x82\xBA", - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, -}; - -static const char *const decompositionPage273[0x100] = { - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\xF0\x91\x84\xB1\xF0\x91\x84\xA7", "\xF0\x91\x84\xB2\xF0\x91\x84\xA7", - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, -}; - -static const char *const decompositionPage275[0x100] = { - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, "\xF0\x91\x8D\x87\xF0\x91\x8C\xBE", - "\xF0\x91\x8D\x87\xF0\x91\x8D\x97", NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, -}; - -static const char *const decompositionPage276[0x100] = { - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, "\xF0\x91\x92\xB9\xF0\x91\x92\xBA", - "\xF0\x91\x92\xB9\xF0\x91\x92\xB0", NULL, - "\xF0\x91\x92\xB9\xF0\x91\x92\xBD", NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, -}; - -static const char *const decompositionPage277[0x100] = { - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\xF0\x91\x96\xB8\xF0\x91\x96\xAF", "\xF0\x91\x96\xB9\xF0\x91\x96\xAF", - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, -}; - -static const char *const decompositionPage281[0x100] = { - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\xF0\x91\xA4\xB5\xF0\x91\xA4\xB0", NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, -}; - -static const char *const decompositionPage465[0x100] = { - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\xF0\x9D\x85\x97\xF0\x9D\x85\xA5", "\xF0\x9D\x85\x98\xF0\x9D\x85\xA5", - "\xF0\x9D\x85\x98\xF0\x9D\x85\xA5\xF0\x9D\x85\xAE", "\xF0\x9D\x85\x98\xF0\x9D\x85\xA5\xF0\x9D\x85\xAF", - "\xF0\x9D\x85\x98\xF0\x9D\x85\xA5\xF0\x9D\x85\xB0", "\xF0\x9D\x85\x98\xF0\x9D\x85\xA5\xF0\x9D\x85\xB1", - "\xF0\x9D\x85\x98\xF0\x9D\x85\xA5\xF0\x9D\x85\xB2", NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, "\xF0\x9D\x86\xB9\xF0\x9D\x85\xA5", - "\xF0\x9D\x86\xBA\xF0\x9D\x85\xA5", "\xF0\x9D\x86\xB9\xF0\x9D\x85\xA5\xF0\x9D\x85\xAE", - "\xF0\x9D\x86\xBA\xF0\x9D\x85\xA5\xF0\x9D\x85\xAE", "\xF0\x9D\x86\xB9\xF0\x9D\x85\xA5\xF0\x9D\x85\xAF", - "\xF0\x9D\x86\xBA\xF0\x9D\x85\xA5\xF0\x9D\x85\xAF", NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, -}; - -static const char *const decompositionPage760[0x100] = { - "\xE4\xB8\xBD", "\xE4\xB8\xB8", - "\xE4\xB9\x81", "\xF0\xA0\x84\xA2", - "\xE4\xBD\xA0", "\xE4\xBE\xAE", - "\xE4\xBE\xBB", "\xE5\x80\x82", - "\xE5\x81\xBA", "\xE5\x82\x99", - "\xE5\x83\xA7", "\xE5\x83\x8F", - "\xE3\x92\x9E", "\xF0\xA0\x98\xBA", - "\xE5\x85\x8D", "\xE5\x85\x94", - "\xE5\x85\xA4", "\xE5\x85\xB7", - "\xF0\xA0\x94\x9C", "\xE3\x92\xB9", - "\xE5\x85\xA7", "\xE5\x86\x8D", - "\xF0\xA0\x95\x8B", "\xE5\x86\x97", - "\xE5\x86\xA4", "\xE4\xBB\x8C", - "\xE5\x86\xAC", "\xE5\x86\xB5", - "\xF0\xA9\x87\x9F", "\xE5\x87\xB5", - "\xE5\x88\x83", "\xE3\x93\x9F", - "\xE5\x88\xBB", "\xE5\x89\x86", - "\xE5\x89\xB2", "\xE5\x89\xB7", - "\xE3\x94\x95", "\xE5\x8B\x87", - "\xE5\x8B\x89", "\xE5\x8B\xA4", - "\xE5\x8B\xBA", "\xE5\x8C\x85", - "\xE5\x8C\x86", "\xE5\x8C\x97", - "\xE5\x8D\x89", "\xE5\x8D\x91", - "\xE5\x8D\x9A", "\xE5\x8D\xB3", - "\xE5\x8D\xBD", "\xE5\x8D\xBF", - "\xE5\x8D\xBF", "\xE5\x8D\xBF", - "\xF0\xA0\xA8\xAC", "\xE7\x81\xB0", - "\xE5\x8F\x8A", "\xE5\x8F\x9F", - "\xF0\xA0\xAD\xA3", "\xE5\x8F\xAB", - "\xE5\x8F\xB1", "\xE5\x90\x86", - "\xE5\x92\x9E", "\xE5\x90\xB8", - "\xE5\x91\x88", "\xE5\x91\xA8", - "\xE5\x92\xA2", "\xE5\x93\xB6", - "\xE5\x94\x90", "\xE5\x95\x93", - "\xE5\x95\xA3", "\xE5\x96\x84", - "\xE5\x96\x84", "\xE5\x96\x99", - "\xE5\x96\xAB", "\xE5\x96\xB3", - "\xE5\x97\x82", "\xE5\x9C\x96", - "\xE5\x98\x86", "\xE5\x9C\x97", - "\xE5\x99\x91", "\xE5\x99\xB4", - "\xE5\x88\x87", "\xE5\xA3\xAE", - "\xE5\x9F\x8E", "\xE5\x9F\xB4", - "\xE5\xA0\x8D", "\xE5\x9E\x8B", - "\xE5\xA0\xB2", "\xE5\xA0\xB1", - "\xE5\xA2\xAC", "\xF0\xA1\x93\xA4", - "\xE5\xA3\xB2", "\xE5\xA3\xB7", - "\xE5\xA4\x86", "\xE5\xA4\x9A", - "\xE5\xA4\xA2", "\xE5\xA5\xA2", - "\xF0\xA1\x9A\xA8", "\xF0\xA1\x9B\xAA", - "\xE5\xA7\xAC", "\xE5\xA8\x9B", - "\xE5\xA8\xA7", "\xE5\xA7\x98", - "\xE5\xA9\xA6", "\xE3\x9B\xAE", - "\xE3\x9B\xBC", "\xE5\xAC\x88", - "\xE5\xAC\xBE", "\xE5\xAC\xBE", - "\xF0\xA1\xA7\x88", "\xE5\xAF\x83", - "\xE5\xAF\x98", "\xE5\xAF\xA7", - "\xE5\xAF\xB3", "\xF0\xA1\xAC\x98", - "\xE5\xAF\xBF", "\xE5\xB0\x86", - "\xE5\xBD\x93", "\xE5\xB0\xA2", - "\xE3\x9E\x81", "\xE5\xB1\xA0", - "\xE5\xB1\xAE", "\xE5\xB3\x80", - "\xE5\xB2\x8D", "\xF0\xA1\xB7\xA4", - "\xE5\xB5\x83", "\xF0\xA1\xB7\xA6", - "\xE5\xB5\xAE", "\xE5\xB5\xAB", - "\xE5\xB5\xBC", "\xE5\xB7\xA1", - "\xE5\xB7\xA2", "\xE3\xA0\xAF", - "\xE5\xB7\xBD", "\xE5\xB8\xA8", - "\xE5\xB8\xBD", "\xE5\xB9\xA9", - "\xE3\xA1\xA2", "\xF0\xA2\x86\x83", - "\xE3\xA1\xBC", "\xE5\xBA\xB0", - "\xE5\xBA\xB3", "\xE5\xBA\xB6", - "\xE5\xBB\x8A", "\xF0\xAA\x8E\x92", - "\xE5\xBB\xBE", "\xF0\xA2\x8C\xB1", - "\xF0\xA2\x8C\xB1", "\xE8\x88\x81", - "\xE5\xBC\xA2", "\xE5\xBC\xA2", - "\xE3\xA3\x87", "\xF0\xA3\x8A\xB8", - "\xF0\xA6\x87\x9A", "\xE5\xBD\xA2", - "\xE5\xBD\xAB", "\xE3\xA3\xA3", - "\xE5\xBE\x9A", "\xE5\xBF\x8D", - "\xE5\xBF\x97", "\xE5\xBF\xB9", - "\xE6\x82\x81", "\xE3\xA4\xBA", - "\xE3\xA4\x9C", "\xE6\x82\x94", - "\xF0\xA2\x9B\x94", "\xE6\x83\x87", - "\xE6\x85\x88", "\xE6\x85\x8C", - "\xE6\x85\x8E", "\xE6\x85\x8C", - "\xE6\x85\xBA", "\xE6\x86\x8E", - "\xE6\x86\xB2", "\xE6\x86\xA4", - "\xE6\x86\xAF", "\xE6\x87\x9E", - "\xE6\x87\xB2", "\xE6\x87\xB6", - "\xE6\x88\x90", "\xE6\x88\x9B", - "\xE6\x89\x9D", "\xE6\x8A\xB1", - "\xE6\x8B\x94", "\xE6\x8D\x90", - "\xF0\xA2\xAC\x8C", "\xE6\x8C\xBD", - "\xE6\x8B\xBC", "\xE6\x8D\xA8", - "\xE6\x8E\x83", "\xE6\x8F\xA4", - "\xF0\xA2\xAF\xB1", "\xE6\x90\xA2", - "\xE6\x8F\x85", "\xE6\x8E\xA9", - "\xE3\xA8\xAE", "\xE6\x91\xA9", - "\xE6\x91\xBE", "\xE6\x92\x9D", - "\xE6\x91\xB7", "\xE3\xA9\xAC", - "\xE6\x95\x8F", "\xE6\x95\xAC", - "\xF0\xA3\x80\x8A", "\xE6\x97\xA3", - "\xE6\x9B\xB8", "\xE6\x99\x89", - "\xE3\xAC\x99", "\xE6\x9A\x91", - "\xE3\xAC\x88", "\xE3\xAB\xA4", - "\xE5\x86\x92", "\xE5\x86\x95", - "\xE6\x9C\x80", "\xE6\x9A\x9C", - "\xE8\x82\xAD", "\xE4\x8F\x99", - "\xE6\x9C\x97", "\xE6\x9C\x9B", - "\xE6\x9C\xA1", "\xE6\x9D\x9E", - "\xE6\x9D\x93", "\xF0\xA3\x8F\x83", - "\xE3\xAD\x89", "\xE6\x9F\xBA", - "\xE6\x9E\x85", "\xE6\xA1\x92", - "\xE6\xA2\x85", "\xF0\xA3\x91\xAD", - "\xE6\xA2\x8E", "\xE6\xA0\x9F", - "\xE6\xA4\x94", "\xE3\xAE\x9D", - "\xE6\xA5\x82", "\xE6\xA6\xA3", - "\xE6\xA7\xAA", "\xE6\xAA\xA8", - "\xF0\xA3\x9A\xA3", "\xE6\xAB\x9B", - "\xE3\xB0\x98", "\xE6\xAC\xA1", - "\xF0\xA3\xA2\xA7", "\xE6\xAD\x94", - "\xE3\xB1\x8E", "\xE6\xAD\xB2", - "\xE6\xAE\x9F", "\xE6\xAE\xBA", - "\xE6\xAE\xBB", "\xF0\xA3\xAA\x8D", - "\xF0\xA1\xB4\x8B", "\xF0\xA3\xAB\xBA", - "\xE6\xB1\x8E", "\xF0\xA3\xB2\xBC", - "\xE6\xB2\xBF", "\xE6\xB3\x8D", - "\xE6\xB1\xA7", "\xE6\xB4\x96", -}; - -static const char *const decompositionPage761[0x100] = { - "\xE6\xB4\xBE", "\xE6\xB5\xB7", - "\xE6\xB5\x81", "\xE6\xB5\xA9", - "\xE6\xB5\xB8", "\xE6\xB6\x85", - "\xF0\xA3\xB4\x9E", "\xE6\xB4\xB4", - "\xE6\xB8\xAF", "\xE6\xB9\xAE", - "\xE3\xB4\xB3", "\xE6\xBB\x8B", - "\xE6\xBB\x87", "\xF0\xA3\xBB\x91", - "\xE6\xB7\xB9", "\xE6\xBD\xAE", - "\xF0\xA3\xBD\x9E", "\xF0\xA3\xBE\x8E", - "\xE6\xBF\x86", "\xE7\x80\xB9", - "\xE7\x80\x9E", "\xE7\x80\x9B", - "\xE3\xB6\x96", "\xE7\x81\x8A", - "\xE7\x81\xBD", "\xE7\x81\xB7", - "\xE7\x82\xAD", "\xF0\xA0\x94\xA5", - "\xE7\x85\x85", "\xF0\xA4\x89\xA3", - "\xE7\x86\x9C", "\xF0\xA4\x8E\xAB", - "\xE7\x88\xA8", "\xE7\x88\xB5", - "\xE7\x89\x90", "\xF0\xA4\x98\x88", - "\xE7\x8A\x80", "\xE7\x8A\x95", - "\xF0\xA4\x9C\xB5", "\xF0\xA4\xA0\x94", - "\xE7\x8D\xBA", "\xE7\x8E\x8B", - "\xE3\xBA\xAC", "\xE7\x8E\xA5", - "\xE3\xBA\xB8", "\xE3\xBA\xB8", - "\xE7\x91\x87", "\xE7\x91\x9C", - "\xE7\x91\xB1", "\xE7\x92\x85", - "\xE7\x93\x8A", "\xE3\xBC\x9B", - "\xE7\x94\xA4", "\xF0\xA4\xB0\xB6", - "\xE7\x94\xBE", "\xF0\xA4\xB2\x92", - "\xE7\x95\xB0", "\xF0\xA2\x86\x9F", - "\xE7\x98\x90", "\xF0\xA4\xBE\xA1", - "\xF0\xA4\xBE\xB8", "\xF0\xA5\x81\x84", - "\xE3\xBF\xBC", "\xE4\x80\x88", - "\xE7\x9B\xB4", "\xF0\xA5\x83\xB3", - "\xF0\xA5\x83\xB2", "\xF0\xA5\x84\x99", - "\xF0\xA5\x84\xB3", "\xE7\x9C\x9E", - "\xE7\x9C\x9F", "\xE7\x9C\x9F", - "\xE7\x9D\x8A", "\xE4\x80\xB9", - "\xE7\x9E\x8B", "\xE4\x81\x86", - "\xE4\x82\x96", "\xF0\xA5\x90\x9D", - "\xE7\xA1\x8E", "\xE7\xA2\x8C", - "\xE7\xA3\x8C", "\xE4\x83\xA3", - "\xF0\xA5\x98\xA6", "\xE7\xA5\x96", - "\xF0\xA5\x9A\x9A", "\xF0\xA5\x9B\x85", - "\xE7\xA6\x8F", "\xE7\xA7\xAB", - "\xE4\x84\xAF", "\xE7\xA9\x80", - "\xE7\xA9\x8A", "\xE7\xA9\x8F", - "\xF0\xA5\xA5\xBC", "\xF0\xA5\xAA\xA7", - "\xF0\xA5\xAA\xA7", "\xE7\xAB\xAE", - "\xE4\x88\x82", "\xF0\xA5\xAE\xAB", - "\xE7\xAF\x86", "\xE7\xAF\x89", - "\xE4\x88\xA7", "\xF0\xA5\xB2\x80", - "\xE7\xB3\x92", "\xE4\x8A\xA0", - "\xE7\xB3\xA8", "\xE7\xB3\xA3", - "\xE7\xB4\x80", "\xF0\xA5\xBE\x86", - "\xE7\xB5\xA3", "\xE4\x8C\x81", - "\xE7\xB7\x87", "\xE7\xB8\x82", - "\xE7\xB9\x85", "\xE4\x8C\xB4", - "\xF0\xA6\x88\xA8", "\xF0\xA6\x89\x87", - "\xE4\x8D\x99", "\xF0\xA6\x8B\x99", - "\xE7\xBD\xBA", "\xF0\xA6\x8C\xBE", - "\xE7\xBE\x95", "\xE7\xBF\xBA", - "\xE8\x80\x85", "\xF0\xA6\x93\x9A", - "\xF0\xA6\x94\xA3", "\xE8\x81\xA0", - "\xF0\xA6\x96\xA8", "\xE8\x81\xB0", - "\xF0\xA3\x8D\x9F", "\xE4\x8F\x95", - "\xE8\x82\xB2", "\xE8\x84\x83", - "\xE4\x90\x8B", "\xE8\x84\xBE", - "\xE5\xAA\xB5", "\xF0\xA6\x9E\xA7", - "\xF0\xA6\x9E\xB5", "\xF0\xA3\x8E\x93", - "\xF0\xA3\x8E\x9C", "\xE8\x88\x81", - "\xE8\x88\x84", "\xE8\xBE\x9E", - "\xE4\x91\xAB", "\xE8\x8A\x91", - "\xE8\x8A\x8B", "\xE8\x8A\x9D", - "\xE5\x8A\xB3", "\xE8\x8A\xB1", - "\xE8\x8A\xB3", "\xE8\x8A\xBD", - "\xE8\x8B\xA6", "\xF0\xA6\xAC\xBC", - "\xE8\x8B\xA5", "\xE8\x8C\x9D", - "\xE8\x8D\xA3", "\xE8\x8E\xAD", - "\xE8\x8C\xA3", "\xE8\x8E\xBD", - "\xE8\x8F\xA7", "\xE8\x91\x97", - "\xE8\x8D\x93", "\xE8\x8F\x8A", - "\xE8\x8F\x8C", "\xE8\x8F\x9C", - "\xF0\xA6\xB0\xB6", "\xF0\xA6\xB5\xAB", - "\xF0\xA6\xB3\x95", "\xE4\x94\xAB", - "\xE8\x93\xB1", "\xE8\x93\xB3", - "\xE8\x94\x96", "\xF0\xA7\x8F\x8A", - "\xE8\x95\xA4", "\xF0\xA6\xBC\xAC", - "\xE4\x95\x9D", "\xE4\x95\xA1", - "\xF0\xA6\xBE\xB1", "\xF0\xA7\x83\x92", - "\xE4\x95\xAB", "\xE8\x99\x90", - "\xE8\x99\x9C", "\xE8\x99\xA7", - "\xE8\x99\xA9", "\xE8\x9A\xA9", - "\xE8\x9A\x88", "\xE8\x9C\x8E", - "\xE8\x9B\xA2", "\xE8\x9D\xB9", - "\xE8\x9C\xA8", "\xE8\x9D\xAB", - "\xE8\x9E\x86", "\xE4\x97\x97", - "\xE8\x9F\xA1", "\xE8\xA0\x81", - "\xE4\x97\xB9", "\xE8\xA1\xA0", - "\xE8\xA1\xA3", "\xF0\xA7\x99\xA7", - "\xE8\xA3\x97", "\xE8\xA3\x9E", - "\xE4\x98\xB5", "\xE8\xA3\xBA", - "\xE3\x92\xBB", "\xF0\xA7\xA2\xAE", - "\xF0\xA7\xA5\xA6", "\xE4\x9A\xBE", - "\xE4\x9B\x87", "\xE8\xAA\xA0", - "\xE8\xAB\xAD", "\xE8\xAE\x8A", - "\xE8\xB1\x95", "\xF0\xA7\xB2\xA8", - "\xE8\xB2\xAB", "\xE8\xB3\x81", - "\xE8\xB4\x9B", "\xE8\xB5\xB7", - "\xF0\xA7\xBC\xAF", "\xF0\xA0\xA0\x84", - "\xE8\xB7\x8B", "\xE8\xB6\xBC", - "\xE8\xB7\xB0", "\xF0\xA0\xA3\x9E", - "\xE8\xBB\x94", "\xE8\xBC\xB8", - "\xF0\xA8\x97\x92", "\xF0\xA8\x97\xAD", - "\xE9\x82\x94", "\xE9\x83\xB1", - "\xE9\x84\x91", "\xF0\xA8\x9C\xAE", - "\xE9\x84\x9B", "\xE9\x88\xB8", - "\xE9\x8B\x97", "\xE9\x8B\x98", - "\xE9\x89\xBC", "\xE9\x8F\xB9", - "\xE9\x90\x95", "\xF0\xA8\xAF\xBA", - "\xE9\x96\x8B", "\xE4\xA6\x95", - "\xE9\x96\xB7", "\xF0\xA8\xB5\xB7", - "\xE4\xA7\xA6", "\xE9\x9B\x83", - "\xE5\xB6\xB2", "\xE9\x9C\xA3", - "\xF0\xA9\x85\x85", "\xF0\xA9\x88\x9A", - "\xE4\xA9\xAE", "\xE4\xA9\xB6", - "\xE9\x9F\xA0", "\xF0\xA9\x90\x8A", - "\xE4\xAA\xB2", "\xF0\xA9\x92\x96", - "\xE9\xA0\x8B", "\xE9\xA0\x8B", -}; - -static const char *const decompositionPage762[0x100] = { - "\xE9\xA0\xA9", "\xF0\xA9\x96\xB6", - "\xE9\xA3\xA2", "\xE4\xAC\xB3", - "\xE9\xA4\xA9", "\xE9\xA6\xA7", - "\xE9\xA7\x82", "\xE9\xA7\xBE", - "\xE4\xAF\x8E", "\xF0\xA9\xAC\xB0", - "\xE9\xAC\x92", "\xE9\xB1\x80", - "\xE9\xB3\xBD", "\xE4\xB3\x8E", - "\xE4\xB3\xAD", "\xE9\xB5\xA7", - "\xF0\xAA\x83\x8E", "\xE4\xB3\xB8", - "\xF0\xAA\x84\x85", "\xF0\xAA\x88\x8E", - "\xF0\xAA\x8A\x91", "\xE9\xBA\xBB", - "\xE4\xB5\x96", "\xE9\xBB\xB9", - "\xE9\xBB\xBE", "\xE9\xBC\x85", - "\xE9\xBC\x8F", "\xE9\xBC\x96", - "\xE9\xBC\xBB", "\xF0\xAA\x98\x80", - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, -}; - -static const char *const decompCompatPage0[0x100] = { - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\x20", NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\x20\xCC\x88", NULL, - "\x61", NULL, - NULL, NULL, - NULL, "\x20\xCC\x84", - NULL, NULL, - "\x32", "\x33", - "\x20\xCC\x81", "\xCE\xBC", - NULL, NULL, - "\x20\xCC\xA7", "\x31", - "\x6F", NULL, - "\x31\xE2\x81\x84\x34", "\x31\xE2\x81\x84\x32", - "\x33\xE2\x81\x84\x34", NULL, - "\x41\xCC\x80", "\x41\xCC\x81", - "\x41\xCC\x82", "\x41\xCC\x83", - "\x41\xCC\x88", "\x41\xCC\x8A", - NULL, "\x43\xCC\xA7", - "\x45\xCC\x80", "\x45\xCC\x81", - "\x45\xCC\x82", "\x45\xCC\x88", - "\x49\xCC\x80", "\x49\xCC\x81", - "\x49\xCC\x82", "\x49\xCC\x88", - NULL, "\x4E\xCC\x83", - "\x4F\xCC\x80", "\x4F\xCC\x81", - "\x4F\xCC\x82", "\x4F\xCC\x83", - "\x4F\xCC\x88", NULL, - NULL, "\x55\xCC\x80", - "\x55\xCC\x81", "\x55\xCC\x82", - "\x55\xCC\x88", "\x59\xCC\x81", - NULL, NULL, - "\x61\xCC\x80", "\x61\xCC\x81", - "\x61\xCC\x82", "\x61\xCC\x83", - "\x61\xCC\x88", "\x61\xCC\x8A", - NULL, "\x63\xCC\xA7", - "\x65\xCC\x80", "\x65\xCC\x81", - "\x65\xCC\x82", "\x65\xCC\x88", - "\x69\xCC\x80", "\x69\xCC\x81", - "\x69\xCC\x82", "\x69\xCC\x88", - NULL, "\x6E\xCC\x83", - "\x6F\xCC\x80", "\x6F\xCC\x81", - "\x6F\xCC\x82", "\x6F\xCC\x83", - "\x6F\xCC\x88", NULL, - NULL, "\x75\xCC\x80", - "\x75\xCC\x81", "\x75\xCC\x82", - "\x75\xCC\x88", "\x79\xCC\x81", - NULL, "\x79\xCC\x88", -}; - -static const char *const decompCompatPage1[0x100] = { - "\x41\xCC\x84", "\x61\xCC\x84", - "\x41\xCC\x86", "\x61\xCC\x86", - "\x41\xCC\xA8", "\x61\xCC\xA8", - "\x43\xCC\x81", "\x63\xCC\x81", - "\x43\xCC\x82", "\x63\xCC\x82", - "\x43\xCC\x87", "\x63\xCC\x87", - "\x43\xCC\x8C", "\x63\xCC\x8C", - "\x44\xCC\x8C", "\x64\xCC\x8C", - NULL, NULL, - "\x45\xCC\x84", "\x65\xCC\x84", - "\x45\xCC\x86", "\x65\xCC\x86", - "\x45\xCC\x87", "\x65\xCC\x87", - "\x45\xCC\xA8", "\x65\xCC\xA8", - "\x45\xCC\x8C", "\x65\xCC\x8C", - "\x47\xCC\x82", "\x67\xCC\x82", - "\x47\xCC\x86", "\x67\xCC\x86", - "\x47\xCC\x87", "\x67\xCC\x87", - "\x47\xCC\xA7", "\x67\xCC\xA7", - "\x48\xCC\x82", "\x68\xCC\x82", - NULL, NULL, - "\x49\xCC\x83", "\x69\xCC\x83", - "\x49\xCC\x84", "\x69\xCC\x84", - "\x49\xCC\x86", "\x69\xCC\x86", - "\x49\xCC\xA8", "\x69\xCC\xA8", - "\x49\xCC\x87", NULL, - "\x49\x4A", "\x69\x6A", - "\x4A\xCC\x82", "\x6A\xCC\x82", - "\x4B\xCC\xA7", "\x6B\xCC\xA7", - NULL, "\x4C\xCC\x81", - "\x6C\xCC\x81", "\x4C\xCC\xA7", - "\x6C\xCC\xA7", "\x4C\xCC\x8C", - "\x6C\xCC\x8C", "\x4C\xC2\xB7", - "\x6C\xC2\xB7", NULL, - NULL, "\x4E\xCC\x81", - "\x6E\xCC\x81", "\x4E\xCC\xA7", - "\x6E\xCC\xA7", "\x4E\xCC\x8C", - "\x6E\xCC\x8C", "\xCA\xBC\x6E", - NULL, NULL, - "\x4F\xCC\x84", "\x6F\xCC\x84", - "\x4F\xCC\x86", "\x6F\xCC\x86", - "\x4F\xCC\x8B", "\x6F\xCC\x8B", - NULL, NULL, - "\x52\xCC\x81", "\x72\xCC\x81", - "\x52\xCC\xA7", "\x72\xCC\xA7", - "\x52\xCC\x8C", "\x72\xCC\x8C", - "\x53\xCC\x81", "\x73\xCC\x81", - "\x53\xCC\x82", "\x73\xCC\x82", - "\x53\xCC\xA7", "\x73\xCC\xA7", - "\x53\xCC\x8C", "\x73\xCC\x8C", - "\x54\xCC\xA7", "\x74\xCC\xA7", - "\x54\xCC\x8C", "\x74\xCC\x8C", - NULL, NULL, - "\x55\xCC\x83", "\x75\xCC\x83", - "\x55\xCC\x84", "\x75\xCC\x84", - "\x55\xCC\x86", "\x75\xCC\x86", - "\x55\xCC\x8A", "\x75\xCC\x8A", - "\x55\xCC\x8B", "\x75\xCC\x8B", - "\x55\xCC\xA8", "\x75\xCC\xA8", - "\x57\xCC\x82", "\x77\xCC\x82", - "\x59\xCC\x82", "\x79\xCC\x82", - "\x59\xCC\x88", "\x5A\xCC\x81", - "\x7A\xCC\x81", "\x5A\xCC\x87", - "\x7A\xCC\x87", "\x5A\xCC\x8C", - "\x7A\xCC\x8C", "\x73", - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\x4F\xCC\x9B", "\x6F\xCC\x9B", - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, "\x55\xCC\x9B", - "\x75\xCC\x9B", NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\x44\x5A\xCC\x8C", "\x44\x7A\xCC\x8C", - "\x64\x7A\xCC\x8C", "\x4C\x4A", - "\x4C\x6A", "\x6C\x6A", - "\x4E\x4A", "\x4E\x6A", - "\x6E\x6A", "\x41\xCC\x8C", - "\x61\xCC\x8C", "\x49\xCC\x8C", - "\x69\xCC\x8C", "\x4F\xCC\x8C", - "\x6F\xCC\x8C", "\x55\xCC\x8C", - "\x75\xCC\x8C", "\x55\xCC\x88\xCC\x84", - "\x75\xCC\x88\xCC\x84", "\x55\xCC\x88\xCC\x81", - "\x75\xCC\x88\xCC\x81", "\x55\xCC\x88\xCC\x8C", - "\x75\xCC\x88\xCC\x8C", "\x55\xCC\x88\xCC\x80", - "\x75\xCC\x88\xCC\x80", NULL, - "\x41\xCC\x88\xCC\x84", "\x61\xCC\x88\xCC\x84", - "\x41\xCC\x87\xCC\x84", "\x61\xCC\x87\xCC\x84", - "\xC3\x86\xCC\x84", "\xC3\xA6\xCC\x84", - NULL, NULL, - "\x47\xCC\x8C", "\x67\xCC\x8C", - "\x4B\xCC\x8C", "\x6B\xCC\x8C", - "\x4F\xCC\xA8", "\x6F\xCC\xA8", - "\x4F\xCC\xA8\xCC\x84", "\x6F\xCC\xA8\xCC\x84", - "\xC6\xB7\xCC\x8C", "\xCA\x92\xCC\x8C", - "\x6A\xCC\x8C", "\x44\x5A", - "\x44\x7A", "\x64\x7A", - "\x47\xCC\x81", "\x67\xCC\x81", - NULL, NULL, - "\x4E\xCC\x80", "\x6E\xCC\x80", - "\x41\xCC\x8A\xCC\x81", "\x61\xCC\x8A\xCC\x81", - "\xC3\x86\xCC\x81", "\xC3\xA6\xCC\x81", - "\xC3\x98\xCC\x81", "\xC3\xB8\xCC\x81", -}; - -static const char *const decompCompatPage2[0x100] = { - "\x41\xCC\x8F", "\x61\xCC\x8F", - "\x41\xCC\x91", "\x61\xCC\x91", - "\x45\xCC\x8F", "\x65\xCC\x8F", - "\x45\xCC\x91", "\x65\xCC\x91", - "\x49\xCC\x8F", "\x69\xCC\x8F", - "\x49\xCC\x91", "\x69\xCC\x91", - "\x4F\xCC\x8F", "\x6F\xCC\x8F", - "\x4F\xCC\x91", "\x6F\xCC\x91", - "\x52\xCC\x8F", "\x72\xCC\x8F", - "\x52\xCC\x91", "\x72\xCC\x91", - "\x55\xCC\x8F", "\x75\xCC\x8F", - "\x55\xCC\x91", "\x75\xCC\x91", - "\x53\xCC\xA6", "\x73\xCC\xA6", - "\x54\xCC\xA6", "\x74\xCC\xA6", - NULL, NULL, - "\x48\xCC\x8C", "\x68\xCC\x8C", - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\x41\xCC\x87", "\x61\xCC\x87", - "\x45\xCC\xA7", "\x65\xCC\xA7", - "\x4F\xCC\x88\xCC\x84", "\x6F\xCC\x88\xCC\x84", - "\x4F\xCC\x83\xCC\x84", "\x6F\xCC\x83\xCC\x84", - "\x4F\xCC\x87", "\x6F\xCC\x87", - "\x4F\xCC\x87\xCC\x84", "\x6F\xCC\x87\xCC\x84", - "\x59\xCC\x84", "\x79\xCC\x84", - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\x68", "\xC9\xA6", - "\x6A", "\x72", - "\xC9\xB9", "\xC9\xBB", - "\xCA\x81", "\x77", - "\x79", NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\x20\xCC\x86", "\x20\xCC\x87", - "\x20\xCC\x8A", "\x20\xCC\xA8", - "\x20\xCC\x83", "\x20\xCC\x8B", - NULL, NULL, - "\xC9\xA3", "\x6C", - "\x73", "\x78", - "\xCA\x95", NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, -}; - -static const char *const decompCompatPage3[0x100] = { - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\xCC\x80", "\xCC\x81", - NULL, "\xCC\x93", - "\xCC\x88\xCC\x81", NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\xCA\xB9", NULL, - NULL, NULL, - NULL, NULL, - "\x20\xCD\x85", NULL, - NULL, NULL, - "\x3B", NULL, - NULL, NULL, - NULL, NULL, - "\x20\xCC\x81", "\x20\xCC\x88\xCC\x81", - "\xCE\x91\xCC\x81", "\xC2\xB7", - "\xCE\x95\xCC\x81", "\xCE\x97\xCC\x81", - "\xCE\x99\xCC\x81", NULL, - "\xCE\x9F\xCC\x81", NULL, - "\xCE\xA5\xCC\x81", "\xCE\xA9\xCC\x81", - "\xCE\xB9\xCC\x88\xCC\x81", NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\xCE\x99\xCC\x88", "\xCE\xA5\xCC\x88", - "\xCE\xB1\xCC\x81", "\xCE\xB5\xCC\x81", - "\xCE\xB7\xCC\x81", "\xCE\xB9\xCC\x81", - "\xCF\x85\xCC\x88\xCC\x81", NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\xCE\xB9\xCC\x88", "\xCF\x85\xCC\x88", - "\xCE\xBF\xCC\x81", "\xCF\x85\xCC\x81", - "\xCF\x89\xCC\x81", NULL, - "\xCE\xB2", "\xCE\xB8", - "\xCE\xA5", "\xCE\xA5\xCC\x81", - "\xCE\xA5\xCC\x88", "\xCF\x86", - "\xCF\x80", NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\xCE\xBA", "\xCF\x81", - "\xCF\x82", NULL, - "\xCE\x98", "\xCE\xB5", - NULL, NULL, - NULL, "\xCE\xA3", - NULL, NULL, - NULL, NULL, - NULL, NULL, -}; - -static const char *const decompCompatPage5[0x100] = { - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, "\xD5\xA5\xD6\x82", - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, -}; - -static const char *const decompCompatPage6[0x100] = { - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\xD8\xA7\xD9\x93", "\xD8\xA7\xD9\x94", - "\xD9\x88\xD9\x94", "\xD8\xA7\xD9\x95", - "\xD9\x8A\xD9\x94", NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, "\xD8\xA7\xD9\xB4", - "\xD9\x88\xD9\xB4", "\xDB\x87\xD9\xB4", - "\xD9\x8A\xD9\xB4", NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\xDB\x95\xD9\x94", NULL, - "\xDB\x81\xD9\x94", NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, "\xDB\x92\xD9\x94", - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, -}; - -static const char *const decompCompatPage12[0x100] = { - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\xE0\xB1\x86\xE0\xB1\x96", NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\xE0\xB2\xBF\xE0\xB3\x95", NULL, - NULL, NULL, - NULL, NULL, - NULL, "\xE0\xB3\x86\xE0\xB3\x95", - "\xE0\xB3\x86\xE0\xB3\x96", NULL, - "\xE0\xB3\x86\xE0\xB3\x82", "\xE0\xB3\x86\xE0\xB3\x82\xE0\xB3\x95", - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, -}; - -static const char *const decompCompatPage13[0x100] = { - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\xE0\xB5\x86\xE0\xB4\xBE", "\xE0\xB5\x87\xE0\xB4\xBE", - "\xE0\xB5\x86\xE0\xB5\x97", NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\xE0\xB7\x99\xE0\xB7\x8A", NULL, - "\xE0\xB7\x99\xE0\xB7\x8F", "\xE0\xB7\x99\xE0\xB7\x8F\xE0\xB7\x8A", - "\xE0\xB7\x99\xE0\xB7\x9F", NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, -}; - -static const char *const decompCompatPage14[0x100] = { - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, "\xE0\xB9\x8D\xE0\xB8\xB2", - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, "\xE0\xBB\x8D\xE0\xBA\xB2", - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\xE0\xBA\xAB\xE0\xBA\x99", "\xE0\xBA\xAB\xE0\xBA\xA1", - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, -}; - -static const char *const decompCompatPage15[0x100] = { - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\xE0\xBC\x8B", NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, "\xE0\xBD\x82\xE0\xBE\xB7", - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, "\xE0\xBD\x8C\xE0\xBE\xB7", - NULL, NULL, - NULL, NULL, - "\xE0\xBD\x91\xE0\xBE\xB7", NULL, - NULL, NULL, - NULL, "\xE0\xBD\x96\xE0\xBE\xB7", - NULL, NULL, - NULL, NULL, - "\xE0\xBD\x9B\xE0\xBE\xB7", NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, "\xE0\xBD\x80\xE0\xBE\xB5", - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, "\xE0\xBD\xB1\xE0\xBD\xB2", - NULL, "\xE0\xBD\xB1\xE0\xBD\xB4", - "\xE0\xBE\xB2\xE0\xBE\x80", "\xE0\xBE\xB2\xE0\xBD\xB1\xE0\xBE\x80", - "\xE0\xBE\xB3\xE0\xBE\x80", "\xE0\xBE\xB3\xE0\xBD\xB1\xE0\xBE\x80", - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, "\xE0\xBD\xB1\xE0\xBE\x80", - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, "\xE0\xBE\x92\xE0\xBE\xB7", - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, "\xE0\xBE\x9C\xE0\xBE\xB7", - NULL, NULL, - NULL, NULL, - "\xE0\xBE\xA1\xE0\xBE\xB7", NULL, - NULL, NULL, - NULL, "\xE0\xBE\xA6\xE0\xBE\xB7", - NULL, NULL, - NULL, NULL, - "\xE0\xBE\xAB\xE0\xBE\xB7", NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, "\xE0\xBE\x90\xE0\xBE\xB5", - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, -}; - -static const char *const decompCompatPage16[0x100] = { - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\xE1\x80\xA5\xE1\x80\xAE", NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\xE1\x83\x9C", NULL, - NULL, NULL, -}; - -static const char *const decompCompatPage29[0x100] = { - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\x41", "\xC3\x86", - "\x42", NULL, - "\x44", "\x45", - "\xC6\x8E", "\x47", - "\x48", "\x49", - "\x4A", "\x4B", - "\x4C", "\x4D", - "\x4E", NULL, - "\x4F", "\xC8\xA2", - "\x50", "\x52", - "\x54", "\x55", - "\x57", "\x61", - "\xC9\x90", "\xC9\x91", - "\xE1\xB4\x82", "\x62", - "\x64", "\x65", - "\xC9\x99", "\xC9\x9B", - "\xC9\x9C", "\x67", - NULL, "\x6B", - "\x6D", "\xC5\x8B", - "\x6F", "\xC9\x94", - "\xE1\xB4\x96", "\xE1\xB4\x97", - "\x70", "\x74", - "\x75", "\xE1\xB4\x9D", - "\xC9\xAF", "\x76", - "\xE1\xB4\xA5", "\xCE\xB2", - "\xCE\xB3", "\xCE\xB4", - "\xCF\x86", "\xCF\x87", - "\x69", "\x72", - "\x75", "\x76", - "\xCE\xB2", "\xCE\xB3", - "\xCF\x81", "\xCF\x86", - "\xCF\x87", NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\xD0\xBD", NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, "\xC9\x92", - "\x63", "\xC9\x95", - "\xC3\xB0", "\xC9\x9C", - "\x66", "\xC9\x9F", - "\xC9\xA1", "\xC9\xA5", - "\xC9\xA8", "\xC9\xA9", - "\xC9\xAA", "\xE1\xB5\xBB", - "\xCA\x9D", "\xC9\xAD", - "\xE1\xB6\x85", "\xCA\x9F", - "\xC9\xB1", "\xC9\xB0", - "\xC9\xB2", "\xC9\xB3", - "\xC9\xB4", "\xC9\xB5", - "\xC9\xB8", "\xCA\x82", - "\xCA\x83", "\xC6\xAB", - "\xCA\x89", "\xCA\x8A", - "\xE1\xB4\x9C", "\xCA\x8B", - "\xCA\x8C", "\x7A", - "\xCA\x90", "\xCA\x91", - "\xCA\x92", "\xCE\xB8", - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, -}; - -static const char *const decompCompatPage30[0x100] = { - "\x41\xCC\xA5", "\x61\xCC\xA5", - "\x42\xCC\x87", "\x62\xCC\x87", - "\x42\xCC\xA3", "\x62\xCC\xA3", - "\x42\xCC\xB1", "\x62\xCC\xB1", - "\x43\xCC\xA7\xCC\x81", "\x63\xCC\xA7\xCC\x81", - "\x44\xCC\x87", "\x64\xCC\x87", - "\x44\xCC\xA3", "\x64\xCC\xA3", - "\x44\xCC\xB1", "\x64\xCC\xB1", - "\x44\xCC\xA7", "\x64\xCC\xA7", - "\x44\xCC\xAD", "\x64\xCC\xAD", - "\x45\xCC\x84\xCC\x80", "\x65\xCC\x84\xCC\x80", - "\x45\xCC\x84\xCC\x81", "\x65\xCC\x84\xCC\x81", - "\x45\xCC\xAD", "\x65\xCC\xAD", - "\x45\xCC\xB0", "\x65\xCC\xB0", - "\x45\xCC\xA7\xCC\x86", "\x65\xCC\xA7\xCC\x86", - "\x46\xCC\x87", "\x66\xCC\x87", - "\x47\xCC\x84", "\x67\xCC\x84", - "\x48\xCC\x87", "\x68\xCC\x87", - "\x48\xCC\xA3", "\x68\xCC\xA3", - "\x48\xCC\x88", "\x68\xCC\x88", - "\x48\xCC\xA7", "\x68\xCC\xA7", - "\x48\xCC\xAE", "\x68\xCC\xAE", - "\x49\xCC\xB0", "\x69\xCC\xB0", - "\x49\xCC\x88\xCC\x81", "\x69\xCC\x88\xCC\x81", - "\x4B\xCC\x81", "\x6B\xCC\x81", - "\x4B\xCC\xA3", "\x6B\xCC\xA3", - "\x4B\xCC\xB1", "\x6B\xCC\xB1", - "\x4C\xCC\xA3", "\x6C\xCC\xA3", - "\x4C\xCC\xA3\xCC\x84", "\x6C\xCC\xA3\xCC\x84", - "\x4C\xCC\xB1", "\x6C\xCC\xB1", - "\x4C\xCC\xAD", "\x6C\xCC\xAD", - "\x4D\xCC\x81", "\x6D\xCC\x81", - "\x4D\xCC\x87", "\x6D\xCC\x87", - "\x4D\xCC\xA3", "\x6D\xCC\xA3", - "\x4E\xCC\x87", "\x6E\xCC\x87", - "\x4E\xCC\xA3", "\x6E\xCC\xA3", - "\x4E\xCC\xB1", "\x6E\xCC\xB1", - "\x4E\xCC\xAD", "\x6E\xCC\xAD", - "\x4F\xCC\x83\xCC\x81", "\x6F\xCC\x83\xCC\x81", - "\x4F\xCC\x83\xCC\x88", "\x6F\xCC\x83\xCC\x88", - "\x4F\xCC\x84\xCC\x80", "\x6F\xCC\x84\xCC\x80", - "\x4F\xCC\x84\xCC\x81", "\x6F\xCC\x84\xCC\x81", - "\x50\xCC\x81", "\x70\xCC\x81", - "\x50\xCC\x87", "\x70\xCC\x87", - "\x52\xCC\x87", "\x72\xCC\x87", - "\x52\xCC\xA3", "\x72\xCC\xA3", - "\x52\xCC\xA3\xCC\x84", "\x72\xCC\xA3\xCC\x84", - "\x52\xCC\xB1", "\x72\xCC\xB1", - "\x53\xCC\x87", "\x73\xCC\x87", - "\x53\xCC\xA3", "\x73\xCC\xA3", - "\x53\xCC\x81\xCC\x87", "\x73\xCC\x81\xCC\x87", - "\x53\xCC\x8C\xCC\x87", "\x73\xCC\x8C\xCC\x87", - "\x53\xCC\xA3\xCC\x87", "\x73\xCC\xA3\xCC\x87", - "\x54\xCC\x87", "\x74\xCC\x87", - "\x54\xCC\xA3", "\x74\xCC\xA3", - "\x54\xCC\xB1", "\x74\xCC\xB1", - "\x54\xCC\xAD", "\x74\xCC\xAD", - "\x55\xCC\xA4", "\x75\xCC\xA4", - "\x55\xCC\xB0", "\x75\xCC\xB0", - "\x55\xCC\xAD", "\x75\xCC\xAD", - "\x55\xCC\x83\xCC\x81", "\x75\xCC\x83\xCC\x81", - "\x55\xCC\x84\xCC\x88", "\x75\xCC\x84\xCC\x88", - "\x56\xCC\x83", "\x76\xCC\x83", - "\x56\xCC\xA3", "\x76\xCC\xA3", - "\x57\xCC\x80", "\x77\xCC\x80", - "\x57\xCC\x81", "\x77\xCC\x81", - "\x57\xCC\x88", "\x77\xCC\x88", - "\x57\xCC\x87", "\x77\xCC\x87", - "\x57\xCC\xA3", "\x77\xCC\xA3", - "\x58\xCC\x87", "\x78\xCC\x87", - "\x58\xCC\x88", "\x78\xCC\x88", - "\x59\xCC\x87", "\x79\xCC\x87", - "\x5A\xCC\x82", "\x7A\xCC\x82", - "\x5A\xCC\xA3", "\x7A\xCC\xA3", - "\x5A\xCC\xB1", "\x7A\xCC\xB1", - "\x68\xCC\xB1", "\x74\xCC\x88", - "\x77\xCC\x8A", "\x79\xCC\x8A", - "\x61\xCA\xBE", "\x73\xCC\x87", - NULL, NULL, - NULL, NULL, - "\x41\xCC\xA3", "\x61\xCC\xA3", - "\x41\xCC\x89", "\x61\xCC\x89", - "\x41\xCC\x82\xCC\x81", "\x61\xCC\x82\xCC\x81", - "\x41\xCC\x82\xCC\x80", "\x61\xCC\x82\xCC\x80", - "\x41\xCC\x82\xCC\x89", "\x61\xCC\x82\xCC\x89", - "\x41\xCC\x82\xCC\x83", "\x61\xCC\x82\xCC\x83", - "\x41\xCC\xA3\xCC\x82", "\x61\xCC\xA3\xCC\x82", - "\x41\xCC\x86\xCC\x81", "\x61\xCC\x86\xCC\x81", - "\x41\xCC\x86\xCC\x80", "\x61\xCC\x86\xCC\x80", - "\x41\xCC\x86\xCC\x89", "\x61\xCC\x86\xCC\x89", - "\x41\xCC\x86\xCC\x83", "\x61\xCC\x86\xCC\x83", - "\x41\xCC\xA3\xCC\x86", "\x61\xCC\xA3\xCC\x86", - "\x45\xCC\xA3", "\x65\xCC\xA3", - "\x45\xCC\x89", "\x65\xCC\x89", - "\x45\xCC\x83", "\x65\xCC\x83", - "\x45\xCC\x82\xCC\x81", "\x65\xCC\x82\xCC\x81", - "\x45\xCC\x82\xCC\x80", "\x65\xCC\x82\xCC\x80", - "\x45\xCC\x82\xCC\x89", "\x65\xCC\x82\xCC\x89", - "\x45\xCC\x82\xCC\x83", "\x65\xCC\x82\xCC\x83", - "\x45\xCC\xA3\xCC\x82", "\x65\xCC\xA3\xCC\x82", - "\x49\xCC\x89", "\x69\xCC\x89", - "\x49\xCC\xA3", "\x69\xCC\xA3", - "\x4F\xCC\xA3", "\x6F\xCC\xA3", - "\x4F\xCC\x89", "\x6F\xCC\x89", - "\x4F\xCC\x82\xCC\x81", "\x6F\xCC\x82\xCC\x81", - "\x4F\xCC\x82\xCC\x80", "\x6F\xCC\x82\xCC\x80", - "\x4F\xCC\x82\xCC\x89", "\x6F\xCC\x82\xCC\x89", - "\x4F\xCC\x82\xCC\x83", "\x6F\xCC\x82\xCC\x83", - "\x4F\xCC\xA3\xCC\x82", "\x6F\xCC\xA3\xCC\x82", - "\x4F\xCC\x9B\xCC\x81", "\x6F\xCC\x9B\xCC\x81", - "\x4F\xCC\x9B\xCC\x80", "\x6F\xCC\x9B\xCC\x80", - "\x4F\xCC\x9B\xCC\x89", "\x6F\xCC\x9B\xCC\x89", - "\x4F\xCC\x9B\xCC\x83", "\x6F\xCC\x9B\xCC\x83", - "\x4F\xCC\x9B\xCC\xA3", "\x6F\xCC\x9B\xCC\xA3", - "\x55\xCC\xA3", "\x75\xCC\xA3", - "\x55\xCC\x89", "\x75\xCC\x89", - "\x55\xCC\x9B\xCC\x81", "\x75\xCC\x9B\xCC\x81", - "\x55\xCC\x9B\xCC\x80", "\x75\xCC\x9B\xCC\x80", - "\x55\xCC\x9B\xCC\x89", "\x75\xCC\x9B\xCC\x89", - "\x55\xCC\x9B\xCC\x83", "\x75\xCC\x9B\xCC\x83", - "\x55\xCC\x9B\xCC\xA3", "\x75\xCC\x9B\xCC\xA3", - "\x59\xCC\x80", "\x79\xCC\x80", - "\x59\xCC\xA3", "\x79\xCC\xA3", - "\x59\xCC\x89", "\x79\xCC\x89", - "\x59\xCC\x83", "\x79\xCC\x83", - NULL, NULL, - NULL, NULL, - NULL, NULL, -}; - -static const char *const decompCompatPage31[0x100] = { - "\xCE\xB1\xCC\x93", "\xCE\xB1\xCC\x94", - "\xCE\xB1\xCC\x93\xCC\x80", "\xCE\xB1\xCC\x94\xCC\x80", - "\xCE\xB1\xCC\x93\xCC\x81", "\xCE\xB1\xCC\x94\xCC\x81", - "\xCE\xB1\xCC\x93\xCD\x82", "\xCE\xB1\xCC\x94\xCD\x82", - "\xCE\x91\xCC\x93", "\xCE\x91\xCC\x94", - "\xCE\x91\xCC\x93\xCC\x80", "\xCE\x91\xCC\x94\xCC\x80", - "\xCE\x91\xCC\x93\xCC\x81", "\xCE\x91\xCC\x94\xCC\x81", - "\xCE\x91\xCC\x93\xCD\x82", "\xCE\x91\xCC\x94\xCD\x82", - "\xCE\xB5\xCC\x93", "\xCE\xB5\xCC\x94", - "\xCE\xB5\xCC\x93\xCC\x80", "\xCE\xB5\xCC\x94\xCC\x80", - "\xCE\xB5\xCC\x93\xCC\x81", "\xCE\xB5\xCC\x94\xCC\x81", - NULL, NULL, - "\xCE\x95\xCC\x93", "\xCE\x95\xCC\x94", - "\xCE\x95\xCC\x93\xCC\x80", "\xCE\x95\xCC\x94\xCC\x80", - "\xCE\x95\xCC\x93\xCC\x81", "\xCE\x95\xCC\x94\xCC\x81", - NULL, NULL, - "\xCE\xB7\xCC\x93", "\xCE\xB7\xCC\x94", - "\xCE\xB7\xCC\x93\xCC\x80", "\xCE\xB7\xCC\x94\xCC\x80", - "\xCE\xB7\xCC\x93\xCC\x81", "\xCE\xB7\xCC\x94\xCC\x81", - "\xCE\xB7\xCC\x93\xCD\x82", "\xCE\xB7\xCC\x94\xCD\x82", - "\xCE\x97\xCC\x93", "\xCE\x97\xCC\x94", - "\xCE\x97\xCC\x93\xCC\x80", "\xCE\x97\xCC\x94\xCC\x80", - "\xCE\x97\xCC\x93\xCC\x81", "\xCE\x97\xCC\x94\xCC\x81", - "\xCE\x97\xCC\x93\xCD\x82", "\xCE\x97\xCC\x94\xCD\x82", - "\xCE\xB9\xCC\x93", "\xCE\xB9\xCC\x94", - "\xCE\xB9\xCC\x93\xCC\x80", "\xCE\xB9\xCC\x94\xCC\x80", - "\xCE\xB9\xCC\x93\xCC\x81", "\xCE\xB9\xCC\x94\xCC\x81", - "\xCE\xB9\xCC\x93\xCD\x82", "\xCE\xB9\xCC\x94\xCD\x82", - "\xCE\x99\xCC\x93", "\xCE\x99\xCC\x94", - "\xCE\x99\xCC\x93\xCC\x80", "\xCE\x99\xCC\x94\xCC\x80", - "\xCE\x99\xCC\x93\xCC\x81", "\xCE\x99\xCC\x94\xCC\x81", - "\xCE\x99\xCC\x93\xCD\x82", "\xCE\x99\xCC\x94\xCD\x82", - "\xCE\xBF\xCC\x93", "\xCE\xBF\xCC\x94", - "\xCE\xBF\xCC\x93\xCC\x80", "\xCE\xBF\xCC\x94\xCC\x80", - "\xCE\xBF\xCC\x93\xCC\x81", "\xCE\xBF\xCC\x94\xCC\x81", - NULL, NULL, - "\xCE\x9F\xCC\x93", "\xCE\x9F\xCC\x94", - "\xCE\x9F\xCC\x93\xCC\x80", "\xCE\x9F\xCC\x94\xCC\x80", - "\xCE\x9F\xCC\x93\xCC\x81", "\xCE\x9F\xCC\x94\xCC\x81", - NULL, NULL, - "\xCF\x85\xCC\x93", "\xCF\x85\xCC\x94", - "\xCF\x85\xCC\x93\xCC\x80", "\xCF\x85\xCC\x94\xCC\x80", - "\xCF\x85\xCC\x93\xCC\x81", "\xCF\x85\xCC\x94\xCC\x81", - "\xCF\x85\xCC\x93\xCD\x82", "\xCF\x85\xCC\x94\xCD\x82", - NULL, "\xCE\xA5\xCC\x94", - NULL, "\xCE\xA5\xCC\x94\xCC\x80", - NULL, "\xCE\xA5\xCC\x94\xCC\x81", - NULL, "\xCE\xA5\xCC\x94\xCD\x82", - "\xCF\x89\xCC\x93", "\xCF\x89\xCC\x94", - "\xCF\x89\xCC\x93\xCC\x80", "\xCF\x89\xCC\x94\xCC\x80", - "\xCF\x89\xCC\x93\xCC\x81", "\xCF\x89\xCC\x94\xCC\x81", - "\xCF\x89\xCC\x93\xCD\x82", "\xCF\x89\xCC\x94\xCD\x82", - "\xCE\xA9\xCC\x93", "\xCE\xA9\xCC\x94", - "\xCE\xA9\xCC\x93\xCC\x80", "\xCE\xA9\xCC\x94\xCC\x80", - "\xCE\xA9\xCC\x93\xCC\x81", "\xCE\xA9\xCC\x94\xCC\x81", - "\xCE\xA9\xCC\x93\xCD\x82", "\xCE\xA9\xCC\x94\xCD\x82", - "\xCE\xB1\xCC\x80", "\xCE\xB1\xCC\x81", - "\xCE\xB5\xCC\x80", "\xCE\xB5\xCC\x81", - "\xCE\xB7\xCC\x80", "\xCE\xB7\xCC\x81", - "\xCE\xB9\xCC\x80", "\xCE\xB9\xCC\x81", - "\xCE\xBF\xCC\x80", "\xCE\xBF\xCC\x81", - "\xCF\x85\xCC\x80", "\xCF\x85\xCC\x81", - "\xCF\x89\xCC\x80", "\xCF\x89\xCC\x81", - NULL, NULL, - "\xCE\xB1\xCC\x93\xCD\x85", "\xCE\xB1\xCC\x94\xCD\x85", - "\xCE\xB1\xCC\x93\xCC\x80\xCD\x85", "\xCE\xB1\xCC\x94\xCC\x80\xCD\x85", - "\xCE\xB1\xCC\x93\xCC\x81\xCD\x85", "\xCE\xB1\xCC\x94\xCC\x81\xCD\x85", - "\xCE\xB1\xCC\x93\xCD\x82\xCD\x85", "\xCE\xB1\xCC\x94\xCD\x82\xCD\x85", - "\xCE\x91\xCC\x93\xCD\x85", "\xCE\x91\xCC\x94\xCD\x85", - "\xCE\x91\xCC\x93\xCC\x80\xCD\x85", "\xCE\x91\xCC\x94\xCC\x80\xCD\x85", - "\xCE\x91\xCC\x93\xCC\x81\xCD\x85", "\xCE\x91\xCC\x94\xCC\x81\xCD\x85", - "\xCE\x91\xCC\x93\xCD\x82\xCD\x85", "\xCE\x91\xCC\x94\xCD\x82\xCD\x85", - "\xCE\xB7\xCC\x93\xCD\x85", "\xCE\xB7\xCC\x94\xCD\x85", - "\xCE\xB7\xCC\x93\xCC\x80\xCD\x85", "\xCE\xB7\xCC\x94\xCC\x80\xCD\x85", - "\xCE\xB7\xCC\x93\xCC\x81\xCD\x85", "\xCE\xB7\xCC\x94\xCC\x81\xCD\x85", - "\xCE\xB7\xCC\x93\xCD\x82\xCD\x85", "\xCE\xB7\xCC\x94\xCD\x82\xCD\x85", - "\xCE\x97\xCC\x93\xCD\x85", "\xCE\x97\xCC\x94\xCD\x85", - "\xCE\x97\xCC\x93\xCC\x80\xCD\x85", "\xCE\x97\xCC\x94\xCC\x80\xCD\x85", - "\xCE\x97\xCC\x93\xCC\x81\xCD\x85", "\xCE\x97\xCC\x94\xCC\x81\xCD\x85", - "\xCE\x97\xCC\x93\xCD\x82\xCD\x85", "\xCE\x97\xCC\x94\xCD\x82\xCD\x85", - "\xCF\x89\xCC\x93\xCD\x85", "\xCF\x89\xCC\x94\xCD\x85", - "\xCF\x89\xCC\x93\xCC\x80\xCD\x85", "\xCF\x89\xCC\x94\xCC\x80\xCD\x85", - "\xCF\x89\xCC\x93\xCC\x81\xCD\x85", "\xCF\x89\xCC\x94\xCC\x81\xCD\x85", - "\xCF\x89\xCC\x93\xCD\x82\xCD\x85", "\xCF\x89\xCC\x94\xCD\x82\xCD\x85", - "\xCE\xA9\xCC\x93\xCD\x85", "\xCE\xA9\xCC\x94\xCD\x85", - "\xCE\xA9\xCC\x93\xCC\x80\xCD\x85", "\xCE\xA9\xCC\x94\xCC\x80\xCD\x85", - "\xCE\xA9\xCC\x93\xCC\x81\xCD\x85", "\xCE\xA9\xCC\x94\xCC\x81\xCD\x85", - "\xCE\xA9\xCC\x93\xCD\x82\xCD\x85", "\xCE\xA9\xCC\x94\xCD\x82\xCD\x85", - "\xCE\xB1\xCC\x86", "\xCE\xB1\xCC\x84", - "\xCE\xB1\xCC\x80\xCD\x85", "\xCE\xB1\xCD\x85", - "\xCE\xB1\xCC\x81\xCD\x85", NULL, - "\xCE\xB1\xCD\x82", "\xCE\xB1\xCD\x82\xCD\x85", - "\xCE\x91\xCC\x86", "\xCE\x91\xCC\x84", - "\xCE\x91\xCC\x80", "\xCE\x91\xCC\x81", - "\xCE\x91\xCD\x85", "\x20\xCC\x93", - "\xCE\xB9", "\x20\xCC\x93", - "\x20\xCD\x82", "\x20\xCC\x88\xCD\x82", - "\xCE\xB7\xCC\x80\xCD\x85", "\xCE\xB7\xCD\x85", - "\xCE\xB7\xCC\x81\xCD\x85", NULL, - "\xCE\xB7\xCD\x82", "\xCE\xB7\xCD\x82\xCD\x85", - "\xCE\x95\xCC\x80", "\xCE\x95\xCC\x81", - "\xCE\x97\xCC\x80", "\xCE\x97\xCC\x81", - "\xCE\x97\xCD\x85", "\x20\xCC\x93\xCC\x80", - "\x20\xCC\x93\xCC\x81", "\x20\xCC\x93\xCD\x82", - "\xCE\xB9\xCC\x86", "\xCE\xB9\xCC\x84", - "\xCE\xB9\xCC\x88\xCC\x80", "\xCE\xB9\xCC\x88\xCC\x81", - NULL, NULL, - "\xCE\xB9\xCD\x82", "\xCE\xB9\xCC\x88\xCD\x82", - "\xCE\x99\xCC\x86", "\xCE\x99\xCC\x84", - "\xCE\x99\xCC\x80", "\xCE\x99\xCC\x81", - NULL, "\x20\xCC\x94\xCC\x80", - "\x20\xCC\x94\xCC\x81", "\x20\xCC\x94\xCD\x82", - "\xCF\x85\xCC\x86", "\xCF\x85\xCC\x84", - "\xCF\x85\xCC\x88\xCC\x80", "\xCF\x85\xCC\x88\xCC\x81", - "\xCF\x81\xCC\x93", "\xCF\x81\xCC\x94", - "\xCF\x85\xCD\x82", "\xCF\x85\xCC\x88\xCD\x82", - "\xCE\xA5\xCC\x86", "\xCE\xA5\xCC\x84", - "\xCE\xA5\xCC\x80", "\xCE\xA5\xCC\x81", - "\xCE\xA1\xCC\x94", "\x20\xCC\x88\xCC\x80", - "\x20\xCC\x88\xCC\x81", "\x60", - NULL, NULL, - "\xCF\x89\xCC\x80\xCD\x85", "\xCF\x89\xCD\x85", - "\xCF\x89\xCC\x81\xCD\x85", NULL, - "\xCF\x89\xCD\x82", "\xCF\x89\xCD\x82\xCD\x85", - "\xCE\x9F\xCC\x80", "\xCE\x9F\xCC\x81", - "\xCE\xA9\xCC\x80", "\xCE\xA9\xCC\x81", - "\xCE\xA9\xCD\x85", "\x20\xCC\x81", - "\x20\xCC\x94", NULL, -}; - -static const char *const decompCompatPage32[0x100] = { - "\x20", "\x20", - "\x20", "\x20", - "\x20", "\x20", - "\x20", "\x20", - "\x20", "\x20", - "\x20", NULL, - NULL, NULL, - NULL, NULL, - NULL, "\xE2\x80\x90", - NULL, NULL, - NULL, NULL, - NULL, "\x20\xCC\xB3", - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\x2E", "\x2E\x2E", - "\x2E\x2E\x2E", NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, "\x20", - NULL, NULL, - NULL, "\xE2\x80\xB2\xE2\x80\xB2", - "\xE2\x80\xB2\xE2\x80\xB2\xE2\x80\xB2", NULL, - "\xE2\x80\xB5\xE2\x80\xB5", "\xE2\x80\xB5\xE2\x80\xB5\xE2\x80\xB5", - NULL, NULL, - NULL, NULL, - "\x21\x21", NULL, - "\x20\xCC\x85", NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, "\x3F\x3F", - "\x3F\x21", "\x21\x3F", - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, "\xE2\x80\xB2\xE2\x80\xB2\xE2\x80\xB2\xE2\x80\xB2", - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, "\x20", - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\x30", "\x69", - NULL, NULL, - "\x34", "\x35", - "\x36", "\x37", - "\x38", "\x39", - "\x2B", "\xE2\x88\x92", - "\x3D", "\x28", - "\x29", "\x6E", - "\x30", "\x31", - "\x32", "\x33", - "\x34", "\x35", - "\x36", "\x37", - "\x38", "\x39", - "\x2B", "\xE2\x88\x92", - "\x3D", "\x28", - "\x29", NULL, - "\x61", "\x65", - "\x6F", "\x78", - "\xC9\x99", "\x68", - "\x6B", "\x6C", - "\x6D", "\x6E", - "\x70", "\x73", - "\x74", NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\x52\x73", NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, -}; - -static const char *const decompCompatPage33[0x100] = { - "\x61\x2F\x63", "\x61\x2F\x73", - "\x43", "\xC2\xB0\x43", - NULL, "\x63\x2F\x6F", - "\x63\x2F\x75", "\xC6\x90", - NULL, "\xC2\xB0\x46", - "\x67", "\x48", - "\x48", "\x48", - "\x68", "\xC4\xA7", - "\x49", "\x49", - "\x4C", "\x6C", - NULL, "\x4E", - "\x4E\x6F", NULL, - NULL, "\x50", - "\x51", "\x52", - "\x52", "\x52", - NULL, NULL, - "\x53\x4D", "\x54\x45\x4C", - "\x54\x4D", NULL, - "\x5A", NULL, - "\xCE\xA9", NULL, - "\x5A", NULL, - "\x4B", "\x41\xCC\x8A", - "\x42", "\x43", - NULL, "\x65", - "\x45", "\x46", - NULL, "\x4D", - "\x6F", "\xD7\x90", - "\xD7\x91", "\xD7\x92", - "\xD7\x93", "\x69", - NULL, "\x46\x41\x58", - "\xCF\x80", "\xCE\xB3", - "\xCE\x93", "\xCE\xA0", - "\xE2\x88\x91", NULL, - NULL, NULL, - NULL, "\x44", - "\x64", "\x65", - "\x69", "\x6A", - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\x31\xE2\x81\x84\x37", "\x31\xE2\x81\x84\x39", - "\x31\xE2\x81\x84\x31\x30", "\x31\xE2\x81\x84\x33", - "\x32\xE2\x81\x84\x33", "\x31\xE2\x81\x84\x35", - "\x32\xE2\x81\x84\x35", "\x33\xE2\x81\x84\x35", - "\x34\xE2\x81\x84\x35", "\x31\xE2\x81\x84\x36", - "\x35\xE2\x81\x84\x36", "\x31\xE2\x81\x84\x38", - "\x33\xE2\x81\x84\x38", "\x35\xE2\x81\x84\x38", - "\x37\xE2\x81\x84\x38", "\x31\xE2\x81\x84", - "\x49", "\x49\x49", - "\x49\x49\x49", "\x49\x56", - "\x56", "\x56\x49", - "\x56\x49\x49", "\x56\x49\x49\x49", - "\x49\x58", "\x58", - "\x58\x49", "\x58\x49\x49", - "\x4C", "\x43", - "\x44", "\x4D", - "\x69", "\x69\x69", - "\x69\x69\x69", "\x69\x76", - "\x76", "\x76\x69", - "\x76\x69\x69", "\x76\x69\x69\x69", - "\x69\x78", "\x78", - "\x78\x69", "\x78\x69\x69", - "\x6C", "\x63", - "\x64", "\x6D", - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, "\x30\xE2\x81\x84\x33", - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\xE2\x86\x90\xCC\xB8", "\xE2\x86\x92\xCC\xB8", - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\xE2\x86\x94\xCC\xB8", NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, "\xE2\x87\x90\xCC\xB8", - "\xE2\x87\x94\xCC\xB8", "\xE2\x87\x92\xCC\xB8", - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, -}; - -static const char *const decompCompatPage34[0x100] = { - NULL, NULL, - NULL, NULL, - "\xE2\x88\x83\xCC\xB8", NULL, - NULL, NULL, - NULL, "\xE2\x88\x88\xCC\xB8", - NULL, NULL, - "\xE2\x88\x8B\xCC\xB8", NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\xE2\x88\xA3\xCC\xB8", NULL, - "\xE2\x88\xA5\xCC\xB8", NULL, - NULL, NULL, - NULL, NULL, - "\xE2\x88\xAB\xE2\x88\xAB", "\xE2\x88\xAB\xE2\x88\xAB\xE2\x88\xAB", - NULL, "\xE2\x88\xAE\xE2\x88\xAE", - "\xE2\x88\xAE\xE2\x88\xAE\xE2\x88\xAE", NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, "\xE2\x88\xBC\xCC\xB8", - NULL, NULL, - "\xE2\x89\x83\xCC\xB8", NULL, - NULL, "\xE2\x89\x85\xCC\xB8", - NULL, "\xE2\x89\x88\xCC\xB8", - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\x3D\xCC\xB8", NULL, - "\xE2\x89\xA1\xCC\xB8", NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, "\xE2\x89\x8D\xCC\xB8", - "\x3C\xCC\xB8", "\x3E\xCC\xB8", - "\xE2\x89\xA4\xCC\xB8", "\xE2\x89\xA5\xCC\xB8", - NULL, NULL, - "\xE2\x89\xB2\xCC\xB8", "\xE2\x89\xB3\xCC\xB8", - NULL, NULL, - "\xE2\x89\xB6\xCC\xB8", "\xE2\x89\xB7\xCC\xB8", - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\xE2\x89\xBA\xCC\xB8", "\xE2\x89\xBB\xCC\xB8", - NULL, NULL, - "\xE2\x8A\x82\xCC\xB8", "\xE2\x8A\x83\xCC\xB8", - NULL, NULL, - "\xE2\x8A\x86\xCC\xB8", "\xE2\x8A\x87\xCC\xB8", - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\xE2\x8A\xA2\xCC\xB8", "\xE2\x8A\xA8\xCC\xB8", - "\xE2\x8A\xA9\xCC\xB8", "\xE2\x8A\xAB\xCC\xB8", - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\xE2\x89\xBC\xCC\xB8", "\xE2\x89\xBD\xCC\xB8", - "\xE2\x8A\x91\xCC\xB8", "\xE2\x8A\x92\xCC\xB8", - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\xE2\x8A\xB2\xCC\xB8", "\xE2\x8A\xB3\xCC\xB8", - "\xE2\x8A\xB4\xCC\xB8", "\xE2\x8A\xB5\xCC\xB8", - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, -}; - -static const char *const decompCompatPage36[0x100] = { - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\x31", "\x32", - "\x33", "\x34", - "\x35", "\x36", - "\x37", "\x38", - "\x39", "\x31\x30", - "\x31\x31", "\x31\x32", - "\x31\x33", "\x31\x34", - "\x31\x35", "\x31\x36", - "\x31\x37", "\x31\x38", - "\x31\x39", "\x32\x30", - "\x28\x31\x29", "\x28\x32\x29", - "\x28\x33\x29", "\x28\x34\x29", - "\x28\x35\x29", "\x28\x36\x29", - "\x28\x37\x29", "\x28\x38\x29", - "\x28\x39\x29", "\x28\x31\x30\x29", - "\x28\x31\x31\x29", "\x28\x31\x32\x29", - "\x28\x31\x33\x29", "\x28\x31\x34\x29", - "\x28\x31\x35\x29", "\x28\x31\x36\x29", - "\x28\x31\x37\x29", "\x28\x31\x38\x29", - "\x28\x31\x39\x29", "\x28\x32\x30\x29", - "\x31\x2E", "\x32\x2E", - "\x33\x2E", "\x34\x2E", - "\x35\x2E", "\x36\x2E", - "\x37\x2E", "\x38\x2E", - "\x39\x2E", "\x31\x30\x2E", - "\x31\x31\x2E", "\x31\x32\x2E", - "\x31\x33\x2E", "\x31\x34\x2E", - "\x31\x35\x2E", "\x31\x36\x2E", - "\x31\x37\x2E", "\x31\x38\x2E", - "\x31\x39\x2E", "\x32\x30\x2E", - "\x28\x61\x29", "\x28\x62\x29", - "\x28\x63\x29", "\x28\x64\x29", - "\x28\x65\x29", "\x28\x66\x29", - "\x28\x67\x29", "\x28\x68\x29", - "\x28\x69\x29", "\x28\x6A\x29", - "\x28\x6B\x29", "\x28\x6C\x29", - "\x28\x6D\x29", "\x28\x6E\x29", - "\x28\x6F\x29", "\x28\x70\x29", - "\x28\x71\x29", "\x28\x72\x29", - "\x28\x73\x29", "\x28\x74\x29", - "\x28\x75\x29", "\x28\x76\x29", - "\x28\x77\x29", "\x28\x78\x29", - "\x28\x79\x29", "\x28\x7A\x29", - "\x41", "\x42", - "\x43", "\x44", - "\x45", "\x46", - "\x47", "\x48", - "\x49", "\x4A", - "\x4B", "\x4C", - "\x4D", "\x4E", - "\x4F", "\x50", - "\x51", "\x52", - "\x53", "\x54", - "\x55", "\x56", - "\x57", "\x58", - "\x59", "\x5A", - "\x61", "\x62", - "\x63", "\x64", - "\x65", "\x66", - "\x67", "\x68", - "\x69", "\x6A", - "\x6B", "\x6C", - "\x6D", "\x6E", - "\x6F", "\x70", - "\x71", "\x72", - "\x73", "\x74", - "\x75", "\x76", - "\x77", "\x78", - "\x79", "\x7A", - "\x30", NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, -}; - -static const char *const decompCompatPage42[0x100] = { - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\xE2\x88\xAB\xE2\x88\xAB\xE2\x88\xAB\xE2\x88\xAB", NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\x3A\x3A\x3D", "\x3D\x3D", - "\x3D\x3D\x3D", NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\xE2\xAB\x9D\xCC\xB8", NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, -}; - -static const char *const decompCompatPage44[0x100] = { - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\x6A", "\x56", - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, -}; - -static const char *const decompCompatPage45[0x100] = { - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, "\xE2\xB5\xA1", - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, -}; - -static const char *const decompCompatPage46[0x100] = { - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, "\xE6\xAF\x8D", - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, "\xE9\xBE\x9F", - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, -}; - -static const char *const decompCompatPage47[0x100] = { - "\xE4\xB8\x80", "\xE4\xB8\xA8", - "\xE4\xB8\xB6", "\xE4\xB8\xBF", - "\xE4\xB9\x99", "\xE4\xBA\x85", - "\xE4\xBA\x8C", "\xE4\xBA\xA0", - "\xE4\xBA\xBA", "\xE5\x84\xBF", - "\xE5\x85\xA5", "\xE5\x85\xAB", - "\xE5\x86\x82", "\xE5\x86\x96", - "\xE5\x86\xAB", "\xE5\x87\xA0", - "\xE5\x87\xB5", "\xE5\x88\x80", - "\xE5\x8A\x9B", "\xE5\x8B\xB9", - "\xE5\x8C\x95", "\xE5\x8C\x9A", - "\xE5\x8C\xB8", "\xE5\x8D\x81", - "\xE5\x8D\x9C", "\xE5\x8D\xA9", - "\xE5\x8E\x82", "\xE5\x8E\xB6", - "\xE5\x8F\x88", "\xE5\x8F\xA3", - "\xE5\x9B\x97", "\xE5\x9C\x9F", - "\xE5\xA3\xAB", "\xE5\xA4\x82", - "\xE5\xA4\x8A", "\xE5\xA4\x95", - "\xE5\xA4\xA7", "\xE5\xA5\xB3", - "\xE5\xAD\x90", "\xE5\xAE\x80", - "\xE5\xAF\xB8", "\xE5\xB0\x8F", - "\xE5\xB0\xA2", "\xE5\xB0\xB8", - "\xE5\xB1\xAE", "\xE5\xB1\xB1", - "\xE5\xB7\x9B", "\xE5\xB7\xA5", - "\xE5\xB7\xB1", "\xE5\xB7\xBE", - "\xE5\xB9\xB2", "\xE5\xB9\xBA", - "\xE5\xB9\xBF", "\xE5\xBB\xB4", - "\xE5\xBB\xBE", "\xE5\xBC\x8B", - "\xE5\xBC\x93", "\xE5\xBD\x90", - "\xE5\xBD\xA1", "\xE5\xBD\xB3", - "\xE5\xBF\x83", "\xE6\x88\x88", - "\xE6\x88\xB6", "\xE6\x89\x8B", - "\xE6\x94\xAF", "\xE6\x94\xB4", - "\xE6\x96\x87", "\xE6\x96\x97", - "\xE6\x96\xA4", "\xE6\x96\xB9", - "\xE6\x97\xA0", "\xE6\x97\xA5", - "\xE6\x9B\xB0", "\xE6\x9C\x88", - "\xE6\x9C\xA8", "\xE6\xAC\xA0", - "\xE6\xAD\xA2", "\xE6\xAD\xB9", - "\xE6\xAE\xB3", "\xE6\xAF\x8B", - "\xE6\xAF\x94", "\xE6\xAF\x9B", - "\xE6\xB0\x8F", "\xE6\xB0\x94", - "\xE6\xB0\xB4", "\xE7\x81\xAB", - "\xE7\x88\xAA", "\xE7\x88\xB6", - "\xE7\x88\xBB", "\xE7\x88\xBF", - "\xE7\x89\x87", "\xE7\x89\x99", - "\xE7\x89\x9B", "\xE7\x8A\xAC", - "\xE7\x8E\x84", "\xE7\x8E\x89", - "\xE7\x93\x9C", "\xE7\x93\xA6", - "\xE7\x94\x98", "\xE7\x94\x9F", - "\xE7\x94\xA8", "\xE7\x94\xB0", - "\xE7\x96\x8B", "\xE7\x96\x92", - "\xE7\x99\xB6", "\xE7\x99\xBD", - "\xE7\x9A\xAE", "\xE7\x9A\xBF", - "\xE7\x9B\xAE", "\xE7\x9F\x9B", - "\xE7\x9F\xA2", "\xE7\x9F\xB3", - "\xE7\xA4\xBA", "\xE7\xA6\xB8", - "\xE7\xA6\xBE", "\xE7\xA9\xB4", - "\xE7\xAB\x8B", "\xE7\xAB\xB9", - "\xE7\xB1\xB3", "\xE7\xB3\xB8", - "\xE7\xBC\xB6", "\xE7\xBD\x91", - "\xE7\xBE\x8A", "\xE7\xBE\xBD", - "\xE8\x80\x81", "\xE8\x80\x8C", - "\xE8\x80\x92", "\xE8\x80\xB3", - "\xE8\x81\xBF", "\xE8\x82\x89", - "\xE8\x87\xA3", "\xE8\x87\xAA", - "\xE8\x87\xB3", "\xE8\x87\xBC", - "\xE8\x88\x8C", "\xE8\x88\x9B", - "\xE8\x88\x9F", "\xE8\x89\xAE", - "\xE8\x89\xB2", "\xE8\x89\xB8", - "\xE8\x99\x8D", "\xE8\x99\xAB", - "\xE8\xA1\x80", "\xE8\xA1\x8C", - "\xE8\xA1\xA3", "\xE8\xA5\xBE", - "\xE8\xA6\x8B", "\xE8\xA7\x92", - "\xE8\xA8\x80", "\xE8\xB0\xB7", - "\xE8\xB1\x86", "\xE8\xB1\x95", - "\xE8\xB1\xB8", "\xE8\xB2\x9D", - "\xE8\xB5\xA4", "\xE8\xB5\xB0", - "\xE8\xB6\xB3", "\xE8\xBA\xAB", - "\xE8\xBB\x8A", "\xE8\xBE\x9B", - "\xE8\xBE\xB0", "\xE8\xBE\xB5", - "\xE9\x82\x91", "\xE9\x85\x89", - "\xE9\x87\x86", "\xE9\x87\x8C", - "\xE9\x87\x91", "\xE9\x95\xB7", - "\xE9\x96\x80", "\xE9\x98\x9C", - "\xE9\x9A\xB6", "\xE9\x9A\xB9", - "\xE9\x9B\xA8", "\xE9\x9D\x91", - "\xE9\x9D\x9E", "\xE9\x9D\xA2", - "\xE9\x9D\xA9", "\xE9\x9F\x8B", - "\xE9\x9F\xAD", "\xE9\x9F\xB3", - "\xE9\xA0\x81", "\xE9\xA2\xA8", - "\xE9\xA3\x9B", "\xE9\xA3\x9F", - "\xE9\xA6\x96", "\xE9\xA6\x99", - "\xE9\xA6\xAC", "\xE9\xAA\xA8", - "\xE9\xAB\x98", "\xE9\xAB\x9F", - "\xE9\xAC\xA5", "\xE9\xAC\xAF", - "\xE9\xAC\xB2", "\xE9\xAC\xBC", - "\xE9\xAD\x9A", "\xE9\xB3\xA5", - "\xE9\xB9\xB5", "\xE9\xB9\xBF", - "\xE9\xBA\xA5", "\xE9\xBA\xBB", - "\xE9\xBB\x83", "\xE9\xBB\x8D", - "\xE9\xBB\x91", "\xE9\xBB\xB9", - "\xE9\xBB\xBD", "\xE9\xBC\x8E", - "\xE9\xBC\x93", "\xE9\xBC\xA0", - "\xE9\xBC\xBB", "\xE9\xBD\x8A", - "\xE9\xBD\x92", "\xE9\xBE\x8D", - "\xE9\xBE\x9C", "\xE9\xBE\xA0", - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, -}; - -static const char *const decompCompatPage48[0x100] = { - "\x20", NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\xE3\x80\x92", NULL, - "\xE5\x8D\x81", "\xE5\x8D\x84", - "\xE5\x8D\x85", NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\xE3\x81\x8B\xE3\x82\x99", NULL, - "\xE3\x81\x8D\xE3\x82\x99", NULL, - "\xE3\x81\x8F\xE3\x82\x99", NULL, - "\xE3\x81\x91\xE3\x82\x99", NULL, - "\xE3\x81\x93\xE3\x82\x99", NULL, - "\xE3\x81\x95\xE3\x82\x99", NULL, - "\xE3\x81\x97\xE3\x82\x99", NULL, - "\xE3\x81\x99\xE3\x82\x99", NULL, - "\xE3\x81\x9B\xE3\x82\x99", NULL, - "\xE3\x81\x9D\xE3\x82\x99", NULL, - "\xE3\x81\x9F\xE3\x82\x99", NULL, - "\xE3\x81\xA1\xE3\x82\x99", NULL, - NULL, "\xE3\x81\xA4\xE3\x82\x99", - NULL, "\xE3\x81\xA6\xE3\x82\x99", - NULL, "\xE3\x81\xA8\xE3\x82\x99", - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\xE3\x81\xAF\xE3\x82\x99", "\xE3\x81\xAF\xE3\x82\x9A", - NULL, "\xE3\x81\xB2\xE3\x82\x99", - "\xE3\x81\xB2\xE3\x82\x9A", NULL, - "\xE3\x81\xB5\xE3\x82\x99", "\xE3\x81\xB5\xE3\x82\x9A", - NULL, "\xE3\x81\xB8\xE3\x82\x99", - "\xE3\x81\xB8\xE3\x82\x9A", NULL, - "\xE3\x81\xBB\xE3\x82\x99", "\xE3\x81\xBB\xE3\x82\x9A", - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\xE3\x81\x86\xE3\x82\x99", NULL, - NULL, NULL, - NULL, NULL, - NULL, "\x20\xE3\x82\x99", - "\x20\xE3\x82\x9A", NULL, - "\xE3\x82\x9D\xE3\x82\x99", "\xE3\x82\x88\xE3\x82\x8A", - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\xE3\x82\xAB\xE3\x82\x99", NULL, - "\xE3\x82\xAD\xE3\x82\x99", NULL, - "\xE3\x82\xAF\xE3\x82\x99", NULL, - "\xE3\x82\xB1\xE3\x82\x99", NULL, - "\xE3\x82\xB3\xE3\x82\x99", NULL, - "\xE3\x82\xB5\xE3\x82\x99", NULL, - "\xE3\x82\xB7\xE3\x82\x99", NULL, - "\xE3\x82\xB9\xE3\x82\x99", NULL, - "\xE3\x82\xBB\xE3\x82\x99", NULL, - "\xE3\x82\xBD\xE3\x82\x99", NULL, - "\xE3\x82\xBF\xE3\x82\x99", NULL, - "\xE3\x83\x81\xE3\x82\x99", NULL, - NULL, "\xE3\x83\x84\xE3\x82\x99", - NULL, "\xE3\x83\x86\xE3\x82\x99", - NULL, "\xE3\x83\x88\xE3\x82\x99", - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\xE3\x83\x8F\xE3\x82\x99", "\xE3\x83\x8F\xE3\x82\x9A", - NULL, "\xE3\x83\x92\xE3\x82\x99", - "\xE3\x83\x92\xE3\x82\x9A", NULL, - "\xE3\x83\x95\xE3\x82\x99", "\xE3\x83\x95\xE3\x82\x9A", - NULL, "\xE3\x83\x98\xE3\x82\x99", - "\xE3\x83\x98\xE3\x82\x9A", NULL, - "\xE3\x83\x9B\xE3\x82\x99", "\xE3\x83\x9B\xE3\x82\x9A", - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\xE3\x82\xA6\xE3\x82\x99", NULL, - NULL, "\xE3\x83\xAF\xE3\x82\x99", - "\xE3\x83\xB0\xE3\x82\x99", "\xE3\x83\xB1\xE3\x82\x99", - "\xE3\x83\xB2\xE3\x82\x99", NULL, - NULL, NULL, - "\xE3\x83\xBD\xE3\x82\x99", "\xE3\x82\xB3\xE3\x83\x88", -}; - -static const char *const decompCompatPage49[0x100] = { - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, "\xE1\x84\x80", - "\xE1\x84\x81", "\xE1\x86\xAA", - "\xE1\x84\x82", "\xE1\x86\xAC", - "\xE1\x86\xAD", "\xE1\x84\x83", - "\xE1\x84\x84", "\xE1\x84\x85", - "\xE1\x86\xB0", "\xE1\x86\xB1", - "\xE1\x86\xB2", "\xE1\x86\xB3", - "\xE1\x86\xB4", "\xE1\x86\xB5", - "\xE1\x84\x9A", "\xE1\x84\x86", - "\xE1\x84\x87", "\xE1\x84\x88", - "\xE1\x84\xA1", "\xE1\x84\x89", - "\xE1\x84\x8A", "\xE1\x84\x8B", - "\xE1\x84\x8C", "\xE1\x84\x8D", - "\xE1\x84\x8E", "\xE1\x84\x8F", - "\xE1\x84\x90", "\xE1\x84\x91", - "\xE1\x84\x92", "\xE1\x85\xA1", - "\xE1\x85\xA2", "\xE1\x85\xA3", - "\xE1\x85\xA4", "\xE1\x85\xA5", - "\xE1\x85\xA6", "\xE1\x85\xA7", - "\xE1\x85\xA8", "\xE1\x85\xA9", - "\xE1\x85\xAA", "\xE1\x85\xAB", - "\xE1\x85\xAC", "\xE1\x85\xAD", - "\xE1\x85\xAE", "\xE1\x85\xAF", - "\xE1\x85\xB0", "\xE1\x85\xB1", - "\xE1\x85\xB2", "\xE1\x85\xB3", - "\xE1\x85\xB4", "\xE1\x85\xB5", - "\xE1\x85\xA0", "\xE1\x84\x94", - "\xE1\x84\x95", "\xE1\x87\x87", - "\xE1\x87\x88", "\xE1\x87\x8C", - "\xE1\x87\x8E", "\xE1\x87\x93", - "\xE1\x87\x97", "\xE1\x87\x99", - "\xE1\x84\x9C", "\xE1\x87\x9D", - "\xE1\x87\x9F", "\xE1\x84\x9D", - "\xE1\x84\x9E", "\xE1\x84\xA0", - "\xE1\x84\xA2", "\xE1\x84\xA3", - "\xE1\x84\xA7", "\xE1\x84\xA9", - "\xE1\x84\xAB", "\xE1\x84\xAC", - "\xE1\x84\xAD", "\xE1\x84\xAE", - "\xE1\x84\xAF", "\xE1\x84\xB2", - "\xE1\x84\xB6", "\xE1\x85\x80", - "\xE1\x85\x87", "\xE1\x85\x8C", - "\xE1\x87\xB1", "\xE1\x87\xB2", - "\xE1\x85\x97", "\xE1\x85\x98", - "\xE1\x85\x99", "\xE1\x86\x84", - "\xE1\x86\x85", "\xE1\x86\x88", - "\xE1\x86\x91", "\xE1\x86\x92", - "\xE1\x86\x94", "\xE1\x86\x9E", - "\xE1\x86\xA1", NULL, - NULL, NULL, - "\xE4\xB8\x80", "\xE4\xBA\x8C", - "\xE4\xB8\x89", "\xE5\x9B\x9B", - "\xE4\xB8\x8A", "\xE4\xB8\xAD", - "\xE4\xB8\x8B", "\xE7\x94\xB2", - "\xE4\xB9\x99", "\xE4\xB8\x99", - "\xE4\xB8\x81", "\xE5\xA4\xA9", - "\xE5\x9C\xB0", "\xE4\xBA\xBA", - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, -}; - -static const char *const decompCompatPage50[0x100] = { - "\x28\xE1\x84\x80\x29", "\x28\xE1\x84\x82\x29", - "\x28\xE1\x84\x83\x29", "\x28\xE1\x84\x85\x29", - "\x28\xE1\x84\x86\x29", "\x28\xE1\x84\x87\x29", - "\x28\xE1\x84\x89\x29", "\x28\xE1\x84\x8B\x29", - "\x28\xE1\x84\x8C\x29", "\x28\xE1\x84\x8E\x29", - "\x28\xE1\x84\x8F\x29", "\x28\xE1\x84\x90\x29", - "\x28\xE1\x84\x91\x29", "\x28\xE1\x84\x92\x29", - "\x28\xE1\x84\x80\xE1\x85\xA1\x29", "\x28\xE1\x84\x82\xE1\x85\xA1\x29", - "\x28\xE1\x84\x83\xE1\x85\xA1\x29", "\x28\xE1\x84\x85\xE1\x85\xA1\x29", - "\x28\xE1\x84\x86\xE1\x85\xA1\x29", "\x28\xE1\x84\x87\xE1\x85\xA1\x29", - "\x28\xE1\x84\x89\xE1\x85\xA1\x29", "\x28\xE1\x84\x8B\xE1\x85\xA1\x29", - "\x28\xE1\x84\x8C\xE1\x85\xA1\x29", "\x28\xE1\x84\x8E\xE1\x85\xA1\x29", - "\x28\xE1\x84\x8F\xE1\x85\xA1\x29", "\x28\xE1\x84\x90\xE1\x85\xA1\x29", - "\x28\xE1\x84\x91\xE1\x85\xA1\x29", "\x28\xE1\x84\x92\xE1\x85\xA1\x29", - "\x28\xE1\x84\x8C\xE1\x85\xAE\x29", "\x28\xE1\x84\x8B\xE1\x85\xA9\xE1\x84\x8C\xE1\x85\xA5\xE1\x86\xAB\x29", - "\x28\xE1\x84\x8B\xE1\x85\xA9\xE1\x84\x92\xE1\x85\xAE\x29", NULL, - "\x28\xE4\xB8\x80\x29", "\x28\xE4\xBA\x8C\x29", - "\x28\xE4\xB8\x89\x29", "\x28\xE5\x9B\x9B\x29", - "\x28\xE4\xBA\x94\x29", "\x28\xE5\x85\xAD\x29", - "\x28\xE4\xB8\x83\x29", "\x28\xE5\x85\xAB\x29", - "\x28\xE4\xB9\x9D\x29", "\x28\xE5\x8D\x81\x29", - "\x28\xE6\x9C\x88\x29", "\x28\xE7\x81\xAB\x29", - "\x28\xE6\xB0\xB4\x29", "\x28\xE6\x9C\xA8\x29", - "\x28\xE9\x87\x91\x29", "\x28\xE5\x9C\x9F\x29", - "\x28\xE6\x97\xA5\x29", "\x28\xE6\xA0\xAA\x29", - "\x28\xE6\x9C\x89\x29", "\x28\xE7\xA4\xBE\x29", - "\x28\xE5\x90\x8D\x29", "\x28\xE7\x89\xB9\x29", - "\x28\xE8\xB2\xA1\x29", "\x28\xE7\xA5\x9D\x29", - "\x28\xE5\x8A\xB4\x29", "\x28\xE4\xBB\xA3\x29", - "\x28\xE5\x91\xBC\x29", "\x28\xE5\xAD\xA6\x29", - "\x28\xE7\x9B\xA3\x29", "\x28\xE4\xBC\x81\x29", - "\x28\xE8\xB3\x87\x29", "\x28\xE5\x8D\x94\x29", - "\x28\xE7\xA5\xAD\x29", "\x28\xE4\xBC\x91\x29", - "\x28\xE8\x87\xAA\x29", "\x28\xE8\x87\xB3\x29", - "\xE5\x95\x8F", "\xE5\xB9\xBC", - "\xE6\x96\x87", "\xE7\xAE\x8F", - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\x50\x54\x45", "\x32\x31", - "\x32\x32", "\x32\x33", - "\x32\x34", "\x32\x35", - "\x32\x36", "\x32\x37", - "\x32\x38", "\x32\x39", - "\x33\x30", "\x33\x31", - "\x33\x32", "\x33\x33", - "\x33\x34", "\x33\x35", - "\xE1\x84\x80", "\xE1\x84\x82", - "\xE1\x84\x83", "\xE1\x84\x85", - "\xE1\x84\x86", "\xE1\x84\x87", - "\xE1\x84\x89", "\xE1\x84\x8B", - "\xE1\x84\x8C", "\xE1\x84\x8E", - "\xE1\x84\x8F", "\xE1\x84\x90", - "\xE1\x84\x91", "\xE1\x84\x92", - "\xE1\x84\x80\xE1\x85\xA1", "\xE1\x84\x82\xE1\x85\xA1", - "\xE1\x84\x83\xE1\x85\xA1", "\xE1\x84\x85\xE1\x85\xA1", - "\xE1\x84\x86\xE1\x85\xA1", "\xE1\x84\x87\xE1\x85\xA1", - "\xE1\x84\x89\xE1\x85\xA1", "\xE1\x84\x8B\xE1\x85\xA1", - "\xE1\x84\x8C\xE1\x85\xA1", "\xE1\x84\x8E\xE1\x85\xA1", - "\xE1\x84\x8F\xE1\x85\xA1", "\xE1\x84\x90\xE1\x85\xA1", - "\xE1\x84\x91\xE1\x85\xA1", "\xE1\x84\x92\xE1\x85\xA1", - "\xE1\x84\x8E\xE1\x85\xA1\xE1\x86\xB7\xE1\x84\x80\xE1\x85\xA9", "\xE1\x84\x8C\xE1\x85\xAE\xE1\x84\x8B\xE1\x85\xB4", - "\xE1\x84\x8B\xE1\x85\xAE", NULL, - "\xE4\xB8\x80", "\xE4\xBA\x8C", - "\xE4\xB8\x89", "\xE5\x9B\x9B", - "\xE4\xBA\x94", "\xE5\x85\xAD", - "\xE4\xB8\x83", "\xE5\x85\xAB", - "\xE4\xB9\x9D", "\xE5\x8D\x81", - "\xE6\x9C\x88", "\xE7\x81\xAB", - "\xE6\xB0\xB4", "\xE6\x9C\xA8", - "\xE9\x87\x91", "\xE5\x9C\x9F", - "\xE6\x97\xA5", "\xE6\xA0\xAA", - "\xE6\x9C\x89", "\xE7\xA4\xBE", - "\xE5\x90\x8D", "\xE7\x89\xB9", - "\xE8\xB2\xA1", "\xE7\xA5\x9D", - "\xE5\x8A\xB4", "\xE7\xA7\x98", - "\xE7\x94\xB7", "\xE5\xA5\xB3", - "\xE9\x81\xA9", "\xE5\x84\xAA", - "\xE5\x8D\xB0", "\xE6\xB3\xA8", - "\xE9\xA0\x85", "\xE4\xBC\x91", - "\xE5\x86\x99", "\xE6\xAD\xA3", - "\xE4\xB8\x8A", "\xE4\xB8\xAD", - "\xE4\xB8\x8B", "\xE5\xB7\xA6", - "\xE5\x8F\xB3", "\xE5\x8C\xBB", - "\xE5\xAE\x97", "\xE5\xAD\xA6", - "\xE7\x9B\xA3", "\xE4\xBC\x81", - "\xE8\xB3\x87", "\xE5\x8D\x94", - "\xE5\xA4\x9C", "\x33\x36", - "\x33\x37", "\x33\x38", - "\x33\x39", "\x34\x30", - "\x34\x31", "\x34\x32", - "\x34\x33", "\x34\x34", - "\x34\x35", "\x34\x36", - "\x34\x37", "\x34\x38", - "\x34\x39", "\x35\x30", - "\x31\xE6\x9C\x88", "\x32\xE6\x9C\x88", - "\x33\xE6\x9C\x88", "\x34\xE6\x9C\x88", - "\x35\xE6\x9C\x88", "\x36\xE6\x9C\x88", - "\x37\xE6\x9C\x88", "\x38\xE6\x9C\x88", - "\x39\xE6\x9C\x88", "\x31\x30\xE6\x9C\x88", - "\x31\x31\xE6\x9C\x88", "\x31\x32\xE6\x9C\x88", - "\x48\x67", "\x65\x72\x67", - "\x65\x56", "\x4C\x54\x44", - "\xE3\x82\xA2", "\xE3\x82\xA4", - "\xE3\x82\xA6", "\xE3\x82\xA8", - "\xE3\x82\xAA", "\xE3\x82\xAB", - "\xE3\x82\xAD", "\xE3\x82\xAF", - "\xE3\x82\xB1", "\xE3\x82\xB3", - "\xE3\x82\xB5", "\xE3\x82\xB7", - "\xE3\x82\xB9", "\xE3\x82\xBB", - "\xE3\x82\xBD", "\xE3\x82\xBF", - "\xE3\x83\x81", "\xE3\x83\x84", - "\xE3\x83\x86", "\xE3\x83\x88", - "\xE3\x83\x8A", "\xE3\x83\x8B", - "\xE3\x83\x8C", "\xE3\x83\x8D", - "\xE3\x83\x8E", "\xE3\x83\x8F", - "\xE3\x83\x92", "\xE3\x83\x95", - "\xE3\x83\x98", "\xE3\x83\x9B", - "\xE3\x83\x9E", "\xE3\x83\x9F", - "\xE3\x83\xA0", "\xE3\x83\xA1", - "\xE3\x83\xA2", "\xE3\x83\xA4", - "\xE3\x83\xA6", "\xE3\x83\xA8", - "\xE3\x83\xA9", "\xE3\x83\xAA", - "\xE3\x83\xAB", "\xE3\x83\xAC", - "\xE3\x83\xAD", "\xE3\x83\xAF", - "\xE3\x83\xB0", "\xE3\x83\xB1", - "\xE3\x83\xB2", "\xE4\xBB\xA4\xE5\x92\x8C", -}; - -static const char *const decompCompatPage51[0x100] = { - "\xE3\x82\xA2\xE3\x83\x8F\xE3\x82\x9A\xE3\x83\xBC\xE3\x83\x88", "\xE3\x82\xA2\xE3\x83\xAB\xE3\x83\x95\xE3\x82\xA1", - "\xE3\x82\xA2\xE3\x83\xB3\xE3\x83\x98\xE3\x82\x9A\xE3\x82\xA2", "\xE3\x82\xA2\xE3\x83\xBC\xE3\x83\xAB", - "\xE3\x82\xA4\xE3\x83\x8B\xE3\x83\xB3\xE3\x82\xAF\xE3\x82\x99", "\xE3\x82\xA4\xE3\x83\xB3\xE3\x83\x81", - "\xE3\x82\xA6\xE3\x82\xA9\xE3\x83\xB3", "\xE3\x82\xA8\xE3\x82\xB9\xE3\x82\xAF\xE3\x83\xBC\xE3\x83\x88\xE3\x82\x99", - "\xE3\x82\xA8\xE3\x83\xBC\xE3\x82\xAB\xE3\x83\xBC", "\xE3\x82\xAA\xE3\x83\xB3\xE3\x82\xB9", - "\xE3\x82\xAA\xE3\x83\xBC\xE3\x83\xA0", "\xE3\x82\xAB\xE3\x82\xA4\xE3\x83\xAA", - "\xE3\x82\xAB\xE3\x83\xA9\xE3\x83\x83\xE3\x83\x88", "\xE3\x82\xAB\xE3\x83\xAD\xE3\x83\xAA\xE3\x83\xBC", - "\xE3\x82\xAB\xE3\x82\x99\xE3\x83\xAD\xE3\x83\xB3", "\xE3\x82\xAB\xE3\x82\x99\xE3\x83\xB3\xE3\x83\x9E", - "\xE3\x82\xAD\xE3\x82\x99\xE3\x82\xAB\xE3\x82\x99", "\xE3\x82\xAD\xE3\x82\x99\xE3\x83\x8B\xE3\x83\xBC", - "\xE3\x82\xAD\xE3\x83\xA5\xE3\x83\xAA\xE3\x83\xBC", "\xE3\x82\xAD\xE3\x82\x99\xE3\x83\xAB\xE3\x82\xBF\xE3\x82\x99\xE3\x83\xBC", - "\xE3\x82\xAD\xE3\x83\xAD", "\xE3\x82\xAD\xE3\x83\xAD\xE3\x82\xAF\xE3\x82\x99\xE3\x83\xA9\xE3\x83\xA0", - "\xE3\x82\xAD\xE3\x83\xAD\xE3\x83\xA1\xE3\x83\xBC\xE3\x83\x88\xE3\x83\xAB", "\xE3\x82\xAD\xE3\x83\xAD\xE3\x83\xAF\xE3\x83\x83\xE3\x83\x88", - "\xE3\x82\xAF\xE3\x82\x99\xE3\x83\xA9\xE3\x83\xA0", "\xE3\x82\xAF\xE3\x82\x99\xE3\x83\xA9\xE3\x83\xA0\xE3\x83\x88\xE3\x83\xB3", - "\xE3\x82\xAF\xE3\x83\xAB\xE3\x82\xBB\xE3\x82\x99\xE3\x82\xA4\xE3\x83\xAD", "\xE3\x82\xAF\xE3\x83\xAD\xE3\x83\xBC\xE3\x83\x8D", - "\xE3\x82\xB1\xE3\x83\xBC\xE3\x82\xB9", "\xE3\x82\xB3\xE3\x83\xAB\xE3\x83\x8A", - "\xE3\x82\xB3\xE3\x83\xBC\xE3\x83\x9B\xE3\x82\x9A", "\xE3\x82\xB5\xE3\x82\xA4\xE3\x82\xAF\xE3\x83\xAB", - "\xE3\x82\xB5\xE3\x83\xB3\xE3\x83\x81\xE3\x83\xBC\xE3\x83\xA0", "\xE3\x82\xB7\xE3\x83\xAA\xE3\x83\xB3\xE3\x82\xAF\xE3\x82\x99", - "\xE3\x82\xBB\xE3\x83\xB3\xE3\x83\x81", "\xE3\x82\xBB\xE3\x83\xB3\xE3\x83\x88", - "\xE3\x82\xBF\xE3\x82\x99\xE3\x83\xBC\xE3\x82\xB9", "\xE3\x83\x86\xE3\x82\x99\xE3\x82\xB7", - "\xE3\x83\x88\xE3\x82\x99\xE3\x83\xAB", "\xE3\x83\x88\xE3\x83\xB3", - "\xE3\x83\x8A\xE3\x83\x8E", "\xE3\x83\x8E\xE3\x83\x83\xE3\x83\x88", - "\xE3\x83\x8F\xE3\x82\xA4\xE3\x83\x84", "\xE3\x83\x8F\xE3\x82\x9A\xE3\x83\xBC\xE3\x82\xBB\xE3\x83\xB3\xE3\x83\x88", - "\xE3\x83\x8F\xE3\x82\x9A\xE3\x83\xBC\xE3\x83\x84", "\xE3\x83\x8F\xE3\x82\x99\xE3\x83\xBC\xE3\x83\xAC\xE3\x83\xAB", - "\xE3\x83\x92\xE3\x82\x9A\xE3\x82\xA2\xE3\x82\xB9\xE3\x83\x88\xE3\x83\xAB", "\xE3\x83\x92\xE3\x82\x9A\xE3\x82\xAF\xE3\x83\xAB", - "\xE3\x83\x92\xE3\x82\x9A\xE3\x82\xB3", "\xE3\x83\x92\xE3\x82\x99\xE3\x83\xAB", - "\xE3\x83\x95\xE3\x82\xA1\xE3\x83\xA9\xE3\x83\x83\xE3\x83\x88\xE3\x82\x99", "\xE3\x83\x95\xE3\x82\xA3\xE3\x83\xBC\xE3\x83\x88", - "\xE3\x83\x95\xE3\x82\x99\xE3\x83\x83\xE3\x82\xB7\xE3\x82\xA7\xE3\x83\xAB", "\xE3\x83\x95\xE3\x83\xA9\xE3\x83\xB3", - "\xE3\x83\x98\xE3\x82\xAF\xE3\x82\xBF\xE3\x83\xBC\xE3\x83\xAB", "\xE3\x83\x98\xE3\x82\x9A\xE3\x82\xBD", - "\xE3\x83\x98\xE3\x82\x9A\xE3\x83\x8B\xE3\x83\x92", "\xE3\x83\x98\xE3\x83\xAB\xE3\x83\x84", - "\xE3\x83\x98\xE3\x82\x9A\xE3\x83\xB3\xE3\x82\xB9", "\xE3\x83\x98\xE3\x82\x9A\xE3\x83\xBC\xE3\x82\xB7\xE3\x82\x99", - "\xE3\x83\x98\xE3\x82\x99\xE3\x83\xBC\xE3\x82\xBF", "\xE3\x83\x9B\xE3\x82\x9A\xE3\x82\xA4\xE3\x83\xB3\xE3\x83\x88", - "\xE3\x83\x9B\xE3\x82\x99\xE3\x83\xAB\xE3\x83\x88", "\xE3\x83\x9B\xE3\x83\xB3", - "\xE3\x83\x9B\xE3\x82\x9A\xE3\x83\xB3\xE3\x83\x88\xE3\x82\x99", "\xE3\x83\x9B\xE3\x83\xBC\xE3\x83\xAB", - "\xE3\x83\x9B\xE3\x83\xBC\xE3\x83\xB3", "\xE3\x83\x9E\xE3\x82\xA4\xE3\x82\xAF\xE3\x83\xAD", - "\xE3\x83\x9E\xE3\x82\xA4\xE3\x83\xAB", "\xE3\x83\x9E\xE3\x83\x83\xE3\x83\x8F", - "\xE3\x83\x9E\xE3\x83\xAB\xE3\x82\xAF", "\xE3\x83\x9E\xE3\x83\xB3\xE3\x82\xB7\xE3\x83\xA7\xE3\x83\xB3", - "\xE3\x83\x9F\xE3\x82\xAF\xE3\x83\xAD\xE3\x83\xB3", "\xE3\x83\x9F\xE3\x83\xAA", - "\xE3\x83\x9F\xE3\x83\xAA\xE3\x83\x8F\xE3\x82\x99\xE3\x83\xBC\xE3\x83\xAB", "\xE3\x83\xA1\xE3\x82\xAB\xE3\x82\x99", - "\xE3\x83\xA1\xE3\x82\xAB\xE3\x82\x99\xE3\x83\x88\xE3\x83\xB3", "\xE3\x83\xA1\xE3\x83\xBC\xE3\x83\x88\xE3\x83\xAB", - "\xE3\x83\xA4\xE3\x83\xBC\xE3\x83\x88\xE3\x82\x99", "\xE3\x83\xA4\xE3\x83\xBC\xE3\x83\xAB", - "\xE3\x83\xA6\xE3\x82\xA2\xE3\x83\xB3", "\xE3\x83\xAA\xE3\x83\x83\xE3\x83\x88\xE3\x83\xAB", - "\xE3\x83\xAA\xE3\x83\xA9", "\xE3\x83\xAB\xE3\x83\x92\xE3\x82\x9A\xE3\x83\xBC", - "\xE3\x83\xAB\xE3\x83\xBC\xE3\x83\x95\xE3\x82\x99\xE3\x83\xAB", "\xE3\x83\xAC\xE3\x83\xA0", - "\xE3\x83\xAC\xE3\x83\xB3\xE3\x83\x88\xE3\x82\xB1\xE3\x82\x99\xE3\x83\xB3", "\xE3\x83\xAF\xE3\x83\x83\xE3\x83\x88", - "\x30\xE7\x82\xB9", "\x31\xE7\x82\xB9", - "\x32\xE7\x82\xB9", "\x33\xE7\x82\xB9", - "\x34\xE7\x82\xB9", "\x35\xE7\x82\xB9", - "\x36\xE7\x82\xB9", "\x37\xE7\x82\xB9", - "\x38\xE7\x82\xB9", "\x39\xE7\x82\xB9", - "\x31\x30\xE7\x82\xB9", "\x31\x31\xE7\x82\xB9", - "\x31\x32\xE7\x82\xB9", "\x31\x33\xE7\x82\xB9", - "\x31\x34\xE7\x82\xB9", "\x31\x35\xE7\x82\xB9", - "\x31\x36\xE7\x82\xB9", "\x31\x37\xE7\x82\xB9", - "\x31\x38\xE7\x82\xB9", "\x31\x39\xE7\x82\xB9", - "\x32\x30\xE7\x82\xB9", "\x32\x31\xE7\x82\xB9", - "\x32\x32\xE7\x82\xB9", "\x32\x33\xE7\x82\xB9", - "\x32\x34\xE7\x82\xB9", "\x68\x50\x61", - "\x64\x61", "\x41\x55", - "\x62\x61\x72", "\x6F\x56", - "\x70\x63", "\x64\x6D", - "\x64\x6D\x32", "\x64\x6D\x33", - "\x49\x55", "\xE5\xB9\xB3\xE6\x88\x90", - "\xE6\x98\xAD\xE5\x92\x8C", "\xE5\xA4\xA7\xE6\xAD\xA3", - "\xE6\x98\x8E\xE6\xB2\xBB", "\xE6\xA0\xAA\xE5\xBC\x8F\xE4\xBC\x9A\xE7\xA4\xBE", - "\x70\x41", "\x6E\x41", - "\xCE\xBC\x41", "\x6D\x41", - "\x6B\x41", "\x4B\x42", - "\x4D\x42", "\x47\x42", - "\x63\x61\x6C", "\x6B\x63\x61\x6C", - "\x70\x46", "\x6E\x46", - "\xCE\xBC\x46", "\xCE\xBC\x67", - "\x6D\x67", "\x6B\x67", - "\x48\x7A", "\x6B\x48\x7A", - "\x4D\x48\x7A", "\x47\x48\x7A", - "\x54\x48\x7A", "\xCE\xBC\x6C", - "\x6D\x6C", "\x64\x6C", - "\x6B\x6C", "\x66\x6D", - "\x6E\x6D", "\xCE\xBC\x6D", - "\x6D\x6D", "\x63\x6D", - "\x6B\x6D", "\x6D\x6D\x32", - "\x63\x6D\x32", "\x6D\x32", - "\x6B\x6D\x32", "\x6D\x6D\x33", - "\x63\x6D\x33", "\x6D\x33", - "\x6B\x6D\x33", "\x6D\xE2\x88\x95\x73", - "\x6D\xE2\x88\x95\x73\x32", "\x50\x61", - "\x6B\x50\x61", "\x4D\x50\x61", - "\x47\x50\x61", "\x72\x61\x64", - "\x72\x61\x64\xE2\x88\x95\x73", "\x72\x61\x64\xE2\x88\x95\x73\x32", - "\x70\x73", "\x6E\x73", - "\xCE\xBC\x73", "\x6D\x73", - "\x70\x56", "\x6E\x56", - "\xCE\xBC\x56", "\x6D\x56", - "\x6B\x56", "\x4D\x56", - "\x70\x57", "\x6E\x57", - "\xCE\xBC\x57", "\x6D\x57", - "\x6B\x57", "\x4D\x57", - "\x6B\xCE\xA9", "\x4D\xCE\xA9", - "\x61\x2E\x6D\x2E", "\x42\x71", - "\x63\x63", "\x63\x64", - "\x43\xE2\x88\x95\x6B\x67", "\x43\x6F\x2E", - "\x64\x42", "\x47\x79", - "\x68\x61", "\x48\x50", - "\x69\x6E", "\x4B\x4B", - "\x4B\x4D", "\x6B\x74", - "\x6C\x6D", "\x6C\x6E", - "\x6C\x6F\x67", "\x6C\x78", - "\x6D\x62", "\x6D\x69\x6C", - "\x6D\x6F\x6C", "\x50\x48", - "\x70\x2E\x6D\x2E", "\x50\x50\x4D", - "\x50\x52", "\x73\x72", - "\x53\x76", "\x57\x62", - "\x56\xE2\x88\x95\x6D", "\x41\xE2\x88\x95\x6D", - "\x31\xE6\x97\xA5", "\x32\xE6\x97\xA5", - "\x33\xE6\x97\xA5", "\x34\xE6\x97\xA5", - "\x35\xE6\x97\xA5", "\x36\xE6\x97\xA5", - "\x37\xE6\x97\xA5", "\x38\xE6\x97\xA5", - "\x39\xE6\x97\xA5", "\x31\x30\xE6\x97\xA5", - "\x31\x31\xE6\x97\xA5", "\x31\x32\xE6\x97\xA5", - "\x31\x33\xE6\x97\xA5", "\x31\x34\xE6\x97\xA5", - "\x31\x35\xE6\x97\xA5", "\x31\x36\xE6\x97\xA5", - "\x31\x37\xE6\x97\xA5", "\x31\x38\xE6\x97\xA5", - "\x31\x39\xE6\x97\xA5", "\x32\x30\xE6\x97\xA5", - "\x32\x31\xE6\x97\xA5", "\x32\x32\xE6\x97\xA5", - "\x32\x33\xE6\x97\xA5", "\x32\x34\xE6\x97\xA5", - "\x32\x35\xE6\x97\xA5", "\x32\x36\xE6\x97\xA5", - "\x32\x37\xE6\x97\xA5", "\x32\x38\xE6\x97\xA5", - "\x32\x39\xE6\x97\xA5", "\x33\x30\xE6\x97\xA5", - "\x33\x31\xE6\x97\xA5", "\x67\x61\x6C", -}; - -static const char *const decompCompatPage166[0x100] = { - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\xD1\x8A", "\xD1\x8C", - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, -}; - -static const char *const decompCompatPage167[0x100] = { - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\xEA\x9D\xAF", NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\xC4\xA6", "\xC5\x93", - NULL, NULL, - NULL, NULL, - NULL, NULL, -}; - -static const char *const decompCompatPage171[0x100] = { - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\xEA\x9C\xA7", "\xEA\xAC\xB7", - "\xC9\xAB", "\xEA\xAD\x92", - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, "\xCA\x8D", - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, -}; - -static const char *const decompCompatPage251[0x100] = { - "\x66\x66", "\x66\x69", - "\x66\x6C", "\x66\x66\x69", - "\x66\x66\x6C", "\x73\x74", - "\x73\x74", NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, "\xD5\xB4\xD5\xB6", - "\xD5\xB4\xD5\xA5", "\xD5\xB4\xD5\xAB", - "\xD5\xBE\xD5\xB6", "\xD5\xB4\xD5\xAD", - NULL, NULL, - NULL, NULL, - NULL, "\xD7\x99\xD6\xB4", - NULL, "\xD7\xB2\xD6\xB7", - "\xD7\xA2", "\xD7\x90", - "\xD7\x93", "\xD7\x94", - "\xD7\x9B", "\xD7\x9C", - "\xD7\x9D", "\xD7\xA8", - "\xD7\xAA", "\x2B", - "\xD7\xA9\xD7\x81", "\xD7\xA9\xD7\x82", - "\xD7\xA9\xD6\xBC\xD7\x81", "\xD7\xA9\xD6\xBC\xD7\x82", - "\xD7\x90\xD6\xB7", "\xD7\x90\xD6\xB8", - "\xD7\x90\xD6\xBC", "\xD7\x91\xD6\xBC", - "\xD7\x92\xD6\xBC", "\xD7\x93\xD6\xBC", - "\xD7\x94\xD6\xBC", "\xD7\x95\xD6\xBC", - "\xD7\x96\xD6\xBC", NULL, - "\xD7\x98\xD6\xBC", "\xD7\x99\xD6\xBC", - "\xD7\x9A\xD6\xBC", "\xD7\x9B\xD6\xBC", - "\xD7\x9C\xD6\xBC", NULL, - "\xD7\x9E\xD6\xBC", NULL, - "\xD7\xA0\xD6\xBC", "\xD7\xA1\xD6\xBC", - NULL, "\xD7\xA3\xD6\xBC", - "\xD7\xA4\xD6\xBC", NULL, - "\xD7\xA6\xD6\xBC", "\xD7\xA7\xD6\xBC", - "\xD7\xA8\xD6\xBC", "\xD7\xA9\xD6\xBC", - "\xD7\xAA\xD6\xBC", "\xD7\x95\xD6\xB9", - "\xD7\x91\xD6\xBF", "\xD7\x9B\xD6\xBF", - "\xD7\xA4\xD6\xBF", "\xD7\x90\xD7\x9C", - "\xD9\xB1", "\xD9\xB1", - "\xD9\xBB", "\xD9\xBB", - "\xD9\xBB", "\xD9\xBB", - "\xD9\xBE", "\xD9\xBE", - "\xD9\xBE", "\xD9\xBE", - "\xDA\x80", "\xDA\x80", - "\xDA\x80", "\xDA\x80", - "\xD9\xBA", "\xD9\xBA", - "\xD9\xBA", "\xD9\xBA", - "\xD9\xBF", "\xD9\xBF", - "\xD9\xBF", "\xD9\xBF", - "\xD9\xB9", "\xD9\xB9", - "\xD9\xB9", "\xD9\xB9", - "\xDA\xA4", "\xDA\xA4", - "\xDA\xA4", "\xDA\xA4", - "\xDA\xA6", "\xDA\xA6", - "\xDA\xA6", "\xDA\xA6", - "\xDA\x84", "\xDA\x84", - "\xDA\x84", "\xDA\x84", - "\xDA\x83", "\xDA\x83", - "\xDA\x83", "\xDA\x83", - "\xDA\x86", "\xDA\x86", - "\xDA\x86", "\xDA\x86", - "\xDA\x87", "\xDA\x87", - "\xDA\x87", "\xDA\x87", - "\xDA\x8D", "\xDA\x8D", - "\xDA\x8C", "\xDA\x8C", - "\xDA\x8E", "\xDA\x8E", - "\xDA\x88", "\xDA\x88", - "\xDA\x98", "\xDA\x98", - "\xDA\x91", "\xDA\x91", - "\xDA\xA9", "\xDA\xA9", - "\xDA\xA9", "\xDA\xA9", - "\xDA\xAF", "\xDA\xAF", - "\xDA\xAF", "\xDA\xAF", - "\xDA\xB3", "\xDA\xB3", - "\xDA\xB3", "\xDA\xB3", - "\xDA\xB1", "\xDA\xB1", - "\xDA\xB1", "\xDA\xB1", - "\xDA\xBA", "\xDA\xBA", - "\xDA\xBB", "\xDA\xBB", - "\xDA\xBB", "\xDA\xBB", - "\xDB\x95\xD9\x94", "\xDB\x95\xD9\x94", - "\xDB\x81", "\xDB\x81", - "\xDB\x81", "\xDB\x81", - "\xDA\xBE", "\xDA\xBE", - "\xDA\xBE", "\xDA\xBE", - "\xDB\x92", "\xDB\x92", - "\xDB\x92\xD9\x94", "\xDB\x92\xD9\x94", - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, "\xDA\xAD", - "\xDA\xAD", "\xDA\xAD", - "\xDA\xAD", "\xDB\x87", - "\xDB\x87", "\xDB\x86", - "\xDB\x86", "\xDB\x88", - "\xDB\x88", "\xDB\x87\xD9\xB4", - "\xDB\x8B", "\xDB\x8B", - "\xDB\x85", "\xDB\x85", - "\xDB\x89", "\xDB\x89", - "\xDB\x90", "\xDB\x90", - "\xDB\x90", "\xDB\x90", - "\xD9\x89", "\xD9\x89", - "\xD9\x8A\xD9\x94\xD8\xA7", "\xD9\x8A\xD9\x94\xD8\xA7", - "\xD9\x8A\xD9\x94\xDB\x95", "\xD9\x8A\xD9\x94\xDB\x95", - "\xD9\x8A\xD9\x94\xD9\x88", "\xD9\x8A\xD9\x94\xD9\x88", - "\xD9\x8A\xD9\x94\xDB\x87", "\xD9\x8A\xD9\x94\xDB\x87", - "\xD9\x8A\xD9\x94\xDB\x86", "\xD9\x8A\xD9\x94\xDB\x86", - "\xD9\x8A\xD9\x94\xDB\x88", "\xD9\x8A\xD9\x94\xDB\x88", - "\xD9\x8A\xD9\x94\xDB\x90", "\xD9\x8A\xD9\x94\xDB\x90", - "\xD9\x8A\xD9\x94\xDB\x90", "\xD9\x8A\xD9\x94\xD9\x89", - "\xD9\x8A\xD9\x94\xD9\x89", "\xD9\x8A\xD9\x94\xD9\x89", - "\xDB\x8C", "\xDB\x8C", - "\xDB\x8C", "\xDB\x8C", -}; - -static const char *const decompCompatPage252[0x100] = { - "\xD9\x8A\xD9\x94\xD8\xAC", "\xD9\x8A\xD9\x94\xD8\xAD", - "\xD9\x8A\xD9\x94\xD9\x85", "\xD9\x8A\xD9\x94\xD9\x89", - "\xD9\x8A\xD9\x94\xD9\x8A", "\xD8\xA8\xD8\xAC", - "\xD8\xA8\xD8\xAD", "\xD8\xA8\xD8\xAE", - "\xD8\xA8\xD9\x85", "\xD8\xA8\xD9\x89", - "\xD8\xA8\xD9\x8A", "\xD8\xAA\xD8\xAC", - "\xD8\xAA\xD8\xAD", "\xD8\xAA\xD8\xAE", - "\xD8\xAA\xD9\x85", "\xD8\xAA\xD9\x89", - "\xD8\xAA\xD9\x8A", "\xD8\xAB\xD8\xAC", - "\xD8\xAB\xD9\x85", "\xD8\xAB\xD9\x89", - "\xD8\xAB\xD9\x8A", "\xD8\xAC\xD8\xAD", - "\xD8\xAC\xD9\x85", "\xD8\xAD\xD8\xAC", - "\xD8\xAD\xD9\x85", "\xD8\xAE\xD8\xAC", - "\xD8\xAE\xD8\xAD", "\xD8\xAE\xD9\x85", - "\xD8\xB3\xD8\xAC", "\xD8\xB3\xD8\xAD", - "\xD8\xB3\xD8\xAE", "\xD8\xB3\xD9\x85", - "\xD8\xB5\xD8\xAD", "\xD8\xB5\xD9\x85", - "\xD8\xB6\xD8\xAC", "\xD8\xB6\xD8\xAD", - "\xD8\xB6\xD8\xAE", "\xD8\xB6\xD9\x85", - "\xD8\xB7\xD8\xAD", "\xD8\xB7\xD9\x85", - "\xD8\xB8\xD9\x85", "\xD8\xB9\xD8\xAC", - "\xD8\xB9\xD9\x85", "\xD8\xBA\xD8\xAC", - "\xD8\xBA\xD9\x85", "\xD9\x81\xD8\xAC", - "\xD9\x81\xD8\xAD", "\xD9\x81\xD8\xAE", - "\xD9\x81\xD9\x85", "\xD9\x81\xD9\x89", - "\xD9\x81\xD9\x8A", "\xD9\x82\xD8\xAD", - "\xD9\x82\xD9\x85", "\xD9\x82\xD9\x89", - "\xD9\x82\xD9\x8A", "\xD9\x83\xD8\xA7", - "\xD9\x83\xD8\xAC", "\xD9\x83\xD8\xAD", - "\xD9\x83\xD8\xAE", "\xD9\x83\xD9\x84", - "\xD9\x83\xD9\x85", "\xD9\x83\xD9\x89", - "\xD9\x83\xD9\x8A", "\xD9\x84\xD8\xAC", - "\xD9\x84\xD8\xAD", "\xD9\x84\xD8\xAE", - "\xD9\x84\xD9\x85", "\xD9\x84\xD9\x89", - "\xD9\x84\xD9\x8A", "\xD9\x85\xD8\xAC", - "\xD9\x85\xD8\xAD", "\xD9\x85\xD8\xAE", - "\xD9\x85\xD9\x85", "\xD9\x85\xD9\x89", - "\xD9\x85\xD9\x8A", "\xD9\x86\xD8\xAC", - "\xD9\x86\xD8\xAD", "\xD9\x86\xD8\xAE", - "\xD9\x86\xD9\x85", "\xD9\x86\xD9\x89", - "\xD9\x86\xD9\x8A", "\xD9\x87\xD8\xAC", - "\xD9\x87\xD9\x85", "\xD9\x87\xD9\x89", - "\xD9\x87\xD9\x8A", "\xD9\x8A\xD8\xAC", - "\xD9\x8A\xD8\xAD", "\xD9\x8A\xD8\xAE", - "\xD9\x8A\xD9\x85", "\xD9\x8A\xD9\x89", - "\xD9\x8A\xD9\x8A", "\xD8\xB0\xD9\xB0", - "\xD8\xB1\xD9\xB0", "\xD9\x89\xD9\xB0", - "\x20\xD9\x8C\xD9\x91", "\x20\xD9\x8D\xD9\x91", - "\x20\xD9\x8E\xD9\x91", "\x20\xD9\x8F\xD9\x91", - "\x20\xD9\x90\xD9\x91", "\x20\xD9\x91\xD9\xB0", - "\xD9\x8A\xD9\x94\xD8\xB1", "\xD9\x8A\xD9\x94\xD8\xB2", - "\xD9\x8A\xD9\x94\xD9\x85", "\xD9\x8A\xD9\x94\xD9\x86", - "\xD9\x8A\xD9\x94\xD9\x89", "\xD9\x8A\xD9\x94\xD9\x8A", - "\xD8\xA8\xD8\xB1", "\xD8\xA8\xD8\xB2", - "\xD8\xA8\xD9\x85", "\xD8\xA8\xD9\x86", - "\xD8\xA8\xD9\x89", "\xD8\xA8\xD9\x8A", - "\xD8\xAA\xD8\xB1", "\xD8\xAA\xD8\xB2", - "\xD8\xAA\xD9\x85", "\xD8\xAA\xD9\x86", - "\xD8\xAA\xD9\x89", "\xD8\xAA\xD9\x8A", - "\xD8\xAB\xD8\xB1", "\xD8\xAB\xD8\xB2", - "\xD8\xAB\xD9\x85", "\xD8\xAB\xD9\x86", - "\xD8\xAB\xD9\x89", "\xD8\xAB\xD9\x8A", - "\xD9\x81\xD9\x89", "\xD9\x81\xD9\x8A", - "\xD9\x82\xD9\x89", "\xD9\x82\xD9\x8A", - "\xD9\x83\xD8\xA7", "\xD9\x83\xD9\x84", - "\xD9\x83\xD9\x85", "\xD9\x83\xD9\x89", - "\xD9\x83\xD9\x8A", "\xD9\x84\xD9\x85", - "\xD9\x84\xD9\x89", "\xD9\x84\xD9\x8A", - "\xD9\x85\xD8\xA7", "\xD9\x85\xD9\x85", - "\xD9\x86\xD8\xB1", "\xD9\x86\xD8\xB2", - "\xD9\x86\xD9\x85", "\xD9\x86\xD9\x86", - "\xD9\x86\xD9\x89", "\xD9\x86\xD9\x8A", - "\xD9\x89\xD9\xB0", "\xD9\x8A\xD8\xB1", - "\xD9\x8A\xD8\xB2", "\xD9\x8A\xD9\x85", - "\xD9\x8A\xD9\x86", "\xD9\x8A\xD9\x89", - "\xD9\x8A\xD9\x8A", "\xD9\x8A\xD9\x94\xD8\xAC", - "\xD9\x8A\xD9\x94\xD8\xAD", "\xD9\x8A\xD9\x94\xD8\xAE", - "\xD9\x8A\xD9\x94\xD9\x85", "\xD9\x8A\xD9\x94\xD9\x87", - "\xD8\xA8\xD8\xAC", "\xD8\xA8\xD8\xAD", - "\xD8\xA8\xD8\xAE", "\xD8\xA8\xD9\x85", - "\xD8\xA8\xD9\x87", "\xD8\xAA\xD8\xAC", - "\xD8\xAA\xD8\xAD", "\xD8\xAA\xD8\xAE", - "\xD8\xAA\xD9\x85", "\xD8\xAA\xD9\x87", - "\xD8\xAB\xD9\x85", "\xD8\xAC\xD8\xAD", - "\xD8\xAC\xD9\x85", "\xD8\xAD\xD8\xAC", - "\xD8\xAD\xD9\x85", "\xD8\xAE\xD8\xAC", - "\xD8\xAE\xD9\x85", "\xD8\xB3\xD8\xAC", - "\xD8\xB3\xD8\xAD", "\xD8\xB3\xD8\xAE", - "\xD8\xB3\xD9\x85", "\xD8\xB5\xD8\xAD", - "\xD8\xB5\xD8\xAE", "\xD8\xB5\xD9\x85", - "\xD8\xB6\xD8\xAC", "\xD8\xB6\xD8\xAD", - "\xD8\xB6\xD8\xAE", "\xD8\xB6\xD9\x85", - "\xD8\xB7\xD8\xAD", "\xD8\xB8\xD9\x85", - "\xD8\xB9\xD8\xAC", "\xD8\xB9\xD9\x85", - "\xD8\xBA\xD8\xAC", "\xD8\xBA\xD9\x85", - "\xD9\x81\xD8\xAC", "\xD9\x81\xD8\xAD", - "\xD9\x81\xD8\xAE", "\xD9\x81\xD9\x85", - "\xD9\x82\xD8\xAD", "\xD9\x82\xD9\x85", - "\xD9\x83\xD8\xAC", "\xD9\x83\xD8\xAD", - "\xD9\x83\xD8\xAE", "\xD9\x83\xD9\x84", - "\xD9\x83\xD9\x85", "\xD9\x84\xD8\xAC", - "\xD9\x84\xD8\xAD", "\xD9\x84\xD8\xAE", - "\xD9\x84\xD9\x85", "\xD9\x84\xD9\x87", - "\xD9\x85\xD8\xAC", "\xD9\x85\xD8\xAD", - "\xD9\x85\xD8\xAE", "\xD9\x85\xD9\x85", - "\xD9\x86\xD8\xAC", "\xD9\x86\xD8\xAD", - "\xD9\x86\xD8\xAE", "\xD9\x86\xD9\x85", - "\xD9\x86\xD9\x87", "\xD9\x87\xD8\xAC", - "\xD9\x87\xD9\x85", "\xD9\x87\xD9\xB0", - "\xD9\x8A\xD8\xAC", "\xD9\x8A\xD8\xAD", - "\xD9\x8A\xD8\xAE", "\xD9\x8A\xD9\x85", - "\xD9\x8A\xD9\x87", "\xD9\x8A\xD9\x94\xD9\x85", - "\xD9\x8A\xD9\x94\xD9\x87", "\xD8\xA8\xD9\x85", - "\xD8\xA8\xD9\x87", "\xD8\xAA\xD9\x85", - "\xD8\xAA\xD9\x87", "\xD8\xAB\xD9\x85", - "\xD8\xAB\xD9\x87", "\xD8\xB3\xD9\x85", - "\xD8\xB3\xD9\x87", "\xD8\xB4\xD9\x85", - "\xD8\xB4\xD9\x87", "\xD9\x83\xD9\x84", - "\xD9\x83\xD9\x85", "\xD9\x84\xD9\x85", - "\xD9\x86\xD9\x85", "\xD9\x86\xD9\x87", - "\xD9\x8A\xD9\x85", "\xD9\x8A\xD9\x87", - "\xD9\x80\xD9\x8E\xD9\x91", "\xD9\x80\xD9\x8F\xD9\x91", - "\xD9\x80\xD9\x90\xD9\x91", "\xD8\xB7\xD9\x89", - "\xD8\xB7\xD9\x8A", "\xD8\xB9\xD9\x89", - "\xD8\xB9\xD9\x8A", "\xD8\xBA\xD9\x89", - "\xD8\xBA\xD9\x8A", "\xD8\xB3\xD9\x89", - "\xD8\xB3\xD9\x8A", "\xD8\xB4\xD9\x89", - "\xD8\xB4\xD9\x8A", "\xD8\xAD\xD9\x89", -}; - -static const char *const decompCompatPage253[0x100] = { - "\xD8\xAD\xD9\x8A", "\xD8\xAC\xD9\x89", - "\xD8\xAC\xD9\x8A", "\xD8\xAE\xD9\x89", - "\xD8\xAE\xD9\x8A", "\xD8\xB5\xD9\x89", - "\xD8\xB5\xD9\x8A", "\xD8\xB6\xD9\x89", - "\xD8\xB6\xD9\x8A", "\xD8\xB4\xD8\xAC", - "\xD8\xB4\xD8\xAD", "\xD8\xB4\xD8\xAE", - "\xD8\xB4\xD9\x85", "\xD8\xB4\xD8\xB1", - "\xD8\xB3\xD8\xB1", "\xD8\xB5\xD8\xB1", - "\xD8\xB6\xD8\xB1", "\xD8\xB7\xD9\x89", - "\xD8\xB7\xD9\x8A", "\xD8\xB9\xD9\x89", - "\xD8\xB9\xD9\x8A", "\xD8\xBA\xD9\x89", - "\xD8\xBA\xD9\x8A", "\xD8\xB3\xD9\x89", - "\xD8\xB3\xD9\x8A", "\xD8\xB4\xD9\x89", - "\xD8\xB4\xD9\x8A", "\xD8\xAD\xD9\x89", - "\xD8\xAD\xD9\x8A", "\xD8\xAC\xD9\x89", - "\xD8\xAC\xD9\x8A", "\xD8\xAE\xD9\x89", - "\xD8\xAE\xD9\x8A", "\xD8\xB5\xD9\x89", - "\xD8\xB5\xD9\x8A", "\xD8\xB6\xD9\x89", - "\xD8\xB6\xD9\x8A", "\xD8\xB4\xD8\xAC", - "\xD8\xB4\xD8\xAD", "\xD8\xB4\xD8\xAE", - "\xD8\xB4\xD9\x85", "\xD8\xB4\xD8\xB1", - "\xD8\xB3\xD8\xB1", "\xD8\xB5\xD8\xB1", - "\xD8\xB6\xD8\xB1", "\xD8\xB4\xD8\xAC", - "\xD8\xB4\xD8\xAD", "\xD8\xB4\xD8\xAE", - "\xD8\xB4\xD9\x85", "\xD8\xB3\xD9\x87", - "\xD8\xB4\xD9\x87", "\xD8\xB7\xD9\x85", - "\xD8\xB3\xD8\xAC", "\xD8\xB3\xD8\xAD", - "\xD8\xB3\xD8\xAE", "\xD8\xB4\xD8\xAC", - "\xD8\xB4\xD8\xAD", "\xD8\xB4\xD8\xAE", - "\xD8\xB7\xD9\x85", "\xD8\xB8\xD9\x85", - "\xD8\xA7\xD9\x8B", "\xD8\xA7\xD9\x8B", - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\xD8\xAA\xD8\xAC\xD9\x85", "\xD8\xAA\xD8\xAD\xD8\xAC", - "\xD8\xAA\xD8\xAD\xD8\xAC", "\xD8\xAA\xD8\xAD\xD9\x85", - "\xD8\xAA\xD8\xAE\xD9\x85", "\xD8\xAA\xD9\x85\xD8\xAC", - "\xD8\xAA\xD9\x85\xD8\xAD", "\xD8\xAA\xD9\x85\xD8\xAE", - "\xD8\xAC\xD9\x85\xD8\xAD", "\xD8\xAC\xD9\x85\xD8\xAD", - "\xD8\xAD\xD9\x85\xD9\x8A", "\xD8\xAD\xD9\x85\xD9\x89", - "\xD8\xB3\xD8\xAD\xD8\xAC", "\xD8\xB3\xD8\xAC\xD8\xAD", - "\xD8\xB3\xD8\xAC\xD9\x89", "\xD8\xB3\xD9\x85\xD8\xAD", - "\xD8\xB3\xD9\x85\xD8\xAD", "\xD8\xB3\xD9\x85\xD8\xAC", - "\xD8\xB3\xD9\x85\xD9\x85", "\xD8\xB3\xD9\x85\xD9\x85", - "\xD8\xB5\xD8\xAD\xD8\xAD", "\xD8\xB5\xD8\xAD\xD8\xAD", - "\xD8\xB5\xD9\x85\xD9\x85", "\xD8\xB4\xD8\xAD\xD9\x85", - "\xD8\xB4\xD8\xAD\xD9\x85", "\xD8\xB4\xD8\xAC\xD9\x8A", - "\xD8\xB4\xD9\x85\xD8\xAE", "\xD8\xB4\xD9\x85\xD8\xAE", - "\xD8\xB4\xD9\x85\xD9\x85", "\xD8\xB4\xD9\x85\xD9\x85", - "\xD8\xB6\xD8\xAD\xD9\x89", "\xD8\xB6\xD8\xAE\xD9\x85", - "\xD8\xB6\xD8\xAE\xD9\x85", "\xD8\xB7\xD9\x85\xD8\xAD", - "\xD8\xB7\xD9\x85\xD8\xAD", "\xD8\xB7\xD9\x85\xD9\x85", - "\xD8\xB7\xD9\x85\xD9\x8A", "\xD8\xB9\xD8\xAC\xD9\x85", - "\xD8\xB9\xD9\x85\xD9\x85", "\xD8\xB9\xD9\x85\xD9\x85", - "\xD8\xB9\xD9\x85\xD9\x89", "\xD8\xBA\xD9\x85\xD9\x85", - "\xD8\xBA\xD9\x85\xD9\x8A", "\xD8\xBA\xD9\x85\xD9\x89", - "\xD9\x81\xD8\xAE\xD9\x85", "\xD9\x81\xD8\xAE\xD9\x85", - "\xD9\x82\xD9\x85\xD8\xAD", "\xD9\x82\xD9\x85\xD9\x85", - "\xD9\x84\xD8\xAD\xD9\x85", "\xD9\x84\xD8\xAD\xD9\x8A", - "\xD9\x84\xD8\xAD\xD9\x89", "\xD9\x84\xD8\xAC\xD8\xAC", - "\xD9\x84\xD8\xAC\xD8\xAC", "\xD9\x84\xD8\xAE\xD9\x85", - "\xD9\x84\xD8\xAE\xD9\x85", "\xD9\x84\xD9\x85\xD8\xAD", - "\xD9\x84\xD9\x85\xD8\xAD", "\xD9\x85\xD8\xAD\xD8\xAC", - "\xD9\x85\xD8\xAD\xD9\x85", "\xD9\x85\xD8\xAD\xD9\x8A", - "\xD9\x85\xD8\xAC\xD8\xAD", "\xD9\x85\xD8\xAC\xD9\x85", - "\xD9\x85\xD8\xAE\xD8\xAC", "\xD9\x85\xD8\xAE\xD9\x85", - NULL, NULL, - "\xD9\x85\xD8\xAC\xD8\xAE", "\xD9\x87\xD9\x85\xD8\xAC", - "\xD9\x87\xD9\x85\xD9\x85", "\xD9\x86\xD8\xAD\xD9\x85", - "\xD9\x86\xD8\xAD\xD9\x89", "\xD9\x86\xD8\xAC\xD9\x85", - "\xD9\x86\xD8\xAC\xD9\x85", "\xD9\x86\xD8\xAC\xD9\x89", - "\xD9\x86\xD9\x85\xD9\x8A", "\xD9\x86\xD9\x85\xD9\x89", - "\xD9\x8A\xD9\x85\xD9\x85", "\xD9\x8A\xD9\x85\xD9\x85", - "\xD8\xA8\xD8\xAE\xD9\x8A", "\xD8\xAA\xD8\xAC\xD9\x8A", - "\xD8\xAA\xD8\xAC\xD9\x89", "\xD8\xAA\xD8\xAE\xD9\x8A", - "\xD8\xAA\xD8\xAE\xD9\x89", "\xD8\xAA\xD9\x85\xD9\x8A", - "\xD8\xAA\xD9\x85\xD9\x89", "\xD8\xAC\xD9\x85\xD9\x8A", - "\xD8\xAC\xD8\xAD\xD9\x89", "\xD8\xAC\xD9\x85\xD9\x89", - "\xD8\xB3\xD8\xAE\xD9\x89", "\xD8\xB5\xD8\xAD\xD9\x8A", - "\xD8\xB4\xD8\xAD\xD9\x8A", "\xD8\xB6\xD8\xAD\xD9\x8A", - "\xD9\x84\xD8\xAC\xD9\x8A", "\xD9\x84\xD9\x85\xD9\x8A", - "\xD9\x8A\xD8\xAD\xD9\x8A", "\xD9\x8A\xD8\xAC\xD9\x8A", - "\xD9\x8A\xD9\x85\xD9\x8A", "\xD9\x85\xD9\x85\xD9\x8A", - "\xD9\x82\xD9\x85\xD9\x8A", "\xD9\x86\xD8\xAD\xD9\x8A", - "\xD9\x82\xD9\x85\xD8\xAD", "\xD9\x84\xD8\xAD\xD9\x85", - "\xD8\xB9\xD9\x85\xD9\x8A", "\xD9\x83\xD9\x85\xD9\x8A", - "\xD9\x86\xD8\xAC\xD8\xAD", "\xD9\x85\xD8\xAE\xD9\x8A", - "\xD9\x84\xD8\xAC\xD9\x85", "\xD9\x83\xD9\x85\xD9\x85", - "\xD9\x84\xD8\xAC\xD9\x85", "\xD9\x86\xD8\xAC\xD8\xAD", - "\xD8\xAC\xD8\xAD\xD9\x8A", "\xD8\xAD\xD8\xAC\xD9\x8A", - "\xD9\x85\xD8\xAC\xD9\x8A", "\xD9\x81\xD9\x85\xD9\x8A", - "\xD8\xA8\xD8\xAD\xD9\x8A", "\xD9\x83\xD9\x85\xD9\x85", - "\xD8\xB9\xD8\xAC\xD9\x85", "\xD8\xB5\xD9\x85\xD9\x85", - "\xD8\xB3\xD8\xAE\xD9\x8A", "\xD9\x86\xD8\xAC\xD9\x8A", - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\xD8\xB5\xD9\x84\xDB\x92", "\xD9\x82\xD9\x84\xDB\x92", - "\xD8\xA7\xD9\x84\xD9\x84\xD9\x87", "\xD8\xA7\xD9\x83\xD8\xA8\xD8\xB1", - "\xD9\x85\xD8\xAD\xD9\x85\xD8\xAF", "\xD8\xB5\xD9\x84\xD8\xB9\xD9\x85", - "\xD8\xB1\xD8\xB3\xD9\x88\xD9\x84", "\xD8\xB9\xD9\x84\xD9\x8A\xD9\x87", - "\xD9\x88\xD8\xB3\xD9\x84\xD9\x85", "\xD8\xB5\xD9\x84\xD9\x89", - "\xD8\xB5\xD9\x84\xD9\x89\x20\xD8\xA7\xD9\x84\xD9\x84\xD9\x87\x20\xD8\xB9\xD9\x84\xD9\x8A\xD9\x87\x20\xD9\x88\xD8\xB3\xD9\x84\xD9\x85", "\xD8\xAC\xD9\x84\x20\xD8\xAC\xD9\x84\xD8\xA7\xD9\x84\xD9\x87", - "\xD8\xB1\xDB\x8C\xD8\xA7\xD9\x84", NULL, - NULL, NULL, -}; - -static const char *const decompCompatPage254[0x100] = { - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\x2C", "\xE3\x80\x81", - "\xE3\x80\x82", "\x3A", - "\x3B", "\x21", - "\x3F", "\xE3\x80\x96", - "\xE3\x80\x97", "\x2E\x2E\x2E", - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\x2E\x2E", "\xE2\x80\x94", - "\xE2\x80\x93", "\x5F", - "\x5F", "\x28", - "\x29", "\x7B", - "\x7D", "\xE3\x80\x94", - "\xE3\x80\x95", "\xE3\x80\x90", - "\xE3\x80\x91", "\xE3\x80\x8A", - "\xE3\x80\x8B", "\xE3\x80\x88", - "\xE3\x80\x89", "\xE3\x80\x8C", - "\xE3\x80\x8D", "\xE3\x80\x8E", - "\xE3\x80\x8F", NULL, - NULL, "\x5B", - "\x5D", "\x20\xCC\x85", - "\x20\xCC\x85", "\x20\xCC\x85", - "\x20\xCC\x85", "\x5F", - "\x5F", "\x5F", - "\x2C", "\xE3\x80\x81", - "\x2E", NULL, - "\x3B", "\x3A", - "\x3F", "\x21", - "\xE2\x80\x94", "\x28", - "\x29", "\x7B", - "\x7D", "\xE3\x80\x94", - "\xE3\x80\x95", "\x23", - "\x26", "\x2A", - "\x2B", "\x2D", - "\x3C", "\x3E", - "\x3D", NULL, - "\x5C", "\x24", - "\x25", "\x40", - NULL, NULL, - NULL, NULL, - "\x20\xD9\x8B", "\xD9\x80\xD9\x8B", - "\x20\xD9\x8C", NULL, - "\x20\xD9\x8D", NULL, - "\x20\xD9\x8E", "\xD9\x80\xD9\x8E", - "\x20\xD9\x8F", "\xD9\x80\xD9\x8F", - "\x20\xD9\x90", "\xD9\x80\xD9\x90", - "\x20\xD9\x91", "\xD9\x80\xD9\x91", - "\x20\xD9\x92", "\xD9\x80\xD9\x92", - "\xD8\xA1", "\xD8\xA7\xD9\x93", - "\xD8\xA7\xD9\x93", "\xD8\xA7\xD9\x94", - "\xD8\xA7\xD9\x94", "\xD9\x88\xD9\x94", - "\xD9\x88\xD9\x94", "\xD8\xA7\xD9\x95", - "\xD8\xA7\xD9\x95", "\xD9\x8A\xD9\x94", - "\xD9\x8A\xD9\x94", "\xD9\x8A\xD9\x94", - "\xD9\x8A\xD9\x94", "\xD8\xA7", - "\xD8\xA7", "\xD8\xA8", - "\xD8\xA8", "\xD8\xA8", - "\xD8\xA8", "\xD8\xA9", - "\xD8\xA9", "\xD8\xAA", - "\xD8\xAA", "\xD8\xAA", - "\xD8\xAA", "\xD8\xAB", - "\xD8\xAB", "\xD8\xAB", - "\xD8\xAB", "\xD8\xAC", - "\xD8\xAC", "\xD8\xAC", - "\xD8\xAC", "\xD8\xAD", - "\xD8\xAD", "\xD8\xAD", - "\xD8\xAD", "\xD8\xAE", - "\xD8\xAE", "\xD8\xAE", - "\xD8\xAE", "\xD8\xAF", - "\xD8\xAF", "\xD8\xB0", - "\xD8\xB0", "\xD8\xB1", - "\xD8\xB1", "\xD8\xB2", - "\xD8\xB2", "\xD8\xB3", - "\xD8\xB3", "\xD8\xB3", - "\xD8\xB3", "\xD8\xB4", - "\xD8\xB4", "\xD8\xB4", - "\xD8\xB4", "\xD8\xB5", - "\xD8\xB5", "\xD8\xB5", - "\xD8\xB5", "\xD8\xB6", - "\xD8\xB6", "\xD8\xB6", - "\xD8\xB6", "\xD8\xB7", - "\xD8\xB7", "\xD8\xB7", - "\xD8\xB7", "\xD8\xB8", - "\xD8\xB8", "\xD8\xB8", - "\xD8\xB8", "\xD8\xB9", - "\xD8\xB9", "\xD8\xB9", - "\xD8\xB9", "\xD8\xBA", - "\xD8\xBA", "\xD8\xBA", - "\xD8\xBA", "\xD9\x81", - "\xD9\x81", "\xD9\x81", - "\xD9\x81", "\xD9\x82", - "\xD9\x82", "\xD9\x82", - "\xD9\x82", "\xD9\x83", - "\xD9\x83", "\xD9\x83", - "\xD9\x83", "\xD9\x84", - "\xD9\x84", "\xD9\x84", - "\xD9\x84", "\xD9\x85", - "\xD9\x85", "\xD9\x85", - "\xD9\x85", "\xD9\x86", - "\xD9\x86", "\xD9\x86", - "\xD9\x86", "\xD9\x87", - "\xD9\x87", "\xD9\x87", - "\xD9\x87", "\xD9\x88", - "\xD9\x88", "\xD9\x89", - "\xD9\x89", "\xD9\x8A", - "\xD9\x8A", "\xD9\x8A", - "\xD9\x8A", "\xD9\x84\xD8\xA7\xD9\x93", - "\xD9\x84\xD8\xA7\xD9\x93", "\xD9\x84\xD8\xA7\xD9\x94", - "\xD9\x84\xD8\xA7\xD9\x94", "\xD9\x84\xD8\xA7\xD9\x95", - "\xD9\x84\xD8\xA7\xD9\x95", "\xD9\x84\xD8\xA7", - "\xD9\x84\xD8\xA7", NULL, - NULL, NULL, -}; - -static const char *const decompCompatPage255[0x100] = { - NULL, "\x21", - "\x22", "\x23", - "\x24", "\x25", - "\x26", "\x27", - "\x28", "\x29", - "\x2A", "\x2B", - "\x2C", "\x2D", - "\x2E", "\x2F", - "\x30", "\x31", - "\x32", "\x33", - "\x34", "\x35", - "\x36", "\x37", - "\x38", "\x39", - "\x3A", "\x3B", - "\x3C", "\x3D", - "\x3E", "\x3F", - "\x40", "\x41", - "\x42", "\x43", - "\x44", "\x45", - "\x46", "\x47", - "\x48", "\x49", - "\x4A", "\x4B", - "\x4C", "\x4D", - "\x4E", "\x4F", - "\x50", "\x51", - "\x52", "\x53", - "\x54", "\x55", - "\x56", "\x57", - "\x58", "\x59", - "\x5A", "\x5B", - "\x5C", "\x5D", - "\x5E", "\x5F", - "\x60", "\x61", - "\x62", "\x63", - "\x64", "\x65", - "\x66", "\x67", - "\x68", "\x69", - "\x6A", "\x6B", - "\x6C", "\x6D", - "\x6E", "\x6F", - "\x70", "\x71", - "\x72", "\x73", - "\x74", "\x75", - "\x76", "\x77", - "\x78", "\x79", - "\x7A", "\x7B", - "\x7C", "\x7D", - "\x7E", "\xE2\xA6\x85", - "\xE2\xA6\x86", "\xE3\x80\x82", - "\xE3\x80\x8C", "\xE3\x80\x8D", - "\xE3\x80\x81", "\xE3\x83\xBB", - "\xE3\x83\xB2", "\xE3\x82\xA1", - "\xE3\x82\xA3", "\xE3\x82\xA5", - "\xE3\x82\xA7", "\xE3\x82\xA9", - "\xE3\x83\xA3", "\xE3\x83\xA5", - "\xE3\x83\xA7", "\xE3\x83\x83", - "\xE3\x83\xBC", "\xE3\x82\xA2", - "\xE3\x82\xA4", "\xE3\x82\xA6", - "\xE3\x82\xA8", "\xE3\x82\xAA", - "\xE3\x82\xAB", "\xE3\x82\xAD", - "\xE3\x82\xAF", "\xE3\x82\xB1", - "\xE3\x82\xB3", "\xE3\x82\xB5", - "\xE3\x82\xB7", "\xE3\x82\xB9", - "\xE3\x82\xBB", "\xE3\x82\xBD", - "\xE3\x82\xBF", "\xE3\x83\x81", - "\xE3\x83\x84", "\xE3\x83\x86", - "\xE3\x83\x88", "\xE3\x83\x8A", - "\xE3\x83\x8B", "\xE3\x83\x8C", - "\xE3\x83\x8D", "\xE3\x83\x8E", - "\xE3\x83\x8F", "\xE3\x83\x92", - "\xE3\x83\x95", "\xE3\x83\x98", - "\xE3\x83\x9B", "\xE3\x83\x9E", - "\xE3\x83\x9F", "\xE3\x83\xA0", - "\xE3\x83\xA1", "\xE3\x83\xA2", - "\xE3\x83\xA4", "\xE3\x83\xA6", - "\xE3\x83\xA8", "\xE3\x83\xA9", - "\xE3\x83\xAA", "\xE3\x83\xAB", - "\xE3\x83\xAC", "\xE3\x83\xAD", - "\xE3\x83\xAF", "\xE3\x83\xB3", - "\xE3\x82\x99", "\xE3\x82\x9A", - "\xE1\x85\xA0", "\xE1\x84\x80", - "\xE1\x84\x81", "\xE1\x86\xAA", - "\xE1\x84\x82", "\xE1\x86\xAC", - "\xE1\x86\xAD", "\xE1\x84\x83", - "\xE1\x84\x84", "\xE1\x84\x85", - "\xE1\x86\xB0", "\xE1\x86\xB1", - "\xE1\x86\xB2", "\xE1\x86\xB3", - "\xE1\x86\xB4", "\xE1\x86\xB5", - "\xE1\x84\x9A", "\xE1\x84\x86", - "\xE1\x84\x87", "\xE1\x84\x88", - "\xE1\x84\xA1", "\xE1\x84\x89", - "\xE1\x84\x8A", "\xE1\x84\x8B", - "\xE1\x84\x8C", "\xE1\x84\x8D", - "\xE1\x84\x8E", "\xE1\x84\x8F", - "\xE1\x84\x90", "\xE1\x84\x91", - "\xE1\x84\x92", NULL, - NULL, NULL, - "\xE1\x85\xA1", "\xE1\x85\xA2", - "\xE1\x85\xA3", "\xE1\x85\xA4", - "\xE1\x85\xA5", "\xE1\x85\xA6", - NULL, NULL, - "\xE1\x85\xA7", "\xE1\x85\xA8", - "\xE1\x85\xA9", "\xE1\x85\xAA", - "\xE1\x85\xAB", "\xE1\x85\xAC", - NULL, NULL, - "\xE1\x85\xAD", "\xE1\x85\xAE", - "\xE1\x85\xAF", "\xE1\x85\xB0", - "\xE1\x85\xB1", "\xE1\x85\xB2", - NULL, NULL, - "\xE1\x85\xB3", "\xE1\x85\xB4", - "\xE1\x85\xB5", NULL, - NULL, NULL, - "\xC2\xA2", "\xC2\xA3", - "\xC2\xAC", "\x20\xCC\x84", - "\xC2\xA6", "\xC2\xA5", - "\xE2\x82\xA9", NULL, - "\xE2\x94\x82", "\xE2\x86\x90", - "\xE2\x86\x91", "\xE2\x86\x92", - "\xE2\x86\x93", "\xE2\x96\xA0", - "\xE2\x97\x8B", NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, -}; - -static const char *const decompCompatPage465[0x100] = { - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\xF0\x9D\x85\x97\xF0\x9D\x85\xA5", "\xF0\x9D\x85\x98\xF0\x9D\x85\xA5", - "\xF0\x9D\x85\x98\xF0\x9D\x85\xA5\xF0\x9D\x85\xAE", "\xF0\x9D\x85\x98\xF0\x9D\x85\xA5\xF0\x9D\x85\xAF", - "\xF0\x9D\x85\x98\xF0\x9D\x85\xA5\xF0\x9D\x85\xB0", "\xF0\x9D\x85\x98\xF0\x9D\x85\xA5\xF0\x9D\x85\xB1", - "\xF0\x9D\x85\x98\xF0\x9D\x85\xA5\xF0\x9D\x85\xB2", NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, "\xF0\x9D\x86\xB9\xF0\x9D\x85\xA5", - "\xF0\x9D\x86\xBA\xF0\x9D\x85\xA5", "\xF0\x9D\x86\xB9\xF0\x9D\x85\xA5\xF0\x9D\x85\xAE", - "\xF0\x9D\x86\xBA\xF0\x9D\x85\xA5\xF0\x9D\x85\xAE", "\xF0\x9D\x86\xB9\xF0\x9D\x85\xA5\xF0\x9D\x85\xAF", - "\xF0\x9D\x86\xBA\xF0\x9D\x85\xA5\xF0\x9D\x85\xAF", NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, -}; - -static const char *const decompCompatPage468[0x100] = { - "\x41", "\x42", - "\x43", "\x44", - "\x45", "\x46", - "\x47", "\x48", - "\x49", "\x4A", - "\x4B", "\x4C", - "\x4D", "\x4E", - "\x4F", "\x50", - "\x51", "\x52", - "\x53", "\x54", - "\x55", "\x56", - "\x57", "\x58", - "\x59", "\x5A", - "\x61", "\x62", - "\x63", "\x64", - "\x65", "\x66", - "\x67", "\x68", - "\x69", "\x6A", - "\x6B", "\x6C", - "\x6D", "\x6E", - "\x6F", "\x70", - "\x71", "\x72", - "\x73", "\x74", - "\x75", "\x76", - "\x77", "\x78", - "\x79", "\x7A", - "\x41", "\x42", - "\x43", "\x44", - "\x45", "\x46", - "\x47", "\x48", - "\x49", "\x4A", - "\x4B", "\x4C", - "\x4D", "\x4E", - "\x4F", "\x50", - "\x51", "\x52", - "\x53", "\x54", - "\x55", "\x56", - "\x57", "\x58", - "\x59", "\x5A", - "\x61", "\x62", - "\x63", "\x64", - "\x65", "\x66", - "\x67", NULL, - "\x69", "\x6A", - "\x6B", "\x6C", - "\x6D", "\x6E", - "\x6F", "\x70", - "\x71", "\x72", - "\x73", "\x74", - "\x75", "\x76", - "\x77", "\x78", - "\x79", "\x7A", - "\x41", "\x42", - "\x43", "\x44", - "\x45", "\x46", - "\x47", "\x48", - "\x49", "\x4A", - "\x4B", "\x4C", - "\x4D", "\x4E", - "\x4F", "\x50", - "\x51", "\x52", - "\x53", "\x54", - "\x55", "\x56", - "\x57", "\x58", - "\x59", "\x5A", - "\x61", "\x62", - "\x63", "\x64", - "\x65", "\x66", - "\x67", "\x68", - "\x69", "\x6A", - "\x6B", "\x6C", - "\x6D", "\x6E", - "\x6F", "\x70", - "\x71", "\x72", - "\x73", "\x74", - "\x75", "\x76", - "\x77", "\x78", - "\x79", "\x7A", - "\x41", NULL, - "\x43", "\x44", - NULL, NULL, - "\x47", NULL, - NULL, "\x4A", - "\x4B", NULL, - NULL, "\x4E", - "\x4F", "\x50", - "\x51", NULL, - "\x53", "\x54", - "\x55", "\x56", - "\x57", "\x58", - "\x59", "\x5A", - "\x61", "\x62", - "\x63", "\x64", - NULL, "\x66", - NULL, "\x68", - "\x69", "\x6A", - "\x6B", "\x6C", - "\x6D", "\x6E", - NULL, "\x70", - "\x71", "\x72", - "\x73", "\x74", - "\x75", "\x76", - "\x77", "\x78", - "\x79", "\x7A", - "\x41", "\x42", - "\x43", "\x44", - "\x45", "\x46", - "\x47", "\x48", - "\x49", "\x4A", - "\x4B", "\x4C", - "\x4D", "\x4E", - "\x4F", "\x50", - "\x51", "\x52", - "\x53", "\x54", - "\x55", "\x56", - "\x57", "\x58", - "\x59", "\x5A", - "\x61", "\x62", - "\x63", "\x64", - "\x65", "\x66", - "\x67", "\x68", - "\x69", "\x6A", - "\x6B", "\x6C", - "\x6D", "\x6E", - "\x6F", "\x70", - "\x71", "\x72", - "\x73", "\x74", - "\x75", "\x76", -}; - -static const char *const decompCompatPage469[0x100] = { - "\x77", "\x78", - "\x79", "\x7A", - "\x41", "\x42", - NULL, "\x44", - "\x45", "\x46", - "\x47", NULL, - NULL, "\x4A", - "\x4B", "\x4C", - "\x4D", "\x4E", - "\x4F", "\x50", - "\x51", NULL, - "\x53", "\x54", - "\x55", "\x56", - "\x57", "\x58", - "\x59", NULL, - "\x61", "\x62", - "\x63", "\x64", - "\x65", "\x66", - "\x67", "\x68", - "\x69", "\x6A", - "\x6B", "\x6C", - "\x6D", "\x6E", - "\x6F", "\x70", - "\x71", "\x72", - "\x73", "\x74", - "\x75", "\x76", - "\x77", "\x78", - "\x79", "\x7A", - "\x41", "\x42", - NULL, "\x44", - "\x45", "\x46", - "\x47", NULL, - "\x49", "\x4A", - "\x4B", "\x4C", - "\x4D", NULL, - "\x4F", NULL, - NULL, NULL, - "\x53", "\x54", - "\x55", "\x56", - "\x57", "\x58", - "\x59", NULL, - "\x61", "\x62", - "\x63", "\x64", - "\x65", "\x66", - "\x67", "\x68", - "\x69", "\x6A", - "\x6B", "\x6C", - "\x6D", "\x6E", - "\x6F", "\x70", - "\x71", "\x72", - "\x73", "\x74", - "\x75", "\x76", - "\x77", "\x78", - "\x79", "\x7A", - "\x41", "\x42", - "\x43", "\x44", - "\x45", "\x46", - "\x47", "\x48", - "\x49", "\x4A", - "\x4B", "\x4C", - "\x4D", "\x4E", - "\x4F", "\x50", - "\x51", "\x52", - "\x53", "\x54", - "\x55", "\x56", - "\x57", "\x58", - "\x59", "\x5A", - "\x61", "\x62", - "\x63", "\x64", - "\x65", "\x66", - "\x67", "\x68", - "\x69", "\x6A", - "\x6B", "\x6C", - "\x6D", "\x6E", - "\x6F", "\x70", - "\x71", "\x72", - "\x73", "\x74", - "\x75", "\x76", - "\x77", "\x78", - "\x79", "\x7A", - "\x41", "\x42", - "\x43", "\x44", - "\x45", "\x46", - "\x47", "\x48", - "\x49", "\x4A", - "\x4B", "\x4C", - "\x4D", "\x4E", - "\x4F", "\x50", - "\x51", "\x52", - "\x53", "\x54", - "\x55", "\x56", - "\x57", "\x58", - "\x59", "\x5A", - "\x61", "\x62", - "\x63", "\x64", - "\x65", "\x66", - "\x67", "\x68", - "\x69", "\x6A", - "\x6B", "\x6C", - "\x6D", "\x6E", - "\x6F", "\x70", - "\x71", "\x72", - "\x73", "\x74", - "\x75", "\x76", - "\x77", "\x78", - "\x79", "\x7A", - "\x41", "\x42", - "\x43", "\x44", - "\x45", "\x46", - "\x47", "\x48", - "\x49", "\x4A", - "\x4B", "\x4C", - "\x4D", "\x4E", - "\x4F", "\x50", - "\x51", "\x52", - "\x53", "\x54", - "\x55", "\x56", - "\x57", "\x58", - "\x59", "\x5A", - "\x61", "\x62", - "\x63", "\x64", - "\x65", "\x66", - "\x67", "\x68", - "\x69", "\x6A", - "\x6B", "\x6C", - "\x6D", "\x6E", - "\x6F", "\x70", - "\x71", "\x72", -}; - -static const char *const decompCompatPage470[0x100] = { - "\x73", "\x74", - "\x75", "\x76", - "\x77", "\x78", - "\x79", "\x7A", - "\x41", "\x42", - "\x43", "\x44", - "\x45", "\x46", - "\x47", "\x48", - "\x49", "\x4A", - "\x4B", "\x4C", - "\x4D", "\x4E", - "\x4F", "\x50", - "\x51", "\x52", - "\x53", "\x54", - "\x55", "\x56", - "\x57", "\x58", - "\x59", "\x5A", - "\x61", "\x62", - "\x63", "\x64", - "\x65", "\x66", - "\x67", "\x68", - "\x69", "\x6A", - "\x6B", "\x6C", - "\x6D", "\x6E", - "\x6F", "\x70", - "\x71", "\x72", - "\x73", "\x74", - "\x75", "\x76", - "\x77", "\x78", - "\x79", "\x7A", - "\x41", "\x42", - "\x43", "\x44", - "\x45", "\x46", - "\x47", "\x48", - "\x49", "\x4A", - "\x4B", "\x4C", - "\x4D", "\x4E", - "\x4F", "\x50", - "\x51", "\x52", - "\x53", "\x54", - "\x55", "\x56", - "\x57", "\x58", - "\x59", "\x5A", - "\x61", "\x62", - "\x63", "\x64", - "\x65", "\x66", - "\x67", "\x68", - "\x69", "\x6A", - "\x6B", "\x6C", - "\x6D", "\x6E", - "\x6F", "\x70", - "\x71", "\x72", - "\x73", "\x74", - "\x75", "\x76", - "\x77", "\x78", - "\x79", "\x7A", - "\x41", "\x42", - "\x43", "\x44", - "\x45", "\x46", - "\x47", "\x48", - "\x49", "\x4A", - "\x4B", "\x4C", - "\x4D", "\x4E", - "\x4F", "\x50", - "\x51", "\x52", - "\x53", "\x54", - "\x55", "\x56", - "\x57", "\x58", - "\x59", "\x5A", - "\x61", "\x62", - "\x63", "\x64", - "\x65", "\x66", - "\x67", "\x68", - "\x69", "\x6A", - "\x6B", "\x6C", - "\x6D", "\x6E", - "\x6F", "\x70", - "\x71", "\x72", - "\x73", "\x74", - "\x75", "\x76", - "\x77", "\x78", - "\x79", "\x7A", - "\xC4\xB1", "\xC8\xB7", - NULL, NULL, - "\xCE\x91", "\xCE\x92", - "\xCE\x93", "\xCE\x94", - "\xCE\x95", "\xCE\x96", - "\xCE\x97", "\xCE\x98", - "\xCE\x99", "\xCE\x9A", - "\xCE\x9B", "\xCE\x9C", - "\xCE\x9D", "\xCE\x9E", - "\xCE\x9F", "\xCE\xA0", - "\xCE\xA1", "\xCE\x98", - "\xCE\xA3", "\xCE\xA4", - "\xCE\xA5", "\xCE\xA6", - "\xCE\xA7", "\xCE\xA8", - "\xCE\xA9", "\xE2\x88\x87", - "\xCE\xB1", "\xCE\xB2", - "\xCE\xB3", "\xCE\xB4", - "\xCE\xB5", "\xCE\xB6", - "\xCE\xB7", "\xCE\xB8", - "\xCE\xB9", "\xCE\xBA", - "\xCE\xBB", "\xCE\xBC", - "\xCE\xBD", "\xCE\xBE", - "\xCE\xBF", "\xCF\x80", - "\xCF\x81", "\xCF\x82", - "\xCF\x83", "\xCF\x84", - "\xCF\x85", "\xCF\x86", - "\xCF\x87", "\xCF\x88", - "\xCF\x89", "\xE2\x88\x82", - "\xCE\xB5", "\xCE\xB8", - "\xCE\xBA", "\xCF\x86", - "\xCF\x81", "\xCF\x80", - "\xCE\x91", "\xCE\x92", - "\xCE\x93", "\xCE\x94", - "\xCE\x95", "\xCE\x96", - "\xCE\x97", "\xCE\x98", - "\xCE\x99", "\xCE\x9A", - "\xCE\x9B", "\xCE\x9C", - "\xCE\x9D", "\xCE\x9E", - "\xCE\x9F", "\xCE\xA0", - "\xCE\xA1", "\xCE\x98", - "\xCE\xA3", "\xCE\xA4", - "\xCE\xA5", "\xCE\xA6", - "\xCE\xA7", "\xCE\xA8", - "\xCE\xA9", "\xE2\x88\x87", - "\xCE\xB1", "\xCE\xB2", - "\xCE\xB3", "\xCE\xB4", -}; - -static const char *const decompCompatPage471[0x100] = { - "\xCE\xB5", "\xCE\xB6", - "\xCE\xB7", "\xCE\xB8", - "\xCE\xB9", "\xCE\xBA", - "\xCE\xBB", "\xCE\xBC", - "\xCE\xBD", "\xCE\xBE", - "\xCE\xBF", "\xCF\x80", - "\xCF\x81", "\xCF\x82", - "\xCF\x83", "\xCF\x84", - "\xCF\x85", "\xCF\x86", - "\xCF\x87", "\xCF\x88", - "\xCF\x89", "\xE2\x88\x82", - "\xCE\xB5", "\xCE\xB8", - "\xCE\xBA", "\xCF\x86", - "\xCF\x81", "\xCF\x80", - "\xCE\x91", "\xCE\x92", - "\xCE\x93", "\xCE\x94", - "\xCE\x95", "\xCE\x96", - "\xCE\x97", "\xCE\x98", - "\xCE\x99", "\xCE\x9A", - "\xCE\x9B", "\xCE\x9C", - "\xCE\x9D", "\xCE\x9E", - "\xCE\x9F", "\xCE\xA0", - "\xCE\xA1", "\xCE\x98", - "\xCE\xA3", "\xCE\xA4", - "\xCE\xA5", "\xCE\xA6", - "\xCE\xA7", "\xCE\xA8", - "\xCE\xA9", "\xE2\x88\x87", - "\xCE\xB1", "\xCE\xB2", - "\xCE\xB3", "\xCE\xB4", - "\xCE\xB5", "\xCE\xB6", - "\xCE\xB7", "\xCE\xB8", - "\xCE\xB9", "\xCE\xBA", - "\xCE\xBB", "\xCE\xBC", - "\xCE\xBD", "\xCE\xBE", - "\xCE\xBF", "\xCF\x80", - "\xCF\x81", "\xCF\x82", - "\xCF\x83", "\xCF\x84", - "\xCF\x85", "\xCF\x86", - "\xCF\x87", "\xCF\x88", - "\xCF\x89", "\xE2\x88\x82", - "\xCE\xB5", "\xCE\xB8", - "\xCE\xBA", "\xCF\x86", - "\xCF\x81", "\xCF\x80", - "\xCE\x91", "\xCE\x92", - "\xCE\x93", "\xCE\x94", - "\xCE\x95", "\xCE\x96", - "\xCE\x97", "\xCE\x98", - "\xCE\x99", "\xCE\x9A", - "\xCE\x9B", "\xCE\x9C", - "\xCE\x9D", "\xCE\x9E", - "\xCE\x9F", "\xCE\xA0", - "\xCE\xA1", "\xCE\x98", - "\xCE\xA3", "\xCE\xA4", - "\xCE\xA5", "\xCE\xA6", - "\xCE\xA7", "\xCE\xA8", - "\xCE\xA9", "\xE2\x88\x87", - "\xCE\xB1", "\xCE\xB2", - "\xCE\xB3", "\xCE\xB4", - "\xCE\xB5", "\xCE\xB6", - "\xCE\xB7", "\xCE\xB8", - "\xCE\xB9", "\xCE\xBA", - "\xCE\xBB", "\xCE\xBC", - "\xCE\xBD", "\xCE\xBE", - "\xCE\xBF", "\xCF\x80", - "\xCF\x81", "\xCF\x82", - "\xCF\x83", "\xCF\x84", - "\xCF\x85", "\xCF\x86", - "\xCF\x87", "\xCF\x88", - "\xCF\x89", "\xE2\x88\x82", - "\xCE\xB5", "\xCE\xB8", - "\xCE\xBA", "\xCF\x86", - "\xCF\x81", "\xCF\x80", - "\xCE\x91", "\xCE\x92", - "\xCE\x93", "\xCE\x94", - "\xCE\x95", "\xCE\x96", - "\xCE\x97", "\xCE\x98", - "\xCE\x99", "\xCE\x9A", - "\xCE\x9B", "\xCE\x9C", - "\xCE\x9D", "\xCE\x9E", - "\xCE\x9F", "\xCE\xA0", - "\xCE\xA1", "\xCE\x98", - "\xCE\xA3", "\xCE\xA4", - "\xCE\xA5", "\xCE\xA6", - "\xCE\xA7", "\xCE\xA8", - "\xCE\xA9", "\xE2\x88\x87", - "\xCE\xB1", "\xCE\xB2", - "\xCE\xB3", "\xCE\xB4", - "\xCE\xB5", "\xCE\xB6", - "\xCE\xB7", "\xCE\xB8", - "\xCE\xB9", "\xCE\xBA", - "\xCE\xBB", "\xCE\xBC", - "\xCE\xBD", "\xCE\xBE", - "\xCE\xBF", "\xCF\x80", - "\xCF\x81", "\xCF\x82", - "\xCF\x83", "\xCF\x84", - "\xCF\x85", "\xCF\x86", - "\xCF\x87", "\xCF\x88", - "\xCF\x89", "\xE2\x88\x82", - "\xCE\xB5", "\xCE\xB8", - "\xCE\xBA", "\xCF\x86", - "\xCF\x81", "\xCF\x80", - "\xCF\x9C", "\xCF\x9D", - NULL, NULL, - "\x30", "\x31", - "\x32", "\x33", - "\x34", "\x35", - "\x36", "\x37", - "\x38", "\x39", - "\x30", "\x31", - "\x32", "\x33", - "\x34", "\x35", - "\x36", "\x37", - "\x38", "\x39", - "\x30", "\x31", - "\x32", "\x33", - "\x34", "\x35", - "\x36", "\x37", - "\x38", "\x39", - "\x30", "\x31", - "\x32", "\x33", - "\x34", "\x35", - "\x36", "\x37", - "\x38", "\x39", - "\x30", "\x31", - "\x32", "\x33", - "\x34", "\x35", - "\x36", "\x37", - "\x38", "\x39", -}; - -static const char *const decompCompatPage494[0x100] = { - "\xD8\xA7", "\xD8\xA8", - "\xD8\xAC", "\xD8\xAF", - NULL, "\xD9\x88", - "\xD8\xB2", "\xD8\xAD", - "\xD8\xB7", "\xD9\x8A", - "\xD9\x83", "\xD9\x84", - "\xD9\x85", "\xD9\x86", - "\xD8\xB3", "\xD8\xB9", - "\xD9\x81", "\xD8\xB5", - "\xD9\x82", "\xD8\xB1", - "\xD8\xB4", "\xD8\xAA", - "\xD8\xAB", "\xD8\xAE", - "\xD8\xB0", "\xD8\xB6", - "\xD8\xB8", "\xD8\xBA", - "\xD9\xAE", "\xDA\xBA", - "\xDA\xA1", "\xD9\xAF", - NULL, "\xD8\xA8", - "\xD8\xAC", NULL, - "\xD9\x87", NULL, - NULL, "\xD8\xAD", - NULL, "\xD9\x8A", - "\xD9\x83", "\xD9\x84", - "\xD9\x85", "\xD9\x86", - "\xD8\xB3", "\xD8\xB9", - "\xD9\x81", "\xD8\xB5", - "\xD9\x82", NULL, - "\xD8\xB4", "\xD8\xAA", - "\xD8\xAB", "\xD8\xAE", - NULL, "\xD8\xB6", - NULL, "\xD8\xBA", - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\xD8\xAC", NULL, - NULL, NULL, - NULL, "\xD8\xAD", - NULL, "\xD9\x8A", - NULL, "\xD9\x84", - NULL, "\xD9\x86", - "\xD8\xB3", "\xD8\xB9", - NULL, "\xD8\xB5", - "\xD9\x82", NULL, - "\xD8\xB4", NULL, - NULL, "\xD8\xAE", - NULL, "\xD8\xB6", - NULL, "\xD8\xBA", - NULL, "\xDA\xBA", - NULL, "\xD9\xAF", - NULL, "\xD8\xA8", - "\xD8\xAC", NULL, - "\xD9\x87", NULL, - NULL, "\xD8\xAD", - "\xD8\xB7", "\xD9\x8A", - "\xD9\x83", NULL, - "\xD9\x85", "\xD9\x86", - "\xD8\xB3", "\xD8\xB9", - "\xD9\x81", "\xD8\xB5", - "\xD9\x82", NULL, - "\xD8\xB4", "\xD8\xAA", - "\xD8\xAB", "\xD8\xAE", - NULL, "\xD8\xB6", - "\xD8\xB8", "\xD8\xBA", - "\xD9\xAE", NULL, - "\xDA\xA1", NULL, - "\xD8\xA7", "\xD8\xA8", - "\xD8\xAC", "\xD8\xAF", - "\xD9\x87", "\xD9\x88", - "\xD8\xB2", "\xD8\xAD", - "\xD8\xB7", "\xD9\x8A", - NULL, "\xD9\x84", - "\xD9\x85", "\xD9\x86", - "\xD8\xB3", "\xD8\xB9", - "\xD9\x81", "\xD8\xB5", - "\xD9\x82", "\xD8\xB1", - "\xD8\xB4", "\xD8\xAA", - "\xD8\xAB", "\xD8\xAE", - "\xD8\xB0", "\xD8\xB6", - "\xD8\xB8", "\xD8\xBA", - NULL, NULL, - NULL, NULL, - NULL, "\xD8\xA8", - "\xD8\xAC", "\xD8\xAF", - NULL, "\xD9\x88", - "\xD8\xB2", "\xD8\xAD", - "\xD8\xB7", "\xD9\x8A", - NULL, "\xD9\x84", - "\xD9\x85", "\xD9\x86", - "\xD8\xB3", "\xD8\xB9", - "\xD9\x81", "\xD8\xB5", - "\xD9\x82", "\xD8\xB1", - "\xD8\xB4", "\xD8\xAA", - "\xD8\xAB", "\xD8\xAE", - "\xD8\xB0", "\xD8\xB6", - "\xD8\xB8", "\xD8\xBA", - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, -}; - -static const char *const decompCompatPage497[0x100] = { - "\x30\x2E", "\x30\x2C", - "\x31\x2C", "\x32\x2C", - "\x33\x2C", "\x34\x2C", - "\x35\x2C", "\x36\x2C", - "\x37\x2C", "\x38\x2C", - "\x39\x2C", NULL, - NULL, NULL, - NULL, NULL, - "\x28\x41\x29", "\x28\x42\x29", - "\x28\x43\x29", "\x28\x44\x29", - "\x28\x45\x29", "\x28\x46\x29", - "\x28\x47\x29", "\x28\x48\x29", - "\x28\x49\x29", "\x28\x4A\x29", - "\x28\x4B\x29", "\x28\x4C\x29", - "\x28\x4D\x29", "\x28\x4E\x29", - "\x28\x4F\x29", "\x28\x50\x29", - "\x28\x51\x29", "\x28\x52\x29", - "\x28\x53\x29", "\x28\x54\x29", - "\x28\x55\x29", "\x28\x56\x29", - "\x28\x57\x29", "\x28\x58\x29", - "\x28\x59\x29", "\x28\x5A\x29", - "\xE3\x80\x94\x53\xE3\x80\x95", "\x43", - "\x52", "\x43\x44", - "\x57\x5A", NULL, - "\x41", "\x42", - "\x43", "\x44", - "\x45", "\x46", - "\x47", "\x48", - "\x49", "\x4A", - "\x4B", "\x4C", - "\x4D", "\x4E", - "\x4F", "\x50", - "\x51", "\x52", - "\x53", "\x54", - "\x55", "\x56", - "\x57", "\x58", - "\x59", "\x5A", - "\x48\x56", "\x4D\x56", - "\x53\x44", "\x53\x53", - "\x50\x50\x56", "\x57\x43", - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\x4D\x43", "\x4D\x44", - "\x4D\x52", NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\x44\x4A", NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, -}; - -static const char *const decompCompatPage498[0x100] = { - "\xE3\x81\xBB\xE3\x81\x8B", "\xE3\x82\xB3\xE3\x82\xB3", - "\xE3\x82\xB5", NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\xE6\x89\x8B", "\xE5\xAD\x97", - "\xE5\x8F\x8C", "\xE3\x83\x86\xE3\x82\x99", - "\xE4\xBA\x8C", "\xE5\xA4\x9A", - "\xE8\xA7\xA3", "\xE5\xA4\xA9", - "\xE4\xBA\xA4", "\xE6\x98\xA0", - "\xE7\x84\xA1", "\xE6\x96\x99", - "\xE5\x89\x8D", "\xE5\xBE\x8C", - "\xE5\x86\x8D", "\xE6\x96\xB0", - "\xE5\x88\x9D", "\xE7\xB5\x82", - "\xE7\x94\x9F", "\xE8\xB2\xA9", - "\xE5\xA3\xB0", "\xE5\x90\xB9", - "\xE6\xBC\x94", "\xE6\x8A\x95", - "\xE6\x8D\x95", "\xE4\xB8\x80", - "\xE4\xB8\x89", "\xE9\x81\x8A", - "\xE5\xB7\xA6", "\xE4\xB8\xAD", - "\xE5\x8F\xB3", "\xE6\x8C\x87", - "\xE8\xB5\xB0", "\xE6\x89\x93", - "\xE7\xA6\x81", "\xE7\xA9\xBA", - "\xE5\x90\x88", "\xE6\xBA\x80", - "\xE6\x9C\x89", "\xE6\x9C\x88", - "\xE7\x94\xB3", "\xE5\x89\xB2", - "\xE5\x96\xB6", "\xE9\x85\x8D", - NULL, NULL, - NULL, NULL, - "\xE3\x80\x94\xE6\x9C\xAC\xE3\x80\x95", "\xE3\x80\x94\xE4\xB8\x89\xE3\x80\x95", - "\xE3\x80\x94\xE4\xBA\x8C\xE3\x80\x95", "\xE3\x80\x94\xE5\xAE\x89\xE3\x80\x95", - "\xE3\x80\x94\xE7\x82\xB9\xE3\x80\x95", "\xE3\x80\x94\xE6\x89\x93\xE3\x80\x95", - "\xE3\x80\x94\xE7\x9B\x97\xE3\x80\x95", "\xE3\x80\x94\xE5\x8B\x9D\xE3\x80\x95", - "\xE3\x80\x94\xE6\x95\x97\xE3\x80\x95", NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\xE5\xBE\x97", "\xE5\x8F\xAF", - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, -}; - -static const char *const decompCompatPage507[0x100] = { - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - NULL, NULL, - "\x30", "\x31", - "\x32", "\x33", - "\x34", "\x35", - "\x36", "\x37", - "\x38", "\x39", - NULL, NULL, - NULL, NULL, - NULL, NULL, +static const OFUnichar caseFoldingPage251[0x100] = { + 0, 0, 0, 0, 0, 64262, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, }; const OFUnichar *const OFUnicodeUppercaseTable[0x1EA] = { uppercasePage0, uppercasePage1, uppercasePage2, uppercasePage3, uppercasePage4, uppercasePage5, emptyPage, emptyPage, @@ -12428,11 +2183,11 @@ emptyPage, emptyPage, emptyPage, emptyPage, emptyPage, emptyPage, emptyPage, emptyPage, emptyPage, emptyPage, emptyPage, emptyPage, emptyPage, emptyPage, emptyPage, uppercasePage255, emptyPage, emptyPage, emptyPage, emptyPage, - uppercasePage260, emptyPage, emptyPage, emptyPage, + uppercasePage260, uppercasePage261, emptyPage, emptyPage, emptyPage, emptyPage, emptyPage, emptyPage, uppercasePage268, emptyPage, emptyPage, emptyPage, emptyPage, emptyPage, emptyPage, emptyPage, emptyPage, emptyPage, emptyPage, emptyPage, uppercasePage280, emptyPage, emptyPage, emptyPage, @@ -12554,11 +2309,11 @@ emptyPage, emptyPage, emptyPage, emptyPage, emptyPage, emptyPage, emptyPage, emptyPage, emptyPage, emptyPage, emptyPage, emptyPage, emptyPage, emptyPage, emptyPage, lowercasePage255, emptyPage, emptyPage, emptyPage, emptyPage, - lowercasePage260, emptyPage, emptyPage, emptyPage, + lowercasePage260, lowercasePage261, emptyPage, emptyPage, emptyPage, emptyPage, emptyPage, emptyPage, lowercasePage268, emptyPage, emptyPage, emptyPage, emptyPage, emptyPage, emptyPage, emptyPage, emptyPage, emptyPage, emptyPage, emptyPage, lowercasePage280, emptyPage, emptyPage, emptyPage, @@ -12680,11 +2435,11 @@ emptyPage, emptyPage, emptyPage, emptyPage, emptyPage, emptyPage, emptyPage, emptyPage, emptyPage, emptyPage, emptyPage, emptyPage, emptyPage, emptyPage, emptyPage, uppercasePage255, emptyPage, emptyPage, emptyPage, emptyPage, - uppercasePage260, emptyPage, emptyPage, emptyPage, + uppercasePage260, uppercasePage261, emptyPage, emptyPage, emptyPage, emptyPage, emptyPage, emptyPage, uppercasePage268, emptyPage, emptyPage, emptyPage, emptyPage, emptyPage, emptyPage, emptyPage, emptyPage, emptyPage, emptyPage, emptyPage, uppercasePage280, emptyPage, emptyPage, emptyPage, @@ -12824,15 +2579,15 @@ emptyPage, emptyPage, emptyPage, emptyPage, emptyPage, emptyPage, emptyPage, emptyPage, emptyPage, emptyPage, emptyPage, emptyPage, emptyPage, emptyPage, emptyPage, - emptyPage, emptyPage, emptyPage, + emptyPage, emptyPage, caseFoldingPage251, emptyPage, emptyPage, emptyPage, lowercasePage255, emptyPage, emptyPage, emptyPage, emptyPage, lowercasePage260, - emptyPage, emptyPage, emptyPage, + lowercasePage261, emptyPage, emptyPage, emptyPage, emptyPage, emptyPage, emptyPage, lowercasePage268, emptyPage, emptyPage, emptyPage, emptyPage, emptyPage, emptyPage, emptyPage, emptyPage, emptyPage, emptyPage, @@ -12907,520 +2662,5 @@ emptyPage, emptyPage, emptyPage, emptyPage, emptyPage, emptyPage, lowercasePage489 }; -const char *const *OFUnicodeDecompositionTable[0x2FB] = { - decompositionPage0, decompositionPage1, decompositionPage2, - decompositionPage3, decompositionPage4, emptyDecompositionPage, - decompositionPage6, emptyDecompositionPage, emptyDecompositionPage, - decompositionPage9, decompositionPage10, decompositionPage11, - decompositionPage12, decompositionPage13, emptyDecompositionPage, - decompositionPage15, decompositionPage16, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - decompositionPage27, emptyDecompositionPage, emptyDecompositionPage, - decompositionPage30, decompositionPage31, decompositionPage32, - decompositionPage33, decompositionPage34, decompositionPage35, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - decompositionPage42, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - decompositionPage48, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - decompositionPage249, decompositionPage250, decompositionPage251, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, decompositionPage272, - decompositionPage273, emptyDecompositionPage, decompositionPage275, - decompositionPage276, decompositionPage277, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, decompositionPage281, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - decompositionPage465, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, decompositionPage760, decompositionPage761, - decompositionPage762 -}; - -const char *const *OFUnicodeDecompositionCompatTable[0x2FB] = { - decompCompatPage0, decompCompatPage1, decompCompatPage2, - decompCompatPage3, decompositionPage4, decompCompatPage5, - decompCompatPage6, emptyDecompositionPage, emptyDecompositionPage, - decompositionPage9, decompositionPage10, decompositionPage11, - decompCompatPage12, decompCompatPage13, decompCompatPage14, - decompCompatPage15, decompCompatPage16, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - decompositionPage27, emptyDecompositionPage, decompCompatPage29, - decompCompatPage30, decompCompatPage31, decompCompatPage32, - decompCompatPage33, decompCompatPage34, decompositionPage35, - decompCompatPage36, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - decompCompatPage42, emptyDecompositionPage, decompCompatPage44, - decompCompatPage45, decompCompatPage46, decompCompatPage47, - decompCompatPage48, decompCompatPage49, decompCompatPage50, - decompCompatPage51, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, decompCompatPage166, decompCompatPage167, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - decompCompatPage171, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - decompositionPage249, decompositionPage250, decompCompatPage251, - decompCompatPage252, decompCompatPage253, decompCompatPage254, - decompCompatPage255, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, decompositionPage272, - decompositionPage273, emptyDecompositionPage, decompositionPage275, - decompositionPage276, decompositionPage277, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, decompositionPage281, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - decompCompatPage465, emptyDecompositionPage, emptyDecompositionPage, - decompCompatPage468, decompCompatPage469, decompCompatPage470, - decompCompatPage471, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, decompCompatPage494, - emptyDecompositionPage, emptyDecompositionPage, decompCompatPage497, - decompCompatPage498, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - decompCompatPage507, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, emptyDecompositionPage, emptyDecompositionPage, - emptyDecompositionPage, decompositionPage760, decompositionPage761, - decompositionPage762 -}; Index: src/unistd_wrapper.h ================================================================== --- src/unistd_wrapper.h +++ src/unistd_wrapper.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in Index: src/versioninfo.rc ================================================================== --- src/versioninfo.rc +++ src/versioninfo.rc @@ -12,11 +12,11 @@ VALUE "ProductName", "ObjFW" VALUE "ProductVersion", PACKAGE_VERSION VALUE "FileVersion", OBJFW_LIB_VERSION VALUE "FileDescription", "Objective-C framework" VALUE "LegalCopyright", - "(c) 2008-2022 Jonathan Schleifer" + "(c) 2008-2024 Jonathan Schleifer" VALUE "InternalName", "ObjFW" VALUE "OriginalFilename", OBJFW_SHARED_LIB } } Index: tests/ForwardingTests.m ================================================================== --- tests/ForwardingTests.m +++ tests/ForwardingTests.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -206,12 +206,12 @@ isEqual: RESULT]) /* * Don't try fpret on Win64 if we don't have stret forwarding, as * long double is handled as a struct there. */ -# if !defined(OF_WINDOWS) || !defined(OF_X86_64) || \ - defined(OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR_STRET) +# if !defined(OF_WINDOWS) || !defined(OF_AMD64) || \ + defined(OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR_STRET) TEST(@"-[forwardingTargetForSelector:] fp return", [testObject forwardingTargetFPRetTest] == 12345678.00006103515625) # endif # ifdef OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR_STRET TEST(@"-[forwardingTargetForSelector:] struct return", Index: tests/ImportTest.m ================================================================== --- tests/ImportTest.m +++ tests/ImportTest.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,6 +11,6 @@ * Public License, either 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 +@import ObjFW; Index: tests/Makefile ================================================================== --- tests/Makefile +++ tests/Makefile @@ -8,11 +8,10 @@ boot.dol \ ${PROG_NOINST}.arm9 \ ${PROG_NOINST}.nds \ ${PROG_NOINST}.nro \ ${PROG_NOINST}.rpx \ - serialization_xml.m \ testfile_bin.m \ testfile_ini.m DISTCLEAN = Info.plist PROG_NOINST = tests${PROG_SUFFIX} @@ -21,20 +20,23 @@ OFASN1DERParsingTests.m \ OFASN1DERRepresentationTests.m \ OFArrayTests.m \ ${OF_BLOCK_TESTS_M} \ OFCharacterSetTests.m \ + OFColorTests.m \ OFDataTests.m \ OFDateTests.m \ OFDictionaryTests.m \ OFHMACTests.m \ OFINIFileTests.m \ + OFIRITests.m \ OFInvocationTests.m \ OFJSONTests.m \ OFListTests.m \ OFLocaleTests.m \ OFMD5HashTests.m \ + OFMatrix4x4Tests.m \ OFMemoryStreamTests.m \ OFMethodSignatureTests.m \ OFNotificationCenterTests.m \ OFNumberTests.m \ OFObjectTests.m \ @@ -45,16 +47,14 @@ OFSHA224HashTests.m \ OFSHA256HashTests.m \ OFSHA384HashTests.m \ OFSHA512HashTests.m \ OFScryptTests.m \ - OFSerializationTests.m \ OFSetTests.m \ OFStreamTests.m \ OFStringTests.m \ OFSystemInfoTests.m \ - OFURITests.m \ OFValueTests.m \ OFXMLElementBuilderTests.m \ OFXMLNodeTests.m \ OFXMLParserTests.m \ RuntimeTests.m \ @@ -63,11 +63,10 @@ ${USE_SRCS_FILES} \ ${USE_SRCS_PLUGINS} \ ${USE_SRCS_SOCKETS} \ ${USE_SRCS_THREADS} \ ${USE_SRCS_WINDOWS} \ - serialization_xml.m \ testfile_bin.m \ testfile_ini.m SRCS_PLUGINS = OFPluginTests.m SRCS_SOCKETS = OFDNSResolverTests.m \ ${OF_HTTP_CLIENT_TESTS_M} \ @@ -92,12 +91,10 @@ 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 $@ @@ -108,11 +105,10 @@ rm -f objfw${OBJFW_LIB_MAJOR}.dll libobjfw.${OBJFW_LIB_MAJOR}.dylib rm -f libobjfwrt.so.${OBJFWRT_LIB_MAJOR} rm -f libobjfwrt.so.${OBJFWRT_LIB_MAJOR_MINOR} rm -f objfwrt${OBJFWRT_LIB_MAJOR}.dll rm -f libobjfwrt.${OBJFWRT_LIB_MAJOR}.dylib - rm -f ${OBJFWRT_AMIGA_LIB} if test -f ../src/libobjfw.so; then \ ${LN_S} ../src/libobjfw.so libobjfw.so.${OBJFW_LIB_MAJOR}; \ ${LN_S} ../src/libobjfw.so \ libobjfw.so.${OBJFW_LIB_MAJOR_MINOR}; \ elif test -f ../src/libobjfw.so.${OBJFW_LIB_MAJOR_MINOR}; then \ @@ -141,14 +137,10 @@ fi if test -f ../src/runtime/libobjfwrt.dylib; then \ ${LN_S} ../src/runtime/libobjfwrt.dylib \ libobjfwrt.${OBJFWRT_LIB_MAJOR}.dylib; \ fi - if test -f ../src/runtime/${OBJFWRT_AMIGA_LIB}; then \ - ${LN_S} ../src/runtime/${OBJFWRT_AMIGA_LIB} \ - ${OBJFWRT_AMIGA_LIB}; \ - fi LD_LIBRARY_PATH=.$${LD_LIBRARY_PATH+:}$$LD_LIBRARY_PATH \ DYLD_FRAMEWORK_PATH=../src:../src/runtime$${DYLD_FRAMEWORK_PATH+:}$$DYLD_FRAMEWORK_PATH \ DYLD_LIBRARY_PATH=.$${DYLD_LIBRARY_PATH+:}$$DYLD_LIBRARY_PATH \ LIBRARY_PATH=.$${LIBRARY_PATH+:}$$LIBRARY_PATH \ ASAN_OPTIONS=allocator_may_return_null=1 \ Index: tests/OFASN1DERParsingTests.m ================================================================== --- tests/OFASN1DERParsingTests.m +++ tests/OFASN1DERParsingTests.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may 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/OFASN1DERRepresentationTests.m ================================================================== --- tests/OFASN1DERRepresentationTests.m +++ tests/OFASN1DERRepresentationTests.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may 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/OFArrayTests.m ================================================================== --- tests/OFArrayTests.m +++ tests/OFArrayTests.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -429,20 +429,20 @@ [OFNumber numberWithInt: 3], [OFNumber numberWithInt: 6], nil]] && [[[arrayClass arrayWithObjects: @"1", @"2", nil] valueForKey: @"@count"] isEqual: [OFNumber numberWithInt: 2]]) mutableArray1 = [mutableArrayClass arrayWithObjects: - [OFMutableURI URIWithString: @"http://foo.bar/"], - [OFMutableURI URIWithString: @"http://bar.qux/"], - [OFMutableURI URIWithString: @"http://qux.quxqux/"], nil]; + [OFMutableIRI IRIWithString: @"http://foo.bar/"], + [OFMutableIRI IRIWithString: @"http://bar.qux/"], + [OFMutableIRI IRIWithString: @"http://qux.quxqux/"], nil]; TEST(@"-[setValue:forKey:]", R([mutableArray1 setValue: [OFNumber numberWithShort: 1234] forKey: @"port"]) && [mutableArray1 isEqual: [arrayClass arrayWithObjects: - [OFURI URIWithString: @"http://foo.bar:1234/"], - [OFURI URIWithString: @"http://bar.qux:1234/"], - [OFURI URIWithString: @"http://qux.quxqux:1234/"], nil]]) + [OFIRI IRIWithString: @"http://foo.bar:1234/"], + [OFIRI IRIWithString: @"http://bar.qux:1234/"], + [OFIRI IRIWithString: @"http://qux.quxqux:1234/"], nil]]) objc_autoreleasePoolPop(pool); } - (void)arrayTests Index: tests/OFBlockTests.m ================================================================== --- tests/OFBlockTests.m +++ tests/OFBlockTests.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,14 @@ extern void *_NSConcreteStackBlock; extern void *_NSConcreteGlobalBlock; extern void *_NSConcreteMallocBlock; #endif +/* Clang on Win32 generates broken code that crashes for global blocks. */ +#if !defined(OF_WINDOWS) || !defined(__clang__) static void (^globalBlock)(void) = ^ {}; +#endif static int (^returnStackBlock(void))(void) { __block int i = 42; @@ -67,15 +70,11 @@ TEST(@"Class of stack block", (Class)&_NSConcreteStackBlock == objc_getClass("OFStackBlock") && [stackBlock isKindOfClass: [OFBlock class]]) -#if !defined(OF_WINDOWS) || !defined(__clang__) || !defined(OF_NO_SHARED) - /* - * Causes a linker error on Windows with Clang when compiling as a - * static library. This is a bug in Clang. - */ +#if !defined(OF_WINDOWS) || !defined(__clang__) TEST(@"Class of global block", (Class)&_NSConcreteGlobalBlock == objc_getClass("OFGlobalBlock") && [globalBlock isKindOfClass: [OFBlock class]]) #endif @@ -92,25 +91,29 @@ TEST(@"Copying a stack block and using its copied variable", (voidBlock = returnStackBlock()) && voidBlock() == 43 && voidBlock() == 44 && voidBlock() == 45) +#if !defined(OF_WINDOWS) || !defined(__clang__) TEST(@"Copying a global block", (id)globalBlock == [[globalBlock copy] autorelease]) +#endif #ifndef __clang_analyzer__ TEST(@"Copying a malloc block", (id)mallocBlock == [mallocBlock copy] && [mallocBlock retainCount] == 2) #endif TEST(@"Autorelease a stack block", R([stackBlock autorelease])) +#if !defined(OF_WINDOWS) || !defined(__clang__) TEST(@"Autorelease a global block", R([globalBlock autorelease])) +#endif #ifndef __clang_analyzer__ TEST(@"Autorelease a malloc block", R([mallocBlock autorelease])) #endif objc_autoreleasePoolPop(pool); } @end Index: tests/OFCharacterSetTests.m ================================================================== --- tests/OFCharacterSetTests.m +++ tests/OFCharacterSetTests.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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/OFColorTests.m Index: tests/OFColorTests.m ================================================================== --- /dev/null +++ tests/OFColorTests.m @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2008-2024 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#include "config.h" + +#import "TestsAppDelegate.h" + +static OFString *const module = @"OFColor"; + +@implementation TestsAppDelegate (OFColorTests) +- (void)colorTests +{ + void *pool = objc_autoreleasePoolPush(); + OFColor *color; + float red, green, blue, alpha; + + TEST(@"+[colorWithRed:green:blue:alpha:]", + (color = [OFColor colorWithRed: 63.f / 255 + green: 127.f / 255 + blue: 1 + alpha: 1])) + +#ifdef OF_OBJFW_RUNTIME + TEST(@"+[colorWithRed:green:blue:alpha:] returns tagged pointer", + object_isTaggedPointer(color)) +#endif + + TEST(@"-[getRed:green:blue:alpha:]", + R([color getRed: &red green: &green blue: &blue alpha: &alpha]) && + red == 63.f / 255 && green == 127.f / 255 && blue == 1 && + alpha == 1) + + objc_autoreleasePoolPop(pool); +} +@end Index: tests/OFDDPSocketTests.m ================================================================== --- tests/OFDDPSocketTests.m +++ tests/OFDDPSocketTests.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,10 +38,11 @@ port: 0 protocolType: 11])) } @catch (OFBindSocketFailedException *e) { switch (e.errNo) { case EAFNOSUPPORT: + case EPROTONOSUPPORT: [OFStdOut setForegroundColor: [OFColor lime]]; [OFStdOut writeLine: @"\r[OFDDPSocket] -[bindToNetwork:node:port:" @"protocolType:] AppleTalk unsupported, skipping " @"tests"]; Index: tests/OFDNSResolverTests.m ================================================================== --- tests/OFDNSResolverTests.m +++ tests/OFDNSResolverTests.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,15 +57,15 @@ [OFStdOut writeFormat: @"[OFDNSResolver] Min number of dots in absolute name: %u\n", resolver.minNumberOfDotsInAbsoluteName]; - [OFStdOut writeFormat: @"[OFDNSResolver] Uses TCP: %u\n", - resolver.usesTCP]; + [OFStdOut writeFormat: @"[OFDNSResolver] Forces TCP: %u\n", + resolver.forcesTCP]; [OFStdOut writeFormat: @"[OFDNSResolver] Config reload interval: %lf\n", resolver.configReloadInterval]; objc_autoreleasePoolPop(pool); } @end Index: tests/OFDataTests.m ================================================================== --- tests/OFDataTests.m +++ tests/OFDataTests.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may 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/OFDictionaryTests.m ================================================================== --- tests/OFDictionaryTests.m +++ tests/OFDictionaryTests.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,12 @@ @implementation TestsAppDelegate (OFHMACTests) - (void)HMACTests { void *pool = objc_autoreleasePoolPush(); - OFURI *URI = [OFURI URIWithString: @"embedded:testfile.bin"]; - OFStream *file = [OFURIHandler openItemAtURI: URI mode: @"r"]; + OFIRI *IRI = [OFIRI IRIWithString: @"embedded:testfile.bin"]; + OFStream *file = [OFIRIHandler openItemAtIRI: IRI mode: @"r"]; OFHMAC *HMACMD5, *HMACSHA1, *HMACRMD160; OFHMAC *HMACSHA256, *HMACSHA384, *HMACSHA512; TEST(@"+[HMACWithHashClass:] with MD5", (HMACMD5 = [OFHMAC HMACWithHashClass: [OFMD5Hash class] Index: tests/OFHTTPClientTests.m ================================================================== --- tests/OFHTTPClientTests.m +++ tests/OFHTTPClientTests.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,16 +36,18 @@ @implementation HTTPClientTestsServer - (id)main { OFTCPSocket *listener, *client; + OFSocketAddress address; char buffer[5]; [condition lock]; listener = [OFTCPSocket socket]; - _port = [listener bindToHost: @"127.0.0.1" port: 0]; + address = [listener bindToHost: @"127.0.0.1" port: 0]; + _port = OFSocketAddressIPPort(&address); [listener listen]; [condition signal]; [condition unlock]; @@ -99,11 +101,11 @@ - (void)HTTPClientTests { void *pool = objc_autoreleasePoolPush(); HTTPClientTestsServer *server; - OFURI *URI; + OFIRI *IRI; OFHTTPClient *client; OFHTTPRequest *request; OFData *data; condition = [OFCondition condition]; @@ -114,17 +116,17 @@ [server start]; [condition wait]; [condition unlock]; - URI = [OFURI URIWithString: + IRI = [OFIRI IRIWithString: [OFString stringWithFormat: @"http://127.0.0.1:%" @PRIu16 "/foo", server->_port]]; TEST(@"-[asyncPerformRequest:]", (client = [OFHTTPClient client]) && (client.delegate = self) && - (request = [OFHTTPRequest requestWithURI: URI]) && + (request = [OFHTTPRequest requestWithIRI: IRI]) && (request.headers = [OFDictionary dictionaryWithObject: @"5" forKey: @"Content-Length"]) && R([client asyncPerformRequest: request])) Index: tests/OFHTTPCookieManagerTests.m ================================================================== --- tests/OFHTTPCookieManagerTests.m +++ tests/OFHTTPCookieManagerTests.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,75 +22,75 @@ @implementation TestsAppDelegate (OFHTTPCookieManagerTests) - (void)HTTPCookieManagerTests { void *pool = objc_autoreleasePoolPush(); OFHTTPCookieManager *manager = [OFHTTPCookieManager manager]; - OFURI *URI1, *URI2, *URI3, *URI4; + OFIRI *IRI1, *IRI2, *IRI3, *IRI4; OFHTTPCookie *cookie1, *cookie2, *cookie3, *cookie4, *cookie5; - URI1 = [OFURI URIWithString: @"http://nil.im/foo"]; - URI2 = [OFURI URIWithString: @"https://nil.im/foo/bar"]; - URI3 = [OFURI URIWithString: @"https://test.nil.im/foo/bar"]; - URI4 = [OFURI URIWithString: @"http://webkeks.org/foo/bar"]; + IRI1 = [OFIRI IRIWithString: @"http://nil.im/foo"]; + IRI2 = [OFIRI IRIWithString: @"https://nil.im/foo/bar"]; + IRI3 = [OFIRI IRIWithString: @"https://test.nil.im/foo/bar"]; + IRI4 = [OFIRI IRIWithString: @"http://webkeks.org/foo/bar"]; cookie1 = [OFHTTPCookie cookieWithName: @"test" value: @"1" domain: @"nil.im"]; - TEST(@"-[addCookie:forURI:] #1", - R([manager addCookie: cookie1 forURI: URI1])) + TEST(@"-[addCookie:forIRI:] #1", + R([manager addCookie: cookie1 forIRI: IRI1])) - TEST(@"-[cookiesForURI:] #1", - [[manager cookiesForURI: URI1] isEqual: + TEST(@"-[cookiesForIRI:] #1", + [[manager cookiesForIRI: IRI1] isEqual: [OFArray arrayWithObject: cookie1]]) cookie2 = [OFHTTPCookie cookieWithName: @"test" value: @"2" domain: @"webkeks.org"]; - TEST(@"-[addCookie:forURI:] #2", - R([manager addCookie: cookie2 forURI: URI1])) + TEST(@"-[addCookie:forIRI:] #2", + R([manager addCookie: cookie2 forIRI: IRI1])) - TEST(@"-[cookiesForURI:] #2", - [[manager cookiesForURI: URI1] isEqual: + TEST(@"-[cookiesForIRI:] #2", + [[manager cookiesForIRI: IRI1] isEqual: [OFArray arrayWithObject: cookie1]] && - [[manager cookiesForURI: URI4] isEqual: [OFArray array]]) + [[manager cookiesForIRI: IRI4] isEqual: [OFArray array]]) cookie3 = [OFHTTPCookie cookieWithName: @"test" value: @"3" domain: @"nil.im"]; cookie3.secure = true; - TEST(@"-[addCookie:forURI:] #3", - R([manager addCookie: cookie3 forURI: URI2])) + TEST(@"-[addCookie:forIRI:] #3", + R([manager addCookie: cookie3 forIRI: IRI2])) - TEST(@"-[cookiesForURI:] #3", - [[manager cookiesForURI: URI2] isEqual: + TEST(@"-[cookiesForIRI:] #3", + [[manager cookiesForIRI: IRI2] isEqual: [OFArray arrayWithObject: cookie3]] && - [[manager cookiesForURI: URI1] isEqual: [OFArray array]]) + [[manager cookiesForIRI: IRI1] isEqual: [OFArray array]]) cookie3.expires = [OFDate dateWithTimeIntervalSinceNow: -1]; cookie4 = [OFHTTPCookie cookieWithName: @"test" value: @"4" domain: @"nil.im"]; cookie4.domain = @".nil.im"; - TEST(@"-[addCookie:forURI:] #4", - R([manager addCookie: cookie4 forURI: URI2])) + TEST(@"-[addCookie:forIRI:] #4", + R([manager addCookie: cookie4 forIRI: IRI2])) - TEST(@"-[cookiesForURI:] #4", - [[manager cookiesForURI: URI2] isEqual: + TEST(@"-[cookiesForIRI:] #4", + [[manager cookiesForIRI: IRI2] isEqual: [OFArray arrayWithObject: cookie4]] && - [[manager cookiesForURI: URI3] isEqual: + [[manager cookiesForIRI: IRI3] isEqual: [OFArray arrayWithObject: cookie4]]) cookie5 = [OFHTTPCookie cookieWithName: @"bar" value: @"5" domain: @"test.nil.im"]; - TEST(@"-[addCookie:forURI:] #5", - R([manager addCookie: cookie5 forURI: URI1])) + TEST(@"-[addCookie:forIRI:] #5", + R([manager addCookie: cookie5 forIRI: IRI1])) - TEST(@"-[cookiesForURI:] #5", - [[manager cookiesForURI: URI1] isEqual: + TEST(@"-[cookiesForIRI:] #5", + [[manager cookiesForIRI: IRI1] isEqual: [OFArray arrayWithObject: cookie4]] && - [[manager cookiesForURI: URI3] isEqual: + [[manager cookiesForIRI: IRI3] isEqual: [OFArray arrayWithObjects: cookie4, cookie5, nil]]) TEST(@"-[purgeExpiredCookies]", [manager.cookies isEqual: [OFArray arrayWithObjects: cookie3, cookie4, cookie5, nil]] && Index: tests/OFHTTPCookieTests.m ================================================================== --- tests/OFHTTPCookieTests.m +++ tests/OFHTTPCookieTests.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,30 +21,30 @@ @implementation TestsAppDelegate (OFHTTPCookieTests) - (void)HTTPCookieTests { void *pool = objc_autoreleasePoolPush(); - OFURI *URI = [OFURI URIWithString: @"http://nil.im"]; + OFIRI *IRI = [OFIRI IRIWithString: @"http://nil.im"]; OFHTTPCookie *cookie1, *cookie2; OFArray OF_GENERIC(OFHTTPCookie *) *cookies; cookie1 = [OFHTTPCookie cookieWithName: @"foo" value: @"bar" domain: @"nil.im"]; - TEST(@"+[cookiesWithResponseHeaderFields:forURI:] #1", + TEST(@"+[cookiesWithResponseHeaderFields:forIRI:] #1", [[OFHTTPCookie cookiesWithResponseHeaderFields: [OFDictionary dictionaryWithObject: @"foo=bar" - forKey: @"Set-Cookie"] forURI: URI] + forKey: @"Set-Cookie"] forIRI: IRI] isEqual: [OFArray arrayWithObject: cookie1]]) cookie2 = [OFHTTPCookie cookieWithName: @"qux" value: @"cookie" domain: @"nil.im"]; - TEST(@"+[cookiesWithResponseHeaderFields:forURI:] #2", + TEST(@"+[cookiesWithResponseHeaderFields:forIRI:] #2", [[OFHTTPCookie cookiesWithResponseHeaderFields: [OFDictionary dictionaryWithObject: @"foo=bar,qux=cookie" - forKey: @"Set-Cookie"] forURI: URI] + forKey: @"Set-Cookie"] forIRI: IRI] isEqual: [OFArray arrayWithObjects: cookie1, cookie2, nil]]) cookie1.expires = [OFDate dateWithTimeIntervalSince1970: 1234567890]; cookie2.expires = [OFDate dateWithTimeIntervalSince1970: 1234567890]; cookie1.path = @"/x"; @@ -52,17 +52,17 @@ cookie2.path = @"/objfw"; cookie2.secure = true; cookie2.HTTPOnly = true; [cookie2.extensions addObject: @"foo"]; [cookie2.extensions addObject: @"bar"]; - TEST(@"+[cookiesWithResponseHeaderFields:forURI:] #3", + TEST(@"+[cookiesWithResponseHeaderFields:forIRI:] #3", [(cookies = [OFHTTPCookie cookiesWithResponseHeaderFields: [OFDictionary dictionaryWithObject: @"foo=bar; Expires=Fri, 13 Feb 2009 23:31:30 GMT; Path=/x," @"qux=cookie; Expires=Fri, 13 Feb 2009 23:31:30 GMT; " @"Domain=webkeks.org; Path=/objfw; Secure; HTTPOnly; foo; bar" - forKey: @"Set-Cookie"] forURI: URI]) isEqual: + forKey: @"Set-Cookie"] forIRI: IRI]) isEqual: [OFArray arrayWithObjects: cookie1, cookie2, nil]]) TEST(@"+[requestHeaderFieldsWithCookies:]", [[OFHTTPCookie requestHeaderFieldsWithCookies: cookies] isEqual: [OFDictionary dictionaryWithObject: @"foo=bar; qux=cookie" Index: tests/OFINIFileTests.m ================================================================== --- tests/OFINIFileTests.m +++ tests/OFINIFileTests.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,23 +41,23 @@ @"bool=false\r\n" @"float=0.25\r\n" @"array1=foo\r\n" @"array1=bar\r\n" @"double=0.75\r\n"; - OFURI *URI; + OFIRI *IRI; OFINIFile *file; OFINICategory *tests, *foobar, *types; OFArray *array; #if defined(OF_HAVE_FILES) && !defined(OF_NINTENDO_DS) - OFURI *writeURI; + OFIRI *writeIRI; #endif module = @"OFINIFile"; - URI = [OFURI URIWithString: @"embedded:testfile.ini"]; - TEST(@"+[fileWithURI:encoding:]", - (file = [OFINIFile fileWithURI: URI + IRI = [OFIRI IRIWithString: @"embedded:testfile.ini"]; + TEST(@"+[fileWithIRI:encoding:]", + (file = [OFINIFile fileWithIRI: IRI encoding: OFStringEncodingCodepage437])) tests = [file categoryForName: @"tests"]; foobar = [file categoryForName: @"foobar"]; types = [file categoryForName: @"types"]; @@ -64,72 +64,75 @@ TEST(@"-[categoryForName:]", tests != nil && foobar != nil && types != nil) module = @"OFINICategory"; - TEST(@"-[stringForKey:]", - [[tests stringForKey: @"foo"] isEqual: @"bar"] && - [[foobar stringForKey: @"quxquxqux"] isEqual: @"hello\"wörld"]) - - TEST(@"-[setString:forKey:]", - R([tests setString: @"baz" forKey: @"foo"]) && - R([tests setString: @"new" forKey: @"new"]) && - R([foobar setString: @"a\fb" forKey: @"qux3"])) - - TEST(@"-[longLongForKey:defaultValue:]", - [types longLongForKey: @"integer" defaultValue: 2] == 0x20) - - TEST(@"-[setLongLong:forKey:]", - R([types setLongLong: 0x10 forKey: @"integer"])) - - TEST(@"-[boolForKey:defaultValue:]", - [types boolForKey: @"bool" defaultValue: false] == true) - - TEST(@"-[setBool:forKey:]", R([types setBool: false forKey: @"bool"])) - - TEST(@"-[floatForKey:defaultValue:]", - [types floatForKey: @"float" defaultValue: 1] == 0.5f) - - TEST(@"-[setFloat:forKey:]", - R([types setFloat: 0.25f forKey: @"float"])) - - TEST(@"-[doubleForKey:defaultValue:]", - [types doubleForKey: @"double" defaultValue: 3] == 0.25) - - TEST(@"-[setDouble:forKey:]", - R([types setDouble: 0.75 forKey: @"double"])) + TEST(@"-[stringValueForKey:]", + [[tests stringValueForKey: @"foo"] isEqual: @"bar"] && + [[foobar stringValueForKey: @"quxquxqux"] isEqual: @"hello\"wörld"]) + + TEST(@"-[setStringValue:forKey:]", + R([tests setStringValue: @"baz" forKey: @"foo"]) && + R([tests setStringValue: @"new" forKey: @"new"]) && + R([foobar setStringValue: @"a\fb" forKey: @"qux3"])) + + TEST(@"-[longLongValueForKey:defaultValue:]", + [types longLongValueForKey: @"integer" defaultValue: 2] == 0x20) + + TEST(@"-[setLongLongValue:forKey:]", + R([types setLongLongValue: 0x10 forKey: @"integer"])) + + TEST(@"-[boolValueForKey:defaultValue:]", + [types boolValueForKey: @"bool" defaultValue: false] == true) + + TEST(@"-[setBoolValue:forKey:]", + R([types setBoolValue: false forKey: @"bool"])) + + TEST(@"-[floatValueForKey:defaultValue:]", + [types floatValueForKey: @"float" defaultValue: 1] == 0.5f) + + TEST(@"-[setFloatValue:forKey:]", + R([types setFloatValue: 0.25f forKey: @"float"])) + + TEST(@"-[doubleValueForKey:defaultValue:]", + [types doubleValueForKey: @"double" defaultValue: 3] == 0.25) + + TEST(@"-[setDoubleValue:forKey:]", + R([types setDoubleValue: 0.75 forKey: @"double"])) array = [OFArray arrayWithObjects: @"1", @"2", nil]; - TEST(@"-[stringArrayForKey:]", - [[types stringArrayForKey: @"array1"] isEqual: array] && - [[types stringArrayForKey: @"array2"] isEqual: array] && - [[types stringArrayForKey: @"array3"] isEqual: [OFArray array]]) + TEST(@"-[arrayValueForKey:]", + [[types arrayValueForKey: @"array1"] isEqual: array] && + [[types arrayValueForKey: @"array2"] isEqual: array] && + [[types arrayValueForKey: @"array3"] isEqual: [OFArray array]]) array = [OFArray arrayWithObjects: @"foo", @"bar", nil]; - TEST(@"-[setStringArray:forKey:]", - R([types setStringArray: array forKey: @"array1"])) + TEST(@"-[setArrayValue:forKey:]", + R([types setArrayValue: array forKey: @"array1"])) TEST(@"-[removeValueForKey:]", R([foobar removeValueForKey: @"quxqux "]) && R([types removeValueForKey: @"array2"])) module = @"OFINIFile"; /* FIXME: Find a way to write files on Nintendo DS */ #if defined(OF_HAVE_FILES) && !defined(OF_NINTENDO_DS) - writeURI = [[OFSystemInfo temporaryDirectoryURI] - URIByAppendingPathComponent: @"objfw-tests.ini" - isDirectory: false]; + writeIRI = [OFSystemInfo temporaryDirectoryIRI]; + if (writeIRI == nil) + writeIRI = [[OFFileManager defaultManager] currentDirectoryIRI]; + writeIRI = [writeIRI IRIByAppendingPathComponent: @"objfw-tests.ini" + isDirectory: false]; TEST(@"-[writeToFile:encoding:]", - R([file writeToURI: writeURI + R([file writeToIRI: writeIRI encoding: OFStringEncodingCodepage437]) && - [[OFString stringWithContentsOfURI: writeURI + [[OFString stringWithContentsOfIRI: writeIRI encoding: OFStringEncodingCodepage437] isEqual: output]) - [[OFFileManager defaultManager] removeItemAtURI: writeURI]; + [[OFFileManager defaultManager] removeItemAtIRI: writeIRI]; #else (void)output; #endif objc_autoreleasePoolPop(pool); } @end Index: tests/OFIPXSocketTests.m ================================================================== --- tests/OFIPXSocketTests.m +++ tests/OFIPXSocketTests.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,12 +26,14 @@ { const unsigned char zeroNode[IPX_NODE_LEN] = { 0 }; void *pool = objc_autoreleasePoolPush(); OFIPXSocket *sock; OFSocketAddress address1, address2; + OFDictionary *networkInterfaces; char buffer[5]; unsigned char node1[IPX_NODE_LEN], node2[IPX_NODE_LEN]; + unsigned char node[IPX_NODE_LEN]; TEST(@"+[socket]", (sock = [OFIPXSocket socket])) @try { TEST(@"-[bindToNetwork:node:port:packetType:]", @@ -59,10 +61,41 @@ } objc_autoreleasePoolPop(pool); return; } + + /* + * Find any network interface with IPX and send to it. Any should be + * fine since we bound to 0.0. + */ + networkInterfaces = [OFSystemInfo networkInterfaces]; + for (OFString *name in networkInterfaces) { + OFNetworkInterface interface = [networkInterfaces + objectForKey: name]; + OFData *addresses = [interface + objectForKey: OFNetworkInterfaceIPXAddresses]; + + if (addresses.count == 0) + continue; + + OFSocketAddressSetIPXNetwork(&address1, + OFSocketAddressIPXNetwork([addresses itemAtIndex: 0])); + OFSocketAddressGetIPXNode([addresses itemAtIndex: 0], node); + OFSocketAddressSetIPXNode(&address1, node); + } + + OFSocketAddressGetIPXNode(&address1, node); + if (OFSocketAddressIPXNetwork(&address1) == 0 && + memcmp(node, zeroNode, 6) == 0) { + [OFStdOut setForegroundColor: [OFColor lime]]; + [OFStdOut writeLine: + @"[OFIPXSocket] -[sendBuffer:length:receiver:]: " + @"Could not determine own address, skipping tests"]; + objc_autoreleasePoolPop(pool); + return; + } TEST(@"-[sendBuffer:length:receiver:]", R([sock sendBuffer: "Hello" length: 5 receiver: &address1])) TEST(@"-[receiveIntoBuffer:length:sender:]", ADDED tests/OFIRITests.m Index: tests/OFIRITests.m ================================================================== --- /dev/null +++ tests/OFIRITests.m @@ -0,0 +1,371 @@ +/* + * Copyright (c) 2008-2024 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#include "config.h" + +#import "TestsAppDelegate.h" + +static OFString *const module = @"OFIRI"; +static OFString *IRIString = @"ht+tp://us%3Aer:p%40w@ho%3Ast:1234/" + @"pa%3Fth?que%23ry=1&f%26oo=b%3dar#frag%23ment"; + +@implementation TestsAppDelegate (OFIRITests) +- (void)IRITests +{ + void *pool = objc_autoreleasePoolPush(); + OFIRI *IRI1, *IRI2, *IRI3, *IRI4, *IRI5, *IRI6, *IRI7, *IRI8, *IRI9; + OFIRI *IRI10, *IRI11; + OFMutableIRI *mutableIRI; + + TEST(@"+[IRIWithString:]", + R(IRI1 = [OFIRI IRIWithString: IRIString]) && + R(IRI2 = [OFIRI IRIWithString: @"http://foo:80"]) && + R(IRI3 = [OFIRI IRIWithString: @"http://bar/"]) && + R(IRI4 = [OFIRI IRIWithString: @"file:///etc/passwd"]) && + R(IRI5 = [OFIRI IRIWithString: @"http://foo/bar/qux/foo%2fbar"]) && + R(IRI6 = [OFIRI IRIWithString: @"https://[12:34::56:abcd]/"]) && + R(IRI7 = [OFIRI IRIWithString: @"https://[12:34::56:abcd]:234/"]) && + R(IRI8 = [OFIRI IRIWithString: @"urn:qux:foo"]) && + R(IRI9 = [OFIRI IRIWithString: @"file:/foo?query#frag"]) && + R(IRI10 = [OFIRI IRIWithString: @"file:foo@bar/qux?query#frag"]) && + R(IRI11 = [OFIRI IRIWithString: @"http://ä/ö?ü"])) + + EXPECT_EXCEPTION(@"+[IRIWithString:] fails with invalid characters #1", + OFInvalidFormatException, + [OFIRI IRIWithString: @"ht,tp://foo"]) + + EXPECT_EXCEPTION(@"+[IRIWithString:] fails with invalid characters #2", + OFInvalidFormatException, + [OFIRI IRIWithString: @"http://f`oo"]) + + EXPECT_EXCEPTION(@"+[IRIWithString:] fails with invalid characters #3", + OFInvalidFormatException, + [OFIRI IRIWithString: @"http://foo/`"]) + + EXPECT_EXCEPTION(@"+[IRIWithString:] fails with invalid characters #4", + OFInvalidFormatException, + [OFIRI IRIWithString: @"http://foo/foo?`"]) + + EXPECT_EXCEPTION(@"+[IRIWithString:] fails with invalid characters #5", + OFInvalidFormatException, + [OFIRI IRIWithString: @"http://foo/foo?foo#`"]) + + EXPECT_EXCEPTION(@"+[IRIWithString:] fails with invalid characters #6", + OFInvalidFormatException, + [OFIRI IRIWithString: @"https://[g]/"]) + + EXPECT_EXCEPTION(@"+[IRIWithString:] fails with invalid characters #7", + OFInvalidFormatException, + [OFIRI IRIWithString: @"https://[f]:/"]) + + EXPECT_EXCEPTION(@"+[IRIWithString:] fails with invalid characters #8", + OFInvalidFormatException, + [OFIRI IRIWithString: @"https://[f]:f/"]) + + EXPECT_EXCEPTION(@"+[IRIWithString:] fails with invalid characters #9", + OFInvalidFormatException, + [OFIRI IRIWithString: @"foo:"]) + + TEST(@"+[IRIWithString:relativeToIRI:]", + [[[OFIRI IRIWithString: @"/foo" relativeToIRI: IRI1] string] + isEqual: @"ht+tp://us%3Aer:p%40w@ho%3Ast:1234/foo"] && + [[[OFIRI IRIWithString: @"foo/bar?q" + relativeToIRI: [OFIRI IRIWithString: @"http://h/qux/quux"]] + string] isEqual: @"http://h/qux/foo/bar?q"] && + [[[OFIRI IRIWithString: @"foo/bar" + relativeToIRI: [OFIRI IRIWithString: @"http://h/qux/?x"]] + string] isEqual: @"http://h/qux/foo/bar"] && + [[[OFIRI IRIWithString: @"http://foo/?q" + relativeToIRI: IRI1] string] isEqual: @"http://foo/?q"] && + [[[OFIRI IRIWithString: @"foo" + relativeToIRI: [OFIRI IRIWithString: @"http://foo/bar"]] + string] isEqual: @"http://foo/foo"] && + [[[OFIRI IRIWithString: @"foo" + relativeToIRI: [OFIRI IRIWithString: @"http://foo"]] + string] isEqual: @"http://foo/foo"]) + + EXPECT_EXCEPTION( + @"+[IRIWithString:relativeToIRI:] fails with invalid characters #1", + OFInvalidFormatException, + [OFIRI IRIWithString: @"`" relativeToIRI: IRI1]) + + EXPECT_EXCEPTION( + @"+[IRIWithString:relativeToIRI:] fails with invalid characters #2", + OFInvalidFormatException, + [OFIRI IRIWithString: @"/`" relativeToIRI: IRI1]) + + EXPECT_EXCEPTION( + @"+[IRIWithString:relativeToIRI:] fails with invalid characters #3", + OFInvalidFormatException, + [OFIRI IRIWithString: @"?`" relativeToIRI: IRI1]) + + EXPECT_EXCEPTION( + @"+[IRIWithString:relativeToIRI:] fails with invalid characters #4", + OFInvalidFormatException, + [OFIRI IRIWithString: @"#`" relativeToIRI: IRI1]) + +#ifdef OF_HAVE_FILES + TEST(@"+[fileIRIWithPath:]", + [[[OFIRI fileIRIWithPath: @"testfile.txt"] fileSystemRepresentation] + isEqual: [[OFFileManager defaultManager].currentDirectoryPath + stringByAppendingPathComponent: @"testfile.txt"]]) + +# if defined(OF_WINDOWS) || defined(OF_MSDOS) + OFIRI *tmp; + TEST(@"+[fileIRIWithPath:] for c:\\", + (tmp = [OFIRI fileIRIWithPath: @"c:\\"]) && + [tmp.string isEqual: @"file:/c:/"] && + [tmp.fileSystemRepresentation isEqual: @"c:\\"]) +# endif + +# ifdef OF_WINDOWS + TEST(@"+[fileIRIWithPath:] with UNC", + (tmp = [OFIRI fileIRIWithPath: @"\\\\foo\\bar" + isDirectory: false]) && + [tmp.host isEqual: @"foo"] && [tmp.path isEqual: @"/bar"] && + [tmp.string isEqual: @"file://foo/bar"] && + [tmp.fileSystemRepresentation isEqual: @"\\\\foo\\bar"] && + (tmp = [OFIRI fileIRIWithPath: @"\\\\test" isDirectory: true]) && + [tmp.host isEqual: @"test"] && [tmp.path isEqual: @"/"] && + [tmp.string isEqual: @"file://test/"] && + [tmp.fileSystemRepresentation isEqual: @"\\\\test"]) +# endif +#endif + + TEST(@"-[string]", + [IRI1.string isEqual: IRIString] && + [IRI2.string isEqual: @"http://foo:80"] && + [IRI3.string isEqual: @"http://bar/"] && + [IRI4.string isEqual: @"file:///etc/passwd"] && + [IRI5.string isEqual: @"http://foo/bar/qux/foo%2fbar"] && + [IRI6.string isEqual: @"https://[12:34::56:abcd]/"] && + [IRI7.string isEqual: @"https://[12:34::56:abcd]:234/"] && + [IRI8.string isEqual: @"urn:qux:foo"] && + [IRI9.string isEqual: @"file:/foo?query#frag"] && + [IRI10.string isEqual: @"file:foo@bar/qux?query#frag"] && + [IRI11.string isEqual: @"http://ä/ö?ü"]) + + TEST(@"-[scheme]", + [IRI1.scheme isEqual: @"ht+tp"] && [IRI4.scheme isEqual: @"file"] && + [IRI9.scheme isEqual: @"file"] && [IRI10.scheme isEqual: @"file"] && + [IRI11.scheme isEqual: @"http"]) + + TEST(@"-[user]", [IRI1.user isEqual: @"us:er"] && IRI4.user == nil && + IRI10.user == nil && IRI11.user == nil) + TEST(@"-[password]", + [IRI1.password isEqual: @"p@w"] && IRI4.password == nil && + IRI10.password == nil && IRI11.password == nil) + TEST(@"-[host]", [IRI1.host isEqual: @"ho:st"] && + [IRI6.host isEqual: @"12:34::56:abcd"] && + [IRI7.host isEqual: @"12:34::56:abcd"] && + IRI8.host == nil && IRI9.host == nil && IRI10.host == nil && + [IRI11.host isEqual: @"ä"]) + TEST(@"-[port]", IRI1.port.unsignedShortValue == 1234 && + [IRI4 port] == nil && IRI7.port.unsignedShortValue == 234 && + IRI8.port == nil && IRI9.port == nil && IRI10.port == nil && + IRI11.port == nil) + TEST(@"-[path]", + [IRI1.path isEqual: @"/pa?th"] && + [IRI4.path isEqual: @"/etc/passwd"] && + [IRI8.path isEqual: @"qux:foo"] && + [IRI9.path isEqual: @"/foo"] && + [IRI10.path isEqual: @"foo@bar/qux"] && + [IRI11.path isEqual: @"/ö"]) + TEST(@"-[pathComponents]", + [IRI1.pathComponents isEqual: + [OFArray arrayWithObjects: @"/", @"pa?th", nil]] && + [IRI4.pathComponents isEqual: + [OFArray arrayWithObjects: @"/", @"etc", @"passwd", nil]] && + [IRI5.pathComponents isEqual: + [OFArray arrayWithObjects: @"/", @"bar", @"qux", @"foo/bar", nil]]) + TEST(@"-[lastPathComponent]", + [[[OFIRI IRIWithString: @"http://host/foo//bar/baz"] + lastPathComponent] isEqual: @"baz"] && + [[[OFIRI IRIWithString: @"http://host/foo//bar/baz/"] + lastPathComponent] isEqual: @"baz"] && + [[[OFIRI IRIWithString: @"http://host/foo/"] + lastPathComponent] isEqual: @"foo"] && + [[[OFIRI IRIWithString: @"http://host/"] + lastPathComponent] isEqual: @"/"] && + [IRI5.lastPathComponent isEqual: @"foo/bar"]) + TEST(@"-[query]", + [IRI1.query isEqual: @"que#ry=1&f&oo=b=ar"] && IRI4.query == nil && + [IRI9.query isEqual: @"query"] && [IRI10.query isEqual: @"query"] && + [IRI11.query isEqual: @"ü"]) + TEST(@"-[queryItems]", + [IRI1.queryItems isEqual: [OFArray arrayWithObjects: + [OFPair pairWithFirstObject: @"que#ry" secondObject: @"1"], + [OFPair pairWithFirstObject: @"f&oo" secondObject: @"b=ar"], nil]]); + TEST(@"-[fragment]", + [IRI1.fragment isEqual: @"frag#ment"] && IRI4.fragment == nil && + [IRI9.fragment isEqual: @"frag"] && + [IRI10.fragment isEqual: @"frag"]) + + TEST(@"-[copy]", R(IRI4 = [[IRI1 copy] autorelease])) + + TEST(@"-[isEqual:]", [IRI1 isEqual: IRI4] && ![IRI2 isEqual: IRI3] && + [[OFIRI IRIWithString: @"HTTP://bar/"] isEqual: IRI3]) + + TEST(@"-[hash:]", IRI1.hash == IRI4.hash && IRI2.hash != IRI3.hash) + + EXPECT_EXCEPTION(@"Detection of invalid format", + OFInvalidFormatException, [OFIRI IRIWithString: @"http"]) + + TEST(@"-[IRIByAddingPercentEncodingForUnicodeCharacters]", + [IRI11.IRIByAddingPercentEncodingForUnicodeCharacters + isEqual: [OFIRI IRIWithString: @"http://%C3%A4/%C3%B6?%C3%BC"]]) + + mutableIRI = [OFMutableIRI IRIWithScheme: @"dummy"]; + + EXPECT_EXCEPTION( + @"-[setPercentEncodedScheme:] with invalid characters fails", + OFInvalidFormatException, mutableIRI.scheme = @"%20") + + TEST(@"-[setHost:]", + (mutableIRI.host = @"ho:st") && + [mutableIRI.percentEncodedHost isEqual: @"ho%3Ast"] && + (mutableIRI.host = @"12:34:ab") && + [mutableIRI.percentEncodedHost isEqual: @"[12:34:ab]"] && + (mutableIRI.host = @"12:34:aB") && + [mutableIRI.percentEncodedHost isEqual: @"[12:34:aB]"] && + (mutableIRI.host = @"12:34:g") && + [mutableIRI.percentEncodedHost isEqual: @"12%3A34%3Ag"]) + + TEST(@"-[setPercentEncodedHost:]", + (mutableIRI.percentEncodedHost = @"ho%3Ast") && + [mutableIRI.host isEqual: @"ho:st"] && + (mutableIRI.percentEncodedHost = @"[12:34]") && + [mutableIRI.host isEqual: @"12:34"] && + (mutableIRI.percentEncodedHost = @"[12::ab]") && + [mutableIRI.host isEqual: @"12::ab"]) + + EXPECT_EXCEPTION( + @"-[setPercentEncodedHost:] with invalid characters fails #1", + OFInvalidFormatException, + mutableIRI.percentEncodedHost = @"/") + + EXPECT_EXCEPTION( + @"-[setPercentEncodedHost:] with invalid characters fails #2", + OFInvalidFormatException, + mutableIRI.percentEncodedHost = @"[12:34") + + EXPECT_EXCEPTION( + @"-[setPercentEncodedHost:] with invalid characters fails #3", + OFInvalidFormatException, + mutableIRI.percentEncodedHost = @"[a::g]") + + TEST(@"-[setUser:]", + (mutableIRI.user = @"us:er") && + [mutableIRI.percentEncodedUser isEqual: @"us%3Aer"]) + + TEST(@"-[setPercentEncodedUser:]", + (mutableIRI.percentEncodedUser = @"us%3Aer") && + [mutableIRI.user isEqual: @"us:er"]) + + EXPECT_EXCEPTION( + @"-[setPercentEncodedUser:] with invalid characters fails", + OFInvalidFormatException, + mutableIRI.percentEncodedHost = @"/") + + TEST(@"-[setPassword:]", + (mutableIRI.password = @"pass:word") && + [mutableIRI.percentEncodedPassword isEqual: @"pass%3Aword"]) + + TEST(@"-[setPercentEncodedPassword:]", + (mutableIRI.percentEncodedPassword = @"pass%3Aword") && + [mutableIRI.password isEqual: @"pass:word"]) + + EXPECT_EXCEPTION( + @"-[setPercentEncodedPassword:] with invalid characters fails", + OFInvalidFormatException, + mutableIRI.percentEncodedPassword = @"/") + + TEST(@"-[setPath:]", + (mutableIRI.path = @"pa/th@?") && + [mutableIRI.percentEncodedPath isEqual: @"pa/th@%3F"]) + + TEST(@"-[setPercentEncodedPath:]", + (mutableIRI.percentEncodedPath = @"pa/th@%3F") && + [mutableIRI.path isEqual: @"pa/th@?"]) + + EXPECT_EXCEPTION( + @"-[setPercentEncodedPath:] with invalid characters fails", + OFInvalidFormatException, + mutableIRI.percentEncodedPath = @"?") + + TEST(@"-[setQuery:]", + (mutableIRI.query = @"que/ry?#") && + [mutableIRI.percentEncodedQuery isEqual: @"que/ry?%23"]) + + TEST(@"-[setPercentEncodedQuery:]", + (mutableIRI.percentEncodedQuery = @"que/ry?%23") && + [mutableIRI.query isEqual: @"que/ry?#"]) + + EXPECT_EXCEPTION( + @"-[setPercentEncodedQuery:] with invalid characters fails", + OFInvalidFormatException, + mutableIRI.percentEncodedQuery = @"`") + + TEST(@"-[setQueryItems:]", + (mutableIRI.queryItems = [OFArray arrayWithObjects: + [OFPair pairWithFirstObject: @"foo&bar" secondObject: @"baz=qux"], + [OFPair pairWithFirstObject: @"f=oobar" secondObject: @"b&azqux"], + nil]) && [mutableIRI.percentEncodedQuery isEqual: + @"foo%26bar=baz%3Dqux&f%3Doobar=b%26azqux"]) + + TEST(@"-[setFragment:]", + (mutableIRI.fragment = @"frag/ment?#") && + [mutableIRI.percentEncodedFragment isEqual: @"frag/ment?%23"]) + + TEST(@"-[setPercentEncodedFragment:]", + (mutableIRI.percentEncodedFragment = @"frag/ment?%23") && + [mutableIRI.fragment isEqual: @"frag/ment?#"]) + + EXPECT_EXCEPTION( + @"-[setPercentEncodedFragment:] with invalid characters fails", + OFInvalidFormatException, + mutableIRI.percentEncodedFragment = @"`") + + TEST(@"-[IRIByAppendingPathComponent:isDirectory:]", + [[[OFIRI IRIWithString: @"file:///foo/bar"] + IRIByAppendingPathComponent: @"qux" isDirectory: false] isEqual: + [OFIRI IRIWithString: @"file:///foo/bar/qux"]] && + [[[OFIRI IRIWithString: @"file:///foo/bar/"] + IRIByAppendingPathComponent: @"qux" isDirectory: false] isEqual: + [OFIRI IRIWithString: @"file:///foo/bar/qux"]] && + [[[OFIRI IRIWithString: @"file:///foo/bar/"] + IRIByAppendingPathComponent: @"qu?x" isDirectory: false] isEqual: + [OFIRI IRIWithString: @"file:///foo/bar/qu%3Fx"]] && + [[[OFIRI IRIWithString: @"file:///foo/bar/"] + IRIByAppendingPathComponent: @"qu?x" isDirectory: true] isEqual: + [OFIRI IRIWithString: @"file:///foo/bar/qu%3Fx/"]]) + + TEST(@"-[IRIByStandardizingPath]", + [[[OFIRI IRIWithString: @"http://foo/bar/.."] + IRIByStandardizingPath] isEqual: + [OFIRI IRIWithString: @"http://foo/"]] && + [[[OFIRI IRIWithString: @"http://foo/bar/%2E%2E/../qux/"] + IRIByStandardizingPath] isEqual: + [OFIRI IRIWithString: @"http://foo/bar/qux/"]] && + [[[OFIRI IRIWithString: @"http://foo/bar/./././qux/./"] + IRIByStandardizingPath] isEqual: + [OFIRI IRIWithString: @"http://foo/bar/qux/"]] && + [[[OFIRI IRIWithString: @"http://foo/bar/../../qux"] + IRIByStandardizingPath] isEqual: + [OFIRI IRIWithString: @"http://foo/../qux"]]) + + objc_autoreleasePoolPop(pool); +} +@end Index: tests/OFInvocationTests.m ================================================================== --- tests/OFInvocationTests.m +++ tests/OFInvocationTests.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,11 +13,10 @@ * file. */ #include "config.h" -#include #include #if defined(HAVE_COMPLEX_H) && !defined(__STDC_NO_COMPLEX__) # include #endif @@ -57,14 +56,10 @@ st.i = 0xAAAAAAAA; TEST(@"+[invocationWithMethodSignature:]", (invocation = [OFInvocation invocationWithMethodSignature: sig])) -#ifdef __clang_analyzer__ - assert(invocation != nil); -#endif - TEST(@"-[setReturnValue]", R([invocation setReturnValue: &st])) TEST(@"-[getReturnValue]", R([invocation getReturnValue: &st2]) && memcmp(&st, &st2, sizeof(st)) == 0) Index: tests/OFJSONTests.m ================================================================== --- tests/OFJSONTests.m +++ tests/OFJSONTests.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,20 +51,21 @@ - (instancetype)initWithTestsAppDelegate: (TestsAppDelegate *)testsAppDelegate { self = [super init]; @try { - uint16_t port; + OFSocketAddress address; _testsAppDelegate = testsAppDelegate; _server = [[OFTCPSocket alloc] init]; - port = [_server bindToHost: @"127.0.0.1" port: 0]; + address = [_server bindToHost: @"127.0.0.1" port: 0]; [_server listen]; _client = [[OFTCPSocket alloc] init]; - [_client connectToHost: @"127.0.0.1" port: port]; + [_client connectToHost: @"127.0.0.1" + port: OFSocketAddressIPPort(&address)]; [_client writeBuffer: "0" length: 1]; } @catch (id e) { [self release]; @throw e; } Index: tests/OFListTests.m ================================================================== --- tests/OFListTests.m +++ tests/OFListTests.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,12 +27,12 @@ @implementation TestsAppDelegate (OFMD5HashTests) - (void)MD5HashTests { void *pool = objc_autoreleasePoolPush(); OFMD5Hash *MD5, *MD5Copy; - OFURI *URI = [OFURI URIWithString: @"embedded:testfile.bin"]; - OFStream *file = [OFURIHandler openItemAtURI: URI mode: @"r"]; + OFIRI *IRI = [OFIRI IRIWithString: @"embedded:testfile.bin"]; + OFStream *file = [OFIRIHandler openItemAtIRI: IRI mode: @"r"]; TEST(@"+[hashWithAllowsSwappableMemory:]", (MD5 = [OFMD5Hash hashWithAllowsSwappableMemory: true])) while (!file.atEndOfStream) { ADDED tests/OFMatrix4x4Tests.m Index: tests/OFMatrix4x4Tests.m ================================================================== --- /dev/null +++ tests/OFMatrix4x4Tests.m @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2008-2024 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#include "config.h" + +#import "TestsAppDelegate.h" + +static OFString *const module = @"OFMatrix4x4Tests"; + +@implementation TestsAppDelegate (OFMatrix4x4Tests) +- (void)matrix4x4Tests +{ + void *pool = objc_autoreleasePoolPush(); + OFMatrix4x4 *matrix, *matrix2; + OFVector4D point; + OFVector4D points[2] = {{ 1, 2, 3, 1 }, { 7, 8, 9, 2 }}; + + TEST(@"+[identityMatrix]", + memcmp([[OFMatrix4x4 identityMatrix] values], (const float [4][4]){ + { 1, 0, 0, 0 }, + { 0, 1, 0, 0 }, + { 0, 0, 1, 0 }, + { 0, 0, 0, 1 } + }, 16 * sizeof(float)) == 0) + + TEST(@"+[matrixWithValues:]", + (matrix = [OFMatrix4x4 matrixWithValues: (const float [4][4]){ + { 1, 2, 3, 4 }, + { 5, 6, 7, 8 }, + { 9, 10, 11, 12 }, + { 13, 14, 15, 16 } + }])) + + TEST(@"-[description]", + [matrix.description isEqual: @""]) + + TEST(@"-[isEqual:]", [[OFMatrix4x4 identityMatrix] isEqual: + [OFMatrix4x4 matrixWithValues: (const float [4][4]){ + { 1, 0, 0, 0 }, + { 0, 1, 0, 0 }, + { 0, 0, 1, 0 }, + { 0, 0, 0, 1 } + }]]) + + TEST(@"-[copy]", (matrix2 = [[matrix copy] autorelease]) && + [matrix2 isEqual: matrix]) + + TEST(@"-[multiplyWithMatrix:] #1", + R([matrix2 multiplyWithMatrix: [OFMatrix4x4 identityMatrix]]) && + [matrix2 isEqual: matrix]) + + matrix2 = [OFMatrix4x4 matrixWithValues: (const float [4][4]){ + { 100, 200, 300, 400 }, + { 500, 600, 700, 800 }, + { 900, 1000, 1100, 1200 }, + { 1300, 1400, 1500, 1600 } + }]; + TEST(@"-[multiplyWithMatrix:] #2", + R([matrix2 multiplyWithMatrix: matrix]) && + [matrix2 isEqual: + [OFMatrix4x4 matrixWithValues: (const float [4][4]){ + { 9000, 10000, 11000, 12000 }, + { 20200, 22800, 25400, 28000 }, + { 31400, 35600, 39800, 44000 }, + { 42600, 48400, 54200, 60000 } + }]]) + + TEST(@"-[translateWithVector:]", + (matrix2 = [OFMatrix4x4 identityMatrix]) && + R([matrix2 translateWithVector: OFMakeVector3D(1, 2, 3)]) && + R(point = + [matrix2 transformedVector: OFMakeVector4D(2, 3, 4, 1)]) && + point.x == 3 && point.y == 5 && point.z == 7 && point.w == 1) + + TEST(@"-[scaleWithVector:]", + R([matrix2 scaleWithVector: OFMakeVector3D(-1, 0.5f, 2)]) && + R(point = + [matrix2 transformedVector: OFMakeVector4D(2, 3, 4, 1)]) && + point.x == -3 && point.y == 2.5 && point.z == 14 && point.w == 1) + + TEST(@"-[transformVectors:count:]", + R([matrix transformVectors: points count: 2]) && + points[0].x == 18 && points[0].y == 46 && points[0].z == 74 && + points[0].w == 102 && points[1].x == 58 && points[1].y == 162 && + points[1].z == 266 && points[1].w == 370) + + objc_autoreleasePoolPop(pool); +} +@end Index: tests/OFMemoryStreamTests.m ================================================================== --- tests/OFMemoryStreamTests.m +++ tests/OFMemoryStreamTests.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may 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/OFMethodSignatureTests.m ================================================================== --- tests/OFMethodSignatureTests.m +++ tests/OFMethodSignatureTests.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may 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/OFNotificationCenterTests.m ================================================================== --- tests/OFNotificationCenterTests.m +++ tests/OFNotificationCenterTests.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,11 +107,11 @@ test1->_received == 1 && test2->_received == 3 && test3->_received == 0 && test4->_received == 0) #ifdef OF_HAVE_BLOCKS __block bool received = false; - OFNotificationCenterHandle *handle; + id handle; notification = [OFNotification notificationWithName: notificationName object: self]; TEST(@"-[addObserverForName:object:usingBlock:]", (handle = [center addObserverForName: notificationName Index: tests/OFNumberTests.m ================================================================== --- tests/OFNumberTests.m +++ tests/OFNumberTests.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may 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/OFPropertyListTests.m ================================================================== --- tests/OFPropertyListTests.m +++ tests/OFPropertyListTests.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,12 +28,12 @@ @implementation TestsAppDelegate (OFRIPEMD160HashTests) - (void)RIPEMD160HashTests { void *pool = objc_autoreleasePoolPush(); OFRIPEMD160Hash *RIPEMD160, *RIPEMD160Copy; - OFURI *URI = [OFURI URIWithString: @"embedded:testfile.bin"]; - OFStream *file = [OFURIHandler openItemAtURI: URI mode: @"r"]; + OFIRI *IRI = [OFIRI IRIWithString: @"embedded:testfile.bin"]; + OFStream *file = [OFIRIHandler openItemAtIRI: IRI mode: @"r"]; TEST(@"+[hashWithAllowsSwappableMemory:]", (RIPEMD160 = [OFRIPEMD160Hash hashWithAllowsSwappableMemory: true])) while (!file.atEndOfStream) { Index: tests/OFSHA1HashTests.m ================================================================== --- tests/OFSHA1HashTests.m +++ tests/OFSHA1HashTests.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,12 +28,12 @@ @implementation TestsAppDelegate (SHA1HashTests) - (void)SHA1HashTests { void *pool = objc_autoreleasePoolPush(); OFSHA1Hash *SHA1, *SHA1Copy; - OFURI *URI = [OFURI URIWithString: @"embedded:testfile.bin"]; - OFStream *file = [OFURIHandler openItemAtURI: URI mode: @"r"]; + OFIRI *IRI = [OFIRI IRIWithString: @"embedded:testfile.bin"]; + OFStream *file = [OFIRIHandler openItemAtIRI: IRI mode: @"r"]; TEST(@"+[hashWithAllowsSwappableMemory:]", (SHA1 = [OFSHA1Hash hashWithAllowsSwappableMemory: true])) while (!file.atEndOfStream) { Index: tests/OFSHA224HashTests.m ================================================================== --- tests/OFSHA224HashTests.m +++ tests/OFSHA224HashTests.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,12 +28,12 @@ @implementation TestsAppDelegate (SHA224HashTests) - (void)SHA224HashTests { void *pool = objc_autoreleasePoolPush(); OFSHA224Hash *SHA224, *SHA224Copy; - OFURI *URI = [OFURI URIWithString: @"embedded:testfile.bin"]; - OFStream *file = [OFURIHandler openItemAtURI: URI mode: @"r"]; + OFIRI *IRI = [OFIRI IRIWithString: @"embedded:testfile.bin"]; + OFStream *file = [OFIRIHandler openItemAtIRI: IRI mode: @"r"]; TEST(@"+[hashWithAllowsSwappableMemory:]", (SHA224 = [OFSHA224Hash hashWithAllowsSwappableMemory: true])) while (!file.atEndOfStream) { Index: tests/OFSHA256HashTests.m ================================================================== --- tests/OFSHA256HashTests.m +++ tests/OFSHA256HashTests.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,12 +28,12 @@ @implementation TestsAppDelegate (SHA256HashTests) - (void)SHA256HashTests { void *pool = objc_autoreleasePoolPush(); OFSHA256Hash *SHA256, *SHA256Copy; - OFURI *URI = [OFURI URIWithString: @"embedded:testfile.bin"]; - OFStream *file = [OFURIHandler openItemAtURI: URI mode: @"r"]; + OFIRI *IRI = [OFIRI IRIWithString: @"embedded:testfile.bin"]; + OFStream *file = [OFIRIHandler openItemAtIRI: IRI mode: @"r"]; TEST(@"+[hashWithAllowsSwappableMemory:]", (SHA256 = [OFSHA256Hash hashWithAllowsSwappableMemory: true])) while (!file.atEndOfStream) { Index: tests/OFSHA384HashTests.m ================================================================== --- tests/OFSHA384HashTests.m +++ tests/OFSHA384HashTests.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,12 +29,12 @@ @implementation TestsAppDelegate (SHA384HashTests) - (void)SHA384HashTests { void *pool = objc_autoreleasePoolPush(); OFSHA384Hash *SHA384, *SHA384Copy; - OFURI *URI = [OFURI URIWithString: @"embedded:testfile.bin"]; - OFStream *file = [OFURIHandler openItemAtURI: URI mode: @"r"]; + OFIRI *IRI = [OFIRI IRIWithString: @"embedded:testfile.bin"]; + OFStream *file = [OFIRIHandler openItemAtIRI: IRI mode: @"r"]; TEST(@"+[hashWithAllowsSwappableMemory:]", (SHA384 = [OFSHA384Hash hashWithAllowsSwappableMemory: true])) while (!file.atEndOfStream) { Index: tests/OFSHA512HashTests.m ================================================================== --- tests/OFSHA512HashTests.m +++ tests/OFSHA512HashTests.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,12 +30,12 @@ @implementation TestsAppDelegate (SHA512HashTests) - (void)SHA512HashTests { void *pool = objc_autoreleasePoolPush(); OFSHA512Hash *SHA512, *SHA512Copy; - OFURI *URI = [OFURI URIWithString: @"embedded:testfile.bin"]; - OFStream *file = [OFURIHandler openItemAtURI: URI mode: @"r"]; + OFIRI *IRI = [OFIRI IRIWithString: @"embedded:testfile.bin"]; + OFStream *file = [OFIRIHandler openItemAtIRI: IRI mode: @"r"]; TEST(@"+[hashWithAllowsSwappableMemory:]", (SHA512 = [OFSHA512Hash hashWithAllowsSwappableMemory: true])) while (!file.atEndOfStream) { Index: tests/OFSPXSocketTests.m ================================================================== --- tests/OFSPXSocketTests.m +++ tests/OFSPXSocketTests.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,11 @@ OFSocketAddress address1; const OFSocketAddress *address2; uint32_t network; unsigned char node[IPX_NODE_LEN], node2[IPX_NODE_LEN]; uint16_t port; + OFDictionary *networkInterfaces; char buffer[5]; SPXSocketDelegate *delegate; TEST(@"+[socket]", (sockClient = [OFSPXSocket socket]) && (sockServer = [OFSPXSocket socket])) @@ -121,10 +122,28 @@ network = OFSocketAddressIPXNetwork(&address1); OFSocketAddressGetIPXNode(&address1, node); port = OFSocketAddressIPXPort(&address1); TEST(@"-[listen]", R([sockServer listen])) + + /* + * Find any network interface with IPX and send to it. Any should be + * fine since we bound to 0.0. + */ + networkInterfaces = [OFSystemInfo networkInterfaces]; + for (OFString *name in networkInterfaces) { + OFNetworkInterface interface = [networkInterfaces + objectForKey: name]; + OFData *addresses = [interface + objectForKey: OFNetworkInterfaceIPXAddresses]; + + if (addresses.count == 0) + continue; + + network = OFSocketAddressIPXNetwork([addresses itemAtIndex: 0]); + OFSocketAddressGetIPXNode([addresses itemAtIndex: 0], node); + } TEST(@"-[connectToNetwork:node:port:]", R([sockClient connectToNetwork: network node: node port: port])) TEST(@"-[accept]", (sockAccepted = [sockServer accept])) @@ -136,11 +155,10 @@ [sockClient receiveIntoBuffer: buffer length: 5] == 5 && memcmp(buffer, "Hello", 5) == 0) TEST(@"-[remoteAddress]", (address2 = sockAccepted.remoteAddress) && - OFSocketAddressIPXNetwork(address2) == network && R(OFSocketAddressGetIPXNode(address2, node2)) && memcmp(node, node2, IPX_NODE_LEN) == 0) delegate = [[[SPXSocketDelegate alloc] init] autorelease]; @@ -171,10 +189,17 @@ [OFDate dateWithTimeIntervalSinceNow: 2]]; TEST(@"-[asyncAccept] & -[asyncConnectToNetwork:node:port:]", delegate->_accepted && delegate->_connected) } @catch (OFObserveKernelEventsFailedException *e) { + /* + * Make sure it doesn't stay in the run loop and throws again + * next time we run the run loop. + */ + [sockClient cancelAsyncRequests]; + [sockServer cancelAsyncRequests]; + switch (e.errNo) { case ENOTSOCK: [OFStdOut setForegroundColor: [OFColor lime]]; [OFStdOut writeLine: @"\r[OFSPXSocket] -[asyncAccept] & " Index: tests/OFSPXStreamSocketTests.m ================================================================== --- tests/OFSPXStreamSocketTests.m +++ tests/OFSPXStreamSocketTests.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,11 @@ OFSocketAddress address1; const OFSocketAddress *address2; uint32_t network; unsigned char node[IPX_NODE_LEN], node2[IPX_NODE_LEN]; uint16_t port; + OFDictionary *networkInterfaces; char buffer[5]; SPXStreamSocketDelegate *delegate; TEST(@"+[socket]", (sockClient = [OFSPXStreamSocket socket]) && (sockServer = [OFSPXStreamSocket socket])) @@ -122,10 +123,28 @@ network = OFSocketAddressIPXNetwork(&address1); OFSocketAddressGetIPXNode(&address1, node); port = OFSocketAddressIPXPort(&address1); TEST(@"-[listen]", R([sockServer listen])) + + /* + * Find any network interface with IPX and send to it. Any should be + * fine since we bound to 0.0. + */ + networkInterfaces = [OFSystemInfo networkInterfaces]; + for (OFString *name in networkInterfaces) { + OFNetworkInterface interface = [networkInterfaces + objectForKey: name]; + OFData *addresses = [interface + objectForKey: OFNetworkInterfaceIPXAddresses]; + + if (addresses.count == 0) + continue; + + network = OFSocketAddressIPXNetwork([addresses itemAtIndex: 0]); + OFSocketAddressGetIPXNode([addresses itemAtIndex: 0], node); + } TEST(@"-[connectToNetwork:node:port:]", R([sockClient connectToNetwork: network node: node port: port])) TEST(@"-[accept]", (sockAccepted = [sockServer accept])) @@ -140,11 +159,10 @@ [sockClient readIntoBuffer: buffer length: 3] == 3 && memcmp(buffer, "llo", 3) == 0) TEST(@"-[remoteAddress]", (address2 = sockAccepted.remoteAddress) && - OFSocketAddressIPXNetwork(address2) == network && R(OFSocketAddressGetIPXNode(address2, node2)) && memcmp(node, node2, IPX_NODE_LEN) == 0) delegate = [[[SPXStreamSocketDelegate alloc] init] autorelease]; @@ -175,10 +193,17 @@ [OFDate dateWithTimeIntervalSinceNow: 2]]; TEST(@"-[asyncAccept] & -[asyncConnectToNetwork:node:port:]", delegate->_accepted && delegate->_connected) } @catch (OFObserveKernelEventsFailedException *e) { + /* + * Make sure it doesn't stay in the run loop and throws again + * next time we run the run loop. + */ + [sockClient cancelAsyncRequests]; + [sockServer cancelAsyncRequests]; + switch (e.errNo) { case ENOTSOCK: [OFStdOut setForegroundColor: [OFColor lime]]; [OFStdOut writeLine: @"\r[OFSPXStreamSocket] -[asyncAccept] & " Index: tests/OFScryptTests.m ================================================================== --- tests/OFScryptTests.m +++ tests/OFScryptTests.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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 tests/OFSerializationTests.m Index: tests/OFSerializationTests.m ================================================================== --- tests/OFSerializationTests.m +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (c) 2008-2022 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#include "config.h" - -#import "TestsAppDelegate.h" - -static OFString *const module = @"OFSerialization"; - -@implementation TestsAppDelegate (OFSerializationTests) -- (void)serializationTests -{ - void *pool = objc_autoreleasePoolPush(); - OFMutableDictionary *dict = [OFMutableDictionary dictionary]; - OFMutableArray *array = [OFMutableArray array]; - OFList *list = [OFList list]; - OFData *data; - OFString *string; - OFUUID *UUID; - - [array addObject: @"Qu\"xbar\ntest"]; - [array addObject: [OFNumber numberWithInt: 1234]]; - [array addObject: [OFNumber numberWithDouble: 1234.5678]]; - [array addObject: [OFMutableString stringWithString: @"asd"]]; - [array addObject: [OFDate dateWithTimeIntervalSince1970: 1234.5678]]; - - [dict setObject: @"Hello" forKey: array]; - [dict setObject: @"B\"la" forKey: @"Blub"]; - - [list appendObject: @"Hello"]; - [list appendObject: @"Wo\rld!\nHow are you?"]; - [list appendObject: [OFURI URIWithString: @"https://objfw.nil.im/"]]; - [list appendObject: - [OFXMLElement elementWithXMLString: @""]]; - [list appendObject: - [OFSet setWithObjects: @"foo", @"foo", @"bar", nil]]; - [list appendObject: - [OFCountedSet setWithObjects: @"foo", @"foo", @"bar", nil]]; - - [dict setObject: @"list" forKey: list]; - - data = [OFData dataWithItems: "0123456789:; + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,12 +16,12 @@ #include "config.h" #import "TestsAppDelegate.h" #import "OFSet.h" -#import "OFMapTableSet.h" -#import "OFMutableMapTableSet.h" +#import "OFConcreteSet.h" +#import "OFConcreteMutableSet.h" static OFString *module; @interface SimpleSet: OFSet { @@ -286,10 +286,10 @@ { module = @"OFSet"; [self setTestsWithClass: [SimpleSet class] mutableClass: [SimpleMutableSet class]]; - module = @"OFMapTableSet"; - [self setTestsWithClass: [OFMapTableSet class] - mutableClass: [OFMutableMapTableSet class]]; + module = @"OFConcreteSet"; + [self setTestsWithClass: [OFConcreteSet class] + mutableClass: [OFConcreteMutableSet class]]; } @end Index: tests/OFSocketTests.m ================================================================== --- tests/OFSocketTests.m +++ tests/OFSocketTests.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -113,10 +113,26 @@ TEST(@"Parsing an IPv6 #5", R(addr = OFSocketAddressParseIP(@"::aaAa", 1234)) && COMPARE_V6(addr, 0, 0, 0, 0, 0, 0, 0, 0xAAAA) && OFFromBigEndian16(addr.sockaddr.in6.sin6_port) == 1234) + TEST(@"Parsing an IPv6 #6", + R(addr = OFSocketAddressParseIP(@"fd00::1%123", 1234)) && + COMPARE_V6(addr, 0xFD00, 0, 0, 0, 0, 0, 0, 1) && + OFFromBigEndian16(addr.sockaddr.in6.sin6_port) == 1234 && + addr.sockaddr.in6.sin6_scope_id == 123) + + TEST(@"Parsing an IPv6 #7", + R(addr = OFSocketAddressParseIP(@"::ffff:127.0.0.1", 1234)) && + COMPARE_V6(addr, 0, 0, 0, 0, 0, 0xFFFF, 0x7F00, 1) && + OFFromBigEndian16(addr.sockaddr.in6.sin6_port) == 1234) + + TEST(@"Parsing an IPv6 #8", + R(addr = OFSocketAddressParseIP(@"64:ff9b::127.0.0.1", 1234)) && + COMPARE_V6(addr, 0x64, 0xFF9B, 0, 0, 0, 0, 0x7F00, 1) && + OFFromBigEndian16(addr.sockaddr.in6.sin6_port) == 1234) + EXPECT_EXCEPTION(@"Refusing invalid IPv6 #1", OFInvalidFormatException, OFSocketAddressParseIP(@"1:::2", 1234)) EXPECT_EXCEPTION(@"Refusing invalid IPv6 #2", OFInvalidFormatException, OFSocketAddressParseIP(@"1: ::2", 1234)) @@ -144,10 +160,12 @@ EXPECT_EXCEPTION(@"Refusing invalid IPv6 #10", OFInvalidFormatException, OFSocketAddressParseIP(@"1:2", 1234)) TEST(@"Port of an IPv6 address", OFSocketAddressIPPort(&addr) == 1234) + + addr.sockaddr.in6.sin6_scope_id = 0; SET_V6(addr, 0, 0, 0, 0, 0, 0, 0, 0) TEST(@"Converting an IPv6 to a string #1", [OFSocketAddressString(&addr) isEqual: @"::"]) Index: tests/OFStreamTests.m ================================================================== --- tests/OFStreamTests.m +++ tests/OFStreamTests.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -355,12 +355,12 @@ TEST(@"+[stringWithContentsOfFile:encoding]", (string = [stringClass stringWithContentsOfFile: @"testfile.txt" encoding: OFStringEncodingISO8859_1]) && [string isEqual: @"testäöü"]) - TEST(@"+[stringWithContentsOfURI:encoding]", (string = [stringClass - stringWithContentsOfURI: [OFURI fileURIWithPath: @"testfile.txt"] + TEST(@"+[stringWithContentsOfIRI:encoding]", (string = [stringClass + stringWithContentsOfIRI: [OFIRI fileIRIWithPath: @"testfile.txt"] encoding: OFStringEncodingISO8859_1]) && [string isEqual: @"testäöü"]) #endif TEST(@"-[appendUTFString:length:]", @@ -1154,11 +1154,11 @@ # if (!defined(OF_SOLARIS) || !defined(OF_X86)) && !defined(OF_AMIGAOS_M68K) # define INPUT @"\t-0.123456789 " # define EXPECTED -0.123456789 # else /* - * Solaris' strtod() has weird rounding on x86, but not on x86_64. + * Solaris' strtod() has weird rounding on x86, but not on AMD64. * AmigaOS 3 with libnix has weird rounding as well. */ # define INPUT @"\t-0.125 " # define EXPECTED -0.125 # endif @@ -1405,20 +1405,10 @@ (mutableString1 = [mutableStringClass stringWithString: whitespace[1]]) && R([mutableString1 deleteEnclosingWhitespaces]) && [mutableString1 isEqual: @""]) -#ifdef OF_HAVE_UNICODE_TABLES - TEST(@"-[decomposedStringWithCanonicalMapping]", - [C(@"H\xC3\xA4llj\xC3\xB6").decomposedStringWithCanonicalMapping - isEqual: @"H\x61\xCC\x88llj\x6F\xCC\x88"]); - - TEST(@"-[decomposedStringWithCompatibilityMapping]", - [C(@"H\xC3\xA4llj\xC3\xB6").decomposedStringWithCompatibilityMapping - isEqual: @"H\x61\xCC\x88llj\x6F\xCC\x88"]); -#endif - TEST(@"-[stringByXMLEscaping]", (string = C(@" &world'\"!&").stringByXMLEscaping) && [string isEqual: @"<hello> &world'"!&"]) TEST(@"-[stringByXMLUnescaping]", Index: tests/OFSystemInfoTests.m ================================================================== --- tests/OFSystemInfoTests.m +++ tests/OFSystemInfoTests.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,15 +14,38 @@ */ #include "config.h" #import "TestsAppDelegate.h" + +#ifdef OF_HAVE_SOCKETS +static void +printAddresses(OFData *addresses, bool *firstAddress) +{ + size_t count = addresses.count; + + for (size_t i = 0; i < count; i++) { + const OFSocketAddress *address = [addresses itemAtIndex: i]; + + if (!*firstAddress) + [OFStdOut writeString: @", "]; + + *firstAddress = false; + + [OFStdOut writeString: OFSocketAddressString(address)]; + } +} +#endif @implementation TestsAppDelegate (OFSystemInfoTests) - (void)systemInfoTests { void *pool = objc_autoreleasePoolPush(); +#ifdef OF_HAVE_SOCKETS + OFDictionary *networkInterfaces; + bool firstInterface = true; +#endif [OFStdOut setForegroundColor: [OFColor lime]]; [OFStdOut writeFormat: @"[OFSystemInfo] Page size: %zd\n", [OFSystemInfo pageSize]]; @@ -44,28 +67,34 @@ [OFStdOut writeFormat: @"[OFSystemInfo] Operating system version: %@\n", [OFSystemInfo operatingSystemVersion]]; - [OFStdOut writeFormat: @"[OFSystemInfo] User config URI: %@\n", - [OFSystemInfo userConfigURI].string]; - - [OFStdOut writeFormat: @"[OFSystemInfo] User data URI: %@\n", - [OFSystemInfo userDataURI].string]; - - [OFStdOut writeFormat: @"[OFSystemInfo] Temporary directory URI: %@\n", - [OFSystemInfo temporaryDirectoryURI].string]; + [OFStdOut writeFormat: @"[OFSystemInfo] User config IRI: %@\n", + [OFSystemInfo userConfigIRI].string]; + + [OFStdOut writeFormat: @"[OFSystemInfo] User data IRI: %@\n", + [OFSystemInfo userDataIRI].string]; + + [OFStdOut writeFormat: @"[OFSystemInfo] Temporary directory IRI: %@\n", + [OFSystemInfo temporaryDirectoryIRI].string]; [OFStdOut writeFormat: @"[OFSystemInfo] CPU vendor: %@\n", [OFSystemInfo CPUVendor]]; [OFStdOut writeFormat: @"[OFSystemInfo] CPU model: %@\n", [OFSystemInfo CPUModel]]; -#if defined(OF_X86_64) || defined(OF_X86) +#if defined(OF_AMD64) || defined(OF_X86) [OFStdOut writeFormat: @"[OFSystemInfo] Supports MMX: %d\n", [OFSystemInfo supportsMMX]]; + + [OFStdOut writeFormat: @"[OFSystemInfo] Supports 3DNow!: %d\n", + [OFSystemInfo supports3DNow]]; + + [OFStdOut writeFormat: @"[OFSystemInfo] Supports enhanced 3DNow!: %d\n", + [OFSystemInfo supportsEnhanced3DNow]]; [OFStdOut writeFormat: @"[OFSystemInfo] Supports SSE: %d\n", [OFSystemInfo supportsSSE]]; [OFStdOut writeFormat: @"[OFSystemInfo] Supports SSE2: %d\n", @@ -92,15 +121,143 @@ [OFStdOut writeFormat: @"[OFSystemInfo] Supports AES-NI: %d\n", [OFSystemInfo supportsAESNI]]; [OFStdOut writeFormat: @"[OFSystemInfo] Supports SHA extensions: %d\n", [OFSystemInfo supportsSHAExtensions]]; + + [OFStdOut writeFormat: @"[OFSystemInfo] Supports fused multiply-add: " + @"%d\n", + [OFSystemInfo supportsFusedMultiplyAdd]]; + + [OFStdOut writeFormat: @"[OFSystemInfo] Supports F16C: %d\n", + [OFSystemInfo supportsF16C]]; + + [OFStdOut writeFormat: + @"[OFSystemInfo] Supports AVX-512 Foundation: %d\n", + [OFSystemInfo supportsAVX512Foundation]]; + + [OFStdOut writeFormat: + @"[OFSystemInfo] Supports AVX-512 Conflict Detection Instructions: " + @"%d\n", + [OFSystemInfo supportsAVX512ConflictDetectionInstructions]]; + + [OFStdOut writeFormat: + @"[OFSystemInfo] Supports AVX-512 Exponential and Reciprocal " + @"Instructions: %d\n", + [OFSystemInfo supportsAVX512ExponentialAndReciprocalInstructions]]; + + [OFStdOut writeFormat: + @"[OFSystemInfo] Supports AVX-512 Prefetch Instructions: %d\n", + [OFSystemInfo supportsAVX512PrefetchInstructions]]; + + [OFStdOut writeFormat: + @"[OFSystemInfo] Supports AVX-512 Vector Length Extensions: %d\n", + [OFSystemInfo supportsAVX512VectorLengthExtensions]]; + + [OFStdOut writeFormat: + @"[OFSystemInfo] Supports AVX-512 Doubleword and Quadword " + @"Instructions: %d\n", + [OFSystemInfo supportsAVX512DoublewordAndQuadwordInstructions]]; + + [OFStdOut writeFormat: + @"[OFSystemInfo] Supports AVX-512 Byte and Word Instructions: %d\n", + [OFSystemInfo supportsAVX512ByteAndWordInstructions]]; + + [OFStdOut writeFormat: + @"[OFSystemInfo] Supports AVX-512 Integer Fused Multiply Add: %d\n", + [OFSystemInfo supportsAVX512IntegerFusedMultiplyAdd]]; + + [OFStdOut writeFormat: + @"[OFSystemInfo] Supports AVX-512 Vector Byte Manipulation " + @"Instructions: %d\n", + [OFSystemInfo supportsAVX512VectorByteManipulationInstructions]]; + + [OFStdOut writeFormat: + @"[OFSystemInfo] Supports AVX-512 Vector Population Count " + @"Instruction: %d\n", + [OFSystemInfo supportsAVX512VectorPopulationCountInstruction]]; + + [OFStdOut writeFormat: + @"[OFSystemInfo] Supports AVX-512 Vector Neutral Network " + @"Instructions: %d\n", + [OFSystemInfo supportsAVX512VectorNeuralNetworkInstructions]]; + + [OFStdOut writeFormat: + @"[OFSystemInfo] Supports AVX-512 Vector Byte Manipulation " + @"Instructions 2: %d\n", + [OFSystemInfo supportsAVX512VectorByteManipulationInstructions2]]; + + [OFStdOut writeFormat: + @"[OFSystemInfo] Supports AVX-512 Bit Algorithms: %d\n", + [OFSystemInfo supportsAVX512BitAlgorithms]]; + + [OFStdOut writeFormat: + @"[OFSystemInfo] Supports AVX-512 Float16 Instructions: %d\n", + [OFSystemInfo supportsAVX512Float16Instructions]]; + + [OFStdOut writeFormat: + @"[OFSystemInfo] Supports AVX-512 BFloat16 Instructions: %d\n", + [OFSystemInfo supportsAVX512BFloat16Instructions]]; #endif #ifdef OF_POWERPC [OFStdOut writeFormat: @"[OFSystemInfo] Supports AltiVec: %d\n", [OFSystemInfo supportsAltiVec]]; #endif + +#ifdef OF_HAVE_SOCKETS + networkInterfaces = [OFSystemInfo networkInterfaces]; + [OFStdOut writeString: @"[OFSystemInfo] Network interfaces: "]; + for (OFString *name in networkInterfaces) { + bool firstAddress = true; + OFNetworkInterface interface; + OFData *hardwareAddress; + + if (!firstInterface) + [OFStdOut writeString: @"; "]; + + firstInterface = false; + + [OFStdOut writeFormat: @"%@(", name]; + + interface = [networkInterfaces objectForKey: name]; + + printAddresses([interface objectForKey: + OFNetworkInterfaceIPv4Addresses], &firstAddress); +# ifdef OF_HAVE_IPV6 + printAddresses([interface objectForKey: + OFNetworkInterfaceIPv6Addresses], &firstAddress); +# endif +# ifdef OF_HAVE_IPX + printAddresses([interface objectForKey: + OFNetworkInterfaceIPXAddresses], &firstAddress); +# endif +# ifdef OF_HAVE_APPLETALK + printAddresses([interface objectForKey: + OFNetworkInterfaceAppleTalkAddresses], &firstAddress); +# endif + + hardwareAddress = [interface + objectForKey: OFNetworkInterfaceHardwareAddress]; + if (hardwareAddress != nil) { + const unsigned char *bytes = hardwareAddress.items; + size_t length = hardwareAddress.count; + + if (!firstAddress) + [OFStdOut writeString: @", "]; + + for (size_t i = 0; i < length; i++) { + if (i > 0) + [OFStdOut writeString: @":"]; + + [OFStdOut writeFormat: @"%02X", bytes[i]]; + } + } + + [OFStdOut writeString: @")"]; + } + [OFStdOut writeString: @"\n"]; +#endif objc_autoreleasePoolPop(pool); } @end Index: tests/OFTCPSocketTests.m ================================================================== --- tests/OFTCPSocketTests.m +++ tests/OFTCPSocketTests.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,23 +24,24 @@ @implementation TestsAppDelegate (OFTCPSocketTests) - (void)TCPSocketTests { void *pool = objc_autoreleasePoolPush(); OFTCPSocket *server, *client = nil, *accepted; - uint16_t port; + OFSocketAddress address; char buffer[6]; TEST(@"+[socket]", (server = [OFTCPSocket socket]) && (client = [OFTCPSocket socket])) TEST(@"-[bindToHost:port:]", - (port = [server bindToHost: @"127.0.0.1" port: 0])) + R(address = [server bindToHost: @"127.0.0.1" port: 0])) TEST(@"-[listen]", R([server listen])) TEST(@"-[connectToHost:port:]", - R([client connectToHost: @"127.0.0.1" port: port])) + R([client connectToHost: @"127.0.0.1" + port: OFSocketAddressIPPort(&address)])) TEST(@"-[accept]", (accepted = [server accept])) TEST(@"-[remoteAddress]", [OFSocketAddressString(accepted.remoteAddress) Index: tests/OFThreadTests.m ================================================================== --- tests/OFThreadTests.m +++ tests/OFThreadTests.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,36 +24,30 @@ @implementation TestsAppDelegate (OFUDPSocketTests) - (void)UDPSocketTests { void *pool = objc_autoreleasePoolPush(); OFUDPSocket *sock; - uint16_t port1; OFSocketAddress addr1, addr2, addr3; char buf[6]; TEST(@"+[socket]", (sock = [OFUDPSocket socket])) TEST(@"-[bindToHost:port:]", - (port1 = [sock bindToHost: @"127.0.0.1" port: 0])) - - addr1 = OFSocketAddressParseIP(@"127.0.0.1", port1); + R(addr1 = [sock bindToHost: @"127.0.0.1" port: 0])) TEST(@"-[sendBuffer:length:receiver:]", R([sock sendBuffer: "Hello" length: 6 receiver: &addr1])) TEST(@"-[receiveIntoBuffer:length:sender:]", [sock receiveIntoBuffer: buf length: 6 sender: &addr2] == 6 && !memcmp(buf, "Hello", 6) && [OFSocketAddressString(&addr2) isEqual: @"127.0.0.1"] && - OFSocketAddressIPPort(&addr2) == port1) - - addr3 = OFSocketAddressParseIP(@"127.0.0.1", port1 + 1); - - /* - * TODO: Move those tests elsewhere as soon as the DNS resolving part - * is no longer in OFUDPSocket. - */ + OFSocketAddressIPPort(&addr2) == OFSocketAddressIPPort(&addr1)) + + addr3 = OFSocketAddressParseIP(@"127.0.0.1", + OFSocketAddressIPPort(&addr1) + 1); + TEST(@"OFSocketAddressEqual()", OFSocketAddressEqual(&addr1, &addr2) && !OFSocketAddressEqual(&addr1, &addr3)) TEST(@"OFSocketAddressHash()", Index: tests/OFUNIXDatagramSocketTests.m ================================================================== --- tests/OFUNIXDatagramSocketTests.m +++ tests/OFUNIXDatagramSocketTests.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,19 +29,19 @@ OFUNIXDatagramSocket *sock; OFSocketAddress address1, address2; char buffer[5]; #if defined(OF_HAVE_FILES) && !defined(OF_IOS) - path = [[OFSystemInfo temporaryDirectoryURI] - URIByAppendingPathComponent: [[OFUUID UUID] UUIDString]] + path = [[OFSystemInfo temporaryDirectoryIRI] + IRIByAppendingPathComponent: [[OFUUID UUID] UUIDString]] .fileSystemRepresentation; #else /* * We can have sockets, including UNIX sockets, while file support is * disabled. * - * We also use this code path for iOS, as the temporaryDirectoryURI is + * We also use this code path for iOS, as the temporaryDirectoryIRI is * too long on the iOS simulator. */ path = [OFString stringWithFormat: @"/tmp/%@", [[OFUUID UUID] UUIDString]]; #endif Index: tests/OFUNIXStreamSocketTests.m ================================================================== --- tests/OFUNIXStreamSocketTests.m +++ tests/OFUNIXStreamSocketTests.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,19 +28,19 @@ OFString *path; OFUNIXStreamSocket *sockClient, *sockServer, *sockAccepted; char buffer[5]; #if defined(OF_HAVE_FILES) && !defined(OF_IOS) - path = [[OFSystemInfo temporaryDirectoryURI] - URIByAppendingPathComponent: [[OFUUID UUID] UUIDString]] + path = [[OFSystemInfo temporaryDirectoryIRI] + IRIByAppendingPathComponent: [[OFUUID UUID] UUIDString]] .fileSystemRepresentation; #else /* * We can have sockets, including UNIX sockets, while file support is * disabled. * - * We also use this code path for iOS, as the temporaryDirectoryURI is + * We also use this code path for iOS, as the temporaryDirectory:RI is * too long on the iOS simulator. */ path = [OFString stringWithFormat: @"/tmp/%@", [[OFUUID UUID] UUIDString]]; #endif @@ -79,16 +79,16 @@ TEST(@"-[readIntoBuffer:length:]", [sockClient readIntoBuffer: buffer length: 5] == 5 && memcmp(buffer, "Hello", 5) == 0) - TEST(@"-[remoteAddress]", - OFSocketAddressUNIXPath(sockAccepted.remoteAddress) == nil) + TEST(@"-[remoteAddress]", OFSocketAddressUNIXPath( + sockAccepted.remoteAddress).length == 0) } @finally { #ifdef OF_HAVE_FILES [[OFFileManager defaultManager] removeItemAtPath: path]; #endif } objc_autoreleasePoolPop(pool); } @end DELETED tests/OFURITests.m Index: tests/OFURITests.m ================================================================== --- tests/OFURITests.m +++ /dev/null @@ -1,356 +0,0 @@ -/* - * Copyright (c) 2008-2022 Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 3, which can be found in the file - * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this - * file. - */ - -#include "config.h" - -#import "TestsAppDelegate.h" - -static OFString *const module = @"OFURI"; -static OFString *URIString = @"ht+tp://us%3Aer:p%40w@ho%3Ast:1234/" - @"pa%3Fth?que%23ry=1&f%26oo=b%3dar#frag%23ment"; - -@implementation TestsAppDelegate (OFURITests) -- (void)URITests -{ - void *pool = objc_autoreleasePoolPush(); - OFURI *URI1, *URI2, *URI3, *URI4, *URI5, *URI6, *URI7, *URI8, *URI9; - OFURI *URI10; - OFMutableURI *mutableURI; - - TEST(@"+[URIWithString:]", - R(URI1 = [OFURI URIWithString: URIString]) && - R(URI2 = [OFURI URIWithString: @"http://foo:80"]) && - R(URI3 = [OFURI URIWithString: @"http://bar/"]) && - R(URI4 = [OFURI URIWithString: @"file:///etc/passwd"]) && - R(URI5 = [OFURI URIWithString: @"http://foo/bar/qux/foo%2fbar"]) && - R(URI6 = [OFURI URIWithString: @"https://[12:34::56:abcd]/"]) && - R(URI7 = [OFURI URIWithString: @"https://[12:34::56:abcd]:234/"]) && - R(URI8 = [OFURI URIWithString: @"urn:qux:foo"]) && - R(URI9 = [OFURI URIWithString: @"file:/foo?query#frag"]) && - R(URI10 = [OFURI URIWithString: @"file:foo@bar/qux?query#frag"])) - - EXPECT_EXCEPTION(@"+[URIWithString:] fails with invalid characters #1", - OFInvalidFormatException, - [OFURI URIWithString: @"ht,tp://foo"]) - - EXPECT_EXCEPTION(@"+[URIWithString:] fails with invalid characters #2", - OFInvalidFormatException, - [OFURI URIWithString: @"http://f`oo"]) - - EXPECT_EXCEPTION(@"+[URIWithString:] fails with invalid characters #3", - OFInvalidFormatException, - [OFURI URIWithString: @"http://foo/`"]) - - EXPECT_EXCEPTION(@"+[URIWithString:] fails with invalid characters #4", - OFInvalidFormatException, - [OFURI URIWithString: @"http://foo/foo?`"]) - - EXPECT_EXCEPTION(@"+[URIWithString:] fails with invalid characters #5", - OFInvalidFormatException, - [OFURI URIWithString: @"http://foo/foo?foo#`"]) - - EXPECT_EXCEPTION(@"+[URIWithString:] fails with invalid characters #6", - OFInvalidFormatException, - [OFURI URIWithString: @"https://[g]/"]) - - EXPECT_EXCEPTION(@"+[URIWithString:] fails with invalid characters #7", - OFInvalidFormatException, - [OFURI URIWithString: @"https://[f]:/"]) - - EXPECT_EXCEPTION(@"+[URIWithString:] fails with invalid characters #8", - OFInvalidFormatException, - [OFURI URIWithString: @"https://[f]:f/"]) - - TEST(@"+[URIWithString:relativeToURI:]", - [[[OFURI URIWithString: @"/foo" relativeToURI: URI1] string] - isEqual: @"ht+tp://us%3Aer:p%40w@ho%3Ast:1234/foo"] && - [[[OFURI URIWithString: @"foo/bar?q" - relativeToURI: [OFURI URIWithString: @"http://h/qux/quux"]] - string] isEqual: @"http://h/qux/foo/bar?q"] && - [[[OFURI URIWithString: @"foo/bar" - relativeToURI: [OFURI URIWithString: @"http://h/qux/?x"]] - string] isEqual: @"http://h/qux/foo/bar"] && - [[[OFURI URIWithString: @"http://foo/?q" - relativeToURI: URI1] string] isEqual: @"http://foo/?q"] && - [[[OFURI URIWithString: @"foo" - relativeToURI: [OFURI URIWithString: @"http://foo/bar"]] - string] isEqual: @"http://foo/foo"] && - [[[OFURI URIWithString: @"foo" - relativeToURI: [OFURI URIWithString: @"http://foo"]] - string] isEqual: @"http://foo/foo"]) - - EXPECT_EXCEPTION( - @"+[URIWithString:relativeToURI:] fails with invalid characters #1", - OFInvalidFormatException, - [OFURI URIWithString: @"`" relativeToURI: URI1]) - - EXPECT_EXCEPTION( - @"+[URIWithString:relativeToURI:] fails with invalid characters #2", - OFInvalidFormatException, - [OFURI URIWithString: @"/`" relativeToURI: URI1]) - - EXPECT_EXCEPTION( - @"+[URIWithString:relativeToURI:] fails with invalid characters #3", - OFInvalidFormatException, - [OFURI URIWithString: @"?`" relativeToURI: URI1]) - - EXPECT_EXCEPTION( - @"+[URIWithString:relativeToURI:] fails with invalid characters #4", - OFInvalidFormatException, - [OFURI URIWithString: @"#`" relativeToURI: URI1]) - -#ifdef OF_HAVE_FILES - TEST(@"+[fileURIWithPath:]", - [[[OFURI fileURIWithPath: @"testfile.txt"] fileSystemRepresentation] - isEqual: [[OFFileManager defaultManager].currentDirectoryPath - stringByAppendingPathComponent: @"testfile.txt"]]) - -# if defined(OF_WINDOWS) || defined(OF_MSDOS) - OFURI *tmp; - TEST(@"+[fileURIWithPath:] for c:\\", - (tmp = [OFURI fileURIWithPath: @"c:\\"]) && - [tmp.string isEqual: @"file:/c:/"] && - [tmp.fileSystemRepresentation isEqual: @"c:\\"]) -# endif - -# ifdef OF_WINDOWS - TEST(@"+[fileURIWithPath:] with UNC", - (tmp = [OFURI fileURIWithPath: @"\\\\foo\\bar" - isDirectory: false]) && - [tmp.host isEqual: @"foo"] && [tmp.path isEqual: @"/bar"] && - [tmp.string isEqual: @"file://foo/bar"] && - [tmp.fileSystemRepresentation isEqual: @"\\\\foo\\bar"] && - (tmp = [OFURI fileURIWithPath: @"\\\\test" isDirectory: true]) && - [tmp.host isEqual: @"test"] && [tmp.path isEqual: @"/"] && - [tmp.string isEqual: @"file://test/"] && - [tmp.fileSystemRepresentation isEqual: @"\\\\test"]) -# endif -#endif - - TEST(@"-[string]", - [URI1.string isEqual: URIString] && - [URI2.string isEqual: @"http://foo:80"] && - [URI3.string isEqual: @"http://bar/"] && - [URI4.string isEqual: @"file:///etc/passwd"] && - [URI5.string isEqual: @"http://foo/bar/qux/foo%2fbar"] && - [URI6.string isEqual: @"https://[12:34::56:abcd]/"] && - [URI7.string isEqual: @"https://[12:34::56:abcd]:234/"] && - [URI8.string isEqual: @"urn:qux:foo"] && - [URI9.string isEqual: @"file:/foo?query#frag"] && - [URI10.string isEqual: @"file:foo@bar/qux?query#frag"]) - - TEST(@"-[scheme]", - [URI1.scheme isEqual: @"ht+tp"] && [URI4.scheme isEqual: @"file"] && - [URI9.scheme isEqual: @"file"] && [URI10.scheme isEqual: @"file"]) - - TEST(@"-[user]", [URI1.user isEqual: @"us:er"] && URI4.user == nil && - URI10.user == nil) - TEST(@"-[password]", - [URI1.password isEqual: @"p@w"] && URI4.password == nil && - URI10.password == nil) - TEST(@"-[host]", [URI1.host isEqual: @"ho:st"] && - [URI6.host isEqual: @"12:34::56:abcd"] && - [URI7.host isEqual: @"12:34::56:abcd"] && - URI8.host == nil && URI9.host == nil && URI10.host == nil) - TEST(@"-[port]", URI1.port.unsignedShortValue == 1234 && - [URI4 port] == nil && URI7.port.unsignedShortValue == 234 && - URI8.port == nil && URI9.port == nil && URI10.port == nil) - TEST(@"-[path]", - [URI1.path isEqual: @"/pa?th"] && - [URI4.path isEqual: @"/etc/passwd"] && - [URI8.path isEqual: @"qux:foo"] && - [URI9.path isEqual: @"/foo"] && - [URI10.path isEqual: @"foo@bar/qux"]) - TEST(@"-[pathComponents]", - [URI1.pathComponents isEqual: - [OFArray arrayWithObjects: @"/", @"pa?th", nil]] && - [URI4.pathComponents isEqual: - [OFArray arrayWithObjects: @"/", @"etc", @"passwd", nil]] && - [URI5.pathComponents isEqual: - [OFArray arrayWithObjects: @"/", @"bar", @"qux", @"foo/bar", nil]]) - TEST(@"-[lastPathComponent]", - [[[OFURI URIWithString: @"http://host/foo//bar/baz"] - lastPathComponent] isEqual: @"baz"] && - [[[OFURI URIWithString: @"http://host/foo//bar/baz/"] - lastPathComponent] isEqual: @"baz"] && - [[[OFURI URIWithString: @"http://host/foo/"] - lastPathComponent] isEqual: @"foo"] && - [[[OFURI URIWithString: @"http://host/"] - lastPathComponent] isEqual: @"/"] && - [URI5.lastPathComponent isEqual: @"foo/bar"]) - TEST(@"-[query]", - [URI1.query isEqual: @"que#ry=1&f&oo=b=ar"] && URI4.query == nil && - [URI9.query isEqual: @"query"] && [URI10.query isEqual: @"query"]) - TEST(@"-[queryItems]", - [URI1.queryItems isEqual: [OFArray arrayWithObjects: - [OFPair pairWithFirstObject: @"que#ry" secondObject: @"1"], - [OFPair pairWithFirstObject: @"f&oo" secondObject: @"b=ar"], nil]]); - TEST(@"-[fragment]", - [URI1.fragment isEqual: @"frag#ment"] && URI4.fragment == nil && - [URI9.fragment isEqual: @"frag"] && - [URI10.fragment isEqual: @"frag"]) - - TEST(@"-[copy]", R(URI4 = [[URI1 copy] autorelease])) - - TEST(@"-[isEqual:]", [URI1 isEqual: URI4] && ![URI2 isEqual: URI3] && - [[OFURI URIWithString: @"HTTP://bar/"] isEqual: URI3]) - - TEST(@"-[hash:]", URI1.hash == URI4.hash && URI2.hash != URI3.hash) - - EXPECT_EXCEPTION(@"Detection of invalid format", - OFInvalidFormatException, [OFURI URIWithString: @"http"]) - - mutableURI = [OFMutableURI URIWithScheme: @"dummy"]; - - EXPECT_EXCEPTION( - @"-[setPercentEncodedScheme:] with invalid characters fails", - OFInvalidFormatException, mutableURI.scheme = @"%20") - - TEST(@"-[setHost:]", - (mutableURI.host = @"ho:st") && - [mutableURI.percentEncodedHost isEqual: @"ho%3Ast"] && - (mutableURI.host = @"12:34:ab") && - [mutableURI.percentEncodedHost isEqual: @"[12:34:ab]"] && - (mutableURI.host = @"12:34:aB") && - [mutableURI.percentEncodedHost isEqual: @"[12:34:aB]"] && - (mutableURI.host = @"12:34:g") && - [mutableURI.percentEncodedHost isEqual: @"12%3A34%3Ag"]) - - TEST(@"-[setPercentEncodedHost:]", - (mutableURI.percentEncodedHost = @"ho%3Ast") && - [mutableURI.host isEqual: @"ho:st"] && - (mutableURI.percentEncodedHost = @"[12:34]") && - [mutableURI.host isEqual: @"12:34"] && - (mutableURI.percentEncodedHost = @"[12::ab]") && - [mutableURI.host isEqual: @"12::ab"]) - - EXPECT_EXCEPTION( - @"-[setPercentEncodedHost:] with invalid characters fails #1", - OFInvalidFormatException, - mutableURI.percentEncodedHost = @"/") - - EXPECT_EXCEPTION( - @"-[setPercentEncodedHost:] with invalid characters fails #2", - OFInvalidFormatException, - mutableURI.percentEncodedHost = @"[12:34") - - EXPECT_EXCEPTION( - @"-[setPercentEncodedHost:] with invalid characters fails #3", - OFInvalidFormatException, - mutableURI.percentEncodedHost = @"[a::g]") - - TEST(@"-[setUser:]", - (mutableURI.user = @"us:er") && - [mutableURI.percentEncodedUser isEqual: @"us%3Aer"]) - - TEST(@"-[setPercentEncodedUser:]", - (mutableURI.percentEncodedUser = @"us%3Aer") && - [mutableURI.user isEqual: @"us:er"]) - - EXPECT_EXCEPTION( - @"-[setPercentEncodedUser:] with invalid characters fails", - OFInvalidFormatException, - mutableURI.percentEncodedHost = @"/") - - TEST(@"-[setPassword:]", - (mutableURI.password = @"pass:word") && - [mutableURI.percentEncodedPassword isEqual: @"pass%3Aword"]) - - TEST(@"-[setPercentEncodedPassword:]", - (mutableURI.percentEncodedPassword = @"pass%3Aword") && - [mutableURI.password isEqual: @"pass:word"]) - - EXPECT_EXCEPTION( - @"-[setPercentEncodedPassword:] with invalid characters fails", - OFInvalidFormatException, - mutableURI.percentEncodedPassword = @"/") - - TEST(@"-[setPath:]", - (mutableURI.path = @"pa/th@?") && - [mutableURI.percentEncodedPath isEqual: @"pa/th@%3F"]) - - TEST(@"-[setPercentEncodedPath:]", - (mutableURI.percentEncodedPath = @"pa/th@%3F") && - [mutableURI.path isEqual: @"pa/th@?"]) - - EXPECT_EXCEPTION( - @"-[setPercentEncodedPath:] with invalid characters fails", - OFInvalidFormatException, - mutableURI.percentEncodedPath = @"?") - - TEST(@"-[setQuery:]", - (mutableURI.query = @"que/ry?#") && - [mutableURI.percentEncodedQuery isEqual: @"que/ry?%23"]) - - TEST(@"-[setPercentEncodedQuery:]", - (mutableURI.percentEncodedQuery = @"que/ry?%23") && - [mutableURI.query isEqual: @"que/ry?#"]) - - EXPECT_EXCEPTION( - @"-[setPercentEncodedQuery:] with invalid characters fails", - OFInvalidFormatException, - mutableURI.percentEncodedQuery = @"`") - - TEST(@"-[setQueryItems:]", - (mutableURI.queryItems = [OFArray arrayWithObjects: - [OFPair pairWithFirstObject: @"foo&bar" secondObject: @"baz=qux"], - [OFPair pairWithFirstObject: @"f=oobar" secondObject: @"b&azqux"], - nil]) && [mutableURI.percentEncodedQuery isEqual: - @"foo%26bar=baz%3Dqux&f%3Doobar=b%26azqux"]) - - TEST(@"-[setFragment:]", - (mutableURI.fragment = @"frag/ment?#") && - [mutableURI.percentEncodedFragment isEqual: @"frag/ment?%23"]) - - TEST(@"-[setPercentEncodedFragment:]", - (mutableURI.percentEncodedFragment = @"frag/ment?%23") && - [mutableURI.fragment isEqual: @"frag/ment?#"]) - - EXPECT_EXCEPTION( - @"-[setPercentEncodedFragment:] with invalid characters fails", - OFInvalidFormatException, - mutableURI.percentEncodedFragment = @"`") - - TEST(@"-[URIByAppendingPathComponent:isDirectory:]", - [[[OFURI URIWithString: @"file:///foo/bar"] - URIByAppendingPathComponent: @"qux" isDirectory: false] isEqual: - [OFURI URIWithString: @"file:///foo/bar/qux"]] && - [[[OFURI URIWithString: @"file:///foo/bar/"] - URIByAppendingPathComponent: @"qux" isDirectory: false] isEqual: - [OFURI URIWithString: @"file:///foo/bar/qux"]] && - [[[OFURI URIWithString: @"file:///foo/bar/"] - URIByAppendingPathComponent: @"qu?x" isDirectory: false] isEqual: - [OFURI URIWithString: @"file:///foo/bar/qu%3Fx"]] && - [[[OFURI URIWithString: @"file:///foo/bar/"] - URIByAppendingPathComponent: @"qu?x" isDirectory: true] isEqual: - [OFURI URIWithString: @"file:///foo/bar/qu%3Fx/"]]) - - TEST(@"-[URIByStandardizingPath]", - [[[OFURI URIWithString: @"http://foo/bar/.."] - URIByStandardizingPath] isEqual: - [OFURI URIWithString: @"http://foo/"]] && - [[[OFURI URIWithString: @"http://foo/bar/%2E%2E/../qux/"] - URIByStandardizingPath] isEqual: - [OFURI URIWithString: @"http://foo/bar/qux/"]] && - [[[OFURI URIWithString: @"http://foo/bar/./././qux/./"] - URIByStandardizingPath] isEqual: - [OFURI URIWithString: @"http://foo/bar/qux/"]] && - [[[OFURI URIWithString: @"http://foo/bar/../../qux"] - URIByStandardizingPath] isEqual: - [OFURI URIWithString: @"http://foo/../qux"]]) - - objc_autoreleasePoolPop(pool); -} -@end Index: tests/OFValueTests.m ================================================================== --- tests/OFValueTests.m +++ tests/OFValueTests.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may 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/OFXMLElementBuilderTests.m ================================================================== --- tests/OFXMLElementBuilderTests.m +++ tests/OFXMLElementBuilderTests.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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 @@ @implementation RuntimeARCTest - (instancetype)init { self = [super init]; -#if defined(OF_WINDOWS) && defined(OF_X86_64) +#if defined(OF_WINDOWS) && defined(OF_AMD64) /* * Clang has a bug on Windows where it creates an invalid call into * objc_retainAutoreleasedReturnValue(). Work around it by not using an * autoreleased exception. */ Index: tests/RuntimeTests.m ================================================================== --- tests/RuntimeTests.m +++ tests/RuntimeTests.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -76,10 +76,14 @@ @end @interface TestsAppDelegate (OFCharacterSetTests) - (void)characterSetTests; @end + +@interface TestsAppDelegate (OFColorTests) +- (void)colorTests; +@end @interface TestsAppDelegate (OFDDPSocketTests) - (void)DDPSocketTests; @end @@ -116,10 +120,14 @@ @end @interface TestsAppDelegate (OFINIFileTests) - (void)INIFileTests; @end + +@interface TestsAppDelegate (OFIRITests) +- (void)IRITests; +@end @interface TestsAppDelegate (OFIPXSocketTests) - (void)IPXSocketTests; @end @@ -148,10 +156,14 @@ @end @interface TestsAppDelegate (OFMD5HashTests) - (void)MD5HashTests; @end + +@interface TestsAppDelegate (OFMatrix4x4Tests) +- (void)matrix4x4Tests; +@end @interface TestsAppDelegate (OFMemoryStreamTests) - (void)memoryStreamTests; @end @@ -225,14 +237,10 @@ @interface TestsAppDelegate (OFSPXStreamSocketTests) - (void)SPXStreamSocketTests; @end -@interface TestsAppDelegate (OFSerializationTests) -- (void)serializationTests; -@end - @interface TestsAppDelegate (OFSetTests) - (void)setTests; @end @interface TestsAppDelegate (OFSystemInfoTests) @@ -269,14 +277,10 @@ @interface TestsAppDelegate (OFUNIXStreamSocketTests) - (void)UNIXStreamSocketTests; @end -@interface TestsAppDelegate (OFURITests) -- (void)URITests; -@end - @interface TestsAppDelegate (OFValueTests) - (void)valueTests; @end @interface TestsAppDelegate (OFWindowsRegistryKeyTests) Index: tests/TestsAppDelegate.m ================================================================== --- tests/TestsAppDelegate.m +++ tests/TestsAppDelegate.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,11 +347,11 @@ [OFStdOut reset]; [OFStdOut eraseLine]; } } -- (void)applicationDidFinishLaunching +- (void)applicationDidFinishLaunching: (OFNotification *)notification { #if defined(OF_IOS) && defined(OF_HAVE_FILES) CFBundleRef mainBundle = CFBundleGetMainBundle(); CFURLRef resourcesURL = CFBundleCopyResourcesDirectoryURL(mainBundle); UInt8 resourcesPath[PATH_MAX]; @@ -389,10 +389,11 @@ [self listTests]; [self setTests]; [self dateTests]; [self valueTests]; [self numberTests]; + [self colorTests]; [self streamTests]; [self memoryStreamTests]; [self notificationCenterTests]; [self MD5HashTests]; [self RIPEMD160HashTests]; @@ -426,11 +427,11 @@ [self kernelEventObserverTests]; #endif #ifdef OF_HAVE_THREADS [self threadTests]; #endif - [self URITests]; + [self IRITests]; #if defined(OF_HAVE_SOCKETS) && defined(OF_HAVE_THREADS) [self HTTPClientTests]; #endif #ifdef OF_HAVE_SOCKETS [self HTTPCookieTests]; @@ -437,18 +438,21 @@ [self HTTPCookieManagerTests]; #endif [self XMLParserTests]; [self XMLNodeTests]; [self XMLElementBuilderTests]; - [self serializationTests]; [self JSONTests]; [self propertyListTests]; [self ASN1DERParsingTests]; [self ASN1DERRepresentationTests]; + + [self matrix4x4Tests]; + #if defined(OF_HAVE_PLUGINS) [self pluginTests]; #endif + #ifdef OF_WINDOWS [self windowsRegistryKeyTests]; #endif #ifdef OF_HAVE_SOCKETS Index: tests/iOS.xcodeproj/project.pbxproj ================================================================== --- tests/iOS.xcodeproj/project.pbxproj +++ tests/iOS.xcodeproj/project.pbxproj @@ -11,11 +11,10 @@ 4BC7FD07201394F300280496 /* ObjFW.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4BC7FD06201394F300280496 /* ObjFW.framework */; }; 4BC7FD092013954B00280496 /* tests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4BC7FD082013954B00280496 /* tests.a */; }; 4BC7FD0B2013956D00280496 /* ObjFW.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4BC7FD06201394F300280496 /* ObjFW.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 4BC7FD102013960600280496 /* testfile.txt in Resources */ = {isa = PBXBuildFile; fileRef = 4BC7FD0C2013960600280496 /* testfile.txt */; }; 4BC7FD112013960600280496 /* testfile.bin in Resources */ = {isa = PBXBuildFile; fileRef = 4BC7FD0D2013960600280496 /* testfile.bin */; }; - 4BC7FD122013960600280496 /* serialization.xml in Resources */ = {isa = PBXBuildFile; fileRef = 4BC7FD0E2013960600280496 /* serialization.xml */; }; 4BC7FD132013960600280496 /* testfile.ini in Resources */ = {isa = PBXBuildFile; fileRef = 4BC7FD0F2013960600280496 /* testfile.ini */; }; 4BEBFB6E2013934E002E8710 /* ImportTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BEBFB6D2013934E002E8710 /* ImportTest.m */; }; /* End PBXBuildFile section */ /* Begin PBXCopyFilesBuildPhase section */ @@ -45,11 +44,10 @@ 4B6AB9CA202BA408007BAC7D /* TestPlugin.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; name = TestPlugin.bundle; path = plugin/TestPlugin.bundle; sourceTree = ""; }; 4BC7FD06201394F300280496 /* ObjFW.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ObjFW.framework; path = ../src/ObjFW.framework; sourceTree = ""; }; 4BC7FD082013954B00280496 /* tests.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = tests.a; sourceTree = ""; }; 4BC7FD0C2013960600280496 /* testfile.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = testfile.txt; sourceTree = ""; }; 4BC7FD0D2013960600280496 /* testfile.bin */ = {isa = PBXFileReference; lastKnownFileType = archive.macbinary; path = testfile.bin; sourceTree = ""; }; - 4BC7FD0E2013960600280496 /* serialization.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = serialization.xml; sourceTree = ""; }; 4BC7FD0F2013960600280496 /* testfile.ini */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = testfile.ini; sourceTree = ""; }; 4BEBFB5B2013934E002E8710 /* tests.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = tests.app; sourceTree = BUILT_PRODUCTS_DIR; }; 4BEBFB6C2013934E002E8710 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = SOURCE_ROOT; }; 4BEBFB6D2013934E002E8710 /* ImportTest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ImportTest.m; sourceTree = SOURCE_ROOT; }; /* End PBXFileReference section */ @@ -97,11 +95,10 @@ 4BEBFB5D2013934E002E8710 /* tests */ = { isa = PBXGroup; children = ( 4BEBFB6C2013934E002E8710 /* Info.plist */, 4BEBFB6D2013934E002E8710 /* ImportTest.m */, - 4BC7FD0E2013960600280496 /* serialization.xml */, 4BC7FD0D2013960600280496 /* testfile.bin */, 4BC7FD0F2013960600280496 /* testfile.ini */, 4BC7FD0C2013960600280496 /* testfile.txt */, ); name = tests; @@ -166,11 +163,10 @@ 4BEBFB592013934E002E8710 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( 4BC7FD102013960600280496 /* testfile.txt in Resources */, - 4BC7FD122013960600280496 /* serialization.xml in Resources */, 4BC7FD132013960600280496 /* testfile.ini in Resources */, 4BC7FD112013960600280496 /* testfile.bin in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -307,11 +303,11 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; LIBRARY_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)", ); - OTHER_LDFLAGS = "-ObjC"; + OTHER_LDFLAGS = "-all_load"; PRODUCT_BUNDLE_IDENTIFIER = im.nil.objfw.tests; PRODUCT_NAME = "$(TARGET_NAME)"; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Debug; @@ -327,11 +323,11 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; LIBRARY_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)", ); - OTHER_LDFLAGS = "-ObjC"; + OTHER_LDFLAGS = "-all_load"; PRODUCT_BUNDLE_IDENTIFIER = im.nil.objfw.tests; PRODUCT_NAME = "$(TARGET_NAME)"; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Release; Index: tests/objc_sync/Makefile ================================================================== --- tests/objc_sync/Makefile +++ tests/objc_sync/Makefile @@ -12,11 +12,10 @@ rm -f objfw${OBJFW_LIB_MAJOR}.dll libobjfw.${OBJFW_LIB_MAJOR}.dylib rm -f libobjfwrt.so.${OBJFWRT_LIB_MAJOR} rm -f libobjfwrt.so.${OBJFWRT_LIB_MAJOR_MINOR} rm -f objfwrt${OBJFWRT_LIB_MAJOR}.dll rm -f libobjfwrt.${OBJFWRT_LIB_MAJOR}.dylib - rm -f ${OBJFWRT_AMIGA_LIB} if test -f ../../src/libobjfw.so; then \ ${LN_S} ../../src/libobjfw.so libobjfw.so.${OBJFW_LIB_MAJOR}; \ ${LN_S} ../../src/libobjfw.so \ libobjfw.so.${OBJFW_LIB_MAJOR_MINOR}; \ elif test -f ../../src/libobjfw.so.${OBJFW_LIB_MAJOR_MINOR}; then \ @@ -45,14 +44,10 @@ fi if test -f ../../src/runtime/libobjfwrt.dylib; then \ ${LN_S} ../../src/runtime/libobjfwrt.dylib \ libobjfwrt.${OBJFWRT_LIB_MAJOR}.dylib; \ fi - if test -f ../../src/runtime/${OBJFWRT_AMIGA_LIB}; then \ - ${LN_S} ../../src/runtime/${OBJFWRT_AMIGA_LIB} \ - ${OBJFWRT_AMIGA_LIB}; \ - fi LD_LIBRARY_PATH=.$${LD_LIBRARY_PATH+:}$$LD_LIBRARY_PATH \ DYLD_LIBRARY_PATH=.$${DYLD_LIBRARY_PATH+:}$$DYLD_LIBRARY_PATH \ LIBRARY_PATH=.$${LIBRARY_PATH+:}$$LIBRARY_PATH \ ${WRAPPER} ./${PROG_NOINST}; EXIT=$$?; \ rm -f libobjfw.so.${OBJFW_LIB_MAJOR}; \ @@ -64,9 +59,7 @@ rm -f objfwrt${OBJFWRT_LIB_MAJOR}.dll; \ rm -f libobjfwrt.${OBJFWRT_LIB_MAJOR}.dylib; \ exit $$EXIT CPPFLAGS += -I../../src -I../../src/runtime -I../.. -LIBS := -L../../src -lobjfw \ - -L../../src/runtime -L../../src/runtime/linklib ${RUNTIME_LIBS} \ - ${LIBS} +LIBS := -L../../src -lobjfw -L../../src/runtime ${RUNTIME_LIBS} ${LIBS} LD = ${OBJC} Index: tests/objc_sync/test.m ================================================================== --- tests/objc_sync/test.m +++ tests/objc_sync/test.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may 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.m ================================================================== --- tests/plugin/TestPlugin.m +++ tests/plugin/TestPlugin.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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 tests/serialization.xml Index: tests/serialization.xml ================================================================== --- tests/serialization.xml +++ /dev/null @@ -1,67 +0,0 @@ - - - - - 01234567-89ab-cdef-fedc-ba9876543210 - - - uuid - - - Blub - - - B"la - - - - Hello - Wo ld! -How are you? - https://objfw.nil.im/ - - - - - - - - - - bar - foo - - - - bar - - - foo - - - - - - list - - - MDEyMzQ1Njc4OTo7PEFCQ0RFRkdISklLTE1OT1BRUlNUVVZXWFla - - - data - - - - Qu"xbar -test - 1234 - 40934a456d5cfaad - asd - 40934a456d5cfaad - - - - Hello - - - Index: tests/terminal/Makefile ================================================================== --- tests/terminal/Makefile +++ tests/terminal/Makefile @@ -12,11 +12,10 @@ rm -f objfw${OBJFW_LIB_MAJOR}.dll libobjfw.${OBJFW_LIB_MAJOR}.dylib rm -f libobjfwrt.so.${OBJFWRT_LIB_MAJOR} rm -f libobjfwrt.so.${OBJFWRT_LIB_MAJOR_MINOR} rm -f objfwrt${OBJFWRT_LIB_MAJOR}.dll rm -f libobjfwrt.${OBJFWRT_LIB_MAJOR}.dylib - rm -f ${OBJFWRT_AMIGA_LIB} if test -f ../../src/libobjfw.so; then \ ${LN_S} ../../src/libobjfw.so libobjfw.so.${OBJFW_LIB_MAJOR}; \ ${LN_S} ../../src/libobjfw.so \ libobjfw.so.${OBJFW_LIB_MAJOR_MINOR}; \ elif test -f ../../src/libobjfw.so.${OBJFW_LIB_MAJOR_MINOR}; then \ @@ -45,14 +44,10 @@ fi if test -f ../../src/runtime/libobjfwrt.dylib; then \ ${LN_S} ../../src/runtime/libobjfwrt.dylib \ libobjfwrt.${OBJFWRT_LIB_MAJOR}.dylib; \ fi - if test -f ../../src/runtime/${OBJFWRT_AMIGA_LIB}; then \ - ${LN_S} ../../src/runtime/${OBJFWRT_AMIGA_LIB} \ - ${OBJFWRT_AMIGA_LIB}; \ - fi LD_LIBRARY_PATH=.$${LD_LIBRARY_PATH+:}$$LD_LIBRARY_PATH \ DYLD_LIBRARY_PATH=.$${DYLD_LIBRARY_PATH+:}$$DYLD_LIBRARY_PATH \ LIBRARY_PATH=.$${LIBRARY_PATH+:}$$LIBRARY_PATH \ ${WRAPPER} ./${PROG_NOINST}; EXIT=$$?; \ rm -f libobjfw.so.${OBJFW_LIB_MAJOR}; \ @@ -64,9 +59,7 @@ rm -f objfwrt${OBJFWRT_LIB_MAJOR}.dll; \ rm -f libobjfwrt.${OBJFWRT_LIB_MAJOR}.dylib; \ exit $$EXIT CPPFLAGS += -I../../src -I../../src/exceptions -I../../src/runtime -I../.. -LIBS := -L../../src -lobjfw \ - -L../../src/runtime -L../../src/runtime/linklib ${RUNTIME_LIBS} \ - ${LIBS} +LIBS := -L../../src -lobjfw -L../../src/runtime ${RUNTIME_LIBS} ${LIBS} LD = ${OBJC} Index: tests/terminal/TerminalTests.m ================================================================== --- tests/terminal/TerminalTests.m +++ tests/terminal/TerminalTests.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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 @@ @end OF_APPLICATION_DELEGATE(TerminalTests) @implementation TerminalTests -- (void)applicationDidFinishLaunching +- (void)applicationDidFinishLaunching: (OFNotification *)notification { OFArray *colors = [OFArray arrayWithObjects: [OFColor black], [OFColor silver], [OFColor grey], [OFColor white], [OFColor maroon], [OFColor red], [OFColor purple], [OFColor fuchsia], [OFColor green], [OFColor lime], [OFColor olive], Index: utils/Makefile ================================================================== --- utils/Makefile +++ utils/Makefile @@ -1,13 +1,12 @@ include ../extra.mk -SUBDIRS += ${OBJFW_NEW} \ - ${OFARC} \ - ${OFDNS} \ - ${OFHASH} \ - ${OFHTTP} \ - completions +SUBDIRS += ${OBJFW_NEW} \ + ${OFARC} \ + ${OFDNS} \ + ${OFHASH} \ + ${OFHTTP} include ../buildsys.mk DISTCLEAN = objfw-config DELETED utils/completions/Makefile Index: utils/completions/Makefile ================================================================== --- utils/completions/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -include ../../extra.mk - -SUBDIRS = ${FISH_COMPLETIONS} - -include ../../buildsys.mk DELETED utils/completions/fish/Makefile Index: utils/completions/fish/Makefile ================================================================== --- utils/completions/fish/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -DATA = objfw-compile.fish \ - objfw-config.fish \ - ofarc.fish \ - ofdns.fish \ - ofhash.fish \ - ofhttp.fish - -include ../../../buildsys.mk - -PACKAGE_NAME = fish/vendor_completions.d DELETED utils/completions/fish/objfw-compile.fish Index: utils/completions/fish/objfw-compile.fish ================================================================== --- utils/completions/fish/objfw-compile.fish +++ /dev/null @@ -1,28 +0,0 @@ -complete -c objfw-compile -s o -x -d 'Specify the output name (not file name!)' -complete -c objfw-compile -l arc -d 'Use automatic reference counting' -complete -c objfw-compile -l lib -x -d \ - 'Compile a library (with the specified version) instead of an application' -complete -c objfw-compile -l plugin \ - -d 'Compile a plugin instead of an application' -complete -c objfw-compile -l package -x -d 'Use the specified package' -complete -c objfw-compile -l builddir -r \ - -d 'Place built objects into the specified directory' -complete -c objfw-compile -s D -x -d 'Pass the specified define to the compiler' -complete -c objfw-compile -o framework -x \ - -d 'Pass the specified -framework argument to the linker (macOS / iOS only)' -# -f* cannot be represented. -complete -c objfw-compile -s F -x \ - -d 'Pass the specified -F flag to the linker (macOS / iOS only)' -# -g* cannot be represented. -complete -c objfw-compile -s I -x \ - -d 'Pass the specified -I flag to the compiler' -complete -c objfw-compile -s l -x -d 'Pass the specified -l flag to the linker' -complete -c objfw-compile -s L -x -d 'Pass the specified -L flag to the linker' -# -m* cannot be represented. -# -O* cannot be represented. -complete -c objfw-compile -o pthread \ - -d 'Pass -pthread to the compiler and linker' -# -std=* cannot be represented. -# -Wl,* cannot be represented. -# -W* cannot be represented. -complete -c objfw-compile -l help -d 'Show this help' DELETED utils/completions/fish/objfw-config.fish Index: utils/completions/fish/objfw-config.fish ================================================================== --- utils/completions/fish/objfw-config.fish +++ /dev/null @@ -1,33 +0,0 @@ -complete -c objfw-config -l all -d 'Outputs all flags + libs' -complete -c objfw-config -l arc -d 'Outputs the required OBJCFLAGS to use ARC' -complete -c objfw-config -l cflags -d 'Outputs the required CFLAGS' -complete -c objfw-config -l cppflags -d 'Outputs the required CPPFLAGS' -complete -c objfw-config -l cxxflags -d 'Outputs the required CXXFLAGS' -complete -c objfw-config -l framework-libs \ - -d 'Outputs the required LIBS, preferring frameworks' -complete -c objfw-config -l help -d 'Print help' -complete -c objfw-config -l ldflags -d 'Outputs the required LDFLAGS' -complete -c objfw-config -l libs -d 'Outputs the required LIBS' -complete -c objfw-config -l lib-cflags \ - -d 'Outputs CFLAGS for building a library' -complete -c objfw-config -l lib-ldflags \ - -d 'Outputs LDFLAGS for building a library' -complete -c objfw-config -l lib-prefix -d 'Outputs the prefix for libraries' -complete -c objfw-config -l lib-suffix -d 'Outputs the suffix for libraries' -complete -c objfw-config -l objc -d 'Outputs the OBJC used to compile ObjFW' -complete -c objfw-config -l objcflags -d 'Outputs the required OBJCFLAGS' -complete -c objfw-config -l package -x \ - -d 'Additionally outputs the flags for the specified package' -complete -c objfw-config -l packages-dir \ - -d 'Outputs the directory where flags for packages are stored' -complete -c objfw-config -l plugin-cflags \ - -d 'Outputs CFLAGS for building a plugin' -complete -c objfw-config -l plugin-ldflags \ - -d 'Outputs LDFLAGS for building a plugin' -complete -c objfw-config -l plugin-suffix -d 'Outputs the suffix for plugins' -complete -c objfw-config -l prog-suffix -d 'Outputs the suffix for binaries' -complete -c objfw-config -l reexport -d 'Outputs LDFLAGS to reexport ObjFW' -complete -c objfw-config -l rpath -d 'Outputs LDFLAGS for using rpath' -complete -c objfw-config -l static-libs \ - -d 'Outputs the required LIBS to link ObjFW statically' -complete -c objfw-config -l version -d 'Outputs the installed version' DELETED utils/completions/fish/ofarc.fish Index: utils/completions/fish/ofarc.fish ================================================================== --- utils/completions/fish/ofarc.fish +++ /dev/null @@ -1,14 +0,0 @@ -complete -c ofarc -s a -l append -d 'Append to archive' -complete -c ofarc -s c -l create -d 'Create archive' -complete -c ofarc -s C -l directory -r -d 'Extract into the specified directory' -complete -c ofarc -s E -l encoding -x \ - -d 'The encoding used by the archive (only tar files)' -complete -c ofarc -s f -l force -d 'Force / overwrite files' -complete -c ofarc -s h -l help -d 'Show help' -complete -c ofarc -s l -l list -d 'List all files in the archive' -complete -c ofarc -s n -l no-clobber -d 'Never overwrite files' -complete -c ofarc -s p -l print -d 'Print one or more files from the archive' -complete -c ofarc -s q -l quiet -d 'Quiet mode (no output, except errors)' -complete -c ofarc -s t -l type -x -a 'gz lha tar tgz zip' -d 'Archive type' -complete -c ofarc -s v -l verbose -d 'Verbose output for file list' -complete -c ofarc -s x -l extract -d 'Extract files' DELETED utils/completions/fish/ofdns.fish Index: utils/completions/fish/ofdns.fish ================================================================== --- utils/completions/fish/ofdns.fish +++ /dev/null @@ -1,5 +0,0 @@ -complete -c ofdns -s c -l class -x -d 'The DNS class to query (defaults to IN)' -complete -c ofdns -s h -l help -d 'Show help' -complete -c ofdns -s s -l server -x -d 'The server to query' -complete -c ofdns -s t -l type -x \ - -d 'The record type to query (defaults to ALL, can be repeated)' DELETED utils/completions/fish/ofhash.fish Index: utils/completions/fish/ofhash.fish ================================================================== --- utils/completions/fish/ofhash.fish +++ /dev/null @@ -1,7 +0,0 @@ -complete -c ofhash --long-option md5 -complete -c ofhash --long-option ripemd160 -complete -c ofhash --long-option sha1 -complete -c ofhash --long-option sha224 -complete -c ofhash --long-option sha256 -complete -c ofhash --long-option sha384 -complete -c ofhash --long-option sha256 DELETED utils/completions/fish/ofhttp.fish Index: utils/completions/fish/ofhttp.fish ================================================================== --- utils/completions/fish/ofhttp.fish +++ /dev/null @@ -1,15 +0,0 @@ -complete -c ofhttp -x -complete -c ofhttp -s b -l body -r -d 'Specify the file to send as body' -complete -c ofhttp -s c -l continue -d 'Continue download of existing file' -complete -c ofhttp -s f -l force -d 'Force / overwrite existing file' -complete -c ofhttp -s h -l help -d 'Show help' -complete -c ofhttp -s H -l header -x -d 'Add a header (e.g. X-Foo:Bar)' -complete -c ofhttp -s m -l method -x -d 'Set the method of the HTTP request' -complete -c ofhttp -s o -l output -r -d 'Specify output file name' -complete -c ofhttp -s O -l detect-filename \ - -d 'Do a HEAD request to detect the file name' -complete -c ofhttp -s P -l proxy -x -d 'Specify SOCKS5 proxy' -complete -c ofhttp -s q -l quiet -d 'Quiet mode (no output, except errors)' -complete -c ofhttp -s v -l verbose -d 'Verbose mode (print headers)' -complete -c ofhttp -l insecure \ - -d 'Ignore TLS errors and allow insecure redirects' Index: utils/objfw-compile ================================================================== --- utils/objfw-compile +++ utils/objfw-compile @@ -1,8 +1,8 @@ #!/bin/sh # -# Copyright (c) 2008-2022 Jonathan Schleifer +# Copyright (c) 2008-2024 Jonathan Schleifer # # All rights reserved. # # This file is part of ObjFW. It may 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/objfw-config.in ================================================================== --- utils/objfw-config.in +++ utils/objfw-config.in @@ -1,8 +1,8 @@ #!/bin/sh # -# Copyright (c) 2008-2022 Jonathan Schleifer +# Copyright (c) 2008-2024 Jonathan Schleifer # # All rights reserved. # # This file is part of ObjFW. It may 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/objfw-embed ================================================================== --- utils/objfw-embed +++ utils/objfw-embed @@ -8,11 +8,15 @@ cat < #include -extern void OFRegisterEmbeddedFile(const char *, const uint8_t *, size_t); +#ifdef OF_COMPILING_OBJFW +# import "OFEmbeddedIRIHandler.h" +#else +# import +#endif static const uint8_t bytes[] = { EOF od -vtx1 $1 | sed -e '/^[^ ][^ ]*$/d;s/ */ /g' -e 's/ $//g;s/^[^ ][^ ]* //' -e 's/ /, 0x/g' -e 's/^/ 0x/' -e 's/$/,/' cat < + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,14 +46,15 @@ @"@end\n" @"\n" @"OF_APPLICATION_DELEGATE(%@)\n" @"\n" @"@implementation %@\n" - @"- (void)applicationDidFinishLaunching\n" + @"- (void)applicationDidFinishLaunching: " + @"(OFNotification *)notification\n" @"{\n" @" [OFApplication terminate];\n" @"}\n" @"@end\n", name, name, name]; [file close]; } Index: utils/objfw-new/NewClass.m ================================================================== --- utils/objfw-new/NewClass.m +++ utils/objfw-new/NewClass.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may 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/objfw-new/ObjFWNew.m ================================================================== --- utils/objfw-new/ObjFWNew.m +++ utils/objfw-new/ObjFWNew.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,56 +29,78 @@ extern void newClass(OFString *, OFString *, OFMutableArray *); OF_APPLICATION_DELEGATE(ObjFWNew) static void -showUsage(void) +help(OFStream *stream, bool full, int status) { - [OFStdErr writeFormat: @"Usage: %@ --app|--class name\n", - [OFApplication programName]]; + [stream writeFormat: + @"Usage: %@ --app|--class [--superclass=] [--property=] name\n", + [OFApplication programName]]; + + if (full) { + [stream writeString: @"\n"]; + [stream writeLine: + @"Options:\n" + @" -a --app Create a new app\n" + @" -c --class Create a new class\n" + @" -h --help Show this help\n" + @" -s --superclass= Specify the superclass for the " + @"class\n" + @" -p --property= Add a property to the class.\n" + @" E.g.: --property='(readonly, " + @"nonatomic) id foo'"]; + } - [OFApplication terminateWithStatus: 1]; + [OFApplication terminateWithStatus: status]; } @implementation ObjFWNew -- (void)applicationDidFinishLaunching +- (void)applicationDidFinishLaunching: (OFNotification *)notification { bool app, class; OFString *superclass = nil, *name; OFMutableArray OF_GENERIC(OFString *) *properties = nil; const OFOptionsParserOption options[] = { { 'a', @"app", 0, &app, NULL }, { 'c', @"class", 0, &class, NULL }, + { 'h', @"help", 0, NULL, NULL }, { 's', @"superclass", 1, NULL, &superclass }, { 'p', @"property", 1, NULL, NULL }, { '\0', nil, 0, NULL, NULL } }; OFOptionsParser *optionsParser; OFUnichar option; + + if ([OFApplication arguments].count == 0) + help(OFStdErr, true, 1); optionsParser = [OFOptionsParser parserWithOptions: options]; while ((option = [optionsParser nextOption]) != '\0') { switch (option) { + case 'h': + help(OFStdOut, true, 0); + break; case 'p': if (properties == nil) properties = [OFMutableArray array]; [properties addObject: optionsParser.argument]; break; case '?': case ':': case '=': - showUsage(); + help(OFStdErr, false, 1); break; } } if ((app ^ class) != 1 || optionsParser.remainingArguments.count != 1) - showUsage(); + help(OFStdErr, false, 1); if ((superclass && !class) || (properties != nil && !class)) - showUsage(); + help(OFStdErr, false, 1); name = optionsParser.remainingArguments.firstObject; if ([name rangeOfString: @"."].location != OFNotFound) { [OFStdErr writeLine: @"Name must not contain dots!"]; [OFApplication terminate]; @@ -87,10 +109,10 @@ if (app) newApp(name); else if (class) newClass(name, superclass, properties); else - showUsage(); + help(OFStdErr, false, 1); [OFApplication terminate]; } @end Index: utils/objfw-new/Property.h ================================================================== --- utils/objfw-new/Property.h +++ utils/objfw-new/Property.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may 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/objfw-new/Property.m ================================================================== --- utils/objfw-new/Property.m +++ utils/objfw-new/Property.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may 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/Archive.h ================================================================== --- utils/ofarc/Archive.h +++ utils/ofarc/Archive.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,19 +14,25 @@ */ #import "OFObject.h" #import "OFFile.h" #import "OFArray.h" + +OF_ASSUME_NONNULL_BEGIN @protocol Archive -+ (instancetype)archiveWithStream: (OF_KINDOF(OFStream *))stream - mode: (OFString *)mode - encoding: (OFStringEncoding)encoding; -- (instancetype)initWithStream: (OF_KINDOF(OFStream *))stream - mode: (OFString *)mode - encoding: (OFStringEncoding)encoding; ++ (instancetype)archiveWithPath: (nullable OFString *)path + stream: (OF_KINDOF(OFStream *))stream + mode: (OFString *)mode + encoding: (OFStringEncoding)encoding; +- (instancetype)initWithPath: (nullable OFString *)path + stream: (OF_KINDOF(OFStream *))stream + mode: (OFString *)mode + encoding: (OFStringEncoding)encoding; - (void)listFiles; - (void)extractFiles: (OFArray OF_GENERIC(OFString *) *)files; - (void)printFiles: (OFArray OF_GENERIC(OFString *) *)files; @optional - (void)addFiles: (OFArray OF_GENERIC(OFString *) *)files; @end + +OF_ASSUME_NONNULL_END Index: utils/ofarc/GZIPArchive.h ================================================================== --- utils/ofarc/GZIPArchive.h +++ utils/ofarc/GZIPArchive.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,22 +63,25 @@ { if (self == [GZIPArchive class]) app = (OFArc *)[OFApplication sharedApplication].delegate; } -+ (instancetype)archiveWithStream: (OF_KINDOF(OFStream *))stream - mode: (OFString *)mode - encoding: (OFStringEncoding)encoding -{ - return [[[self alloc] initWithStream: stream - mode: mode - encoding: encoding] autorelease]; -} - -- (instancetype)initWithStream: (OF_KINDOF(OFStream *))stream - mode: (OFString *)mode - encoding: (OFStringEncoding)encoding ++ (instancetype)archiveWithPath: (OFString *)path + stream: (OF_KINDOF(OFStream *))stream + mode: (OFString *)mode + encoding: (OFStringEncoding)encoding +{ + return [[[self alloc] initWithPath: path + stream: stream + mode: mode + encoding: encoding] autorelease]; +} + +- (instancetype)initWithPath: (OFString *)path + stream: (OF_KINDOF(OFStream *))stream + mode: (OFString *)mode + encoding: (OFStringEncoding)encoding { self = [super init]; @try { _stream = [[OFGZIPStream alloc] initWithStream: stream @@ -109,12 +112,12 @@ { OFString *fileName; OFFile *output; if (files.count != 0) { - [OFStdErr writeLine: - OF_LOCALIZED(@"cannot_extract_specific_file_from_gz", + [OFStdErr writeLine: OF_LOCALIZED( + @"cannot_extract_specific_file_from_gz", @"Cannot extract a specific file of a .gz archive!")]; app->_exitStatus = 1; return; } Index: utils/ofarc/LHAArchive.h ================================================================== --- utils/ofarc/LHAArchive.h +++ utils/ofarc/LHAArchive.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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 "OFApplication.h" #import "OFDate.h" #import "OFFileManager.h" #import "OFLocale.h" @@ -24,10 +26,12 @@ #import "OFStdIOStream.h" #import "OFString.h" #import "LHAArchive.h" #import "OFArc.h" + +#import "OFSetItemAttributesFailedException.h" static OFArc *app; static OFString * indent(OFString *string) @@ -61,33 +65,41 @@ setModificationDate(OFString *path, OFLHAArchiveEntry *entry) { OFFileAttributes attributes = [OFDictionary dictionaryWithObject: entry.modificationDate forKey: OFFileModificationDate]; - [[OFFileManager defaultManager] setAttributes: attributes - ofItemAtPath: path]; + @try { + [[OFFileManager defaultManager] setAttributes: attributes + ofItemAtPath: path]; + } @catch (OFSetItemAttributesFailedException *e) { + if (e.errNo != EISDIR) + @throw e; + } } @implementation LHAArchive + (void)initialize { if (self == [LHAArchive class]) app = (OFArc *)[OFApplication sharedApplication].delegate; } -+ (instancetype)archiveWithStream: (OF_KINDOF(OFStream *))stream - mode: (OFString *)mode - encoding: (OFStringEncoding)encoding ++ (instancetype)archiveWithPath: (OFString *)path + stream: (OF_KINDOF(OFStream *))stream + mode: (OFString *)mode + encoding: (OFStringEncoding)encoding { - return [[[self alloc] initWithStream: stream - mode: mode - encoding: encoding] autorelease]; + return [[[self alloc] initWithPath: path + stream: stream + mode: mode + encoding: encoding] autorelease]; } -- (instancetype)initWithStream: (OF_KINDOF(OFStream *))stream - mode: (OFString *)mode - encoding: (OFStringEncoding)encoding +- (instancetype)initWithPath: (OFString *)path + stream: (OF_KINDOF(OFStream *))stream + mode: (OFString *)mode + encoding: (OFStringEncoding)encoding { self = [super init]; @try { _archive = [[OFLHAArchive alloc] initWithStream: stream Index: utils/ofarc/Makefile ================================================================== --- utils/ofarc/Makefile +++ utils/ofarc/Makefile @@ -18,10 +18,8 @@ CPPFLAGS += -I../../src \ -I../../src/runtime \ -I../../src/exceptions \ -I../.. \ -DLOCALIZATION_DIR=\"${datadir}/ofarc/localization\" -LIBS := -L../../src -lobjfw \ - -L../../src/runtime -L../../src/runtime/linklib ${RUNTIME_LIBS} \ - ${LIBS} +LIBS := -L../../src -lobjfw -L../../src/runtime ${RUNTIME_LIBS} ${LIBS} LD = ${OBJC} LDFLAGS += ${LDFLAGS_RPATH} Index: utils/ofarc/OFArc.h ================================================================== --- utils/ofarc/OFArc.h +++ utils/ofarc/OFArc.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,15 +19,15 @@ #import "OFApplication.h" #import "OFArray.h" #import "OFFile.h" #import "OFFileManager.h" +#import "OFIRI.h" #import "OFLocale.h" #import "OFOptionsParser.h" #import "OFSandbox.h" #import "OFStdIOStream.h" -#import "OFURI.h" #import "OFArc.h" #import "GZIPArchive.h" #import "LHAArchive.h" #import "TarArchive.h" @@ -57,23 +57,23 @@ [stream writeString: @"\n"]; [stream writeLine: OF_LOCALIZED(@"full_usage", @"Options:\n" @" -a --append Append to archive\n" @" -c --create Create archive\n" - @" -C --directory Extract into the specified " + @" -C --directory= Extract into the specified " @"directory\n" - @" -E --encoding The encoding used by the archive " + @" -E --encoding= The encoding used by the archive " "(only tar files)\n" @" -f --force Force / overwrite files\n" @" -h --help Show this help\n" @" -l --list List all files in the archive\n" @" -n --no-clobber Never overwrite files\n" @" -p --print Print one or more files from the " @"archive\n" @" -q --quiet Quiet mode (no output, except " @"errors)\n" - @" -t --type Archive type (gz, lha, tar, tgz, " + @" -t --type= Archive type (gz, lha, tar, tgz, " @"zip)\n" @" -v --verbose Verbose output for file list\n" @" -x --extract Extract files")]; } @@ -165,11 +165,11 @@ [archive addFiles: expandedFiles]; } @implementation OFArc -- (void)applicationDidFinishLaunching +- (void)applicationDidFinishLaunching: (OFNotification *)notification { OFString *outputDir, *encodingString, *type; const OFOptionsParserOption options[] = { { 'a', @"append", 0, NULL, NULL }, { 'c', @"create", 0, NULL, NULL }, @@ -205,14 +205,15 @@ [OFApplication of_activateSandbox: sandbox]; #endif #ifndef OF_AMIGAOS - [OFLocale addLocalizationDirectory: @LOCALIZATION_DIR]; + [OFLocale addLocalizationDirectoryIRI: + [OFIRI fileIRIWithPath: @LOCALIZATION_DIR]]; #else - [OFLocale addLocalizationDirectory: - @"PROGDIR:/share/ofarc/localization"]; + [OFLocale addLocalizationDirectoryIRI: + [OFIRI fileIRIWithPath: @"PROGDIR:/share/ofarc/localization"]]; #endif optionsParser = [OFOptionsParser parserWithOptions: options]; while ((option = [optionsParser nextOption]) != '\0') { switch (option) { @@ -460,11 +461,11 @@ encoding: [OFLocale encoding]]; [OFStdErr writeString: @"\r"]; [OFStdErr writeLine: OF_LOCALIZED( @"failed_to_create_directory", @"Failed to create directory %[dir]: %[error]", - @"dir", e.URI.fileSystemRepresentation, + @"dir", e.IRI.fileSystemRepresentation, @"error", error)]; _exitStatus = 1; } @catch (OFOpenItemFailedException *e) { OFString *error = [OFString stringWithCString: strerror(e.errNo) @@ -485,15 +486,17 @@ } [OFApplication terminateWithStatus: _exitStatus]; } -- (id )openArchiveWithPath: (OFString *)path +- (id )openArchiveWithPath: (OFString *)path_ type: (OFString *)type mode: (char)mode encoding: (OFStringEncoding)encoding { + /* To make clang-analyzer happy about assigning nil to path later. */ + OFString *path = path_; OFString *modeString, *fileModeString; OFStream *file = nil; id archive = nil; [_archivePath release]; @@ -531,10 +534,12 @@ file = OFStdIn; break; default: @throw [OFInvalidArgumentException exception]; } + + path = nil; } else { @try { file = [OFFile fileWithPath: path mode: fileModeString]; } @catch (OFOpenItemFailedException *e) { OFString *error = [OFString @@ -565,32 +570,37 @@ type = @"zip"; } @try { if ([type isEqual: @"gz"]) - archive = [GZIPArchive archiveWithStream: file - mode: modeString - encoding: encoding]; + archive = [GZIPArchive archiveWithPath: path + stream: file + mode: modeString + encoding: encoding]; else if ([type isEqual: @"lha"]) - archive = [LHAArchive archiveWithStream: file - mode: modeString - encoding: encoding]; + archive = [LHAArchive archiveWithPath: path + stream: file + mode: modeString + encoding: encoding]; else if ([type isEqual: @"tar"]) - archive = [TarArchive archiveWithStream: file - mode: modeString - encoding: encoding]; + archive = [TarArchive archiveWithPath: path + stream: file + mode: modeString + encoding: encoding]; else if ([type isEqual: @"tgz"]) { OFStream *GZIPStream = [OFGZIPStream streamWithStream: file mode: modeString]; - archive = [TarArchive archiveWithStream: GZIPStream - mode: modeString - encoding: encoding]; + archive = [TarArchive archiveWithPath: path + stream: GZIPStream + mode: modeString + encoding: encoding]; } else if ([type isEqual: @"zip"]) - archive = [ZIPArchive archiveWithStream: file - mode: modeString - encoding: encoding]; + archive = [ZIPArchive archiveWithPath: path + stream: file + mode: modeString + encoding: encoding]; else { [OFStdErr writeLine: OF_LOCALIZED( @"unknown_archive_type", @"Unknown archive type: %[type]", @"type", type)]; @@ -637,15 +647,15 @@ } return archive; error: - if (mode == 'c') + if (mode == 'c' && path != nil) [[OFFileManager defaultManager] removeItemAtPath: path]; [OFApplication terminateWithStatus: 1]; - return nil; + abort(); } - (bool)shouldExtractFile: (OFString *)fileName outFileName: (OFString *)outFileName { Index: utils/ofarc/TarArchive.h ================================================================== --- utils/ofarc/TarArchive.h +++ utils/ofarc/TarArchive.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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 "OFApplication.h" #import "OFDate.h" #import "OFFileManager.h" #import "OFLocale.h" @@ -24,10 +26,12 @@ #import "OFStdIOStream.h" #import "OFString.h" #import "TarArchive.h" #import "OFArc.h" + +#import "OFSetItemAttributesFailedException.h" static OFArc *app; static void setPermissions(OFString *path, OFTarArchiveEntry *entry) @@ -54,33 +58,41 @@ return; attributes = [OFDictionary dictionaryWithObject: modificationDate forKey: OFFileModificationDate]; - [[OFFileManager defaultManager] setAttributes: attributes - ofItemAtPath: path]; + @try { + [[OFFileManager defaultManager] setAttributes: attributes + ofItemAtPath: path]; + } @catch (OFSetItemAttributesFailedException *e) { + if (e.errNo != EISDIR) + @throw e; + } } @implementation TarArchive + (void)initialize { if (self == [TarArchive class]) app = (OFArc *)[OFApplication sharedApplication].delegate; } -+ (instancetype)archiveWithStream: (OF_KINDOF(OFStream *))stream - mode: (OFString *)mode - encoding: (OFStringEncoding)encoding ++ (instancetype)archiveWithPath: (OFString *)path + stream: (OF_KINDOF(OFStream *))stream + mode: (OFString *)mode + encoding: (OFStringEncoding)encoding { - return [[[self alloc] initWithStream: stream - mode: mode - encoding: encoding] autorelease]; + return [[[self alloc] initWithPath: path + stream: stream + mode: mode + encoding: encoding] autorelease]; } -- (instancetype)initWithStream: (OF_KINDOF(OFStream *))stream - mode: (OFString *)mode - encoding: (OFStringEncoding)encoding +- (instancetype)initWithPath: (OFString *)path + stream: (OF_KINDOF(OFStream *))stream + mode: (OFString *)mode + encoding: (OFStringEncoding)encoding { self = [super init]; @try { _archive = [[OFTarArchive alloc] initWithStream: stream Index: utils/ofarc/ZIPArchive.h ================================================================== --- utils/ofarc/ZIPArchive.h +++ utils/ofarc/ZIPArchive.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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 "OFZIPArchive.h" #import "Archive.h" -@interface ZIPArchive: OFObject +@interface ZIPArchive: OFObject { + OFString *_path; OFZIPArchive *_archive; } @end Index: utils/ofarc/ZIPArchive.m ================================================================== --- utils/ofarc/ZIPArchive.m +++ utils/ofarc/ZIPArchive.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,10 +31,11 @@ #import "OFArc.h" #import "OFInvalidFormatException.h" #import "OFOpenItemFailedException.h" #import "OFOutOfRangeException.h" +#import "OFSetItemAttributesFailedException.h" static OFArc *app; static void setPermissions(OFString *path, OFZIPArchiveEntry *entry) @@ -64,39 +65,49 @@ return; attributes = [OFDictionary dictionaryWithObject: modificationDate forKey: OFFileModificationDate]; - [[OFFileManager defaultManager] setAttributes: attributes - ofItemAtPath: path]; + @try { + [[OFFileManager defaultManager] setAttributes: attributes + ofItemAtPath: path]; + } @catch (OFSetItemAttributesFailedException *e) { + if (e.errNo != EISDIR) + @throw e; + } } @implementation ZIPArchive + (void)initialize { if (self == [ZIPArchive class]) app = (OFArc *)[OFApplication sharedApplication].delegate; } -+ (instancetype)archiveWithStream: (OF_KINDOF(OFStream *))stream - mode: (OFString *)mode - encoding: (OFStringEncoding)encoding ++ (instancetype)archiveWithPath: (OFString *)path + stream: (OF_KINDOF(OFStream *))stream + mode: (OFString *)mode + encoding: (OFStringEncoding)encoding { - return [[[self alloc] initWithStream: stream - mode: mode - encoding: encoding] autorelease]; + return [[[self alloc] initWithPath: path + stream: stream + mode: mode + encoding: encoding] autorelease]; } -- (instancetype)initWithStream: (OF_KINDOF(OFStream *))stream - mode: (OFString *)mode - encoding: (OFStringEncoding)encoding +- (instancetype)initWithPath: (OFString *)path + stream: (OF_KINDOF(OFStream *))stream + mode: (OFString *)mode + encoding: (OFStringEncoding)encoding { self = [super init]; @try { + _path = [path copy]; _archive = [[OFZIPArchive alloc] initWithStream: stream mode: mode]; + _archive.delegate = self; } @catch (id e) { [self release]; @throw e; } @@ -103,14 +114,37 @@ return self; } - (void)dealloc { + [_path release]; [_archive release]; [super dealloc]; } + +- (OFSeekableStream *)archive: (OFZIPArchive *)archive + wantsPartNumbered: (unsigned int)partNumber + lastPartNumber: (unsigned int)lastPartNumber +{ + OFString *path; + + if ([_path.pathExtension caseInsensitiveCompare: @"zip"] != + OFOrderedSame) + return nil; + + if (partNumber > 98) + return nil; + + if (partNumber == lastPartNumber) + path = _path; + else + path = [_path.stringByDeletingPathExtension + stringByAppendingFormat: @".z%02u", partNumber + 1]; + + return [OFFile fileWithPath: path mode: @"r"]; +} - (void)listFiles { for (OFZIPArchiveEntry *entry in _archive.entries) { void *pool = objc_autoreleasePoolPush(); Index: utils/ofarc/localization/de.json ================================================================== --- utils/ofarc/localization/de.json +++ utils/ofarc/localization/de.json @@ -1,23 +1,34 @@ +/* + * German localization for ofarc. + * + * Copyright (c) 2017-2024 Jonathan Schleifer + * + * Permission to use, copy, modify, and/or distribute this localization for + * any purpose with or without fee is hereby granted. + */ + +/* vim: se ft=javascript sw=4 et: */ + { - "usage": [ + usage: [ "Benutzung: %[prog] -[acCfhlnpqtvx] archiv.zip [datei1 datei2 ...]" ], - "full_usage": [ + full_usage: [ "Optionen:\n", " -a --append Zu Archiv hinzufügen\n", " -c --create Archiv erstellen\n", - " -C --directory In angegebenes Verzeichnis entpacken\n", - " -E --encoding Das Encoding des Archivs (nur tar-Dateien)\n", + " -C --directory= In angegebenes Verzeichnis entpacken\n", + " -E --encoding= Das Encoding des Archivs (nur tar-Dateien)\n", " -f --force Existierende Dateien überschreiben\n", " -h --help Diese Hilfe anzeigen\n", " -l --list Alle Dateien im Archiv auflisten\n", " -n --no-clobber Dateien niemals überschreiben\n", " -p --print Eine oder mehr Dateien aus dem Archiv ausgeben", "\n", " -q --quiet Ruhiger Modus (keine Ausgabe außer Fehler)\n", - " -t --type Archiv-Typ (gz, lha, tar, tgz, zip)\n", + " -t --type= Archiv-Typ (gz, lha, tar, tgz, zip)\n", " -v --verbose Ausführlicher Modus für Datei-Liste\n", " -x --extract Dateien entpacken" ], "2_options_mutually_exclusive": [ "Fehler: -%[shortopt1] / --%[longopt1] und ", @@ -27,104 +38,104 @@ "Fehler: -%[shortopt1] / --%[longopt1], -%[shortopt2] / ", "--%[longopt2], -%[shortopt3] / --%[longopt3], ", "-%[shortopt4] / --%[longopt4] und\n", " -%[shortopt5] / --%[longopt5] schließen sich gegenseitig aus!" ], - "option_takes_no_argument": "%[prog]: Option --%[opt] nimmt kein Argument", - "long_option_requires_argument": [ + option_takes_no_argument: "%[prog]: Option --%[opt] nimmt kein Argument", + long_option_requires_argument: [ "%[prog]: Option --%[opt] benötigt ein Argument" ], - "option_requires_argument": "%[prog]: Option -%[opt] benötigt ein Argument", - "unknown_long_option": "%[prog]: Unbekannte Option: --%[opt]", - "unknown_option": "%[prog]: Unbekannte Option: -%[opt]", - "invalid_encoding": "%[prog]: Invalid encoding: %[encoding]", - "writing_not_supported": [ + option_requires_argument: "%[prog]: Option -%[opt] benötigt ein Argument", + unknown_long_option: "%[prog]: Unbekannte Option: --%[opt]", + unknown_option: "%[prog]: Unbekannte Option: -%[opt]", + invalid_encoding: "%[prog]: Invalid encoding: %[encoding]", + writing_not_supported: [ "Schreiben von Dateien des Typs %[type] wird (noch) nicht unterstützt!" ], - "failed_to_create_directory": [ + failed_to_create_directory: [ "Fehler beim Erstellen des Verzeichnis %[dir]: %[error]" ], - "failed_to_open_file": "Fehler beim Öffnen der Datei %[file]: %[error]", - "unknown_archive_type": "Unbekannter Archivtyp: %[type]", - "failed_to_read_file": "Fehler beim Lesen der Datei %[file]: %[error]", - "failed_to_write_file": "Fehler beim Schreiben der Datei %[file]: %[error]", - "failed_to_seek_in_file": "Fehler beim Suchen in Datei %[file]: %[error]", - "file_is_not_a_valid_archive": "Datei %[file] ist kein gültiges Archiv!", - "file_skipped": "übersprungen", - "ask_overwrite": "%[file] überschreiben? [ynAN?]", - "ask_overwrite_help": [ + failed_to_open_file: "Fehler beim Öffnen der Datei %[file]: %[error]", + unknown_archive_type: "Unbekannter Archivtyp: %[type]", + failed_to_read_file: "Fehler beim Lesen der Datei %[file]: %[error]", + failed_to_write_file: "Fehler beim Schreiben der Datei %[file]: %[error]", + failed_to_seek_in_file: "Fehler beim Suchen in Datei %[file]: %[error]", + file_is_not_a_valid_archive: "Datei %[file] ist kein gültiges Archiv!", + file_skipped: "übersprungen", + ask_overwrite: "%[file] überschreiben? [ynAN?]", + ask_overwrite_help: [ " y: Ja\n", " n: Nein\n", " A: Immer\n", " N: Nie" ], - "skipping_file": "Überspringe %[file]...", - "extracting_file": "Entpacke %[file]...", - "extracting_file_percent": "Entpacke %[file]... %[percent]%", - "extracting_file_done": "Entpacke %[file]... fertig", - "cannot_list_gz": "Kann Dateien eines .gz-Archivs nicht auflisten!", - "cannot_extract_specific_file_from_gz": [ + skipping_file: "Überspringe %[file]...", + extracting_file: "Entpacke %[file]...", + extracting_file_percent: "Entpacke %[file]... %[percent]%", + extracting_file_done: "Entpacke %[file]... fertig", + cannot_list_gz: "Kann Dateien eines .gz-Archivs nicht auflisten!", + cannot_extract_specific_file_from_gz: [ "Kann keine spezifische Datei aus einem .gz-Archiv entpacken!" ], - "cannot_print_specific_file_from_gz": [ + cannot_print_specific_file_from_gz: [ "Kann keine spezifische Datei aus einem .gz-Archiv ausgeben!" ], - "list_size": [ + list_size: [ "Größe: ", [ {"size == 1": "1 Byte"}, {"": "%[size] Bytes"} ] ], - "list_posix_permissions": "POSIX-Berechtigungen: %[perm]", - "list_owner_account_id": "Besitzerkontennummer: %[id]", - "list_group_owner_account_id": "Gruppenbesitzerkontennummer: %[id]", - "list_owner_account_name": "Besitzerkontenname: %[name]", - "list_group_owner_account_name": "Gruppebesitzerkontenname: %[name]", - "list_header_level": "Header-Level: %[level]", - "list_modification_date": "Änderungsdatum: %[date]", - "list_type_normal": "Typ: Normale Datei", - "list_type_hardlink": "Typ: Harter Link", - "list_type_symlink": "Typ: Symbolischer Link", - "list_link_target": "Zieldateiname: %[target]", - "list_type_character_device": "Typ: Zeichenorientiertes Gerät", - "list_type_block_device": "Typ: Blockorientiertes Gerät", - "list_device_major": "Major-Nummer des Geräts: %[major]", - "list_device_minor": "Minor-Nummer des Geräts: %[minor]", - "list_type_directory": "Typ: Verzeichnis", - "list_type_fifo": "Typ: FIFO", - "list_type_contiguous_file": "Typ: Zusammenhängende Datei", - "list_type_unknown": "Typ: Unbekannt", - "list_compressed_size": [ + list_posix_permissions: "POSIX-Berechtigungen: %[perm]", + list_owner_account_id: "Besitzerkontennummer: %[id]", + list_group_owner_account_id: "Gruppenbesitzerkontennummer: %[id]", + list_owner_account_name: "Besitzerkontenname: %[name]", + list_group_owner_account_name: "Gruppebesitzerkontenname: %[name]", + list_header_level: "Header-Level: %[level]", + list_modification_date: "Änderungsdatum: %[date]", + list_type_normal: "Typ: Normale Datei", + list_type_hardlink: "Typ: Harter Link", + list_type_symlink: "Typ: Symbolischer Link", + list_link_target: "Zieldateiname: %[target]", + list_type_character_device: "Typ: Zeichenorientiertes Gerät", + list_type_block_device: "Typ: Blockorientiertes Gerät", + list_device_major: "Major-Nummer des Geräts: %[major]", + list_device_minor: "Minor-Nummer des Geräts: %[minor]", + list_type_directory: "Typ: Verzeichnis", + list_type_fifo: "Typ: FIFO", + list_type_contiguous_file: "Typ: Zusammenhängende Datei", + list_type_unknown: "Typ: Unbekannt", + list_compressed_size: [ "Komprimierte Größe: ", [ {"size == 1": "1 Byte"}, {"": "%[size] Bytes"} ] ], - "list_uncompressed_size": [ + list_uncompressed_size: [ "Unkomprimierte Größe: ", [ {"size == 1": "1 Byte"}, {"": "%[size] Bytes"} ] ], - "list_compression_method": "Kompressionsmethode: %[method]", - "list_osid": "Betriebssystem-Identifikator: %[osid]", - "list_extensions": "Erweiterungen: %[extensions]", - "list_version_made_by": "Erstellt mit Version: %[version]", - "list_min_version_needed": "Mindestens benötigte Version: %[version]", - "list_general_purpose_bit_flag": "General Purpose Bit Flag: %[gpbf]", - "list_extra_field": "Extra-Feld: %[extra]", - "list_comment": "Kommentar: %[comment]", - "refusing_to_extract_file": "Verweigere Entpacken von %[file]!", - "file_not_in_archive": "Datei %[file] ist nicht im Archiv!", - "print_no_file_specified": [ + list_compression_method: "Kompressionsmethode: %[method]", + list_osid: "Betriebssystem-Identifikator: %[osid]", + list_extensions: "Erweiterungen: %[extensions]", + list_version_made_by: "Erstellt mit Version: %[version]", + list_min_version_needed: "Mindestens benötigte Version: %[version]", + list_general_purpose_bit_flag: "General Purpose Bit Flag: %[gpbf]", + list_extra_field: "Extra-Feld: %[extra]", + list_comment: "Kommentar: %[comment]", + refusing_to_extract_file: "Verweigere Entpacken von %[file]!", + file_not_in_archive: "Datei %[file] ist nicht im Archiv!", + print_no_file_specified: [ "Benötige eine oder mehrere Dateien zum Ausgeben!" ], - "add_no_file_specified": [ + add_no_file_specified: [ "Benötige eine oder mehrere Dateien zum Hinzufügen!" ], - "adding_file": "Füge %[file] hinzu...", - "adding_file_percent": "Füge %[file] hinzu... %[percent]%", - "adding_file_done": "Füge %[file] hinzu... fertig" + adding_file: "Füge %[file] hinzu...", + adding_file_percent: "Füge %[file] hinzu... %[percent]%", + adding_file_done: "Füge %[file] hinzu... fertig", } Index: utils/ofarc/localization/localizations.json ================================================================== --- utils/ofarc/localization/localizations.json +++ utils/ofarc/localization/localizations.json @@ -1,11 +1,22 @@ +/* + * Localization mapping for ofarc. + * + * Copyright (c) 2017-2023 Jonathan Schleifer + * + * Permission to use, copy, modify, and/or distribute this mapping for any + * purpose with or without fee is hereby granted. + */ + +/* vim: se ft=javascript sw=4 et: */ + { - "de": { + de: { "": "de" }, - "deutsch": { + deutsch: { "": "de" }, - "german": { + german: { "": "de" - } + }, } Index: utils/ofdns/Makefile ================================================================== --- utils/ofdns/Makefile +++ utils/ofdns/Makefile @@ -14,10 +14,8 @@ CPPFLAGS += -I../../src \ -I../../src/runtime \ -I../../src/exceptions \ -I../.. \ -DLOCALIZATION_DIR=\"${datadir}/ofdns/localization\" -LIBS := -L../../src -lobjfw \ - -L../../src/runtime -L../../src/runtime/linklib ${RUNTIME_LIBS} \ - ${LIBS} +LIBS := -L../../src -lobjfw -L../../src/runtime ${RUNTIME_LIBS} ${LIBS} LD = ${OBJC} LDFLAGS += ${LDFLAGS_RPATH} Index: utils/ofdns/OFDNS.m ================================================================== --- utils/ofdns/OFDNS.m +++ utils/ofdns/OFDNS.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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" #import "OFApplication.h" #import "OFArray.h" #import "OFDNSResolver.h" +#import "OFIRI.h" #import "OFLocale.h" #import "OFOptionsParser.h" #import "OFSandbox.h" #import "OFStdIOStream.h" @@ -33,28 +34,29 @@ OF_APPLICATION_DELEGATE(OFDNS) static void help(OFStream *stream, bool full, int status) { - [OFStdErr writeLine: - OF_LOCALIZED(@"usage", + [OFStdErr writeLine: OF_LOCALIZED(@"usage", @"Usage: %[prog] -[chst] domain1 [domain2 ...]", @"prog", [OFApplication programName])]; if (full) { [stream writeString: @"\n"]; [stream writeLine: OF_LOCALIZED(@"full_usage", @"Options:\n " - @"-c --class " + @"-c --class= " @" The DNS class to query (defaults to IN)\n " - @"-h --help " + @"-h --help " @" Show this help\n " - @"-s --server" + @"-s --server=" @" The server to query\n " - @"-t --type " + @"-t --type= " @" The record type to query (defaults to ALL, can be " - @"repeated)")]; + @"repeated)\n " + @" --tcp " + @" Force using TCP for the query")]; } [OFApplication terminateWithStatus: status]; } @@ -67,29 +69,30 @@ _inFlight--; if (exception == nil) [OFStdOut writeFormat: @"%@\n", response]; else { - [OFStdErr writeLine: OF_LOCALIZED( - @"failed_to_resolve", + [OFStdErr writeLine: OF_LOCALIZED(@"failed_to_resolve", @"Failed to resolve: %[exception]", @"exception", exception)]; _errors++; } if (_inFlight == 0) [OFApplication terminateWithStatus: _errors]; } -- (void)applicationDidFinishLaunching +- (void)applicationDidFinishLaunching: (OFNotification *)notification { OFString *DNSClassString, *server; + bool forceTCP; const OFOptionsParserOption options[] = { { 'c', @"class", 1, NULL, &DNSClassString }, { 'h', @"help", 0, NULL, NULL }, { 's', @"server", 1, NULL, &server }, { 't', @"type", 1, NULL, NULL }, + { '\0', @"tcp", 0, &forceTCP, NULL }, { '\0', nil, 0, NULL, NULL } }; OFMutableArray OF_GENERIC(OFString *) *recordTypes; OFOptionsParser *optionsParser; OFUnichar option; @@ -97,14 +100,15 @@ OFDNSResolver *resolver; OFDNSClass DNSClass; #ifdef OF_HAVE_FILES # ifndef OF_AMIGAOS - [OFLocale addLocalizationDirectory: @LOCALIZATION_DIR]; + [OFLocale addLocalizationDirectoryIRI: + [OFIRI fileIRIWithPath: @LOCALIZATION_DIR]]; # else - [OFLocale addLocalizationDirectory: - @"PROGDIR:/share/ofdns/localization"]; + [OFLocale addLocalizationDirectoryIRI: + [OFIRI fileIRIWithPath: @"PROGDIR:/share/ofdns/localization"]]; # endif #endif #ifdef OF_HAVE_SANDBOX OFSandbox *sandbox = [[OFSandbox alloc] init]; @@ -178,20 +182,21 @@ if (remainingArguments.count < 1) help(OFStdErr, false, 1); resolver = [OFDNSResolver resolver]; + resolver.configReloadInterval = 0; + resolver.forcesTCP = forceTCP; + DNSClass = (DNSClassString != nil ? OFDNSClassParseName(DNSClassString) : OFDNSClassIN); if (recordTypes.count == 0) [recordTypes addObject: @"ALL"]; - if (server != nil) { - resolver.configReloadInterval = 0; + if (server != nil) resolver.nameServers = [OFArray arrayWithObject: server]; - } for (OFString *domainName in remainingArguments) { for (OFString *recordTypeString in recordTypes) { OFDNSRecordType recordType = OFDNSRecordTypeParseName(recordTypeString); Index: utils/ofdns/localization/de.json ================================================================== --- utils/ofdns/localization/de.json +++ utils/ofdns/localization/de.json @@ -1,18 +1,30 @@ +/* + * German localization for ofdns. + * + * Copyright (c) 2020-2024 Jonathan Schleifer + * + * Permission to use, copy, modify, and/or distribute this localization for + * any purpose with or without fee is hereby granted. + */ + +/* vim: se ft=javascript sw=4 et: */ + { - "usage": "Benutzung: %[prog] -[chst] domain1 [domain2 ...]", - "full_usage": [ + usage: "Benutzung: %[prog] -[chst] domain1 [domain2 ...]", + full_usage: [ "Optionen:\n", - " -c --class Die anzufragende DNS-Klasse (standardmäßig IN)\n", - " -h --help Diese Hilfe anzeigen\n", - " -s --server Der abzufragende Server\n", - " -t --type Der anzufragende Record-Typ (standardmäßig ALL,\n", - " kann wiederholt werden)" + " -c --class= Die anzufragende DNS-Klasse (standardmäßig IN)\n", + " -h --help Diese Hilfe anzeigen\n", + " -s --server= Der abzufragende Server\n", + " -t --type= Der anzufragende Record-Typ (standardmäßig ALL,\n", + " kann wiederholt werden)\n", + " --tcp Benutzung von TCP erzwingen" ], - "long_option_requires_argument": [ + long_option_requires_argument: [ "%[prog]: Option --%[opt] benötigt ein Argument" ], - "option_requires_argument": "%[prog]: Option -%[opt] benötigt ein Argument", - "unknown_long_option": "%[prog]: Unbekannte Option: --%[opt]", - "unknown_option": "%[prog]: Unbekannte Option: -%[opt]", - "failed_to_resolve": "Auflösen fehlgeschlagen: %[exception]" + option_requires_argument: "%[prog]: Option -%[opt] benötigt ein Argument", + unknown_long_option: "%[prog]: Unbekannte Option: --%[opt]", + unknown_option: "%[prog]: Unbekannte Option: -%[opt]", + failed_to_resolve: "Auflösen fehlgeschlagen: %[exception]", } Index: utils/ofdns/localization/localizations.json ================================================================== --- utils/ofdns/localization/localizations.json +++ utils/ofdns/localization/localizations.json @@ -1,11 +1,22 @@ +/* + * Localization mapping for ofdns. + * + * Copyright (c) 2020-2023 Jonathan Schleifer + * + * Permission to use, copy, modify, and/or distribute this mapping for any + * purpose with or without fee is hereby granted. + */ + +/* vim: se ft=javascript sw=4 et: */ + { - "de": { + de: { "": "de" }, - "deutsch": { + deutsch: { "": "de" }, - "german": { + german: { "": "de" - } + }, } Index: utils/ofhash/Makefile ================================================================== --- utils/ofhash/Makefile +++ utils/ofhash/Makefile @@ -14,10 +14,8 @@ CPPFLAGS += -I../../src \ -I../../src/runtime \ -I../../src/exceptions \ -I../.. \ -DLOCALIZATION_DIR=\"${datadir}/ofhash/localization\" -LIBS := -L../../src -lobjfw \ - -L../../src/runtime -L../../src/runtime/linklib ${RUNTIME_LIBS} \ - ${LIBS} +LIBS := -L../../src -lobjfw -L../../src/runtime ${RUNTIME_LIBS} ${LIBS} LD = ${OBJC} LDFLAGS += ${LDFLAGS_RPATH} Index: utils/ofhash/OFHash.m ================================================================== --- utils/ofhash/OFHash.m +++ utils/ofhash/OFHash.m @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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" #import "OFApplication.h" #import "OFArray.h" #import "OFFile.h" +#import "OFIRI.h" #import "OFLocale.h" #import "OFMD5Hash.h" #import "OFOptionsParser.h" #import "OFRIPEMD160Hash.h" #import "OFSHA1Hash.h" @@ -66,11 +67,11 @@ [OFStdOut writeFormat: @" %@\n", path]; } @implementation OFHash -- (void)applicationDidFinishLaunching +- (void)applicationDidFinishLaunching: (OFNotification *)notification { int exitStatus = 0; bool calculateMD5, calculateRIPEMD160, calculateSHA1, calculateSHA224; bool calculateSHA256, calculateSHA384, calculateSHA512; const OFOptionsParserOption options[] = { @@ -93,30 +94,31 @@ OFSHA256Hash *SHA256Hash = nil; OFSHA384Hash *SHA384Hash = nil; OFSHA512Hash *SHA512Hash = nil; #ifndef OF_AMIGAOS - [OFLocale addLocalizationDirectory: @LOCALIZATION_DIR]; + [OFLocale addLocalizationDirectoryIRI: + [OFIRI fileIRIWithPath: @LOCALIZATION_DIR]]; #else - [OFLocale addLocalizationDirectory: - @"PROGDIR:/share/ofhash/localization"]; + [OFLocale addLocalizationDirectoryIRI: + [OFIRI fileIRIWithPath: @"PROGDIR:/share/ofhash/localization"]]; #endif while ((option = [optionsParser nextOption]) != '\0') { switch (option) { case '?': if (optionsParser.lastLongOption != nil) - [OFStdErr writeLine: - OF_LOCALIZED(@"unknown_long_option", + [OFStdErr writeLine: OF_LOCALIZED( + @"unknown_long_option", @"%[prog]: Unknown option: --%[opt]", @"prog", [OFApplication programName], @"opt", optionsParser.lastLongOption)]; else { OFString *optStr = [OFString stringWithFormat: - @"%c", optionsParser.lastOption]; - [OFStdErr writeLine: - OF_LOCALIZED(@"unknown_option", + @"%C", optionsParser.lastOption]; + [OFStdErr writeLine: OF_LOCALIZED( + @"unknown_option", @"%[prog]: Unknown option: -%[opt]", @"prog", [OFApplication programName], @"opt", optStr)]; } Index: utils/ofhash/localization/de.json ================================================================== --- utils/ofhash/localization/de.json +++ utils/ofhash/localization/de.json @@ -1,10 +1,21 @@ +/* + * German localization for ofhash. + * + * Copyright (c) 2017-2023 Jonathan Schleifer + * + * Permission to use, copy, modify, and/or distribute this localization for + * any purpose with or without fee is hereby granted. + */ + +/* vim: se ft=javascript sw=4 et: */ + { - "usage": [ + usage: [ "Benutzung: %[prog] [--md5] [--ripemd160] [--sha1] [--sha224] ", "[--sha256] [--sha384] [--sha512] datei1 [datei2 ...]" ], - "unknown_long_option": "%[prog]: Unbekannte Option: --%[opt]", - "unknown_option": "%[prog]: Unbekannte Option: -%[opt]", - "failed_to_open_file": "Fehler beim Öffnen der Datei %[file]: %[error]", - "failed_to_read_file": "Fehler beim Lesen der Datei %[file]: %[error]" + unknown_long_option: "%[prog]: Unbekannte Option: --%[opt]", + unknown_option: "%[prog]: Unbekannte Option: -%[opt]", + failed_to_open_file: "Fehler beim Öffnen der Datei %[file]: %[error]", + failed_to_read_file: "Fehler beim Lesen der Datei %[file]: %[error]", } Index: utils/ofhash/localization/localizations.json ================================================================== --- utils/ofhash/localization/localizations.json +++ utils/ofhash/localization/localizations.json @@ -1,11 +1,22 @@ +/* + * Localization mapping for ofhash. + * + * Copyright (c) 2017-2023 Jonathan Schleifer + * + * Permission to use, copy, modify, and/or distribute this mapping for any + * purpose with or without fee is hereby granted. + */ + +/* vim: se ft=javascript sw=4 et: */ + { - "de": { + de: { "": "de" }, - "deutsch": { + deutsch: { "": "de" }, - "german": { + german: { "": "de" - } + }, } Index: utils/ofhttp/Makefile ================================================================== --- utils/ofhttp/Makefile +++ utils/ofhttp/Makefile @@ -15,13 +15,11 @@ CPPFLAGS += -I../../src \ -I../../src/runtime \ -I../../src/exceptions \ -I../../src/tls \ -I../.. \ - -DLOCALIZATION_DIR='"${datadir}/ofhttp/localization"' \ - -DLIB_PREFIX='"${LIB_PREFIX}"' \ - -DLIB_SUFFIX='"${LIB_SUFFIX}"' + -DLOCALIZATION_DIR='"${datadir}/ofhttp/localization"' LIBS := -L../../src -L../../src/tls ${OFHTTP_LIBS} -lobjfw \ - -L../../src/runtime -L../../src/runtime/linklib ${RUNTIME_LIBS} \ + -L../../src/runtime ${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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It 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,16 +16,18 @@ #include "config.h" #import "OFApplication.h" #import "OFArray.h" #import "OFData.h" +#import "OFDate.h" #import "OFDictionary.h" #import "OFFile.h" #import "OFFileManager.h" #import "OFHTTPClient.h" #import "OFHTTPRequest.h" #import "OFHTTPResponse.h" +#import "OFIRI.h" #import "OFLocale.h" #import "OFOptionsParser.h" #ifdef OF_HAVE_PLUGINS # import "OFPlugin.h" #endif @@ -32,11 +34,10 @@ #import "OFSandbox.h" #import "OFStdIOStream.h" #import "OFSystemInfo.h" #import "OFTCPSocket.h" #import "OFTLSStream.h" -#import "OFURI.h" #ifdef HAVE_TLS_SUPPORT # import "ObjFWTLS.h" #endif @@ -48,10 +49,12 @@ #import "OFInvalidServerResponseException.h" #import "OFOpenItemFailedException.h" #import "OFOutOfRangeException.h" #import "OFReadFailedException.h" #import "OFResolveHostFailedException.h" +#import "OFSetItemAttributesFailedException.h" +#import "OFTLSHandshakeFailedException.h" #import "OFUnsupportedProtocolException.h" #import "OFWriteFailedException.h" #import "ProgressBar.h" @@ -60,12 +63,12 @@ #define KIBIBYTE (1024) @interface OFHTTP: OFObject { - OFArray OF_GENERIC(OFString *) *_URIs; - size_t _URIIndex; + OFArray OF_GENERIC(OFString *) *_IRIs; + size_t _IRIIndex; int _errorCode; OFString *_outputPath, *_currentFileName; bool _continue, _force, _detectFileName, _detectFileNameRequest; bool _detectedFileName, _quiet, _verbose, _insecure, _ignoreStatus; bool _useUnicode; @@ -77,11 +80,11 @@ OFStream *_output; unsigned long long _received, _length, _resumedFrom; ProgressBar *_progressBar; } -- (void)downloadNextURI; +- (void)downloadNextIRI; @end #ifdef HAVE_TLS_SUPPORT void _reference_to_ObjFWTLS(void) @@ -93,38 +96,37 @@ OF_APPLICATION_DELEGATE(OFHTTP) static void help(OFStream *stream, bool full, int status) { - [OFStdErr writeLine: - OF_LOCALIZED(@"usage", - @"Usage: %[prog] -[cehHmoOPqv] uri1 [uri2 ...]", + [OFStdErr writeLine: OF_LOCALIZED(@"usage", + @"Usage: %[prog] -[cehHmoOPqv] iri1 [iri2 ...]", @"prog", [OFApplication programName])]; if (full) { [stream writeString: @"\n"]; [stream writeLine: OF_LOCALIZED(@"full_usage", @"Options:\n " - @"-b --body " + @"-b --body= " @" Specify the file to send as body\n " @" " @" (- for standard input)\n " @"-c --continue " @" Continue download of existing file\n " @"-f --force " @" Force / overwrite existing file\n " @"-h --help " @" Show this help\n " - @"-H --header " + @"-H --header= " @" Add a header (e.g. X-Foo:Bar)\n " - @"-m --method " + @"-m --method= " @" Set the method of the HTTP request\n " - @"-o --output " + @"-o --output= " @" Specify output file name\n " @"-O --detect-filename" @" Do a HEAD request to detect the file name\n " - @"-P --proxy " + @"-P --proxy= " @" Specify SOCKS5 proxy\n " @"-q --quiet " @" Quiet mode (no output, except errors)\n " @"-v --verbose " @" Verbose mode (print headers)\n " @@ -369,11 +371,11 @@ void *pool = objc_autoreleasePoolPush(); method = method.uppercaseString; @try { - _method = OFHTTPRequestMethodParseName(method); + _method = OFHTTPRequestMethodParseString(method); } @catch (OFInvalidArgumentException *e) { [OFStdErr writeLine: OF_LOCALIZED(@"invalid_input_method", @"%[prog]: Invalid request method %[method]!", @"prog", [OFApplication programName], @"method", method)]; @@ -410,11 +412,11 @@ @"prog", [OFApplication programName])]; [OFApplication terminateWithStatus: 1]; } } -- (void)applicationDidFinishLaunching +- (void)applicationDidFinishLaunching: (OFNotification *)notification { OFString *outputPath; const OFOptionsParserOption options[] = { { 'b', @"body", 1, NULL, NULL }, { 'c', @"continue", 0, &_continue, NULL }, @@ -449,14 +451,15 @@ [OFApplication of_activateSandbox: sandbox]; #endif #ifndef OF_AMIGAOS - [OFLocale addLocalizationDirectory: @LOCALIZATION_DIR]; + [OFLocale addLocalizationDirectoryIRI: + [OFIRI fileIRIWithPath: @LOCALIZATION_DIR]]; #else - [OFLocale addLocalizationDirectory: - @"PROGDIR:/share/ofhttp/localization"]; + [OFLocale addLocalizationDirectoryIRI: + [OFIRI fileIRIWithPath: @"PROGDIR:/share/ofhttp/localization"]]; #endif optionsParser = [OFOptionsParser parserWithOptions: options]; while ((option = [optionsParser nextOption]) != '\0') { switch (option) { @@ -475,52 +478,52 @@ case 'P': [self setProxy: optionsParser.argument]; break; case ':': if (optionsParser.lastLongOption != nil) - [OFStdErr writeLine: - OF_LOCALIZED(@"long_argument_missing", + [OFStdErr writeLine: OF_LOCALIZED( + @"long_argument_missing", @"%[prog]: Argument for option --%[opt] " - @"missing" + @"missing", @"prog", [OFApplication programName], @"opt", optionsParser.lastLongOption)]; else { OFString *optStr = [OFString - stringWithFormat: @"%c", + stringWithFormat: @"%C", optionsParser.lastOption]; - [OFStdErr writeLine: - OF_LOCALIZED(@"argument_missing", + [OFStdErr writeLine: OF_LOCALIZED( + @"argument_missing", @"%[prog]: Argument for option -%[opt] " @"missing", @"prog", [OFApplication programName], @"opt", optStr)]; } [OFApplication terminateWithStatus: 1]; break; case '=': - [OFStdErr writeLine: - OF_LOCALIZED(@"option_takes_no_argument", + [OFStdErr writeLine: OF_LOCALIZED( + @"option_takes_no_argument", @"%[prog]: Option --%[opt] takes no argument", @"prog", [OFApplication programName], @"opt", optionsParser.lastLongOption)]; [OFApplication terminateWithStatus: 1]; break; case '?': if (optionsParser.lastLongOption != nil) - [OFStdErr writeLine: - OF_LOCALIZED(@"unknown_long_option", + [OFStdErr writeLine: OF_LOCALIZED( + @"unknown_long_option", @"%[prog]: Unknown option: --%[opt]", @"prog", [OFApplication programName], @"opt", optionsParser.lastLongOption)]; else { OFString *optStr = [OFString - stringWithFormat: @"%c", + stringWithFormat: @"%C", optionsParser.lastOption]; - [OFStdErr writeLine: - OF_LOCALIZED(@"unknown_option", + [OFStdErr writeLine: OF_LOCALIZED( + @"unknown_option", @"%[prog]: Unknown option: -%[opt]", @"prog", [OFApplication programName], @"opt", optStr)]; } @@ -544,13 +547,13 @@ sandbox.allowsUnveil = false; [OFApplication of_activateSandbox: sandbox]; #endif _outputPath = [outputPath copy]; - _URIs = [optionsParser.remainingArguments copy]; + _IRIs = [optionsParser.remainingArguments copy]; - if (_URIs.count < 1) + if (_IRIs.count < 1) help(OFStdErr, false, 1); if (_quiet && _verbose) { [OFStdErr writeLine: OF_LOCALIZED(@"quiet_xor_verbose", @"%[prog]: -q / --quiet and -v / --verbose are mutually " @@ -566,14 +569,14 @@ @"mutually exclusive!", @"prog", [OFApplication programName])]; [OFApplication terminateWithStatus: 1]; } - if (_outputPath != nil && _URIs.count > 1) { - [OFStdErr writeLine: - OF_LOCALIZED(@"output_only_with_one_uri", - @"%[prog]: Cannot use -o / --output when more than one URI " + if (_outputPath != nil && _IRIs.count > 1) { + [OFStdErr writeLine: OF_LOCALIZED( + @"output_only_with_one_iri", + @"%[prog]: Cannot use -o / --output when more than one IRI " @"has been specified!", @"prog", [OFApplication programName])]; [OFApplication terminateWithStatus: 1]; } @@ -584,11 +587,11 @@ _useUnicode = [OFSystemInfo isWindowsNT]; #else _useUnicode = ([OFLocale encoding] == OFStringEncodingUTF8); #endif - [self performSelector: @selector(downloadNextURI) afterDelay: 0]; + [self performSelector: @selector(downloadNextIRI) afterDelay: 0]; } - (void)client: (OFHTTPClient *)client didCreateTLSStream: (OFTLSStream *)stream request: (OFHTTPRequest *)request @@ -608,11 +611,11 @@ [body writeBuffer: buffer length: length]; } } - (bool)client: (OFHTTPClient *)client - shouldFollowRedirectToURI: (OFURI *)URI + shouldFollowRedirectToIRI: (OFIRI *)IRI statusCode: (short)statusCode request: (OFHTTPRequest *)request response: (OFHTTPResponse *)response { if (_verbose) { @@ -630,13 +633,13 @@ objc_autoreleasePoolPop(pool); } if (!_quiet) { if (_useUnicode) - [OFStdOut writeFormat: @"☇ %@", URI.string]; + [OFStdOut writeFormat: @"☇ %@", IRI.string]; else - [OFStdOut writeFormat: @"< %@", URI.string]; + [OFStdOut writeFormat: @"< %@", IRI.string]; } _length = 0; return true; @@ -646,11 +649,11 @@ didReadIntoBuffer: (void *)buffer length: (size_t)length exception: (id)exception { if (exception != nil) { - OFString *URI; + OFString *IRI; [_progressBar stop]; [_progressBar draw]; [_progressBar release]; _progressBar = nil; @@ -659,21 +662,21 @@ [OFStdOut writeString: @"\n "]; [OFStdOut writeLine: OF_LOCALIZED(@"download_error", @"Error!")]; } - URI = [_URIs objectAtIndex: _URIIndex - 1]; + IRI = [_IRIs objectAtIndex: _IRIIndex - 1]; [OFStdErr writeLine: OF_LOCALIZED( @"download_failed_exception", - @"%[prog]: Failed to download <%[uri]>!\n" + @"%[prog]: Failed to download <%[iri]>!\n" @" %[exception]", @"prog", [OFApplication programName], - @"uri", URI, + @"iri", IRI, @"exception", exception)]; _errorCode = 1; - [self performSelector: @selector(downloadNextURI) + [self performSelector: @selector(downloadNextIRI) afterDelay: 0]; return false; } [_output writeBuffer: buffer length: length]; @@ -691,11 +694,11 @@ [OFStdOut writeString: @"\n "]; [OFStdOut writeLine: OF_LOCALIZED(@"download_done", @"Done!")]; } - [self performSelector: @selector(downloadNextURI) + [self performSelector: @selector(downloadNextIRI) afterDelay: 0]; return false; } return true; @@ -813,40 +816,40 @@ if ([exception isKindOfClass: [OFResolveHostFailedException class]]) { if (!_quiet) [OFStdOut writeString: @"\n"]; - [OFStdErr writeLine: - OF_LOCALIZED(@"download_resolve_host_failed", - @"%[prog]: Failed to download <%[uri]>!\n" + [OFStdErr writeLine: OF_LOCALIZED( + @"download_resolve_host_failed", + @"%[prog]: Failed to download <%[iri]>!\n" @" Failed to resolve host: %[exception]", @"prog", [OFApplication programName], - @"uri", request.URI.string, + @"iri", request.IRI.string, @"exception", exception)]; } else if ([exception isKindOfClass: [OFConnectSocketFailedException class]]) { if (!_quiet) [OFStdOut writeString: @"\n"]; - [OFStdErr writeLine: - OF_LOCALIZED(@"download_failed_connection_failed", - @"%[prog]: Failed to download <%[uri]>!\n" + [OFStdErr writeLine: OF_LOCALIZED( + @"download_failed_connection_failed", + @"%[prog]: Failed to download <%[iri]>!\n" @" Connection failed: %[exception]", @"prog", [OFApplication programName], - @"uri", request.URI.string, + @"iri", request.IRI.string, @"exception", exception)]; } else if ([exception isKindOfClass: [OFInvalidServerResponseException class]]) { if (!_quiet) [OFStdOut writeString: @"\n"]; [OFStdErr writeLine: OF_LOCALIZED( @"download_failed_invalid_server_response", - @"%[prog]: Failed to download <%[uri]>!\n" + @"%[prog]: Failed to download <%[iri]>!\n" @" Invalid server response!", @"prog", [OFApplication programName], - @"uri", request.URI.string)]; + @"iri", request.IRI.string)]; } else if ([exception isKindOfClass: [OFUnsupportedProtocolException class]]) { if (!_quiet) [OFStdOut writeString: @"\n"]; @@ -855,10 +858,26 @@ @" In order to download via HTTPS, you need to " @"either build ObjFW with TLS\n" @" support or preload a library adding TLS " @"support to ObjFW!", @"prog", [OFApplication programName])]; + } else if ([exception isKindOfClass: + [OFTLSHandshakeFailedException class]]) { + OFString *error = OFTLSStreamErrorCodeDescription( + ((OFTLSHandshakeFailedException *)exception) + .errorCode); + + if (!_quiet) + [OFStdOut writeString: @"\n"]; + + [OFStdErr writeLine: OF_LOCALIZED( + @"download_failed_tls_handshake_failed", + @"%[prog]: Failed to download <%[iri]>!\n" + @" TLS handshake failed: %[error]", + @"prog", [OFApplication programName], + @"iri", request.IRI.string, + @"error", error)]; } else if ([exception isKindOfClass: [OFReadOrWriteFailedException class]]) { OFString *error = OF_LOCALIZED( @"download_failed_read_or_write_failed_any", @"Read or write failed"); @@ -879,14 +898,14 @@ @"write", @"Write failed"); [OFStdErr writeLine: OF_LOCALIZED( @"download_failed_read_or_write_failed", - @"%[prog]: Failed to download <%[uri]>!\n" + @"%[prog]: Failed to download <%[iri]>!\n" @" %[error]: %[exception]", @"prog", [OFApplication programName], - @"uri", request.URI.string, + @"iri", request.IRI.string, @"error", error, @"exception", exception)]; } else if ([exception isKindOfClass: [OFHTTPRequestFailedException class]]) { short statusCode; @@ -899,20 +918,20 @@ statusCode = response.statusCode; codeString = [OFString stringWithFormat: @"%hd %@", statusCode, OFHTTPStatusCodeString(statusCode)]; [OFStdErr writeLine: OF_LOCALIZED(@"download_failed", - @"%[prog]: Failed to download <%[uri]>!\n" + @"%[prog]: Failed to download <%[iri]>!\n" @" HTTP status code: %[code]", @"prog", [OFApplication programName], - @"uri", request.URI.string, + @"iri", request.IRI.string, @"code", codeString)]; } else @throw exception; _errorCode = 1; - [self performSelector: @selector(downloadNextURI) + [self performSelector: @selector(downloadNextIRI) afterDelay: 0]; return; } after_exception_handling: @@ -923,14 +942,14 @@ _currentFileName = [fileNameFromContentDisposition( [response.headers objectForKey: @"Content-Disposition"]) copy]; _detectedFileName = true; - /* Handle this URI on the next -[downloadNextURI] call */ - _URIIndex--; + /* Handle this IRI on the next -[downloadNextIRI] call */ + _IRIIndex--; - [self performSelector: @selector(downloadNextURI) + [self performSelector: @selector(downloadNextIRI) afterDelay: 0]; return; } if ([_outputPath isEqual: @"-"]) @@ -963,10 +982,43 @@ @"exception", e)]; _errorCode = 1; goto next; } + +#ifdef OF_LINUX + @try { + OFString *IRIString = request.IRI.string; + OFData *downloadedFromData = [OFData + dataWithItems: IRIString.UTF8String + count: IRIString.UTF8StringLength + 1]; + [[OFFileManager defaultManager] + setExtendedAttributeData: downloadedFromData + forName: @"user.ofhttp." + @"downloaded_from" + ofItemAtPath: _currentFileName]; + } @catch (OFSetItemAttributesFailedException *) { + /* Ignore */ + } +#endif + +#ifdef OF_MACOS + @try { + OFString *quarantine = [OFString stringWithFormat: + @"0000;%08" @PRIx64 @";ofhttp;", + (uint64_t)[[OFDate date] timeIntervalSince1970]]; + OFData *quarantineData = [OFData + dataWithItems: quarantine.UTF8String + count: quarantine.UTF8StringLength]; + [[OFFileManager defaultManager] + setExtendedAttributeData: quarantineData + forName: @"com.apple.quarantine" + ofItemAtPath: _currentFileName]; + } @catch (OFSetItemAttributesFailedException *e) { + /* Ignore */ + } +#endif } if (!_quiet) { _progressBar = [[ProgressBar alloc] initWithLength: _length @@ -985,47 +1037,47 @@ next: [_currentFileName release]; _currentFileName = nil; - [self performSelector: @selector(downloadNextURI) afterDelay: 0]; + [self performSelector: @selector(downloadNextIRI) afterDelay: 0]; } -- (void)downloadNextURI +- (void)downloadNextIRI { - OFString *URIString = nil; - OFURI *URI; + OFString *IRIString = nil; + OFIRI *IRI; OFMutableDictionary *clientHeaders; OFHTTPRequest *request; _received = _length = _resumedFrom = 0; if (_output != OFStdOut) [_output release]; _output = nil; - if (_URIIndex >= _URIs.count) + if (_IRIIndex >= _IRIs.count) [OFApplication terminateWithStatus: _errorCode]; @try { - URIString = [_URIs objectAtIndex: _URIIndex++]; - URI = [OFURI URIWithString: URIString]; + IRIString = [_IRIs objectAtIndex: _IRIIndex++]; + IRI = [OFIRI IRIWithString: IRIString]; } @catch (OFInvalidFormatException *e) { - [OFStdErr writeLine: OF_LOCALIZED(@"invalid_uri", - @"%[prog]: Invalid URI: <%[uri]>!", + [OFStdErr writeLine: OF_LOCALIZED(@"invalid_iri", + @"%[prog]: Invalid IRI: <%[iri]>!", @"prog", [OFApplication programName], - @"uri", URIString)]; + @"iri", IRIString)]; _errorCode = 1; goto next; } - if (![URI.scheme isEqual: @"http"] && ![URI.scheme isEqual: @"https"]) { + if (![IRI.scheme isEqual: @"http"] && ![IRI.scheme isEqual: @"https"]) { [OFStdErr writeLine: OF_LOCALIZED(@"invalid_scheme", - @"%[prog]: Invalid scheme: <%[uri]>!", + @"%[prog]: Invalid scheme: <%[iri]>!", @"prog", [OFApplication programName], - @"uri", URIString)]; + @"iri", IRIString)]; _errorCode = 1; goto next; } @@ -1032,16 +1084,16 @@ clientHeaders = [[_clientHeaders mutableCopy] autorelease]; if (_detectFileName && !_detectedFileName) { if (!_quiet) { if (_useUnicode) - [OFStdOut writeFormat: @"⠒ %@", URI.string]; + [OFStdOut writeFormat: @"⠒ %@", IRI.string]; else - [OFStdOut writeFormat: @"? %@", URI.string]; + [OFStdOut writeFormat: @"? %@", IRI.string]; } - request = [OFHTTPRequest requestWithURI: URI]; + request = [OFHTTPRequest requestWithIRI: IRI]; request.headers = clientHeaders; request.method = OFHTTPRequestMethodHead; _detectFileNameRequest = true; [_HTTPClient asyncPerformRequest: request]; @@ -1056,13 +1108,13 @@ if (_currentFileName == nil) _currentFileName = [_outputPath copy]; if (_currentFileName == nil) - _currentFileName = [URI.path.lastPathComponent copy]; + _currentFileName = [IRI.path.lastPathComponent copy]; - if ([_currentFileName isEqual: @"/"]) { + if ([_currentFileName isEqual: @"/"] || _currentFileName.length == 0) { [_currentFileName release]; _currentFileName = nil; } if (_currentFileName == nil) @@ -1078,31 +1130,31 @@ if (size > ULLONG_MAX) @throw [OFOutOfRangeException exception]; _resumedFrom = (unsigned long long)size; - range = [OFString stringWithFormat: @"bytes=%jd-", + range = [OFString stringWithFormat: @"bytes=%ju-", _resumedFrom]; [clientHeaders setObject: range forKey: @"Range"]; } @catch (OFGetItemAttributesFailedException *e) { } } if (!_quiet) { if (_useUnicode) - [OFStdOut writeFormat: @"⇣ %@", URI.string]; + [OFStdOut writeFormat: @"⇣ %@", IRI.string]; else - [OFStdOut writeFormat: @"< %@", URI.string]; + [OFStdOut writeFormat: @"< %@", IRI.string]; } - request = [OFHTTPRequest requestWithURI: URI]; + request = [OFHTTPRequest requestWithIRI: IRI]; request.headers = clientHeaders; request.method = _method; _detectFileNameRequest = false; [_HTTPClient asyncPerformRequest: request]; return; next: - [self performSelector: @selector(downloadNextURI) afterDelay: 0]; + [self performSelector: @selector(downloadNextIRI) afterDelay: 0]; } @end Index: utils/ofhttp/ProgressBar.h ================================================================== --- utils/ofhttp/ProgressBar.h +++ utils/ofhttp/ProgressBar.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may 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-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may 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/localization/de.json ================================================================== --- utils/ofhttp/localization/de.json +++ utils/ofhttp/localization/de.json @@ -1,108 +1,123 @@ +/* + * German localization for ofhttp. + * + * Copyright (c) 2017-2024 Jonathan Schleifer + * + * Permission to use, copy, modify, and/or distribute this localization for + * any purpose with or without fee is hereby granted. + */ + +/* vim: se ft=javascript sw=4 et: */ + { - "usage": "Benutzung: %[prog] -[cehHmoOPqv] uri1 [uri2 ...]", - "full_usage": [ + usage: "Benutzung: %[prog] -[cehHmoOPqv] iri1 [iri2 ...]", + full_usage: [ "Optionen:\n", - " -b --body Angegebene Datei als Body übergeben\n", + " -b --body= Angegebene Datei als Body übergeben\n", " (- für Standard-Eingabe)\n", " -c --continue Download von existierender Datei ", "fortsetzen\n", " -f --force Existierende Datei überschreiben\n", " -h --help Diese Hilfe anzeigen\n", - " -H --header Einen Header (z.B. X-Foo:Bar) hinzufügen\n", - " -m --method HTTP Request-Methode setzen\n", - " -o --output Ausgabe-Dateiname angeben\n", + " -H --header= Einen Header (z.B. X-Foo:Bar) hinzufügen\n", + " -m --method= HTTP Request-Methode setzen\n", + " -o --output= Ausgabe-Dateiname angeben\n", " -O --detect-filename Dateiname mittels HEAD-Request ermitteln\n", - " -P --proxy SOCKS5-Proxy angeben\n", + " -P --proxy= SOCKS5-Proxy angeben\n", " -q --quiet Ruhiger Modus (keine Ausgabe außer Fehler)", "\n", " -v --verbose Ausführlicher Modus (gibt Header aus)\n", " --insecure TLS-Fehler ignorieren und unsichere\n", " Weiterleitungen erlauben\n", " --ignore-status HTTP Status-Code ignorieren" ], - "invalid_input_header": "%[prog]: Header müssen im Format Name:Wert sein!", - "invalid_input_method": "%[prog]: Ungültige Request-Methode %[method]!", - "invalid_input_proxy": "%[prog]: Proxy muss im Format Host:Port sein!", - "long_argument_missing": "%[prog]: Argument für Option --%[opt] fehlt", - "argument_missing": "%[prog]: Argument für option -%[opt] fehlt", - "option_takes_no_argument": "%[prog]: Option --%[opt] nimmt kein Argument", - "unknown_long_option": "%[prog]: Unbekannte Option: --%[opt]", - "unknown_option": "%[prog]: Unbekannte Option: -%[opt]", - "quiet_xor_verbose": [ + invalid_input_header: "%[prog]: Header müssen im Format Name:Wert sein!", + invalid_input_method: "%[prog]: Ungültige Request-Methode %[method]!", + invalid_input_proxy: "%[prog]: Proxy muss im Format Host:Port sein!", + long_argument_missing: "%[prog]: Argument für Option --%[opt] fehlt", + argument_missing: "%[prog]: Argument für option -%[opt] fehlt", + option_takes_no_argument: "%[prog]: Option --%[opt] nimmt kein Argument", + unknown_long_option: "%[prog]: Unbekannte Option: --%[opt]", + unknown_option: "%[prog]: Unbekannte Option: -%[opt]", + quiet_xor_verbose: [ "%[prog]: -q / --quiet und -v / --verbose schließen sich gegenseitig ", "aus!" ], - "output_xor_detect_filename": [ + output_xor_detect_filename: [ "%[prog]: -o / --output und -O / --detect-filename schließen sich ", "gegenseitig aus!" ], - "output_only_with_one_uri": [ - "%[prog]: -o / --output kann nicht mit mehr als einer URI benutzt ", + output_only_with_one_iri: [ + "%[prog]: -o / --output kann nicht mit mehr als einer IRI benutzt ", "werden!" ], - "download_resolve_host_failed": [ - "%[prog]: Fehler beim Download von <%[uri]>!\n", + download_resolve_host_failed: [ + "%[prog]: Fehler beim Download von <%[iri]>!\n", " Host auflösen fehlgeschlagen: %[exception]" ], - "download_failed_connection_failed": [ - "%[prog]: Fehler beim Download von <%[uri]>!\n", + download_failed_connection_failed: [ + "%[prog]: Fehler beim Download von <%[iri]>!\n", " Verbindung fehlgeschlagen: %[exception]" ], - "download_failed_invalid_server_response": [ - "%[prog]: Fehler beim Download von <%[uri]>!\n", + download_failed_invalid_server_response: [ + "%[prog]: Fehler beim Download von <%[iri]>!\n", " Ungültige Antwort vom Server!" ], - "no_tls_support": [ + no_tls_support: [ "%[prog]: Keine TLS-Unterstützung in ObjFW!\n", " Um via HTTPS runterzuladen müssen Sie entweder ObjFW mit TLS-", "Unterstützung\n", " kompilieren oder eine Bibliothek mittels „preload” laden, welche ", "TLS-Support\n", " zu ObjFW hinzufügt!" ], - "download_failed_read_or_write_failed_any": "Lesen oder Schreiben", - "download_failed_read_or_write_failed_read": "Lesen", - "download_failed_read_or_write_failed_write": "Schreiben", - "download_failed_read_or_write_failed": [ - "%[prog]: Fehler beim Download von <%[uri]>!\n", + download_failed_tls_handshake_failed: [ + "%[prog]: Fehler beim Download von <%[iri]>!\n", + " TLS-Handshake fehlgeschlagen: %[error]" + ], + download_failed_read_or_write_failed_any: "Lesen oder Schreiben", + download_failed_read_or_write_failed_read: "Lesen", + download_failed_read_or_write_failed_write: "Schreiben", + download_failed_read_or_write_failed: [ + "%[prog]: Fehler beim Download von <%[iri]>!\n", " %[error]: %[exception]" ], - "download_failed": [ - "%[prog]: Fehler beim Download von <%[uri]>!\n", + download_failed: [ + "%[prog]: Fehler beim Download von <%[iri]>!\n", " HTTP Status-Code: %[code]" ], - "download_error": "Fehler!", - "download_failed_exception": [ - "%[prog]: Fehler beim Download von <%[uri]>!\n", + download_error: "Fehler!", + download_failed_exception: [ + "%[prog]: Fehler beim Download von <%[iri]>!\n", " %[exception]" ], - "download_done": "Fertig!", - "invalid_uri": "%[prog]: Ungültige URI: <%[uri]>!", - "invalid_scheme": "%[prog]: Ungültiges Schema: <%[uri]>!", - "type_unknown": "unbekannt", - "size_gib": "%[num] GiB", - "size_mib": "%[num] MiB", - "size_kib": "%[num] KiB", - "size_bytes": [ + download_done: "Fertig!", + invalid_iri: "%[prog]: Ungültige IRI: <%[iri]>!", + invalid_scheme: "%[prog]: Ungültiges Schema: <%[iri]>!", + type_unknown: "unbekannt", + size_gib: "%[num] GiB", + size_mib: "%[num] MiB", + size_kib: "%[num] KiB", + size_bytes: [ [ {"num == 1": "1 Byte"}, {"": "%[num] Bytes"} ] ], - "size_unknown": "unbekannt", - "info_name_unaligned": "Name: %[name]", - "info_name": "Name: %[name]", - "info_type": "Typ: %[type]", - "info_size": "Größe: %[size]", - "output_already_exists": "%[prog]: Datei %[filename] existiert bereits!", - "failed_to_open_output": [ + size_unknown: "unbekannt", + info_name_unaligned: "Name: %[name]", + info_name: "Name: %[name]", + info_type: "Typ: %[type]", + info_size: "Größe: %[size]", + output_already_exists: "%[prog]: Datei %[filename] existiert bereits!", + failed_to_open_output: [ "%[prog]: Kann Datei %[filename] nicht öffnen: %[exception]" ], - "eta_days": "%[num] t ", - "progress_bytes": [ + eta_days: "%[num] t ", + progress_bytes: [ [ {"num == 1": "1 Byte "}, {"": "%[num] Bytes"} ] - ] + ], } Index: utils/ofhttp/localization/localizations.json ================================================================== --- utils/ofhttp/localization/localizations.json +++ utils/ofhttp/localization/localizations.json @@ -1,11 +1,22 @@ +/* + * Localization mapping for ofhttp. + * + * Copyright (c) 2017-2023 Jonathan Schleifer + * + * Permission to use, copy, modify, and/or distribute this mapping for any + * purpose with or without fee is hereby granted. + */ + +/* vim: se ft=javascript sw=4 et: */ + { - "de": { + de: { "": "de" }, - "deutsch": { + deutsch: { "": "de" }, - "german": { + german: { "": "de" - } + }, }