1
0
mirror of https://github.com/rwengine/openrw.git synced 2024-11-07 03:12:36 +01:00

Rewrite findPathRealCase to use boost::filesystem, move it to FileIndex

This commit is contained in:
darkf 2016-08-03 17:50:41 -07:00
parent 196f9f6d25
commit 40705a6666
3 changed files with 40 additions and 54 deletions

View File

@ -14,65 +14,13 @@
#include <loaders/LoaderGXT.hpp> #include <loaders/LoaderGXT.hpp>
#include <loaders/BackgroundLoader.hpp> #include <loaders/BackgroundLoader.hpp>
#include <core/Logger.hpp> #include <core/Logger.hpp>
#include <platform/FileIndex.hpp>
#include <iostream> #include <iostream>
#include <fstream> #include <fstream>
#include <sstream> #include <sstream>
#include <algorithm> #include <algorithm>
#ifndef RW_WINDOWS
#include <dirent.h>
#else
#include <platform/msdirent.h>
#endif
#include <sys/types.h>
/**
* Finds the 'real' case for a path, to get around the fact that Rockstar's data is usually the wrong case.
* @param base The base of the path to start looking from.
* @param path the lowercase path.
*/
std::string findPathRealCase(const std::string& base, const std::string& path)
{
#ifndef RW_WINDOWS
size_t endslash = path.find("/");
bool isDirectory = true;
if(endslash == path.npos) {
isDirectory = false;
}
std::string orgFileName = isDirectory ? path.substr(0, endslash) : path;
std::transform(orgFileName.begin(), orgFileName.end(), orgFileName.begin(), ::tolower);
std::string realName;
// Open the current "base" path (i.e. the real path)
DIR* dp = opendir(base.c_str());
dirent* ep;
if( dp != NULL) {
while( (ep = readdir(dp)) ) {
realName = ep->d_name;
std::string lowerRealName = realName;
std::transform(lowerRealName.begin(), lowerRealName.end(), lowerRealName.begin(), ::tolower);
if( lowerRealName == orgFileName) {
closedir(dp);
if( isDirectory) {
return findPathRealCase(base + "/" + realName, path.substr(endslash+1));
}
else {
return base + "/" + realName;
}
}
}
closedir(dp);
}
return "";
#else
// Is anything other than Windows likely to fall here?
return base + "/" + path;
#endif
}
// Yet another hack function to fix these paths // Yet another hack function to fix these paths
std::string fixPath(std::string path) { std::string fixPath(std::string path) {
for( size_t t = 0; t < path.size(); ++t) { for( size_t t = 0; t < path.size(); ++t) {
@ -84,7 +32,6 @@ std::string fixPath(std::string path) {
return path; return path;
} }
GameData::GameData(Logger* log, WorkContext* work, const std::string& path) GameData::GameData(Logger* log, WorkContext* work, const std::string& path)
: datpath(path), logger(log), workContext(work), engine(nullptr) : datpath(path), logger(log), workContext(work), engine(nullptr)
{ {

View File

@ -6,6 +6,43 @@
using namespace boost::filesystem; using namespace boost::filesystem;
/**
* Finds the 'real' case for a path, to get around the fact that Rockstar's data is usually the wrong case.
* @param base The base of the path to start looking from.
* @param path the lowercase path.
*/
std::string findPathRealCase(const std::string& base_src, const std::string& path_src)
{
path base(base_src);
path searchpath(path_src);
// Iterate over each component of the path
for(const path& path_component : searchpath) {
std::string cmp_lower = path_component.string();
std::transform(cmp_lower.begin(), cmp_lower.end(), cmp_lower.begin(), ::tolower);
// Search the current base path for a filename matching the component we're searching for
bool found = false;
for(const directory_entry& entry : directory_iterator(base)) {
std::string lowerName = entry.path().filename().string();
std::transform(lowerName.begin(), lowerName.end(), lowerName.begin(), ::tolower);
if(lowerName == cmp_lower) {
// We got a match, so add it to base and continue
base /= lowerName;
found = true;
break;
}
}
if(!found) {
throw std::runtime_error("Can't find real path case of " + path_src);
}
}
return base.string();
}
void FileIndex::indexTree(const std::string& root) void FileIndex::indexTree(const std::string& root)
{ {
for(const auto& entry : recursive_directory_iterator(root)) { for(const auto& entry : recursive_directory_iterator(root)) {

View File

@ -4,6 +4,8 @@
#include <string> #include <string>
#include <map> #include <map>
std::string findPathRealCase(const std::string& base_src, const std::string& path_src);
class FileIndex class FileIndex
{ {
public: public: