ADDED .github/workflows/macos-13.yml
Index: .github/workflows/macos-13.yml
==================================================================
--- .github/workflows/macos-13.yml
+++ .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@v2
+ - name: autogen.sh
+ run: ./autogen.sh
+ - name: configure
+ run: ./configure ${{ matrix.configure_flags }}
+ - name: make
+ run: make -j$(sysctl -n hw.logicalcpu)
+ - name: make check
+ run: make check
+ - name: make install
+ run: sudo make install
Index: ChangeLog
==================================================================
--- ChangeLog
+++ ChangeLog
@@ -2,11 +2,16 @@
* 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 0.90.2 -> ObjFW 1.0, 08.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 +18,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 +31,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 +63,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 +77,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 +126,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 +159,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 +175,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 +222,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 +241,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 +291,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 +328,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 +349,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: Makefile
==================================================================
--- Makefile
+++ Makefile
@@ -26,11 +26,11 @@
release: docs
echo "Generating tarball for version ${PACKAGE_VERSION}..."
rm -fr objfw-${PACKAGE_VERSION} objfw-${PACKAGE_VERSION}.tar \
objfw-${PACKAGE_VERSION}.tar.gz
fossil tarball --name objfw-${PACKAGE_VERSION} current - \
- --exclude '.fossil*,.git*' | ofarc -ttgz -xq -
+ --exclude '.fossil*,.git*,objfw.spec' | ofarc -ttgz -xq -
cp configure config.h.in objfw-${PACKAGE_VERSION}/
ofarc -cq objfw-${PACKAGE_VERSION}.tar objfw-${PACKAGE_VERSION}
rm -fr objfw-${PACKAGE_VERSION}
gzip -9 objfw-${PACKAGE_VERSION}.tar
rm -f objfw-${PACKAGE_VERSION}.tar
Index: PLATFORMS.md
==================================================================
--- PLATFORMS.md
+++ PLATFORMS.md
@@ -78,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`.
@@ -233,12 +233,11 @@
Windows
-------
- * OS Versions: 98 SE, NT 4.0, XP (x86), 7 (x64), 8 (x64), 8.1 (x64), 10, 11,
- Wine (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 (AMD64 & x86),
Clang 14.0.4 from msys2 (AArch64)
Index: README.md
==================================================================
--- README.md
+++ README.md
@@ -311,11 +311,11 @@
Amiga
Install [amiga-gcc](https://github.com/bebbo/amiga-gcc). Then follow the
normal process, but instead of `./configure` run:
- $ ./configure --host=m68k-amigaos OBJC=m68k-amigaos-g++
+ $ ./configure --host=m68k-amigaos
Writing your first application with ObjFW
To create your first, empty application, you can use `objfw-new`:
Index: configure.ac
==================================================================
--- configure.ac
+++ configure.ac
@@ -1448,10 +1448,12 @@
#ifdef AF_INET6
egrep_cpp_yes
#endif
], [
AC_DEFINE(OF_HAVE_IPV6, 1, [Whether we have IPv6])
+
+ AC_CHECK_FUNCS(inet6_getscopeid)
])
], [
dnl Work around a bug in autoconf 2.61 that creates a broken
dnl configure if this branch is empty.
:
@@ -1783,25 +1785,10 @@
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], [
- tls_support="GnuTLS"
- TLS_CPPFLAGS="$gnutls_CFLAGS $TLS_CPPFLAGS"
- TLS_LIBS="$gnutls_LIBS $TLS_LIBS"
-
- AC_SUBST(OF_GNUTLS_TLS_STREAM_M, "OFGnuTLSTLSStream.m")
- ], [
- dnl Disable default action-if-not-found, which exits
- dnl configure with an error.
- :
- ])
- ])
-
AS_IF([test x"$with_tls" = x"openssl" \
-o \( x"$with_tls" = x"yes" -a x"$tls_support" = x"no" \)], [
case "$host_os" in
morphos*)
ssl="ssl_shared"
@@ -1821,10 +1808,25 @@
AC_SUBST(OF_OPENSSL_TLS_STREAM_M,
"OFOpenSSLTLSStream.m")
])
], [], [-l$crypto])
])
+
+ AS_IF([test x"$with_tls" = x"gnutls" \
+ -o \( x"$with_tls" = x"yes" -a x"$tls_support" = x"no" \)], [
+ PKG_CHECK_MODULES(gnutls, [gnutls >= 3.5.0], [
+ tls_support="GnuTLS"
+ TLS_CPPFLAGS="$gnutls_CFLAGS $TLS_CPPFLAGS"
+ TLS_LIBS="$gnutls_LIBS $TLS_LIBS"
+
+ AC_SUBST(OF_GNUTLS_TLS_STREAM_M, "OFGnuTLSTLSStream.m")
+ ], [
+ dnl Disable default action-if-not-found, which exits
+ dnl configure with an error.
+ :
+ ])
+ ])
AS_IF([test x"$tls_support" != x"no"], [
AC_SUBST(TLS, "tls")
AC_SUBST(TLS_CPPFLAGS)
AC_SUBST(TLS_LIBS)
Index: objfw.spec
==================================================================
--- objfw.spec
+++ objfw.spec
@@ -30,11 +30,11 @@
BuildRequires: autoconf
BuildRequires: automake
BuildRequires: clang
BuildRequires: make
-BuildRequires: pkgconfig(gnutls)
+BuildRequires: pkgconfig(openssl)
Requires: %{libobjfw_pkgname}%{_isa} = %{version}-%{release}
Requires: %{libobjfw_pkgname}-devel = %{version}-%{release}
Requires: %{libobjfwrt_pkgname}%{_isa} = %{version}-%{release}
Requires: %{libobjfwrt_pkgname}-devel = %{version}-%{release}
Requires: ofarc%{_isa} = %{version}-%{release}
@@ -87,11 +87,11 @@
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
+Requires: openssl%{_isa} >= 1.1.1
%description -n %{libobjfwtls_pkgname}
The %{libobjfwtls_pkgname} package contains TLS support for ObjFW
%package -n %{libobjfwtls_pkgname}-devel
Index: src/OFDatagramSocket.h
==================================================================
--- src/OFDatagramSocket.h
+++ src/OFDatagramSocket.h
@@ -105,10 +105,11 @@
OFReadyForWritingObserving>
{
OFSocketHandle _socket;
#ifdef OF_AMIGAOS
LONG _socketID;
+ int _family; /* unused, reserved for ABI stability */
#endif
bool _canBlock;
#ifdef OF_WII
bool _canSendToBroadcastAddresses;
#endif
@@ -119,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;
/**
Index: src/OFDate.m
==================================================================
--- src/OFDate.m
+++ src/OFDate.m
@@ -657,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
@@ -710,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
Index: src/OFHTTPClient.m
==================================================================
--- src/OFHTTPClient.m
+++ src/OFHTTPClient.m
@@ -385,19 +385,11 @@
* 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];
Index: src/OFHTTPResponse.m
==================================================================
--- src/OFHTTPResponse.m
+++ src/OFHTTPResponse.m
@@ -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/OFINICategory.h
==================================================================
--- src/OFINICategory.h
+++ src/OFINICategory.h
@@ -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
@@ -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/OFINIFileSettings.m
==================================================================
--- src/OFINIFileSettings.m
+++ src/OFINIFileSettings.m
@@ -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];
}
Index: src/OFSequencedPacketSocket.h
==================================================================
--- src/OFSequencedPacketSocket.h
+++ src/OFSequencedPacketSocket.h
@@ -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;
/**
Index: src/OFStream.h
==================================================================
--- src/OFStream.h
+++ src/OFStream.h
@@ -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;
/**
Index: src/OFStreamSocket.h
==================================================================
--- src/OFStreamSocket.h
+++ src/OFStreamSocket.h
@@ -66,10 +66,11 @@
OFReadyForWritingObserving>
{
OFSocketHandle _socket;
#ifdef OF_AMIGAOS
LONG _socketID;
+ int _family; /* unused, reserved for ABI stability */
#endif
bool _atEndOfStream, _listening;
OFSocketAddress _remoteAddress;
OF_RESERVE_IVARS(OFStreamSocket, 4)
}
Index: src/OFTCPSocket.h
==================================================================
--- src/OFTCPSocket.h
+++ src/OFTCPSocket.h
@@ -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
/**
Index: src/OFXMLParser.h
==================================================================
--- src/OFXMLParser.h
+++ src/OFXMLParser.h
@@ -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/exceptions/OFBindUNIXSocketFailedException.h
==================================================================
--- src/exceptions/OFBindUNIXSocketFailedException.h
+++ src/exceptions/OFBindUNIXSocketFailedException.h
@@ -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/platform/POSIX/OFSystemInfo+NetworkInterfaces.m
==================================================================
--- src/platform/POSIX/OFSystemInfo+NetworkInterfaces.m
+++ src/platform/POSIX/OFSystemInfo+NetworkInterfaces.m
@@ -224,14 +224,20 @@
# 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)
+ == 0x80) {
+# if defined(HAVE_INET6_GETSCOPEID)
+ inet6_getscopeid(&address.sockaddr.in6,
+ INET6_IS_ADDR_LINKLOCAL);
+# elif defined(HAVE_IF_NAMETOINDEX)
address.sockaddr.in6.sin6_scope_id =
if_nametoindex(
[name cStringWithEncoding: encoding]);
+# endif
+ }
# endif
[addresses addItem: &address];
next:
Index: src/runtime/arc.m
==================================================================
--- src/runtime/arc.m
+++ src/runtime/arc.m
@@ -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/private.h
==================================================================
--- src/runtime/private.h
+++ src/runtime/private.h
@@ -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;
Index: src/tls/OFOpenSSLTLSStream.m
==================================================================
--- src/tls/OFOpenSSLTLSStream.m
+++ src/tls/OFOpenSSLTLSStream.m
@@ -106,26 +106,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 +117,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;
Index: tests/OFINIFileTests.m
==================================================================
--- tests/OFINIFileTests.m
+++ tests/OFINIFileTests.m
@@ -64,51 +64,52 @@
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"]))
Index: utils/ofarc/Archive.h
==================================================================
--- utils/ofarc/Archive.h
+++ utils/ofarc/Archive.h
@@ -18,15 +18,15 @@
#import "OFArray.h"
OF_ASSUME_NONNULL_BEGIN
@protocol Archive
-+ (instancetype)archiveWithPath: (OFString *)path
++ (instancetype)archiveWithPath: (nullable OFString *)path
stream: (OF_KINDOF(OFStream *))stream
mode: (OFString *)mode
encoding: (OFStringEncoding)encoding;
-- (instancetype)initWithPath: (OFString *)path
+- (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;
Index: utils/ofarc/OFArc.m
==================================================================
--- utils/ofarc/OFArc.m
+++ utils/ofarc/OFArc.m
@@ -486,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];
@@ -645,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/ZIPArchive.m
==================================================================
--- utils/ofarc/ZIPArchive.m
+++ utils/ofarc/ZIPArchive.m
@@ -139,18 +139,11 @@
path = _path;
else
path = [_path.stringByDeletingPathExtension
stringByAppendingFormat: @".z%02u", partNumber + 1];
- @try {
- return [OFFile fileWithPath: path mode: @"r"];
- } @catch (OFOpenItemFailedException *e) {
- if (e.errNo != ENOENT)
- @throw e;
-
- return nil;
- }
+ return [OFFile fileWithPath: path mode: @"r"];
}
- (void)listFiles
{
for (OFZIPArchiveEntry *entry in _archive.entries) {
Index: utils/ofhttp/OFHTTP.m
==================================================================
--- utils/ofhttp/OFHTTP.m
+++ utils/ofhttp/OFHTTP.m
@@ -50,10 +50,11 @@
#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"
@@ -858,10 +859,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");
@@ -1094,11 +1111,11 @@
_currentFileName = [_outputPath copy];
if (_currentFileName == nil)
_currentFileName = [IRI.path.lastPathComponent copy];
- if ([_currentFileName isEqual: @"/"]) {
+ if ([_currentFileName isEqual: @"/"] || _currentFileName.length == 0) {
[_currentFileName release];
_currentFileName = nil;
}
if (_currentFileName == nil)
Index: utils/ofhttp/localization/de.json
==================================================================
--- utils/ofhttp/localization/de.json
+++ utils/ofhttp/localization/de.json
@@ -58,10 +58,14 @@
"Unterstützung\n",
" kompilieren oder eine Bibliothek mittels „preload” laden, welche ",
"TLS-Support\n",
" zu ObjFW hinzufügt!"
],
+ "download_failed_tls_handshake_failed": [
+ "%[prog]: Fehler beim Download von <%[iri]>!\n",
+ " TLS-Handshake fehlgeschlagen: %[error]"
+ ],
"download_failed_read_or_write_failed_any": "Lesen oder Schreiben",
"download_failed_read_or_write_failed_read": "Lesen",
"download_failed_read_or_write_failed_write": "Schreiben",
"download_failed_read_or_write_failed": [
"%[prog]: Fehler beim Download von <%[iri]>!\n",