mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-01 14:58:14 +00:00
Path: make WithReplacedExtension(old, new) report a mismatch instead of hiding it
It used to return the path unchanged when the path didn't end in oldExtension, so a caller that guessed wrong silently went on using the original file - and "the screenshot next to this savestate" quietly becomes "this savestate". Every caller had to know to check the extension first, and most didn't. Now it's [[nodiscard]] bool with an out-param, in the style of ComputePathTo next door, so the mismatch has to be handled. Changing the signature rather than the behaviour means no call site can keep the old assumption by accident. All four callers wanted "skip it" or "fall back", which they now say out loud. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
This commit is contained in:
1 parent
90a85e235b
commit
4ae682283c
8 files changed
+57
-28
No files matched your search
@@ -82,14 +82,16 @@ AndroidContentURI AndroidContentURI::WithExtraExtension(std::string_view extensi
|
||||
return uri;
|
||||
}
|
||||
|
||||
AndroidContentURI AndroidContentURI::WithReplacedExtension(const std::string &oldExtension, const std::string &newExtension) const {
|
||||
bool AndroidContentURI::WithReplacedExtension(const std::string &oldExtension, const std::string &newExtension, AndroidContentURI *out) const {
|
||||
_dbg_assert_(!oldExtension.empty() && oldExtension[0] == '.');
|
||||
_dbg_assert_(!newExtension.empty() && newExtension[0] == '.');
|
||||
AndroidContentURI uri = *this;
|
||||
if (endsWithNoCase(file, oldExtension)) {
|
||||
uri.file = file.substr(0, file.size() - oldExtension.size()) + newExtension;
|
||||
if (!endsWithNoCase(file, oldExtension)) {
|
||||
return false;
|
||||
}
|
||||
return uri;
|
||||
AndroidContentURI uri = *this;
|
||||
uri.file = file.substr(0, file.size() - oldExtension.size()) + newExtension;
|
||||
*out = uri;
|
||||
return true;
|
||||
}
|
||||
|
||||
AndroidContentURI AndroidContentURI::WithReplacedExtension(const std::string &newExtension) const {
|
||||
|
||||
@@ -32,7 +32,8 @@ public:
|
||||
AndroidContentURI WithRootFilePath(const std::string &filePath);
|
||||
AndroidContentURI WithComponent(std::string_view filePath);
|
||||
AndroidContentURI WithExtraExtension(std::string_view extension); // The ext string contains the dot.
|
||||
AndroidContentURI WithReplacedExtension(const std::string &oldExtension, const std::string &newExtension) const;
|
||||
// False, leaving *out alone, if the file doesn't end in oldExtension. See Path's version.
|
||||
[[nodiscard]] bool WithReplacedExtension(const std::string &oldExtension, const std::string &newExtension, AndroidContentURI *out) const;
|
||||
AndroidContentURI WithReplacedExtension(const std::string &newExtension) const;
|
||||
|
||||
bool CanNavigateUp() const;
|
||||
|
||||
+16
-11
@@ -119,20 +119,25 @@ Path Path::WithExtraExtension(std::string_view ext) const {
|
||||
return Path(path_ + std::string(ext));
|
||||
}
|
||||
|
||||
Path Path::WithReplacedExtension(const std::string &oldExtension, const std::string &newExtension) const {
|
||||
if (type_ == PathType::CONTENT_URI) {
|
||||
AndroidContentURI uri(path_);
|
||||
return Path(uri.WithReplacedExtension(oldExtension, newExtension).ToString());
|
||||
}
|
||||
|
||||
bool Path::WithReplacedExtension(const std::string &oldExtension, const std::string &newExtension, Path *out) const {
|
||||
_dbg_assert_(!oldExtension.empty() && oldExtension[0] == '.');
|
||||
_dbg_assert_(!newExtension.empty() && newExtension[0] == '.');
|
||||
if (endsWithNoCase(path_, oldExtension)) {
|
||||
std::string newPath = path_.substr(0, path_.size() - oldExtension.size());
|
||||
return Path(newPath + newExtension);
|
||||
} else {
|
||||
return Path(*this);
|
||||
|
||||
if (type_ == PathType::CONTENT_URI) {
|
||||
AndroidContentURI uri(path_);
|
||||
AndroidContentURI replaced;
|
||||
if (!uri.WithReplacedExtension(oldExtension, newExtension, &replaced)) {
|
||||
return false;
|
||||
}
|
||||
*out = Path(replaced.ToString());
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!endsWithNoCase(path_, oldExtension)) {
|
||||
return false;
|
||||
}
|
||||
*out = Path(path_.substr(0, path_.size() - oldExtension.size()) + newExtension);
|
||||
return true;
|
||||
}
|
||||
|
||||
Path Path::WithReplacedExtension(const std::string &newExtension) const {
|
||||
|
||||
+7
-1
@@ -86,7 +86,13 @@ public:
|
||||
|
||||
// File extension manipulation.
|
||||
Path WithExtraExtension(std::string_view ext) const;
|
||||
Path WithReplacedExtension(const std::string &oldExtension, const std::string &newExtension) const;
|
||||
// Swaps one known extension for another, e.g. ".ppst" -> ".jpg". Returns false and leaves *out
|
||||
// alone if the path doesn't actually end in oldExtension. That case has to be handled: this
|
||||
// used to return the path unchanged, so a caller that guessed the extension wrong quietly
|
||||
// carried on with the original file - and "delete the screenshot next to this savestate" then
|
||||
// means "delete the savestate".
|
||||
[[nodiscard]] bool WithReplacedExtension(const std::string &oldExtension, const std::string &newExtension, Path *out) const;
|
||||
// Replaces whatever extension is there, so there's nothing to fail on.
|
||||
Path WithReplacedExtension(const std::string &newExtension) const;
|
||||
|
||||
std::string GetFilename() const; // Really, GetLastComponent. Could be a file or directory. Includes the extension.
|
||||
|
||||
Reference in new issue
Block a user