[Scummvm-git-logs] scummvm master -> e0b8e6685e1e317bcced3678db7160dda763f636
sev-
noreply at scummvm.org
Sun Sep 17 17:17:38 UTC 2023
This automated email contains information about 5 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
79e06f899a COMMON: Fix String::matchString matching excluded characters with trailing asterisk wildcards
1155eb7894 COMMON: Add isPathDirectory to Archive, and isDirectory and listChildren to ArchiveMember
b93d803f3e COMMON: Add isDirectory and listChildren to FSNode and FSDirectoryFile
63b01f5e85 COMMON: Strip trailing slashes from ZipArchive directories and improve directory detection. Add support for listChildre
e0b8e6685e SWORD25: Fix extracted files support and update ZipArchive handling to process directories
Commit: 79e06f899ad26bf66a6902a41212fefafa73d379
https://github.com/scummvm/scummvm/commit/79e06f899ad26bf66a6902a41212fefafa73d379
Author: elasota (ejlasota at gmail.com)
Date: 2023-09-17T19:17:33+02:00
Commit Message:
COMMON: Fix String::matchString matching excluded characters with trailing asterisk wildcards
Changed paths:
common/str.cpp
diff --git a/common/str.cpp b/common/str.cpp
index 9994f209b32..193e5b3ed16 100644
--- a/common/str.cpp
+++ b/common/str.cpp
@@ -638,6 +638,7 @@ bool matchString(const char *str, const char *pat, bool ignoreCase, const char *
const char *p = nullptr;
const char *q = nullptr;
bool escaped = false;
+ bool noExclusions = (wildcardExclusions == nullptr || !*wildcardExclusions);
for (;;) {
if (wildcardExclusions && strchr(wildcardExclusions, *str)) {
@@ -662,8 +663,8 @@ bool matchString(const char *str, const char *pat, bool ignoreCase, const char *
p = nullptr;
q = nullptr;
}
- // If pattern ended with * -> match
- if (!*pat)
+ // If pattern ended with * and there are no exclusions -> match
+ if (!*pat && noExclusions)
return true;
break;
Commit: 1155eb789430f68b84f92c615422bf7b74ba7cd8
https://github.com/scummvm/scummvm/commit/1155eb789430f68b84f92c615422bf7b74ba7cd8
Author: elasota (ejlasota at gmail.com)
Date: 2023-09-17T19:17:33+02:00
Commit Message:
COMMON: Add isPathDirectory to Archive, and isDirectory and listChildren to ArchiveMember
Changed paths:
common/archive.cpp
common/archive.h
diff --git a/common/archive.cpp b/common/archive.cpp
index e882cd88d4a..db189daf2a6 100644
--- a/common/archive.cpp
+++ b/common/archive.cpp
@@ -30,6 +30,20 @@
namespace Common {
+ArchiveMember::~ArchiveMember() {
+}
+
+U32String ArchiveMember::getDisplayName() const {
+ return getName();
+}
+
+bool ArchiveMember::isDirectory() const {
+ return false;
+}
+
+void ArchiveMember::listChildren(ArchiveMemberList &childList, const char *pattern) const {
+}
+
GenericArchiveMember::GenericArchiveMember(const String &pathStr, const Archive &parent)
: _parent(parent), _path(pathStr, parent.getPathSeparator()) {
}
@@ -58,6 +72,23 @@ SeekableReadStream *GenericArchiveMember::createReadStreamForAltStream(AltStream
return _parent.createReadStreamForMemberAltStream(_path, altStreamType);
}
+bool GenericArchiveMember::isDirectory() const {
+ return _parent.isPathDirectory(_path);
+}
+
+void GenericArchiveMember::listChildren(ArchiveMemberList &childList, const char *pattern) const {
+ if (!pattern)
+ pattern = "*";
+
+ Common::Path searchPath = _path.appendComponent(pattern);
+
+ _parent.listMatchingMembers(childList, searchPath);
+}
+
+bool Archive::isPathDirectory(const Path &path) const {
+ return false;
+}
+
int Archive::listMatchingMembers(ArchiveMemberList &list, const Path &pattern, bool matchPathComponents) const {
// Get all "names" (TODO: "files" ?)
ArchiveMemberList allNames;
@@ -384,6 +415,29 @@ bool SearchSet::hasFile(const Path &path) const {
return false;
}
+bool SearchSet::isPathDirectory(const Path &path) const {
+ if (path.empty())
+ return false;
+
+ ArchiveNodeList::const_iterator it = _list.begin();
+ for (; it != _list.end(); ++it) {
+ if (it->_arc->isPathDirectory(path)) {
+ // See if an earlier archive contains the same path as a non-directory file.
+ // If this is the case, then we want to return false here because getMember will return
+ // that file. This is a bit faster than hasFile for each archive first.
+ while (it != _list.begin()) {
+ --it;
+ if (it->_arc->hasFile(path))
+ return false;
+ }
+
+ return true;
+ }
+ }
+
+ return false;
+}
+
int SearchSet::listMatchingMembers(ArchiveMemberList &list, const Path &pattern, bool matchPathComponents) const {
int matches = 0;
diff --git a/common/archive.h b/common/archive.h
index 6624c73ad71..aeae4e98265 100644
--- a/common/archive.h
+++ b/common/archive.h
@@ -43,6 +43,7 @@ namespace Common {
* @{
*/
+class ArchiveMember;
class FSNode;
class SeekableReadStream;
@@ -53,6 +54,8 @@ enum class AltStreamType {
MacResourceFork,
};
+typedef SharedPtr<ArchiveMember> ArchiveMemberPtr; /*!< Shared pointer to an archive member. */
+typedef List<ArchiveMemberPtr> ArchiveMemberList; /*!< List of archive members. */
/**
* The ArchiveMember class is an abstract interface to represent elements inside
@@ -64,7 +67,7 @@ enum class AltStreamType {
*/
class ArchiveMember {
public:
- virtual ~ArchiveMember() { }
+ virtual ~ArchiveMember();
virtual SeekableReadStream *createReadStream() const = 0; /*!< Create a read stream. */
virtual SeekableReadStream *createReadStreamForAltStream(AltStreamType altStreamType) const = 0; /*!< Create a read stream of an alternate stream. */
@@ -76,12 +79,11 @@ public:
virtual Path getPathInArchive() const = 0; /*!< Get the full path of the archive member relative to the containing archive root. */
virtual String getFileName() const = 0; /*!< Get the file name of the archive member relative to its containing directory within the archive. */
- virtual U32String getDisplayName() const { return getName(); } /*!< Get the display name of the archive member. */
+ virtual bool isDirectory() const; /*!< Checks if the ArchiveMember is a directory. */
+ virtual void listChildren(ArchiveMemberList &childList, const char *pattern = nullptr) const; /*!< Adds the immediate children of this archive member to childList, optionally matching a pattern. */
+ virtual U32String getDisplayName() const; /*!< Get the display name of the archive member. */
};
-typedef SharedPtr<ArchiveMember> ArchiveMemberPtr; /*!< Shared pointer to an archive member. */
-typedef List<ArchiveMemberPtr> ArchiveMemberList; /*!< List of archive members. */
-
struct ArchiveMemberDetails {
ArchiveMemberPtr arcMember;
Common::String arcName;
@@ -121,6 +123,8 @@ public:
String getFileName() const override; /*!< Get the file name of the archive member relative to its containing directory within the archive. */
SeekableReadStream *createReadStream() const override; /*!< Create a read stream. */
SeekableReadStream *createReadStreamForAltStream(AltStreamType altStreamType) const override; /*!< Create a read stream of an alternate stream. */
+ bool isDirectory() const override;
+ void listChildren(ArchiveMemberList &childList, const char *pattern) const override;
private:
const Archive &_parent;
@@ -140,10 +144,15 @@ public:
/**
* Check if a member with the given @p name is present in the Archive.
* Patterns are not allowed, as this is meant to be a quick File::exists()
- * replacement.
+ * replacement. This returns "true" for both files and directories.
*/
virtual bool hasFile(const Path &path) const = 0;
+ /**
+ * Check if a member with the given @p name exists and is a directory.
+ */
+ virtual bool isPathDirectory(const Path &path) const;
+
/**
* Add all members of the Archive matching the specified pattern to the list.
* Must only append to list, and not remove elements from it.
@@ -410,6 +419,7 @@ public:
void setPriority(const String& name, int priority);
bool hasFile(const Path &path) const override;
+ bool isPathDirectory(const Path &path) const override;
int listMatchingMembers(ArchiveMemberList &list, const Path &pattern, bool matchPathComponents = false) const override;
int listMatchingMembers(ArchiveMemberDetailsList &list, const Path &pattern, bool matchPathComponents = false) const;
int listMembers(ArchiveMemberList &list) const override;
Commit: b93d803f3e64e05bc07c52abd3e7de264272e918
https://github.com/scummvm/scummvm/commit/b93d803f3e64e05bc07c52abd3e7de264272e918
Author: elasota (ejlasota at gmail.com)
Date: 2023-09-17T19:17:33+02:00
Commit Message:
COMMON: Add isDirectory and listChildren to FSNode and FSDirectoryFile
Changed paths:
common/fs.cpp
common/fs.h
diff --git a/common/fs.cpp b/common/fs.cpp
index 42ab5f7b1be..936d5b46324 100644
--- a/common/fs.cpp
+++ b/common/fs.cpp
@@ -38,13 +38,16 @@ public:
Path getPathInArchive() const override;
String getFileName() const override;
U32String getDisplayName() const override;
+ bool isDirectory() const override;
+ void listChildren(ArchiveMemberList &list, const char *pattern) const override;
private:
Common::Path _pathInDirectory;
FSNode _fsNode;
};
-FSDirectoryFile::FSDirectoryFile(const Common::Path &pathInDirectory, const FSNode &fsNode) : _pathInDirectory(pathInDirectory), _fsNode(fsNode) {
+FSDirectoryFile::FSDirectoryFile(const Common::Path &pathInDirectory, const FSNode &fsNode)
+ : _pathInDirectory(pathInDirectory), _fsNode(fsNode) {
}
SeekableReadStream *FSDirectoryFile::createReadStream() const {
@@ -71,6 +74,30 @@ U32String FSDirectoryFile::getDisplayName() const {
return _fsNode.getDisplayName();
}
+bool FSDirectoryFile::isDirectory() const {
+ return _fsNode.isDirectory();
+}
+
+void FSDirectoryFile::listChildren(ArchiveMemberList &list, const char *pattern) const {
+ // We don't check for includeDirectories in the parent archive to determine the list mode here because it is implicit,
+ // i.e. if includeDirectories was set false, then this file isn't a directory in the first place.
+
+ FSList fsList;
+ if (!_fsNode.getChildren(fsList, FSNode::kListAll))
+ return;
+
+ for (const FSNode &fsNode : fsList) {
+ Common::String fileName = fsNode.getName();
+
+ if (pattern != nullptr && !fileName.matchString(pattern, true))
+ continue;
+
+ Common::Path subPath = _pathInDirectory.appendComponent(fileName);
+
+ list.push_back(ArchiveMemberPtr(new FSDirectoryFile(subPath, fsNode)));
+ }
+}
+
FSNode::FSNode() {
}
@@ -79,6 +106,9 @@ FSNode::FSNode(AbstractFSNode *realNode)
: _realNode(realNode) {
}
+FSNode::~FSNode() {
+}
+
FSNode::FSNode(const Path &p) {
assert(g_system);
FilesystemFactory *factory = g_system->getFilesystemFactory();
@@ -176,6 +206,19 @@ bool FSNode::isDirectory() const {
return _realNode && _realNode->isDirectory();
}
+void FSNode::listChildren(ArchiveMemberList &childList, const char *pattern) const {
+ Common::FSList fsList;
+ if (!getChildren(fsList, Common::FSNode::kListAll))
+ return;
+
+ for (const Common::FSNode &fsNode : fsList) {
+ if (pattern != nullptr && !fsNode.getName().matchString(pattern))
+ continue;
+
+ childList.push_back(ArchiveMemberPtr(new FSNode(fsNode)));
+ }
+}
+
bool FSNode::isReadable() const {
return _realNode && _realNode->isReadable();
}
@@ -299,6 +342,14 @@ bool FSDirectory::hasFile(const Path &path) const {
return node && node->exists();
}
+bool FSDirectory::isPathDirectory(const Path &path) const {
+ if (path.toString().empty() || !_node.isDirectory())
+ return false;
+
+ FSNode *node = lookupCache(_fileCache, path);
+ return node && node->isDirectory();
+}
+
const ArchiveMemberPtr FSDirectory::getMember(const Path &path) const {
if (path.toString().empty() || !_node.isDirectory())
return ArchiveMemberPtr();
diff --git a/common/fs.h b/common/fs.h
index 6fa54266f2a..8581230e032 100644
--- a/common/fs.h
+++ b/common/fs.h
@@ -106,8 +106,7 @@ public:
* used (usually the root directory).
*/
explicit FSNode(const Path &path);
-
- virtual ~FSNode() {}
+ ~FSNode();
/**
* Compare the name of this node to the name of another. Directories
@@ -223,7 +222,13 @@ public:
* Or even replace isDirectory by a getType() method that can return values like
* kDirNodeType, kFileNodeType, kInvalidNodeType.
*/
- bool isDirectory() const;
+ bool isDirectory() const override;
+
+ /**
+ * Adds the immediate children of this FSNode to a list, optionally matching a pattern.
+ * Has no effect if this FSNode is not a directory.
+ */
+ void listChildren(Common::ArchiveMemberList &childList, const char *pattern = nullptr) const override;
/**
* Indicate whether the object referred by this node can be read from or not.
@@ -258,7 +263,7 @@ public:
*
* @return Pointer to the stream object, nullptr in case of a failure.
*/
- SeekableReadStream *createReadStream() const override;
+ SeekableReadStream *createReadStream() const;
/**
* Create a SeekableReadStream instance corresponding to an alternate stream
@@ -268,7 +273,7 @@ public:
*
* @return Pointer to the stream object, nullptr in case of a failure.
*/
- SeekableReadStream *createReadStreamForAltStream(AltStreamType altStreamType) const override;
+ SeekableReadStream *createReadStreamForAltStream(AltStreamType altStreamType) const;
/**
* Create a WriteStream instance corresponding to the file
@@ -410,6 +415,11 @@ public:
*/
bool hasFile(const Path &path) const override;
+ /**
+ * Check if a specified subpath is a directory.
+ */
+ bool isPathDirectory(const Path &path) const override;
+
/**
* Return a list of matching file names. Pattern can use GLOB wildcards.
*/
Commit: 63b01f5e85771909a9b3144ed5723945854bde76
https://github.com/scummvm/scummvm/commit/63b01f5e85771909a9b3144ed5723945854bde76
Author: elasota (ejlasota at gmail.com)
Date: 2023-09-17T19:17:33+02:00
Commit Message:
COMMON: Strip trailing slashes from ZipArchive directories and improve directory detection. Add support for listChildren and isDirectory.
Changed paths:
common/compression/unzip.cpp
diff --git a/common/compression/unzip.cpp b/common/compression/unzip.cpp
index cc5027a4dd3..df49edcca57 100644
--- a/common/compression/unzip.cpp
+++ b/common/compression/unzip.cpp
@@ -535,14 +535,49 @@ 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;
- const char *name = szCurrentFileName;
+ Common::String name(szCurrentFileName);
- if (flattenTree)
- for (const char *p = szCurrentFileName; *p; p++)
- if (*p == '\\' || *p == '/')
- name = p + 1;
+ bool isDirectory = false;
+ if (name.hasSuffix("/") || name.hasSuffix("\\")) {
+ isDirectory = true;
+ name = name.substr(0, name.size() - 1);
+ }
+
+ // If platform is specified as MS-DOS or Unix, check the directory flag
+ if (!isDirectory) {
+ int platform = (us->cur_file_info.version >> 8) & 0xff;
+ switch (platform) {
+ case 1: // Amiga
+ isDirectory = ((us->cur_file_info.external_fa & 0xc000000u) == 0x8000000u); // ((external_fa >> 16) & IFMT) == IFDIR
+ break;
+ case 0: // FAT (MS-DOS)
+ case 6: // HPFS (OS/2)
+ case 11: // NTFS
+ case 14: // VFAT
+ isDirectory = ((us->cur_file_info.external_fa & 0x10) == 0x10); // external_fa & FILE_ATTRIBUTE_DIRECTORY
+ break;
+ case 3: // Unix
+ isDirectory = ((us->cur_file_info.external_fa & 0xf0000000u) == 0x40000000u); // S_ISDIR(external_fa >> 16)
+ break;
+ default:
+ break;
+ }
+ }
- us->_hash[Common::String(name)] = fe;
+ 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);
+ }
+
+ us->_hash[name] = fe;
// Move to the next file
err = unzGoToNextFile((unzFile)us);
@@ -1001,6 +1036,7 @@ public:
~ZipArchive();
bool hasFile(const Path &path) const override;
+ 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;
@@ -1040,6 +1076,19 @@ bool ZipArchive::hasFile(const Path &path) const {
return (unzLocateFile(_zipFile, name.c_str(), 2) == UNZ_OK);
}
+bool ZipArchive::isPathDirectory(const Path &path) const {
+ String name = path.toString();
+
+ if (unzLocateFile(_zipFile, name.c_str(), 2) != UNZ_OK)
+ return false;
+
+ unz_file_info fi;
+ if (unzGetCurrentFileInfo(_zipFile, &fi, nullptr, 0, nullptr, 0, nullptr, 0) != UNZ_OK)
+ return false;
+
+ return (fi.external_fa & 0x10) != 0;
+}
+
int ZipArchive::listMembers(ArchiveMemberList &list) const {
int members = 0;
Commit: e0b8e6685e1e317bcced3678db7160dda763f636
https://github.com/scummvm/scummvm/commit/e0b8e6685e1e317bcced3678db7160dda763f636
Author: elasota (ejlasota at gmail.com)
Date: 2023-09-17T19:17:33+02:00
Commit Message:
SWORD25: Fix extracted files support and update ZipArchive handling to process directories
Changed paths:
engines/sword25/package/packagemanager.cpp
diff --git a/engines/sword25/package/packagemanager.cpp b/engines/sword25/package/packagemanager.cpp
index ddf6c3ba211..ec287bc10cf 100644
--- a/engines/sword25/package/packagemanager.cpp
+++ b/engines/sword25/package/packagemanager.cpp
@@ -272,36 +272,17 @@ int PackageManager::doSearch(Common::ArchiveMemberList &list, const Common::Stri
// Create a list of the matching names
for (Common::ArchiveMemberList::iterator it = memberList.begin(); it != memberList.end(); ++it) {
- Common::String name;
- bool matchType;
-
- // FSNode->getName() returns only name of the file, without the directory
- // getPath() returns full path in the FS. Thus, we're getting it and
- // removing the root from it.
- if (_extractedFiles) {
- Common::FSNode *node = (Common::FSNode *)(it->get());
-
- name = node->getPath().substr(_directoryName.size());
-
- for (uint c = 0; c < name.size(); c++) {
- if (name[c] == '\\')
- name.replace(c, 1, "/");
- }
-
- matchType = (((typeFilter & PackageManager::FT_DIRECTORY) && node->isDirectory()) ||
- ((typeFilter & PackageManager::FT_FILE) && !node->isDirectory()));
- } else {
- name = (*it)->getName();
- matchType = ((typeFilter & PackageManager::FT_DIRECTORY) && name.hasSuffix("/")) ||
- ((typeFilter & PackageManager::FT_FILE) && !name.hasSuffix("/"));
- }
+ Common::Path name = (*it)->getPathInArchive();
+ bool isDirectory = (*it)->isDirectory();
+ bool matchType = (((typeFilter & PackageManager::FT_DIRECTORY) && isDirectory) ||
+ ((typeFilter & PackageManager::FT_FILE) && !isDirectory));
if (matchType) {
// Do not add duplicate files
bool found = false;
for (Common::ArchiveMemberList::iterator it1 = list.begin(); it1 != list.end(); ++it1) {
- if ((*it1)->getName() == name) {
+ if ((*it1)->getPathInArchive() == name) {
found = true;
break;
}
@@ -309,7 +290,7 @@ int PackageManager::doSearch(Common::ArchiveMemberList &list, const Common::Stri
if (!found) {
list.push_back(Common::ArchiveMemberList::value_type(new Common::GenericArchiveMember(name, *(*i)->archive)));
- debug(9, "> %s", name.c_str());
+ debug(9, "> %s", name.toString().c_str());
}
num++;
}
More information about the Scummvm-git-logs
mailing list