From 316457b9884ad4fd87e1c89af953d2d7ef177166 Mon Sep 17 00:00:00 2001 From: Jonas Kulla Date: Thu, 16 Jan 2014 04:19:22 +0100 Subject: [PATCH] Refactoring --- src/filesystem.cpp | 176 +++++++++++++++++++++++++-------------------- 1 file changed, 97 insertions(+), 79 deletions(-) diff --git a/src/filesystem.cpp b/src/filesystem.cpp index 3072ca3..b66a8b3 100644 --- a/src/filesystem.cpp +++ b/src/filesystem.cpp @@ -500,21 +500,20 @@ static const PHYSFS_Archiver RGSS_Archiver = struct FileSystemPrivate { - /* All keys are lower case */ + /* Maps: lower case filename, To: actual (mixed case) filename. + * This is for compatibility with games that take Windows' + * case insensitivity for granted */ BoostHash pathCache; + bool havePathCache; std::vector extensions[FileSystem::Undefined+1]; - // FIXME Need to find a better way to do this.. - char pathBuffer[512]; - bool havePathCache; - /* Attempt to locate an extension string in a filename. * Either a pointer into the input string pointing at the * extension, or null is returned */ const char *findExt(const char *filename) { - int len; + size_t len; for (len = strlen(filename); len > 0; --len) { @@ -528,105 +527,124 @@ struct FileSystemPrivate return 0; } - const char *completeFileName(const char *filename, - FileSystem::FileType type, - const char **foundExt) + /* Complete filename via regular physfs lookup */ + bool completeFilenameReg(const char *filename, + FileSystem::FileType type, + char *outBuffer, + size_t outN, + const char **foundExt) { - if (!havePathCache) + /* Try supplementing extensions to find an existing path */ + const std::vector &extList = extensions[type]; + + for (size_t i = 0; i < extList.size(); ++i) { - if (PHYSFS_exists(filename)) + const char *ext = extList[i].c_str(); + + snprintf(outBuffer, outN, "%s.%s", filename, ext); + + if (PHYSFS_exists(outBuffer)) { if (foundExt) - *foundExt = findExt(filename); + *foundExt = ext; - return filename; + return true; } - - const std::vector &extList = extensions[type]; - for (size_t i = 0; i < extList.size(); ++i) - { - const char *ext = extList[i].c_str(); - - snprintf(pathBuffer, sizeof(pathBuffer), "%s.%s", filename, ext); - - if (PHYSFS_exists(pathBuffer)) - { - if (foundExt) - *foundExt = ext; - - return pathBuffer; - } - } - - // Is this even necessary? - if (foundExt) - *foundExt = 0; - - return 0; } - char buff[512]; - size_t i; - - for (i = 0; i < sizeof(buff) && filename[i]; ++i) - buff[i] = tolower(filename[i]); - - buff[i] = '\0'; - - std::string key(buff); - - /* If the path was already complete, - * we are done at this point */ - if (pathCache.contains(key)) + /* Doing the check without supplemented extension + * fits the usage pattern of RMXP games */ + if (PHYSFS_exists(filename)) { - /* The extension might already be included here, - * so try to find it */ + strncpy(outBuffer, filename, outN); + if (foundExt) *foundExt = findExt(filename); - return pathCache[key].c_str(); + return true; } - char buff2[512]; + return false; + } - /* Try supplementing extensions - * to find an existing path */ - if (type != FileSystem::Undefined) + /* Complete filename via path cache */ + bool completeFilenamePC(const char *filename, + FileSystem::FileType type, + char *outBuffer, + size_t outN, + const char **foundExt) + { + size_t i; + char lowCase[512]; + + for (i = 0; i < sizeof(lowCase)-1 && filename[i]; ++i) + lowCase[i] = tolower(filename[i]); + + lowCase[i] = '\0'; + + std::string key; + + const std::vector &extList = extensions[type]; + + for (size_t i = 0; i < extList.size(); ++i) { - std::vector &extList = extensions[type]; - for (size_t i = 0; i < extList.size(); ++i) + const char *ext = extList[i].c_str(); + + snprintf(outBuffer, outN, "%s.%s", lowCase, ext); + key = outBuffer; + + if (pathCache.contains(key)) { - const char *ext = extList[i].c_str(); + strncpy(outBuffer, pathCache[key].c_str(), outN); - snprintf(buff2, sizeof(buff2), "%s.%s", buff, ext); - key = buff2; + if (foundExt) + *foundExt = ext; - if (pathCache.contains(key)) - { - if (foundExt) - *foundExt = ext; - - return pathCache[key].c_str(); - } + return true; } } - if (foundExt) - *foundExt = 0; + key = lowCase; - return 0; + if (pathCache.contains(key)) + { + strncpy(outBuffer, pathCache[key].c_str(), outN); + + if (foundExt) + *foundExt = findExt(filename); + + return true; + } + + return false; } - PHYSFS_File *openReadInt(const char *filename, - FileSystem::FileType type, - const char **foundExt) + /* Try to complete 'filename' with file extensions + * based on 'type'. If no combination could be found, + * returns false, and 'foundExt' is untouched */ + bool completeFileName(const char *filename, + FileSystem::FileType type, + char *outBuffer, + size_t outN, + const char **foundExt) { - const char *foundName = completeFileName(filename, type, foundExt); + if (havePathCache) + return completeFilenamePC(filename, type, outBuffer, outN, foundExt); + else + return completeFilenameReg(filename, type, outBuffer, outN, foundExt); + } - if (!foundName) + PHYSFS_File *openReadHandle(const char *filename, + FileSystem::FileType type, + const char **foundExt) + { + char found[512]; + + if (!completeFileName(filename, type, found, sizeof(found), foundExt)) throw Exception(Exception::NoFileError, "%s", filename); - PHYSFS_File *handle = PHYSFS_openRead(foundName); + PHYSFS_File *handle = PHYSFS_openRead(found); + if (!handle) throw Exception(Exception::PHYSFSError, "PhysFS: %s", PHYSFS_getLastError()); @@ -826,7 +844,7 @@ void FileSystem::openRead(SDL_RWops &ops, bool freeOnClose, const char **foundExt) { - PHYSFS_File *handle = p->openReadInt(filename, type, foundExt); + PHYSFS_File *handle = p->openReadHandle(filename, type, foundExt); ops.size = SDL_RWopsSize; ops.seek = SDL_RWopsSeek; @@ -844,7 +862,7 @@ void FileSystem::openRead(SDL_RWops &ops, bool FileSystem::exists(const char *filename, FileType type) { - const char *foundName = p->completeFileName(filename, type, 0); + char found[512]; - return (foundName != 0); + return p->completeFileName(filename, type, found, sizeof(found), 0); }