diff --git a/rwengine/src/engine/GameData.cpp b/rwengine/src/engine/GameData.cpp index 3cd34bb2..48c1e121 100644 --- a/rwengine/src/engine/GameData.cpp +++ b/rwengine/src/engine/GameData.cpp @@ -14,65 +14,13 @@ #include #include #include +#include #include #include #include #include -#ifndef RW_WINDOWS -#include -#else -#include -#endif -#include - -/** - * 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 std::string fixPath(std::string path) { for( size_t t = 0; t < path.size(); ++t) { @@ -84,7 +32,6 @@ std::string fixPath(std::string path) { return path; } - GameData::GameData(Logger* log, WorkContext* work, const std::string& path) : datpath(path), logger(log), workContext(work), engine(nullptr) { diff --git a/rwlib/source/platform/FileIndex.cpp b/rwlib/source/platform/FileIndex.cpp index de2c52d0..e8e6401f 100644 --- a/rwlib/source/platform/FileIndex.cpp +++ b/rwlib/source/platform/FileIndex.cpp @@ -6,6 +6,43 @@ 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) { for(const auto& entry : recursive_directory_iterator(root)) { diff --git a/rwlib/source/platform/FileIndex.hpp b/rwlib/source/platform/FileIndex.hpp index 11f332e1..2d9e6b0f 100644 --- a/rwlib/source/platform/FileIndex.hpp +++ b/rwlib/source/platform/FileIndex.hpp @@ -4,6 +4,8 @@ #include #include +std::string findPathRealCase(const std::string& base_src, const std::string& path_src); + class FileIndex { public: