COMMON: Move Archive API to Path

This commit is contained in:
Le Philousophe 2023-09-10 10:21:31 +02:00 committed by Eugene Sandulenko
parent 3c5fe56de6
commit 93a8f7f4d6
32 changed files with 230 additions and 252 deletions

View File

@ -239,7 +239,7 @@ SeekableReadStream *MemcachingCaseInsensitiveArchive::createReadStreamForMemberI
return memStream;
}
SharedArchiveContents MemcachingCaseInsensitiveArchive::readContentsForPathAltStream(const String &translatedPath, AltStreamType altStreamType) const {
SharedArchiveContents MemcachingCaseInsensitiveArchive::readContentsForPathAltStream(const Path &translatedPath, AltStreamType altStreamType) const {
return SharedArchiveContents();
}
@ -251,7 +251,7 @@ bool MemcachingCaseInsensitiveArchive::CacheKey_EqualTo::operator()(const CacheK
}
uint MemcachingCaseInsensitiveArchive::CacheKey_Hash::operator()(const CacheKey &x) const {
return static_cast<uint>(hashit_lower(x.path) * 1000003u) ^ static_cast<uint>(x.altStreamType);
return static_cast<uint>(x.path.hashIgnoreCase() * 1000003u) ^ static_cast<uint>(x.altStreamType);
};
SearchSet::ArchiveNodeList::iterator SearchSet::find(const String &name) {

View File

@ -272,20 +272,18 @@ public:
SeekableReadStream *createReadStreamForMember(const Path &path) const;
SeekableReadStream *createReadStreamForMemberAltStream(const Path &path, Common::AltStreamType altStreamType) 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 Path translatePath(const Path &path) const {
return path.normalize();
}
virtual SharedArchiveContents readContentsForPath(const String &translatedPath) const = 0;
virtual SharedArchiveContents readContentsForPathAltStream(const String &translatedPath, AltStreamType altStreamType) const;
virtual SharedArchiveContents readContentsForPath(const Path &translatedPath) const = 0;
virtual SharedArchiveContents readContentsForPathAltStream(const Path &translatedPath, AltStreamType altStreamType) const;
private:
struct CacheKey {
CacheKey();
String path;
Path path;
AltStreamType altStreamType;
};

View File

@ -61,7 +61,7 @@ ClickteamInstaller::ClickteamFileDescriptor::ClickteamFileDescriptor(const Click
char *strings = (char *)tag + stringsOffset;
char *p;
for (p = strings; p < (char*)tag + lmax && *p; p++);
_fileName = Common::String(strings, p - strings);
_fileName = Common::Path(Common::String(strings, p - strings), Common::Path::kNoSeparator);
_fileDescriptorOffset = off;
_supported = true;
_isPatchFile = false;
@ -81,7 +81,7 @@ ClickteamInstaller::ClickteamFileDescriptor::ClickteamFileDescriptor(const Click
byte type = tag[7];
if (type != 0) {
_supported = false;
_fileName = "";
_fileName.clear();
_fileDataOffset = 0;
_fileDescriptorOffset = off;
_compressedSize = 0;
@ -119,7 +119,7 @@ ClickteamInstaller::ClickteamFileDescriptor::ClickteamFileDescriptor(const Click
char *strings = (char *)tag + stringsOffset;
char *p;
for (p = strings; p < (char*)tag + lmax && *p; p++);
_fileName = Common::String(strings, p - strings);
_fileName = Common::Path(Common::String(strings, p - strings), Common::Path::kNoSeparator);
_fileDescriptorOffset = off;
_compressedSize = 0;
_fileDataOffset = 0;
@ -305,7 +305,7 @@ struct TagHead {
};
int ClickteamInstaller::findPatchIdx(const ClickteamFileDescriptor &desc, Common::SeekableReadStream *refStream,
const Common::String &fileName,
const Common::Path &fileName,
uint32 crcXor, bool doWarn) {
bool hasMatching = refStream->size() == desc._uncompressedSize; // Maybe already patched?
for (uint i = 0; !hasMatching && i < desc._patchEntries.size(); i++)
@ -315,7 +315,7 @@ int ClickteamInstaller::findPatchIdx(const ClickteamFileDescriptor &desc, Common
}
if (!hasMatching) {
if (doWarn)
warning("Couldn't find matching patch entry for file %s size %d", fileName.c_str(), (int)refStream->size());
warning("Couldn't find matching patch entry for file %s size %d", fileName.toString().c_str(), (int)refStream->size());
return -1;
}
uint32 crcOriginal = 0;
@ -336,7 +336,7 @@ int ClickteamInstaller::findPatchIdx(const ClickteamFileDescriptor &desc, Common
if (patchDescIdx == -1 && refStream->size() == desc._uncompressedSize && crcOriginal == desc._expectedCRC)
return -2;
if (patchDescIdx < 0 && doWarn) {
warning("Couldn't find matching patch entry for file %s size %d and CRC 0x%x", fileName.c_str(), (int)refStream->size(), crcOriginal);
warning("Couldn't find matching patch entry for file %s size %d and CRC 0x%x", fileName.toString().c_str(), (int)refStream->size(), crcOriginal);
}
return patchDescIdx;
}
@ -348,7 +348,7 @@ ClickteamInstaller* ClickteamInstaller::open(Common::SeekableReadStream *stream,
ClickteamInstaller* ClickteamInstaller::openPatch(Common::SeekableReadStream *stream, bool verifyOriginal, bool verifyAllowSkip,
Common::Archive *reference, DisposeAfterUse::Flag dispose) {
Common::HashMap<Common::String, ClickteamFileDescriptor, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> files;
Common::HashMap<Common::Path, ClickteamFileDescriptor, Common::Path::IgnoreCase_Hash, Common::Path::IgnoreCase_EqualTo> files;
HashMap<uint16, Common::SharedPtr<ClickteamTag>> tags;
uint32 crc_xor;
@ -435,10 +435,10 @@ ClickteamInstaller* ClickteamInstaller::openPatch(Common::SeekableReadStream *st
return nullptr;
if (verifyOriginal && reference) {
for (Common::HashMap<Common::String, ClickteamFileDescriptor, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo>::iterator i = files.begin(), end = files.end();
for (Common::HashMap<Common::Path, ClickteamFileDescriptor, Common::Path::IgnoreCase_Hash, Common::Path::IgnoreCase_EqualTo>::iterator i = files.begin(), end = files.end();
i != end; ++i) {
if (i->_value._isPatchFile) {
Common::ScopedPtr<Common::SeekableReadStream> refStream(reference->createReadStreamForMember(Common::Path(i->_key, '\\')));
Common::ScopedPtr<Common::SeekableReadStream> refStream(reference->createReadStreamForMember(i->_key));
if (!refStream) {
if (verifyAllowSkip) {
i->_value._isReferenceMissing = true;
@ -453,7 +453,7 @@ ClickteamInstaller* ClickteamInstaller::openPatch(Common::SeekableReadStream *st
}
if (!reference) {
for (Common::HashMap<Common::String, ClickteamFileDescriptor, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo>::iterator i = files.begin(), end = files.end();
for (Common::HashMap<Common::Path, ClickteamFileDescriptor, Common::Path::IgnoreCase_Hash, Common::Path::IgnoreCase_EqualTo>::iterator i = files.begin(), end = files.end();
i != end; ++i) {
if (i->_value._isPatchFile) {
i->_value._isReferenceMissing = true;
@ -471,7 +471,7 @@ bool ClickteamInstaller::hasFile(const Path &path) const {
int ClickteamInstaller::listMembers(ArchiveMemberList &list) const {
int members = 0;
for (Common::HashMap<Common::String, ClickteamFileDescriptor, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo>::const_iterator i = _files.begin(), end = _files.end();
for (Common::HashMap<Common::Path, ClickteamFileDescriptor, Common::Path::IgnoreCase_Hash, Common::Path::IgnoreCase_EqualTo>::const_iterator i = _files.begin(), end = _files.end();
i != end; ++i) {
if (!i->_value._isReferenceMissing) {
list.push_back(ArchiveMemberList::value_type(new GenericArchiveMember(i->_key, *this)));
@ -483,7 +483,7 @@ int ClickteamInstaller::listMembers(ArchiveMemberList &list) const {
}
const ArchiveMemberPtr ClickteamInstaller::getMember(const Path &path) const {
Common::String translated = translatePath(path);
Common::Path translated = translatePath(path);
ClickteamFileDescriptor el;
if (!_files.tryGetVal(translated, el))
return nullptr;
@ -494,7 +494,7 @@ const ArchiveMemberPtr ClickteamInstaller::getMember(const Path &path) const {
return Common::SharedPtr<Common::ArchiveMember>(new GenericArchiveMember(el._fileName, *this));
}
Common::SharedArchiveContents ClickteamInstaller::readContentsForPath(const Common::String& translated) const {
Common::SharedArchiveContents ClickteamInstaller::readContentsForPath(const Common::Path &translated) const {
ClickteamFileDescriptor desc;
byte *uncompressedBuffer = nullptr;
@ -504,9 +504,9 @@ Common::SharedArchiveContents ClickteamInstaller::readContentsForPath(const Comm
return Common::SharedArchiveContents();
if (desc._isPatchFile) {
Common::ScopedPtr<Common::SeekableReadStream> refStream(_reference->createReadStreamForMemberNext(Common::Path(translated, '\\'), this));
Common::ScopedPtr<Common::SeekableReadStream> refStream(_reference->createReadStreamForMemberNext(translated, this));
if (!refStream) {
warning("Couldn't open reference file for %s. Skipping", translated.c_str());
warning("Couldn't open reference file for %s. Skipping", translated.toString('\\').c_str());
return Common::SharedArchiveContents();
}
int patchDescIdx = findPatchIdx(desc, refStream.get(), translated, _crcXor, true);
@ -608,7 +608,7 @@ Common::SharedArchiveContents ClickteamInstaller::readContentsForPath(const Comm
uint32 actualCrc = computeCRC(uncompressedBuffer, desc._uncompressedSize, 0);
if (actualCrc != expectedCrc) {
warning("CRC mismatch for %s: expected=%08x (obfuscated %08x), actual=%08x (back %08x)", desc._fileName.c_str(), expectedCrc, desc._expectedCRC, actualCrc, actualCrc ^ _crcXor);
warning("CRC mismatch for %s: expected=%08x (obfuscated %08x), actual=%08x (back %08x)", desc._fileName.toString().c_str(), expectedCrc, desc._expectedCRC, actualCrc, actualCrc ^ _crcXor);
delete[] uncompressedBuffer;
return Common::SharedArchiveContents();
}

View File

@ -57,7 +57,7 @@ public:
bool hasFile(const Common::Path &path) const override;
int listMembers(Common::ArchiveMemberList&) const override;
const ArchiveMemberPtr getMember(const Common::Path &path) const override;
Common::SharedArchiveContents readContentsForPath(const Common::String& translated) const override;
Common::SharedArchiveContents readContentsForPath(const Common::Path &translated) const override;
ClickteamTag* getTag(ClickteamTagId tagId) const;
@ -74,7 +74,7 @@ private:
};
class ClickteamFileDescriptor {
private:
Common::String _fileName;
Common::Path _fileName;
// Offset of the file contents relative to the beginning of block3
uint32 _fileDataOffset;
@ -97,8 +97,8 @@ private:
ClickteamFileDescriptor() : _fileDataOffset(0), _fileDescriptorOffset(0), _compressedSize(0), _uncompressedSize(0) {}
};
ClickteamInstaller(Common::HashMap<Common::String, ClickteamFileDescriptor, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> files,
Common::HashMap<uint16, Common::SharedPtr<ClickteamTag>> tags,
ClickteamInstaller(const Common::HashMap<Common::Path, ClickteamFileDescriptor, Common::Path::IgnoreCase_Hash, Common::Path::IgnoreCase_EqualTo> &files,
const Common::HashMap<uint16, Common::SharedPtr<ClickteamTag>> &tags,
uint32 crcXor, uint32 block3Offset, uint32 block3Size, Common::SeekableReadStream *stream,
Common::Archive *reference,
DisposeAfterUse::Flag dispose)
@ -106,9 +106,9 @@ private:
_reference(reference) {
}
static int findPatchIdx(const ClickteamFileDescriptor &desc, Common::SeekableReadStream *refStream, const Common::String &fileName,
static int findPatchIdx(const ClickteamFileDescriptor &desc, Common::SeekableReadStream *refStream, const Common::Path &fileName,
uint32 crcXor, bool doWarn);
Common::HashMap<Common::String, ClickteamFileDescriptor, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> _files;
Common::HashMap<Common::Path, ClickteamFileDescriptor, Common::Path::IgnoreCase_Hash, Common::Path::IgnoreCase_EqualTo> _files;
Common::HashMap<uint16, Common::SharedPtr<ClickteamTag>> _tags;
Common::DisposablePtr<Common::SeekableReadStream> _stream;
uint32 _crcXor, _block3Offset/*, _block3Size*/;

View File

@ -581,29 +581,26 @@ bool DecompressingStream::rewind() {
class ArchiveItem : public Common::ArchiveMember {
public:
ArchiveItem(Common::SeekableReadStream *stream, Common::Mutex *guardMutex, const Common::String &path, const Common::String &name, int64 filePos, uint compressedSize, uint decompressedSize, bool isCompressed);
ArchiveItem(Common::SeekableReadStream *stream, Common::Mutex *guardMutex, const Common::Path &path, int64 filePos, uint compressedSize, uint decompressedSize, bool isCompressed);
Common::SeekableReadStream *createReadStream() const override;
Common::SeekableReadStream *createReadStreamForAltStream(Common::AltStreamType altStreamType) const override;
Common::String getName() const override;
Common::Path getPathInArchive() const override { return getName(); }
Common::String getFileName() const override { return getName(); }
const Common::String &getPath() const;
Common::String getName() const override { return getFileName(); }
Common::Path getPathInArchive() const override { return _path; }
Common::String getFileName() const override { return _path.getLastComponent().toString(); }
private:
Common::SeekableReadStream *_stream;
Common::Mutex *_guardMutex;
Common::String _path;
Common::String _name;
Common::Path _path;
int64 _filePos;
uint _compressedSize;
uint _decompressedSize;
bool _isCompressed;
};
ArchiveItem::ArchiveItem(Common::SeekableReadStream *stream, Common::Mutex *guardMutex, const Common::String &path, const Common::String &name, int64 filePos, uint compressedSize, uint decompressedSize, bool isCompressed)
: _stream(stream), _guardMutex(guardMutex), _path(path), _name(name), _filePos(filePos), _compressedSize(compressedSize), _decompressedSize(decompressedSize), _isCompressed(isCompressed) {
ArchiveItem::ArchiveItem(Common::SeekableReadStream *stream, Common::Mutex *guardMutex, const Common::Path &path, int64 filePos, uint compressedSize, uint decompressedSize, bool isCompressed)
: _stream(stream), _guardMutex(guardMutex), _path(path), _filePos(filePos), _compressedSize(compressedSize), _decompressedSize(decompressedSize), _isCompressed(isCompressed) {
}
Common::SeekableReadStream *ArchiveItem::createReadStream() const {
@ -627,14 +624,6 @@ Common::SeekableReadStream *ArchiveItem::createReadStreamForAltStream(Common::Al
return nullptr;
}
Common::String ArchiveItem::getName() const {
return _name;
}
const Common::String &ArchiveItem::getPath() const {
return _path;
}
class PackageArchive : public Common::Archive {
public:
explicit PackageArchive(Common::SeekableReadStream *stream);
@ -656,7 +645,7 @@ private:
static Common::String normalizePath(const Common::Path &path);
Common::Array<Common::SharedPtr<ArchiveItem> > _items;
Common::HashMap<Common::String, uint> _pathToItemIndex;
Common::HashMap<Common::Path, uint, Common::Path::IgnoreCase_Hash, Common::Path::IgnoreCase_EqualTo> _pathToItemIndex;
Common::SeekableReadStream *_stream;
};
@ -792,23 +781,12 @@ bool PackageArchive::load(const char *prefix) {
if (fileName.hasPrefix(prefix)) {
fileName = fileName.substr(strlen(prefix));
fileName.replace('\\', '/');
Common::Path path(fileName, '/');
size_t bsPos = fileName.findFirstOf('\\');
while (bsPos != Common::String::npos) {
fileName.replace(bsPos, 1, "/");
bsPos = fileName.findFirstOf('\\');
}
Common::SharedPtr<ArchiveItem> item(new ArchiveItem(_stream, getGuardMutex(), path, dataStart, static_cast<uint>(dataEnd - dataStart), decompressedSize, isCompressed));
Common::String fileNameNoDir = fileName;
size_t lastSlashPos = fileNameNoDir.findLastOf('/');
if (lastSlashPos != Common::String::npos)
fileNameNoDir = fileNameNoDir.substr(lastSlashPos + 1);
Common::SharedPtr<ArchiveItem> item(new ArchiveItem(_stream, getGuardMutex(), fileName, fileNameNoDir, dataStart, static_cast<uint>(dataEnd - dataStart), decompressedSize, isCompressed));
fileName.toLowercase();
_pathToItemIndex[fileName] = _items.size();
_pathToItemIndex[path] = _items.size();
_items.push_back(item);
}
@ -852,7 +830,7 @@ Common::String PackageArchive::normalizePath(const Common::Path &path) {
}
bool PackageArchive::hasFile(const Common::Path &path) const {
return _pathToItemIndex.find(normalizePath(path)) != _pathToItemIndex.end();
return _pathToItemIndex.find(path) != _pathToItemIndex.end();
}
int PackageArchive::listMembers(Common::ArchiveMemberList &list) const {
@ -863,12 +841,11 @@ int PackageArchive::listMembers(Common::ArchiveMemberList &list) const {
}
int PackageArchive::listMatchingMembers(Common::ArchiveMemberList &list, const Common::Path &pattern, bool matchPathComponents) const {
Common::String patternString = pattern.toString();
int matches = 0;
const char *wildcardExclusions = matchPathComponents ? NULL : "/";
for (const Common::SharedPtr<ArchiveItem> &item : _items) {
if (item->getPath().matchString(patternString, true, wildcardExclusions)) {
if (normalizePath(item->getPathInArchive()).matchString(normalizePath(pattern), false, wildcardExclusions)) {
list.push_back(item.staticCast<Common::ArchiveMember>());
matches++;
}
@ -878,7 +855,7 @@ int PackageArchive::listMatchingMembers(Common::ArchiveMemberList &list, const C
}
const Common::ArchiveMemberPtr PackageArchive::getMember(const Common::Path &path) const {
Common::HashMap<Common::String, uint>::const_iterator it = _pathToItemIndex.find(normalizePath(path));
Common::HashMap<Common::Path, uint, Common::Path::IgnoreCase_Hash, Common::Path::IgnoreCase_EqualTo>::const_iterator it = _pathToItemIndex.find(path);
if (it == _pathToItemIndex.end())
return nullptr;

View File

@ -87,7 +87,7 @@ class InstallShieldCabinet : public Archive {
public:
InstallShieldCabinet();
bool open(const String *baseName, const FSNode *node);
bool open(const Path *baseName, const FSNode *node);
void close();
// Archive API implementation
@ -123,22 +123,22 @@ private:
};
int _version;
typedef HashMap<String, FileEntry, IgnoreCase_Hash, IgnoreCase_EqualTo> FileMap;
typedef HashMap<Path, FileEntry, Path::IgnoreCase_Hash, Path::IgnoreCase_EqualTo> FileMap;
FileMap _map;
String _baseName;
Path _baseName;
Common::Array<VolumeHeader> _volumeHeaders;
bool _useSearchMan;
static bool readVolumeHeader(SeekableReadStream *volumeStream, VolumeHeader &inVolumeHeader);
String getHeaderName() const;
String getVolumeName(uint volume) const;
Path getHeaderName() const;
Path getVolumeName(uint volume) const;
};
InstallShieldCabinet::InstallShieldCabinet() : _version(0), _useSearchMan(false) {
}
bool InstallShieldCabinet::open(const String *baseName, const FSNode *node) {
bool InstallShieldCabinet::open(const Path *baseName, const FSNode *node) {
// Store the base name so we can generate file names
if (baseName) {
_baseName = *baseName;
@ -150,8 +150,10 @@ bool InstallShieldCabinet::open(const String *baseName, const FSNode *node) {
return false;
}
if (_baseName.hasSuffix(".cab") || _baseName.hasSuffix(".hdr")) {
_baseName.erase(_baseName.size() - 5, String::npos);
String strippedName = _baseName.baseName();
if (strippedName.hasSuffix(".cab") || strippedName.hasSuffix(".hdr")) {
strippedName.erase(strippedName.size() - 5, String::npos);
_baseName = _baseName.getParent().appendComponent(strippedName);
}
uint fileIndex = 0;
@ -250,7 +252,7 @@ bool InstallShieldCabinet::open(const String *baseName, const FSNode *node) {
// Then let's get the string
file->seek(headerHeader.cabDescriptorOffset + fileTableOffset + nameOffset);
String fileName = file->readString();
Path fileName(file->readString(), '\\');
// Entries can appear in multiple volumes (sometimes erroneously).
// We keep the one with the lowest volume ID
@ -303,10 +305,10 @@ bool InstallShieldCabinet::open(const String *baseName, const FSNode *node) {
// Then let's get the string
file->seek(headerHeader.cabDescriptorOffset + fileTableOffset + nameOffset);
String fileName = file->readString();
Path fileName(file->readString(), '\\');
if (entry.volume == 0) {
warning("Couldn't find the volume for file %s", fileName.c_str());
warning("Couldn't find the volume for file %s", fileName.toString('\\').c_str());
close();
return false;
}
@ -331,8 +333,7 @@ void InstallShieldCabinet::close() {
}
bool InstallShieldCabinet::hasFile(const Path &path) const {
String name = path.toString();
return _map.contains(name);
return _map.contains(path);
}
int InstallShieldCabinet::listMembers(ArchiveMemberList &list) const {
@ -347,14 +348,13 @@ const ArchiveMemberPtr InstallShieldCabinet::getMember(const Path &path) const {
}
SeekableReadStream *InstallShieldCabinet::createReadStreamForMember(const Path &path) const {
String name = path.toString();
if (!_map.contains(name))
if (!_map.contains(path))
return nullptr;
const FileEntry &entry = _map[name];
const FileEntry &entry = _map[path];
if (entry.flags & kObfuscated) {
warning("Cannot extract obfuscated file %s", name.c_str());
warning("Cannot extract obfuscated file %s", path.toString().c_str());
return nullptr;
}
@ -369,7 +369,7 @@ SeekableReadStream *InstallShieldCabinet::createReadStreamForMember(const Path &
}
if (!stream) {
warning("Failed to open volume for file '%s'", name.c_str());
warning("Failed to open volume for file '%s'", path.toString().c_str());
return nullptr;
}
@ -396,7 +396,7 @@ SeekableReadStream *InstallShieldCabinet::createReadStreamForMember(const Path &
}
if (!stream.get()) {
warning("Failed to read split file %s", name.c_str());
warning("Failed to read split file %s", path.toString().c_str());
free(src);
return nullptr;
}
@ -428,7 +428,7 @@ SeekableReadStream *InstallShieldCabinet::createReadStreamForMember(const Path &
// Entries with size 0 are valid, and do not need to be inflated
if (entry.compressedSize != 0) {
if (!inflateZlibInstallShield(dst, entry.uncompressedSize, src, entry.compressedSize)) {
warning("failed to inflate CAB file '%s'", name.c_str());
warning("failed to inflate CAB file '%s'", path.toString().c_str());
free(dst);
free(src);
return nullptr;
@ -499,17 +499,17 @@ bool InstallShieldCabinet::readVolumeHeader(SeekableReadStream *volumeStream, In
return true;
}
String InstallShieldCabinet::getHeaderName() const {
return _baseName + "1.hdr";
Path InstallShieldCabinet::getHeaderName() const {
return _baseName.append("1.hdr");
}
String InstallShieldCabinet::getVolumeName(uint volume) const {
return String::format("%s%d.cab", _baseName.c_str(), volume);
Path InstallShieldCabinet::getVolumeName(uint volume) const {
return _baseName.append(String::format("%d.cab", volume));
}
} // End of anonymous namespace
Archive *makeInstallShieldArchive(const String &baseName) {
Archive *makeInstallShieldArchive(const Path &baseName) {
InstallShieldCabinet *cab = new InstallShieldCabinet();
if (!cab->open(&baseName, nullptr)) {
delete cab;

View File

@ -49,7 +49,7 @@ class SeekableReadStream;
*
* @param baseName The base filename, e.g. the "data" in "data1.cab"
*/
Archive *makeInstallShieldArchive(const Common::String &baseName);
Archive *makeInstallShieldArchive(const Common::Path &baseName);
/**
* This factory method creates an Archive instance corresponding to the content

View File

@ -34,7 +34,7 @@ InstallShieldV3::~InstallShieldV3() {
close();
}
bool InstallShieldV3::open(const Common::String &filename) {
bool InstallShieldV3::open(const Common::Path &filename) {
close();
_stream = SearchMan.createReadStreamForMember(filename);
@ -74,8 +74,7 @@ void InstallShieldV3::close() {
}
bool InstallShieldV3::hasFile(const Common::Path &path) const {
Common::String name = path.toString();
return _map.contains(name);
return _map.contains(path);
}
int InstallShieldV3::listMembers(Common::ArchiveMemberList &list) const {
@ -86,20 +85,14 @@ int InstallShieldV3::listMembers(Common::ArchiveMemberList &list) const {
}
const Common::ArchiveMemberPtr InstallShieldV3::getMember(const Common::Path &path) const {
Common::String name = path.toString();
return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(name, *this));
return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(path, *this));
}
Common::SeekableReadStream *InstallShieldV3::createReadStreamForMember(const Common::Path &path) const {
Common::String name = path.toString();
// Make sure "/" is converted to "\"
while (name.contains("/"))
Common::replace(name, "/", "\\");
if (!_stream || !_map.contains(name))
if (!_stream || !_map.contains(path))
return nullptr;
const FileEntry &entry = _map[name];
const FileEntry &entry = _map[path];
// Seek to our offset and then send it off to the decompressor
_stream->seek(entry.offset);
@ -178,7 +171,7 @@ bool InstallShieldV3::read() {
if (!dirNames[i].empty())
name = dirNames[i] + "\\" + name;
_map[name] = entry;
_map[Path(name, '\\')] = entry;
debug(3, "Found file '%s' at 0x%08x (Comp: 0x%08x, Uncomp: 0x%08x)", name.c_str(),
entry.offset, entry.compressedSize, entry.uncompressedSize);
}

View File

@ -37,7 +37,7 @@ public:
InstallShieldV3();
~InstallShieldV3() override;
bool open(const Common::String &filename);
bool open(const Common::Path &filename);
bool open(const Common::FSNode &node);
bool open(Common::SeekableReadStream *stream);
void close();
@ -61,7 +61,7 @@ private:
Common::SeekableReadStream *_stream;
typedef Common::HashMap<Common::String, FileEntry, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> FileMap;
typedef Common::HashMap<Path, FileEntry, Path::IgnoreCase_Hash, Path::IgnoreCase_EqualTo> FileMap;
FileMap _map;
};

View File

@ -43,7 +43,7 @@ public:
StuffItArchive();
~StuffItArchive() override;
bool open(const Common::String &filename, bool flattenTree);
bool open(const Common::Path &filename, bool flattenTree);
bool open(Common::SeekableReadStream *stream, bool flattenTree);
void close();
bool isOpen() const { return _stream != nullptr; }
@ -52,9 +52,9 @@ public:
bool hasFile(const Common::Path &path) const override;
int listMembers(Common::ArchiveMemberList &list) const override;
const Common::ArchiveMemberPtr getMember(const Common::Path &path) const override;
Common::SharedArchiveContents readContentsForPath(const Common::String &name) const override;
Common::SharedArchiveContents readContentsForPathAltStream(const String &translatedPath, Common::AltStreamType altStreamType) const override;
Common::String translatePath(const Common::Path &path) const override;
Common::SharedArchiveContents readContentsForPath(const Common::Path &name) const override;
Common::SharedArchiveContents readContentsForPathAltStream(const Common::Path &translatedPath, Common::AltStreamType altStreamType) const override;
Common::Path translatePath(const Common::Path &path) const override;
char getPathSeparator() const override;
private:
@ -82,10 +82,10 @@ private:
Common::SeekableReadStream *_stream;
typedef Common::HashMap<Common::String, FileEntry, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> FileMap;
typedef Common::HashMap<Common::Path, FileEntry, Common::Path::IgnoreCase_Hash, Common::Path::IgnoreCase_EqualTo> FileMap;
FileMap _map;
typedef Common::HashMap<Common::String, Common::MacFinderInfoData, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> MetadataMap;
typedef Common::HashMap<Common::Path, Common::MacFinderInfoData, Common::Path::IgnoreCase_Hash, Common::Path::IgnoreCase_EqualTo> MetadataMap;
MetadataMap _metadataMap;
bool _flattenTree;
@ -98,7 +98,7 @@ private:
void update14(uint16 first, uint16 last, byte *code, uint16 *freq) const;
void readTree14(Common::BitStream8LSB *bits, SIT14Data *dat, uint16 codesize, uint16 *result) const;
Common::SharedArchiveContents readContentsForPathFork(const String &translatedPath, bool isResFork) const;
Common::SharedArchiveContents readContentsForPathFork(const Common::Path &translatedPath, bool isResFork) const;
};
StuffItArchive::StuffItArchive() : Common::MemcachingCaseInsensitiveArchive(), _flattenTree(false) {
@ -117,7 +117,7 @@ static const uint32 s_magicNumbers[] = {
MKTAG('S', 'T', 'i', '3'), MKTAG('S', 'T', 'i', '4'), MKTAG('S', 'T', '4', '6')
};
bool StuffItArchive::open(const Common::String &filename, bool flattenTree) {
bool StuffItArchive::open(const Common::Path &filename, bool flattenTree) {
Common::SeekableReadStream *stream = SearchMan.createReadStreamForMember(filename);
return open(stream, flattenTree);
}
@ -237,12 +237,14 @@ bool StuffItArchive::open(Common::SeekableReadStream *stream, bool flattenTree)
if (!flattenTree)
name = dirPrefix + name;
_metadataMap[name] = finfo.toData();
Common::Path path(name, ':');
_metadataMap[path] = finfo.toData();
if (dataForkUncompressedSize != 0) {
// We have a data fork
FileEntryFork &entryFork = _map[name].dataFork;
FileEntryFork &entryFork = _map[path].dataFork;
entryFork.compression = dataForkCompression;
entryFork.uncompressedSize = dataForkUncompressedSize;
entryFork.compressedSize = dataForkCompressedSize;
@ -255,7 +257,7 @@ bool StuffItArchive::open(Common::SeekableReadStream *stream, bool flattenTree)
if (resForkUncompressedSize != 0) {
// We have a resource fork
FileEntryFork &entryFork = _map[name].resFork;
FileEntryFork &entryFork = _map[path].resFork;
entryFork.compression = resForkCompression;
entryFork.uncompressedSize = resForkUncompressedSize;
entryFork.compressedSize = resForkCompressedSize;
@ -279,8 +281,7 @@ void StuffItArchive::close() {
}
bool StuffItArchive::hasFile(const Common::Path &path) const {
Common::String name = path.toString(':');
return _map.contains(name);
return _map.contains(path);
}
int StuffItArchive::listMembers(Common::ArchiveMemberList &list) const {
@ -294,11 +295,11 @@ const Common::ArchiveMemberPtr StuffItArchive::getMember(const Common::Path &pat
return Common::ArchiveMemberPtr(new StuffItArchiveMember(path, *this));
}
Common::SharedArchiveContents StuffItArchive::readContentsForPath(const Common::String &name) const {
return readContentsForPathFork(name, false);
Common::SharedArchiveContents StuffItArchive::readContentsForPath(const Common::Path &path) const {
return readContentsForPathFork(path, false);
}
Common::SharedArchiveContents StuffItArchive::readContentsForPathAltStream(const String &translatedPath, Common::AltStreamType altStreamType) const {
Common::SharedArchiveContents StuffItArchive::readContentsForPathAltStream(const Common::Path &translatedPath, Common::AltStreamType altStreamType) const {
if (altStreamType == Common::AltStreamType::MacFinderInfo) {
if (_metadataMap.contains(translatedPath)) {
const Common::MacFinderInfoData &metadata = _metadataMap[translatedPath];
@ -315,13 +316,13 @@ Common::SharedArchiveContents StuffItArchive::readContentsForPathAltStream(const
return Common::SharedArchiveContents();
}
Common::SharedArchiveContents StuffItArchive::readContentsForPathFork(const Common::String &name, bool isResFork) const {
FileMap::const_iterator entryIt = _map.find(name);
Common::SharedArchiveContents StuffItArchive::readContentsForPathFork(const Common::Path &path, bool isResFork) const {
FileMap::const_iterator entryIt = _map.find(path);
if (entryIt == _map.end())
return Common::SharedArchiveContents();
const FileEntry &entry = _map[name];
const FileEntry &entry = entryIt->_value;
const FileEntryFork &entryFork = isResFork ? entry.resFork : entry.dataFork;
if (entryFork.uncompressedSize == 0) {
@ -358,14 +359,14 @@ Common::SharedArchiveContents StuffItArchive::readContentsForPathFork(const Comm
uint16 actualCRC = Common::CRC16().crcFast(uncompressedBlock, entryFork.uncompressedSize);
if (actualCRC != entryFork.crc) {
error("StuffItArchive::readContentsForPath(): CRC mismatch: %04x vs %04x for file %s %s fork", actualCRC, entryFork.crc, name.c_str(), (isResFork ? "res" : "data"));
error("StuffItArchive::readContentsForPath(): CRC mismatch: %04x vs %04x for file %s %s fork", actualCRC, entryFork.crc, path.toString().c_str(), (isResFork ? "res" : "data"));
}
return Common::SharedArchiveContents(uncompressedBlock, entryFork.uncompressedSize);
}
Common::String StuffItArchive::translatePath(const Common::Path &path) const {
return _flattenTree ? path.getLastComponent().toString() : path.toString(':');
Common::Path StuffItArchive::translatePath(const Common::Path &path) const {
return _flattenTree ? path.getLastComponent() : path;
}
char StuffItArchive::getPathSeparator() const {
@ -1133,7 +1134,7 @@ bool StuffItArchive::StuffItArchiveMember::isInMacArchive() const {
return true;
}
Common::Archive *createStuffItArchive(const Common::String &fileName, bool flattenTree) {
Common::Archive *createStuffItArchive(const Common::Path &fileName, bool flattenTree) {
StuffItArchive *archive = new StuffItArchive();
if (!archive->open(fileName, flattenTree)) {

View File

@ -43,7 +43,7 @@ namespace Common {
*/
class Archive;
class String;
class Path;
class SeekableReadStream;
/**
@ -55,7 +55,7 @@ class SeekableReadStream;
*
* @return The StuffIt archive
*/
Archive *createStuffItArchive(const String &fileName, bool flattenTree = false);
Archive *createStuffItArchive(const Path &fileName, bool flattenTree = false);
Archive *createStuffItArchive(SeekableReadStream *stream, bool flattenTree = false);
/** @} */

View File

@ -697,24 +697,24 @@ struct ArjFileChunk {
ArjFileChunk(ArjHeader* header, uint volume) : _header(header), _volume(volume) {}
};
typedef HashMap<String, Array<ArjFileChunk>, IgnoreCase_Hash, IgnoreCase_EqualTo> ArjHeadersMap;
typedef HashMap<Path, Array<ArjFileChunk>, Path::IgnoreCase_Hash, Path::IgnoreCase_EqualTo> ArjHeadersMap;
class ArjArchive : public MemcachingCaseInsensitiveArchive {
ArjHeadersMap _headers;
Array<String> _arjFilenames;
Array<Path> _arjFilenames;
bool _flattenTree;
public:
ArjArchive(const Array<String> &names, bool flattenTree);
ArjArchive(const Array<Path> &names, bool flattenTree);
virtual ~ArjArchive();
// Archive implementation
bool hasFile(const Path &path) const override;
int listMembers(ArchiveMemberList &list) const override;
const ArchiveMemberPtr getMember(const Path &path) const override;
Common::SharedArchiveContents readContentsForPath(const Common::String& translated) const override;
Common::String translatePath(const Common::Path &path) const override {
return _flattenTree ? path.getLastComponent().toString() : path.toString();
Common::SharedArchiveContents readContentsForPath(const Common::Path &translated) const override;
Common::Path translatePath(const Common::Path &path) const override {
return _flattenTree ? path.getLastComponent() : path;
}
};
@ -727,7 +727,7 @@ ArjArchive::~ArjArchive() {
}
}
ArjArchive::ArjArchive(const Array<String> &filenames, bool flattenTree) : _arjFilenames(filenames), _flattenTree(flattenTree) {
ArjArchive::ArjArchive(const Array<Path> &filenames, bool flattenTree) : _arjFilenames(filenames), _flattenTree(flattenTree) {
for (uint i = 0; i < _arjFilenames.size(); i++) {
File arjFile;
@ -753,21 +753,28 @@ ArjArchive::ArjArchive(const Array<String> &filenames, bool flattenTree) : _arjF
while ((header = readHeader(arjFile)) != nullptr) {
const char *name = header->filename;
if (_flattenTree)
for (const char *p = header->filename; *p; p++)
if (*p == '\\' || *p == '/')
if (_flattenTree) {
for (const char *p = header->filename; *p; p++) {
if (*p == '\\' || *p == '/') {
name = p + 1;
_headers[name].push_back(ArjFileChunk(header, i));
}
}
} else {
for (char *p = header->filename; *p; p++) {
if (*p == '\\')
*p = '/';
}
}
_headers[Path(name)].push_back(ArjFileChunk(header, i));
arjFile.seek(header->compSize, SEEK_CUR);
}
}
debug(0, "ArjArchive::ArjArchive(%d volume(s) starting with %s): Located %d files", filenames.size(), filenames.empty() ? "" : filenames[0].c_str(), _headers.size());
debug(0, "ArjArchive::ArjArchive(%d volume(s) starting with %s): Located %d files", filenames.size(), filenames.empty() ? "" : filenames[0].toString(Common::Path::kNativeSeparator).c_str(), _headers.size());
}
bool ArjArchive::hasFile(const Path &path) const {
String name = path.toString();
return _headers.contains(name);
return _headers.contains(path);
}
int ArjArchive::listMembers(ArchiveMemberList &list) const {
@ -775,7 +782,7 @@ int ArjArchive::listMembers(ArchiveMemberList &list) const {
ArjHeadersMap::const_iterator it = _headers.begin();
for ( ; it != _headers.end(); ++it) {
list.push_back(ArchiveMemberList::value_type(new GenericArchiveMember(Common::String(it->_value[0]._header->filename), *this)));
list.push_back(ArchiveMemberList::value_type(new GenericArchiveMember(Path(it->_value[0]._header->filename), *this)));
matches++;
}
@ -783,19 +790,18 @@ int ArjArchive::listMembers(ArchiveMemberList &list) const {
}
const ArchiveMemberPtr ArjArchive::getMember(const Path &path) const {
String name = path.toString();
if (!hasFile(name))
if (!hasFile(path))
return ArchiveMemberPtr();
return ArchiveMemberPtr(new GenericArchiveMember(name, *this));
return ArchiveMemberPtr(new GenericArchiveMember(path, *this));
}
Common::SharedArchiveContents ArjArchive::readContentsForPath(const Common::String& name) const {
if (!_headers.contains(name)) {
Common::SharedArchiveContents ArjArchive::readContentsForPath(const Common::Path &path) const {
if (!_headers.contains(path)) {
return Common::SharedArchiveContents();
}
const Array <ArjFileChunk>& hdrs = _headers[name];
const Array <ArjFileChunk>& hdrs = _headers[path];
uint64 uncompressedSize = 0;
uint totalChunks;
@ -848,11 +854,11 @@ Common::SharedArchiveContents ArjArchive::readContentsForPath(const Common::Stri
return Common::SharedArchiveContents(uncompressedData, uncompressedSize);
}
Archive *makeArjArchive(const String &name, bool flattenTree) {
Archive *makeArjArchive(const Path &name, bool flattenTree) {
return new ArjArchive({name}, flattenTree);
}
Archive *makeArjArchive(const Array<String> &names, bool flattenTree) {
Archive *makeArjArchive(const Array<Path> &names, bool flattenTree) {
return new ArjArchive(names, flattenTree);
}

View File

@ -49,12 +49,12 @@ class Archive;
*
* May return 0 in case of a failure.
*/
Archive *makeArjArchive(const String &name, bool flattenTree = false);
Archive *makeArjArchive(const Path &name, bool flattenTree = false);
/**
* Similar to previous but for multi-volume archives
*/
Archive *makeArjArchive(const Array<String> &names, bool flattenTree = false);
Archive *makeArjArchive(const Array<Path> &names, bool flattenTree = false);
/** @} */

View File

@ -318,8 +318,8 @@ typedef struct {
unz_file_info_internal cur_file_info_internal; /* private info about it*/
} cached_file_in_zip;
typedef Common::HashMap<Common::String, cached_file_in_zip, Common::IgnoreCase_Hash,
Common::IgnoreCase_EqualTo> ZipHash;
typedef Common::HashMap<Common::Path, cached_file_in_zip, Common::Path::IgnoreCase_Hash,
Common::Path::IgnoreCase_EqualTo> ZipHash;
/* unz_s contain internal information about the zipfile
*/
@ -535,12 +535,14 @@ unzFile unzOpen(Common::SeekableReadStream *stream, bool flattenTree) {
fe.cur_file_info = us->cur_file_info;
fe.cur_file_info_internal = us->cur_file_info_internal;
Common::String name(szCurrentFileName);
bool isDirectory = false;
if (name.hasSuffix("/") || name.hasSuffix("\\")) {
isDirectory = true;
name = name.substr(0, name.size() - 1);
if (*szCurrentFileName) {
char *szCurrentFileNameSuffix = szCurrentFileName + strlen(szCurrentFileName) - 1;
if (*szCurrentFileNameSuffix == '/' || *szCurrentFileNameSuffix == '\\') {
isDirectory = true;
// Strip trailing path terminator
*szCurrentFileNameSuffix = '\0';
}
}
// If platform is specified as MS-DOS or Unix, check the directory flag
@ -564,20 +566,21 @@ unzFile unzOpen(Common::SeekableReadStream *stream, bool flattenTree) {
}
}
const char *name = szCurrentFileName;
if (flattenTree) {
if (isDirectory)
continue;
size_t slashPos = name.findLastOf('\\');
if (slashPos != Common::String::npos)
name = name.substr(slashPos + 1);
slashPos = name.findLastOf('/');
if (slashPos != Common::String::npos)
name = name.substr(slashPos + 1);
for (const char *p = szCurrentFileName; *p; p++)
if (*p == '\\' || *p == '/')
name = p + 1;
} else {
for (char *p = szCurrentFileName; *p; p++)
if (*p == '\\')
*p = '/';
}
us->_hash[name] = fe;
us->_hash[Common::Path(name)] = fe;
// Move to the next file
err = unzGoToNextFile((unzFile)us);
@ -832,21 +835,18 @@ int unzGoToNextFile(unzFile file) {
UNZ_OK if the file is found. It becomes the current file.
UNZ_END_OF_LIST_OF_FILE if the file is not found
*/
int unzLocateFile(unzFile file, const char *szFileName, int iCaseSensitivity) {
int unzLocateFile(unzFile file, const Common::Path &szFileName, int iCaseSensitivity) {
unz_s *s;
if (file == nullptr)
return UNZ_PARAMERROR;
if (strlen(szFileName) >= UNZ_MAXFILENAMEINZIP)
return UNZ_PARAMERROR;
s=(unz_s *)file;
if (!s->current_file_ok)
return UNZ_END_OF_LIST_OF_FILE;
// Check to see if the entry exists
ZipHash::iterator i = s->_hash.find(Common::String(szFileName));
ZipHash::iterator i = s->_hash.find(szFileName);
if (i == s->_hash.end())
return UNZ_END_OF_LIST_OF_FILE;
@ -1039,9 +1039,9 @@ public:
bool isPathDirectory(const Path &path) const override;
int listMembers(ArchiveMemberList &list) const override;
const ArchiveMemberPtr getMember(const Path &path) const override;
Common::SharedArchiveContents readContentsForPath(const Common::String& translated) const override;
Common::String translatePath(const Common::Path &path) const override {
return _flattenTree ? path.getLastComponent().toString() : path.toString();
Common::SharedArchiveContents readContentsForPath(const Common::Path &translated) const override;
Common::Path translatePath(const Common::Path &path) const override {
return _flattenTree ? path.getLastComponent() : path;
}
};
@ -1072,14 +1072,11 @@ ZipArchive::~ZipArchive() {
}
bool ZipArchive::hasFile(const Path &path) const {
String name = path.toString();
return (unzLocateFile(_zipFile, name.c_str(), 2) == UNZ_OK);
return (unzLocateFile(_zipFile, path, 2) == UNZ_OK);
}
bool ZipArchive::isPathDirectory(const Path &path) const {
String name = path.toString();
if (unzLocateFile(_zipFile, name.c_str(), 2) != UNZ_OK)
if (unzLocateFile(_zipFile, path, 2) != UNZ_OK)
return false;
unz_file_info fi;
@ -1103,15 +1100,14 @@ int ZipArchive::listMembers(ArchiveMemberList &list) const {
}
const ArchiveMemberPtr ZipArchive::getMember(const Path &path) const {
String name = path.toString();
if (!hasFile(name))
if (!hasFile(path))
return ArchiveMemberPtr();
return ArchiveMemberPtr(new GenericArchiveMember(path, *this));
}
Common::SharedArchiveContents ZipArchive::readContentsForPath(const Common::String& name) const {
if (unzLocateFile(_zipFile, name.c_str(), 2) != UNZ_OK)
Common::SharedArchiveContents ZipArchive::readContentsForPath(const Common::Path &path) const {
if (unzLocateFile(_zipFile, path, 2) != UNZ_OK)
return Common::SharedArchiveContents();
#ifndef USE_ZLIB
return unzOpenCurrentFile(_zipFile, _crc);
@ -1120,7 +1116,7 @@ Common::SharedArchiveContents ZipArchive::readContentsForPath(const Common::Stri
#endif
}
Archive *makeZipArchive(const String &name, bool flattenTree) {
Archive *makeZipArchive(const Path &name, bool flattenTree) {
return makeZipArchive(SearchMan.createReadStreamForMember(name), flattenTree);
}

View File

@ -45,7 +45,7 @@ class SeekableReadStream;
*
* May return 0 in case of a failure.
*/
Archive *makeZipArchive(const String &name, bool flattenTree = false);
Archive *makeZipArchive(const Path &name, bool flattenTree = false);
/**
* This factory method creates an Archive instance corresponding to the content

View File

@ -351,7 +351,7 @@ void ProDOSDisk::getVolumeBitmap(VolHeader *h) {
/* Gets the volume information and parses the filesystem, adding file objects to a map as it goes */
bool ProDOSDisk::open(const Common::String filename) {
bool ProDOSDisk::open(const Common::Path &filename) {
_disk.open(filename);
_disk.read(_loader1, kBlockSize);
_disk.read(_loader2, kBlockSize);
@ -371,7 +371,7 @@ bool ProDOSDisk::open(const Common::String filename) {
/* Constructor simply calls open(), and if it is successful it prints a statement */
ProDOSDisk::ProDOSDisk(const Common::String filename) {
ProDOSDisk::ProDOSDisk(const Common::Path &filename) {
if (open(filename)) {
//debug("%s has been loaded", filename.c_str());
}

View File

@ -116,11 +116,11 @@ class ProDOSDisk : public Common::Archive {
public:
static const int kBlockSize = 512; // A ProDOS block is always 512 bytes (should this be an enum?)
ProDOSDisk(const Common::String filename);
ProDOSDisk(const Common::Path &filename);
~ProDOSDisk(); // Frees the memory used in the dictionary and the volume bitmap
// Called from the constructor, it parses the volume and fills the hashmap with files
bool open(const Common::String filename);
bool open(const Common::Path &filename);
// These are the Common::Archive related methods
bool hasFile(const Common::Path &path) const override;

View File

@ -82,7 +82,7 @@ String WinResourceID::toString() const {
return "";
}
bool WinResources::loadFromEXE(const String &fileName) {
bool WinResources::loadFromEXE(const Path &fileName) {
if (fileName.empty())
return false;
@ -96,7 +96,7 @@ bool WinResources::loadFromEXE(const String &fileName) {
return loadFromEXE(file);
}
bool WinResources::loadFromCompressedEXE(const String &fileName) {
bool WinResources::loadFromCompressedEXE(const Path &fileName) {
// Based on http://www.cabextract.org.uk/libmspack/doc/szdd_kwaj_format.html
// TODO: Merge this with with loadFromEXE() so the handling of the compressed
@ -172,7 +172,7 @@ bool WinResources::loadFromCompressedEXE(const String &fileName) {
}
WinResources *WinResources::createFromEXE(const String &fileName) {
WinResources *WinResources::createFromEXE(const Path &fileName) {
WinResources *exe;
// First try loading via the NE code

View File

@ -37,6 +37,7 @@ namespace Common {
* @{
*/
class Path;
class SeekableReadStream;
/** The default Windows resources. */
@ -114,10 +115,10 @@ public:
virtual void clear() = 0;
/** Load from an EXE file. */
virtual bool loadFromEXE(const String &fileName);
virtual bool loadFromEXE(const Path &fileName);
/** Load from a Windows compressed EXE file. */
virtual bool loadFromCompressedEXE(const String &fileName);
virtual bool loadFromCompressedEXE(const Path &fileName);
/** Load from a stream. */
virtual bool loadFromEXE(SeekableReadStream *stream, DisposeAfterUse::Flag disposeFileHandle = DisposeAfterUse::YES) = 0;
@ -139,7 +140,7 @@ public:
return getResource(type, id);
}
static WinResources *createFromEXE(const String &fileName);
static WinResources *createFromEXE(const Path &fileName);
static WinResources *createFromEXE(SeekableReadStream *stream);
typedef Common::HashMap<Common::String, Common::U32String, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> VersionHash;

View File

@ -41,7 +41,7 @@ XMLParser::~XMLParser() {
_layoutList.clear();
}
bool XMLParser::loadFile(const String &filename) {
bool XMLParser::loadFile(const Path &filename) {
_stream = SearchMan.createReadStreamForMember(filename);
if (!_stream)
return false;
@ -96,7 +96,7 @@ bool XMLParser::parserError(const String &errStr) {
assert(_stream->pos() == startPosition);
currentPosition = startPosition;
Common::String errorMessage = Common::String::format("\n File <%s>, line %d:\n", _fileName.c_str(), lineCount);
Common::String errorMessage = Common::String::format("\n File <%s>, line %d:\n", _fileName.toString().c_str(), lineCount);
if (startPosition > 1) {
int keyOpening = 0;

View File

@ -168,7 +168,7 @@ public:
*
* @param filename Name of the file to load.
*/
bool loadFile(const String &filename);
bool loadFile(const Path &filename);
bool loadFile(const FSNode &node);
@ -377,7 +377,7 @@ private:
char _char;
bool _allowText; /** Allow text nodes in the doc (default false) */
SeekableReadStream *_stream;
String _fileName;
Path _fileName;
ParserState _state; /** Internal state of the parser */

View File

@ -29,7 +29,7 @@ LuaFileProxy *LuaFileProxy::create(const Common::String &filename, const Common:
if (filename.contains("config.lua"))
return new LuaFileConfig(filename, mode);
return new LuaFileRead(filename, mode);
return new LuaFileRead(Common::Path(filename, '/'), mode);
}
LuaFileConfig::LuaFileConfig(const Common::String &filename, const Common::String &mode) : _readPos(0) {
@ -235,10 +235,10 @@ void LuaFileConfig::setLanguage(const Common::String &lang) {
}
LuaFileRead::LuaFileRead(const Common::String &filename, const Common::String &mode) {
LuaFileRead::LuaFileRead(const Common::Path &filename, const Common::String &mode) {
assert(mode == "r");
if (!_file.open(filename))
error("Could not open file %s", filename.c_str());
error("Could not open file %s", filename.toString().c_str());
_size = _file.size();
}

View File

@ -69,7 +69,7 @@ private:
Common::File _file;
int32 _size;
public:
LuaFileRead(const Common::String &filename, const Common::String &mode);
LuaFileRead(const Common::Path &filename, const Common::String &mode);
public:
virtual ~LuaFileRead() {}

View File

@ -177,7 +177,7 @@ SeekableReadStream *MacResManager::openAppleDoubleWithAppleOrOSXNaming(Archive&
const Common::FSNode *plainFsNode = dynamic_cast<const Common::FSNode *>(archiveMember.get());
// Try finding __MACOSX
Common::StringArray components = (plainFsNode ? Common::Path(plainFsNode->getPath(), '/') : fileName).splitComponents();
Common::StringArray components = (plainFsNode ? plainFsNode->getPath() : fileName).splitComponents();
if (components.empty() || components[components.size() - 1].empty())
return nullptr;
for (int i = components.size() - 1; i >= 0; i--) {
@ -512,20 +512,20 @@ bool MacResManager::getFileFinderInfo(const Path &fileName, MacFinderInfo &outFi
return getFileFinderInfo(fileName, SearchMan, outFinderInfo, outFinderExtendedInfo);
}
void MacResManager::listFiles(StringArray &files, const String &pattern) {
void MacResManager::listFiles(Array<Path> &files, const Path &pattern) {
// Base names discovered so far.
typedef HashMap<String, bool, IgnoreCase_Hash, IgnoreCase_EqualTo> BaseNameSet;
typedef HashMap<Path, bool, Path::IgnoreCase_Hash, Path::IgnoreCase_EqualTo> BaseNameSet;
BaseNameSet baseNames;
// List files itself.
ArchiveMemberList memberList;
SearchMan.listMatchingMembers(memberList, pattern);
SearchMan.listMatchingMembers(memberList, pattern + ".rsrc");
SearchMan.listMatchingMembers(memberList, pattern + ".bin");
SearchMan.listMatchingMembers(memberList, pattern.append(".rsrc"));
SearchMan.listMatchingMembers(memberList, pattern.append(".bin"));
SearchMan.listMatchingMembers(memberList, constructAppleDoubleName(pattern));
for (ArchiveMemberList::const_iterator i = memberList.begin(), end = memberList.end(); i != end; ++i) {
String filename = (*i)->getName();
String filename = (*i)->getFileName();
// For raw resource forks and MacBinary files we strip the extension
// here to obtain a valid base name.
@ -560,12 +560,13 @@ void MacResManager::listFiles(StringArray &files, const String &pattern) {
// Strip AppleDouble '._' prefix if applicable.
bool isAppleDoubleName = false;
const String filenameAppleDoubleStripped = disassembleAppleDoubleName(filename, &isAppleDoubleName).toString();
const Path filenameAppleDoubleStripped = disassembleAppleDoubleName(
Common::Path(filename, Common::Path::kNoSeparator), &isAppleDoubleName);
if (isAppleDoubleName) {
SeekableReadStream *stream = (*i)->createReadStream();
if (stream->readUint32BE() == 0x00051607) {
filename = filenameAppleDoubleStripped;
filename = filenameAppleDoubleStripped.baseName();
}
// TODO: Should we really keep filenames suggesting AppleDouble
// but not being AppleDouble around? This might depend on the
@ -573,7 +574,8 @@ void MacResManager::listFiles(StringArray &files, const String &pattern) {
delete stream;
}
baseNames[filename] = true;
Common::Path basePath((*i)->getPathInArchive().getParent().appendComponent(filename));
baseNames[basePath] = true;
}
// Append resulting base names to list to indicate found files.
@ -1011,25 +1013,28 @@ void MacResManager::readMap() {
}
}
Path MacResManager::constructAppleDoubleName(Path name) {
Path MacResManager::constructAppleDoubleName(const Path &name) {
// Insert "._" before the last portion of a path name
Path parent = name.getParent();
Path ret = name.getParent();
Path lastComponent = name.getLastComponent();
return parent.append("._").append(lastComponent);
return ret.appendInPlace("._").appendInPlace(lastComponent);
}
Path MacResManager::disassembleAppleDoubleName(Path name, bool *isAppleDouble) {
Path MacResManager::disassembleAppleDoubleName(const Path &name, bool *isAppleDouble) {
if (isAppleDouble) {
*isAppleDouble = false;
}
// Remove "._" before the last portion of a path name.
Path parent = name.getParent();
Path lastComponent = name.getLastComponent();
String lastComponentString = lastComponent.toString();
if (!lastComponentString.hasPrefix("._"))
Path ret = name.getParent();
String lastComponent = name.baseName();
if (!lastComponent.hasPrefix("._"))
return name;
return parent.appendComponent(lastComponentString.substr(2));
ret = ret.appendComponent(lastComponent.substr(2));
if (name.isSeparatorTerminated()) {
ret.appendInPlace("/");
}
return ret;
}
void MacResManager::dumpRaw() {
@ -1048,10 +1053,10 @@ void MacResManager::dumpRaw() {
dataSize = len;
}
Common::String filename = Common::String::format("./dumps/%s-%s-%d", _baseFileName.toString().c_str(), tag2str(_resTypes[i].id), j);
Common::String filename = Common::String::format("./dumps/%s-%s-%d", _baseFileName.baseName().c_str(), tag2str(_resTypes[i].id), j);
_stream->read(data, len);
if (!out.open(filename)) {
if (!out.open(Common::Path(filename, '/'))) {
warning("MacResManager::dumpRaw(): Can not open dump file %s", filename.c_str());
return;
}

View File

@ -193,7 +193,7 @@ public:
* @param pattern Pattern to match against. Taking String::matchPattern's
* format.
*/
static void listFiles(StringArray &files, const String &pattern);
static void listFiles(Array<Path> &files, const Path &pattern);
/**
* Close the Mac data/resource fork pair.
@ -321,8 +321,8 @@ private:
static bool readAndValidateMacBinaryHeader(SeekableReadStream &stream, byte (&outMacBinaryHeader)[MBI_INFOHDR]);
static Path constructAppleDoubleName(Path name);
static Path disassembleAppleDoubleName(Path name, bool *isAppleDouble);
static Path constructAppleDoubleName(const Path &name);
static Path disassembleAppleDoubleName(const Path &name, bool *isAppleDouble);
static SeekableReadStream *openAppleDoubleWithAppleOrOSXNaming(Archive& archive, const Path &fileName);

View File

@ -227,7 +227,7 @@ bool TranslationManager::openTranslationsFile(File &inFile) {
// Then try to open it using the SearchMan.
ArchiveMemberList fileList;
SearchMan.listMatchingMembers(fileList, _translationsFileName);
SearchMan.listMatchingMembers(fileList, Common::Path(_translationsFileName, Common::Path::kNoSeparator));
for (ArchiveMemberList::iterator it = fileList.begin(); it != fileList.end(); ++it) {
ArchiveMember const &m = **it;
SeekableReadStream *const stream = m.createReadStream();

View File

@ -59,7 +59,7 @@ RNCAArchive* RNCAArchive::open(Common::SeekableReadStream *stream, DisposeAfterU
ptr++;
uint32 off = READ_BE_UINT32(ptr);
eptr = ptr + 4;
files[fileName] = RNCAFileDescriptor(fileName, off);
files[Common::Path(fileName, Common::Path::kNoSeparator)] = RNCAFileDescriptor(fileName, off);
}
delete[] metadata;
@ -80,14 +80,14 @@ int RNCAArchive::listMembers(Common::ArchiveMemberList &list) const {
}
const Common::ArchiveMemberPtr RNCAArchive::getMember(const Common::Path &path) const {
Common::String translated = translatePath(path);
Common::Path translated = translatePath(path);
if (!_files.contains(translated))
return nullptr;
return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(_files.getVal(translated)._fileName, *this));
}
Common::SharedArchiveContents RNCAArchive::readContentsForPath(const Common::String& translated) const {
Common::SharedArchiveContents RNCAArchive::readContentsForPath(const Common::Path &translated) const {
if (!_files.contains(translated))
return Common::SharedArchiveContents();
const RNCAFileDescriptor& desc = _files.getVal(translated);

View File

@ -34,7 +34,7 @@ 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::SharedArchiveContents readContentsForPath(const Common::String& translated) const override;
Common::SharedArchiveContents readContentsForPath(const Common::Path &translated) const override;
static RNCAArchive* open(Common::SeekableReadStream *stream, DisposeAfterUse::Flag dispose = DisposeAfterUse::NO);
@ -53,7 +53,7 @@ private:
RNCAFileDescriptor() : _fileDataOffset(0) {}
};
typedef Common::HashMap<Common::String, RNCAFileDescriptor, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> FileMap;
typedef Common::HashMap<Common::Path, RNCAFileDescriptor, Common::Path::IgnoreCase_Hash, Common::Path::IgnoreCase_EqualTo> FileMap;
RNCAArchive(FileMap files, Common::SeekableReadStream *stream, DisposeAfterUse::Flag dispose)
: _files(files), _stream(stream, dispose) {

View File

@ -76,14 +76,14 @@ int MpsInstaller::listMembers(Common::ArchiveMemberList &list) const {
}
const Common::ArchiveMemberPtr MpsInstaller::getMember(const Common::Path &path) const {
Common::String translated = translatePath(path);
Common::Path translated = translatePath(path);
if (!_files.contains(translated))
return nullptr;
return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(_files.getVal(translated)._fileName, *this));
}
Common::SharedArchiveContents MpsInstaller::readContentsForPath(const Common::String& translated) const {
Common::SharedArchiveContents MpsInstaller::readContentsForPath(const Common::Path &translated) const {
if (!_files.contains(translated))
return Common::SharedArchiveContents();
FileDescriptor desc = _files.getVal(translated);

View File

@ -33,11 +33,11 @@ namespace MADS {
class MpsInstaller : public Common::MemcachingCaseInsensitiveArchive {
public:
bool hasFile(const Common::Path &path) const override;
int listMembers(Common::ArchiveMemberList&) const override;
int listMembers(Common::ArchiveMemberList &) const override;
const Common::ArchiveMemberPtr getMember(const Common::Path &path) const override;
Common::SharedArchiveContents readContentsForPath(const Common::String& translatedPath) const override;
Common::SharedArchiveContents readContentsForPath(const Common::Path &translatedPath) const override;
static MpsInstaller* open(const Common::Path& baseName);
static MpsInstaller* open(const Common::Path &baseName);
private:
// Similar to FileDescriptionBin but in native-endian and native strings.
@ -73,7 +73,7 @@ private:
friend class MpsInstaller;
};
typedef Common::HashMap<Common::String, FileDescriptor, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> FileMap;
typedef Common::HashMap<Common::Path, FileDescriptor, Common::Path::IgnoreCase_Hash, Common::Path::IgnoreCase_EqualTo> FileMap;
MpsInstaller(const FileMap& files,
const Common::Path& baseName) : _files(files), _baseName(baseName) {}

View File

@ -349,12 +349,12 @@ Common::Error SagaEngine::run() {
setTotalPlayTime(0);
if (getFeatures() & GF_INSTALLER) {
Common::Array<Common::String> filenames;
Common::Array<Common::Path> filenames;
for (const ADGameFileDescription *gameArchiveDescription = getArchivesDescriptions();
gameArchiveDescription->fileName; gameArchiveDescription++)
filenames.push_back(gameArchiveDescription->fileName);
Common::Archive *archive = nullptr;
if (filenames.size() == 1 && filenames[0].hasSuffix(".exe"))
if (filenames.size() == 1 && filenames[0].baseName().hasSuffix(".exe"))
archive = Common::makeZipArchive(filenames[0], true);
else
archive = Common::makeArjArchive(filenames, true);

View File

@ -655,12 +655,13 @@ int ResourceManager::addAppropriateSources() {
#endif
} else if (Common::MacResManager::exists("Data1")) {
// Mac SCI1.1+ file naming scheme
Common::StringArray files;
Common::Array<Common::Path> files;
Common::MacResManager::listFiles(files, "Data#");
Common::MacResManager::listFiles(files, "Data##");
for (Common::StringArray::const_iterator x = files.begin(); x != files.end(); ++x) {
addSource(new MacResourceForkResourceSource(*x, atoi(x->c_str() + 4)));
for (Common::Array<Common::Path>::const_iterator x = files.begin(); x != files.end(); ++x) {
Common::String path(x->toString());
addSource(new MacResourceForkResourceSource(path, atoi(path.c_str() + 4)));
}
#ifdef ENABLE_SCI32