It never ends...

This commit is contained in:
Henrik Rydgård 2021-05-09 18:38:48 +02:00
parent a40b1dec5f
commit 2e16e83159
43 changed files with 292 additions and 277 deletions

View File

@ -1,6 +1,6 @@
#include "Common/File/Path.h"
#include "Common/StringUtils.h"
#include "Common/Log.h"
#include "Common/Data/Encoding/Utf8.h"
Path::Path(const std::string &str) {
@ -39,10 +39,22 @@ void Path::Init(const std::string &str) {
}
}
// We always use forward slashes internally, we convert to backslash only when
// converted to a wstring.
Path Path::operator /(const std::string &subdir) const {
// We always use forward slashes internally, we convert to backslash only when
// converted to a wstring.
return Path(path_ + "/" + subdir);
if (subdir.empty()) {
return Path(path_);
}
std::string fullPath = path_;
if (subdir.front() != '/') {
fullPath += "/";
}
fullPath += subdir;
// Prevent adding extra slashes.
if (fullPath.back() == '/') {
fullPath.pop_back();
}
return Path(fullPath);
}
void Path::operator /=(const std::string &subdir) {
@ -50,18 +62,40 @@ void Path::operator /=(const std::string &subdir) {
}
Path Path::WithExtraExtension(const std::string &ext) const {
return Path(path_ + "." + ext);
_dbg_assert_(!ext.empty() && ext[0] == '.');
return Path(path_ + ext);
}
Path Path::WithReplacedExtension(const std::string &oldExtension, const std::string &newExtension) const {
if (endsWithNoCase(path_, "." + oldExtension)) {
std::string newPath = path_.substr(0, path_.size() - oldExtension.size() - 1);
return Path(newPath + "." + newExtension);
_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);
}
}
Path Path::WithReplacedExtension(const std::string &newExtension) const {
_dbg_assert_(!newExtension.empty() && newExtension[0] == '.');
if (path_.empty()) {
return Path(*this);
}
std::string extension = GetFileExtension();
std::string newPath = path_.substr(0, path_.size() - extension.size()) + newExtension;
return Path(newPath);
}
std::string Path::GetFilename() const {
size_t pos = path_.rfind('/');
if (pos != std::string::npos) {
return path_.substr(pos + 1);
}
// No directory components, just return the full path.
return path_;
}
std::string Path::GetFileExtension() const {
size_t pos = path_.rfind(".");
if (pos == std::string::npos) {
@ -72,17 +106,27 @@ std::string Path::GetFileExtension() const {
// Don't want to detect "df/file" from "/as.df/file"
return "";
}
std::string ext = path_.substr(pos + 1);
std::string ext = path_.substr(pos);
for (size_t i = 0; i < ext.size(); i++) {
ext[i] = tolower(ext[i]);
}
return ext;
}
Path Path::Directory() const {
std::string directory;
SplitPath(path_, &directory, nullptr, nullptr);
return Path(directory);
std::string Path::GetDirectory() const {
size_t pos = path_.rfind('/');
if (pos != std::string::npos) {
return path_.substr(0, pos);
} else {
// There could be a ':', too. Unlike the slash, let's include that
// in the returned directory.
size_t c_pos = path_.rfind(':');
if (c_pos != std::string::npos) {
return path_.substr(0, c_pos + 1);
}
}
// No directory components, just return the full path.
return path_;
}
bool Path::FilePathContains(const std::string &needle) const {
@ -125,6 +169,11 @@ bool Path::CanNavigateUp() const {
return true;
}
Path Path::NavigateUp() const {
std::string dir = GetDirectory();
return Path(dir);
}
bool Path::IsAbsolute() const {
if (path_.empty())
return true;

View File

@ -59,11 +59,12 @@ public:
// File extension manipulation.
Path WithExtraExtension(const std::string &ext) const;
Path WithReplacedExtension(const std::string &oldExtension, const std::string &newExtension) const;
Path WithReplacedExtension(const std::string &newExtension) const;
// Removes the last component.
Path Directory() const;
std::string GetFileExtension() const;
std::string GetFilename() const; // Really, GetLastComponent. Could be a file or directory.
std::string GetFileExtension() const; // Always lowercase return. Includes the dot.
std::string GetDirectory() const;
const std::string &ToString() const;
@ -74,6 +75,8 @@ public:
std::string ToVisualString() const;
bool CanNavigateUp() const;
Path NavigateUp() const;
bool operator ==(const Path &other) const {
return path_ == other.path_ && type_ == other.type_;
}

View File

@ -125,22 +125,6 @@ bool SplitPath(const std::string& full_path, std::string* _pPath, std::string* _
return true;
}
std::string GetFilenameFromPath(std::string full_path) {
size_t pos;
#ifdef _WIN32
pos = full_path.rfind('\\');
if (pos != std::string::npos) {
return full_path.substr(pos + 1);
}
#endif
pos = full_path.rfind('/');
if (pos != std::string::npos) {
return full_path.substr(pos + 1);
}
// No directory components, just return the full path.
return full_path;
}
std::string LineNumberString(const std::string &str) {
std::stringstream input(str);
std::stringstream output;

View File

@ -101,5 +101,3 @@ inline void CharArrayFromFormat(char (& out)[Count], const char* format, ...)
// "C:/Windows/winhelp.exe" to "C:/Windows/", "winhelp", ".exe"
bool SplitPath(const std::string& full_path, std::string* _pPath, std::string* _pFilename, std::string* _pExtension);
std::string GetFilenameFromPath(std::string full_path);

View File

@ -1536,7 +1536,7 @@ void Config::RemoveRecent(const std::string &file) {
void Config::CleanRecent() {
std::vector<std::string> cleanedRecent;
for (size_t i = 0; i < recentIsos.size(); i++) {
FileLoader *loader = ConstructFileLoader(recentIsos[i]);
FileLoader *loader = ConstructFileLoader(Path(recentIsos[i]));
if (loader->ExistsFast()) {
// Make sure we don't have any redundant items.
auto duplicate = std::find(cleanedRecent.begin(), cleanedRecent.end(), recentIsos[i]);
@ -1577,7 +1577,8 @@ const Path Config::FindConfigFile(const std::string &baseFilename) {
const Path filename = defaultPath_ / baseFilename;
if (!File::Exists(filename)) {
Path path = filename.Directory();
// Make sure at least the directory it's supposed to be in exists.
Path path = filename.NavigateUp();
if (createdPath_ != path) {
File::CreateFullPath(path);
createdPath_ = path;

View File

@ -45,7 +45,7 @@ static const u32 CACHE_SPACE_FLEX = 4;
Path DiskCachingFileLoaderCache::cacheDir_;
std::map<std::string, DiskCachingFileLoaderCache *> DiskCachingFileLoader::caches_;
std::map<Path, DiskCachingFileLoaderCache *> DiskCachingFileLoader::caches_;
std::mutex DiskCachingFileLoader::cachesMutex_;
// Takes ownership of backend.
@ -118,11 +118,11 @@ size_t DiskCachingFileLoader::ReadAt(s64 absolutePos, size_t bytes, void *data,
return readSize;
}
std::vector<std::string> DiskCachingFileLoader::GetCachedPathsInUse() {
std::vector<Path> DiskCachingFileLoader::GetCachedPathsInUse() {
std::lock_guard<std::mutex> guard(cachesMutex_);
// This is on the file loader so that it can manage the caches_.
std::vector<std::string> files;
std::vector<Path> files;
for (auto it : caches_) {
files.push_back(it.first);
@ -134,7 +134,7 @@ std::vector<std::string> DiskCachingFileLoader::GetCachedPathsInUse() {
void DiskCachingFileLoader::InitCache() {
std::lock_guard<std::mutex> guard(cachesMutex_);
std::string path = ProxiedFileLoader::GetPath();
Path path = ProxiedFileLoader::GetPath();
auto &entry = caches_[path];
if (!entry) {
entry = new DiskCachingFileLoaderCache(path, filesize_);
@ -155,7 +155,7 @@ void DiskCachingFileLoader::ShutdownCache() {
cache_ = nullptr;
}
DiskCachingFileLoaderCache::DiskCachingFileLoaderCache(const std::string &path, u64 filesize)
DiskCachingFileLoaderCache::DiskCachingFileLoaderCache(const Path &path, u64 filesize)
: filesize_(filesize), origPath_(path) {
InitCache(path);
}
@ -164,7 +164,7 @@ DiskCachingFileLoaderCache::~DiskCachingFileLoaderCache() {
ShutdownCache();
}
void DiskCachingFileLoaderCache::InitCache(const std::string &filename) {
void DiskCachingFileLoaderCache::InitCache(const Path &filename) {
cacheSize_ = 0;
indexCount_ = 0;
oldestGeneration_ = 0;
@ -172,7 +172,7 @@ void DiskCachingFileLoaderCache::InitCache(const std::string &filename) {
flags_ = 0;
generation_ = 0;
const Path cacheFilePath = Path(MakeCacheFilePath(filename));
const Path cacheFilePath = MakeCacheFilePath(filename);
bool fileLoaded = LoadCacheFile(cacheFilePath);
// We do some basic locking to protect against two things: crashes and concurrency.
@ -409,9 +409,9 @@ u32 DiskCachingFileLoaderCache::AllocateBlock(u32 indexPos) {
return INVALID_BLOCK;
}
std::string DiskCachingFileLoaderCache::MakeCacheFilename(const std::string &path) {
std::string DiskCachingFileLoaderCache::MakeCacheFilename(const Path &path) {
static const char *const invalidChars = "?*:/\\^|<>\"'";
std::string filename = path;
std::string filename = path.ToString();
for (size_t i = 0; i < filename.size(); ++i) {
int c = filename[i];
if (strchr(invalidChars, c) != nullptr) {
@ -421,7 +421,7 @@ std::string DiskCachingFileLoaderCache::MakeCacheFilename(const std::string &pat
return filename + ".ppdc";
}
::Path DiskCachingFileLoaderCache::MakeCacheFilePath(const std::string &filename) {
::Path DiskCachingFileLoaderCache::MakeCacheFilePath(const Path &filename) {
Path dir = cacheDir_;
if (dir.empty()) {
dir = GetSysDirectory(DIRECTORY_CACHE);
@ -801,9 +801,9 @@ u32 DiskCachingFileLoaderCache::CountCachedFiles() {
void DiskCachingFileLoaderCache::GarbageCollectCacheFiles(u64 goalBytes) {
// We attempt to free up at least enough files from the cache to get goalBytes more space.
const std::vector<std::string> usedPaths = DiskCachingFileLoader::GetCachedPathsInUse();
const std::vector<Path> usedPaths = DiskCachingFileLoader::GetCachedPathsInUse();
std::set<std::string> used;
for (std::string path : usedPaths) {
for (const Path &path : usedPaths) {
used.insert(MakeCacheFilename(path));
}

View File

@ -42,7 +42,7 @@ public:
}
size_t ReadAt(s64 absolutePos, size_t bytes, void *data, Flags flags = Flags::NONE) override;
static std::vector<std::string> GetCachedPathsInUse();
static std::vector<Path> GetCachedPathsInUse();
private:
void Prepare();
@ -55,13 +55,13 @@ private:
// We don't support concurrent disk cache access (we use memory cached indexes.)
// So we have to ensure there's only one of these per.
static std::map<std::string, DiskCachingFileLoaderCache *> caches_;
static std::map<Path, DiskCachingFileLoaderCache *> caches_;
static std::mutex cachesMutex_;
};
class DiskCachingFileLoaderCache {
public:
DiskCachingFileLoaderCache(const std::string &path, u64 filesize);
DiskCachingFileLoaderCache(const Path &path, u64 filesize);
~DiskCachingFileLoaderCache();
bool IsValid() {
@ -87,7 +87,7 @@ public:
bool HasData() const;
private:
void InitCache(const std::string &path);
void InitCache(const Path &path);
void ShutdownCache();
bool MakeCacheSpaceFor(size_t blocks);
void RebalanceGenerations();
@ -99,8 +99,8 @@ private:
void WriteIndexData(u32 indexPos, BlockInfo &info);
s64 GetBlockOffset(u32 block);
::Path MakeCacheFilePath(const std::string &filename);
std::string MakeCacheFilename(const std::string &path);
Path MakeCacheFilePath(const Path &filename);
std::string MakeCacheFilename(const Path &path);
bool LoadCacheFile(const Path &path);
void LoadCacheIndex();
void CreateCacheFile(const Path &path);

View File

@ -23,8 +23,8 @@
#include "Core/Config.h"
#include "Core/FileLoaders/HTTPFileLoader.h"
HTTPFileLoader::HTTPFileLoader(const std::string &filename)
: url_(filename), progress_(&cancel_), filename_(filename) {
HTTPFileLoader::HTTPFileLoader(const ::Path &filename)
: url_(filename.ToString()), progress_(&cancel_), filename_(filename) {
}
void HTTPFileLoader::Prepare() {
@ -172,7 +172,7 @@ s64 HTTPFileLoader::FileSize() {
return filesize_;
}
std::string HTTPFileLoader::GetPath() const {
Path HTTPFileLoader::GetPath() const {
return filename_;
}

View File

@ -20,6 +20,7 @@
#include <mutex>
#include <vector>
#include "Common/File/Path.h"
#include "Common/Net/HTTPClient.h"
#include "Common/Net/Resolve.h"
#include "Common/Net/URL.h"
@ -28,7 +29,7 @@
class HTTPFileLoader : public FileLoader {
public:
HTTPFileLoader(const std::string &filename);
HTTPFileLoader(const ::Path &filename);
virtual ~HTTPFileLoader() override;
bool IsRemote() override {
@ -38,7 +39,7 @@ public:
virtual bool ExistsFast() override;
virtual bool IsDirectory() override;
virtual s64 FileSize() override;
virtual std::string GetPath() const override;
virtual Path GetPath() const override;
virtual size_t ReadAt(s64 absolutePos, size_t bytes, size_t count, void *data, Flags flags = Flags::NONE) override {
return ReadAt(absolutePos, bytes * count, data, flags) / bytes;
@ -71,7 +72,7 @@ private:
Url url_;
http::Client client_;
http::RequestProgress progress_;
std::string filename_;
::Path filename_;
bool connected_ = false;
bool cancel_ = false;
const char *latestError_ = "";

View File

@ -32,7 +32,7 @@
#endif
#ifndef _WIN32
LocalFileLoader::LocalFileLoader(int fd, const std::string &filename) : fd_(fd), filename_(filename), isOpenedByFd_(fd != -1) {
LocalFileLoader::LocalFileLoader(int fd, const Path &filename) : fd_(fd), filename_(filename), isOpenedByFd_(fd != -1) {
if (fd != -1) {
DetectSizeFd();
}
@ -51,7 +51,7 @@ void LocalFileLoader::DetectSizeFd() {
}
#endif
LocalFileLoader::LocalFileLoader(const std::string &filename)
LocalFileLoader::LocalFileLoader(const Path &filename)
: filesize_(0), filename_(filename), isOpenedByFd_(false) {
if (filename.empty()) {
ERROR_LOG(FILESYS, "LocalFileLoader can't load empty filenames");
@ -70,9 +70,9 @@ LocalFileLoader::LocalFileLoader(const std::string &filename)
const DWORD access = GENERIC_READ, share = FILE_SHARE_READ, mode = OPEN_EXISTING, flags = FILE_ATTRIBUTE_NORMAL;
#if PPSSPP_PLATFORM(UWP)
handle_ = CreateFile2(ConvertUTF8ToWString(filename).c_str(), access, share, mode, nullptr);
handle_ = CreateFile2(filename.ToWString().c_str(), access, share, mode, nullptr);
#else
handle_ = CreateFile(ConvertUTF8ToWString(filename).c_str(), access, share, nullptr, mode, flags, nullptr);
handle_ = CreateFile(filename.ToWString().c_str(), access, share, nullptr, mode, flags, nullptr);
#endif
if (handle_ == INVALID_HANDLE_VALUE) {
return;
@ -130,10 +130,6 @@ s64 LocalFileLoader::FileSize() {
return filesize_;
}
std::string LocalFileLoader::GetPath() const {
return filename_.ToString();
}
size_t LocalFileLoader::ReadAt(s64 absolutePos, size_t bytes, size_t count, void *data, Flags flags) {
if (bytes == 0)
return 0;

View File

@ -23,21 +23,22 @@
#include "Common/File/Path.h"
#include "Core/Loaders.h"
#ifdef _WIN32
typedef void *HANDLE;
#endif
class LocalFileLoader : public FileLoader {
public:
LocalFileLoader(const std::string &filename);
LocalFileLoader(const int fd, const std::string &filename);
LocalFileLoader(const Path &filename);
LocalFileLoader(const int fd, const Path &filename);
virtual ~LocalFileLoader();
virtual bool Exists() override;
virtual bool IsDirectory() override;
virtual s64 FileSize() override;
virtual std::string GetPath() const override;
virtual Path GetPath() const override {
return filename_;
}
virtual size_t ReadAt(s64 absolutePos, size_t bytes, size_t count, void *data, Flags flags = Flags::NONE) override;
private:
@ -48,7 +49,7 @@ private:
HANDLE handle_;
#endif
u64 filesize_;
::Path filename_;
Path filename_;
std::mutex readLock_;
bool isOpenedByFd_;
};

View File

@ -129,7 +129,7 @@ bool BlobFileSystem::RemoveFile(const std::string &filename) {
}
bool BlobFileSystem::GetHostPath(const std::string &inpath, Path &outpath) {
outpath = Path(fileLoader_->GetPath());
outpath = fileLoader_->GetPath();
return true;
}

View File

@ -50,8 +50,8 @@
const std::string INDEX_FILENAME = ".ppsspp-index.lst";
VirtualDiscFileSystem::VirtualDiscFileSystem(IHandleAllocator *_hAlloc, std::string _basePath)
: basePath(_basePath),currentBlockIndex(0) {
VirtualDiscFileSystem::VirtualDiscFileSystem(IHandleAllocator *_hAlloc, const Path &_basePath)
: basePath(_basePath), currentBlockIndex(0) {
hAlloc = _hAlloc;
LoadFileListIndex();
}
@ -78,13 +78,6 @@ void VirtualDiscFileSystem::LoadFileListIndex() {
return;
}
/*
in.open(filename.c_str(), std::ios::in);
if (in.fail()) {
>>>>>>> 52a34c2de (Introduce Path, start using it all over the place.)
return;
}*/
std::string buf;
static const int MAX_LINE_SIZE = 2048;
char linebuf[MAX_LINE_SIZE]{};

View File

@ -27,7 +27,7 @@
class VirtualDiscFileSystem: public IFileSystem {
public:
VirtualDiscFileSystem(IHandleAllocator *_hAlloc, std::string _basePath);
VirtualDiscFileSystem(IHandleAllocator *_hAlloc, const Path &_basePath);
~VirtualDiscFileSystem();
void DoState(PointerWrap &p) override;

View File

@ -482,7 +482,7 @@ static u32 sceUmdGetErrorStat()
return umdErrorStat;
}
void __UmdReplace(std::string filepath) {
void __UmdReplace(Path filepath) {
std::string error = "";
if (!UmdReplace(filepath, error)) {
ERROR_LOG(SCEIO, "UMD Replace failed: %s", error.c_str());

View File

@ -17,6 +17,8 @@
#pragma once
#include "Common/File/Path.h"
enum pspUmdState {
PSP_UMD_INIT = 0x00,
PSP_UMD_NOT_PRESENT = 0x01,
@ -41,7 +43,7 @@ enum pspUmdType {
void __UmdInit();
void __UmdDoState(PointerWrap &p);
void __UmdReplace(std::string filepath);
void __UmdReplace(Path filepath);
bool getUMDReplacePermit();
void Register_sceUmdUser();

View File

@ -40,8 +40,8 @@ void RegisterFileLoaderFactory(std::string prefix, std::unique_ptr<FileLoaderFac
factories[prefix] = std::move(factory);
}
FileLoader *ConstructFileLoader(const std::string &filename) {
if (filename.find("http://") == 0 || filename.find("https://") == 0) {
FileLoader *ConstructFileLoader(const Path &filename) {
if (filename.Type() == PathType::HTTP) {
FileLoader *baseLoader = new RetryingFileLoader(new HTTPFileLoader(filename));
// For headless, avoid disk caching since it's usually used for tests that might mutate.
if (!PSP_CoreParameter().headLess) {
@ -51,7 +51,7 @@ FileLoader *ConstructFileLoader(const std::string &filename) {
}
for (auto &iter : factories) {
if (startsWith(filename, iter.first)) {
if (startsWith(filename.ToString(), iter.first)) {
return iter.second->ConstructFileLoader(filename);
}
}
@ -73,7 +73,7 @@ IdentifiedFileType Identify_File(FileLoader *fileLoader) {
return IdentifiedFileType::ERROR_IDENTIFYING;
}
std::string extension = File::GetFileExtension(fileLoader->GetPath());
std::string extension = fileLoader->GetPath().GetFileExtension();
if (extension == ".iso") {
// may be a psx iso, they have 2352 byte sectors. You never know what some people try to open
if ((fileLoader->FileSize() % 2352) == 0) {
@ -143,9 +143,9 @@ IdentifiedFileType Identify_File(FileLoader *fileLoader) {
}
if (id == 'FLE\x7F') {
std::string filename = fileLoader->GetPath();
Path filename = fileLoader->GetPath();
// There are a few elfs misnamed as pbp (like Trig Wars), accept that.
if (extension == ".plf" || strstr(filename.c_str(), "BOOT.BIN") ||
if (extension == ".plf" || strstr(filename.GetFilename().c_str(), "BOOT.BIN") ||
extension == ".elf" || extension == ".prx" || extension == ".pbp") {
return IdentifiedFileType::PSP_ELF;
}
@ -176,14 +176,13 @@ IdentifiedFileType Identify_File(FileLoader *fileLoader) {
// Let's check if we got pointed to a PBP within such a directory.
// If so we just move up and return the directory itself as the game.
std::string path = File::GetDir(fileLoader->GetPath());
// If loading from memstick...
size_t pos = path.find("PSP/GAME/");
if (pos != std::string::npos) {
if (fileLoader->GetPath().FilePathContains("PSP/GAME/")) {
return IdentifiedFileType::PSP_PBP_DIRECTORY;
}
return IdentifiedFileType::PSP_PBP;
} else if (extension == ".pbp") {
}
else if (extension == ".pbp") {
ERROR_LOG(LOADER, "A PBP with the wrong magic number?");
return IdentifiedFileType::PSP_PBP;
} else if (extension == ".bin") {
@ -205,7 +204,7 @@ IdentifiedFileType Identify_File(FileLoader *fileLoader) {
FileLoader *ResolveFileLoaderTarget(FileLoader *fileLoader) {
IdentifiedFileType type = Identify_File(fileLoader);
if (type == IdentifiedFileType::PSP_PBP_DIRECTORY) {
const std::string ebootFilename = ResolvePBPFile(fileLoader->GetPath());
const Path ebootFilename = ResolvePBPFile(fileLoader->GetPath());
if (ebootFilename != fileLoader->GetPath()) {
// Switch fileLoader to the actual EBOOT.
delete fileLoader;
@ -215,28 +214,20 @@ FileLoader *ResolveFileLoaderTarget(FileLoader *fileLoader) {
return fileLoader;
}
std::string ResolvePBPDirectory(const std::string &filename) {
bool hasPBP = endsWith(filename, "/EBOOT.PBP");
#ifdef _WIN32
hasPBP = hasPBP || endsWith(filename, "\\EBOOT.PBP");
#endif
if (hasPBP) {
return filename.substr(0, filename.length() - strlen("/EBOOT.PBP"));
Path ResolvePBPDirectory(const Path &filename) {
if (filename.GetFilename() == "EBOOT.PBP") {
return filename.NavigateUp();
} else {
return filename;
}
return filename;
}
std::string ResolvePBPFile(const std::string &filename) {
bool hasPBP = endsWith(filename, "/EBOOT.PBP");
#ifdef _WIN32
hasPBP = hasPBP || endsWith(filename, "\\EBOOT.PBP");
#endif
if (!hasPBP) {
return filename + "/EBOOT.PBP";
Path ResolvePBPFile(const Path &filename) {
if (filename.GetFilename() != "EBOOT.PBP") {
return filename / "EBOOT.PBP";
} else {
return filename;
}
return filename;
}
bool LoadFile(FileLoader **fileLoaderPtr, std::string *error_string) {
@ -260,11 +251,12 @@ bool LoadFile(FileLoader **fileLoaderPtr, std::string *error_string) {
coreState = CORE_BOOT_ERROR;
return false;
}
std::string path = fileLoader->GetPath();
size_t pos = path.find("PSP/GAME/");
std::string dir = fileLoader->GetPath().GetDirectory();
size_t pos = dir.find("PSP/GAME/");
if (pos != std::string::npos) {
path = ResolvePBPDirectory(path);
pspFileSystem.SetStartingDirectory("ms0:/" + path.substr(pos));
dir = ResolvePBPDirectory(Path(dir)).ToString();
pspFileSystem.SetStartingDirectory("ms0:/" + dir.substr(pos));
}
return Load_PSP_ELF_PBP(fileLoader, error_string);
} else {
@ -355,7 +347,7 @@ bool LoadFile(FileLoader **fileLoaderPtr, std::string *error_string) {
return false;
}
bool UmdReplace(std::string filepath, std::string &error) {
bool UmdReplace(const Path &filepath, std::string &error) {
IFileSystem* currentUMD = pspFileSystem.GetSystem("disc0:");
if (!currentUMD) {
@ -367,7 +359,7 @@ bool UmdReplace(std::string filepath, std::string &error) {
if (!loadedFile->Exists()) {
delete loadedFile;
error = loadedFile->GetPath() + " doesn't exist";
error = loadedFile->GetPath().ToVisualString() + " doesn't exist";
return false;
}
UpdateLoadedFile(loadedFile);

View File

@ -21,6 +21,7 @@
#include <memory>
#include "Common/CommonTypes.h"
#include "Common/File/Path.h"
enum class IdentifiedFileType {
ERROR_IDENTIFYING,
@ -74,15 +75,15 @@ public:
}
virtual bool IsDirectory() = 0;
virtual s64 FileSize() = 0;
virtual std::string GetPath() const = 0;
virtual Path GetPath() const = 0;
virtual size_t ReadAt(s64 absolutePos, size_t bytes, size_t count, void *data, Flags flags = Flags::NONE) = 0;
virtual size_t ReadAt(s64 absolutePos, size_t bytes, void *data, Flags flags = Flags::NONE) {
return ReadAt(absolutePos, 1, bytes, data, flags);
}
// Cancel any operations that might block, if possible.
virtual void Cancel() {
}
virtual void Cancel() {}
virtual std::string LatestError() const {
return "";
@ -112,7 +113,7 @@ public:
s64 FileSize() override {
return backend_->FileSize();
}
std::string GetPath() const override {
Path GetPath() const override {
return backend_->GetPath();
}
void Cancel() override {
@ -136,23 +137,23 @@ inline u32 operator & (const FileLoader::Flags &a, const FileLoader::Flags &b) {
return (u32)a & (u32)b;
}
FileLoader *ConstructFileLoader(const std::string &filename);
FileLoader *ConstructFileLoader(const Path &filename);
// Resolve to the target binary, ISO, or other file (e.g. from a directory.)
FileLoader *ResolveFileLoaderTarget(FileLoader *fileLoader);
std::string ResolvePBPDirectory(const std::string &filename);
std::string ResolvePBPFile(const std::string &filename);
Path ResolvePBPDirectory(const Path &filename);
Path ResolvePBPFile(const Path &filename);
IdentifiedFileType Identify_File(FileLoader *fileLoader);
class FileLoaderFactory {
public:
virtual ~FileLoaderFactory() {}
virtual FileLoader *ConstructFileLoader(const std::string &filename) = 0;
virtual FileLoader *ConstructFileLoader(const Path &filename) = 0;
};
void RegisterFileLoaderFactory(std::string name, std::unique_ptr<FileLoaderFactory> factory);
void RegisterFileLoaderFactory(std::string prefix, std::unique_ptr<FileLoaderFactory> factory);
// Can modify the string filename, as it calls IdentifyFile above.
bool LoadFile(FileLoader **fileLoaderPtr, std::string *error_string);
bool UmdReplace(std::string filepath, std::string &error);
bool UmdReplace(const Path &filepath, std::string &error);

View File

@ -375,16 +375,10 @@ bool Load_PSP_ELF_PBP(FileLoader *fileLoader, std::string *error_string) {
pspFileSystem.Mount("umd:", blockSystem);
}
}
std::string full_path = fileLoader->GetPath();
std::string path, file, extension;
SplitPath(ReplaceAll(full_path, "\\", "/"), &path, &file, &extension);
if (!path.empty() && path.back() == '/')
path.resize(path.size() - 1);
#ifdef _WIN32
if (!path.empty() && path.back() == '\\')
path.resize(path.size() - 1);
#endif
Path full_path = fileLoader->GetPath();
std::string path = full_path.GetDirectory();
std::string extension = full_path.GetFileExtension();
std::string file = full_path.GetFilename();
size_t pos = path.find("PSP/GAME/");
std::string ms_path;
@ -396,11 +390,6 @@ bool Load_PSP_ELF_PBP(FileLoader *fileLoader, std::string *error_string) {
ms_path = "umd0:/";
}
#ifdef _WIN32
// Turn the slashes back to the Windows way.
path = ReplaceAll(path, "/", "\\");
#endif
if (!PSP_CoreParameter().mountRoot.empty()) {
// We don't want to worry about .. and cwd and such.
const Path rootNorm = NormalizePath(PSP_CoreParameter().mountRoot);
@ -425,7 +414,7 @@ bool Load_PSP_ELF_PBP(FileLoader *fileLoader, std::string *error_string) {
DirectoryFileSystem *fs = new DirectoryFileSystem(&pspFileSystem, Path(path), FileSystemFlags::SIMULATE_FAT32 | FileSystemFlags::CARD);
pspFileSystem.Mount("umd0:", fs);
std::string finalName = ms_path + file + extension;
std::string finalName = ms_path + file;
std::string homebrewName = PSP_CoreParameter().fileToStart.ToVisualString();
std::size_t lslash = homebrewName.find_last_of("/");
@ -449,14 +438,14 @@ bool Load_PSP_ELF_PBP(FileLoader *fileLoader, std::string *error_string) {
Path oldNamePrefix = savestateDir / StringFromFormat("%s_%d", homebrewName.c_str(), i);
Path oldIDPrefix = savestateDir / StringFromFormat("%s_1.00_%d", madeUpID.c_str(), i);
if (oldIDPrefix != newPrefix && File::Exists(oldIDPrefix.WithExtraExtension("ppst")))
File::Rename(oldIDPrefix.WithExtraExtension("ppst"), newPrefix.WithExtraExtension("ppst"));
else if (File::Exists(oldNamePrefix.WithExtraExtension("ppst")))
File::Rename(oldNamePrefix.WithExtraExtension("ppst"), newPrefix.WithExtraExtension("ppst"));
if (oldIDPrefix != newPrefix && File::Exists(oldIDPrefix.WithExtraExtension("jpg")))
File::Rename(oldIDPrefix.WithExtraExtension("jpg"), newPrefix.WithExtraExtension("jpg"));
else if (File::Exists(oldNamePrefix.WithExtraExtension("jpg")))
File::Rename(oldNamePrefix.WithExtraExtension("jpg"), newPrefix.WithExtraExtension("jpg"));
if (oldIDPrefix != newPrefix && File::Exists(oldIDPrefix.WithExtraExtension(".ppst")))
File::Rename(oldIDPrefix.WithExtraExtension(".ppst"), newPrefix.WithExtraExtension(".ppst"));
else if (File::Exists(oldNamePrefix.WithExtraExtension(".ppst")))
File::Rename(oldNamePrefix.WithExtraExtension(".ppst"), newPrefix.WithExtraExtension(".ppst"));
if (oldIDPrefix != newPrefix && File::Exists(oldIDPrefix.WithExtraExtension(".jpg")))
File::Rename(oldIDPrefix.WithExtraExtension(".jpg"), newPrefix.WithExtraExtension(".jpg"));
else if (File::Exists(oldNamePrefix.WithExtraExtension(".jpg")))
File::Rename(oldNamePrefix.WithExtraExtension(".jpg"), newPrefix.WithExtraExtension(".jpg"));
}
PSPLoaders_Shutdown();

View File

@ -101,8 +101,8 @@ namespace Reporting
static std::mutex crcLock;
static std::condition_variable crcCond;
static std::string crcFilename;
static std::map<std::string, u32> crcResults;
static Path crcFilename;
static std::map<Path, u32> crcResults;
static volatile bool crcPending = false;
static volatile bool crcCancel = false;
static std::thread crcThread;
@ -126,11 +126,10 @@ namespace Reporting
crcResults[crcFilename] = crc;
crcPending = false;
crcCond.notify_one();
return 0;
}
void QueueCRC(const std::string &gamePath) {
void QueueCRC(const Path &gamePath) {
std::lock_guard<std::mutex> guard(crcLock);
auto it = crcResults.find(gamePath);
@ -151,12 +150,12 @@ namespace Reporting
crcThread = std::thread(CalculateCRCThread);
}
bool HasCRC(const std::string &gamePath) {
bool HasCRC(const Path &gamePath) {
std::lock_guard<std::mutex> guard(crcLock);
return crcResults.find(gamePath) != crcResults.end();
}
uint32_t RetrieveCRC(const std::string &gamePath) {
uint32_t RetrieveCRC(const Path &gamePath) {
QueueCRC(gamePath);
std::unique_lock<std::mutex> guard(crcLock);
@ -173,11 +172,11 @@ namespace Reporting
static uint32_t RetrieveCRCUnlessPowerSaving(const Path &gamePath) {
// It's okay to use it if we have it already.
if (Core_GetPowerSaving() && !HasCRC(gamePath.ToString())) {
if (Core_GetPowerSaving() && !HasCRC(gamePath)) {
return 0;
}
return RetrieveCRC(gamePath.ToString());
return RetrieveCRC(gamePath);
}
static void PurgeCRC() {

View File

@ -21,6 +21,7 @@
#include <vector>
#include "Common/CommonTypes.h"
#include "Common/File/Path.h"
#include "Common/Log.h"
#define DEBUG_LOG_REPORT(t,...) do { DEBUG_LOG(t, __VA_ARGS__); Reporting::ReportMessage(__VA_ARGS__); } while (false)
@ -88,14 +89,14 @@ namespace Reporting
std::vector<std::string> CompatibilitySuggestions();
// Queues game for CRC hash if needed.
void QueueCRC(const std::string &gamePath);
void QueueCRC(const Path &gamePath);
// Returns true if the hash is available, does not queue if not.
bool HasCRC(const std::string &gamePath);
bool HasCRC(const Path &gamePath);
// Blocks until the CRC hash is available for game, and returns it.
// To avoid stalling, call HasCRC() in update() or similar and call this if it returns true.
uint32_t RetrieveCRC(const std::string &gamePath);
uint32_t RetrieveCRC(const Path &gamePath);
// Returns true if that identifier has not been logged yet.
bool ShouldLogNTimes(const char *identifier, int n);

View File

@ -463,7 +463,7 @@ namespace SaveState
}
static void SwapIfExists(const Path &from, const Path &to) {
Path temp = from.WithExtraExtension("tmp");
Path temp = from.WithExtraExtension(".tmp");
if (File::Exists(from)) {
File::Rename(from, temp);
File::Rename(to, from);
@ -486,7 +486,7 @@ namespace SaveState
} else {
DeleteIfExists(fn);
}
File::Rename(fn.WithExtraExtension("tmp"), fn);
File::Rename(fn.WithExtraExtension(".tmp"), fn);
}
if (callback) {
callback(status, message, data);
@ -498,7 +498,7 @@ namespace SaveState
RenameIfExists(shot, shotUndo);
}
SaveScreenshot(shot, Callback(), 0);
Save(fn.WithExtraExtension("tmp"), slot, renameCallback, cbUserData);
Save(fn.WithExtraExtension(".tmp"), slot, renameCallback, cbUserData);
} else {
auto sy = GetI18NCategory("System");
if (callback)
@ -532,7 +532,7 @@ namespace SaveState
bool HasUndoSaveInSlot(const std::string &gameFilename, int slot)
{
Path fn = GenerateSaveSlotFilename(gameFilename, slot, STATE_EXTENSION);
return File::Exists(fn.WithExtraExtension("undo"));
return File::Exists(fn.WithExtraExtension(".undo"));
}
bool HasScreenshotInSlot(const std::string &gameFilename, int slot)

View File

@ -231,7 +231,7 @@ bool CPU_Init() {
Memory::g_PSPModel = g_Config.iPSPModel;
Path filename = coreParameter.fileToStart;
loadedFile = ResolveFileLoaderTarget(ConstructFileLoader(filename.ToString()));
loadedFile = ResolveFileLoaderTarget(ConstructFileLoader(filename));
#if PPSSPP_ARCH(AMD64)
if (g_Config.bCacheFullIsoInRam) {
loadedFile = new RamCachingFileLoader(loadedFile);
@ -241,7 +241,7 @@ bool CPU_Init() {
// TODO: Put this somewhere better?
if (!coreParameter.mountIso.empty()) {
coreParameter.mountIsoLoader = ConstructFileLoader(coreParameter.mountIso.ToString());
coreParameter.mountIsoLoader = ConstructFileLoader(coreParameter.mountIso);
}
MIPSAnalyst::Reset();

View File

@ -15,6 +15,8 @@
// Official git repository and contact information can be found at
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
#include "ppsspp_config.h"
#include <algorithm>
#include <cctype>
#include <cstring>
@ -137,7 +139,7 @@ void GameManager::Update() {
return;
}
// Game downloaded to temporary file - install it!
InstallGameOnThread(curDownload_->url(), fileName.ToString(), true);
InstallGameOnThread(Path(curDownload_->url()), fileName, true);
} else {
ERROR_LOG(HLE, "Expected HTTP status code 200, got status code %d. Install cancelled, deleting partial file '%s'",
curDownload_->ResultCode(), fileName.c_str());
@ -169,7 +171,7 @@ static void countSlashes(const std::string &fileName, int *slashLocation, int *s
}
}
ZipFileContents DetectZipFileContents(std::string fileName, ZipFileInfo *info) {
ZipFileContents DetectZipFileContents(const Path &fileName, ZipFileInfo *info) {
int error = 0;
struct zip *z = zip_open(fileName.c_str(), 0, &error);
if (!z) {
@ -254,7 +256,8 @@ ZipFileContents DetectZipFileContents(struct zip *z, ZipFileInfo *info) {
}
}
bool GameManager::InstallGame(const std::string &url, const std::string &fileName, bool deleteAfter) {
// Parameters need to be by value, since this is a thread func.
bool GameManager::InstallGame(Path url, Path fileName, bool deleteAfter) {
if (installInProgress_) {
ERROR_LOG(HLE, "Cannot have two installs in progress at the same time");
return false;
@ -265,10 +268,11 @@ bool GameManager::InstallGame(const std::string &url, const std::string &fileNam
return false;
}
std::string extension = url.GetFileExtension();
// Examine the URL to guess out what we're installing.
if (endsWithNoCase(url, ".cso") || endsWithNoCase(url, ".iso")) {
if (extension == "cso" || extension == "iso") {
// It's a raw ISO or CSO file. We just copy it to the destination.
std::string shortFilename = GetFilenameFromPath(url);
std::string shortFilename = Path(url).GetFilename();
return InstallRawISO(fileName, shortFilename, deleteAfter);
}
@ -278,6 +282,8 @@ bool GameManager::InstallGame(const std::string &url, const std::string &fileNam
Path pspGame = GetSysDirectory(DIRECTORY_GAME);
Path dest = pspGame;
int error = 0;
// TODO(scoped): zip_open ain't gonna work. zip_fdopen though..
struct zip *z = zip_open(fileName.c_str(), 0, &error);
if (!z) {
ERROR_LOG(HLE, "Failed to open ZIP file '%s', error code=%i", fileName.c_str(), error);
@ -351,7 +357,7 @@ bool GameManager::DetectTexturePackDest(struct zip *z, int iniIndex, Path &dest)
if (games.size() > 1) {
// Check for any supported game on their recent list and use that instead.
for (const std::string &path : g_Config.recentIsos) {
std::string recentID = GetGameID(path);
std::string recentID = GetGameID(Path(path));
if (games.find(recentID) != games.end()) {
gameID = recentID;
break;
@ -371,7 +377,7 @@ void GameManager::SetInstallError(const std::string &err) {
InstallDone();
}
std::string GameManager::GetGameID(const std::string &path) const {
std::string GameManager::GetGameID(const Path &path) const {
auto loader = ConstructFileLoader(path);
std::string id;
@ -495,7 +501,7 @@ bool GameManager::ExtractFile(struct zip *z, int file_index, const Path &outFile
}
// TODO(scoped): This one will be slightly tricky.
bool GameManager::InstallMemstickGame(struct zip *z, const std::string &zipfile, const std::string &dest, const ZipFileInfo &info, bool allowRoot, bool deleteAfter) {
bool GameManager::InstallMemstickGame(struct zip *z, const Path &zipfile, const std::string &dest, const ZipFileInfo &info, bool allowRoot, bool deleteAfter) {
size_t allBytes = 0;
size_t bytesCopied = 0;
@ -591,7 +597,7 @@ bail:
return false;
}
bool GameManager::InstallZippedISO(struct zip *z, int isoFileIndex, std::string zipfile, bool deleteAfter) {
bool GameManager::InstallZippedISO(struct zip *z, int isoFileIndex, const Path &zipfile, bool deleteAfter) {
// Let's place the output file in the currently selected Games directory.
std::string fn = zip_get_name(z, isoFileIndex, 0);
@ -614,7 +620,7 @@ bool GameManager::InstallZippedISO(struct zip *z, int isoFileIndex, std::string
}
zip_close(z);
if (deleteAfter) {
File::Delete(Path(zipfile));
File::Delete(zipfile);
}
z = 0;
@ -625,7 +631,7 @@ bool GameManager::InstallZippedISO(struct zip *z, int isoFileIndex, std::string
return true;
}
bool GameManager::InstallGameOnThread(std::string url, std::string fileName, bool deleteAfter) {
bool GameManager::InstallGameOnThread(const Path &url, const Path &fileName, bool deleteAfter) {
if (installInProgress_) {
return false;
}
@ -633,12 +639,12 @@ bool GameManager::InstallGameOnThread(std::string url, std::string fileName, boo
return true;
}
bool GameManager::InstallRawISO(const std::string &file, const std::string &originalName, bool deleteAfter) {
bool GameManager::InstallRawISO(const Path &file, const std::string &originalName, bool deleteAfter) {
Path destPath = Path(g_Config.currentDirectory) / originalName;
// TODO: To save disk space, we should probably attempt a move first.
if (File::Copy(Path(file), destPath)) {
if (File::Copy(file, destPath)) {
if (deleteAfter) {
File::Delete(Path(file));
File::Delete(file);
}
}
installProgress_ = 1.0f;

View File

@ -73,20 +73,20 @@ public:
}
// Only returns false if there's already an installation in progress.
bool InstallGameOnThread(std::string url, std::string tempFileName, bool deleteAfter);
bool InstallGameOnThread(const Path &url, const Path &tempFileName, bool deleteAfter);
private:
bool InstallGame(const std::string &url, const std::string &tempFileName, bool deleteAfter);
bool InstallMemstickGame(struct zip *z, const std::string &zipFile, const std::string &pspGame, const ZipFileInfo &info, bool allowRoot, bool deleteAfter);
bool InstallZippedISO(struct zip *z, int isoFileIndex, std::string zipfile, bool deleteAfter);
bool InstallRawISO(const std::string &zipFile, const std::string &originalName, bool deleteAfter);
bool InstallGame(Path url, Path tempFileName, bool deleteAfter);
bool InstallMemstickGame(struct zip *z, const Path &zipFile, const std::string &pspGame, const ZipFileInfo &info, bool allowRoot, bool deleteAfter);
bool InstallZippedISO(struct zip *z, int isoFileIndex, const Path &zipfile, bool deleteAfter);
bool InstallRawISO(const Path &zipFile, const std::string &originalName, bool deleteAfter);
void InstallDone();
bool ExtractFile(struct zip *z, int file_index, const Path &outFilename, size_t *bytesCopied, size_t allBytes);
bool DetectTexturePackDest(struct zip *z, int iniIndex, Path &dest);
void SetInstallError(const std::string &err);
std::string GetTempFilename() const;
std::string GetGameID(const std::string &path) const;
std::string GetGameID(const Path &path) const;
std::string GetPBPGameID(FileLoader *loader) const;
std::string GetISOGameID(FileLoader *loader) const;
std::shared_ptr<http::Download> curDownload_;
@ -115,4 +115,4 @@ struct ZipFileInfo {
};
ZipFileContents DetectZipFileContents(struct zip *z, ZipFileInfo *info);
ZipFileContents DetectZipFileContents(std::string fileName, ZipFileInfo *info);
ZipFileContents DetectZipFileContents(const Path &fileName, ZipFileInfo *info);

View File

@ -71,7 +71,7 @@ bool GameInfo::Delete() {
case IdentifiedFileType::PSP_SAVEDATA_DIRECTORY:
{
// TODO: This could be handled by Core/Util/GameManager too somehow.
Path directoryToRemove = Path(ResolvePBPDirectory(filePath_.ToString()));
Path directoryToRemove = ResolvePBPDirectory(filePath_);
INFO_LOG(SYSTEM, "Deleting %s", directoryToRemove.c_str());
if (!File::DeleteDirRecursively(directoryToRemove)) {
ERROR_LOG(SYSTEM, "Failed to delete file");
@ -115,7 +115,7 @@ u64 GameInfo::GetGameSizeInBytes() {
switch (fileType) {
case IdentifiedFileType::PSP_PBP_DIRECTORY:
case IdentifiedFileType::PSP_SAVEDATA_DIRECTORY:
return File::GetDirectoryRecursiveSize(Path(ResolvePBPDirectory(filePath_.ToString())), nullptr, File::GETFILES_GETHIDDEN);
return File::GetDirectoryRecursiveSize(ResolvePBPDirectory(filePath_), nullptr, File::GETFILES_GETHIDDEN);
default:
return GetFileLoader()->FileSize();
@ -201,7 +201,7 @@ bool GameInfo::LoadFromPath(const Path &gamePath) {
std::lock_guard<std::mutex> guard(lock);
// No need to rebuild if we already have it loaded.
if (filePath_ != gamePath) {
fileLoader.reset(ConstructFileLoader(gamePath.ToString()));
fileLoader.reset(ConstructFileLoader(gamePath));
if (!fileLoader)
return false;
filePath_ = gamePath;
@ -220,7 +220,7 @@ std::shared_ptr<FileLoader> GameInfo::GetFileLoader() {
return fileLoader;
}
if (!fileLoader) {
fileLoader.reset(ConstructFileLoader(filePath_.ToString()));
fileLoader.reset(ConstructFileLoader(filePath_));
}
return fileLoader;
}
@ -361,9 +361,9 @@ public:
{
auto pbpLoader = info_->GetFileLoader();
if (info_->fileType == IdentifiedFileType::PSP_PBP_DIRECTORY) {
Path ebootPath = Path(ResolvePBPFile(gamePath_.ToString()));
Path ebootPath = ResolvePBPFile(gamePath_);
if (ebootPath != gamePath_) {
pbpLoader.reset(ConstructFileLoader(ebootPath.ToString()));
pbpLoader.reset(ConstructFileLoader(ebootPath));
}
}
@ -372,7 +372,7 @@ public:
if (pbp.IsELF()) {
goto handleELF;
}
ERROR_LOG(LOADER, "invalid pbp %s\n", pbpLoader->GetPath().c_str());
ERROR_LOG(LOADER, "invalid pbp '%s'\n", pbpLoader->GetPath().c_str());
info_->pending = false;
info_->working = false;
return;
@ -466,7 +466,7 @@ handleELF:
case IdentifiedFileType::PSP_SAVEDATA_DIRECTORY:
{
SequentialHandleAllocator handles;
VirtualDiscFileSystem umd(&handles, gamePath_.c_str());
VirtualDiscFileSystem umd(&handles, gamePath_);
// Alright, let's fetch the PARAM.SFO.
std::string paramSFOcontents;
@ -507,7 +507,7 @@ handleELF:
{
info_->fileType = IdentifiedFileType::PSP_ISO;
SequentialHandleAllocator handles;
VirtualDiscFileSystem umd(&handles, gamePath_.c_str());
VirtualDiscFileSystem umd(&handles, gamePath_);
// Alright, let's fetch the PARAM.SFO.
std::string paramSFOcontents;

View File

@ -96,7 +96,7 @@ void GameScreen::CreateViews() {
tvRegion_->SetShadow(true);
tvCRC_ = infoLayout->Add(new TextView("", ALIGN_LEFT, true, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT)));
tvCRC_->SetShadow(true);
tvCRC_->SetVisibility(Reporting::HasCRC(gamePath_.ToString()) ? V_VISIBLE : V_GONE);
tvCRC_->SetVisibility(Reporting::HasCRC(gamePath_) ? V_VISIBLE : V_GONE);
} else {
tvTitle_ = nullptr;
tvGameSize_ = nullptr;
@ -240,9 +240,9 @@ void GameScreen::render() {
}
}
if (tvCRC_ && Reporting::HasCRC(gamePath_.ToString())) {
if (tvCRC_ && Reporting::HasCRC(gamePath_)) {
auto rp = GetI18NCategory("Reporting");
std::string crc = StringFromFormat("%08X", Reporting::RetrieveCRC(gamePath_.ToString()));
std::string crc = StringFromFormat("%08X", Reporting::RetrieveCRC(gamePath_));
tvCRC_->SetText(ReplaceAll(rp->T("FeedbackCRCValue", "Disc CRC: [VALUE]"), "[VALUE]", crc));
tvCRC_->SetVisibility(UI::V_VISIBLE);
}

View File

@ -29,7 +29,7 @@ void InstallZipScreen::CreateViews() {
using namespace UI;
File::FileInfo fileInfo;
bool success = File::GetFileInfo(Path(zipPath_), &fileInfo);
bool success = File::GetFileInfo(zipPath_, &fileInfo);
auto di = GetI18NCategory("Dialog");
auto iz = GetI18NCategory("InstallZip");
@ -43,7 +43,7 @@ void InstallZipScreen::CreateViews() {
root_->Add(leftColumn);
root_->Add(rightColumnItems);
std::string shortFilename = GetFilenameFromPath(zipPath_);
std::string shortFilename = zipPath_.GetFilename();
// TODO: Do in the background?
ZipFileInfo zipInfo;

View File

@ -26,7 +26,7 @@
class InstallZipScreen : public UIDialogScreenWithBackground {
public:
InstallZipScreen(std::string zipPath) : zipPath_(zipPath) {}
InstallZipScreen(const Path &zipPath) : zipPath_(zipPath) {}
virtual void update() override;
virtual bool key(const KeyInput &key) override;
@ -40,7 +40,7 @@ private:
UI::Choice *backChoice_ = nullptr;
UI::ProgressBar *progressBar_ = nullptr;
UI::TextView *doneView_ = nullptr;
std::string zipPath_;
Path zipPath_;
bool returnToHomebrew_ = true;
bool installStarted_ = false;
bool deleteZipFile_ = false;

View File

@ -69,7 +69,7 @@ bool MainScreen::showHomebrewTab = false;
bool LaunchFile(ScreenManager *screenManager, const Path &path) {
// Depending on the file type, we don't want to launch EmuScreen at all.
auto loader = ConstructFileLoader(path.ToString());
auto loader = ConstructFileLoader(path);
if (!loader) {
return false;
}
@ -79,7 +79,7 @@ bool LaunchFile(ScreenManager *screenManager, const Path &path) {
switch (type) {
case IdentifiedFileType::ARCHIVE_ZIP:
screenManager->push(new InstallZipScreen(path.ToString()));
screenManager->push(new InstallZipScreen(path));
break;
default:
// Let the EmuScreen take care of it.
@ -620,7 +620,7 @@ static bool IsValidPBP(const Path &path, bool allowHomebrew) {
if (!File::Exists(path))
return false;
std::unique_ptr<FileLoader> loader(ConstructFileLoader(path.ToString()));
std::unique_ptr<FileLoader> loader(ConstructFileLoader(path));
PBPReader pbp(loader.get());
std::vector<u8> sfoData;
if (!pbp.GetSubFile(PBP_PARAM_SFO, &sfoData))
@ -1509,7 +1509,7 @@ void UmdReplaceScreen::update() {
}
UI::EventReturn UmdReplaceScreen::OnGameSelected(UI::EventParams &e) {
__UmdReplace(e.s);
__UmdReplace(Path(e.s));
TriggerFinish(DR_OK);
return UI::EVENT_DONE;
}
@ -1525,7 +1525,7 @@ UI::EventReturn UmdReplaceScreen::OnGameSettings(UI::EventParams &e) {
}
UI::EventReturn UmdReplaceScreen::OnGameSelectedInstant(UI::EventParams &e) {
__UmdReplace(e.s);
__UmdReplace(Path(e.s));
TriggerFinish(DR_OK);
return UI::EVENT_DONE;
}

View File

@ -29,7 +29,7 @@
struct ShaderInfo;
struct TextureShaderInfo;
extern std::string boot_filename;
extern Path boot_filename;
void UIBackgroundInit(UIContext &dc);
void UIBackgroundShutdown();

View File

@ -207,7 +207,7 @@ int Win32Mix(short *buffer, int numSamples, int bits, int rate, int channels) {
// globals
static LogListener *logger = nullptr;
std::string boot_filename = "";
Path boot_filename;
void NativeHost::InitSound() {
#if PPSSPP_PLATFORM(IOS)
@ -559,7 +559,7 @@ void NativeInit(int argc, const char *argv[], const char *savegame_dir, const ch
bool gotBootFilename = false;
bool gotoGameSettings = false;
bool gotoTouchScreenTest = false;
boot_filename = "";
boot_filename.clear();
// Parse command line
LogTypes::LOG_LEVELS logLevel = LogTypes::LINFO;
@ -644,10 +644,7 @@ void NativeInit(int argc, const char *argv[], const char *savegame_dir, const ch
}
}
if (okToLoad) {
boot_filename = argv[i];
#ifdef _WIN32
boot_filename = ReplaceAll(boot_filename, "\\", "/");
#endif
boot_filename = Path(std::string(argv[i]));
skipLogo = true;
}
if (okToLoad && okToCheck) {
@ -758,7 +755,7 @@ void NativeInit(int argc, const char *argv[], const char *savegame_dir, const ch
screenManager->switchScreen(new MainScreen());
screenManager->push(new TouchTestScreen());
} else if (skipLogo) {
screenManager->switchScreen(new EmuScreen(Path(boot_filename)));
screenManager->switchScreen(new EmuScreen(boot_filename));
} else {
screenManager->switchScreen(new LogoScreen());
}

View File

@ -270,7 +270,7 @@ void ReportScreen::CreateViews() {
}
#ifdef MOBILE_DEVICE
if (!Core_GetPowerSaving() && !Reporting::HasCRC(gamePath_.ToString())) {
if (!Core_GetPowerSaving() && !Reporting::HasCRC(gamePath_)) {
auto crcWarning = new TextView(rp->T("FeedbackIncludeCRC", "Note: Battery will be used to send a disc CRC"), FLAG_WRAP_TEXT, false, new LinearLayoutParams(Margins(12, 5, 0, 5)));
crcWarning->SetShadow(true);
crcWarning->SetEnabledPtr(&enableReporting_);
@ -334,8 +334,8 @@ void ReportScreen::UpdateCRCInfo() {
auto rp = GetI18NCategory("Reporting");
std::string updated;
if (Reporting::HasCRC(gamePath_.ToString())) {
std::string crc = StringFromFormat("%08X", Reporting::RetrieveCRC(gamePath_.ToString()));
if (Reporting::HasCRC(gamePath_)) {
std::string crc = StringFromFormat("%08X", Reporting::RetrieveCRC(gamePath_));
updated = ReplaceAll(rp->T("FeedbackCRCValue", "Disc CRC: [VALUE]"), "[VALUE]", crc);
} else if (showCRC_) {
updated = rp->T("FeedbackCRCCalculating", "Disc CRC: Calculating...");
@ -395,7 +395,7 @@ EventReturn ReportScreen::HandleBrowser(EventParams &e) {
}
EventReturn ReportScreen::HandleShowCRC(EventParams &e) {
Reporting::QueueCRC(gamePath_.ToString());
Reporting::QueueCRC(gamePath_);
showCRC_ = true;
return EVENT_DONE;
}

View File

@ -426,11 +426,11 @@ bool SavedataBrowser::ByFilename(const UI::View *v1, const UI::View *v2) {
}
static time_t GetTotalSize(const SavedataButton *b) {
auto fileLoader = std::unique_ptr<FileLoader>(ConstructFileLoader(b->GamePath().ToString()));
auto fileLoader = std::unique_ptr<FileLoader>(ConstructFileLoader(b->GamePath()));
switch (Identify_File(fileLoader.get())) {
case IdentifiedFileType::PSP_PBP_DIRECTORY:
case IdentifiedFileType::PSP_SAVEDATA_DIRECTORY:
return File::GetDirectoryRecursiveSize(Path(ResolvePBPDirectory(b->GamePath().ToString())), nullptr, File::GETFILES_GETHIDDEN);
return File::GetDirectoryRecursiveSize(ResolvePBPDirectory(b->GamePath()), nullptr, File::GETFILES_GETHIDDEN);
default:
return fileLoader->FileSize();
@ -447,7 +447,7 @@ bool SavedataBrowser::BySize(const UI::View *v1, const UI::View *v2) {
}
static time_t GetDateSeconds(const SavedataButton *b) {
auto fileLoader = std::unique_ptr<FileLoader>(ConstructFileLoader(b->GamePath().ToString()));
auto fileLoader = std::unique_ptr<FileLoader>(ConstructFileLoader(b->GamePath()));
tm datetm;
bool success;
if (Identify_File(fileLoader.get()) == IdentifiedFileType::PSP_SAVEDATA_DIRECTORY) {

View File

@ -175,6 +175,6 @@ size_t StorageFileLoader::ReadAt(s64 absolutePos, size_t bytes, size_t count, vo
}
}
FileLoader *StorageFileLoaderFactory::ConstructFileLoader(const std::string &filename) {
FileLoader *StorageFileLoaderFactory::ConstructFileLoader(const Path &filename) {
return file_ ? new StorageFileLoader(file_) : nullptr;
}

View File

@ -9,6 +9,7 @@
#include <string>
#include "Common/CommonTypes.h"
#include "Common/File/Path.h"
#include "Core/Loaders.h"
// This thing is a terrible abomination that wraps asynchronous file access behind a synchronous interface,
@ -24,7 +25,7 @@ public:
bool IsDirectory() override;
s64 FileSize() override;
std::string GetPath() const override;
Path GetPath() const override;
size_t ReadAt(s64 absolutePos, size_t bytes, size_t count, void *data, Flags flags = Flags::NONE) override;
@ -73,7 +74,7 @@ private:
class StorageFileLoaderFactory : public FileLoaderFactory {
public:
StorageFileLoaderFactory(Windows::Storage::StorageFile ^file, IdentifiedFileType fileType) : file_(file), fileType_(fileType) { }
FileLoader *ConstructFileLoader(const std::string &filename) override;
FileLoader *ConstructFileLoader(const Path &filename) override;
private:
Windows::Storage::StorageFile ^file_;

View File

@ -450,8 +450,7 @@ namespace MainWindow {
}
if (W32Util::BrowseForFileName(true, GetHWND(), L"Switch UMD", 0, ConvertUTF8ToWString(filter).c_str(), L"*.pbp;*.elf;*.iso;*.cso;", fn)) {
fn = ReplaceAll(fn, "\\", "/");
__UmdReplace(fn);
__UmdReplace(Path(fn));
}
}

View File

@ -60,6 +60,7 @@ struct JNIEnv {};
#include "Common/System/NativeApp.h"
#include "Common/System/System.h"
#include "Common/Thread/ThreadUtil.h"
#include "Common/File/Path.h"
#include "Common/File/VFS/VFS.h"
#include "Common/File/VFS/AssetReader.h"
#include "Common/Input/InputState.h"
@ -248,9 +249,9 @@ int Android_OpenContentUriFd(const std::string &filename) {
class ContentURIFileLoader : public ProxiedFileLoader {
public:
ContentURIFileLoader(const std::string &filename)
ContentURIFileLoader(const Path &filename)
: ProxiedFileLoader(nullptr) { // we overwrite the nullptr below
int fd = Android_OpenContentUriFd(filename);
int fd = Android_OpenContentUriFd(filename.ToString());
INFO_LOG(SYSTEM, "Fd %d for content URI: '%s'", fd, filename.c_str());
backend_ = new LocalFileLoader(fd, filename);
}
@ -267,7 +268,7 @@ public:
class AndroidContentLoaderFactory : public FileLoaderFactory {
public:
AndroidContentLoaderFactory() {}
FileLoader *ConstructFileLoader(const std::string &filename) override {
FileLoader *ConstructFileLoader(const Path &filename) override {
return new ContentURIFileLoader(filename);
}
};

View File

@ -168,24 +168,17 @@ protected:
size_t pos_ = 0;
};
std::string ExpectedFromFilename(const std::string &bootFilename) {
size_t pos = bootFilename.find_last_of('.');
if (pos == bootFilename.npos) {
return bootFilename + ".expected";
Path ExpectedScreenshotFromFilename(const Path &bootFilename) {
std::string extension = bootFilename.GetFileExtension();
if (extension.empty()) {
return bootFilename.WithExtraExtension(".bmp");
}
return bootFilename.substr(0, pos) + ".expected";
}
std::string ExpectedScreenshotFromFilename(const std::string &bootFilename) {
size_t pos = bootFilename.find_last_of('.');
if (pos == bootFilename.npos) {
return bootFilename + ".bmp";
}
// Let's use pngs as the default for ppdmp tests.
if (bootFilename.substr(pos) == ".ppdmp") {
return bootFilename.substr(0, pos) + ".png";
if (extension == ".ppdmp") {
return bootFilename.WithReplacedExtension(".png");
}
return bootFilename.substr(0, pos) + ".expected.bmp";
return bootFilename.WithReplacedExtension(".expected.bmp");
}
static std::string ChopFront(std::string s, std::string front)
@ -209,14 +202,14 @@ static std::string ChopEnd(std::string s, std::string end)
return s;
}
std::string GetTestName(const std::string &bootFilename)
std::string GetTestName(const Path &bootFilename)
{
// Kinda ugly, trying to guesstimate the test name from filename...
return ChopEnd(ChopFront(ChopFront(bootFilename, "tests/"), "pspautotests/tests/"), ".prx");
return ChopEnd(ChopFront(ChopFront(bootFilename.ToString(), "tests/"), "pspautotests/tests/"), ".prx");
}
bool CompareOutput(const std::string &bootFilename, const std::string &output, bool verbose) {
std::string expect_filename = ExpectedFromFilename(bootFilename);
bool CompareOutput(const Path &bootFilename, const std::string &output, bool verbose) {
Path expect_filename = bootFilename.WithReplacedExtension("prx", "expected");
std::unique_ptr<FileLoader> expect_loader(ConstructFileLoader(expect_filename));
if (expect_loader->Exists()) {
@ -372,7 +365,7 @@ std::vector<u32> TranslateDebugBufferToCompare(const GPUDebugBuffer *buffer, u32
return data;
}
double CompareScreenshot(const std::vector<u32> &pixels, u32 stride, u32 w, u32 h, const std::string& screenshotFilename, std::string &error)
double CompareScreenshot(const std::vector<u32> &pixels, u32 stride, u32 w, u32 h, const Path& screenshotFilename, std::string &error)
{
if (pixels.size() < stride * h)
{
@ -388,7 +381,7 @@ double CompareScreenshot(const std::vector<u32> &pixels, u32 stride, u32 w, u32
if (loader->Exists()) {
uint8_t header[2];
if (loader->ReadAt(0, 2, header) != 2) {
error = "Unable to read screenshot data: " + screenshotFilename;
error = "Unable to read screenshot data: " + screenshotFilename.ToVisualString();
return -1.0f;
}
@ -397,7 +390,7 @@ double CompareScreenshot(const std::vector<u32> &pixels, u32 stride, u32 w, u32
asBitmap = true;
// The bitmap header is 14 + 40 bytes. We could validate it but the test would fail either way.
if (reference && loader->ReadAt(14 + 40, sizeof(u32), stride * h, reference) != stride * h) {
error = "Unable to read screenshot data: " + screenshotFilename;
error = "Unable to read screenshot data: " + screenshotFilename.ToVisualString();
return -1.0f;
}
} else {
@ -405,23 +398,23 @@ double CompareScreenshot(const std::vector<u32> &pixels, u32 stride, u32 w, u32
std::vector<uint8_t> compressed;
compressed.resize(loader->FileSize());
if (loader->ReadAt(0, compressed.size(), &compressed[0]) != compressed.size()) {
error = "Unable to read screenshot data: " + screenshotFilename;
error = "Unable to read screenshot data: " + screenshotFilename.ToVisualString();
return -1.0f;
}
int width, height;
if (!pngLoadPtr(&compressed[0], compressed.size(), &width, &height, (unsigned char **)&reference)) {
error = "Unable to read screenshot data: " + screenshotFilename;
error = "Unable to read screenshot data: " + screenshotFilename.ToVisualString();
return -1.0f;
}
}
} else {
error = "Unable to read screenshot: " + screenshotFilename;
error = "Unable to read screenshot: " + screenshotFilename.ToVisualString();
return -1.0f;
}
if (!reference) {
error = "Unable to allocate screenshot data: " + screenshotFilename;
error = "Unable to allocate screenshot data: " + screenshotFilename.ToVisualString();
return -1.0f;
}

View File

@ -19,6 +19,7 @@
#include <vector>
#include "Common/CommonTypes.h"
#include "Common/File/Path.h"
struct GPUDebugBuffer;
@ -27,10 +28,10 @@ extern std::string currentTestName;
void TeamCityPrint(const char *fmt, ...);
void GitHubActionsPrint(const char *type, const char *fmt, ...);
std::string ExpectedFromFilename(const std::string &bootFilename);
std::string ExpectedScreenshotFromFilename(const std::string &bootFilename);
std::string GetTestName(const std::string &bootFilename);
Path ExpectedFromFilename(const Path &bootFilename);
Path ExpectedScreenshotFromFilename(const Path &bootFilename);
std::string GetTestName(const Path &bootFilename);
bool CompareOutput(const std::string &bootFilename, const std::string &output, bool verbose);
bool CompareOutput(const Path &bootFilename, const std::string &output, bool verbose);
std::vector<u32> TranslateDebugBufferToCompare(const GPUDebugBuffer *buffer, u32 stride, u32 h);
double CompareScreenshot(const std::vector<u32> &pixels, u32 stride, u32 w, u32 h, const std::string& screenshotFilename, std::string &error);
double CompareScreenshot(const std::vector<u32> &pixels, u32 stride, u32 w, u32 h, const Path &screenshotFilename, std::string &error);

View File

@ -152,7 +152,7 @@ static HeadlessHost *getHost(GPUCore gpuCore) {
bool RunAutoTest(HeadlessHost *headlessHost, CoreParameter &coreParameter, bool autoCompare, bool verbose, double timeout)
{
// Kinda ugly, trying to guesstimate the test name from filename...
currentTestName = GetTestName(coreParameter.fileToStart.ToString());
currentTestName = GetTestName(coreParameter.fileToStart);
std::string output;
if (autoCompare)
@ -172,7 +172,7 @@ bool RunAutoTest(HeadlessHost *headlessHost, CoreParameter &coreParameter, bool
host->BootDone();
if (autoCompare)
headlessHost->SetComparisonScreenshot(ExpectedScreenshotFromFilename(coreParameter.fileToStart.ToString()));
headlessHost->SetComparisonScreenshot(ExpectedScreenshotFromFilename(coreParameter.fileToStart));
bool passed = true;
// TODO: We must have some kind of stack overflow or we're not following the ABI right.
@ -221,7 +221,7 @@ bool RunAutoTest(HeadlessHost *headlessHost, CoreParameter &coreParameter, bool
headlessHost->FlushDebugOutput();
if (autoCompare && passed)
passed = CompareOutput(coreParameter.fileToStart.ToString(), output, verbose);
passed = CompareOutput(coreParameter.fileToStart, output, verbose);
TeamCityPrint("testFinished name='%s'", currentTestName.c_str());
@ -423,7 +423,7 @@ int main(int argc, const char* argv[])
g_Config.flash0Directory = Path(File::GetExeDirectory()) / "assets/flash0";
if (screenshotFilename != 0)
headlessHost->SetComparisonScreenshot(screenshotFilename);
headlessHost->SetComparisonScreenshot(Path(std::string(screenshotFilename)));
#ifdef __ANDROID__
// For some reason the debugger installs it with this name?
@ -456,7 +456,7 @@ int main(int argc, const char* argv[])
bool passed = RunAutoTest(headlessHost, coreParameter, autoCompare, verbose, timeout);
if (autoCompare)
{
std::string testName = GetTestName(coreParameter.fileToStart.ToString());
std::string testName = GetTestName(coreParameter.fileToStart);
if (passed)
{
passedTests.push_back(testName);

View File

@ -17,6 +17,8 @@
#pragma once
#include "Common/File/Path.h"
#include "Core/CoreParameter.h"
#include "Core/Host.h"
#include "Core/Debugger/SymbolMap.h"
@ -66,7 +68,7 @@ public:
}
}
virtual void SetComparisonScreenshot(const std::string &filename) {
virtual void SetComparisonScreenshot(const Path &filename) {
comparisonScreenshot_ = filename;
}
@ -80,7 +82,7 @@ public:
protected:
void SendOrCollectDebugOutput(const std::string &output);
std::string comparisonScreenshot_;
Path comparisonScreenshot_;
std::string debugOutputBuffer_;
GPUCore gpuCore_;
GraphicsContext *gfx_ = nullptr;

View File

@ -588,13 +588,18 @@ static bool TestPath() {
EXPECT_EQ_STR(path.ToString(), std::string("/asdf/jkl"));
Path path2("/asdf/jkl");
EXPECT_EQ_STR(path2.ToString(), std::string("/asdf/jkl"));
EXPECT_EQ_STR(path2.NavigateUp().ToString(), std::string("/asdf"));
Path path3 = path2 / "foo/bar";
EXPECT_EQ_STR(path3.WithExtraExtension("txt").ToString(), std::string("/asdf/jkl/foo/bar.txt"));
EXPECT_EQ_STR(path3.WithExtraExtension(".txt").ToString(), std::string("/asdf/jkl/foo/bar.txt"));
EXPECT_EQ_STR(Path("foo.bar/hello").GetFileExtension(), std::string(""));
EXPECT_EQ_STR(Path("foo.bar/hello.txt").WithReplacedExtension("txt", "html").ToString(), std::string("foo.bar/hello.html"));
EXPECT_EQ_STR(Path("foo.bar/hello.txt").WithReplacedExtension(".txt", ".html").ToString(), std::string("foo.bar/hello.html"));
EXPECT_EQ_STR(Path("C:\\Yo").GetDirectory(), std::string("C:"));
EXPECT_EQ_STR(Path("C:\\Yo").GetFilename(), std::string("Yo"));
EXPECT_EQ_STR(Path("C:\\Yo\\Lo").GetDirectory(), std::string("C:/Yo"));
EXPECT_EQ_STR(Path("C:\\Yo\\Lo").GetFilename(), std::string("Lo"));
return true;
}