diff options
Diffstat (limited to 'common')
-rw-r--r-- | common/unarj.cpp | 114 | ||||
-rw-r--r-- | common/unarj.h | 24 |
2 files changed, 96 insertions, 42 deletions
diff --git a/common/unarj.cpp b/common/unarj.cpp index 4e0c32544d..73579250cd 100644 --- a/common/unarj.cpp +++ b/common/unarj.cpp @@ -752,67 +752,84 @@ void ArjDecoder::decode_f(int32 origsize) { _outstream->write(_ntext, r); } +#pragma mark ArjArchive implementation -#pragma mark ArjFile implementation - -ArjFile::ArjFile() { - _fallBack = false; -} - -ArjFile::~ArjFile() { - for (uint i = 0; i < _headers.size(); i++) - delete _headers[i]; -} - -void ArjFile::registerArchive(const String &filename) { - int32 first_hdr_pos; - ArjHeader *header; - File archiveFile; +ArjArchive::ArjArchive(const String &filename) : _arjFilename(filename) { + Common::File arjFile; - if (!archiveFile.open(filename)) + if (!arjFile.open(_arjFilename)) { + warning("ArjArchive::ArjArchive(): Could not find the archive file"); return; + } + + int32 firstHeaderOffset = findHeader(arjFile); - first_hdr_pos = findHeader(archiveFile); - - if (first_hdr_pos < 0) { - warning("ArjFile::registerArchive(): Could not find a valid header"); + if (firstHeaderOffset < 0) { + warning("ArjArchive::ArjArchive(): Could not find a valid header"); return; } - archiveFile.seek(first_hdr_pos, SEEK_SET); - if (readHeader(archiveFile) == NULL) + arjFile.seek(firstHeaderOffset, SEEK_SET); + if (readHeader(arjFile) == NULL) return; - while ((header = readHeader(archiveFile)) != NULL) { + ArjHeader *header; + while ((header = readHeader(arjFile)) != NULL) { _headers.push_back(header); - archiveFile.seek(header->compSize, SEEK_CUR); + arjFile.seek(header->compSize, SEEK_CUR); _fileMap[header->filename] = _headers.size() - 1; - _archMap[header->filename] = filename; } - debug(0, "ArjFile::registerArchive(%s): Located %d files", filename.c_str(), _headers.size()); + debug(0, "ArjArchive::ArjArchive(%s): Located %d files", filename.c_str(), _headers.size()); } -SeekableReadStream *ArjFile::open(const Common::String &filename) { +ArjArchive::~ArjArchive() { + for (uint i = 0; i < _headers.size(); i++) + delete _headers[i]; +} - if (_fallBack && SearchMan.hasFile(filename)) { - return SearchMan.createReadStreamForMember(filename); + +bool ArjArchive::hasFile(const String &name) { + return _fileMap.contains(name); +} + +int ArjArchive::listMembers(ArchiveMemberList &list) { + int matches = 0; + + Common::Array<ArjHeader *>::iterator it = _headers.begin(); + for ( ; it != _headers.end(); ++it) { + list.push_back(ArchiveMemberList::value_type(new GenericArchiveMember((*it)->filename, this))); + matches++; } - if (!_fileMap.contains(filename)) + return matches; +} + +ArchiveMemberPtr ArjArchive::getMember(const String &name) { + if (!hasFile(name)) + return ArchiveMemberPtr(); + + return ArchiveMemberPtr(new GenericArchiveMember(name, this)); +} + +SeekableReadStream *ArjArchive::createReadStreamForMember(const String &name) const { + if (!_fileMap.contains(name)) { return 0; + } + + ArjHeader *hdr = _headers[_fileMap[name]]; + + Common::File archiveFile; + archiveFile.open(_arjFilename); + archiveFile.seek(hdr->pos, SEEK_SET); - ArjHeader *hdr = _headers[_fileMap[filename]]; // TODO: It would be good if ArjFile could decompress files in a streaming // mode, so it would not need to pre-allocate the entire output. byte *uncompressedData = (byte *)malloc(hdr->origSize); - - File archiveFile; - archiveFile.open(_archMap[filename]); - archiveFile.seek(hdr->pos, SEEK_SET); + assert(uncompressedData); if (hdr->method == 0) { // store int32 len = archiveFile.read(uncompressedData, hdr->origSize); @@ -824,8 +841,8 @@ SeekableReadStream *ArjFile::open(const Common::String &filename) { // If reading from archiveFile directly is too slow to be usable, // maybe the filesystem code should instead wrap its files // in a BufferedReadStream. - decoder->_compressed = new BufferedReadStream(&archiveFile, 4096, false); - decoder->_outstream = new MemoryWriteStream(uncompressedData, hdr->origSize); + decoder->_compressed = new Common::BufferedReadStream(&archiveFile, 4096, false); + decoder->_outstream = new Common::MemoryWriteStream(uncompressedData, hdr->origSize); if (hdr->method == 1 || hdr->method == 2 || hdr->method == 3) decoder->decode(hdr->origSize); @@ -835,7 +852,28 @@ SeekableReadStream *ArjFile::open(const Common::String &filename) { delete decoder; } - return new MemoryReadStream(uncompressedData, hdr->origSize, true); + return new Common::MemoryReadStream(uncompressedData, hdr->origSize, true); +} + +#pragma mark ArjFile implementation + +ArjFile::ArjFile() { + _fallBack = false; +} + +ArjFile::~ArjFile() { +} + +void ArjFile::registerArchive(const String &filename) { + add(filename, new ArjArchive(filename)); +} + +SeekableReadStream *ArjFile::open(const Common::String &filename) { + if (_fallBack && SearchMan.hasFile(filename)) { + return SearchMan.createReadStreamForMember(filename); + } + + return createReadStreamForMember(filename); } diff --git a/common/unarj.h b/common/unarj.h index eaf2bb4f85..92ca4a8354 100644 --- a/common/unarj.h +++ b/common/unarj.h @@ -28,6 +28,7 @@ #include "common/file.h" #include "common/hash-str.h" +#include "common/archive.h" namespace Common { @@ -35,9 +36,27 @@ struct ArjHeader; typedef HashMap<String, int, IgnoreCase_Hash, IgnoreCase_EqualTo> ArjFilesMap; +class ArjArchive : public Common::Archive { + + Common::Array<ArjHeader *> _headers; + ArjFilesMap _fileMap; + + Common::String _arjFilename; + +public: + ArjArchive(const String &name); + virtual ~ArjArchive(); + + // Common::Archive implementation + virtual bool hasFile(const String &name); + virtual int listMembers(ArchiveMemberList &list); + virtual ArchiveMemberPtr getMember(const String &name); + virtual SeekableReadStream *createReadStreamForMember(const String &name) const; +}; + // TODO: Get rid of this class, by implementing an ArjArchive subclass of Common::Archive. // Then ArjFile can be substituted by a SearchSet full of ArjArchives plus SearchMan. -class ArjFile : public NonCopyable { +class ArjFile : public SearchSet { public: ArjFile(); ~ArjFile(); @@ -51,9 +70,6 @@ public: private: bool _fallBack; - Array<ArjHeader *> _headers; - ArjFilesMap _fileMap; - StringMap _archMap; }; } // End of namespace Common |