Rewrite FileSearch and improve ScanDirectoryTree.

- FileSearch is now just one function, and it converts the original glob
  into a regex on all platforms rather than relying on native Windows
  pattern matching on there and a complete hack elsewhere.  It now
  supports recursion out of the box rather than manually expanding
  into a full list of directories in multiple call sites.

  - This adds a GCC >= 4.9 dependency due to older versions having
  outright broken <regex>.  MSVC is fine with it.

- ScanDirectoryTree returns the parent entry rather than filling parts
  of it in via reference.  The count is now stored in the entry like it
  was for subdirectories.

- .glsl file search is now done with DoFileSearch.

- IOCTLV_READ_DIR now uses ScanDirectoryTree directly and sorts the
  results after replacements for better determinism.
This commit is contained in:
comex
2014-11-15 15:46:40 -05:00
parent 6ff3fcee59
commit a225426510
17 changed files with 156 additions and 348 deletions

View File

@ -151,16 +151,7 @@ GCMemcardDirectory::GCMemcardDirectory(const std::string& directory, int slot, u
hdrfile.ReadBytes(&m_hdr, BLOCK_SIZE);
}
File::FSTEntry FST_Temp;
File::ScanDirectoryTree(m_SaveDirectory, FST_Temp);
CFileSearch::XStringVector Directory;
Directory.push_back(m_SaveDirectory);
CFileSearch::XStringVector Extensions;
Extensions.push_back("*.gci");
CFileSearch FileSearch(Extensions, Directory);
const CFileSearch::XStringVector& rFilenames = FileSearch.GetFileNames();
std::vector<std::string> rFilenames = DoFileSearch({"*.gci"}, {m_SaveDirectory});
if (rFilenames.size() > 112)
{
@ -170,7 +161,7 @@ GCMemcardDirectory::GCMemcardDirectory(const std::string& directory, int slot, u
4000);
}
for (auto gciFile : rFilenames)
for (const std::string& gciFile : rFilenames)
{
if (m_saves.size() == DIRLEN)
{

View File

@ -67,9 +67,8 @@ void CWiiSaveCrypted::ExportAllSaves()
const u32 path_mask = 0x00010000;
for (int i = 0; i < 8; ++i)
{
File::FSTEntry fst_tmp;
std::string folder = StringFromFormat("%s/%08x/", title_folder.c_str(), path_mask | i);
File::ScanDirectoryTree(folder, fst_tmp);
File::FSTEntry fst_tmp = File::ScanDirectoryTree(folder, false);
for (const File::FSTEntry& entry : fst_tmp.children)
{
@ -627,8 +626,7 @@ void CWiiSaveCrypted::ScanForFiles(const std::string& save_directory, std::vecto
file_list.push_back(directories[i]);
}
File::FSTEntry fst_tmp;
File::ScanDirectoryTree(directories[i], fst_tmp);
File::FSTEntry fst_tmp = File::ScanDirectoryTree(directories[i], false);
for (const File::FSTEntry& elem : fst_tmp.children)
{
if (elem.virtualName != "banner.bin")

View File

@ -5,7 +5,6 @@
#include "Common/ChunkFile.h"
#include "Common/CommonPaths.h"
#include "Common/CommonTypes.h"
#include "Common/FileSearch.h"
#include "Common/FileUtil.h"
#include "Common/NandPaths.h"
#include "Common/StringUtil.h"
@ -106,25 +105,28 @@ IPCCommandResult CWII_IPC_HLE_Device_fs::IOCtlV(u32 _CommandAddress)
break;
}
// make a file search
CFileSearch::XStringVector Directories;
Directories.push_back(DirName);
CFileSearch::XStringVector Extensions;
Extensions.push_back("*.*");
CFileSearch FileSearch(Extensions, Directories);
File::FSTEntry entry = File::ScanDirectoryTree(DirName, false);
// it is one
if ((CommandBuffer.InBuffer.size() == 1) && (CommandBuffer.PayloadBuffer.size() == 1))
{
size_t numFile = FileSearch.GetFileNames().size();
size_t numFile = entry.children.size();
INFO_LOG(WII_IPC_FILEIO, "\t%lu files found", (unsigned long)numFile);
Memory::Write_U32((u32)numFile, CommandBuffer.PayloadBuffer[0].m_Address);
}
else
{
for (File::FSTEntry& child : entry.children)
{
// Decode entities of invalid file system characters so that
// games (such as HP:HBP) will be able to find what they expect.
for (const Common::replace_t& r : replacements)
child.virtualName = ReplaceAll(child.virtualName, r.second, {r.first});
}
std::sort(entry.children.begin(), entry.children.end(), [](const File::FSTEntry& one, const File::FSTEntry& two) { return one.virtualName < two.virtualName; });
u32 MaxEntries = Memory::Read_U32(CommandBuffer.InBuffer[0].m_Address);
memset(Memory::GetPointer(CommandBuffer.PayloadBuffer[0].m_Address), 0, CommandBuffer.PayloadBuffer[0].m_Size);
@ -132,22 +134,10 @@ IPCCommandResult CWII_IPC_HLE_Device_fs::IOCtlV(u32 _CommandAddress)
size_t numFiles = 0;
char* pFilename = (char*)Memory::GetPointer((u32)(CommandBuffer.PayloadBuffer[0].m_Address));
for (size_t i=0; i<FileSearch.GetFileNames().size(); i++)
for (size_t i=0; i < entry.children.size() && i < MaxEntries; i++)
{
if (i >= MaxEntries)
break;
const std::string& FileName = entry.children[i].virtualName;
std::string name, ext;
SplitPath(FileSearch.GetFileNames()[i], nullptr, &name, &ext);
std::string FileName = name + ext;
// Decode entities of invalid file system characters so that
// games (such as HP:HBP) will be able to find what they expect.
for (const Common::replace_t& r : replacements)
{
for (size_t j = 0; (j = FileName.find(r.second, j)) != FileName.npos; ++j)
FileName.replace(j, r.second.length(), 1, r.first);
}
strcpy(pFilename, FileName.c_str());
pFilename += FileName.length();
@ -192,10 +182,9 @@ IPCCommandResult CWII_IPC_HLE_Device_fs::IOCtlV(u32 _CommandAddress)
}
else
{
File::FSTEntry parentDir;
// add one for the folder itself, allows some games to create their save files
// R8XE52 (Jurassic: The Hunted), STEETR (Tetris Party Deluxe) now create their saves with this change
iNodes = 1 + File::ScanDirectoryTree(path, parentDir);
File::FSTEntry parentDir = File::ScanDirectoryTree(path, true);
// add one for the folder itself
iNodes = 1 + (u32)parentDir.size;
u64 totalSize = ComputeTotalFileSize(parentDir); // "Real" size, to be converted to nand blocks
@ -542,8 +531,7 @@ void CWII_IPC_HLE_Device_fs::DoState(PointerWrap& p)
{
//recurse through tmp and save dirs and files
File::FSTEntry parentEntry;
File::ScanDirectoryTree(Path, parentEntry);
File::FSTEntry parentEntry = File::ScanDirectoryTree(Path, true);
std::deque<File::FSTEntry> todo;
todo.insert(todo.end(), parentEntry.children.begin(),
parentEntry.children.end());