Refactoring

This commit is contained in:
Jonas Kulla 2014-01-16 04:19:22 +01:00
parent 91efcfa06d
commit 316457b988
1 changed files with 97 additions and 79 deletions

View File

@ -500,21 +500,20 @@ static const PHYSFS_Archiver RGSS_Archiver =
struct FileSystemPrivate 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<std::string, std::string> pathCache; BoostHash<std::string, std::string> pathCache;
bool havePathCache;
std::vector<std::string> extensions[FileSystem::Undefined+1]; std::vector<std::string> 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. /* Attempt to locate an extension string in a filename.
* Either a pointer into the input string pointing at the * Either a pointer into the input string pointing at the
* extension, or null is returned */ * extension, or null is returned */
const char *findExt(const char *filename) const char *findExt(const char *filename)
{ {
int len; size_t len;
for (len = strlen(filename); len > 0; --len) for (len = strlen(filename); len > 0; --len)
{ {
@ -528,105 +527,124 @@ struct FileSystemPrivate
return 0; return 0;
} }
const char *completeFileName(const char *filename, /* Complete filename via regular physfs lookup */
bool completeFilenameReg(const char *filename,
FileSystem::FileType type, FileSystem::FileType type,
char *outBuffer,
size_t outN,
const char **foundExt) const char **foundExt)
{ {
if (!havePathCache) /* Try supplementing extensions to find an existing path */
const std::vector<std::string> &extList = extensions[type];
for (size_t i = 0; i < extList.size(); ++i)
{ {
const char *ext = extList[i].c_str();
snprintf(outBuffer, outN, "%s.%s", filename, ext);
if (PHYSFS_exists(outBuffer))
{
if (foundExt)
*foundExt = ext;
return true;
}
}
/* Doing the check without supplemented extension
* fits the usage pattern of RMXP games */
if (PHYSFS_exists(filename)) if (PHYSFS_exists(filename))
{ {
strncpy(outBuffer, filename, outN);
if (foundExt) if (foundExt)
*foundExt = findExt(filename); *foundExt = findExt(filename);
return filename; return true;
} }
return false;
}
/* 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<std::string> &extList = extensions[type]; const std::vector<std::string> &extList = extensions[type];
for (size_t i = 0; i < extList.size(); ++i) for (size_t i = 0; i < extList.size(); ++i)
{ {
const char *ext = extList[i].c_str(); const char *ext = extList[i].c_str();
snprintf(pathBuffer, sizeof(pathBuffer), "%s.%s", filename, ext); snprintf(outBuffer, outN, "%s.%s", lowCase, ext);
key = outBuffer;
if (PHYSFS_exists(pathBuffer)) if (pathCache.contains(key))
{ {
strncpy(outBuffer, pathCache[key].c_str(), outN);
if (foundExt) if (foundExt)
*foundExt = ext; *foundExt = ext;
return pathBuffer; return true;
} }
} }
// Is this even necessary? key = lowCase;
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)) if (pathCache.contains(key))
{ {
/* The extension might already be included here, strncpy(outBuffer, pathCache[key].c_str(), outN);
* so try to find it */
if (foundExt) if (foundExt)
*foundExt = findExt(filename); *foundExt = findExt(filename);
return pathCache[key].c_str(); return true;
} }
char buff2[512]; return false;
}
/* Try supplementing extensions /* Try to complete 'filename' with file extensions
* to find an existing path */ * based on 'type'. If no combination could be found,
if (type != FileSystem::Undefined) * returns false, and 'foundExt' is untouched */
bool completeFileName(const char *filename,
FileSystem::FileType type,
char *outBuffer,
size_t outN,
const char **foundExt)
{ {
std::vector<std::string> &extList = extensions[type]; if (havePathCache)
for (size_t i = 0; i < extList.size(); ++i) return completeFilenamePC(filename, type, outBuffer, outN, foundExt);
{ else
const char *ext = extList[i].c_str(); return completeFilenameReg(filename, type, outBuffer, outN, foundExt);
snprintf(buff2, sizeof(buff2), "%s.%s", buff, ext);
key = buff2;
if (pathCache.contains(key))
{
if (foundExt)
*foundExt = ext;
return pathCache[key].c_str();
}
}
} }
if (foundExt) PHYSFS_File *openReadHandle(const char *filename,
*foundExt = 0;
return 0;
}
PHYSFS_File *openReadInt(const char *filename,
FileSystem::FileType type, FileSystem::FileType type,
const char **foundExt) const char **foundExt)
{ {
const char *foundName = completeFileName(filename, type, foundExt); char found[512];
if (!foundName) if (!completeFileName(filename, type, found, sizeof(found), foundExt))
throw Exception(Exception::NoFileError, "%s", filename); throw Exception(Exception::NoFileError, "%s", filename);
PHYSFS_File *handle = PHYSFS_openRead(foundName); PHYSFS_File *handle = PHYSFS_openRead(found);
if (!handle) if (!handle)
throw Exception(Exception::PHYSFSError, "PhysFS: %s", PHYSFS_getLastError()); throw Exception(Exception::PHYSFSError, "PhysFS: %s", PHYSFS_getLastError());
@ -826,7 +844,7 @@ void FileSystem::openRead(SDL_RWops &ops,
bool freeOnClose, bool freeOnClose,
const char **foundExt) const char **foundExt)
{ {
PHYSFS_File *handle = p->openReadInt(filename, type, foundExt); PHYSFS_File *handle = p->openReadHandle(filename, type, foundExt);
ops.size = SDL_RWopsSize; ops.size = SDL_RWopsSize;
ops.seek = SDL_RWopsSeek; ops.seek = SDL_RWopsSeek;
@ -844,7 +862,7 @@ void FileSystem::openRead(SDL_RWops &ops,
bool FileSystem::exists(const char *filename, FileType type) 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);
} }