Index: src/OFInflate64Stream.h ================================================================== --- src/OFInflate64Stream.h +++ src/OFInflate64Stream.h @@ -13,19 +13,87 @@ * Public License, either version 2 or 3, which can be found in the file * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this * file. */ -#import "OFInflateStream.h" +#import "OFStream.h" +#import "OFKernelEventObserver.h" OF_ASSUME_NONNULL_BEGIN + +#define OF_INFLATE64_STREAM_BUFFER_SIZE 4096 /*! * @class OFInflate64Stream OFInflate64Stream.h ObjFW/OFInflate64Stream.h * - * @brief A class that handles Deflate64 decompression transparently for an + * @note This class only conforms to OFReadyForReadingObserving if the + * underlying stream does so, too. + * + * @brief A class that handles Deflate decompression transparently for an + * underlying stream. + */ +@interface OFInflate64Stream: OFStream +{ +#ifdef OF_INFLATE64_STREAM_M +@public +#endif + OF_KINDOF(OFStream *) _stream; + unsigned char _buffer[OF_INFLATE64_STREAM_BUFFER_SIZE]; + uint16_t _bufferIndex, _bufferLength; + uint8_t _byte; + uint8_t _bitIndex, _savedBitsLength; + uint16_t _savedBits; + unsigned char *_Nullable _slidingWindow; + uint16_t _slidingWindowIndex, _slidingWindowMask; + int _state; + union { + struct { + uint8_t position; + uint8_t length[4]; + } uncompressedHeader; + struct { + uint16_t position, length; + } uncompressed; + struct { + struct of_huffman_tree *_Nullable litLenTree; + struct of_huffman_tree *_Nullable distTree; + struct of_huffman_tree *_Nullable codeLenTree; + struct of_huffman_tree *_Nullable treeIter; + uint8_t *_Nullable lengths; + uint16_t receivedCount; + uint8_t value, litLenCodesCount, distCodesCount; + uint8_t codeLenCodesCount; + } huffmanTree; + struct { + struct of_huffman_tree *_Nullable litLenTree; + struct of_huffman_tree *_Nullable distTree; + struct of_huffman_tree *_Nullable treeIter; + int state; + uint16_t value, length, distance, extraBits; + } huffman; + } _context; + bool _inLastBlock, _atEndOfStream; +} + +/*! + * @brief Creates a new OFInflate64Stream with the specified underlying stream. + * + * @param stream The underlying stream to which compressed data is written or + * from which compressed data is read + * @return A new, autoreleased OFInflate64Stream + */ ++ (instancetype)streamWithStream: (OFStream *)stream; + +- (instancetype)init OF_UNAVAILABLE; + +/*! + * @brief Initializes an already allocated OFInflate64Stream with the specified * underlying stream. + * + * @param stream The underlying stream to which compressed data is written or + * from which compressed data is read + * @return A initialized OFInflate64Stream */ -@interface OFInflate64Stream: OFInflateStream +- (instancetype)initWithStream: (OFStream *)stream OF_DESIGNATED_INITIALIZER; @end OF_ASSUME_NONNULL_END Index: src/OFInflate64Stream.m ================================================================== --- src/OFInflate64Stream.m +++ src/OFInflate64Stream.m @@ -13,7 +13,7 @@ * Public License, either version 2 or 3, which can be found in the file * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this * file. */ -#define INFLATE64 +#define OF_INFLATE64_STREAM_M #include "OFInflateStream.m" Index: src/OFInflateStream.m ================================================================== --- src/OFInflateStream.m +++ src/OFInflateStream.m @@ -22,11 +22,11 @@ #include #include #include -#ifndef INFLATE64 +#ifndef OF_INFLATE64_STREAM_M # import "OFInflateStream.h" #else # import "OFInflate64Stream.h" # define OFInflateStream OFInflate64Stream #endif @@ -36,11 +36,15 @@ #import "OFInitializationFailedException.h" #import "OFInvalidFormatException.h" #import "OFNotOpenException.h" #import "OFOutOfMemoryException.h" -#define BUFFER_SIZE OF_INFLATE_STREAM_BUFFER_SIZE +#ifndef OF_INFLATE64_STREAM_M +# define BUFFER_SIZE OF_INFLATE_STREAM_BUFFER_SIZE +#else +# define BUFFER_SIZE OF_INFLATE64_STREAM_BUFFER_SIZE +#endif enum state { BLOCK_HEADER, UNCOMPRESSED_BLOCK_HEADER, UNCOMPRESSED_BLOCK, @@ -55,11 +59,11 @@ AWAIT_DISTANCE, AWAIT_DISTANCE_EXTRA_BITS, PROCESS_PAIR }; -#ifndef INFLATE64 +#ifndef OF_INFLATE64_STREAM_M static const uint8_t numDistanceCodes = 30; static const uint8_t lengthCodes[29] = { /* indices are -257, values -3 */ 0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 255 @@ -166,11 +170,10 @@ lengths[i] = 5; fixedDistTree = of_huffman_tree_construct(lengths, 32); } -#ifndef INFLATE64 + (instancetype)streamWithStream: (OFStream *)stream { return [[[self alloc] initWithStream: stream] autorelease]; } @@ -187,11 +190,11 @@ _stream = [stream retain]; /* 0-7 address the bit, 8 means fetch next byte */ _bitIndex = 8; -#ifdef INFLATE64 +#ifdef OF_INFLATE64_STREAM_M _slidingWindowMask = 0xFFFF; #else _slidingWindowMask = 0x7FFF; #endif _slidingWindow = [self allocZeroedMemoryWithSize: @@ -220,11 +223,10 @@ of_huffman_tree_release(_context.huffman.distTree); } [super dealloc]; } -#endif - (size_t)lowlevelReadIntoBuffer: (void *)buffer_ length: (size_t)length { unsigned char *buffer = buffer_; @@ -654,11 +656,10 @@ } OF_UNREACHABLE } -#ifndef INFLATE64 - (bool)lowlevelIsAtEndOfStream { if (_stream == nil) @throw [OFNotOpenException exceptionWithObject: self]; @@ -672,11 +673,10 @@ - (bool)hasDataInReadBuffer { return ([super hasDataInReadBuffer] || [_stream hasDataInReadBuffer]); } -#endif - (void)close { /* Give back our buffer to the stream, in case it's shared */ [_stream unreadFromBuffer: _buffer + _bufferIndex