From 1161c5817059464ab511632c0ce5d14593ced1a3 Mon Sep 17 00:00:00 2001 From: Jose Date: Fri, 2 May 2014 19:56:38 +0200 Subject: ICE-4851 - Use wstrings for input and output data that contain non-ASCII characters? --- cpp/src/Ice/LoggerI.cpp | 117 +++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 110 insertions(+), 7 deletions(-) (limited to 'cpp/src/Ice/LoggerI.cpp') diff --git a/cpp/src/Ice/LoggerI.cpp b/cpp/src/Ice/LoggerI.cpp index 3375a2704e5..b5e599cc638 100644 --- a/cpp/src/Ice/LoggerI.cpp +++ b/cpp/src/Ice/LoggerI.cpp @@ -11,7 +11,13 @@ #include #include #include -#include + +#ifdef _WIN32 +# include +# include +# include +#endif + #include using namespace std; @@ -41,9 +47,70 @@ public: Init init; +#ifdef _WIN32 +string +UTF8ToCodePage(const string& in, int codePage) +{ + string out; + if(!in.empty()) + { + if(CP_UTF8 == codePage) + { + out = in; + } + else + { + IceUtil::ScopedArray wbuffer; + int size = 0; + int wlength = 0; + do + { + size == 0 ? 2 * in.size() : 2 * size; + wbuffer.reset(new wchar_t[size]); + wlength = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, in.c_str(), -1, wbuffer.get(), size); + } + while(wlength == 0 && GetLastError() == ERROR_INSUFFICIENT_BUFFER); + + if(wlength == 0) + { + throw IceUtil::IllegalConversionException(__FILE__, __LINE__, IceUtilInternal::lastErrorToString()); + } + + // + // WC_ERR_INVALID_CHARS conversion flag is only supported with 65001 (UTF-8) and + // 54936 (GB18030 Simplified Chinese) + // + DWORD conversionFlags = (codePage == 65001 || codePage == 54936) ? WC_ERR_INVALID_CHARS : 0; + + IceUtil::ScopedArray buffer; + + size = 0; + int length = 0; + do + { + size == 0 ? wlength + 2 : 2 * size; + buffer.reset(new char[length]); + length = WideCharToMultiByte(codePage, conversionFlags, wbuffer.get(), wlength, buffer.get(), size, 0, 0); + } + while(length == 0 && GetLastError() == ERROR_INSUFFICIENT_BUFFER); + + if(!length) + { + throw IceUtil::IllegalConversionException(__FILE__, __LINE__, IceUtilInternal::lastErrorToString());; + } + out.assign(buffer.get(), length); + } + } + return out; } +#endif -Ice::LoggerI::LoggerI(const string& prefix, const string& file) +} + +Ice::LoggerI::LoggerI(const string& prefix, const string& file, + bool convert, const IceUtil::StringConverterPtr& converter) : + _convert(convert), + _converter(converter) { if(!prefix.empty()) { @@ -52,10 +119,6 @@ Ice::LoggerI::LoggerI(const string& prefix, const string& file) if(!file.empty()) { - // - // The given file string is execpted to be encoded as UTF8 by - // the caller, so no need to convert it here. - // _file = file; _out.open(file, fstream::out | fstream::app); if(!_out.is_open()) @@ -108,7 +171,7 @@ Ice::LoggerI::error(const string& message) LoggerPtr Ice::LoggerI::cloneWithPrefix(const std::string& prefix) { - return new LoggerI(prefix, _file); + return new LoggerI(prefix, _file, _convert, _converter); } void @@ -134,6 +197,46 @@ Ice::LoggerI::write(const string& message, bool indent) } else { +#ifndef _WIN32 cerr << s << endl; +#else + // + // Convert the message from the native narrow string encoding to the console + // code page encoding for printing. If the _convert member is set to false + // we don't do any conversion. + // + if(!_convert) + { + cerr << s << endl; + } + else + { + try + { + // + // First we convert the message to UTF8 using nativeToUTF8 + // then we convert the message to the console code page + // using UTF8ToCodePage. + // + // nativeToUTF8 doesn't do any conversion if the converter is + // null likewise UTF8ToCodePage doesn't do any conversion if + // the code page is UTF8. + // + // We cannot use cerr here as writing to console using cerr + // will do its own conversion and will corrupt the messages. + // + fprintf_s(stderr, "%s\n", UTF8ToCodePage(IceUtil::nativeToUTF8(_converter, s), + GetConsoleOutputCP()).c_str()); + } + catch(const IceUtil::IllegalConversionException&) + { + // + // If there is a problem with the encoding conversions we just + // write the original message without encoding conversions. + // + fprintf_s(stderr, "%s\n", s.c_str()); + } + } +#endif } } -- cgit v1.2.3