[Scummvm-git-logs] scummvm master -> ace9a26180ccc4f73b918420a004d5da92bf5e2e
sev-
noreply at scummvm.org
Mon Jun 23 23:07:39 UTC 2025
This automated email contains information about 2 new commits which have been
pushed to the 'scummvm' repo located at https://api.github.com/repos/scummvm/scummvm .
Summary:
9b6414e94f COMMON: Implement Path::removeExtension() and relevant tests
ace9a26180 GUI: INTEGRITY: Boilerplate code for macfile-format-agnostic checksums
Commit: 9b6414e94f9e3ee9f15e28dd503d519193a4b2f1
https://github.com/scummvm/scummvm/commit/9b6414e94f9e3ee9f15e28dd503d519193a4b2f1
Author: Eugene Sandulenko (sev at scummvm.org)
Date: 2025-06-24T01:07:26+02:00
Commit Message:
COMMON: Implement Path::removeExtension() and relevant tests
Changed paths:
common/path.cpp
common/path.h
test/common/path.h
diff --git a/common/path.cpp b/common/path.cpp
index 07e3bafa368..4fb1446a1df 100644
--- a/common/path.cpp
+++ b/common/path.cpp
@@ -610,6 +610,53 @@ Path &Path::removeTrailingSeparators() {
return *this;
}
+Path &Path::removeExtension(const char *ext) {
+ if (_str.empty()) {
+ return *this;
+ }
+
+ // Find the last separator
+ size_t last = _str.size() - 1;
+ if (isSeparatorTerminated()) {
+ last--;
+ }
+
+ size_t sepPos = findLastSeparator(last);
+ const char *begin;
+ if (sepPos == String::npos) {
+ // No separator found, we are a single component
+ begin = _str.c_str();
+ } else {
+ // We have a separator, so we can find the last component
+ begin = _str.c_str() + sepPos + 1;
+ }
+
+ const char *end = _str.c_str() + _str.size();
+ String component(begin, end);
+
+ // If the last component is shorter than the extension,
+ // or it is punycode encoded, we do not change the path
+ if ((ext && component.size() < strlen(ext)) || punycode_hasprefix(component))
+ return *this;
+
+ if (!ext) {
+ // Remove the last extension, if any
+ size_t dotPos = component.findLastOf('.');
+ if (dotPos == String::npos) {
+ return *this; // No change
+ }
+
+ _str.chop(end - begin - dotPos);
+
+ return *this;
+ } else if (component.hasSuffix(ext)) {
+ // Remove the given extension, if it matches
+ _str.chop(strlen(ext));
+ }
+
+ return *this;
+}
+
const char *Path::getSuffix(const Common::Path &other) const {
if (other.empty()) {
// Other is empty, return full string
diff --git a/common/path.h b/common/path.h
index 0f17e0b18c1..0579646d642 100644
--- a/common/path.h
+++ b/common/path.h
@@ -469,6 +469,19 @@ public:
*/
Path &removeTrailingSeparators();
+ /**
+ * Removes extension from the last component of this path (in-place).
+ * If the last component has no extension, this does nothing.
+ *
+ * Punycode encoded paths are not supported.
+ *
+ * If nullptr is passed as @p ext, it will remove the last extension,
+ * otherwise it will remove the extension only if it matches @p ext.
+ *
+ * The extension must have a leading dot, e.g. ".txt".
+ */
+ Path &removeExtension(const char *ext = nullptr);
+
/**
* Returns whether this path ends with a separator
*/
diff --git a/test/common/path.h b/test/common/path.h
index c14cfcd4f2e..bbf2607f551 100644
--- a/test/common/path.h
+++ b/test/common/path.h
@@ -538,4 +538,66 @@ class PathTestSuite : public CxxTest::TestSuite
void test_canUnescape() {
TS_ASSERT(Common::Path::canUnescape(true, true, ""));
}
+
+ void test_removeExtension() {
+ Common::Path p(TEST_PATH);
+ p.removeExtension();
+ TS_ASSERT_EQUALS(p.toString(), "parent/dir/file");
+
+ Common::Path p2("parent/dir/file.txt.gz");
+ p2.removeExtension();
+ TS_ASSERT_EQUALS(p2.toString(), "parent/dir/file.txt");
+
+ Common::Path p3("parent/dir/file.");
+ p3.removeExtension();
+ TS_ASSERT_EQUALS(p3.toString(), "parent/dir/file");
+
+ Common::Path p4("parent/dir/file.txt.txt");
+ p4.removeExtension(".txt");
+ TS_ASSERT_EQUALS(p4.toString(), "parent/dir/file.txt");
+
+ Common::Path p5("parent/dir/file.txt");
+ p5.removeExtension(".txt");
+ TS_ASSERT_EQUALS(p5.toString(), "parent/dir/file");
+
+ Common::Path p6("parent/dir.txt/file.gz");
+ p6.removeExtension(".txt");
+ TS_ASSERT_EQUALS(p6.toString(), "parent/dir.txt/file.gz");
+
+ Common::Path p7("parent/dir/xn--Sound Manager 3.1 SoundLib-lba84k/Sound.txt");
+ p7.removeExtension(".txt");
+ TS_ASSERT_EQUALS(p7.toString(), "parent/dir/xn--Sound Manager 3.1 SoundLib-lba84k/Sound");
+
+ Common::Path p8("parent/dir/Sound/xn--dialred.dir-qa21d");
+ p8.removeExtension(".dir");
+ TS_ASSERT_EQUALS(p8.toString(), "parent/dir/Sound/xn--dialred.dir-qa21d");
+
+ Common::Path p9("parent/dir/.ab");
+ p9.removeExtension();
+ TS_ASSERT_EQUALS(p9.toString(), "parent/dir/");
+
+ Common::Path p10("parent/dir/.ab");
+ p10.removeExtension(".abc");
+ TS_ASSERT_EQUALS(p10.toString(), "parent/dir/.ab");
+
+ Common::Path p11(".ab");
+ p11.removeExtension(".abc");
+ TS_ASSERT_EQUALS(p11.toString(), ".ab");
+
+ Common::Path p12("test.dir");
+ p12.removeExtension(".dir");
+ TS_ASSERT_EQUALS(p12.toString(), "test");
+
+ Common::Path p13("test.dir");
+ p13.removeExtension(".txt");
+ TS_ASSERT_EQUALS(p13.toString(), "test.dir");
+
+ Common::Path p14("test.dir.txt");
+ p14.removeExtension(".dir");
+ TS_ASSERT_EQUALS(p14.toString(), "test.dir.txt");
+
+ Common::Path p15(".dir");
+ p15.removeExtension(".dir");
+ TS_ASSERT_EQUALS(p15.toString(), "");
+ }
};
Commit: ace9a26180ccc4f73b918420a004d5da92bf5e2e
https://github.com/scummvm/scummvm/commit/ace9a26180ccc4f73b918420a004d5da92bf5e2e
Author: Eugene Sandulenko (sev at scummvm.org)
Date: 2025-06-24T01:07:26+02:00
Commit Message:
GUI: INTEGRITY: Boilerplate code for macfile-format-agnostic checksums
Changed paths:
gui/integrity-dialog.cpp
diff --git a/gui/integrity-dialog.cpp b/gui/integrity-dialog.cpp
index aec7fef451c..14d818553d3 100644
--- a/gui/integrity-dialog.cpp
+++ b/gui/integrity-dialog.cpp
@@ -351,6 +351,39 @@ Common::Array<Common::StringArray> IntegrityDialog::generateChecksums(Common::Pa
if (fileList.empty())
return {};
+ // First, we go through the list and check any Mac files
+ Common::HashMap<Common::Path, bool, Common::Path::IgnoreCase_Hash, Common::Path::IgnoreCase_EqualTo> macFiles;
+ Common::HashMap<Common::Path, bool, Common::Path::IgnoreCase_Hash, Common::Path::IgnoreCase_EqualTo> toRemove;
+ Common::List<Common::Path> filteredFileList;
+ Common::List<Common::Path> tmpFileList;
+
+ for (const auto &entry : fileList) {
+ if (entry.isDirectory())
+ continue;
+
+ Common::Path filename(entry.getPath().relativeTo(gamePath));
+ const Common::Path originalFileName = filename;
+ filename.removeExtension(".bin");
+ filename.removeExtension(".rsrc");
+
+ auto macFile = Common::MacResManager();
+
+ if (macFile.open(filename) && macFile.isMacFile()) {
+ macFiles[filename] = true;
+
+ tmpFileList.push_back(filename);
+ } else {
+ if (!toRemove.contains(originalFileName))
+ tmpFileList.push_back(originalFileName);
+ }
+ }
+
+ for (const auto &entry : tmpFileList) {
+ if (!toRemove.contains(entry)) {
+ filteredFileList.push_back(entry);
+ }
+ }
+
// Process the files and subdirectories in the current directory recursively
for (const auto &entry : fileList) {
if (entry.isDirectory()) {
More information about the Scummvm-git-logs
mailing list