Merge pull request #2633 from rmccampbell/unicode_fix

Unicode fix
pull/2626/head^2
Kim Kulling 2019-09-06 11:28:57 +02:00 committed by GitHub
commit 1a8375f925
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 60 additions and 101 deletions

View File

@ -61,83 +61,66 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
using namespace Assimp; using namespace Assimp;
// maximum path length #ifdef _WIN32
// XXX http://insanecoding.blogspot.com/2007/11/pathmax-simply-isnt.html static std::wstring Utf8ToWide(const char* in)
#ifdef PATH_MAX {
# define PATHLIMIT PATH_MAX int size = MultiByteToWideChar(CP_UTF8, 0, in, -1, nullptr, 0);
#else // size includes terminating null; std::wstring adds null automatically
# define PATHLIMIT 4096 std::wstring out(static_cast<size_t>(size) - 1, L'\0');
MultiByteToWideChar(CP_UTF8, 0, in, -1, &out[0], size);
return out;
}
static std::string WideToUtf8(const wchar_t* in)
{
int size = WideCharToMultiByte(CP_UTF8, 0, in, -1, nullptr, 0, nullptr, nullptr);
// size includes terminating null; std::string adds null automatically
std::string out(static_cast<size_t>(size) - 1, '\0');
WideCharToMultiByte(CP_UTF8, 0, in, -1, &out[0], size, nullptr, nullptr);
return out;
}
#endif #endif
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Tests for the existence of a file at the given path. // Tests for the existence of a file at the given path.
bool DefaultIOSystem::Exists( const char* pFile) const bool DefaultIOSystem::Exists(const char* pFile) const
{ {
#ifdef _WIN32 #ifdef _WIN32
wchar_t fileName16[PATHLIMIT]; struct __stat64 filestat;
if (_wstat64(Utf8ToWide(pFile).c_str(), &filestat) != 0) {
#ifndef WindowsStore return false;
bool isUnicode = IsTextUnicode(pFile, static_cast<int>(strlen(pFile)), NULL) != 0;
if (isUnicode) {
MultiByteToWideChar(CP_UTF8, MB_PRECOMPOSED, pFile, -1, fileName16, PATHLIMIT);
struct __stat64 filestat;
if (0 != _wstat64(fileName16, &filestat)) {
return false;
}
} else {
#endif
FILE* file = ::fopen(pFile, "rb");
if (!file)
return false;
::fclose(file);
#ifndef WindowsStore
} }
#endif
#else #else
FILE* file = ::fopen( pFile, "rb"); FILE* file = ::fopen(pFile, "rb");
if( !file) if (!file)
return false; return false;
::fclose( file); ::fclose(file);
#endif #endif
return true; return true;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Open a new file with a given path. // Open a new file with a given path.
IOStream* DefaultIOSystem::Open( const char* strFile, const char* strMode) IOStream* DefaultIOSystem::Open(const char* strFile, const char* strMode)
{ {
ai_assert(NULL != strFile); ai_assert(strFile != nullptr);
ai_assert(NULL != strMode); ai_assert(strMode != nullptr);
FILE* file; FILE* file;
#ifdef _WIN32 #ifdef _WIN32
wchar_t fileName16[PATHLIMIT]; file = ::_wfopen(Utf8ToWide(strFile).c_str(), Utf8ToWide(strMode).c_str());
#ifndef WindowsStore
bool isUnicode = IsTextUnicode(strFile, static_cast<int>(strlen(strFile)), NULL) != 0;
if (isUnicode) {
MultiByteToWideChar(CP_UTF8, MB_PRECOMPOSED, strFile, -1, fileName16, PATHLIMIT);
std::string mode8(strMode);
file = ::_wfopen(fileName16, std::wstring(mode8.begin(), mode8.end()).c_str());
} else {
#endif
file = ::fopen(strFile, strMode);
#ifndef WindowsStore
}
#endif
#else #else
file = ::fopen(strFile, strMode); file = ::fopen(strFile, strMode);
#endif #endif
if (nullptr == file) if (!file)
return nullptr; return nullptr;
return new DefaultIOStream(file, (std::string) strFile); return new DefaultIOStream(file, strFile);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Closes the given file and releases all resources associated with it. // Closes the given file and releases all resources associated with it.
void DefaultIOSystem::Close( IOStream* pFile) void DefaultIOSystem::Close(IOStream* pFile)
{ {
delete pFile; delete pFile;
} }
@ -155,78 +138,56 @@ char DefaultIOSystem::getOsSeparator() const
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// IOSystem default implementation (ComparePaths isn't a pure virtual function) // IOSystem default implementation (ComparePaths isn't a pure virtual function)
bool IOSystem::ComparePaths (const char* one, const char* second) const bool IOSystem::ComparePaths(const char* one, const char* second) const
{ {
return !ASSIMP_stricmp(one,second); return !ASSIMP_stricmp(one, second);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Convert a relative path into an absolute path // Convert a relative path into an absolute path
inline static void MakeAbsolutePath (const char* in, char* _out) inline static std::string MakeAbsolutePath(const char* in)
{ {
ai_assert(in && _out); ai_assert(in);
#if defined( _MSC_VER ) || defined( __MINGW32__ ) std::string out;
#ifndef WindowsStore #ifdef _WIN32
bool isUnicode = IsTextUnicode(in, static_cast<int>(strlen(in)), NULL) != 0; wchar_t* ret = ::_wfullpath(nullptr, Utf8ToWide(in).c_str(), 0);
if (isUnicode) { if (ret) {
wchar_t out16[PATHLIMIT]; out = WideToUtf8(ret);
wchar_t in16[PATHLIMIT]; free(ret);
MultiByteToWideChar(CP_UTF8, MB_PRECOMPOSED, in, -1, out16, PATHLIMIT); }
wchar_t* ret = ::_wfullpath(out16, in16, PATHLIMIT); #else
if (ret) { char* ret = realpath(in, nullptr);
WideCharToMultiByte(CP_UTF8, MB_PRECOMPOSED, out16, -1, _out, PATHLIMIT, nullptr, nullptr); if (ret) {
} out = ret;
if (!ret) { free(ret);
// preserve the input path, maybe someone else is able to fix
// the path before it is accessed (e.g. our file system filter)
ASSIMP_LOG_WARN_F("Invalid path: ", std::string(in));
strcpy(_out, in);
}
} else {
#endif
char* ret = :: _fullpath(_out, in, PATHLIMIT);
if (!ret) {
// preserve the input path, maybe someone else is able to fix
// the path before it is accessed (e.g. our file system filter)
ASSIMP_LOG_WARN_F("Invalid path: ", std::string(in));
strcpy(_out, in);
}
#ifndef WindowsStore
} }
#endif #endif
#else if (!ret) {
// use realpath
char* ret = realpath(in, _out);
if(!ret) {
// preserve the input path, maybe someone else is able to fix // preserve the input path, maybe someone else is able to fix
// the path before it is accessed (e.g. our file system filter) // the path before it is accessed (e.g. our file system filter)
ASSIMP_LOG_WARN_F("Invalid path: ", std::string(in)); ASSIMP_LOG_WARN_F("Invalid path: ", std::string(in));
strcpy(_out,in); out = in;
} }
#endif return out;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// DefaultIOSystem's more specialized implementation // DefaultIOSystem's more specialized implementation
bool DefaultIOSystem::ComparePaths (const char* one, const char* second) const bool DefaultIOSystem::ComparePaths(const char* one, const char* second) const
{ {
// chances are quite good both paths are formatted identically, // chances are quite good both paths are formatted identically,
// so we can hopefully return here already // so we can hopefully return here already
if( !ASSIMP_stricmp(one,second) ) if (!ASSIMP_stricmp(one, second))
return true; return true;
char temp1[PATHLIMIT]; std::string temp1 = MakeAbsolutePath(one);
char temp2[PATHLIMIT]; std::string temp2 = MakeAbsolutePath(second);
MakeAbsolutePath (one, temp1); return !ASSIMP_stricmp(temp1, temp2);
MakeAbsolutePath (second, temp2);
return !ASSIMP_stricmp(temp1,temp2);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
std::string DefaultIOSystem::fileName( const std::string &path ) std::string DefaultIOSystem::fileName(const std::string& path)
{ {
std::string ret = path; std::string ret = path;
std::size_t last = ret.find_last_of("\\/"); std::size_t last = ret.find_last_of("\\/");
@ -235,16 +196,16 @@ std::string DefaultIOSystem::fileName( const std::string &path )
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
std::string DefaultIOSystem::completeBaseName( const std::string &path ) std::string DefaultIOSystem::completeBaseName(const std::string& path)
{ {
std::string ret = fileName(path); std::string ret = fileName(path);
std::size_t pos = ret.find_last_of('.'); std::size_t pos = ret.find_last_of('.');
if(pos != ret.npos) ret = ret.substr(0, pos); if (pos != std::string::npos) ret = ret.substr(0, pos);
return ret; return ret;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
std::string DefaultIOSystem::absolutePath( const std::string &path ) std::string DefaultIOSystem::absolutePath(const std::string& path)
{ {
std::string ret = path; std::string ret = path;
std::size_t last = ret.find_last_of("\\/"); std::size_t last = ret.find_last_of("\\/");
@ -253,5 +214,3 @@ std::string DefaultIOSystem::absolutePath( const std::string &path )
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
#undef PATHLIMIT