Index: ObjFW.xcodeproj/project.pbxproj ================================================================== --- ObjFW.xcodeproj/project.pbxproj +++ ObjFW.xcodeproj/project.pbxproj @@ -268,10 +268,12 @@ 4B5CF8FA14940BD2007AA324 /* OFString+JSONValue.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B5CF8F714940BD2007AA324 /* OFString+JSONValue.m */; }; 4B64D6EF1425381E007BDFB1 /* OFStreamObserver_poll.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B64D6EB1425381E007BDFB1 /* OFStreamObserver_poll.h */; }; 4B64D6F01425381E007BDFB1 /* OFStreamObserver_poll.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B64D6EC1425381E007BDFB1 /* OFStreamObserver_poll.m */; }; 4B64D6F11425381E007BDFB1 /* OFStreamObserver_select.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B64D6ED1425381E007BDFB1 /* OFStreamObserver_select.h */; }; 4B64D6F21425381E007BDFB1 /* OFStreamObserver_select.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B64D6EE1425381E007BDFB1 /* OFStreamObserver_select.m */; }; + 4B66B636182ADC45000A69E3 /* OFDeflate64Stream.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B66B634182ADC45000A69E3 /* OFDeflate64Stream.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 4B66B637182ADC45000A69E3 /* OFDeflate64Stream.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B66B635182ADC45000A69E3 /* OFDeflate64Stream.m */; }; 4B6743F1163C384A00EB1E59 /* OFLockFailedException.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B6743EB163C384A00EB1E59 /* OFLockFailedException.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4B6743F2163C384A00EB1E59 /* OFLockFailedException.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B6743EC163C384A00EB1E59 /* OFLockFailedException.m */; }; 4B6743F3163C384A00EB1E59 /* OFStillLockedException.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B6743ED163C384A00EB1E59 /* OFStillLockedException.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4B6743F4163C384A00EB1E59 /* OFStillLockedException.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B6743EE163C384A00EB1E59 /* OFStillLockedException.m */; }; 4B6743F5163C384A00EB1E59 /* OFUnlockFailedException.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B6743EF163C384A00EB1E59 /* OFUnlockFailedException.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -636,10 +638,12 @@ 4B5CF8F714940BD2007AA324 /* OFString+JSONValue.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "OFString+JSONValue.m"; path = "src/OFString+JSONValue.m"; sourceTree = ""; }; 4B64D6EB1425381E007BDFB1 /* OFStreamObserver_poll.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFStreamObserver_poll.h; path = src/OFStreamObserver_poll.h; sourceTree = ""; }; 4B64D6EC1425381E007BDFB1 /* OFStreamObserver_poll.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFStreamObserver_poll.m; path = src/OFStreamObserver_poll.m; sourceTree = ""; }; 4B64D6ED1425381E007BDFB1 /* OFStreamObserver_select.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFStreamObserver_select.h; path = src/OFStreamObserver_select.h; sourceTree = ""; }; 4B64D6EE1425381E007BDFB1 /* OFStreamObserver_select.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFStreamObserver_select.m; path = src/OFStreamObserver_select.m; sourceTree = ""; }; + 4B66B634182ADC45000A69E3 /* OFDeflate64Stream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFDeflate64Stream.h; path = src/OFDeflate64Stream.h; sourceTree = ""; }; + 4B66B635182ADC45000A69E3 /* OFDeflate64Stream.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFDeflate64Stream.m; path = src/OFDeflate64Stream.m; sourceTree = ""; }; 4B6743EB163C384A00EB1E59 /* OFLockFailedException.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFLockFailedException.h; path = src/exceptions/OFLockFailedException.h; sourceTree = ""; }; 4B6743EC163C384A00EB1E59 /* OFLockFailedException.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFLockFailedException.m; path = src/exceptions/OFLockFailedException.m; sourceTree = ""; }; 4B6743ED163C384A00EB1E59 /* OFStillLockedException.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFStillLockedException.h; path = src/exceptions/OFStillLockedException.h; sourceTree = ""; }; 4B6743EE163C384A00EB1E59 /* OFStillLockedException.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFStillLockedException.m; path = src/exceptions/OFStillLockedException.m; sourceTree = ""; }; 4B6743EF163C384A00EB1E59 /* OFUnlockFailedException.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFUnlockFailedException.h; path = src/exceptions/OFUnlockFailedException.h; sourceTree = ""; }; @@ -1160,10 +1164,12 @@ 4B879A8A177231F000EBCEA4 /* OFDataArray+MessagePackValue.m */, 4BE5F0D912DF4225005C7A0C /* OFDate.h */, 4BE5F0DA12DF4225005C7A0C /* OFDate.m */, 4B86E7C917F8B98200ACA680 /* OFDeflateStream.h */, 4B86E7CA17F8B98200ACA680 /* OFDeflateStream.m */, + 4B66B634182ADC45000A69E3 /* OFDeflate64Stream.h */, + 4B66B635182ADC45000A69E3 /* OFDeflate64Stream.m */, 4B6799621099E7C50041064A /* OFDictionary.h */, 4B6799631099E7C50041064A /* OFDictionary.m */, 4B2B3E75140D430500EC2F7C /* OFDictionary_hashtable.h */, 4B2B3E76140D430500EC2F7C /* OFDictionary_hashtable.m */, 4B0108C910EB8C9300631877 /* OFEnumerator.h */, @@ -1459,10 +1465,11 @@ 4B3D23C31337FC8300DD29B8 /* OFDataArray+Hashing.h in Headers */, 4B879A8C177231F000EBCEA4 /* OFDataArray+MessagePackValue.h in Headers */, 4B3D23C41337FC8300DD29B8 /* OFDate.h in Headers */, 4B3D23C51337FCB000DD29B8 /* OFDictionary.h in Headers */, 4B86E7CB17F8B98200ACA680 /* OFDeflateStream.h in Headers */, + 4B66B636182ADC45000A69E3 /* OFDeflate64Stream.h in Headers */, 4B3D23C61337FCB000DD29B8 /* OFEnumerator.h in Headers */, 4B17FF74133A2AAB003E6DCD /* OFException.h in Headers */, 4B3D23C81337FCB000DD29B8 /* OFFile.h in Headers */, 4B3D23C91337FCB000DD29B8 /* OFHash.h in Headers */, 4BB4B54416775FF4002A2DCE /* OFHTTPClient.h in Headers */, @@ -1822,10 +1829,11 @@ 4B3D23901337FC0D00DD29B8 /* OFDataArray.m in Sources */, 4B3D23911337FC0D00DD29B8 /* OFDataArray+Hashing.m in Sources */, 4B879A8D177231F000EBCEA4 /* OFDataArray+MessagePackValue.m in Sources */, 4B3D23921337FC0D00DD29B8 /* OFDate.m in Sources */, 4B86E7CC17F8B98200ACA680 /* OFDeflateStream.m in Sources */, + 4B66B637182ADC45000A69E3 /* OFDeflate64Stream.m in Sources */, 4B3D23931337FC0D00DD29B8 /* OFDictionary.m in Sources */, 4B2B3E80140D430500EC2F7C /* OFDictionary_hashtable.m in Sources */, 4B3D23941337FC0D00DD29B8 /* OFEnumerator.m in Sources */, 4B3D23961337FC0D00DD29B8 /* OFFile.m in Sources */, 4BB4B54516775FF4002A2DCE /* OFHTTPClient.m in Sources */, Index: src/Makefile ================================================================== --- src/Makefile +++ src/Makefile @@ -17,10 +17,11 @@ OFDataArray.m \ OFDataArray+Hashing.m \ OFDataArray+MessagePackValue.m \ OFDate.m \ OFDeflateStream.m \ + OFDeflate64Stream.m \ OFDictionary.m \ OFEnumerator.m \ OFFile.m \ OFIntrospection.m \ OFList.m \ ADDED src/OFDeflate64Stream.h Index: src/OFDeflate64Stream.h ================================================================== --- src/OFDeflate64Stream.h +++ src/OFDeflate64Stream.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013 + * Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#import "OFDeflateStream.h" + +/*! + * @brief A class for a stream that handles Deflate64 compression or + * decompression transparently for an underlying stream. + */ +@interface OFDeflate64Stream: OFDeflateStream +@end ADDED src/OFDeflate64Stream.m Index: src/OFDeflate64Stream.m ================================================================== --- src/OFDeflate64Stream.m +++ src/OFDeflate64Stream.m @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013 + * Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It 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 "OFDeflate64Stream.h" + +static const uint_fast8_t numDistanceCodes = 32; +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, 0 +}; +static const uint8_t lengthExtraBits[29] = { + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, + 5, 5, 5, 5, 16 +}; +static const uint16_t distanceCodes[32] = { + 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, + 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577, + 32769, 49153 +}; +static const uint8_t distanceExtraBits[32] = { + 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, + 10, 11, 11, 12, 12, 13, 13, 14, 14 +}; + +@implementation OFDeflate64Stream +- initWithStream: (OFStream*)stream +{ + self = [super initWithStream: stream]; + + _slidingWindowMask = 0xFFFF; + _codes.numDistanceCodes = numDistanceCodes; + _codes.lengthCodes = lengthCodes; + _codes.lengthExtraBits = lengthExtraBits; + _codes.distanceCodes = distanceCodes; + _codes.distanceExtraBits = distanceExtraBits; + + return self; +} +@end Index: src/OFDeflateStream.h ================================================================== --- src/OFDeflateStream.h +++ src/OFDeflateStream.h @@ -17,11 +17,11 @@ #import "OFStream.h" #define OF_DEFLATE_STREAM_BUFFER_SIZE 4096 /*! - * @brief A class for a stream that handles deflate compression or decompression + * @brief A class for a stream that handles Deflate compression or decompression * transparently for an underlying stream. */ @interface OFDeflateStream: OFStream { #ifdef OF_DEFLATE_STREAM_M @@ -32,12 +32,19 @@ uint_fast16_t _bufferIndex, _bufferLength; uint8_t _byte; uint_fast8_t _bitIndex, _savedBitsLength; uint_fast16_t _savedBits; @protected - char *_slidingWindow; - uint_fast16_t _slidingWindowIndex; + uint8_t *_slidingWindow; + uint_fast16_t _slidingWindowIndex, _slidingWindowMask; + struct { + uint_fast8_t numDistanceCodes; + const uint8_t *lengthCodes; + const uint8_t *lengthExtraBits; + const uint16_t *distanceCodes; + const uint8_t *distanceExtraBits; + } _codes; enum { OF_DEFLATE_STREAM_BLOCK_HEADER, OF_DEFLATE_STREAM_UNCOMPRESSED_BLOCK_HEADER, OF_DEFLATE_STREAM_UNCOMPRESSED_BLOCK, OF_DEFLATE_STREAM_HUFFMAN_TREE, Index: src/OFDeflateStream.m ================================================================== --- src/OFDeflateStream.m +++ src/OFDeflateStream.m @@ -55,10 +55,11 @@ struct huffman_tree { struct huffman_tree *leafs[2]; uint16_t value; }; +static const uint_fast8_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 }; @@ -274,10 +275,16 @@ { self = [super init]; _stream = [stream retain]; _bitIndex = 8; /* 0-7 address the bit, 8 means fetch next byte */ + _slidingWindowMask = 0x7FFF; + _codes.numDistanceCodes = numDistanceCodes; + _codes.lengthCodes = lengthCodes; + _codes.lengthExtraBits = lengthExtraBits; + _codes.distanceCodes = distanceCodes; + _codes.distanceExtraBits = distanceExtraBits; return self; } - (void)dealloc @@ -292,11 +299,11 @@ { uint8_t *buffer = buffer_; uint_fast16_t bits; uint16_t value; size_t i, tmp, bytesWritten = 0; - char *slidingWindow; + uint8_t *slidingWindow; uint_fast16_t slidingWindowIndex; if (_atEndOfStream) @throw [OFReadFailedException exceptionWithStream: self requestedLength: length]; @@ -386,21 +393,23 @@ tmp = [_stream readIntoBuffer: buffer + bytesWritten length: tmp]; if OF_UNLIKELY (_slidingWindow == NULL) { - _slidingWindow = [self allocMemoryWithSize: 0x8000]; + _slidingWindow = + [self allocMemoryWithSize: _slidingWindowMask + 1]; /* Avoid leaking data */ - memset(_slidingWindow, 0, 0x8000); + memset(_slidingWindow, 0, _slidingWindowMask + 1); } slidingWindow = _slidingWindow; slidingWindowIndex = _slidingWindowIndex; for (i = 0; i < tmp; i++) { slidingWindow[slidingWindowIndex] = buffer[bytesWritten + i]; - slidingWindowIndex = (slidingWindowIndex + 1) & 0x7FFF; + slidingWindowIndex = (slidingWindowIndex + 1) & + _slidingWindowMask; } _slidingWindowIndex = slidingWindowIndex; length -= tmp; bytesWritten += tmp; @@ -572,18 +581,21 @@ buffer[bytesWritten++] = CTX.value; length--; if (_slidingWindow == NULL) { _slidingWindow = [self - allocMemoryWithSize: 0x8000]; + allocMemoryWithSize: + _slidingWindowMask + 1]; /* Avoid leaking data */ - memset(_slidingWindow, 0, 0x8000); + memset(_slidingWindow, 0, + _slidingWindowMask + 1); } _slidingWindow[_slidingWindowIndex] = CTX.value; _slidingWindowIndex = - (_slidingWindowIndex + 1) & 0x7FFF; + (_slidingWindowIndex + 1) & + _slidingWindowMask; CTX.state = AWAIT_CODE; CTX.treeIter = CTX.litLenTree; } @@ -602,16 +614,17 @@ if (CTX.state == AWAIT_DISTANCE) { if OF_UNLIKELY (!walkTree(self, &CTX.treeIter, &value)) return bytesWritten; - if OF_UNLIKELY (value > 29) + if OF_UNLIKELY (value >= + _codes.numDistanceCodes) @throw [OFInvalidFormatException exception]; - CTX.distance = distanceCodes[value]; - extraBits = distanceExtraBits[value]; + CTX.distance = _codes.distanceCodes[value]; + extraBits = _codes.distanceExtraBits[value]; if (extraBits > 0) { if OF_UNLIKELY (!tryReadBits(self, &bits, extraBits)) { CTX.state = @@ -649,20 +662,21 @@ CTX.length -= j; return bytesWritten; } index = (_slidingWindowIndex - - CTX.distance) & 0x7FFF; + CTX.distance) & _slidingWindowMask; value = _slidingWindow[index]; buffer[bytesWritten++] = value; length--; _slidingWindow[_slidingWindowIndex] = value; _slidingWindowIndex = - (_slidingWindowIndex + 1) & 0x7FFF; + (_slidingWindowIndex + 1) & + _slidingWindowMask; } CTX.state = AWAIT_CODE; CTX.treeIter = CTX.litLenTree; } @@ -692,18 +706,21 @@ buffer[bytesWritten++] = value; length--; if (_slidingWindow == NULL) { _slidingWindow = [self - allocMemoryWithSize: 0x8000]; + allocMemoryWithSize: + _slidingWindowMask + 1]; /* Avoid leaking data */ - memset(_slidingWindow, 0, 0x8000); + memset(_slidingWindow, 0, + _slidingWindowMask + 1); } _slidingWindow[_slidingWindowIndex] = value; _slidingWindowIndex = - (_slidingWindowIndex + 1) & 0x7FFF; + (_slidingWindowIndex + 1) & + _slidingWindowMask; CTX.treeIter = CTX.litLenTree; continue; } @@ -710,12 +727,12 @@ if OF_UNLIKELY (value > 285) @throw [OFInvalidFormatException exception]; /* Length of length distance pair */ lengthCodeIndex = value - 257; - CTX.length = lengthCodes[lengthCodeIndex] + 3; - extraBits = lengthExtraBits[lengthCodeIndex]; + CTX.length = _codes.lengthCodes[lengthCodeIndex] + 3; + extraBits = _codes.lengthExtraBits[lengthCodeIndex]; if (extraBits > 0) { if OF_UNLIKELY (!tryReadBits(self, &bits, extraBits)) { CTX.extraBits = extraBits; Index: src/OFZIPArchive.m ================================================================== --- src/OFZIPArchive.m +++ src/OFZIPArchive.m @@ -22,10 +22,11 @@ #import "OFDataArray.h" #import "OFArray.h" #import "OFDictionary.h" #import "OFFile.h" #import "OFDeflateStream.h" +#import "OFDeflate64Stream.h" #import "OFChecksumFailedException.h" #import "OFInvalidArgumentException.h" #import "OFInvalidFormatException.h" #import "OFNotImplementedException.h" @@ -500,10 +501,14 @@ break; case 8: /* Deflate */ _stream = [[OFDeflateStream alloc] initWithStream: _file]; break; + case 9: /* Deflate64 */ + _stream = [[OFDeflate64Stream alloc] + initWithStream: _file]; + break; default: @throw [OFNotImplementedException exceptionWithSelector: _cmd object: self]; }