From 15d84825d9bfeb9c8a8bac3c638c8a1ffbd77f60 Mon Sep 17 00:00:00 2001 From: Stepan Hrbek Date: Thu, 31 Dec 2015 03:18:11 +0100 Subject: [PATCH 1/3] Collada exporter: Fix isalnum(negative number) assert. isalnum(negative number) asserts in MSVC. It was first visible problem when exporting unicode filenames. --- code/ColladaExporter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/ColladaExporter.cpp b/code/ColladaExporter.cpp index 6bd87e8f0..c0279e4c1 100644 --- a/code/ColladaExporter.cpp +++ b/code/ColladaExporter.cpp @@ -540,7 +540,7 @@ void ColladaExporter::WriteImageEntry( const Surface& pSurface, const std::strin std::stringstream imageUrlEncoded; for( std::string::const_iterator it = pSurface.texture.begin(); it != pSurface.texture.end(); ++it ) { - if( isalnum( *it) || *it == '_' || *it == '.' || *it == '/' || *it == '\\' ) + if( isalnum( (unsigned char) *it) || *it == '_' || *it == '.' || *it == '/' || *it == '\\' ) imageUrlEncoded << *it; else imageUrlEncoded << '%' << std::hex << size_t( (unsigned char) *it) << std::dec; From 39ab716e1190294fcfd451c98673f03e8041af68 Mon Sep 17 00:00:00 2001 From: Stepan Hrbek Date: Thu, 31 Dec 2015 03:22:25 +0100 Subject: [PATCH 2/3] Collada exporter: Fix unicode filenames. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Although existing code uses "C" locale partially, both calls to isalnum() clearly did not use it. So for example character "รค" was written to .dae as is, rather than converted to %e4, generated .dae was unreadable to many parsers. --- code/ColladaExporter.cpp | 7 ++++--- code/ColladaExporter.h | 3 +++ 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/code/ColladaExporter.cpp b/code/ColladaExporter.cpp index c0279e4c1..2f1236aab 100644 --- a/code/ColladaExporter.cpp +++ b/code/ColladaExporter.cpp @@ -93,7 +93,8 @@ void ExportSceneCollada(const char* pFile, IOSystem* pIOSystem, const aiScene* p ColladaExporter::ColladaExporter( const aiScene* pScene, IOSystem* pIOSystem, const std::string& path, const std::string& file) : mIOSystem(pIOSystem), mPath(path), mFile(file) { // make sure that all formatting happens using the standard, C locale and not the user's current locale - mOutput.imbue( std::locale("C") ); + clocale = std::locale("C"); + mOutput.imbue( clocale ); mScene = pScene; mSceneOwned = false; @@ -540,7 +541,7 @@ void ColladaExporter::WriteImageEntry( const Surface& pSurface, const std::strin std::stringstream imageUrlEncoded; for( std::string::const_iterator it = pSurface.texture.begin(); it != pSurface.texture.end(); ++it ) { - if( isalnum( (unsigned char) *it) || *it == '_' || *it == '.' || *it == '/' || *it == '\\' ) + if( isalnum( (unsigned char) *it, clocale) || *it == '_' || *it == '.' || *it == '/' || *it == '\\' ) imageUrlEncoded << *it; else imageUrlEncoded << '%' << std::hex << size_t( (unsigned char) *it) << std::dec; @@ -633,7 +634,7 @@ void ColladaExporter::WriteMaterials() for( std::string::iterator it = materials[a].name.begin(); it != materials[a].name.end(); ++it ) { // isalnum on MSVC asserts for code points outside [0,255]. Thus prevent unwanted promotion // of char to signed int and take the unsigned char value. - if( !isalnum( static_cast(*it) ) ) { + if( !isalnum( static_cast(*it), clocale ) ) { *it = '_'; } } diff --git a/code/ColladaExporter.h b/code/ColladaExporter.h index 858cef2b6..f8bdbe7fc 100644 --- a/code/ColladaExporter.h +++ b/code/ColladaExporter.h @@ -130,6 +130,9 @@ public: std::stringstream mOutput; protected: + /// C locale + std::locale clocale; + /// The IOSystem for output IOSystem* mIOSystem; From 24f03141d655be7b095d6e292c544201c8ab2fec Mon Sep 17 00:00:00 2001 From: Stepan Hrbek Date: Thu, 31 Dec 2015 14:41:53 +0100 Subject: [PATCH 3/3] Reimplement isalnum(c,C locale) because I can't make AppVeyor see satndard version. --- code/ColladaExporter.cpp | 16 ++++++++++------ code/ColladaExporter.h | 3 --- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/code/ColladaExporter.cpp b/code/ColladaExporter.cpp index 2f1236aab..73caea5c6 100644 --- a/code/ColladaExporter.cpp +++ b/code/ColladaExporter.cpp @@ -93,8 +93,7 @@ void ExportSceneCollada(const char* pFile, IOSystem* pIOSystem, const aiScene* p ColladaExporter::ColladaExporter( const aiScene* pScene, IOSystem* pIOSystem, const std::string& path, const std::string& file) : mIOSystem(pIOSystem), mPath(path), mFile(file) { // make sure that all formatting happens using the standard, C locale and not the user's current locale - clocale = std::locale("C"); - mOutput.imbue( clocale ); + mOutput.imbue( std::locale("C") ); mScene = pScene; mSceneOwned = false; @@ -527,6 +526,13 @@ void ColladaExporter::ReadMaterialSurface( Surface& poSurface, const aiMaterial* } } +// ------------------------------------------------------------------------------------------------ +// Reimplementation of isalnum(,C locale), because AppVeyor does not see standard version. +static bool isalnum_C(char c) +{ + return strchr("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",c); +} + // ------------------------------------------------------------------------------------------------ // Writes an image entry for the given surface void ColladaExporter::WriteImageEntry( const Surface& pSurface, const std::string& pNameAdd) @@ -541,7 +547,7 @@ void ColladaExporter::WriteImageEntry( const Surface& pSurface, const std::strin std::stringstream imageUrlEncoded; for( std::string::const_iterator it = pSurface.texture.begin(); it != pSurface.texture.end(); ++it ) { - if( isalnum( (unsigned char) *it, clocale) || *it == '_' || *it == '.' || *it == '/' || *it == '\\' ) + if( isalnum_C( (unsigned char) *it) || *it == '_' || *it == '.' || *it == '/' || *it == '\\' ) imageUrlEncoded << *it; else imageUrlEncoded << '%' << std::hex << size_t( (unsigned char) *it) << std::dec; @@ -632,9 +638,7 @@ void ColladaExporter::WriteMaterials() name = "mat"; materials[a].name = std::string( "m") + boost::lexical_cast (a) + name.C_Str(); for( std::string::iterator it = materials[a].name.begin(); it != materials[a].name.end(); ++it ) { - // isalnum on MSVC asserts for code points outside [0,255]. Thus prevent unwanted promotion - // of char to signed int and take the unsigned char value. - if( !isalnum( static_cast(*it), clocale ) ) { + if( !isalnum_C( *it ) ) { *it = '_'; } } diff --git a/code/ColladaExporter.h b/code/ColladaExporter.h index f8bdbe7fc..858cef2b6 100644 --- a/code/ColladaExporter.h +++ b/code/ColladaExporter.h @@ -130,9 +130,6 @@ public: std::stringstream mOutput; protected: - /// C locale - std::locale clocale; - /// The IOSystem for output IOSystem* mIOSystem;