// Common/StringConvert.cpp #include "StdAfx.h" #include "StringConvert.h" #ifndef _WIN32 #include <stdlib.h> #endif static const char k_DefultChar = '_'; #ifdef _WIN32 /* MultiByteToWideChar(CodePage, DWORD dwFlags, LPCSTR lpMultiByteStr, int cbMultiByte, LPWSTR lpWideCharStr, int cchWideChar) if (cbMultiByte == 0) return: 0. ERR: ERROR_INVALID_PARAMETER if (cchWideChar == 0) return: the required buffer size in characters. if (supplied buffer size was not large enough) return: 0. ERR: ERROR_INSUFFICIENT_BUFFER The number of filled characters in lpWideCharStr can be smaller than cchWideChar (if last character is complex) If there are illegal characters: if MB_ERR_INVALID_CHARS is set in dwFlags: - the function stops conversion on illegal character. - Return: 0. ERR: ERROR_NO_UNICODE_TRANSLATION. if MB_ERR_INVALID_CHARS is NOT set in dwFlags: before Vista: illegal character is dropped (skipped). WinXP-64: GetLastError() returns 0. in Vista+: illegal character is not dropped (MSDN). Undocumented: illegal character is converted to U+FFFD, which is REPLACEMENT CHARACTER. */ void MultiByteToUnicodeString2(UString &dest, const AString &src, UINT codePage) { dest.Empty(); if (src.IsEmpty()) return; { /* wchar_t *d = dest.GetBuf(src.Len()); const char *s = (const char *)src; unsigned i; for (i = 0;;) { Byte c = (Byte)s[i]; if (c >= 0x80 || c == 0) break; d[i++] = (wchar_t)c; } if (i != src.Len()) { unsigned len = MultiByteToWideChar(codePage, 0, s + i, src.Len() - i, d + i, src.Len() + 1 - i); if (len == 0) throw 282228; i += len; } d[i] = 0; dest.ReleaseBuf_SetLen(i); */ unsigned len = MultiByteToWideChar(codePage, 0, src, src.Len(), NULL, 0); if (len == 0) { if (GetLastError() != 0) throw 282228; } else { len = MultiByteToWideChar(codePage, 0, src, src.Len(), dest.GetBuf(len), len); if (len == 0) throw 282228; dest.ReleaseBuf_SetEnd(len); } } } /* int WideCharToMultiByte( UINT CodePage, DWORD dwFlags, LPCWSTR lpWideCharStr, int cchWideChar, LPSTR lpMultiByteStr, int cbMultiByte, LPCSTR lpDefaultChar, LPBOOL lpUsedDefaultChar); if (lpDefaultChar == NULL), - it uses system default value. if (CodePage == CP_UTF7 || CodePage == CP_UTF8) if (lpDefaultChar != NULL || lpUsedDefaultChar != NULL) return: 0. ERR: ERROR_INVALID_PARAMETER. The function operates most efficiently, if (lpDefaultChar == NULL && lpUsedDefaultChar == NULL) */ static void UnicodeStringToMultiByte2(AString &dest, const UString &src, UINT codePage, char defaultChar, bool &defaultCharWasUsed) { dest.Empty(); defaultCharWasUsed = false; if (src.IsEmpty()) return; { /* unsigned numRequiredBytes = src.Len() * 2; char *d = dest.GetBuf(numRequiredBytes); const wchar_t *s = (const wchar_t *)src; unsigned i; for (i = 0;;) { wchar_t c = s[i]; if (c >= 0x80 || c == 0) break; d[i++] = (char)c; } if (i != src.Len()) { BOOL defUsed = FALSE; defaultChar = defaultChar; bool isUtf = (codePage == CP_UTF8 || codePage == CP_UTF7); unsigned len = WideCharToMultiByte(codePage, 0, s + i, src.Len() - i, d + i, numRequiredBytes + 1 - i, (isUtf ? NULL : &defaultChar), (isUtf ? NULL : &defUsed)); defaultCharWasUsed = (defUsed != FALSE); if (len == 0) throw 282229; i += len; } d[i] = 0; dest.ReleaseBuf_SetLen(i); */ /* if (codePage != CP_UTF7) { const wchar_t *s = (const wchar_t *)src; unsigned i; for (i = 0;; i++) { wchar_t c = s[i]; if (c >= 0x80 || c == 0) break; } if (s[i] == 0) { char *d = dest.GetBuf(src.Len()); for (i = 0;;) { wchar_t c = s[i]; if (c == 0) break; d[i++] = (char)c; } d[i] = 0; dest.ReleaseBuf_SetLen(i); return; } } */ unsigned len = WideCharToMultiByte(codePage, 0, src, src.Len(), NULL, 0, NULL, NULL); if (len == 0) { if (GetLastError() != 0) throw 282228; } else { BOOL defUsed = FALSE; bool isUtf = (codePage == CP_UTF8 || codePage == CP_UTF7); // defaultChar = defaultChar; len = WideCharToMultiByte(codePage, 0, src, src.Len(), dest.GetBuf(len), len, (isUtf ? NULL : &defaultChar), (isUtf ? NULL : &defUsed) ); if (!isUtf) defaultCharWasUsed = (defUsed != FALSE); if (len == 0) throw 282228; dest.ReleaseBuf_SetEnd(len); } } } /* #ifndef UNDER_CE AString SystemStringToOemString(const CSysString &src) { AString dest; const unsigned len = src.Len() * 2; CharToOem(src, dest.GetBuf(len)); dest.ReleaseBuf_CalcLen(len); return dest; } #endif */ #else void MultiByteToUnicodeString2(UString &dest, const AString &src, UINT /* codePage */) { dest.Empty(); if (src.IsEmpty()) return; size_t limit = ((size_t)src.Len() + 1) * 2; wchar_t *d = dest.GetBuf((unsigned)limit); size_t len = mbstowcs(d, src, limit); if (len != (size_t)-1) { dest.ReleaseBuf_SetEnd((unsigned)len); return; } { unsigned i; const char *s = (const char *)src; for (i = 0;;) { Byte c = (Byte)s[i]; if (c == 0) break; d[i++] = (wchar_t)c; } d[i] = 0; dest.ReleaseBuf_SetLen(i); } } static void UnicodeStringToMultiByte2(AString &dest, const UString &src, UINT /* codePage */, char defaultChar, bool &defaultCharWasUsed) { dest.Empty(); defaultCharWasUsed = false; if (src.IsEmpty()) return; size_t limit = ((size_t)src.Len() + 1) * 6; char *d = dest.GetBuf((unsigned)limit); size_t len = wcstombs(d, src, limit); if (len != (size_t)-1) { dest.ReleaseBuf_SetEnd((unsigned)len); return; } { const wchar_t *s = (const wchar_t *)src; unsigned i; for (i = 0;;) { wchar_t c = s[i]; if (c == 0) break; if (c >= 0x100) { c = defaultChar; defaultCharWasUsed = true; } d[i++] = (char)c; } d[i] = 0; dest.ReleaseBuf_SetLen(i); } } #endif UString MultiByteToUnicodeString(const AString &src, UINT codePage) { UString dest; MultiByteToUnicodeString2(dest, src, codePage); return dest; } UString MultiByteToUnicodeString(const char *src, UINT codePage) { return MultiByteToUnicodeString(AString(src), codePage); } void UnicodeStringToMultiByte2(AString &dest, const UString &src, UINT codePage) { bool defaultCharWasUsed; UnicodeStringToMultiByte2(dest, src, codePage, k_DefultChar, defaultCharWasUsed); } AString UnicodeStringToMultiByte(const UString &src, UINT codePage, char defaultChar, bool &defaultCharWasUsed) { AString dest; UnicodeStringToMultiByte2(dest, src, codePage, defaultChar, defaultCharWasUsed); return dest; } AString UnicodeStringToMultiByte(const UString &src, UINT codePage) { AString dest; bool defaultCharWasUsed; UnicodeStringToMultiByte2(dest, src, codePage, k_DefultChar, defaultCharWasUsed); return dest; }