mirror of
https://github.com/hrydgard/ppsspp.git
synced 2024-11-27 07:20:49 +00:00
UI: Avoid using game info cache in savedata sort.
It can change mid-sort causing the sorting results to be inconsistent, which will crash many implementations of std::stable_sort. Also, fix an issue where it kept resorting after it didn't need to and make it strictly ordered for equal dates/sizes. Fixes #11892.
This commit is contained in:
parent
d6d6dbb772
commit
a99549c451
@ -110,27 +110,11 @@ bool GameInfo::Delete() {
|
||||
}
|
||||
}
|
||||
|
||||
static int64_t GetDirectoryRecursiveSize(const std::string &path) {
|
||||
std::vector<FileInfo> fileInfo;
|
||||
getFilesInDir(path.c_str(), &fileInfo);
|
||||
int64_t sizeSum = 0;
|
||||
// Note: getFileInDir does not fill in fileSize properly.
|
||||
for (size_t i = 0; i < fileInfo.size(); i++) {
|
||||
FileInfo finfo;
|
||||
getFileInfo(fileInfo[i].fullName.c_str(), &finfo);
|
||||
if (!finfo.isDirectory)
|
||||
sizeSum += finfo.size;
|
||||
else
|
||||
sizeSum += GetDirectoryRecursiveSize(finfo.fullName);
|
||||
}
|
||||
return sizeSum;
|
||||
}
|
||||
|
||||
u64 GameInfo::GetGameSizeInBytes() {
|
||||
switch (fileType) {
|
||||
case IdentifiedFileType::PSP_PBP_DIRECTORY:
|
||||
case IdentifiedFileType::PSP_SAVEDATA_DIRECTORY:
|
||||
return GetDirectoryRecursiveSize(ResolvePBPDirectory(filePath_));
|
||||
return getDirectoryRecursiveSize(ResolvePBPDirectory(filePath_), nullptr, GETFILES_GETHIDDEN);
|
||||
|
||||
default:
|
||||
return GetFileLoader()->FileSize();
|
||||
|
@ -132,8 +132,9 @@ public:
|
||||
: UI::LinearLayout(orientation, layoutParams) {
|
||||
}
|
||||
|
||||
void SetCompare(CompareFunc lessFunc, DoneFunc) {
|
||||
void SetCompare(CompareFunc lessFunc, DoneFunc doneFunc) {
|
||||
lessFunc_ = lessFunc;
|
||||
doneFunc_ = doneFunc;
|
||||
}
|
||||
|
||||
void Update() override;
|
||||
@ -336,43 +337,56 @@ bool SavedataBrowser::ByFilename(const UI::View *v1, const UI::View *v2) {
|
||||
return strcmp(b1->GamePath().c_str(), b2->GamePath().c_str()) < 0;
|
||||
}
|
||||
|
||||
static time_t GetTotalSize(const SavedataButton *b) {
|
||||
auto fileLoader = std::unique_ptr<FileLoader>(ConstructFileLoader(b->GamePath()));
|
||||
tm datetm;
|
||||
bool success;
|
||||
switch (Identify_File(fileLoader.get())) {
|
||||
case IdentifiedFileType::PSP_PBP_DIRECTORY:
|
||||
case IdentifiedFileType::PSP_SAVEDATA_DIRECTORY:
|
||||
return getDirectoryRecursiveSize(ResolvePBPDirectory(b->GamePath()), nullptr, GETFILES_GETHIDDEN);
|
||||
|
||||
default:
|
||||
return fileLoader->FileSize();
|
||||
}
|
||||
}
|
||||
|
||||
bool SavedataBrowser::BySize(const UI::View *v1, const UI::View *v2) {
|
||||
const SavedataButton *b1 = static_cast<const SavedataButton *>(v1);
|
||||
const SavedataButton *b2 = static_cast<const SavedataButton *>(v2);
|
||||
|
||||
std::shared_ptr<GameInfo> g1info = g_gameInfoCache->GetInfo(nullptr, b1->GamePath(), GAMEINFO_WANTSIZE);
|
||||
std::shared_ptr<GameInfo> g2info = g_gameInfoCache->GetInfo(nullptr, b2->GamePath(), GAMEINFO_WANTSIZE);
|
||||
if (GetTotalSize(b1) > GetTotalSize(b2))
|
||||
return true;
|
||||
return strcmp(b1->GamePath().c_str(), b2->GamePath().c_str()) < 0;
|
||||
}
|
||||
|
||||
// They might be zero, but that's fine.
|
||||
return g1info->gameSize > g2info->gameSize;
|
||||
static time_t GetDateSeconds(const SavedataButton *b) {
|
||||
auto fileLoader = std::unique_ptr<FileLoader>(ConstructFileLoader(b->GamePath()));
|
||||
tm datetm;
|
||||
bool success;
|
||||
if (Identify_File(fileLoader.get()) == IdentifiedFileType::PSP_SAVEDATA_DIRECTORY) {
|
||||
success = File::GetModifTime(b->GamePath() + "/PARAM.SFO", datetm);
|
||||
} else {
|
||||
success = File::GetModifTime(b->GamePath(), datetm);
|
||||
}
|
||||
|
||||
if (success) {
|
||||
return mktime(&datetm);
|
||||
}
|
||||
return (time_t)0;
|
||||
}
|
||||
|
||||
bool SavedataBrowser::ByDate(const UI::View *v1, const UI::View *v2) {
|
||||
const SavedataButton *b1 = static_cast<const SavedataButton *>(v1);
|
||||
const SavedataButton *b2 = static_cast<const SavedataButton *>(v2);
|
||||
|
||||
auto getDateSeconds = [&](const SavedataButton *b) {
|
||||
std::shared_ptr<GameInfo> ginfo = g_gameInfoCache->GetInfo(nullptr, b->GamePath(), 0);
|
||||
tm datetm;
|
||||
bool success;
|
||||
if (ginfo && ginfo->fileType == IdentifiedFileType::PSP_SAVEDATA_DIRECTORY) {
|
||||
success = File::GetModifTime(b->GamePath() + "/PARAM.SFO", datetm);
|
||||
} else {
|
||||
success = File::GetModifTime(b->GamePath(), datetm);
|
||||
}
|
||||
|
||||
if (success) {
|
||||
return mktime(&datetm);
|
||||
}
|
||||
return (time_t)0;
|
||||
};
|
||||
|
||||
return getDateSeconds(b1) > getDateSeconds(b2);
|
||||
if (GetDateSeconds(b1) > GetDateSeconds(b2))
|
||||
return true;
|
||||
return strcmp(b1->GamePath().c_str(), b2->GamePath().c_str()) < 0;
|
||||
}
|
||||
|
||||
bool SavedataBrowser::SortDone() {
|
||||
PrioritizedWorkQueue *wq = g_gameInfoCache->WorkQueue();
|
||||
return wq->Done();
|
||||
return true;
|
||||
}
|
||||
|
||||
void SavedataBrowser::Refresh() {
|
||||
|
@ -297,6 +297,22 @@ size_t getFilesInDir(const char *directory, std::vector<FileInfo> *files, const
|
||||
return foundEntries;
|
||||
}
|
||||
|
||||
int64_t getDirectoryRecursiveSize(const std::string &path, const char *filter, int flags) {
|
||||
std::vector<FileInfo> fileInfo;
|
||||
getFilesInDir(path.c_str(), &fileInfo, filter, flags);
|
||||
int64_t sizeSum = 0;
|
||||
// Note: getFileInDir does not fill in fileSize properly.
|
||||
for (size_t i = 0; i < fileInfo.size(); i++) {
|
||||
FileInfo finfo;
|
||||
getFileInfo(fileInfo[i].fullName.c_str(), &finfo);
|
||||
if (!finfo.isDirectory)
|
||||
sizeSum += finfo.size;
|
||||
else
|
||||
sizeSum += getDirectoryRecursiveSize(finfo.fullName, filter, flags);
|
||||
}
|
||||
return sizeSum;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
// Returns a vector with the device names
|
||||
std::vector<std::string> getWindowsDrives()
|
||||
|
@ -34,7 +34,8 @@ FILE *openCFile(const std::string &filename, const char *mode);
|
||||
enum {
|
||||
GETFILES_GETHIDDEN = 1
|
||||
};
|
||||
size_t getFilesInDir(const char *directory, std::vector<FileInfo> *files, const char *filter = 0, int flags = 0);
|
||||
size_t getFilesInDir(const char *directory, std::vector<FileInfo> *files, const char *filter = nullptr, int flags = 0);
|
||||
int64_t getDirectoryRecursiveSize(const std::string &path, const char *filter = nullptr, int flags = 0);
|
||||
|
||||
#ifdef _WIN32
|
||||
std::vector<std::string> getWindowsDrives();
|
||||
|
Loading…
Reference in New Issue
Block a user