Index: src/OFLHAArchive.h ================================================================== --- src/OFLHAArchive.h +++ src/OFLHAArchive.h @@ -32,10 +32,14 @@ @interface OFLHAArchive: OFObject { OFStream *_stream; uint_least8_t _mode; OFStringEncoding _encoding; + OFLHAArchiveEntry *_Nullable _currentEntry; +#ifdef OF_LHA_ARCHIVE_M +@public +#endif OFStream *_Nullable _lastReturnedStream; } /** * @brief The encoding to use for the archive. Defaults to ISO 8859-1. Index: src/OFLHAArchive.m ================================================================== --- src/OFLHAArchive.m +++ src/OFLHAArchive.m @@ -11,10 +11,12 @@ * 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 OF_LHA_ARCHIVE_M + #include "config.h" #include #import "OFLHAArchive.h" @@ -43,36 +45,40 @@ }; OF_DIRECT_MEMBERS @interface OFLHAArchiveFileReadStream: OFStream { + OFLHAArchive *_archive; OFStream *_stream, *_decompressedStream; OFLHAArchiveEntry *_entry; unsigned long long _toRead; uint16_t _CRC16; bool _atEndOfStream, _skipped; } -- (instancetype)of_initWithStream: (OFStream *)stream - entry: (OFLHAArchiveEntry *)entry; +- (instancetype)of_initWithArchive: (OFLHAArchive *)archive + stream: (OFStream *)stream + entry: (OFLHAArchiveEntry *)entry; - (void)of_skip; @end OF_DIRECT_MEMBERS @interface OFLHAArchiveFileWriteStream: OFStream { + OFLHAArchive *_archive; OFMutableLHAArchiveEntry *_entry; OFStringEncoding _encoding; OFSeekableStream *_stream; OFStreamOffset _headerOffset; uint32_t _bytesWritten; uint16_t _CRC16; } -- (instancetype)of_initWithStream: (OFSeekableStream *)stream - entry: (OFLHAArchiveEntry *)entry - encoding: (OFStringEncoding)encoding; +- (instancetype)of_initWithArchive: (OFLHAArchive *)archive + stream: (OFSeekableStream *)stream + entry: (OFLHAArchiveEntry *)entry + encoding: (OFStringEncoding)encoding; @end @implementation OFLHAArchive @synthesize encoding = _encoding; @@ -154,29 +160,32 @@ - (void)dealloc { if (_stream != nil) [self close]; + [_currentEntry release]; + [super dealloc]; } - (OFLHAArchiveEntry *)nextEntry { - OFLHAArchiveEntry *entry; char header[21]; size_t headerLen; if (_mode != modeRead) @throw [OFInvalidArgumentException exception]; + + [_currentEntry release]; + _currentEntry = nil; [(OFLHAArchiveFileReadStream *)_lastReturnedStream of_skip]; @try { [_lastReturnedStream close]; } @catch (OFNotOpenException *e) { /* Might have already been closed by the user - that's fine. */ } - [_lastReturnedStream release]; _lastReturnedStream = nil; for (headerLen = 0; headerLen < 21;) { if (_stream.atEndOfStream) { if (headerLen == 0) @@ -190,32 +199,34 @@ headerLen += [_stream readIntoBuffer: header + headerLen length: 21 - headerLen]; } - entry = [[[OFLHAArchiveEntry alloc] + _currentEntry= [[OFLHAArchiveEntry alloc] of_initWithHeader: header stream: _stream - encoding: _encoding] autorelease]; + encoding: _encoding]; - _lastReturnedStream = [[OFLHAArchiveFileReadStream alloc] - of_initWithStream: _stream - entry: entry]; - - return entry; + return _currentEntry; } - (OFStream *)streamForReadingCurrentEntry { if (_mode != modeRead) @throw [OFInvalidArgumentException exception]; - if (_lastReturnedStream == nil) + if (_currentEntry == nil) @throw [OFInvalidArgumentException exception]; - return [[(OFLHAArchiveFileReadStream *)_lastReturnedStream - retain] autorelease]; + _lastReturnedStream = [[[OFLHAArchiveFileReadStream alloc] + of_initWithArchive: self + stream: _stream + entry: _currentEntry] autorelease]; + [_currentEntry release]; + _currentEntry = nil; + + return _lastReturnedStream; } - (OFStream *)streamForWritingEntry: (OFLHAArchiveEntry *)entry { OFString *compressionMethod; @@ -233,20 +244,19 @@ @try { [_lastReturnedStream close]; } @catch (OFNotOpenException *e) { /* Might have already been closed by the user - that's fine. */ } - [_lastReturnedStream release]; _lastReturnedStream = nil; - _lastReturnedStream = [[OFLHAArchiveFileWriteStream alloc] - of_initWithStream: (OFSeekableStream *)_stream - entry: entry - encoding: _encoding]; + _lastReturnedStream = [[[OFLHAArchiveFileWriteStream alloc] + of_initWithArchive: self + stream: (OFSeekableStream *)_stream + entry: entry + encoding: _encoding] autorelease]; - return [[(OFLHAArchiveFileWriteStream *)_lastReturnedStream - retain] autorelease]; + return _lastReturnedStream; } - (void)close { if (_stream == nil) @@ -255,27 +265,28 @@ @try { [_lastReturnedStream close]; } @catch (OFNotOpenException *e) { /* Might have already been closed by the user - that's fine. */ } - [_lastReturnedStream release]; _lastReturnedStream = nil; [_stream release]; _stream = nil; } @end @implementation OFLHAArchiveFileReadStream -- (instancetype)of_initWithStream: (OFStream *)stream - entry: (OFLHAArchiveEntry *)entry +- (instancetype)of_initWithArchive: (OFLHAArchive *)archive + stream: (OFStream *)stream + entry: (OFLHAArchiveEntry *)entry { self = [super init]; @try { OFString *compressionMethod; + _archive = [archive retain]; _stream = [stream retain]; compressionMethod = entry.compressionMethod; if ([compressionMethod isEqual: @"-lh4-"] || @@ -311,10 +322,15 @@ { if (_stream != nil || _decompressedStream != nil) [self close]; [_entry release]; + + if (_archive->_lastReturnedStream == self) + _archive->_lastReturnedStream = nil; + + [_archive release]; [super dealloc]; } - (bool)lowlevelIsAtEndOfStream @@ -440,17 +456,19 @@ [super close]; } @end @implementation OFLHAArchiveFileWriteStream -- (instancetype)of_initWithStream: (OFSeekableStream *)stream - entry: (OFLHAArchiveEntry *)entry - encoding: (OFStringEncoding)encoding +- (instancetype)of_initWithArchive: (OFLHAArchive *)archive + stream: (OFSeekableStream *)stream + entry: (OFLHAArchiveEntry *)entry + encoding: (OFStringEncoding)encoding { self = [super init]; @try { + _archive = [archive retain]; _entry = [entry mutableCopy]; _encoding = encoding; _headerOffset = [stream seekToOffset: 0 whence: OFSeekCurrent]; [_entry of_writeToStream: stream encoding: _encoding]; @@ -472,10 +490,15 @@ { if (_stream != nil) [self close]; [_entry release]; + + if (_archive->_lastReturnedStream == self) + _archive->_lastReturnedStream = nil; + + [_archive release]; [super dealloc]; } - (size_t)lowlevelWriteBuffer: (const void *)buffer length: (size_t)length