aboutsummaryrefslogtreecommitdiff
path: root/common
diff options
context:
space:
mode:
Diffstat (limited to 'common')
-rw-r--r--common/unarj.cpp114
-rw-r--r--common/unarj.h24
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