Trust the gamelist by not checking whether files exist and also improve the algorithm for parsing the gamelist.

This commit is contained in:
Alex Jones 2016-08-09 21:26:30 +01:00
parent 0ab75f8996
commit 454a18f9ec
6 changed files with 51 additions and 23 deletions

View file

@ -56,8 +56,7 @@ FileData::~FileData()
if(mParent)
mParent->removeChild(this);
while(mChildren.size())
delete mChildren.back();
mChildren.clear();
}
std::string FileData::getDisplayName() const
@ -107,15 +106,20 @@ void FileData::addChild(FileData* file)
assert(mType == FOLDER);
assert(file->getParent() == NULL);
const std::string key = file->getPath().filename().string();
if (mChildrenByFilename.find(key) == mChildrenByFilename.end())
{
mChildrenByFilename[key] = file;
mChildren.push_back(file);
file->mParent = this;
}
}
void FileData::removeChild(FileData* file)
{
assert(mType == FOLDER);
assert(file->getParent() == this);
mChildrenByFilename.erase(file->getPath().filename().string());
for(auto it = mChildren.begin(); it != mChildren.end(); it++)
{
if(*it == file)
@ -127,6 +131,7 @@ void FileData::removeChild(FileData* file)
// File somehow wasn't in our children.
assert(false);
}
void FileData::sort(ComparisonFunction& comparator, bool ascending)

View file

@ -1,7 +1,8 @@
#pragma once
#include <vector>
#include <unordered_map>
#include <string>
#include <vector>
#include <boost/filesystem.hpp>
#include "MetaData.h"
@ -39,6 +40,7 @@ public:
inline FileType getType() const { return mType; }
inline const boost::filesystem::path& getPath() const { return mPath; }
inline FileData* getParent() const { return mParent; }
inline const std::unordered_map<std::string, FileData*>& getChildrenByFilename() const { return mChildrenByFilename; }
inline const std::vector<FileData*>& getChildren() const { return mChildren; }
inline SystemData* getSystem() const { return mSystem; }
@ -76,5 +78,6 @@ private:
boost::filesystem::path mPath;
SystemData* mSystem;
FileData* mParent;
std::unordered_map<std::string,FileData*> mChildrenByFilename;
std::vector<FileData*> mChildren;
};

View file

@ -8,13 +8,21 @@
namespace fs = boost::filesystem;
FileData* findOrCreateFile(SystemData* system, const boost::filesystem::path& path, FileType type)
FileData* findOrCreateFile(SystemData* system, const boost::filesystem::path& path, FileType type, bool trustGamelist)
{
// first, verify that path is within the system's root folder
FileData* root = system->getRootFolder();
fs::path relative;
bool contains = false;
fs::path relative = removeCommonPath(path, root->getPath(), contains);
if (trustGamelist)
{
relative = removeCommonPathUsingStrings(path, root->getPath(), contains);
}
else
{
relative = removeCommonPath(path, root->getPath(), contains);
}
if(!contains)
{
LOG(LogError) << "File path \"" << path << "\" is outside system path \"" << system->getStartPath() << "\"";
@ -26,16 +34,12 @@ FileData* findOrCreateFile(SystemData* system, const boost::filesystem::path& pa
bool found = false;
while(path_it != relative.end())
{
const std::vector<FileData*>& children = treeNode->getChildren();
found = false;
for(auto child_it = children.begin(); child_it != children.end(); child_it++)
{
if((*child_it)->getPath().filename() == *path_it)
{
treeNode = *child_it;
found = true;
break;
}
const std::unordered_map<std::string, FileData*>& children = treeNode->getChildrenByFilename();
std::string key = path_it->string();
found = children.find(key) != children.end();
if (found) {
treeNode = children.at(key);
}
// this is the end
@ -79,6 +83,7 @@ FileData* findOrCreateFile(SystemData* system, const boost::filesystem::path& pa
void parseGamelist(SystemData* system)
{
bool trustGamelist = Settings::getInstance()->getBool("ParseGamelistOnly");
std::string xmlpath = system->getGamelistPath(false);
if(!boost::filesystem::exists(xmlpath))
@ -114,13 +119,13 @@ void parseGamelist(SystemData* system)
{
fs::path path = resolvePath(fileNode.child("path").text().get(), relativeTo, false);
if(!boost::filesystem::exists(path))
if(!trustGamelist && !boost::filesystem::exists(path))
{
LOG(LogWarning) << "File \"" << path << "\" does not exist! Ignoring.";
continue;
}
FileData* file = findOrCreateFile(system, path, type);
FileData* file = findOrCreateFile(system, path, type, trustGamelist);
if(!file)
{
LOG(LogError) << "Error finding/creating FileData for \"" << path << "\", skipping.";

View file

@ -198,7 +198,7 @@ void SystemData::populateFolder(FileData* folder)
populateFolder(newFolder);
//ignore folders that do not contain games
if(newFolder->getChildren().size() == 0)
if(newFolder->getChildrenByFilename().size() == 0)
delete newFolder;
else
folder->addChild(newFolder);
@ -311,7 +311,7 @@ bool SystemData::loadConfig()
path = genericPath.generic_string();
SystemData* newSys = new SystemData(name, fullname, path, extensions, cmd, platformIds, themeFolder);
if(newSys->getRootFolder()->getChildren().size() == 0)
if(newSys->getRootFolder()->getChildrenByFilename().size() == 0)
{
LOG(LogWarning) << "System \"" << name << "\" has no games! Ignoring it.";
delete newSys;

View file

@ -100,6 +100,20 @@ fs::path resolvePath(const fs::path& path, const fs::path& relativeTo, bool allo
return path;
}
fs::path removeCommonPathUsingStrings(const fs::path& path, const fs::path& relativeTo, bool& contains)
{
std::string pathStr = path.c_str();
std::string relativeToStr = relativeTo.c_str();
if (pathStr.find_first_of(relativeToStr) == 0) {
contains = true;
return pathStr.substr(relativeToStr.size() + 1);
}
else {
contains = false;
return path;
}
}
// example: removeCommonPath("/home/pi/roms/nes/foo/bar.nes", "/home/pi/roms/nes/") returns "foo/bar.nes"
fs::path removeCommonPath(const fs::path& path, const fs::path& relativeTo, bool& contains)
{

View file

@ -19,6 +19,7 @@ float round(float num);
std::string getCanonicalPath(const std::string& str);
boost::filesystem::path removeCommonPathUsingStrings(const boost::filesystem::path& path, const boost::filesystem::path& relativeTo, bool& contains);
// example: removeCommonPath("/home/pi/roms/nes/foo/bar.nes", "/home/pi/roms/nes/") returns "foo/bar.nes"
boost::filesystem::path removeCommonPath(const boost::filesystem::path& path, const boost::filesystem::path& relativeTo, bool& contains);