NFD filename translation on OS X

This commit is contained in:
Mathew 2014-08-19 10:57:03 -04:00
parent 7452331e04
commit f89216368d
1 changed files with 57 additions and 3 deletions

View File

@ -37,6 +37,10 @@
#include <algorithm> #include <algorithm>
#include <vector> #include <vector>
#ifdef __APPLE__
#include <iconv.h>
#endif
static inline PHYSFS_File *sdlPHYS(SDL_RWops *ops) static inline PHYSFS_File *sdlPHYS(SDL_RWops *ops)
{ {
return static_cast<PHYSFS_File*>(ops->hidden.unknown.data1); return static_cast<PHYSFS_File*>(ops->hidden.unknown.data1);
@ -364,10 +368,48 @@ void FileSystem::addPath(const char *path)
PHYSFS_mount(path, 0, 1); PHYSFS_mount(path, 0, 1);
} }
#ifdef __APPLE__
struct CacheEnumCBData
{
FileSystemPrivate *p;
iconv_t nfd2nfc;
CacheEnumCBData(FileSystemPrivate *fsp)
{
p = fsp;
nfd2nfc = iconv_open("utf-8", "utf-8-mac");
}
~CacheEnumCBData()
{
iconv_close(nfd2nfc);
}
void nfcFromNfd(char *dst, const char *src, size_t dstSize)
{
size_t srcSize = strlen(src);
/* Reserve room for null terminator */
--dstSize;
/* iconv takes a char** instead of a const char**, even though
* the string data isn't written to. */
iconv(nfd2nfc,
const_cast<char**>(&src), &srcSize,
&dst, &dstSize);
/* Null-terminate */
*dst = 0;
}
};
#endif
static void cacheEnumCB(void *d, const char *origdir, static void cacheEnumCB(void *d, const char *origdir,
const char *fname) const char *fname)
{ {
#ifdef __APPLE__
CacheEnumCBData *data = static_cast<CacheEnumCBData*>(d);
FileSystemPrivate *p = data->p;
#else
FileSystemPrivate *p = static_cast<FileSystemPrivate*>(d); FileSystemPrivate *p = static_cast<FileSystemPrivate*>(d);
#endif
char buf[512]; char buf[512];
@ -376,7 +418,14 @@ static void cacheEnumCB(void *d, const char *origdir,
else else
snprintf(buf, sizeof(buf), "%s/%s", origdir, fname); snprintf(buf, sizeof(buf), "%s/%s", origdir, fname);
char *ptr = buf; #ifdef __APPLE__
char bufNfc[sizeof(buf)];
data->nfcFromNfd(bufNfc, buf, sizeof(bufNfc));
#else
char *const bufNfc = buf;
#endif
char *ptr = bufNfc;
/* Trim leading slash */ /* Trim leading slash */
if (*ptr == '/') if (*ptr == '/')
@ -384,19 +433,24 @@ static void cacheEnumCB(void *d, const char *origdir,
std::string mixedCase(ptr); std::string mixedCase(ptr);
for (char *p = buf; *p; ++p) for (char *p = bufNfc; *p; ++p)
*p = tolower(*p); *p = tolower(*p);
std::string lowerCase(ptr); std::string lowerCase(ptr);
p->pathCache.insert(lowerCase, mixedCase); p->pathCache.insert(lowerCase, mixedCase);
PHYSFS_enumerateFilesCallback(mixedCase.c_str(), cacheEnumCB, p); PHYSFS_enumerateFilesCallback(mixedCase.c_str(), cacheEnumCB, d);
} }
void FileSystem::createPathCache() void FileSystem::createPathCache()
{ {
#ifdef __APPLE__
CacheEnumCBData data(p);
PHYSFS_enumerateFilesCallback("", cacheEnumCB, &data);
#else
PHYSFS_enumerateFilesCallback("", cacheEnumCB, p); PHYSFS_enumerateFilesCallback("", cacheEnumCB, p);
#endif
p->havePathCache = true; p->havePathCache = true;
} }