Index: ChangeLog ================================================================== --- ChangeLog +++ ChangeLog @@ -1,8 +1,55 @@ Legend: * Changes of existing features or bugfixes + New features + +This file only contains the most significant changes. + +ObjFW 0.90 -> ObjFW 0.90.1, 20.08.2017 + * OFData: Fix -[description] + * OFFileManager: Set errno to 0 before readdir() + * OFDate: Add -[localMinute] + * OFTarArchiveEntry: Fix prefix handling for ustar + * OFZIPArchive: Fix uncompressed + data descriptor + * OFArray: Fix MessagePack encoding + * of_asprintf: Don't require set up OFLocalization + * OFGZIPStream: Add missing documentation + * Fix a linker warning on OpenBSD/SPARC64 + * Remove the OFFile b modes from MorphOS + (they were already removed for all other OSes) + +ObjFW 0.8.1 -> ObjFW 0.90, 01.08.2017 + + New classes: OFFileManager, OFGZIPStream, OFTarArchive, OFTarArchiveEntry + OFHMAC, OFSandbox, OFHTTPCookie, OFHTTPCookieManager, + OFLocalization + + New platforms: Nintendo 3DS, MorphOS + + New lookup assembly for platforms: SPARC64/ELF, ARM64/ELF + + New forwarding for: ARM64/ELF + + New tools: objfw-new (to create boilerplate code) + + New options: --disable-unicode-tables + * Required GCC version increased to 4.6 + * OFDataArray was split into OFData and OFMutableData + * OFURL was split into OFURL and OFMutableURL + * Most properties are now nonatomic + (this changes from returned retained + autoreleased to +0 retained) + * Correct handling of encoding on Win32 console + (stream is read and written in UTF-8 and translated to UTF-16 on the fly) + * Runtime is now built as a separate library + + More encodings for strings + * Reworked OFOptionsParser API + * Refactored OFKernelEventObserver + * Better randomization of HTTP header order + * Allow overriding all HTTP headers + * Definition of thread priorities changed + + Key Value Coding + + Exceptions in ObjC++ + * OFHash was renamed to OFCryptoHash + + PBKDF2 + + scrypt + + Xcode project to build for iOS + + String decomposition to NFD + * OFFile modes simplified ('b' removed) ObjFW 0.8 -> ObjFW 0.8.1, 04.10.2015 * Adjust to __nullable / __nonnull being changed to _Nullable / _Nonnull in Clang 3.7 (this fixes compilation with Clang 3.7) * Blocks: Proper handling when called from a byref handler Index: configure.ac ================================================================== --- configure.ac +++ configure.ac @@ -1,6 +1,6 @@ -AC_INIT(ObjFW, 0.9-dev, js@heap.zone) +AC_INIT(ObjFW, 0.90.1, js@heap.zone) BUILDSYS_INIT AS_IF([test configure.ac -nt configure], [ AC_MSG_ERROR([configure.ac is newer than configure! Run autoreconf!]) ]) @@ -23,11 +23,10 @@ OBJCFLAGS="$OBJCFLAGS -noixemul" LDFLAGS="$LDFLAGS -noixemul" enable_files="yes" # Required for reading ENV: AC_SUBST(NOIXEMUL, -noixemul) - AC_SUBST(OBJFW_RT_MORPHOS_LIB, objfw-rt.library) ]) enable_shared="no" enable_threads="no" ;; @@ -655,12 +654,10 @@ AC_SUBST(ENCODINGS_A, "encodings.a") AC_SUBST(ENCODINGS_ENCODINGS_A, "encodings/encodings.a") ]) ]) -AC_CHECK_FUNCS(sigaction) - AC_CHECK_FUNCS(arc4random random, break) AC_CHECK_LIB(dl, dlopen, LIBS="$LIBS -ldl") AC_CHECK_HEADERS_ONCE(dlfcn.h) case "$host_os" in @@ -1040,10 +1037,11 @@ "OFKernelEventObserver_epoll.m") break ]) AS_IF([test x"$with_wii" = x"yes"], [ + AC_DEFINE(HAVE_POLL, 1, [Whether we have poll()]) AC_SUBST(OFKERNELEVENTOBSERVER_POLL_M, "OFKernelEventObserver_poll.m") ], [ AC_CHECK_HEADERS(poll.h) AC_CHECK_FUNC(poll, [ @@ -1202,11 +1200,11 @@ ;; *) AC_HEADER_SYS_WAIT AC_CHECK_FUNCS(kill) - AC_CHECK_FUNC(posix_spawnp, [ + AC_CHECK_FUNCS(posix_spawnp, [ AS_IF([test x"$ac_cv_func_kill" = x"yes"], [ have_processes="yes" AC_CHECK_HEADERS(spawn.h) ]) Index: extra.mk.in ================================================================== --- extra.mk.in +++ extra.mk.in @@ -1,15 +1,14 @@ OBJFW_SHARED_LIB = @OBJFW_SHARED_LIB@ OBJFW_STATIC_LIB = @OBJFW_STATIC_LIB@ # When changing: Be sure to also change these in the Xcode project! OBJFW_LIB_MAJOR = 8 -OBJFW_LIB_MINOR = 0 +OBJFW_LIB_MINOR = 1 OBJFW_LIB_MAJOR_MINOR = ${OBJFW_LIB_MAJOR}.${OBJFW_LIB_MINOR} OBJFW_RT_SHARED_LIB = @OBJFW_RT_SHARED_LIB@ OBJFW_RT_STATIC_LIB = @OBJFW_RT_STATIC_LIB@ -OBJFW_RT_MORPHOS_LIB = @OBJFW_RT_MORPHOS_LIB@ OBJFW_RT_LIB_MAJOR = 0 OBJFW_RT_LIB_MINOR = 0 OBJFW_RT_LIB_MAJOR_MINOR = ${OBJFW_RT_LIB_MAJOR}.${OBJFW_RT_LIB_MINOR} OBJFW_BRIDGE_SHARED_LIB = @OBJFW_BRIDGE_SHARED_LIB@ Index: src/OFApplication.h ================================================================== --- src/OFApplication.h +++ src/OFApplication.h @@ -126,16 +126,16 @@ OFArray OF_GENERIC(OFString *) *_arguments; OFMutableDictionary OF_GENERIC(OFString *, OFString *) *_environment; int *_argc; char ***_argv; @public - id _delegate; - void (*_SIGINTHandler)(id, SEL); + id _Nullable _delegate; + void (*_Nullable _SIGINTHandler)(id, SEL); #ifndef OF_WINDOWS - void (*_SIGHUPHandler)(id, SEL); - void (*_SIGUSR1Handler)(id, SEL); - void (*_SIGUSR2Handler)(id, SEL); + void (*_Nullable _SIGHUPHandler)(id, SEL); + void (*_Nullable _SIGUSR1Handler)(id, SEL); + void (*_Nullable _SIGUSR2Handler)(id, SEL); #endif } /*! * The name of the program (argv[0]). Index: src/OFApplication.m ================================================================== --- src/OFApplication.m +++ src/OFApplication.m @@ -69,16 +69,10 @@ # define asm __asm__ # include # undef asm #endif -#ifdef HAVE_SIGACTION -# ifndef SA_RESTART -# define SA_RESTART 0 -# endif -#endif - @interface OFApplication () - (instancetype)of_init OF_METHOD_FAMILY(init); - (void)of_setArgumentCount: (int *)argc andArgumentValues: (char **[])argv; #ifdef OF_WINDOWS @@ -507,37 +501,21 @@ return _delegate; } - (void)setDelegate: (id )delegate { -#ifdef HAVE_SIGACTION - struct sigaction sa = { .sa_flags = SA_RESTART }; - sigemptyset(&sa.sa_mask); - -# define REGISTER_SIGNAL(sig) \ - if ([delegate respondsToSelector: \ - @selector(applicationDidReceive##sig)]) { \ - _##sig##Handler = (void (*)(id, SEL))[(id)delegate \ - methodForSelector: \ - @selector(applicationDidReceive##sig)]; \ - \ - sa.sa_handler = handle##sig; \ - } else \ - sa.sa_handler = SIG_DFL; \ - \ - OF_ENSURE(sigaction(sig, &sa, NULL) == 0); -#else -# define REGISTER_SIGNAL(sig) \ +#define REGISTER_SIGNAL(sig) \ if ([delegate respondsToSelector: \ @selector(applicationDidReceive##sig)]) { \ _##sig##Handler = (void (*)(id, SEL))[(id)delegate \ methodForSelector: \ @selector(applicationDidReceive##sig)]; \ signal(sig, handle##sig); \ - } else \ - signal(sig, (void (*)(int))SIG_DFL); -#endif + } else { \ + _##sig##Handler = NULL; \ + signal(sig, (void (*)(int))SIG_DFL); \ + } _delegate = delegate; REGISTER_SIGNAL(SIGINT) #ifdef SIGHUP Index: src/OFArray.h ================================================================== --- src/OFArray.h +++ src/OFArray.h @@ -218,11 +218,11 @@ * @note A @ref OFNull value is translated to nil! * * @param value The value for the specified key * @param key The key of the value to set */ -- (void)setValue: (nullable id)value +- (void)setValue: (id)value forKey: (OFString *)key; /*! * @brief Copies the objects at the specified range to the specified buffer. * @@ -264,21 +264,21 @@ * object. * * @param object The object which is checked for being in the array * @return A boolean whether the array contains the specified object */ -- (bool)containsObject: (nullable ObjectType)object; +- (bool)containsObject: (ObjectType)object; /*! * @brief Checks whether the array contains an object with the specified * address. * * @param object The object which is checked for being in the array * @return A boolean whether the array contains an object with the specified * address */ -- (bool)containsObjectIdenticalTo: (nullable ObjectType)object; +- (bool)containsObjectIdenticalTo: (ObjectType)object; /*! * @brief Returns the first object of the array or `nil`. * * @warning The returned object is *not* retained and autoreleased for @@ -483,15 +483,15 @@ #endif @end @interface OFArrayEnumerator: OFEnumerator { - OFArray *_array; - size_t _count; + OFArray *_array; + size_t _count; unsigned long _mutations; - unsigned long *_mutationsPtr; - size_t _position; + unsigned long *_Nullable _mutationsPtr; + size_t _position; } - initWithArray: (OFArray *)data mutationsPtr: (unsigned long *_Nullable)mutationsPtr; @end Index: src/OFArray.m ================================================================== --- src/OFArray.m +++ src/OFArray.m @@ -317,13 +317,10 @@ objc_autoreleasePoolPop(pool); return; } - if (value == [OFNull null]) - value = nil; - for (id object in self) [object setValue: value forKey: key]; } @@ -450,21 +447,32 @@ if (separator == nil) @throw [OFInvalidArgumentException exception]; if ([self count] == 0) return @""; - if ([self count] == 1) - return [[self firstObject] performSelector: selector]; + + if ([self count] == 1) { + OFString *component = + [[self firstObject] performSelector: selector]; + + if (component == nil) + @throw [OFInvalidArgumentException exception]; + + return component; + } ret = [OFMutableString string]; if (options & OF_ARRAY_SKIP_EMPTY) { for (id object in self) { void *pool = objc_autoreleasePoolPush(); OFString *component = [object performSelector: selector]; + if (component == nil) + @throw [OFInvalidArgumentException exception]; + if ([component length] > 0) { if ([ret length] > 0) [ret appendString: separator]; [ret appendString: component]; } @@ -474,17 +482,22 @@ } else { bool first = true; for (id object in self) { void *pool = objc_autoreleasePoolPush(); + OFString *component = + [object performSelector: selector]; + + if (component == nil) + @throw [OFInvalidArgumentException exception]; if OF_UNLIKELY (first) first = false; else [ret appendString: separator]; - [ret appendString: [object performSelector: selector]]; + [ret appendString: component]; objc_autoreleasePoolPop(pool); } } @@ -674,11 +687,11 @@ [data addItem: &type]; [data addItems: &tmp count: sizeof(tmp)]; } else if (count <= UINT32_MAX) { - uint8_t type = 0xDC; + uint8_t type = 0xDD; uint32_t tmp = OF_BSWAP32_IF_LE((uint32_t)count); [data addItem: &type]; [data addItems: &tmp count: sizeof(tmp)]; Index: src/OFCollection.h ================================================================== --- src/OFCollection.h +++ src/OFCollection.h @@ -36,9 +36,9 @@ * specified object. * * @param object The object which is checked for being in the collection * @return A boolean whether the collection contains the specified object */ -- (bool)containsObject: (nullable id)object; +- (bool)containsObject: (id)object; @end OF_ASSUME_NONNULL_END Index: src/OFData.h ================================================================== --- src/OFData.h +++ src/OFData.h @@ -32,11 +32,11 @@ * for OFData with item size 1. */ @interface OFData: OFObject { - char *_items; + unsigned char *_items; size_t _count, _itemSize; bool _freeWhenDone; } /*! Index: src/OFData.m ================================================================== --- src/OFData.m +++ src/OFData.m @@ -183,11 +183,11 @@ @try { if (itemSize == 0) @throw [OFInvalidArgumentException exception]; - _items = (char *)items; + _items = (unsigned char *)items; _itemSize = itemSize; _count = count; _freeWhenDone = freeWhenDone; } @catch (id e) { [self release]; Index: src/OFDate.h ================================================================== --- src/OFDate.h +++ src/OFDate.h @@ -186,10 +186,17 @@ * * @return The minute of the date */ - (uint8_t)minute; +/*! + * @brief Returns the minute of the date in local time. + * + * @return The minute of the date in local time + */ +- (uint8_t)localMinute; + /*! * @brief Returns the hour of the date. * * @return The hour of the date */ @@ -298,21 +305,21 @@ * If the argument is `nil`, it returns the receiver. * * @param otherDate Another date * @return The earlier date of the two dates */ -- (OFDate *)earlierDate: (OFDate *)otherDate; +- (OFDate *)earlierDate: (nullable OFDate *)otherDate; /*! * @brief Returns the later of the two dates. * * If the argument is `nil`, it returns the receiver. * * @param otherDate Another date * @return The later date of the two dates */ -- (OFDate *)laterDate: (OFDate *)otherDate; +- (OFDate *)laterDate: (nullable OFDate *)otherDate; /*! * @brief Returns the seconds since 1970-01-01T00:00:00Z. * * @return The seconds since 1970-01-01T00:00:00Z Index: src/OFDate.m ================================================================== --- src/OFDate.m +++ src/OFDate.m @@ -451,10 +451,15 @@ - (uint8_t)minute { GMTIME_RET(tm_min) } + +- (uint8_t)localMinute +{ + LOCALTIME_RET(tm_min) +} - (uint8_t)hour { GMTIME_RET(tm_hour) } Index: src/OFDictionary.h ================================================================== --- src/OFDictionary.h +++ src/OFDictionary.h @@ -219,11 +219,11 @@ * @ref OFUndefinedKeyException is thrown. * * @param key The key to set * @param value The value to set the key to */ -- (void)setValue: (nullable id)value +- (void)setValue: (id)value forKey: (OFString *)key; /*! * @brief Checks whether the dictionary contains an object equal to the * specified object. Index: src/OFFile.m ================================================================== --- src/OFFile.m +++ src/OFFile.m @@ -132,44 +132,26 @@ { *append = false; if (strcmp(mode, "r") == 0) return MODE_OLDFILE; + if (strcmp(mode, "r+") == 0) + return MODE_OLDFILE; if (strcmp(mode, "w") == 0) return MODE_NEWFILE; if (strcmp(mode, "wx") == 0) return MODE_NEWFILE; + if (strcmp(mode, "w+") == 0) + return MODE_NEWFILE; + if (strcmp(mode, "w+x") == 0) + return MODE_NEWFILE; if (strcmp(mode, "a") == 0) { *append = true; return MODE_READWRITE; } - if (strcmp(mode, "rb") == 0) - return MODE_OLDFILE; - if (strcmp(mode, "wb") == 0) - return MODE_NEWFILE; - if (strcmp(mode, "wbx") == 0) - return MODE_NEWFILE; - if (strcmp(mode, "ab") == 0) { - *append = true; - return MODE_READWRITE; - } - if (strcmp(mode, "r+") == 0) - return MODE_OLDFILE; - if (strcmp(mode, "w+") == 0) - return MODE_NEWFILE; if (strcmp(mode, "a+") == 0) { *append = true; - return MODE_READWRITE; - } - if (strcmp(mode, "r+b") == 0 || strcmp(mode, "rb+") == 0) - return MODE_OLDFILE; - if (strcmp(mode, "w+b") == 0 || strcmp(mode, "wb+") == 0) - return MODE_NEWFILE; - if (strcmp(mode, "w+bx") == 0 || strcmp(mode, "wb+x") == 0) - return MODE_NEWFILE; - if (strcmp(mode, "ab+") == 0 || strcmp(mode, "a+b") == 0) { - *append = true; return MODE_READWRITE; } return -1; } Index: src/OFFileManager.m ================================================================== --- src/OFFileManager.m +++ src/OFFileManager.m @@ -571,10 +571,11 @@ errNo: errno]; if (dirent == NULL) break; # else + errno = 0; if ((dirent = readdir(dir)) == NULL) { if (errno == 0) break; else @throw [OFReadFailedException Index: src/OFGZIPStream.h ================================================================== --- src/OFGZIPStream.h +++ src/OFGZIPStream.h @@ -19,14 +19,20 @@ @class OFInflateStream; OF_ASSUME_NONNULL_BEGIN +/*! + * @class OFGZIPStream OFGZIPStream.h ObjFW/OFGZIPStream.h + * + * @brief A class that handles GZIP compression and decompression transparently + * for an underlying stream. + */ @interface OFGZIPStream: OFStream { OFStream *_stream; - OFInflateStream *_inflateStream; + OFInflateStream *_Nullable _inflateStream; enum of_gzip_stream_state { OF_GZIP_STREAM_ID1, OF_GZIP_STREAM_ID2, OF_GZIP_STREAM_COMPRESSION_METHOD, OF_GZIP_STREAM_FLAGS, @@ -67,16 +73,31 @@ OF_GZIP_STREAM_OS_ACORN_RISCOS = 13, OF_GZIP_STREAM_OS_UNKNOWN = 255 } _OS; size_t _bytesRead; uint8_t _buffer[4]; - OFDate *_modificationDate; + OFDate *_Nullable _modificationDate; uint16_t _extraLength; uint32_t _CRC32, _uncompressedSize; } +/*! + * @brief Creates a new OFGZIPStream with the specified underlying stream. + * + * @param stream The underlying stream for the OFGZIPStream + * @return A new, autoreleased OFGZIPStream + */ + (instancetype)streamWithStream: (OFStream *)stream; + - init OF_UNAVAILABLE; + +/*! + * @brief Initializes an already allocated OFGZIPStream with the specified + * underlying stream. + * + * @param stream The underlying stream for the OFGZIPStream + * @return An initialized OFGZIPStream + */ - initWithStream: (OFStream *)stream OF_DESIGNATED_INITIALIZER; @end OF_ASSUME_NONNULL_END Index: src/OFHMAC.h ================================================================== --- src/OFHMAC.h +++ src/OFHMAC.h @@ -25,12 +25,12 @@ * @brief A class which provides methods to calculate an HMAC. */ @interface OFHMAC: OFObject { Class _hashClass; - id _outerHash, _innerHash; - id _outerHashCopy, _innerHashCopy; + id _Nullable _outerHash, _innerHash; + id _Nullable _outerHashCopy, _innerHashCopy; bool _calculated; } /*! The class for the cryptographic hash used by the HMAC. */ @property (readonly, nonatomic) Class hashClass; Index: src/OFHTTPClient.h ================================================================== --- src/OFHTTPClient.h +++ src/OFHTTPClient.h @@ -102,16 +102,16 @@ * * @brief A class for performing HTTP requests. */ @interface OFHTTPClient: OFObject { - id _delegate; + id _Nullable _delegate; bool _insecureRedirectsAllowed; - OFTCPSocket *_socket; - OFURL *_lastURL; + OFTCPSocket *_Nullable _socket; + OFURL *_Nullable _lastURL; bool _lastWasHEAD; - OFHTTPResponse *_lastResponse; + OFHTTPResponse *_Nullable _lastResponse; } /*! * The delegate of the HTTP request. */ Index: src/OFHTTPCookie.h ================================================================== --- src/OFHTTPCookie.h +++ src/OFHTTPCookie.h @@ -31,11 +31,11 @@ * @brief A class for storing and manipulating HTTP cookies. */ @interface OFHTTPCookie: OFObject { OFString *_name, *_value, *_domain, *_path; - OFDate *_expires; + OFDate *_Nullable _expires; bool _secure, _HTTPOnly; OFMutableArray OF_GENERIC(OFString *) *_extensions; } /*! Index: src/OFHTTPRequest.h ================================================================== --- src/OFHTTPRequest.h +++ src/OFHTTPRequest.h @@ -69,13 +69,13 @@ @interface OFHTTPRequest: OFObject { OFURL *_URL; of_http_request_method_t _method; of_http_request_protocol_version_t _protocolVersion; - OFDictionary OF_GENERIC(OFString *, OFString *) *_headers; - OFData *_body; - OFString *_remoteAddress; + OFDictionary OF_GENERIC(OFString *, OFString *) *_Nullable _headers; + OFData *_Nullable _body; + OFString *_Nullable _remoteAddress; } /*! * The URL of the HTTP request. */ Index: src/OFHTTPResponse.h ================================================================== --- src/OFHTTPResponse.h +++ src/OFHTTPResponse.h @@ -40,12 +40,12 @@ @property (nonatomic) short statusCode; /*! * The headers of the reply to the HTTP request. */ -@property OF_NULLABLE_PROPERTY (nonatomic, copy) - OFDictionary OF_GENERIC(OFString *, OFString *) *headers; +@property (copy, nonatomic) OFDictionary OF_GENERIC(OFString *, OFString *) + *headers; /*! * @brief Sets the protocol version of the HTTP request reply. * * @param protocolVersion The protocol version of the HTTP request reply Index: src/OFHTTPResponse.m ================================================================== --- src/OFHTTPResponse.m +++ src/OFHTTPResponse.m @@ -140,12 +140,18 @@ - init { self = [super init]; - _protocolVersion.major = 1; - _protocolVersion.minor = 1; + @try { + _protocolVersion.major = 1; + _protocolVersion.minor = 1; + _headers = [[OFDictionary alloc] init]; + } @catch (id e) { + [self release]; + @throw e; + } return self; } - (void)dealloc Index: src/OFHTTPServer.h ================================================================== --- src/OFHTTPServer.h +++ src/OFHTTPServer.h @@ -86,15 +86,15 @@ * * @brief A class for creating a simple HTTP server inside of applications. */ @interface OFHTTPServer: OFObject { - OFString *_host; + OFString *_Nullable _host; uint16_t _port; - id _delegate; - OFString *_name; - OFTCPSocket *_listeningSocket; + id _Nullable _delegate; + OFString *_Nullable _name; + OFTCPSocket *_Nullable _listeningSocket; } /*! * The host on which the HTTP server will listen. */ Index: src/OFINICategory+Private.h ================================================================== --- src/OFINICategory+Private.h +++ src/OFINICategory+Private.h @@ -20,13 +20,13 @@ OF_ASSUME_NONNULL_BEGIN @class OFStream; @interface OFINICategory () -- (instancetype)of_init OF_METHOD_FAMILY(init); +- (instancetype)of_initWithName: (OFString *)name OF_METHOD_FAMILY(init); - (void)of_parseLine: (OFString *)line; - (bool)of_writeToStream: (OFStream *)stream encoding: (of_string_encoding_t)encoding first: (bool)first; @end OF_ASSUME_NONNULL_END Index: src/OFINICategory.m ================================================================== --- src/OFINICategory.m +++ src/OFINICategory.m @@ -119,15 +119,16 @@ @end @implementation OFINICategory @synthesize name = _name; -- (instancetype)of_init +- (instancetype)of_initWithName: (OFString *)name { self = [super init]; @try { + _name = [name copy]; _lines = [[OFMutableArray alloc] init]; } @catch (id e) { [self release]; @throw e; } Index: src/OFINIFile.m ================================================================== --- src/OFINIFile.m +++ src/OFINIFile.m @@ -102,12 +102,11 @@ for (category in _categories) if ([[category name] isEqual: name]) return category; - category = [[[OFINICategory alloc] of_init] autorelease]; - [category setName: name]; + category = [[[OFINICategory alloc] of_initWithName: name] autorelease]; [_categories addObject: category]; objc_autoreleasePoolPop(pool); return category; @@ -144,12 +143,11 @@ categoryName = [line substringWithRange: of_range(1, [line length] - 2)]; category = [[[OFINICategory alloc] - of_init] autorelease]; - [category setName: categoryName]; + of_initWithName: categoryName] autorelease]; [_categories addObject: category]; } else { if (category == nil) @throw [OFInvalidFormatException exception]; Index: src/OFInflateStream.h ================================================================== --- src/OFInflateStream.h +++ src/OFInflateStream.h @@ -35,11 +35,11 @@ uint8_t _buffer[OF_INFLATE_STREAM_BUFFER_SIZE]; uint16_t _bufferIndex, _bufferLength; uint8_t _byte; uint8_t _bitIndex, _savedBitsLength; uint16_t _savedBits; - uint8_t *_slidingWindow; + uint8_t *_Nullable _slidingWindow; uint16_t _slidingWindowIndex, _slidingWindowMask; int _state; union { struct { uint8_t position; @@ -47,20 +47,23 @@ } uncompressedHeader; struct { uint16_t position, length; } uncompressed; struct { - struct huffman_tree *litLenTree, *distTree; - struct huffman_tree *codeLenTree, *treeIter; - uint8_t *lengths; + struct huffman_tree *_Nullable litLenTree; + struct huffman_tree *_Nullable distTree; + struct huffman_tree *_Nullable codeLenTree; + struct huffman_tree *_Nullable treeIter; + uint8_t *_Nullable lengths; uint16_t receivedCount; uint8_t value, litLenCodesCount, distCodesCount; uint8_t codeLenCodesCount; } huffmanTree; struct { - struct huffman_tree *litLenTree, *distTree; - struct huffman_tree *treeIter; + struct huffman_tree *_Nullable litLenTree; + struct huffman_tree *_Nullable distTree; + struct huffman_tree *_Nullable treeIter; int state; uint16_t value, length, distance, extraBits; } huffman; } _context; bool _inLastBlock, _atEndOfStream; Index: src/OFIntrospection.h ================================================================== --- src/OFIntrospection.h +++ src/OFIntrospection.h @@ -72,11 +72,11 @@ */ @interface OFProperty: OFObject { OFString *_name; unsigned _attributes; - OFString *_getter, *_setter; + OFString *_Nullable _getter, *_Nullable _setter; } /*! * The name of the property. */ Index: src/OFKernelEventObserver.h ================================================================== --- src/OFKernelEventObserver.h +++ src/OFKernelEventObserver.h @@ -109,11 +109,11 @@ { OFMutableArray OF_GENERIC(id ) *_readObjects; OFMutableArray OF_GENERIC(id ) *_writeObjects; - id _delegate; + id _Nullable _delegate; #ifdef OF_HAVE_PIPE int _cancelFD[2]; #else of_socket_t _cancelFD[2]; struct sockaddr_in _cancelAddr; Index: src/OFKeyValueCoding.h ================================================================== --- src/OFKeyValueCoding.h +++ src/OFKeyValueCoding.h @@ -52,11 +52,11 @@ * @brief Set the value for the specified key * * @param value The value for the specified key * @param key The key of the value to set */ -- (void)setValue: (nullable id)value +- (void)setValue: (id)value forKey: (OFString *)key; /*! * @brief This is called by @ref setValue:forKey: if the specified key does not * exist. Index: src/OFList.h ================================================================== --- src/OFList.h +++ src/OFList.h @@ -29,15 +29,15 @@ * * A struct that contains a pointer to the next list object, the previous list * object and the object. */ struct of_list_object_t { - /// A pointer to the next list object in the list - of_list_object_t *next; - /// A pointer to the previous list object in the list - of_list_object_t *previous; - /// The object for the list object + /*! A pointer to the next list object in the list */ + of_list_object_t *_Nullable next; + /*! A pointer to the previous list object in the list */ + of_list_object_t *_Nullable previous; + /*! The object for the list object */ id __unsafe_unretained object; }; /*! * @class OFList OFList.h ObjFW/OFList.h @@ -48,14 +48,14 @@ OFSerialization> #if !defined(OF_HAVE_GENERICS) && !defined(DOXYGEN) # define ObjectType id #endif { - of_list_object_t *_firstListObject; - of_list_object_t *_lastListObject; - size_t _count; - unsigned long _mutations; + of_list_object_t *_Nullable _firstListObject; + of_list_object_t *_Nullable _lastListObject; + size_t _count; + unsigned long _mutations; } /*! * The first list object of the list. */ @@ -182,16 +182,16 @@ #endif @end @interface OFListEnumerator: OFEnumerator { - OFList *_list; - of_list_object_t *_current; - unsigned long _mutations; - unsigned long *_mutationsPtr; + OFList *_list; + of_list_object_t *_Nullable _current; + unsigned long _mutations; + unsigned long *_Nullable _mutationsPtr; } - initWithList: (OFList *)list mutationsPointer: (unsigned long *)mutationsPtr; @end OF_ASSUME_NONNULL_END Index: src/OFLocalization.h ================================================================== --- src/OFLocalization.h +++ src/OFLocalization.h @@ -34,12 +34,11 @@ * * @brief A class for querying the locale and retrieving localized strings. */ @interface OFLocalization: OFObject { - OFString *_language; - OFString *_territory; + OFString *_Nullable _language, *_Nullable _territory; of_string_encoding_t _encoding; OFString *_decimalPoint; OFMutableArray OF_GENERIC(OFDictionary OF_GENERIC(OFString *, id) *) *_localizedStrings; } Index: src/OFMapTable.h ================================================================== --- src/OFMapTable.h +++ src/OFMapTable.h @@ -25,18 +25,19 @@ * @struct of_map_table_functions_t OFMapTable.h ObjFW/OFMapTable.h * * @brief A struct describing the functions to be used by the map table. */ typedef struct { - /// The function to retain keys / objects - void *_Nonnull (*_Nullable retain)(void *object); - /// The function to release keys / objects - void (*_Nullable release)(void *object); - /// The function to hash keys - uint32_t (*_Nullable hash)(void *object); - /// The function to compare keys / objects - bool (*_Nullable equal)(void *object1, void *object2); + /*! The function to retain keys / objects */ + void *_Nullable (*_Nullable retain)(void *_Nullable object); + /*! The function to release keys / objects */ + void (*_Nullable release)(void *_Nullable object); + /*! The function to hash keys */ + uint32_t (*_Nullable hash)(void *_Nullable object); + /*! The function to compare keys / objects */ + bool (*_Nullable equal)(void *_Nullable object1, + void *_Nullable object2); } of_map_table_functions_t; #ifdef OF_HAVE_BLOCKS /*! * @brief A block for enumerating an OFMapTable. @@ -68,11 +69,11 @@ * and objects should be retained, released, compared and hashed. */ @interface OFMapTable: OFObject { of_map_table_functions_t _keyFunctions, _objectFunctions; - struct of_map_table_bucket **_buckets; + struct of_map_table_bucket *_Nonnull *_Nullable _buckets; uint32_t _count, _capacity; uint8_t _rotate; unsigned long _mutations; } @@ -235,14 +236,14 @@ * keys or objects. */ @interface OFMapTableEnumerator: OFObject { OFMapTable *_mapTable; - struct of_map_table_bucket **_buckets; + struct of_map_table_bucket *_Nonnull *_Nullable _buckets; uint32_t _capacity; unsigned long _mutations; - unsigned long *_mutationsPtr; + unsigned long *_Nullable _mutationsPtr; uint32_t _position; } - init OF_UNAVAILABLE; @@ -249,15 +250,15 @@ /*! * @brief Returns the next object. * * @return The next object */ -- (void *)nextObject; +- (nullable void *)nextObject; /*! * @brief Resets the enumerator, so the next call to @ref nextKey returns the * first key again. */ - (void)reset; @end OF_ASSUME_NONNULL_END Index: src/OFMutableURL.m ================================================================== --- src/OFMutableURL.m +++ src/OFMutableURL.m @@ -16,10 +16,11 @@ #include "config.h" #import "OFMutableURL.h" #import "OFURL+Private.h" +#import "OFString.h" @implementation OFMutableURL @dynamic scheme, host, port, user, password, path, parameters, query, fragment; + (instancetype)URL Index: src/OFMutex.h ================================================================== --- src/OFMutex.h +++ src/OFMutex.h @@ -28,11 +28,11 @@ */ @interface OFMutex: OFObject { of_mutex_t _mutex; bool _initialized; - OFString *_name; + OFString *_Nullable _name; } /*! * @brief Creates a new mutex. * Index: src/OFObject.h ================================================================== --- src/OFObject.h +++ src/OFObject.h @@ -646,11 +646,12 @@ * @brief Allocates memory and stores it in the object's memory pool. * * It will be freed automatically when the object is deallocated. * * @param size The size of the memory to allocate - * @return A pointer to the allocated memory + * @return A pointer to the allocated memory. May return NULL if the specified + * size is 0. */ - (void *)allocMemoryWithSize: (size_t)size; /*! * @brief Allocates memory for the specified number of items and stores it in @@ -658,11 +659,12 @@ * * It will be freed automatically when the object is deallocated. * * @param size The size of each item to allocate * @param count The number of items to allocate - * @return A pointer to the allocated memory + * @return A pointer to the allocated memory. May return NULL if the specified + * size or count is 0. */ - (void *)allocMemoryWithSize: (size_t)size count: (size_t)count; /*! Index: src/OFObject.m ================================================================== --- src/OFObject.m +++ src/OFObject.m @@ -828,11 +828,11 @@ { void *pointer; struct pre_mem *preMem; if OF_UNLIKELY (size == 0) - return NULL; + return (void *_Nonnull)NULL; if OF_UNLIKELY (size > SIZE_MAX - PRE_IVARS_ALIGN) @throw [OFOutOfRangeException exception]; if OF_UNLIKELY ((pointer = malloc(PRE_MEM_ALIGN + size)) == NULL) Index: src/OFOptionsParser.h ================================================================== --- src/OFOptionsParser.h +++ src/OFOptionsParser.h @@ -70,11 +70,11 @@ of_options_parser_option_t *_options; OFMapTable *_longOptions; OFArray OF_GENERIC(OFString *) *_arguments; size_t _index, _subIndex; of_unichar_t _lastOption; - OFString *_lastLongOption, *_argument; + OFString *_Nullable _lastLongOption, *_Nullable _argument; bool _done; } /*! * The last parsed option. Index: src/OFRecursiveMutex.h ================================================================== --- src/OFRecursiveMutex.h +++ src/OFRecursiveMutex.h @@ -29,11 +29,11 @@ */ @interface OFRecursiveMutex: OFObject { of_rmutex_t _rmutex; bool _initialized; - OFString *_name; + OFString *_Nullable _name; } /*! * @brief Creates a new recursive mutex. * Index: src/OFRunLoop.m ================================================================== --- src/OFRunLoop.m +++ src/OFRunLoop.m @@ -15,10 +15,11 @@ */ #include "config.h" #include +#include #import "OFRunLoop.h" #import "OFRunLoop+Private.h" #import "OFDictionary.h" #ifdef OF_HAVE_SOCKETS @@ -31,10 +32,12 @@ #endif #import "OFSortedList.h" #import "OFTimer.h" #import "OFTimer+Private.h" #import "OFDate.h" + +#import "OFObserveFailedException.h" static OFRunLoop *mainRunLoop = nil; #ifdef OF_HAVE_SOCKETS @interface OFRunLoop_QueueItem: OFObject @@ -717,12 +720,17 @@ if (timeout < 0) timeout = 0; #if defined(OF_HAVE_SOCKETS) - [_kernelEventObserver - observeForTimeInterval: timeout]; + @try { + [_kernelEventObserver + observeForTimeInterval: timeout]; + } @catch (OFObserveFailedException *e) { + if ([e errNo] != EINTR) + @throw e; + } #elif defined(OF_HAVE_THREADS) [_condition lock]; [_condition waitForTimeInterval: timeout]; [_condition unlock]; #else @@ -733,11 +741,16 @@ * No more timers and no deadline: Just watch for I/O * until we get an event. If a timer is added by * another thread, it cancels the observe. */ #if defined(OF_HAVE_SOCKETS) - [_kernelEventObserver observe]; + @try { + [_kernelEventObserver observe]; + } @catch (OFObserveFailedException *e) { + if ([e errNo] != EINTR) + @throw e; + } #elif defined(OF_HAVE_THREADS) [_condition lock]; [_condition wait]; [_condition unlock]; #else Index: src/OFSet.h ================================================================== --- src/OFSet.h +++ src/OFSet.h @@ -243,11 +243,11 @@ * @note A @ref OFNull value is translated to nil! * * @param value The value for the specified key * @param key The key of the value to set */ -- (void)setValue: (nullable id)value +- (void)setValue: (id)value forKey: (OFString *)key; /*! * @brief Returns an OFEnumerator to enumerate through all objects of the set. * Index: src/OFSet.m ================================================================== --- src/OFSet.m +++ src/OFSet.m @@ -253,13 +253,10 @@ objc_autoreleasePoolPop(pool); return; } - if (value == [OFNull null]) - value = nil; - for (id object in self) [object setValue: value forKey: key]; } Index: src/OFStream.h ================================================================== --- src/OFStream.h +++ src/OFStream.h @@ -92,11 +92,12 @@ OFCopying> { #if !defined(OF_SEEKABLE_STREAM_M) && !defined(OF_TCP_SOCKET_M) @private #endif - char *_readBuffer, *_readBufferMemory, *_writeBuffer; + char *_Nullable _readBuffer, *_Nullable _readBufferMemory; + char *_Nullable _writeBuffer; size_t _readBufferLength, _writeBufferLength; bool _writeBuffered, _waitingForDelimiter; @protected bool _blocking; } Index: src/OFStream.m ================================================================== --- src/OFStream.m +++ src/OFStream.m @@ -56,11 +56,11 @@ #define MIN_READ_SIZE 512 @implementation OFStream @synthesize of_waitingForDelimiter = _waitingForDelimiter; -#if !defined(OF_WINDOWS) && !defined(OF_MORPHOS) +#if defined(SIGPIPE) && defined(SIG_IGN) + (void)initialize { if (self == [OFStream class]) signal(SIGPIPE, SIG_IGN); } Index: src/OFString+XMLUnescaping.h ================================================================== --- src/OFString+XMLUnescaping.h +++ src/OFString+XMLUnescaping.h @@ -58,12 +58,12 @@ * * @param string The string which contains the unknown entity * @param entity The name of the entity that is unknown * @return A substitution for the entity or `nil` */ -- (OFString *)string: (OFString *)string - containsUnknownEntityNamed: (OFString *)entity; +- (nullable OFString *)string: (OFString *)string + containsUnknownEntityNamed: (OFString *)entity; @end @interface OFString (XMLUnescaping) /*! * @brief Unescapes XML in the string. Index: src/OFString.h ================================================================== --- src/OFString.h +++ src/OFString.h @@ -18,10 +18,16 @@ # define __STDC_LIMIT_MACROS #endif #ifndef __STDC_CONSTANT_MACROS # define __STDC_CONSTANT_MACROS #endif + +#import "objfw-defs.h" + +#ifdef OF_HAVE_SYS_TYPES_H +# include +#endif #include #include #import "OFObject.h" Index: src/OFString_UTF8.h ================================================================== --- src/OFString_UTF8.h +++ src/OFString_UTF8.h @@ -33,11 +33,11 @@ size_t cStringLength; bool isUTF8; size_t length; bool hashed; uint32_t hash; - char *freeWhenDone; + char *_Nullable freeWhenDone; } *restrict _s; struct of_string_utf8_ivars _storage; } @end Index: src/OFTCPSocket.h ================================================================== --- src/OFTCPSocket.h +++ src/OFTCPSocket.h @@ -59,13 +59,13 @@ * To create a server, create a socket, bind it and listen on it. */ @interface OFTCPSocket: OFStreamSocket { bool _listening; - struct sockaddr *_address; + struct sockaddr *_Nullable _address; socklen_t _addressLength; - OFString *_SOCKS5Host; + OFString *_Nullable _SOCKS5Host; uint16_t _SOCKS5Port; #ifdef OF_WII uint16_t _port; #endif } Index: src/OFTCPSocket.m ================================================================== --- src/OFTCPSocket.m +++ src/OFTCPSocket.m @@ -183,11 +183,11 @@ @try { [_socket connectToHost: _host port: _port]; } @catch (OFException *e) { - _exception = e; + _exception = [e retain]; } [self performSelector: @selector(didConnect) onThread: _sourceThread waitUntilDone: false]; Index: src/OFTarArchive.h ================================================================== --- src/OFTarArchive.h +++ src/OFTarArchive.h @@ -32,11 +32,11 @@ #ifdef OF_TAR_ARCHIVE_ENTRY_M @public #endif OFStream *_stream; @protected - OFTarArchiveEntry *_lastReturnedEntry; + OFTarArchiveEntry *_Nullable _lastReturnedEntry; } /*! * @brief Creates a new OFTarArchive object with the specified stream. * @@ -84,9 +84,9 @@ * @ref OFReadFailedException! * * @return The next entry from the tar archive or `nil` if all entries have * been read */ -- (OFTarArchiveEntry *)nextEntry; +- (nullable OFTarArchiveEntry *)nextEntry; @end OF_ASSUME_NONNULL_END Index: src/OFTarArchiveEntry.h ================================================================== --- src/OFTarArchiveEntry.h +++ src/OFTarArchiveEntry.h @@ -55,12 +55,12 @@ OFString *_fileName; uint32_t _mode; uint64_t _size, _toRead; OFDate *_modificationDate; of_tar_archive_entry_type_t _type; - OFString *_targetFileName; - OFString *_owner, *_group; + OFString *_Nullable _targetFileName; + OFString *_Nullable _owner, *_Nullable _group; uint32_t _deviceMajor, _deviceMinor; } /*! * The file name of the entry. Index: src/OFTarArchiveEntry.m ================================================================== --- src/OFTarArchiveEntry.m +++ src/OFTarArchiveEntry.m @@ -86,24 +86,28 @@ if (_type == '\0') _type = OF_TAR_ARCHIVE_ENTRY_TYPE_FILE; if (memcmp(header + 257, "ustar\0" "00", 8) == 0) { - OFString *fileName; + OFString *prefix; _owner = [stringFromBuffer(header + 265, 32) copy]; _group = [stringFromBuffer(header + 297, 32) copy]; _deviceMajor = (uint32_t)octalValueFromBuffer( header + 329, 8, UINT32_MAX); _deviceMinor = (uint32_t)octalValueFromBuffer( header + 337, 8, UINT32_MAX); - fileName = [OFString stringWithFormat: @"%@/%@", - stringFromBuffer(header + 345, 155), _fileName]; - [_fileName release]; - _fileName = [fileName copy]; + prefix = stringFromBuffer(header + 345, 155); + if ([prefix length] > 0) { + OFString *fileName = [OFString + stringWithFormat: @"%@/%@", + prefix, _fileName]; + [_fileName release]; + _fileName = [fileName copy]; + } } objc_autoreleasePoolPop(pool); } @catch (id e) { [self release]; Index: src/OFThread.h ================================================================== --- src/OFThread.h +++ src/OFThread.h @@ -69,14 +69,14 @@ void *_pool; # ifdef OF_HAVE_BLOCKS of_thread_block_t _threadBlock; # endif id _returnValue; - OFRunLoop *_runLoop; + OFRunLoop *_Nullable _runLoop; OFMutableDictionary *_threadDictionary; @private - OFString *_name; + OFString *_Nullable _name; } #ifdef OF_HAVE_BLOCKS /*! * The block to execute in the thread. Index: src/OFTimer.h ================================================================== --- src/OFTimer.h +++ src/OFTimer.h @@ -43,11 +43,12 @@ */ @interface OFTimer: OFObject { OFDate *_fireDate; of_time_interval_t _interval; - id _target, _object1, _object2; + id _target; + id _Nullable _object1, _object2; SEL _selector; uint8_t _arguments; bool _repeats; #ifdef OF_HAVE_BLOCKS of_timer_block_t _block; @@ -55,11 +56,11 @@ bool _valid; #ifdef OF_HAVE_THREADS OFCondition *_condition; bool _done; #endif - OFRunLoop *_inRunLoop; + OFRunLoop *_Nullable _inRunLoop; } /*! * The time interval in which the timer will repeat, if it is a repeating * timer. Index: src/OFURL.h ================================================================== --- src/OFURL.h +++ src/OFURL.h @@ -28,11 +28,13 @@ */ @interface OFURL: OFObject { OFString *_scheme, *_host; uint16_t _port; - OFString *_user, *_password, *_path, *_parameters, *_query, *_fragment; + OFString *_Nullable _user, *_Nullable _password, *_path; + OFString *_Nullable _parameters, *_Nullable _query; + OFString *_Nullable _fragment; } /*! * The scheme part of the URL. */ Index: src/OFXMLAttribute.h ================================================================== --- src/OFXMLAttribute.h +++ src/OFXMLAttribute.h @@ -26,11 +26,11 @@ * @brief A representation of an attribute of an XML element as an object. */ @interface OFXMLAttribute: OFXMLNode { @public - OFString *_name, *_namespace, *_stringValue; + OFString *_name, *_Nullable _namespace, *_stringValue; } /*! * The name of the attribute. */ Index: src/OFXMLElement.h ================================================================== --- src/OFXMLElement.h +++ src/OFXMLElement.h @@ -30,14 +30,15 @@ * * @brief A class which stores an XML element. */ @interface OFXMLElement: OFXMLNode { - OFString *_name, *_namespace, *_defaultNamespace; - OFMutableArray OF_GENERIC(OFXMLAttribute *) *_attributes; - OFMutableDictionary OF_GENERIC(OFString *, OFString *) *_namespaces; - OFMutableArray OF_GENERIC(OFXMLNode *) *_children; + OFString *_name, *_Nullable _namespace, *_Nullable _defaultNamespace; + OFMutableArray OF_GENERIC(OFXMLAttribute *) *_Nullable _attributes; + OFMutableDictionary OF_GENERIC(OFString *, OFString *) *_Nullable + _namespaces; + OFMutableArray OF_GENERIC(OFXMLNode *) *_Nullable _children; } /*! * The name of the element. */ @@ -276,21 +277,21 @@ * @brief Returns the attribute with the specified name. * * @param attributeName The name of the attribute * @return The attribute with the specified name */ -- (OFXMLAttribute *)attributeForName: (OFString *)attributeName; +- (nullable OFXMLAttribute *)attributeForName: (OFString *)attributeName; /*! * @brief Returns the attribute with the specified name and namespace. * * @param attributeName The name of the attribute * @param attributeNS The namespace of the attribute * @return The attribute with the specified name and namespace */ -- (OFXMLAttribute *)attributeForName: (OFString *)attributeName - namespace: (nullable OFString *)attributeNS; +- (nullable OFXMLAttribute *)attributeForName: (OFString *)attributeName + namespace: (nullable OFString *)attributeNS; /*! * @brief Removes the attribute with the specified name. * * @param attributeName The name of the attribute @@ -397,11 +398,11 @@ * @brief Returns the first child element with the specified name. * * @param elementName The name of the element * @return The first child element with the specified name */ -- (OFXMLElement *)elementForName: (OFString *)elementName; +- (nullable OFXMLElement *)elementForName: (OFString *)elementName; /*! * @brief Returns the child elements with the specified name. * * @param elementName The name of the elements @@ -415,12 +416,12 @@ * * @param elementName The name of the element * @param elementNS The namespace of the element * @return The first child element with the specified name and namespace */ -- (OFXMLElement *)elementForName: (OFString *)elementName - namespace: (nullable OFString *)elementNS; +- (nullable OFXMLElement *)elementForName: (OFString *)elementName + namespace: (nullable OFString *)elementNS; /*! * @brief Returns the child elements with the specified name and namespace. * * @param elementName The name of the elements Index: src/OFXMLElementBuilder.h ================================================================== --- src/OFXMLElementBuilder.h +++ src/OFXMLElementBuilder.h @@ -104,11 +104,11 @@ * setting the OFXMLElementBuilder as delegate for the parser. */ @interface OFXMLElementBuilder: OFObject { OFMutableArray OF_GENERIC(OFXMLElement *) *_stack; - id _delegate; + id _Nullable _delegate; } /*! * The delegate for the OFXMLElementBuilder. */ Index: src/OFXMLParser.h ================================================================== --- src/OFXMLParser.h +++ src/OFXMLParser.h @@ -114,12 +114,12 @@ * * @param parser The parser which found an unknown entity * @param entity The name of the entity the XML parser didn't know * @return A substitution for the entity or `nil` */ -- (OFString *)parser: (OFXMLParser *)parser - foundUnknownEntityNamed: (OFString *)entity; +- (nullable OFString *)parser: (OFXMLParser *)parser + foundUnknownEntityNamed: (OFString *)entity; @end /*! * @class OFXMLParser OFXMLParser.h ObjFW/OFXMLParser.h * @@ -128,11 +128,11 @@ * OFXMLParser is an event-based XML parser which calls the delegate's callbacks * as soon as it finds something, thus suitable for streams as well. */ @interface OFXMLParser: OFObject { - id _delegate; + id _Nullable _delegate; enum of_xml_parser_state { OF_XMLPARSER_IN_BYTE_ORDER_MARK, OF_XMLPARSER_OUTSIDE_TAG, OF_XMLPARSER_TAG_OPENED, OF_XMLPARSER_IN_PROCESSING_INSTRUCTIONS, @@ -153,18 +153,18 @@ OF_XMLPARSER_IN_COMMENT_2, OF_XMLPARSER_IN_DOCTYPE, OF_XMLPARSER_NUM_STATES } _state; size_t _i, _last; - const char *_data; + const char *_Nullable _data; OFMutableData *_buffer; - OFString *_name, *_prefix; + OFString *_Nullable _name, *_Nullable _prefix; OFMutableArray OF_GENERIC(OFMutableDictionary OF_GENERIC(OFString *, OFString *) *) *_namespaces; OFMutableArray OF_GENERIC(OFXMLAttribute *) *_attributes; - OFString *_attributeName, *_attributePrefix; + OFString *_Nullable _attributeName, *_Nullable _attributePrefix; char _delimiter; OFMutableArray OF_GENERIC(OFString *) *_previous; size_t _level; bool _acceptProlog; size_t _lineNumber; Index: src/OFZIPArchive.h ================================================================== --- src/OFZIPArchive.h +++ src/OFZIPArchive.h @@ -36,15 +36,15 @@ OFSeekableStream *_stream; uint32_t _diskNumber, _centralDirectoryDisk; uint64_t _centralDirectoryEntriesInDisk, _centralDirectoryEntries; uint64_t _centralDirectorySize; int64_t _centralDirectoryOffset; - OFString *_archiveComment; + OFString *_Nullable _archiveComment; OFMutableArray OF_GENERIC(OFZIPArchiveEntry *) *_entries; OFMutableDictionary OF_GENERIC(OFString *, OFZIPArchiveEntry *) *_pathToEntryMap; - OFStream *_lastReturnedStream; + OFStream *_Nullable _lastReturnedStream; } /*! * The archive comment. */ Index: src/OFZIPArchive.m ================================================================== --- src/OFZIPArchive.m +++ src/OFZIPArchive.m @@ -71,19 +71,18 @@ @end @interface OFZIPArchive_FileStream: OFStream { OFStream *_stream, *_decompressedStream; - OFZIPArchive_LocalFileHeader *_localFileHeader; - bool _hasDataDescriptor; - uint64_t _size; + OFZIPArchiveEntry *_entry; + uint64_t _toRead; uint32_t _CRC32; bool _atEndOfStream; } - initWithStream: (OFStream *)path - localFileHeader: (OFZIPArchive_LocalFileHeader *)localFileHeader; + entry: (OFZIPArchiveEntry *)localFileHeader; @end uint32_t of_zip_archive_read_field32(const uint8_t **data, uint16_t *size) { @@ -358,11 +357,11 @@ exceptionWithVersion: version]; } _lastReturnedStream = [[OFZIPArchive_FileStream alloc] initWithStream: _stream - localFileHeader: localFileHeader]; + entry: entry]; objc_autoreleasePoolPop(pool); return _lastReturnedStream; } @@ -451,18 +450,18 @@ } @end @implementation OFZIPArchive_FileStream - initWithStream: (OFStream *)stream - localFileHeader: (OFZIPArchive_LocalFileHeader *)localFileHeader + entry: (OFZIPArchiveEntry *)entry { self = [super init]; @try { _stream = [stream retain]; - switch (localFileHeader->_compressionMethod) { + switch ([entry compressionMethod]) { case OF_ZIP_ARCHIVE_ENTRY_COMPRESSION_METHOD_NONE: _decompressedStream = [stream retain]; break; case OF_ZIP_ARCHIVE_ENTRY_COMPRESSION_METHOD_DEFLATE: _decompressedStream = [[OFInflateStream alloc] @@ -476,14 +475,12 @@ @throw [OFNotImplementedException exceptionWithSelector: _cmd object: self]; } - _localFileHeader = [localFileHeader retain]; - _hasDataDescriptor = (localFileHeader->_generalPurposeBitFlag & - (1 << 3)); - _size = localFileHeader->_uncompressedSize; + _entry = [entry retain]; + _toRead = [entry uncompressedSize]; _CRC32 = ~0; } @catch (id e) { [self release]; @throw e; } @@ -493,12 +490,13 @@ - (void)dealloc { [self close]; + [_stream release]; [_decompressedStream release]; - [_localFileHeader release]; + [_entry release]; [super dealloc]; } - (bool)lowlevelIsAtEndOfStream @@ -507,58 +505,36 @@ } - (size_t)lowlevelReadIntoBuffer: (void *)buffer length: (size_t)length { - size_t min, ret; + size_t ret; if (_stream == nil) @throw [OFNotOpenException exceptionWithObject: self]; if (_atEndOfStream) return 0; - if (_hasDataDescriptor) { - if ([_decompressedStream isAtEndOfStream]) { - uint32_t CRC32; - - _atEndOfStream = true; - - CRC32 = [_stream readLittleEndianInt32]; - if (CRC32 == 0x08074B50) - CRC32 = [_stream readLittleEndianInt32]; - - if (~_CRC32 != CRC32) - @throw [OFChecksumFailedException exception]; - - /* - * FIXME: Check (un)compressed length! - * (Note: Both are 64 bit if the entry uses ZIP64!) - */ - - return 0; - } - - ret = [_decompressedStream readIntoBuffer: buffer - length: length]; - } else { - if (_size == 0) { - _atEndOfStream = true; - - if (~_CRC32 != _localFileHeader->_CRC32) - @throw [OFChecksumFailedException exception]; - - return 0; - } - - min = (length < _size ? length : (size_t)_size); - ret = [_decompressedStream readIntoBuffer: buffer - length: min]; - _size -= ret; - } - - _CRC32 = of_crc32(_CRC32, buffer, ret); + if (sizeof(length) >= sizeof(uint64_t) && length > UINT64_MAX) + @throw [OFOutOfRangeException exception]; + + if ((uint64_t)length > _toRead) + length = (size_t)_toRead; + + ret = [_decompressedStream readIntoBuffer: buffer + length: length]; + + if (ret == 0) + _atEndOfStream = true; + + _toRead -= ret; + _CRC32 = of_crc32(_CRC32, buffer, ret); + + if (_toRead == 0) + if (~_CRC32 != [_entry CRC32]) + @throw [OFChecksumFailedException exception]; return ret; } - (void)close Index: src/OFZIPArchiveEntry.h ================================================================== --- src/OFZIPArchiveEntry.h +++ src/OFZIPArchiveEntry.h @@ -93,12 +93,12 @@ uint16_t _compressionMethod; uint16_t _lastModifiedFileTime, _lastModifiedFileDate; uint32_t _CRC32; uint64_t _compressedSize, _uncompressedSize; OFString *_fileName; - OFData *_extraField; - OFString *_fileComment; + OFData *_Nullable _extraField; + OFString *_Nullable _fileComment; uint32_t _startDiskNumber; uint16_t _internalAttributes; uint32_t _versionSpecificAttributes; int64_t _localFileHeaderOffset; } Index: src/block.h ================================================================== --- src/block.h +++ src/block.h @@ -28,12 +28,12 @@ int reserved; void (*invoke)(void *block, ...); struct of_block_descriptor_t { unsigned long reserved; unsigned long size; - void (*copy_helper)(void *dest, void *src); - void (*dispose_helper)(void *src); + void (*_Nullable copy_helper)(void *dest, void *src); + void (*_Nullable dispose_helper)(void *src); const char *signature; } *descriptor; } of_block_literal_t; #ifdef __cplusplus Index: src/exceptions/OFMemoryNotPartOfObjectException.h ================================================================== --- src/exceptions/OFMemoryNotPartOfObjectException.h +++ src/exceptions/OFMemoryNotPartOfObjectException.h @@ -25,18 +25,18 @@ * * @brief An exception indicating the given memory is not part of the object. */ @interface OFMemoryNotPartOfObjectException: OFException { - void *_pointer; + void *_Nullable _pointer; id _object; } /*! * A pointer to the memory which is not part of the object. */ -@property (readonly, nonatomic) void *pointer; +@property OF_NULLABLE_PROPERTY (readonly, nonatomic) void *pointer; /*! * The object which the memory is not part of. */ @property (readonly, nonatomic) id object; @@ -48,11 +48,11 @@ * * @param pointer A pointer to the memory that is not part of the object * @param object The object which the memory is not part of * @return A new, autoreleased memory not part of object exception */ -+ (instancetype)exceptionWithPointer: (void *)pointer ++ (instancetype)exceptionWithPointer: (nullable void *)pointer object: (id)object; - init OF_UNAVAILABLE; /*! @@ -60,10 +60,10 @@ * * @param pointer A pointer to the memory that is not part of the object * @param object The object which the memory is not part of * @return An initialized memory not part of object exception */ -- initWithPointer: (void *)pointer +- initWithPointer: (nullable void *)pointer object: (id)object OF_DESIGNATED_INITIALIZER; @end OF_ASSUME_NONNULL_END Index: src/of_asprintf.m ================================================================== --- src/of_asprintf.m +++ src/of_asprintf.m @@ -558,14 +558,16 @@ @try { OFMutableString *tmpStr = [OFMutableString stringWithUTF8String: tmp length: tmpLen]; - OFString *decimalPoint = + OFString *point = [OFLocalization decimalPoint]; - [tmpStr replaceOccurrencesOfString: decimalPoint - withString: @"."]; + if (point != nil) + [tmpStr + replaceOccurrencesOfString: point + withString: @"."]; if ([tmpStr UTF8StringLength] > INT_MAX) return false; tmpLen = (int)[tmpStr UTF8StringLength]; tmp2 = malloc(tmpLen); memcpy(tmp2, [tmpStr UTF8String], tmpLen); Index: src/runtime/Makefile ================================================================== --- src/runtime/Makefile +++ src/runtime/Makefile @@ -2,11 +2,10 @@ SUBDIRS = lookup-asm SHARED_LIB = ${OBJFW_RT_SHARED_LIB} STATIC_LIB = ${OBJFW_RT_STATIC_LIB} -MORPHOS_LIB = ${OBJFW_RT_MORPHOS_LIB} LIB_MAJOR = ${OBJFW_RT_LIB_MAJOR} LIB_MINOR = ${OBJFW_RT_LIB_MINOR} SRCS = arc.m \ category.m \ @@ -29,22 +28,13 @@ INCLUDES = ObjFW-RT.h includesubdir = ObjFW-RT OBJS_EXTRA = ${LOOKUP_ASM_LOOKUP_ASM_A} LIB_OBJS_EXTRA = ${LOOKUP_ASM_LOOKUP_ASM_LIB_A} -MORPHOS_LIB_OBJS_EXTRA = morphos-library.o ${LOOKUP_ASM_LOOKUP_ASM_A} include ../../buildsys.mk -${MORPHOS_LIB}: ppcinline.h -ppcinline.h: ObjFW-RT.fd protos.h - cvinclude.pl \ - --root ObjFW_RT \ - --fd ObjFW-RT.fd \ - --clib protos.h \ - --inline $@ - CPPFLAGS += -I. -I.. -I../.. \ -DOF_COMPILING_OBJFW_RT \ -DOBJFW_RT_LIB_MAJOR=${OBJFW_RT_LIB_MAJOR} \ -DOBJFW_RT_LIB_MINOR=${OBJFW_RT_LIB_MINOR} LD = ${OBJC} Index: src/runtime/ObjFW-RT.h ================================================================== --- src/runtime/ObjFW-RT.h +++ src/runtime/ObjFW-RT.h @@ -197,14 +197,13 @@ struct objc_protocol_list *_Nullable next; long count; Protocol *__unsafe_unretained _Nonnull list[1]; }; -#if 1 /* !defined(__MORPHOS__) || defined(OF_COMPILING_OBJFW_RT) */ -# ifdef __cplusplus +#ifdef __cplusplus extern "C" { -# endif +#endif extern SEL _Nonnull sel_registerName(const char *_Nonnull); extern const char *_Nonnull sel_getName(SEL _Nonnull); extern bool sel_isEqual(SEL _Nonnull, SEL _Nonnull); extern Class _Nonnull objc_allocateClassPair(Class _Nullable, const char *_Nonnull, size_t); @@ -239,30 +238,11 @@ objc_uncaught_exception_handler _Nullable); extern void objc_setForwardHandler(IMP _Nullable, IMP _Nullable); extern void objc_setEnumerationMutationHandler( objc_enumeration_mutation_handler _Nullable); extern void objc_zero_weak_references(id _Nonnull); -# ifdef __cplusplus -} -# endif -#else -# define BOOL EXEC_BOOL -# include -# undef BOOL -# ifdef __cplusplus -extern "C" { -# endif -extern struct Library *ObjFWRTBase; -# ifdef __cplusplus -} -# endif -# include "ppcinline.h" -#endif - -#ifdef __cplusplus -extern "C" { -#endif + /* * Used by the compiler, but can also be called manually. * * They need to be in the glue code for the MorphOS library. * 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 @@ -50,15 +50,20 @@ #endif ldx [%o2 + %o4], %o2 ldx [%o2 + %o5], %o2 cmp %o2, 0 - be,pn %xcc, \not_found + be,pn %xcc, 0f nop retl mov %o2, %o0 + +0: + mov %o7, %g1 + call \not_found + mov %g1, %o7 .type \name, %function .size \name, .-\name .endm .macro generate_lookup_super name lookup DELETED src/runtime/morphos-library.m Index: src/runtime/morphos-library.m ================================================================== --- src/runtime/morphos-library.m +++ src/runtime/morphos-library.m @@ -1,221 +0,0 @@ -/* - * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017 - * Jonathan Schleifer - * - * All rights reserved. - * - * This file is part of ObjFW. It may be distributed under the terms of the - * Q Public License 1.0, which can be found in the file LICENSE.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * Public License, either version 2 or 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 "ObjFW-RT.h" -#import "macros.h" - -#define BOOL EXEC_BOOL -#include -#include -#include -#include -#include -#include -#include -#undef BOOL - -struct ObjFWRTBase { - struct Library library; - BPTR seg_list; -}; - -/* Forward declarations for all functions in the func_table */ -static struct Library *lib_init(struct ObjFWRTBase *base, BPTR seg_list, - struct ExecBase *exec_base); -static struct Library *lib_open(void); -static BPTR lib_close(void); -static BPTR lib_expunge(void); -static void lib_null(void); -void objc_set_exit(void OF_NO_RETURN_FUNC (*exit_fn_)(int status)); - -static ULONG func_table[] = { - FUNCARRAY_BEGIN, - FUNCARRAY_32BIT_NATIVE, - (ULONG)lib_open, - (ULONG)lib_close, - (ULONG)lib_expunge, - (ULONG)lib_null, - -1, - FUNCARRAY_32BIT_SYSTEMV, - /* Functions for the glue code */ - (ULONG)objc_set_exit, - /* Used by the compiler - these need glue code */ - (ULONG)__objc_exec_class, - (ULONG)objc_msg_lookup, - (ULONG)objc_msg_lookup_stret, - (ULONG)objc_msg_lookup_super, - (ULONG)objc_msg_lookup_super_stret, - (ULONG)objc_lookUpClass, - (ULONG)objc_getClass, - (ULONG)objc_getRequiredClass, - (ULONG)objc_exception_throw, - (ULONG)objc_sync_enter, - (ULONG)objc_sync_exit, - (ULONG)objc_getProperty, - (ULONG)objc_setProperty, - (ULONG)objc_getPropertyStruct, - (ULONG)objc_setPropertyStruct, - (ULONG)objc_enumerationMutation, - /* Functions declared in ObjFW-RT.h */ - (ULONG)sel_registerName, - (ULONG)sel_getName, - (ULONG)sel_isEqual, - (ULONG)objc_allocateClassPair, - (ULONG)objc_registerClassPair, - (ULONG)objc_getClassList, - (ULONG)objc_copyClassList, - (ULONG)class_isMetaClass, - (ULONG)class_getName, - (ULONG)class_getSuperclass, - (ULONG)class_getInstanceSize, - (ULONG)class_respondsToSelector, - (ULONG)class_conformsToProtocol, - (ULONG)class_getMethodImplementation, - (ULONG)class_getMethodImplementation_stret, - (ULONG)class_getMethodTypeEncoding, - (ULONG)class_addMethod, - (ULONG)class_replaceMethod, - (ULONG)object_getClass, - (ULONG)object_setClass, - (ULONG)object_getClassName, - (ULONG)protocol_getName, - (ULONG)protocol_isEqual, - (ULONG)protocol_conformsToProtocol, - (ULONG)objc_exit, - (ULONG)objc_setUncaughtExceptionHandler, - (ULONG)objc_setForwardHandler, - (ULONG)objc_setEnumerationMutationHandler, - (ULONG)objc_zero_weak_references, - -1, - FUNCARRAY_END -}; - -static struct Library *lib_init(struct ObjFWRTBase *base, BPTR seg_list, - struct ExecBase *exec_base); - -static struct { - LONG struct_size; - ULONG *func_table; - void *data_table; - struct Library *(*init_func)(struct ObjFWRTBase *base, BPTR seg_list, - struct ExecBase *exec_base); -} init_table = { - .struct_size = sizeof(struct ObjFWRTBase), - func_table, - NULL, - lib_init -}; - -static struct Resident resident = { - .rt_MatchWord = RTC_MATCHWORD, - .rt_MatchTag = &resident, - .rt_EndSkip = &resident + 1, - .rt_Flags = RTF_AUTOINIT | RTF_PPC, - .rt_Version = OBJFW_RT_LIB_MAJOR * 10 + OBJFW_RT_LIB_MINOR, - .rt_Type = NT_LIBRARY, - .rt_Pri = 0, - .rt_Name = (char *)"objfw-rt.library", - .rt_IdString = (char *)"ObjFW-RT " PACKAGE_VERSION - " \xA9 2008-2017 Jonathan Schleifer", - .rt_Init = &init_table -}; - -/* Magic required to make this a MorphOS binary */ -const ULONG __abox__ = 1; - -/* Global variables needed by libnix */ -int ThisRequiresConstructorHandling; -struct ExecBase *SysBase; -void *libnix_mempool; - -/* Functions passed in from the glue linklib */ -static void OF_NO_RETURN_FUNC (*exit_fn)(int status); - -void OF_NO_RETURN_FUNC -exit(int status) -{ - exit_fn(status); -} - -void -objc_set_exit(void OF_NO_RETURN_FUNC (*exit_fn_)(int status)) -{ - exit_fn = exit_fn_; -} - -/* Standard library functions */ -static struct Library *lib_init(struct ObjFWRTBase *base, BPTR seg_list, - struct ExecBase *exec_base) -{ - SysBase = exec_base; - - base->seg_list = seg_list; - - return &base->library; -} - -static struct Library * -lib_open(void) -{ - struct ObjFWRTBase *base = (struct ObjFWRTBase *)REG_A6; - - base->library.lib_OpenCnt++; - base->library.lib_Flags &= ~LIBF_DELEXP; - - return &base->library; -} - -static BPTR -expunge(struct ObjFWRTBase *base) -{ - /* Still in use - set delayed expunge flag and refuse to expunge */ - if (base->library.lib_OpenCnt > 0) { - base->library.lib_Flags |= LIBF_DELEXP; - return 0; - } - - Remove(&base->library.lib_Node); - FreeMem((char *)base - base->library.lib_NegSize, - base->library.lib_NegSize + base->library.lib_PosSize); - - return base->seg_list; -} - -static BPTR -lib_close(void) -{ - struct ObjFWRTBase *base = (struct ObjFWRTBase *)REG_A6; - - /* Not used anymore and delayed expunge flag set -> expunge */ - if (--base->library.lib_OpenCnt == 0 && - (base->library.lib_Flags & LIBF_DELEXP)) - return expunge(base); - - return 0; -} - -static BPTR -lib_expunge(void) -{ - return expunge((struct ObjFWRTBase *)REG_A6); -} - -static void -lib_null(void) -{ -} Index: tests/OFBlockTests.m ================================================================== --- tests/OFBlockTests.m +++ tests/OFBlockTests.m @@ -69,13 +69,19 @@ TEST(@"Class of stack block", (Class)&_NSConcreteStackBlock == objc_getClass("OFStackBlock") && [s isKindOfClass: [OFBlock class]]) +#if !defined(OF_WINDOWS) || !defined(__clang__) + /* + * Causes a linker error on Windows with Clang when compiling as a + * static library. This is a bug in Clang. + */ TEST(@"Class of global block", (Class)&_NSConcreteGlobalBlock == objc_getClass("OFGlobalBlock") && [g isKindOfClass: [OFBlock class]]) +#endif TEST(@"Class of a malloc block", (Class)&_NSConcreteMallocBlock == objc_getClass("OFMallocBlock")) TEST(@"Copying a stack block", Index: tests/OFKernelEventObserverTests.m ================================================================== --- tests/OFKernelEventObserverTests.m +++ tests/OFKernelEventObserverTests.m @@ -20,21 +20,21 @@ #import "OFString.h" #import "OFDate.h" #import "OFTCPSocket.h" #import "OFAutoreleasePool.h" -#if defined(HAVE_SYS_SELECT_H) || defined(OF_WINDOWS) -# import "OFKernelEventObserver_select.h" -#endif -#if defined(HAVE_POLL_H) || defined(OF_WII) -# import "OFKernelEventObserver_poll.h" +#ifdef HAVE_KQUEUE +# import "OFKernelEventObserver_kqueue.h" #endif #ifdef HAVE_EPOLL # import "OFKernelEventObserver_epoll.h" #endif -#ifdef HAVE_KQUEUE -# import "OFKernelEventObserver_kqueue.h" +#ifdef HAVE_POLL +# import "OFKernelEventObserver_poll.h" +#endif +#ifdef HAVE_SELECT +# import "OFKernelEventObserver_select.h" #endif #import "TestsAppDelegate.h" #define EXPECTED_EVENTS 3 @@ -201,10 +201,11 @@ @end @implementation TestsAppDelegate (OFKernelEventObserverTests) - (void)kernelEventObserverTestsWithClass: (Class)class { + OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init]; ObserverTest *test; module = [class className]; test = [[[ObserverTest alloc] initWithTestsAppDelegate: self] autorelease]; @@ -216,22 +217,22 @@ TEST(@"-[addObjectForReading:]", R([test->_observer addObjectForReading: test->_server])) [test run]; _fails += test->_fails; + + [pool drain]; } - (void)kernelEventObserverTests { - OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init]; - -#if defined(HAVE_SYS_SELECT_H) || defined(OF_WINDOWS) +#ifdef HAVE_SELECT [self kernelEventObserverTestsWithClass: [OFKernelEventObserver_select class]]; #endif -#if defined(HAVE_POLL_H) || defined(OF_WII) +#ifdef HAVE_POLL [self kernelEventObserverTestsWithClass: [OFKernelEventObserver_poll class]]; #endif #ifdef HAVE_EPOLL @@ -241,9 +242,7 @@ #ifdef HAVE_KQUEUE [self kernelEventObserverTestsWithClass: [OFKernelEventObserver_kqueue class]]; #endif - - [pool drain]; } @end Index: tests/OFObjectTests.m ================================================================== --- tests/OFObjectTests.m +++ tests/OFObjectTests.m @@ -253,11 +253,11 @@ [m unsignedLongLongValue] == 100 && [m floatValue] == 110 && [m doubleValue] == 120) EXPECT_EXCEPTION(@"Catch -[setValue:forKey:] with nil key for scalar", - OFInvalidArgumentException, [m setValue: nil + OFInvalidArgumentException, [m setValue: (id _Nonnull)nil forKey: @"intValue"]) [pool drain]; } @end