Implement case insensitive path resolution

This commit is contained in:
Jonas Kulla 2013-09-30 21:19:43 +02:00
parent f49b03ba23
commit 408864339f
3 changed files with 104 additions and 53 deletions

View File

@ -525,32 +525,6 @@ void FileStream::close()
} }
} }
static void enumCB(void *, const char *origdir,
const char *fname)
{
qDebug() << origdir << fname;
char buf[128];
sprintf(buf, "%s/%s", origdir, fname);
PHYSFS_enumerateFilesCallback(buf, enumCB, 0);
}
FileSystem::FileSystem(const char *argv0)
{
PHYSFS_init(argv0);
PHYSFS_registerArchiver(&RGSS_Archiver);
}
FileSystem::~FileSystem()
{
if (PHYSFS_deinit() == 0)
qDebug() << "PhyFS failed to deinit.";
}
void FileSystem::addPath(const char *path)
{
PHYSFS_mount(path, 0, 1);
}
static const char *imgExt[] = static const char *imgExt[] =
{ {
"jpg", "jpg",
@ -583,50 +557,117 @@ struct FileExtensions
{ fonExt, ARRAY_SIZE(fonExt) } { fonExt, ARRAY_SIZE(fonExt) }
}; };
static const char *completeFileName(const char *filename, struct FileSystemPrivate
FileSystem::FileType type)
{ {
static char buff[1024]; /* All keys are lower case */
QHash<QByteArray, QByteArray> pathCache;
if (PHYSFS_exists(filename)) const char *completeFileName(const char *filename,
return filename; FileSystem::FileType type)
if (type != FileSystem::Undefined)
{ {
FileExtensions *extTest = &fileExtensions[type]; char buff[512];
for (int i = 0; i < extTest->count; ++i) size_t i;
for (i = 0; i < sizeof(buff) && filename[i]; ++i)
buff[i] = tolower(filename[i]);
buff[i] = '\0';
QByteArray key(buff);
if (pathCache.contains(key))
return pathCache[key].constData();
char buff2[512];
if (type != FileSystem::Undefined)
{ {
snprintf(buff, sizeof(buff), "%s.%s", filename, extTest->ext[i]); FileExtensions *extTest = &fileExtensions[type];
if (PHYSFS_exists(buff)) for (int i = 0; i < extTest->count; ++i)
return buff; {
snprintf(buff2, sizeof(buff2), "%s.%s", buff, extTest->ext[i]);
key = buff2;
if (pathCache.contains(key))
return pathCache[key].constData();
}
} }
return 0;
} }
return 0; PHYSFS_File *openReadInt(const char *filename,
FileSystem::FileType type)
{
const char *foundName = completeFileName(filename, type);
if (!foundName)
throw Exception(Exception::NoFileError,
"No such file or directory - %s", filename);
PHYSFS_File *handle = PHYSFS_openRead(foundName);
if (!handle)
throw Exception(Exception::PHYSFSError, "PhysFS: %s", PHYSFS_getLastError());
PHYSFS_fileLength(handle);
return handle;
}
};
FileSystem::FileSystem(const char *argv0)
{
p = new FileSystemPrivate;
PHYSFS_init(argv0);
PHYSFS_registerArchiver(&RGSS_Archiver);
} }
static PHYSFS_File *openReadInt(const char *filename, FileSystem::~FileSystem()
FileSystem::FileType type)
{ {
const char *foundName = completeFileName(filename, type); delete p;
if (!foundName) if (PHYSFS_deinit() == 0)
throw Exception(Exception::NoFileError, qDebug() << "PhyFS failed to deinit.";
"No such file or directory - %s", filename); }
PHYSFS_File *handle = PHYSFS_openRead(foundName); void FileSystem::addPath(const char *path)
if (!handle) {
throw Exception(Exception::PHYSFSError, "PhysFS: %s", PHYSFS_getLastError()); PHYSFS_mount(path, 0, 1);
}
PHYSFS_fileLength(handle); static void cacheEnumCB(void *d, const char *origdir,
const char *fname)
{
FileSystemPrivate *p = static_cast<FileSystemPrivate*>(d);
return handle; char buf[512];
if (*origdir != '.')
snprintf(buf, sizeof(buf), "%s/%s", origdir, fname);
else
strncpy(buf, fname, sizeof(buf));
QByteArray mixedCase = buf;
QByteArray lowerCase = mixedCase;
for (char *p = lowerCase.data(); *p; ++p)
*p = tolower(*p);
p->pathCache.insert(lowerCase, mixedCase);
PHYSFS_enumerateFilesCallback(mixedCase.constData(), cacheEnumCB, p);
}
void FileSystem::createPathCache()
{
PHYSFS_enumerateFilesCallback(".", cacheEnumCB, p);
} }
FileStream FileSystem::openRead(const char *filename, FileStream FileSystem::openRead(const char *filename,
FileType type) FileType type)
{ {
PHYSFS_File *handle = openReadInt(filename, type); PHYSFS_File *handle = p->openReadInt(filename, type);
return FileStream(handle); return FileStream(handle);
} }
@ -727,7 +768,7 @@ void FileSystem::openRead(SDL_RWops &ops,
FileType type, FileType type,
bool freeOnClose) bool freeOnClose)
{ {
PHYSFS_File *handle = openReadInt(filename, type); PHYSFS_File *handle = p->openReadInt(filename, type);
ops.size = SDL_RWopsSize; ops.size = SDL_RWopsSize;
ops.seek = SDL_RWopsSeek; ops.seek = SDL_RWopsSeek;
@ -745,7 +786,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 = completeFileName(filename, type); const char *foundName = p->completeFileName(filename, type);
return (foundName != 0); return (foundName != 0);
} }

View File

@ -49,6 +49,8 @@ private:
PHYSFS_File *p; /* NULL denotes invalid stream */ PHYSFS_File *p; /* NULL denotes invalid stream */
}; };
struct FileSystemPrivate;
class FileSystem class FileSystem
{ {
public: public:
@ -57,6 +59,9 @@ public:
void addPath(const char *path); void addPath(const char *path);
/* Call this after the last 'addPath()' */
void createPathCache();
/* For extension supplementing */ /* For extension supplementing */
enum FileType enum FileType
{ {
@ -76,6 +81,9 @@ public:
bool exists(const char *filename, bool exists(const char *filename,
FileType type = Undefined); FileType type = Undefined);
private:
FileSystemPrivate *p;
}; };
extern const Uint32 SDL_RWOPS_PHYSFS; extern const Uint32 SDL_RWOPS_PHYSFS;

View File

@ -117,6 +117,8 @@ struct GlobalStatePrivate
for (int i = 0; i < config.rtps.count(); ++i) for (int i = 0; i < config.rtps.count(); ++i)
fileSystem.addPath(config.rtps[i].constData()); fileSystem.addPath(config.rtps[i].constData());
fileSystem.createPathCache();
globalTexW = 128; globalTexW = 128;
globalTexH = 64; globalTexH = 64;