[Scummvm-git-logs] scummvm master -> 2b9244c2de2ecc4c115eccab35be98c33f050649

phcoder noreply at scummvm.org
Thu Dec 1 00:53:30 UTC 2022


This automated email contains information about 8 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
1d15e2a66e COMMON: Fix DisposablePtr move constructor in presence of a deleter
81040b5d20 COMMON: Make memstream support SharedPtr-backed array
b2def0293c COMMON: Add MemcachingCaseInsensitiveArchive for caching archive contents
acc709730f COMMON: Switch clickteam to MemcachingCaseInsensitiveArchive.
2521169a7b DREAMWEB: Switch RNCA archive to MemcachingCaseInsensitiveArchive.
489d83c76d MADS: Switch MpsInstaller archive to MemcachingCaseInsensitiveArchive
bb792d2c3a COMMON: Switch unarj to MemcachingCaseInsensitiveArchive
2b9244c2de COMMON: Switch unzip to MemcachingCaseInsensitiveArchive


Commit: 1d15e2a66e4524df4a922f8c3a947a773d1d5f68
    https://github.com/scummvm/scummvm/commit/1d15e2a66e4524df4a922f8c3a947a773d1d5f68
Author: Vladimir Serbinenko (phcoder at gmail.com)
Date: 2022-12-01T01:52:46+01:00

Commit Message:
COMMON: Fix DisposablePtr move constructor in presence of a deleter

Changed paths:
    common/ptr.h


diff --git a/common/ptr.h b/common/ptr.h
index 2922dbdb4e8..4f61dd9cd01 100644
--- a/common/ptr.h
+++ b/common/ptr.h
@@ -658,7 +658,7 @@ public:
 
 	explicit DisposablePtr(PointerType o, DisposeAfterUse::Flag dispose) : _pointer(o), _dispose(dispose), _shared() {}
 	explicit DisposablePtr(SharedPtr<T> o) : _pointer(o.get()), _dispose(DisposeAfterUse::NO), _shared(o) {}
-	DisposablePtr(DisposablePtr<T>&& o) : _pointer(o._pointer), _dispose(o._dispose), _shared(o._shared) {
+	DisposablePtr(DisposablePtr<T, DL>&& o) : _pointer(o._pointer), _dispose(o._dispose), _shared(o._shared) {
 		o._pointer = nullptr;
 		o._dispose = DisposeAfterUse::NO;
 		o._shared.reset();


Commit: 81040b5d2064abfed69214f7f2086d518ee1e147
    https://github.com/scummvm/scummvm/commit/81040b5d2064abfed69214f7f2086d518ee1e147
Author: Vladimir Serbinenko (phcoder at gmail.com)
Date: 2022-12-01T01:52:46+01:00

Commit Message:
COMMON: Make memstream support SharedPtr-backed array

This allows to safely implement archive contents caches.

The change to lilliput is needed to allow to keep move-constructot
semantics of ScriptStream which would otherwise disappear because
DisposablePtr is non-copyable

Changed paths:
    common/memstream.h
    common/stream.cpp
    engines/lilliput/stream.h


diff --git a/common/memstream.h b/common/memstream.h
index 17bbc30dd8e..e787b95bb1e 100644
--- a/common/memstream.h
+++ b/common/memstream.h
@@ -42,14 +42,28 @@ namespace Common {
  */
 class MemoryReadStream : virtual public SeekableReadStream {
 private:
-	const byte * const _ptrOrig;
+	struct CastFreeDeleter {
+		inline void operator()(const byte *object) {
+			free(const_cast<byte *>(object));
+		}
+	};
+
+	// Note when using SharedPtr, then deleting is handled
+	// by SharedPtr and not by CastFreeDeleter
+	Common::DisposablePtr<const byte, CastFreeDeleter> _ptrOrig;
 	const byte *_ptr;
-	const uint32 _size;
+	uint32 _size;
 	uint32 _pos;
-	DisposeAfterUse::Flag _disposeMemory;
 	bool _eos;
 
 public:
+	MemoryReadStream(MemoryReadStream &&other) : _ptrOrig(Common::move(other._ptrOrig)), _ptr(other._ptr), _size(other._size), _pos(other._pos), _eos(other._eos) {
+		// other must remaining in a valid state. Let's make it into zero-sized stream.
+		other._ptr = nullptr;
+		other._size = 0;
+		other._pos = 0;
+		other._eos = false;
+	}
 
 	/**
 	 * This constructor takes a pointer to a memory buffer and a length, and
@@ -57,17 +71,18 @@ public:
 	 * of the buffer and hence free's it when destructed.
 	 */
 	MemoryReadStream(const byte *dataPtr, uint32 dataSize, DisposeAfterUse::Flag disposeMemory = DisposeAfterUse::NO) :
-		_ptrOrig(dataPtr),
+		_ptrOrig(dataPtr, disposeMemory),
 		_ptr(dataPtr),
 		_size(dataSize),
 		_pos(0),
-		_disposeMemory(disposeMemory),
 		_eos(false) {}
 
-	~MemoryReadStream() {
-		if (_disposeMemory)
-			free(const_cast<byte *>(_ptrOrig));
-	}
+	MemoryReadStream(SharedPtr<byte> dataPtr, uint32 dataSize) :
+		_ptrOrig(dataPtr),
+		_ptr(dataPtr.get()),
+		_size(dataSize),
+		_pos(0),
+		_eos(false) {}
 
 	uint32 read(void *dataPtr, uint32 dataSize);
 
diff --git a/common/stream.cpp b/common/stream.cpp
index 80495c95581..176e35a9bb8 100644
--- a/common/stream.cpp
+++ b/common/stream.cpp
@@ -119,7 +119,7 @@ bool MemoryReadStream::seek(int64 offs, int whence) {
 	case SEEK_SET:
 		// Fall through
 	default:
-		_ptr = _ptrOrig + offs;
+		_ptr = _ptrOrig.get() + offs;
 		_pos = offs;
 		break;
 
diff --git a/engines/lilliput/stream.h b/engines/lilliput/stream.h
index a191c45a675..696d5e58370 100644
--- a/engines/lilliput/stream.h
+++ b/engines/lilliput/stream.h
@@ -30,6 +30,9 @@ class ScriptStream : public Common::MemoryReadStream {
 private:
 	byte *_orgPtr;
 public:
+	ScriptStream(ScriptStream &&other) : Common::MemoryReadStream(Common::move(other)), _orgPtr(other._orgPtr) {
+		other._orgPtr = nullptr;
+	}
 	ScriptStream(byte *buf, int bufSize);
 	~ScriptStream() override;
 


Commit: b2def0293cb79c562f84aa9932aae0ee402a9430
    https://github.com/scummvm/scummvm/commit/b2def0293cb79c562f84aa9932aae0ee402a9430
Author: Vladimir Serbinenko (phcoder at gmail.com)
Date: 2022-12-01T01:52:46+01:00

Commit Message:
COMMON: Add MemcachingCaseInsensitiveArchive for caching archive contents

This allows to share code for caching decompressed contents.

Changed paths:
    common/archive.cpp
    common/archive.h


diff --git a/common/archive.cpp b/common/archive.cpp
index 1009a7c2c9b..a61aa2fc331 100644
--- a/common/archive.cpp
+++ b/common/archive.cpp
@@ -23,6 +23,7 @@
 #include "common/fs.h"
 #include "common/system.h"
 #include "common/textconsole.h"
+#include "common/memstream.h"
 
 namespace Common {
 
@@ -60,6 +61,19 @@ int Archive::listMatchingMembers(ArchiveMemberList &list, const Path &pattern) c
 	return matches;
 }
 
+SeekableReadStream *MemcachingCaseInsensitiveArchive::createReadStreamForMember(const Path &path) const {
+	String translated = translatePath(path);
+	if (!_cache.contains(translated)) {
+		_cache[translated] = readContentsForPath(translated);
+	}
+
+	const SharedArchiveContents& entry = _cache[translated];
+
+	if (entry.isFileMissing())
+		return nullptr;
+
+	return new Common::MemoryReadStream(entry.getContents(), entry.getSize());
+}
 
 
 SearchSet::ArchiveNodeList::iterator SearchSet::find(const String &name) {
diff --git a/common/archive.h b/common/archive.h
index f6ab784d8c5..2e89a8e992f 100644
--- a/common/archive.h
+++ b/common/archive.h
@@ -26,6 +26,8 @@
 #include "common/list.h"
 #include "common/path.h"
 #include "common/ptr.h"
+#include "common/hashmap.h"
+#include "common/hash-str.h"
 #include "common/singleton.h"
 
 namespace Common {
@@ -139,6 +141,39 @@ public:
 	virtual SeekableReadStream *createReadStreamForMember(const Path &path) const = 0;
 };
 
+class SharedArchiveContents {
+public:
+	SharedArchiveContents(byte *contents, uint32 contentSize) : _contents(contents, ArrayDeleter<byte>()), _contentSize(contentSize), _missingFile(false) {}
+	SharedArchiveContents() : _contents(nullptr), _contentSize(0), _missingFile(true) {}
+
+	bool isFileMissing() const { return _missingFile; }
+	SharedPtr<byte> getContents() const { return _contents; }
+	uint32 getSize() const { return _contentSize; }
+
+private:
+	SharedPtr<byte> _contents;
+	uint32 _contentSize;
+	bool _missingFile;
+};
+
+/**
+ * An archive that caches the resulting contents.
+ */
+class MemcachingCaseInsensitiveArchive : public Archive {
+public:
+	SeekableReadStream *createReadStreamForMember(const Path &path) const;
+
+	virtual String translatePath(const Path &path) const {
+		// Most of users of this class implement DOS-like archives.
+		// Others override this method.
+		return normalizePath(path.toString('\\'), '\\');
+	}
+
+	virtual SharedArchiveContents readContentsForPath(const String& translatedPath) const = 0;
+
+private:
+	mutable HashMap<String, SharedArchiveContents, IgnoreCase_Hash, IgnoreCase_EqualTo> _cache;
+};
 
 /**
  * The SearchSet class enables access to a group of Archives through the Archive interface.


Commit: acc709730f0cd86d418ac77fd93836c28f1eb74b
    https://github.com/scummvm/scummvm/commit/acc709730f0cd86d418ac77fd93836c28f1eb74b
Author: Vladimir Serbinenko (phcoder at gmail.com)
Date: 2022-12-01T01:52:46+01:00

Commit Message:
COMMON: Switch clickteam to MemcachingCaseInsensitiveArchive.

Changed paths:
    common/clickteam.cpp
    common/clickteam.h


diff --git a/common/clickteam.cpp b/common/clickteam.cpp
index 022522afde4..d6334cc97d3 100644
--- a/common/clickteam.cpp
+++ b/common/clickteam.cpp
@@ -216,12 +216,8 @@ ClickteamInstaller* ClickteamInstaller::open(Common::SeekableReadStream *stream,
 	return new ClickteamInstaller(files, tags, crc_xor, block3_offset, block3_len, stream, dispose);
 }
 
-static Common::String translateName(const Path &path) {
-	return Common::normalizePath(path.toString('\\'), '\\');
-}
-
 bool ClickteamInstaller::hasFile(const Path &path) const {
-	return _files.contains(translateName(path));
+	return _files.contains(translatePath(path));
 }
 
 int ClickteamInstaller::listMembers(ArchiveMemberList &list) const {
@@ -237,32 +233,27 @@ int ClickteamInstaller::listMembers(ArchiveMemberList &list) const {
 }
 
 const ArchiveMemberPtr ClickteamInstaller::getMember(const Path &path) const {
-	Common::String translated = translateName(path);
+	Common::String translated = translatePath(path);
 	if (!_files.contains(translated))
 		return nullptr;
 
 	return Common::SharedPtr<Common::ArchiveMember>(new GenericArchiveMember(_files.getVal(translated)._fileName, this));
 }
 
-// TODO: Make streams stay valid after destructing of archive
-SeekableReadStream *ClickteamInstaller::createReadStreamForMember(const Path &path) const {
-	Common::String translated = translateName(path);
+Common::SharedArchiveContents ClickteamInstaller::readContentsForPath(const Common::String& translated) const {
 	if (!_files.contains(translated))
-		return nullptr;
+		return Common::SharedArchiveContents();
 	ClickteamFileDescriptor desc = _files.getVal(translated);
-	if (_cache.contains(desc._fileName)) {
-		return new Common::MemoryReadStream(_cache[desc._fileName].get(), desc._uncompressedSize, DisposeAfterUse::NO);
-	}
 	Common::SeekableReadStream *subStream = new Common::SeekableSubReadStream(_stream.get(), _block3Offset + desc._fileDataOffset,
 										  _block3Offset + desc._fileDataOffset + desc._compressedSize);
 	if (!subStream) {
 		debug("Decompression error");
-		return nullptr;
+		return Common::SharedArchiveContents();
 	}
 	Common::ScopedPtr<Common::SeekableReadStream> uncStream(GzioReadStream::openClickteam(subStream, desc._uncompressedSize, DisposeAfterUse::YES));
 	if (!uncStream) {
 		debug("Decompression error");
-		return nullptr;
+		return Common::SharedArchiveContents();
 	}
 
 	byte *uncompressedBuffer = new byte[desc._uncompressedSize];
@@ -271,7 +262,7 @@ SeekableReadStream *ClickteamInstaller::createReadStreamForMember(const Path &pa
 	if (ret < 0 || ret < desc._uncompressedSize) {
 		debug ("Decompression error");
 		delete[] uncompressedBuffer;
-		return nullptr;
+		return Common::SharedArchiveContents();
 	}
 
 	if (desc._expectedCRC != 0 || !desc._fileName.equalsIgnoreCase("Uninstal.exe")) {
@@ -281,13 +272,12 @@ SeekableReadStream *ClickteamInstaller::createReadStreamForMember(const Path &pa
 		if (actualCrc != expectedCrc) {
 			debug("CRC mismatch for %s: expected=%08x (obfuscated %08x), actual=%08x", desc._fileName.c_str(), expectedCrc, desc._expectedCRC, actualCrc);
 			delete[] uncompressedBuffer;
-			return nullptr;
+			return Common::SharedArchiveContents();
 		}
 	}
 
-	_cache[desc._fileName].reset(uncompressedBuffer);
 	// TODO: Make it configurable to use a uncompressing substream instead
-	return new Common::MemoryReadStream(uncompressedBuffer, desc._uncompressedSize, DisposeAfterUse::NO);
+	return Common::SharedArchiveContents(uncompressedBuffer, desc._uncompressedSize);
 }
 
 }
diff --git a/common/clickteam.h b/common/clickteam.h
index aa3e67f4a50..0eecfe1a007 100644
--- a/common/clickteam.h
+++ b/common/clickteam.h
@@ -29,7 +29,7 @@
 #include "common/hash-str.h"
 
 namespace Common {
-class ClickteamInstaller : public Archive {
+class ClickteamInstaller : public MemcachingCaseInsensitiveArchive {
 public:
 	enum class ClickteamTagId : uint16 {
 		BANNER_IMAGE = 0x1235,
@@ -56,7 +56,7 @@ public:
 	bool hasFile(const Path &path) const override;
 	int listMembers(Common::ArchiveMemberList&) const override;
 	const ArchiveMemberPtr getMember(const Path &path) const override;
-	SeekableReadStream *createReadStreamForMember(const Path &path) const override;
+	Common::SharedArchiveContents readContentsForPath(const Common::String& translated) const override;
 
 	ClickteamTag* getTag(ClickteamTagId tagId) const;
 
@@ -91,7 +91,6 @@ private:
 	Common::HashMap<Common::String, ClickteamFileDescriptor, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> _files;
 	Common::HashMap<uint16, Common::SharedPtr<ClickteamTag>> _tags;
 	Common::DisposablePtr<Common::SeekableReadStream> _stream;
-	mutable Common::HashMap<Common::String, Common::ScopedPtr<byte, Common::ArrayDeleter<byte>>, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> _cache;
 	uint32 _crcXor, _block3Offset/*, _block3Size*/;
 };
 }


Commit: 2521169a7b8c840c9fe435aaad83601541f7e0fa
    https://github.com/scummvm/scummvm/commit/2521169a7b8c840c9fe435aaad83601541f7e0fa
Author: Vladimir Serbinenko (phcoder at gmail.com)
Date: 2022-12-01T01:52:46+01:00

Commit Message:
DREAMWEB: Switch RNCA archive to MemcachingCaseInsensitiveArchive.

Changed paths:
    engines/dreamweb/rnca_archive.cpp
    engines/dreamweb/rnca_archive.h


diff --git a/engines/dreamweb/rnca_archive.cpp b/engines/dreamweb/rnca_archive.cpp
index 242207db4d5..7b29851b366 100644
--- a/engines/dreamweb/rnca_archive.cpp
+++ b/engines/dreamweb/rnca_archive.cpp
@@ -67,12 +67,8 @@ RNCAArchive* RNCAArchive::open(Common::SeekableReadStream *stream, DisposeAfterU
 	return new RNCAArchive(files, stream, dispose);
 }
 
-static Common::String translateName(const Common::Path &path) {
-	return Common::normalizePath(path.toString('\\'), '\\');
-}
-
 bool RNCAArchive::hasFile(const Common::Path &path) const {
-	return _files.contains(translateName(path));
+	return _files.contains(translatePath(path));
 }
 
 int RNCAArchive::listMembers(Common::ArchiveMemberList &list) const {
@@ -84,32 +80,21 @@ int RNCAArchive::listMembers(Common::ArchiveMemberList &list) const {
 }
 
 const Common::ArchiveMemberPtr RNCAArchive::getMember(const Common::Path &path) const {
-	Common::String translated = translateName(path);
+	Common::String translated = translatePath(path);
 	if (!_files.contains(translated))
 		return nullptr;
 
 	return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(_files.getVal(translated)._fileName, this));
 }
 
-// TODO: Make streams stay valid after destruction of archive
-Common::SeekableReadStream *RNCAArchive::createReadStreamForMember(const Common::Path &path) const {
-	Common::String translated = translateName(path);
+Common::SharedArchiveContents RNCAArchive::readContentsForPath(const Common::String& translated) const {
 	if (!_files.contains(translated))
-		return nullptr;
+		return Common::SharedArchiveContents();
 	const RNCAFileDescriptor& desc = _files.getVal(translated);
-	if (_cache.contains(desc._fileName)) {
-		const Common::SharedPtr<CacheEntry> &entry = _cache[desc._fileName];
-		if (entry->is_error) {
-			return nullptr;
-		}
-		return new Common::MemoryReadStream(entry->contents, entry->size, DisposeAfterUse::NO);
-	}
-
 	_stream->seek(desc._fileDataOffset);
 
 	if (_stream->readUint32BE() != Common::RncDecoder::kRnc1Signature) {
-		_cache[desc._fileName] = CacheEntry::error();
-		return nullptr;
+		return Common::SharedArchiveContents();
 	}
 
 	// Read unpacked/packed file length
@@ -117,9 +102,8 @@ Common::SeekableReadStream *RNCAArchive::createReadStreamForMember(const Common:
 	uint32 packLen = _stream->readUint32BE();
 
 	if (unpackLen > 0x7ffff000 || packLen > 0x7ffff000) {
-		_cache[desc._fileName] = CacheEntry::error();
 		debug("Header error for %s", desc._fileName.c_str());
-		return nullptr;
+		return Common::SharedArchiveContents();
 	}
 
 	// Rewind back the header
@@ -128,18 +112,16 @@ Common::SeekableReadStream *RNCAArchive::createReadStreamForMember(const Common:
 
 	byte *compressedBuffer = new byte[packLen];
 	if (_stream->read(compressedBuffer, packLen) != packLen) {
-		_cache[desc._fileName] = CacheEntry::error();
 		debug("Read error for %s", desc._fileName.c_str());
-		return nullptr;		
+		return Common::SharedArchiveContents();
 	}
 	byte *uncompressedBuffer = new byte[unpackLen];
 
 	Common::RncDecoder rnc;
 	
 	if (rnc.unpackM1(compressedBuffer, packLen, uncompressedBuffer) != (int32) unpackLen) {
-		_cache[desc._fileName] = CacheEntry::error();
 		debug("Unpacking error for %s", desc._fileName.c_str());
-		return nullptr;
+		return Common::SharedArchiveContents();
 	}
 
 	byte b = 0;
@@ -147,13 +129,8 @@ Common::SeekableReadStream *RNCAArchive::createReadStreamForMember(const Common:
 		b += *ptr;
 		*ptr = b;
 	}
-	
-	_cache[desc._fileName].reset(new CacheEntry);
-	_cache[desc._fileName]->size = unpackLen;
-	_cache[desc._fileName]->is_error = false;
-	_cache[desc._fileName]->contents = uncompressedBuffer;
 
-	return new Common::MemoryReadStream(uncompressedBuffer, unpackLen, DisposeAfterUse::NO);
+	return Common::SharedArchiveContents(uncompressedBuffer, unpackLen);
 }
 
 } // End of namespace DreamWeb
diff --git a/engines/dreamweb/rnca_archive.h b/engines/dreamweb/rnca_archive.h
index 49033330508..e808f8d6972 100644
--- a/engines/dreamweb/rnca_archive.h
+++ b/engines/dreamweb/rnca_archive.h
@@ -29,12 +29,12 @@
 #include "common/hash-str.h"
 
 namespace DreamWeb {
-class RNCAArchive : public Common::Archive {
+class RNCAArchive : public Common::MemcachingCaseInsensitiveArchive {
 public:
 	bool hasFile(const Common::Path &path) const override;
 	int listMembers(Common::ArchiveMemberList&) const override;
 	const Common::ArchiveMemberPtr getMember(const Common::Path &path) const override;
-	Common::SeekableReadStream *createReadStreamForMember(const Common::Path &path) const override;
+	Common::SharedArchiveContents readContentsForPath(const Common::String& translated) const override;
 
 	static RNCAArchive* open(Common::SeekableReadStream *stream, DisposeAfterUse::Flag dispose = DisposeAfterUse::NO);
 	
@@ -53,25 +53,6 @@ private:
 		RNCAFileDescriptor() : _fileDataOffset(0) {}
 	};
 
-	struct CacheEntry {
-		byte *contents;
-		uint32 size;
-		bool is_error;
-
-		~CacheEntry() {
-			delete[] contents;
-		}
-
-		static Common::SharedPtr<CacheEntry> error() {
-			Common::SharedPtr<CacheEntry> ret(new CacheEntry());
-			ret->size = 0;
-			ret->is_error = true;
-			ret->contents = nullptr;
-
-			return ret;
-		}
-	};
-
 	typedef Common::HashMap<Common::String, RNCAFileDescriptor, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> FileMap;
 
 	RNCAArchive(FileMap files, Common::SeekableReadStream *stream, DisposeAfterUse::Flag dispose)
@@ -80,7 +61,6 @@ private:
 
 	FileMap _files;
 	Common::DisposablePtr<Common::SeekableReadStream> _stream;
-	mutable Common::HashMap<Common::String, Common::SharedPtr<CacheEntry>, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> _cache;
 };
 }
 #endif


Commit: 489d83c76d20677ae8cab8b16c070e3637aa129d
    https://github.com/scummvm/scummvm/commit/489d83c76d20677ae8cab8b16c070e3637aa129d
Author: Vladimir Serbinenko (phcoder at gmail.com)
Date: 2022-12-01T01:52:46+01:00

Commit Message:
MADS: Switch MpsInstaller archive to MemcachingCaseInsensitiveArchive

Changed paths:
    engines/mads/mps_installer.cpp
    engines/mads/mps_installer.h


diff --git a/engines/mads/mps_installer.cpp b/engines/mads/mps_installer.cpp
index 44639ebed26..6d6e07a94cf 100644
--- a/engines/mads/mps_installer.cpp
+++ b/engines/mads/mps_installer.cpp
@@ -63,13 +63,8 @@ MpsInstaller* MpsInstaller::open(const Common::Path& baseName) {
 	return new MpsInstaller(_files, baseName);
 }
 
-// Use of \\ as path separator is a guess. Never seen an archive with subfolders
-static Common::String translateName(const Common::Path &path) {
-	return Common::normalizePath(path.toString('\\'), '\\');
-}
-
 bool MpsInstaller::hasFile(const Common::Path &path) const {
-	return _files.contains(translateName(path));
+	return _files.contains(translatePath(path));
 }
 
 int MpsInstaller::listMembers(Common::ArchiveMemberList &list) const {
@@ -81,26 +76,21 @@ int MpsInstaller::listMembers(Common::ArchiveMemberList &list) const {
 }
 
 const Common::ArchiveMemberPtr MpsInstaller::getMember(const Common::Path &path) const {
-	Common::String translated = translateName(path);
+	Common::String translated = translatePath(path);
 	if (!_files.contains(translated))
 		return nullptr;
 
 	return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(_files.getVal(translated)._fileName, this));
 }
 
-// TODO: Make streams stay valid after destruction of archive
-Common::SeekableReadStream *MpsInstaller::createReadStreamForMember(const Common::Path &path) const {
-	Common::String translated = translateName(path);
+Common::SharedArchiveContents MpsInstaller::readContentsForPath(const Common::String& translated) const {
 	if (!_files.contains(translated))
-		return nullptr;
+		return Common::SharedArchiveContents();
 	FileDescriptor desc = _files.getVal(translated);
-	if (_cache.contains(desc._fileName)) {
-		return new Common::MemoryReadStream(_cache[desc._fileName].get(), desc._uncompressedSize, DisposeAfterUse::NO);
-	}
 
 	if (desc._compressionAlgo != 0 && desc._compressionAlgo != 1) {
 		debug ("Unsupported compression algorithm %d for %s", desc._compressionAlgo, desc._fileName.c_str());
-		return nullptr;
+		return Common::SharedArchiveContents();
 	}
 
 
@@ -115,14 +105,14 @@ Common::SeekableReadStream *MpsInstaller::createReadStreamForMember(const Common
 		if (!fvol.open(volumePath)) {
 			error("Failed to open volume %s.%03d", volumePath.toString().c_str(), vol);
 			delete[] compressedBuf;
-			return nullptr;
+			return Common::SharedArchiveContents();
 		}
 		fvol.seek(off);
 		int32 actual = fvol.read(outptr, rem);
 		if (actual <= 0) {
 			warning("Read failure in volume %s.%03d", volumePath.toString().c_str(), vol);
 			delete[] compressedBuf;
-			return nullptr;
+			return Common::SharedArchiveContents();
 		}
 
 		rem -= actual;
@@ -148,7 +138,7 @@ Common::SeekableReadStream *MpsInstaller::createReadStreamForMember(const Common
 			delete[] compressedBuf;
 			delete[] uncompressedBuf;
 			error("Unable to decompress %s", desc._fileName.c_str());
-			return nullptr;
+			return Common::SharedArchiveContents();
 		}
 		delete[] compressedBuf;
 		compressedBuf = nullptr;
@@ -156,8 +146,7 @@ Common::SeekableReadStream *MpsInstaller::createReadStreamForMember(const Common
 		break;
 	}
 
-	_cache[desc._fileName].reset(uncompressedBuf);
 	// TODO: Make it configurable to read directly from disk, at least in the uncompressed case
-	return new Common::MemoryReadStream(uncompressedBuf, desc._uncompressedSize, DisposeAfterUse::NO);
+	return Common::SharedArchiveContents(uncompressedBuf, desc._uncompressedSize);
 }
 }
diff --git a/engines/mads/mps_installer.h b/engines/mads/mps_installer.h
index 630ed8c3ca0..487ffa076c1 100644
--- a/engines/mads/mps_installer.h
+++ b/engines/mads/mps_installer.h
@@ -30,12 +30,12 @@
 
 namespace MADS {
 
-class MpsInstaller : public Common::Archive {
+class MpsInstaller : public Common::MemcachingCaseInsensitiveArchive {
 public:
 	bool hasFile(const Common::Path &path) const override;
 	int listMembers(Common::ArchiveMemberList&) const override;
 	const Common::ArchiveMemberPtr getMember(const Common::Path &path) const override;
-	Common::SeekableReadStream *createReadStreamForMember(const Common::Path &path) const override;
+	Common::SharedArchiveContents readContentsForPath(const Common::String& translatedPath) const override;
 
 	static MpsInstaller* open(const Common::Path& baseName);
 
@@ -79,7 +79,6 @@ private:
 		     const Common::Path& baseName) : _files(files), _baseName(baseName) {}
 
 	FileMap _files;
-	mutable Common::HashMap<Common::String, Common::ScopedPtr<byte, Common::ArrayDeleter<byte>>, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> _cache;
 	Common::Path _baseName;
 };
 }


Commit: bb792d2c3a8f170a9a77a0679466c8bdda89e97b
    https://github.com/scummvm/scummvm/commit/bb792d2c3a8f170a9a77a0679466c8bdda89e97b
Author: Vladimir Serbinenko (phcoder at gmail.com)
Date: 2022-12-01T01:52:46+01:00

Commit Message:
COMMON: Switch unarj to MemcachingCaseInsensitiveArchive

Changed paths:
    common/unarj.cpp


diff --git a/common/unarj.cpp b/common/unarj.cpp
index c4e25f8f6c6..f580124d123 100644
--- a/common/unarj.cpp
+++ b/common/unarj.cpp
@@ -699,7 +699,7 @@ struct ArjFileChunk {
 
 typedef HashMap<String, Array<ArjFileChunk>, IgnoreCase_Hash, IgnoreCase_EqualTo> ArjHeadersMap;
 
-class ArjArchive : public Archive {
+class ArjArchive : public MemcachingCaseInsensitiveArchive {
 	ArjHeadersMap _headers;
 	Array<String> _arjFilenames;
 
@@ -711,7 +711,10 @@ public:
 	bool hasFile(const Path &path) const override;
 	int listMembers(ArchiveMemberList &list) const override;
 	const ArchiveMemberPtr getMember(const Path &path) const override;
-	SeekableReadStream *createReadStreamForMember(const Path &path) const override;
+	Common::SharedArchiveContents readContentsForPath(const Common::String& translated) const override;
+	Common::String translatePath(const Common::Path &path) const override {
+		return path.toString();
+	}
 };
 
 ArjArchive::~ArjArchive() {
@@ -780,10 +783,9 @@ const ArchiveMemberPtr ArjArchive::getMember(const Path &path) const {
 	return ArchiveMemberPtr(new GenericArchiveMember(name, this));
 }
 
-SeekableReadStream *ArjArchive::createReadStreamForMember(const Path &path) const {
-	String name = path.toString();
+Common::SharedArchiveContents ArjArchive::readContentsForPath(const Common::String& name) const {
 	if (!_headers.contains(name)) {
-		return nullptr;
+		return Common::SharedArchiveContents();
 	}
 
 	const Array <ArjFileChunk>& hdrs = _headers[name];
@@ -800,13 +802,12 @@ SeekableReadStream *ArjArchive::createReadStreamForMember(const Path &path) cons
 
 	// Prevent overflows
 	if (uncompressedSize > 0x70000000)
-		return nullptr;
+		return Common::SharedArchiveContents();
 
 	// 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(uncompressedSize);
+	byte *uncompressedData = new byte[uncompressedSize];
 	uint32 uncompressedPtr = 0;
-	assert(uncompressedData);
 
 	for (uint chunk = 0; chunk < totalChunks; chunk++) {
 		File archiveFile;
@@ -837,7 +838,7 @@ SeekableReadStream *ArjArchive::createReadStreamForMember(const Path &path) cons
 		uncompressedPtr += hdr->origSize;
 	}
 
-	return new MemoryReadStream(uncompressedData, uncompressedSize, DisposeAfterUse::YES);
+	return Common::SharedArchiveContents(uncompressedData, uncompressedSize);
 }
 
 Archive *makeArjArchive(const String &name) {


Commit: 2b9244c2de2ecc4c115eccab35be98c33f050649
    https://github.com/scummvm/scummvm/commit/2b9244c2de2ecc4c115eccab35be98c33f050649
Author: Vladimir Serbinenko (phcoder at gmail.com)
Date: 2022-12-01T01:52:46+01:00

Commit Message:
COMMON: Switch unzip to MemcachingCaseInsensitiveArchive

Changed paths:
    common/unzip.cpp


diff --git a/common/unzip.cpp b/common/unzip.cpp
index 58132fb41b6..f22fe3c4df3 100644
--- a/common/unzip.cpp
+++ b/common/unzip.cpp
@@ -219,7 +219,7 @@ int unzGetCurrentFileInfo(unzFile file,
    from it, and close it (you can close it before reading all the file)
    */
 
-Common::SeekableReadStream *unzOpenCurrentFile(unzFile file, const Common::CRC32& crc);
+Common::SharedArchiveContents unzOpenCurrentFile(unzFile file, const Common::CRC32& crc);
 /*
   Open for reading data the current file in the zipfile.
   If there is no error, the return value is UNZ_OK.
@@ -902,31 +902,30 @@ static int unzlocal_CheckCurrentFileCoherencyHeader(unz_s *s, uInt *piSizeVar,
   Open for reading data the current file in the zipfile.
   If there is no error and the file is opened, the return value is UNZ_OK.
 */
-Common::SeekableReadStream *unzOpenCurrentFile (unzFile file, const Common::CRC32 &crc) {
+Common::SharedArchiveContents unzOpenCurrentFile (unzFile file, const Common::CRC32 &crc) {
 	uInt iSizeVar;
 	unz_s *s;
 	uLong offset_local_extrafield;  /* offset of the local extra field */
 	uInt  size_local_extrafield;    /* size of the local extra field */
 
 	if (file == nullptr)
-		return nullptr;
+		return Common::SharedArchiveContents();
 	s = (unz_s *)file;
 	if (!s->current_file_ok)
-		return nullptr;
+		return Common::SharedArchiveContents();
 
 	if (unzlocal_CheckCurrentFileCoherencyHeader(s, &iSizeVar,
 				&offset_local_extrafield, &size_local_extrafield) != UNZ_OK)
-		return nullptr;
+		return Common::SharedArchiveContents();
 
 	if (s->cur_file_info.compression_method != 0 && s->cur_file_info.compression_method != Z_DEFLATED) {
 		warning("Unknown compression algoritthm %d", (int)s->cur_file_info.compression_method);
-		return nullptr;
+		return Common::SharedArchiveContents();
 	}
 
 	uint32 crc32_wait = s->cur_file_info.crc;
 
-	byte *compressedBuffer = (byte *)malloc(s->cur_file_info.compressed_size);
-	assert(s->cur_file_info.compressed_size == 0 || compressedBuffer != nullptr);
+	byte *compressedBuffer = new byte[s->cur_file_info.compressed_size];
 	s->_stream->seek(s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER + iSizeVar);
 	s->_stream->read(compressedBuffer, s->cur_file_info.compressed_size);
 	byte *uncompressedBuffer = nullptr;
@@ -936,33 +935,33 @@ Common::SeekableReadStream *unzOpenCurrentFile (unzFile file, const Common::CRC3
 		uncompressedBuffer = compressedBuffer;
 		break;
 	case Z_DEFLATED:
-		uncompressedBuffer = (byte *)malloc(s->cur_file_info.uncompressed_size);
+		uncompressedBuffer = new byte[s->cur_file_info.uncompressed_size];
 		assert(s->cur_file_info.uncompressed_size == 0 || uncompressedBuffer != nullptr);
 		Common::GzioReadStream::deflateDecompress(uncompressedBuffer, s->cur_file_info.uncompressed_size, compressedBuffer, s->cur_file_info.compressed_size);
-		free(compressedBuffer);
+		delete[] compressedBuffer;
 		compressedBuffer = nullptr;
 		break;
 	default:
 		warning("Unknown compression algoritthm %d", (int)s->cur_file_info.compression_method);
-		free(compressedBuffer);
-		return nullptr;
+		delete[] compressedBuffer;
+		return Common::SharedArchiveContents();
 	}
 
 	uint32 crc32_data = crc.crcFast(uncompressedBuffer, s->cur_file_info.uncompressed_size);
 	if (crc32_data != crc32_wait) {
-		free(uncompressedBuffer);
+		delete[] uncompressedBuffer;
 		warning("CRC32 mismatch: %08x, %08x", crc32_data, crc32_wait);
-		return nullptr;
+		return Common::SharedArchiveContents();
 	}
 
-	return new Common::MemoryReadStream(uncompressedBuffer, s->cur_file_info.uncompressed_size, DisposeAfterUse::YES);
+	return Common::SharedArchiveContents(uncompressedBuffer, s->cur_file_info.uncompressed_size);
 }
 
 
 namespace Common {
 
 
-class ZipArchive : public Archive {
+class ZipArchive : public MemcachingCaseInsensitiveArchive {
 	unzFile _zipFile;
 	Common::CRC32 _crc;
 
@@ -975,7 +974,10 @@ public:
 	bool hasFile(const Path &path) const override;
 	int listMembers(ArchiveMemberList &list) const override;
 	const ArchiveMemberPtr getMember(const Path &path) const override;
-	SeekableReadStream *createReadStreamForMember(const Path &path) const override;
+	Common::SharedArchiveContents readContentsForPath(const Common::String& translated) const override;
+	Common::String translatePath(const Common::Path &path) const override {
+		return path.toString();
+	}
 };
 
 /*
@@ -1030,10 +1032,9 @@ const ArchiveMemberPtr ZipArchive::getMember(const Path &path) const {
 	return ArchiveMemberPtr(new GenericArchiveMember(name, this));
 }
 
-SeekableReadStream *ZipArchive::createReadStreamForMember(const Path &path) const {
-	String name = path.toString();
+Common::SharedArchiveContents ZipArchive::readContentsForPath(const Common::String& name) const {
 	if (unzLocateFile(_zipFile, name.c_str(), 2) != UNZ_OK)
-		return nullptr;
+		return Common::SharedArchiveContents();
 
 	return unzOpenCurrentFile(_zipFile, _crc);
 }




More information about the Scummvm-git-logs mailing list