@@ -24,39 +24,38 @@ # import "OFInflateStream.h" #else # import "OFInflate64Stream.h" # define OFInflateStream OFInflate64Stream #endif - -#import "huffman_tree.h" +#import "OFHuffmanTree.h" #import "OFInitializationFailedException.h" #import "OFInvalidFormatException.h" #import "OFNotOpenException.h" #import "OFOutOfMemoryException.h" #ifndef OF_INFLATE64_STREAM_M -# define BUFFER_SIZE OF_INFLATE_STREAM_BUFFER_SIZE +# define bufferSize OFInflateStreamBufferSize #else -# define BUFFER_SIZE OF_INFLATE64_STREAM_BUFFER_SIZE +# define bufferSize OFInflate64StreamBufferSize #endif -enum state { - BLOCK_HEADER, - UNCOMPRESSED_BLOCK_HEADER, - UNCOMPRESSED_BLOCK, - HUFFMAN_TREE, - HUFFMAN_BLOCK +enum State { + stateBlockHeader, + stateUncompressedBlockHeader, + stateUncompressedBlock, + stateHuffmanTree, + stateHuffmanBlock }; -enum huffman_state { - WRITE_VALUE, - AWAIT_CODE, - AWAIT_LENGTH_EXTRA_BITS, - AWAIT_DISTANCE, - AWAIT_DISTANCE_EXTRA_BITS, - PROCESS_PAIR +enum HuffmanState { + huffmanStateWriteValue, + huffmanStateAwaitCode, + huffmanStateAwaitLengthExtraBits, + huffmanStateAwaitDistance, + huffmanStateAwaitDistanceExtraBits, + huffmanStateProcessPair }; #ifndef OF_INFLATE64_STREAM_M static const uint8_t numDistanceCodes = 30; static const uint8_t lengthCodes[29] = { @@ -98,11 +97,11 @@ }; #endif static const uint8_t codeLengthsOrder[19] = { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 }; -static struct of_huffman_tree *fixedLitLenTree, *fixedDistTree; +static OFHuffmanTree fixedLitLenTree, fixedDistTree; @implementation OFInflateStream static OF_INLINE bool tryReadBits(OFInflateStream *stream, uint16_t *bits, uint8_t count) { @@ -117,11 +116,11 @@ stream->_byte = stream->_buffer[stream->_bufferIndex++]; else { size_t length = [stream->_stream readIntoBuffer: stream->_buffer - length: BUFFER_SIZE]; + length: bufferSize]; if OF_UNLIKELY (length < 1) { stream->_savedBits = ret; stream->_savedBitsLength = i; return false; @@ -159,16 +158,16 @@ for (uint16_t i = 256; i <= 279; i++) lengths[i] = 7; for (uint16_t i = 280; i <= 287; i++) lengths[i] = 8; - fixedLitLenTree = of_huffman_tree_construct(lengths, 288); + fixedLitLenTree = OFHuffmanTreeNew(lengths, 288); for (uint16_t i = 0; i <= 31; i++) lengths[i] = 5; - fixedDistTree = of_huffman_tree_construct(lengths, 32); + fixedDistTree = OFHuffmanTreeNew(lengths, 32); } + (instancetype)streamWithStream: (OFStream *)stream { return [[[self alloc] initWithStream: stream] autorelease]; @@ -192,11 +191,11 @@ #ifdef OF_INFLATE64_STREAM_M _slidingWindowMask = 0xFFFF; #else _slidingWindowMask = 0x7FFF; #endif - _slidingWindow = of_alloc_zeroed(_slidingWindowMask + 1, 1); + _slidingWindow = OFAllocZeroedMemory(_slidingWindowMask + 1, 1); } @catch (id e) { [self release]; @throw e; } @@ -206,25 +205,24 @@ - (void)dealloc { if (_stream != nil) [self close]; - free(_slidingWindow); + OFFreeMemory(_slidingWindow); - if (_state == HUFFMAN_TREE) { - free(_context.huffmanTree.lengths); + if (_state == stateHuffmanTree) { + OFFreeMemory(_context.huffmanTree.lengths); if (_context.huffmanTree.codeLenTree != NULL) - of_huffman_tree_release( - _context.huffmanTree.codeLenTree); + OFHuffmanTreeFree(_context.huffmanTree.codeLenTree); } - if (_state == HUFFMAN_TREE || _state == HUFFMAN_BLOCK) { + if (_state == stateHuffmanTree || _state == stateHuffmanBlock) { if (_context.huffman.litLenTree != fixedLitLenTree) - of_huffman_tree_release(_context.huffman.litLenTree); + OFHuffmanTreeFree(_context.huffman.litLenTree); if (_context.huffman.distTree != fixedDistTree) - of_huffman_tree_release(_context.huffman.distTree); + OFHuffmanTreeFree(_context.huffman.distTree); } [super dealloc]; } @@ -242,12 +240,12 @@ if (_atEndOfStream) return 0; start: - switch ((enum state)_state) { - case BLOCK_HEADER: + switch ((enum State)_state) { + case stateBlockHeader: if OF_UNLIKELY (_inLastBlock) { [_stream unreadFromBuffer: _buffer + _bufferIndex length: _bufferLength - _bufferIndex]; _bufferIndex = _bufferLength = 0; @@ -261,24 +259,24 @@ _inLastBlock = (bits & 1); switch (bits >> 1) { case 0: /* No compression */ - _state = UNCOMPRESSED_BLOCK_HEADER; + _state = stateUncompressedBlockHeader; _bitIndex = 8; _context.uncompressedHeader.position = 0; memset(_context.uncompressedHeader.length, 0, 4); break; case 1: /* Fixed Huffman */ - _state = HUFFMAN_BLOCK; - _context.huffman.state = AWAIT_CODE; + _state = stateHuffmanBlock; + _context.huffman.state = huffmanStateAwaitCode; _context.huffman.litLenTree = fixedLitLenTree; _context.huffman.distTree = fixedDistTree; _context.huffman.treeIter = fixedLitLenTree; break; case 2: /* Dynamic Huffman */ - _state = HUFFMAN_TREE; + _state = stateHuffmanTree; _context.huffmanTree.lengths = NULL; _context.huffmanTree.receivedCount = 0; _context.huffmanTree.value = 0xFE; _context.huffmanTree.litLenCodesCount = 0xFF; _context.huffmanTree.distCodesCount = 0xFF; @@ -287,11 +285,11 @@ default: @throw [OFInvalidFormatException exception]; } goto start; - case UNCOMPRESSED_BLOCK_HEADER: + case stateUncompressedBlockHeader: #define CTX _context.uncompressedHeader /* FIXME: This can be done more efficiently than unreading */ [_stream unreadFromBuffer: _buffer + _bufferIndex length: _bufferLength - _bufferIndex]; _bufferIndex = _bufferLength = 0; @@ -305,11 +303,11 @@ if OF_UNLIKELY ((CTX.length[0] | (CTX.length[1] << 8)) != (uint16_t)~(CTX.length[2] | (CTX.length[3] << 8))) @throw [OFInvalidFormatException exception]; - _state = UNCOMPRESSED_BLOCK; + _state = stateUncompressedBlock; /* * Do not reorder! _context.uncompressed.position and * _context.uncompressedHeader.length overlap! */ @@ -317,11 +315,11 @@ CTX.length[0] | (CTX.length[1] << 8); _context.uncompressed.position = 0; goto start; #undef CTX - case UNCOMPRESSED_BLOCK: + case stateUncompressedBlock: #define CTX _context.uncompressed if OF_UNLIKELY (length == 0) return bytesWritten; tmp = (length < (size_t)CTX.length - CTX.position @@ -343,15 +341,15 @@ length -= tmp; bytesWritten += tmp; CTX.position += tmp; if OF_UNLIKELY (CTX.position == CTX.length) - _state = BLOCK_HEADER; + _state = stateBlockHeader; goto start; #undef CTX - case HUFFMAN_TREE: + case stateHuffmanTree: #define CTX _context.huffmanTree if OF_LIKELY (CTX.value == 0xFE) { if OF_LIKELY (CTX.litLenCodesCount == 0xFF) { if OF_UNLIKELY (!tryReadBits(self, &bits, 5)) return bytesWritten; @@ -376,11 +374,11 @@ CTX.codeLenCodesCount = bits; } if OF_LIKELY (CTX.lengths == NULL) - CTX.lengths = of_alloc_zeroed(19, 1); + CTX.lengths = OFAllocZeroedMemory(19, 1); for (uint16_t i = CTX.receivedCount; i < CTX.codeLenCodesCount + 4; i++) { if OF_UNLIKELY (!tryReadBits(self, &bits, 3)) { CTX.receivedCount = i; @@ -388,30 +386,29 @@ } CTX.lengths[codeLengthsOrder[i]] = bits; } - CTX.codeLenTree = of_huffman_tree_construct( - CTX.lengths, 19); + CTX.codeLenTree = OFHuffmanTreeNew(CTX.lengths, 19); CTX.treeIter = CTX.codeLenTree; - free(CTX.lengths); + OFFreeMemory(CTX.lengths); CTX.lengths = NULL; CTX.receivedCount = 0; CTX.value = 0xFF; } if OF_LIKELY (CTX.lengths == NULL) - CTX.lengths = of_alloc( + CTX.lengths = OFAllocMemory( CTX.litLenCodesCount + CTX.distCodesCount + 258, 1); for (uint16_t i = CTX.receivedCount; i < CTX.litLenCodesCount + CTX.distCodesCount + 258;) { uint8_t j, count; if OF_LIKELY (CTX.value == 0xFF) { - if OF_UNLIKELY (!of_huffman_tree_walk(self, + if OF_UNLIKELY (!OFHuffmanTreeWalk(self, tryReadBits, &CTX.treeIter, &value)) { CTX.receivedCount = i; return bytesWritten; } @@ -474,38 +471,38 @@ CTX.lengths[i++] = value; CTX.value = 0xFF; } - of_huffman_tree_release(CTX.codeLenTree); + OFHuffmanTreeFree(CTX.codeLenTree); CTX.codeLenTree = NULL; - CTX.litLenTree = of_huffman_tree_construct(CTX.lengths, + CTX.litLenTree = OFHuffmanTreeNew(CTX.lengths, CTX.litLenCodesCount + 257); - CTX.distTree = of_huffman_tree_construct( + CTX.distTree = OFHuffmanTreeNew( CTX.lengths + CTX.litLenCodesCount + 257, CTX.distCodesCount + 1); - free(CTX.lengths); + OFFreeMemory(CTX.lengths); /* * litLenTree and distTree are at the same location in * _context.huffman and _context.huffmanTree, thus no need to * set them. */ - _state = HUFFMAN_BLOCK; - _context.huffman.state = AWAIT_CODE; + _state = stateHuffmanBlock; + _context.huffman.state = huffmanStateAwaitCode; _context.huffman.treeIter = CTX.litLenTree; goto start; #undef CTX - case HUFFMAN_BLOCK: + case stateHuffmanBlock: #define CTX _context.huffman for (;;) { uint8_t extraBits, lengthCodeIndex; - if OF_UNLIKELY (CTX.state == WRITE_VALUE) { + if OF_UNLIKELY (CTX.state == huffmanStateWriteValue) { if OF_UNLIKELY (length == 0) return bytesWritten; buffer[bytesWritten++] = CTX.value; length--; @@ -513,28 +510,29 @@ _slidingWindow[_slidingWindowIndex] = CTX.value; _slidingWindowIndex = (_slidingWindowIndex + 1) & _slidingWindowMask; - CTX.state = AWAIT_CODE; + CTX.state = huffmanStateAwaitCode; CTX.treeIter = CTX.litLenTree; } - if OF_UNLIKELY (CTX.state == AWAIT_LENGTH_EXTRA_BITS) { + if OF_UNLIKELY (CTX.state == + huffmanStateAwaitLengthExtraBits) { if OF_UNLIKELY (!tryReadBits(self, &bits, CTX.extraBits)) return bytesWritten; CTX.length += bits; - CTX.state = AWAIT_DISTANCE; + CTX.state = huffmanStateAwaitDistance; CTX.treeIter = CTX.distTree; } /* Distance of length distance pair */ - if (CTX.state == AWAIT_DISTANCE) { - if OF_UNLIKELY (!of_huffman_tree_walk(self, + if (CTX.state == huffmanStateAwaitDistance) { + if OF_UNLIKELY (!OFHuffmanTreeWalk(self, tryReadBits, &CTX.treeIter, &value)) return bytesWritten; if OF_UNLIKELY (value >= numDistanceCodes) @throw [OFInvalidFormatException @@ -544,32 +542,34 @@ extraBits = distanceExtraBits[value]; if (extraBits > 0) { if OF_UNLIKELY (!tryReadBits(self, &bits, extraBits)) { - CTX.state = - AWAIT_DISTANCE_EXTRA_BITS; +#define HSADEB huffmanStateAwaitDistanceExtraBits + CTX.state = HSADEB; +#undef HSADEB CTX.extraBits = extraBits; return bytesWritten; } CTX.distance += bits; } - CTX.state = PROCESS_PAIR; - } else if (CTX.state == AWAIT_DISTANCE_EXTRA_BITS) { + CTX.state = huffmanStateProcessPair; + } else if (CTX.state == + huffmanStateAwaitDistanceExtraBits) { if OF_UNLIKELY (!tryReadBits(self, &bits, CTX.extraBits)) return bytesWritten; CTX.distance += bits; - CTX.state = PROCESS_PAIR; + CTX.state = huffmanStateProcessPair; } /* Length distance pair */ - if (CTX.state == PROCESS_PAIR) { + if (CTX.state == huffmanStateProcessPair) { for (uint_fast16_t j = 0; j < CTX.length; j++) { uint16_t idx; if OF_UNLIKELY (length == 0) { CTX.length -= j; @@ -588,33 +588,33 @@ _slidingWindowIndex = (_slidingWindowIndex + 1) & _slidingWindowMask; } - CTX.state = AWAIT_CODE; + CTX.state = huffmanStateAwaitCode; CTX.treeIter = CTX.litLenTree; } - if OF_UNLIKELY (!of_huffman_tree_walk(self, tryReadBits, + if OF_UNLIKELY (!OFHuffmanTreeWalk(self, tryReadBits, &CTX.treeIter, &value)) return bytesWritten; /* End of block */ if OF_UNLIKELY (value == 256) { if (CTX.litLenTree != fixedLitLenTree) - of_huffman_tree_release(CTX.litLenTree); + OFHuffmanTreeFree(CTX.litLenTree); if (CTX.distTree != fixedDistTree) - of_huffman_tree_release(CTX.distTree); + OFHuffmanTreeFree(CTX.distTree); - _state = BLOCK_HEADER; + _state = stateBlockHeader; goto start; } /* Literal byte */ if OF_LIKELY (value < 256) { if OF_UNLIKELY (length == 0) { - CTX.state = WRITE_VALUE; + CTX.state = huffmanStateWriteValue; CTX.value = value; return bytesWritten; } buffer[bytesWritten++] = value; @@ -639,19 +639,20 @@ if (extraBits > 0) { if OF_UNLIKELY (!tryReadBits(self, &bits, extraBits)) { CTX.extraBits = extraBits; - CTX.state = AWAIT_LENGTH_EXTRA_BITS; + CTX.state = + huffmanStateAwaitLengthExtraBits; return bytesWritten; } CTX.length += bits; } CTX.treeIter = CTX.distTree; - CTX.state = AWAIT_DISTANCE; + CTX.state = huffmanStateAwaitDistance; } break; #undef CTX }