From: <man...@us...> - 2013-11-07 15:45:42
|
Revision: 3111 http://sourceforge.net/p/modplug/code/3111 Author: manxorist Date: 2013-11-07 15:45:35 +0000 (Thu, 07 Nov 2013) Log Message: ----------- [Fix] VS2008 gets the character set conversion wrong for std::fstream filenames as char strings. It uses the C locale instead of the windows CP_ACP ansi codepage for conversion. Provide mpt::fstream in common/mptFstream.h wrappers around <fstream> which do the conversion the correct way on VS2008. For other compilers, nothing is changed. Modified Paths: -------------- trunk/OpenMPT/libopenmpt/libopenmpt.vcxproj trunk/OpenMPT/libopenmpt/libopenmpt.vcxproj.filters trunk/OpenMPT/mptrack/CommandSet.cpp trunk/OpenMPT/mptrack/Mod2wave.cpp trunk/OpenMPT/mptrack/Moddoc.cpp trunk/OpenMPT/mptrack/Settings.cpp trunk/OpenMPT/mptrack/TuningDialog.cpp trunk/OpenMPT/mptrack/Vstplug.cpp trunk/OpenMPT/mptrack/mptrack_08.vcproj trunk/OpenMPT/mptrack/mptrack_10.vcxproj trunk/OpenMPT/mptrack/mptrack_10.vcxproj.filters trunk/OpenMPT/soundlib/Load_it.cpp trunk/OpenMPT/soundlib/tuningCollection.cpp trunk/OpenMPT/test/test.cpp Added Paths: ----------- trunk/OpenMPT/common/mptFstream.h Added: trunk/OpenMPT/common/mptFstream.h =================================================================== --- trunk/OpenMPT/common/mptFstream.h (rev 0) +++ trunk/OpenMPT/common/mptFstream.h 2013-11-07 15:45:35 UTC (rev 3111) @@ -0,0 +1,167 @@ +/* + * mptFstream.h + * ------------ + * Purpose: A wrapper around std::fstream, fixing VS2008 charset conversion braindamage. + * Notes : You should only ever use these wrappers instead of plain std::fstream classes. + * Authors: OpenMPT Devs + * The OpenMPT source code is released under the BSD license. Read LICENSE for more details. + */ + +#pragma once + +#include <fstream> + +#if MPT_COMPILER_MSVC && MPT_MSVC_BEFORE(2010,0) +#include "../common/mptString.h" +#endif + +namespace mpt +{ + +#if MPT_COMPILER_MSVC && MPT_MSVC_BEFORE(2010,0) + +// VS2008 converts char filenames with CRT mbcs string conversion functions to wchar_t filenames. +// This is totally wrong for Win32 GUI applications because the C locale does not necessarily match the current windows ANSI codepage (CP_ACP). +// Work around this insanity by using our own string conversions for the std::fstream filenames. + +class fstream + : public std::fstream +{ +private: + void mptopen(const std::wstring & filename, std::ios_base::openmode mode) + { + std::fstream::open(filename.c_str(), mode); + } + void mptopen(const std::string & filename, std::ios_base::openmode mode) + { + mptopen(mpt::String::Decode(filename, mpt::CharsetLocale).c_str(), mode); + } + void mptopen(const char * filename, std::ios_base::openmode mode) + { + mptopen(filename ? std::string(filename) : std::string(), mode); + } +public: + fstream() {} + fstream(const char * filename, std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out) + { + mptopen(filename, mode); + } + fstream(const std::string & filename, std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out) + { + mptopen(filename, mode); + } + fstream(const wchar_t * filename, std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out) + { + mptopen(filename, mode); + } + fstream(const std::wstring & filename, std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out) + { + mptopen(filename, mode); + } + void open(const char * filename, std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out) + { + mptopen(filename, mode); + } + void open(const std::string & filename, std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out) + { + mptopen(filename, mode); + } +}; + +class ifstream + : public std::ifstream +{ +private: + void mptopen(const std::wstring & filename, std::ios_base::openmode mode) + { + std::ifstream::open(filename.c_str(), mode); + } + void mptopen(const std::string & filename, std::ios_base::openmode mode) + { + mptopen(mpt::String::Decode(filename, mpt::CharsetLocale).c_str(), mode); + } + void mptopen(const char * filename, std::ios_base::openmode mode) + { + mptopen(filename ? std::string(filename) : std::string(), mode); + } +public: + ifstream() {} + ifstream(const char * filename, std::ios_base::openmode mode = std::ios_base::in) + { + mptopen(filename, mode); + } + ifstream(const std::string & filename, std::ios_base::openmode mode = std::ios_base::in) + { + mptopen(filename, mode); + } + ifstream(const wchar_t * filename, std::ios_base::openmode mode = std::ios_base::in) + { + mptopen(filename, mode); + } + ifstream(const std::wstring & filename, std::ios_base::openmode mode = std::ios_base::in) + { + mptopen(filename, mode); + } + void open(const char * filename, std::ios_base::openmode mode = std::ios_base::in) + { + mptopen(filename, mode); + } + void open(const std::string & filename, std::ios_base::openmode mode = std::ios_base::in) + { + mptopen(filename, mode); + } +}; + +class ofstream + : public std::ofstream +{ +private: + void mptopen(const std::wstring & filename, std::ios_base::openmode mode) + { + std::ofstream::open(filename.c_str(), mode); + } + void mptopen(const std::string & filename, std::ios_base::openmode mode) + { + mptopen(mpt::String::Decode(filename, mpt::CharsetLocale).c_str(), mode); + } + void mptopen(const char * filename, std::ios_base::openmode mode) + { + mptopen(filename ? std::string(filename) : std::string(), mode); + } +public: + ofstream() {} + ofstream(const char * filename, std::ios_base::openmode mode = std::ios_base::out) + { + mptopen(filename, mode); + } + ofstream(const std::string & filename, std::ios_base::openmode mode = std::ios_base::out) + { + mptopen(filename, mode); + } + ofstream(const wchar_t * filename, std::ios_base::openmode mode = std::ios_base::out) + { + mptopen(filename, mode); + } + ofstream(const std::wstring & filename, std::ios_base::openmode mode = std::ios_base::out) + { + mptopen(filename, mode); + } + void open(const char * filename, std::ios_base::openmode mode = std::ios_base::out) + { + mptopen(filename, mode); + } + void open(const std::string & filename, std::ios_base::openmode mode = std::ios_base::out) + { + mptopen(filename, mode); + } +}; + +#else + +typedef std::fstream fstream; +typedef std::ifstream ifstream; +typedef std::ofstream ofstream; + +#endif + +} // namespace mpt Property changes on: trunk/OpenMPT/common/mptFstream.h ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +text/x-chdr \ No newline at end of property Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Modified: trunk/OpenMPT/libopenmpt/libopenmpt.vcxproj =================================================================== --- trunk/OpenMPT/libopenmpt/libopenmpt.vcxproj 2013-11-07 15:39:20 UTC (rev 3110) +++ trunk/OpenMPT/libopenmpt/libopenmpt.vcxproj 2013-11-07 15:45:35 UTC (rev 3111) @@ -415,6 +415,7 @@ <ClInclude Include="..\common\FlagSet.h" /> <ClInclude Include="..\common\Logging.h" /> <ClInclude Include="..\common\misc_util.h" /> + <ClInclude Include="..\common\mptFstream.h" /> <ClInclude Include="..\common\mptString.h" /> <ClInclude Include="..\common\mutex.h" /> <ClInclude Include="..\common\Profiler.h" /> Modified: trunk/OpenMPT/libopenmpt/libopenmpt.vcxproj.filters =================================================================== --- trunk/OpenMPT/libopenmpt/libopenmpt.vcxproj.filters 2013-11-07 15:39:20 UTC (rev 3110) +++ trunk/OpenMPT/libopenmpt/libopenmpt.vcxproj.filters 2013-11-07 15:45:35 UTC (rev 3111) @@ -254,6 +254,9 @@ <ClInclude Include="libopenmpt_stream_callbacks_file.h"> <Filter>Header Files</Filter> </ClInclude> + <ClInclude Include="..\common\mptFstream.h"> + <Filter>Header Files\common</Filter> + </ClInclude> </ItemGroup> <ItemGroup> <ClCompile Include="..\common\AudioCriticalSection.cpp"> Modified: trunk/OpenMPT/mptrack/CommandSet.cpp =================================================================== --- trunk/OpenMPT/mptrack/CommandSet.cpp 2013-11-07 15:39:20 UTC (rev 3110) +++ trunk/OpenMPT/mptrack/CommandSet.cpp 2013-11-07 15:45:35 UTC (rev 3111) @@ -16,7 +16,7 @@ #include "../mptrack/Reporting.h" #include <stdio.h> #include <stdlib.h> -#include <fstream> +#include "../common/mptFstream.h" #define ENABLE_LOGGING 0 @@ -1678,7 +1678,7 @@ bool CCommandSet::LoadFile(CString fileName) //------------------------------------------ { - std::ifstream fin(fileName); + mpt::ifstream fin(fileName); if (fin.fail()) { CString strMsg; Modified: trunk/OpenMPT/mptrack/Mod2wave.cpp =================================================================== --- trunk/OpenMPT/mptrack/Mod2wave.cpp 2013-11-07 15:39:20 UTC (rev 3110) +++ trunk/OpenMPT/mptrack/Mod2wave.cpp 2013-11-07 15:45:35 UTC (rev 3111) @@ -24,7 +24,7 @@ #include "../soundlib/Dither.h" #include "../soundlib/AudioReadTarget.h" -#include <fstream> +#include "../common/mptFstream.h" extern const char *gszChnCfgNames[3]; @@ -847,13 +847,13 @@ char *tempPath = _tempnam("", "OpenMPT_mod2wave"); const std::string normalizeFileName = tempPath; free(tempPath); - std::fstream normalizeFile; + mpt::fstream normalizeFile; if(m_Settings.Normalize) { normalizeFile.open(normalizeFileName.c_str(), std::ios::binary | std::ios::in | std::ios::out | std::ios::trunc); } - std::ofstream fileStream(m_lpszFileName, std::ios::binary | std::ios::trunc); + mpt::ofstream fileStream(m_lpszFileName, std::ios::binary | std::ios::trunc); if(!fileStream) { Modified: trunk/OpenMPT/mptrack/Moddoc.cpp =================================================================== --- trunk/OpenMPT/mptrack/Moddoc.cpp 2013-11-07 15:39:20 UTC (rev 3110) +++ trunk/OpenMPT/mptrack/Moddoc.cpp 2013-11-07 15:45:35 UTC (rev 3111) @@ -31,7 +31,7 @@ #ifdef NO_FILEREADER_STD_ISTREAM #include "MemoryMappedFile.h" #else -#include <fstream> +#include "../common/mptFstream.h" #endif #include "soundlib/FileReader.h" #include <shlwapi.h> @@ -218,7 +218,7 @@ BeginWaitCursor(); #ifndef NO_FILEREADER_STD_ISTREAM - std::ifstream f(lpszPathName, std::ios_base::binary); + mpt::ifstream f(lpszPathName, std::ios_base::binary); m_SndFile.Create(FileReader(&f), CSoundFile::loadCompleteModule, this); #else { Modified: trunk/OpenMPT/mptrack/Settings.cpp =================================================================== --- trunk/OpenMPT/mptrack/Settings.cpp 2013-11-07 15:39:20 UTC (rev 3110) +++ trunk/OpenMPT/mptrack/Settings.cpp 2013-11-07 15:45:35 UTC (rev 3111) @@ -20,7 +20,7 @@ #include <shlwapi.h> #include <algorithm> -#include <fstream> +#include "../common/mptFstream.h" #include <iterator> @@ -434,7 +434,7 @@ static std::vector<char> ReadFile(const mpt::PathString &filename) { - std::ifstream s(filename.c_str(), std::ios::binary); + mpt::ifstream s(filename.c_str(), std::ios::binary); std::vector<char> result; while(s) { @@ -449,7 +449,7 @@ static void WriteFileUTF16LE(const mpt::PathString &filename, const std::wstring &str) { STATIC_ASSERT(sizeof(wchar_t) == 2); - std::ofstream inifile(filename.c_str(), std::ios::binary | std::ios::trunc); + mpt::ofstream inifile(filename.c_str(), std::ios::binary | std::ios::trunc); const uint8 UTF16LE_BOM[] = { 0xff, 0xfe }; inifile.write(reinterpret_cast<const char*>(UTF16LE_BOM), 2); inifile.write(reinterpret_cast<const char*>(str.c_str()), str.length() * sizeof(std::wstring::value_type)); Modified: trunk/OpenMPT/mptrack/TuningDialog.cpp =================================================================== --- trunk/OpenMPT/mptrack/TuningDialog.cpp 2013-11-07 15:39:20 UTC (rev 3110) +++ trunk/OpenMPT/mptrack/TuningDialog.cpp 2013-11-07 15:45:35 UTC (rev 3111) @@ -13,7 +13,7 @@ #include "TuningDialog.h" #include "TrackerSettings.h" #include <algorithm> -#include <fstream> +#include "../common/mptFstream.h" #include "../common/misc_util.h" #include "tuningdialog.h" @@ -639,7 +639,7 @@ bool failure = true; - std::ofstream fout(files.first_file.c_str(), std::ios::binary); + mpt::ofstream fout(files.first_file.c_str(), std::ios::binary); const std::string ext = "." + files.extension; if(ext == CTuning::s_FileExtension) @@ -699,7 +699,7 @@ if (bIsTun) { - std::ifstream fin(files.filenames[counter].c_str(), std::ios::binary); + mpt::ifstream fin(files.filenames[counter].c_str(), std::ios::binary); pT = CTuningRTI::DeserializeOLD(fin); if(pT == 0) {fin.clear(); fin.seekg(0); pT = CTuningRTI::Deserialize(fin);} Modified: trunk/OpenMPT/mptrack/Vstplug.cpp =================================================================== --- trunk/OpenMPT/mptrack/Vstplug.cpp 2013-11-07 15:39:20 UTC (rev 3110) +++ trunk/OpenMPT/mptrack/Vstplug.cpp 2013-11-07 15:45:35 UTC (rev 3111) @@ -28,7 +28,7 @@ #include "MemoryMappedFile.h" #include "../soundlib/FileReader.h" #include "../soundlib/plugins/JBridge.h" -#include <fstream> +#include "../common/mptFstream.h" #ifdef VST_USE_ALTERNATIVE_MAGIC //Pelya's plugin ID fix. Breaks fx presets, so let's avoid it for now. #include "../zlib/zlib.h" //For CRC32 calculation (to detect plugins with same UID) #endif // VST_USE_ALTERNATIVE_MAGIC @@ -1622,8 +1622,7 @@ bool bank = !mpt::strnicmp(files.first_file.substr(files.first_file.length() - 3).c_str(), "fxb", 3); - std::fstream f; - f.open(files.first_file.c_str(), std::ios::out | std::ios::trunc | std::ios::binary); + mpt::fstream f(files.first_file.c_str(), std::ios::out | std::ios::trunc | std::ios::binary); if(f.good() && VSTPresets::SaveFile(f, *this, bank)) { return true; Modified: trunk/OpenMPT/mptrack/mptrack_08.vcproj =================================================================== --- trunk/OpenMPT/mptrack/mptrack_08.vcproj 2013-11-07 15:39:20 UTC (rev 3110) +++ trunk/OpenMPT/mptrack/mptrack_08.vcproj 2013-11-07 15:45:35 UTC (rev 3111) @@ -1041,6 +1041,10 @@ > </File> <File + RelativePath="..\common\mptFstream.h" + > + </File> + <File RelativePath=".\mptrack.h" > </File> Modified: trunk/OpenMPT/mptrack/mptrack_10.vcxproj =================================================================== --- trunk/OpenMPT/mptrack/mptrack_10.vcxproj 2013-11-07 15:39:20 UTC (rev 3110) +++ trunk/OpenMPT/mptrack/mptrack_10.vcxproj 2013-11-07 15:45:35 UTC (rev 3111) @@ -622,6 +622,7 @@ <ClInclude Include="..\common\FlagSet.h" /> <ClInclude Include="..\common\Logging.h" /> <ClInclude Include="..\common\misc_util.h" /> + <ClInclude Include="..\common\mptFstream.h" /> <ClInclude Include="..\common\mptString.h" /> <ClInclude Include="..\common\mutex.h" /> <ClInclude Include="..\common\Profiler.h" /> Modified: trunk/OpenMPT/mptrack/mptrack_10.vcxproj.filters =================================================================== --- trunk/OpenMPT/mptrack/mptrack_10.vcxproj.filters 2013-11-07 15:39:20 UTC (rev 3110) +++ trunk/OpenMPT/mptrack/mptrack_10.vcxproj.filters 2013-11-07 15:45:35 UTC (rev 3111) @@ -936,6 +936,9 @@ <ClInclude Include="svn_version\svn_version.h"> <Filter>Header Files</Filter> </ClInclude> + <ClInclude Include="..\common\mptFstream.h"> + <Filter>Header Files\common</Filter> + </ClInclude> </ItemGroup> <ItemGroup> <None Include="res\bitmap1.bmp"> Modified: trunk/OpenMPT/soundlib/Load_it.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_it.cpp 2013-11-07 15:39:20 UTC (rev 3110) +++ trunk/OpenMPT/soundlib/Load_it.cpp 2013-11-07 15:45:35 UTC (rev 3111) @@ -16,7 +16,7 @@ #include "../mptrack/moddoc.h" #endif #include "../common/serialization_utils.h" -#include <fstream> +#include "../common/mptFstream.h" #include <sstream> #include <list> #include "../common/version.h" @@ -1624,7 +1624,7 @@ // Using std::ios::in | std::ios::out | std::ios::ate prevents truncation and sets the file pointer to the end of the so-far saved file, // but it also allows reading, which does no harm but is not what we actually really want here. // That's a very broken interface. - std::ofstream fout(lpszFileName, std::ios::binary | std::ios::ate | std::ios::in); + mpt::ofstream fout(lpszFileName, std::ios::binary | std::ios::ate | std::ios::in); #endif const uint32 MPTStartPos = (uint32)fout.tellp(); Modified: trunk/OpenMPT/soundlib/tuningCollection.cpp =================================================================== --- trunk/OpenMPT/soundlib/tuningCollection.cpp 2013-11-07 15:39:20 UTC (rev 3110) +++ trunk/OpenMPT/soundlib/tuningCollection.cpp 2013-11-07 15:45:35 UTC (rev 3111) @@ -13,7 +13,7 @@ #include "../common/serialization_utils.h" #include <algorithm> #include <bitset> -#include <fstream> +#include "../common/mptFstream.h" /* Version history: @@ -124,7 +124,7 @@ { if(m_SavefilePath.length() < 1) return SERIALIZATION_FAILURE; - std::ofstream fout(m_SavefilePath.c_str(), std::ios::binary); + mpt::ofstream fout(m_SavefilePath.c_str(), std::ios::binary); if(!fout.good()) return SERIALIZATION_FAILURE; @@ -139,7 +139,7 @@ { if(m_SavefilePath.length() < 1) return SERIALIZATION_FAILURE; - std::ifstream fin(m_SavefilePath.c_str(), std::ios::binary); + mpt::ifstream fin(m_SavefilePath.c_str(), std::ios::binary); if(!fin.good()) return SERIALIZATION_FAILURE; Modified: trunk/OpenMPT/test/test.cpp =================================================================== --- trunk/OpenMPT/test/test.cpp 2013-11-07 15:39:20 UTC (rev 3110) +++ trunk/OpenMPT/test/test.cpp 2013-11-07 15:45:35 UTC (rev 3111) @@ -32,7 +32,7 @@ #include "../mptrack/Settings.h" #endif // MODPLUG_TRACKER #ifndef MODPLUG_TRACKER -#include <fstream> +#include "../common/mptFstream.h" #endif // !MODPLUG_TRACKER #include <limits> #ifndef MODPLUG_TRACKER @@ -1424,7 +1424,7 @@ static TSoundFileContainer CreateSoundFileContainer(const std::string &filename) { - std::ifstream stream(filename, std::ios::binary); + mpt::ifstream stream(filename, std::ios::binary); FileReader file(&stream); std::shared_ptr<CSoundFile> pSndFile(new CSoundFile()); pSndFile->Create(file, CSoundFile::loadCompleteModule); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |