// Convert wide characters to multibyte characters and write to the log file. // This function was split out into a separate function because the Log // function was getting cluttered. static void WriteWideCharacterToLog(const TCHAR* pwsz) { DWORD dwWritten; size_t converted; char psz[LOG_BUFFER_LENGTH]; mbstate_t mbstate; wcsrtombs_s(&converted, psz, LOG_BUFFER_LENGTH - 1, &pwsz, wcslen(pwsz) * sizeof(TCHAR), &mbstate); WriteFile((HANDLE) hfLog, psz, strlen(psz), &dwWritten, NULL); }
//---------------------------------------------------------------------- // //---------------------------------------------------------------------- bool SystemMultiByteEncoding::ConvertFromUTF16(const byte_t* pInBuffer, size_t uInByteCount, byte_t* pOutBuffer, size_t uOutBufferByteCount, size_t* pBytesUsed, size_t* pCharsUsed, bool* pUsedDefaultChar) const { #ifdef LNOTE_WCHAR_16 // wcsrtombs_s は変換したいサイズを指定することができず、基本的に \0 まで変換することになる。 // そのため、一度別バッファに移して \0 を付ける ReferenceBuffer tmpWideBuffer; tmpWideBuffer.reserve(uInByteCount + sizeof(wchar_t)); // NULL 文字分 tmpWideBuffer.copy(pInBuffer, uInByteCount); wchar_t* wideStr = (wchar_t*)tmpWideBuffer.getPointer(); wideStr[uInByteCount / sizeof(wchar_t)] = L'\0'; // Wide → Multi size_t convertedLen; mbstate_t mbstate = 0; ::memset((void*)&mbstate, 0, sizeof(mbstate)); errno_t err = wcsrtombs_s( &convertedLen, // 変換された文字数が格納される (Multi への変換なので、バイト数) (char*)pOutBuffer, // 出力先バッファ uOutBufferByteCount, // 出力先バッファのサイズ (バイト数) (const wchar_t**)&wideStr, // 変換元 _TRUNCATE, // 出力先バッファに格納できる最大バイト数 (実質↑↑と同じ。_TRUNCATE で \0 まで) &mbstate); LN_THROW(err == 0, ArgumentException); // 終端には \0 が強制的に付加される。純粋な文字部分のサイズが欲しいので -1 する。 // TODO: つまり、出力バッファは ↑の第2引数 +1ワード分 確保しておく必要がある convertedLen--; // wcsrtombs_s じゃ文字数カウントはできないので UnicodeUtils を使う int count; if (LN::UnicodeUtils::GetUTF16CharCount((LN::UTF16*)pInBuffer, uInByteCount / sizeof(LN::UTF16), true, &count) != LN::UTFConversionResult_Success){ return false; } *pBytesUsed = convertedLen; *pCharsUsed = count; #else LN_THROW(0, NotImplementedException); #endif return true; }
void TestAddendum( void ) { wchar_t wc; wchar_t wcs[10]; wchar_t * wcsPtr; int status; mbstate_t state; unsigned char mbc[MB_LEN_MAX]; unsigned char mbcs[10*MB_LEN_MAX+1]; unsigned char * mbcsPtr; errno_t rc; size_t retval; int violations = NumViolations; status = wctob( L'!' ); VERIFY( status == '!' ); status = mbtowc( &wc, "\x90\x90", 2 ); #ifndef DUMMY_DBCS VERIFY( status == 2 ); status = wctob( wc ); VERIFY( status == EOF ); #else VERIFY( status == 1 ); status = wctob( wc ); VERIFY( status == 0x90 ); #endif status = sisinit( NULL ); VERIFY( status != 0 ); state = 0; status = sisinit( &state ); VERIFY( status == 0 ); state = 123; status = sisinit( &state ); VERIFY( status == 0 ); status = mbrlen( "\0""!", 2, &state ); VERIFY( status == 0 ); status = mbrlen( "!", 2, &state ); VERIFY( status == 1 ); wc = L'\0'; rc = wcrtomb_s( &retval, mbc, MB_LEN_MAX, wc, &state ); VERIFY( rc == 0 ); VERIFY( *mbc == '\0' ); VERIFY( retval == 1 ); VERIFY( violations == NumViolations ); rc = wcrtomb_s( &retval, mbc, MB_LEN_MAX, L'X', &state ); VERIFY( rc == 0 ); VERIFY( *mbc == 'X' ); VERIFY( retval == 1 ); VERIFY( violations == NumViolations ); rc = wcrtomb_s( &retval, NULL, 0, L'X', &state ); VERIFY( rc == 0 ); VERIFY( retval == 1 ); VERIFY( violations == NumViolations ); _mbscpy( mbcs, "Foo!\x90\x90" ); mbcsPtr = mbcs; wcs[5] = wcs[6] = L'-'; rc = mbsrtowcs_s( &retval, wcs, 10, (const char**)(&mbcsPtr), 6, &state ); VERIFY( rc == 0 ); VERIFY( retval == 5 ); VERIFY( wcs[0] == L'F' ); VERIFY( wcs[1] == L'o' ); VERIFY( wcs[2] == L'o' ); VERIFY( wcs[3] == L'!' ); mbcsPtr = mbcs; rc = mbsrtowcs_s( &retval, NULL, 0, (const char**)(&mbcsPtr), 1, &state ); VERIFY( rc == 0 ); VERIFY( retval == 5 ); wcsPtr = wcs; _mbsset( mbcs, _mbsnextc("#") ); rc = wcsrtombs_s( &retval, mbcs, 10, (const wchar_t**)(&wcsPtr), 6, &state ); VERIFY( rc == 0 ); VERIFY( retval == 6 ); mbcs[retval] = '\0'; VERIFY( _mbscmp( mbcs, "Foo!\x90\x90" ) == 0 ); wcsPtr = wcs; rc = wcsrtombs_s( &retval, NULL, 0, (const wchar_t**)(&wcsPtr), 20, &state ); VERIFY( rc == 0 ); VERIFY( retval == 6 ); /***********************************************************************/ /* test runtime-constraints */ /***********************************************************************/ *mbc = 'X'; rc = wcrtomb_s( NULL, mbc, MB_LEN_MAX, wc, &state ); VERIFY( rc != 0 ); VERIFY( *mbc == '\0' ); VERIFY( ++violations == NumViolations ); *mbc = 'X'; rc = wcrtomb_s( &retval, mbc, MB_LEN_MAX, L'X', NULL ); VERIFY( rc != 0 ); VERIFY( *mbc == '\0' ); VERIFY( retval == -1 ); VERIFY( ++violations == NumViolations ); rc = wcrtomb_s( &retval, NULL, MB_LEN_MAX, L'X', &state ); VERIFY( rc != 0 ); VERIFY( retval == -1 ); VERIFY( ++violations == NumViolations ); *mbc = 'X'; rc = wcrtomb_s( &retval, mbc, 0, L'X', &state ); VERIFY( rc != 0 ); VERIFY( *mbc == 'X' ); VERIFY( retval == -1 ); VERIFY( ++violations == NumViolations ); #if RSIZE_MAX != SIZE_MAX rc = wcrtomb_s( &retval, mbc, ~0, L'X', &state ); VERIFY( rc != 0 ); VERIFY( retval == -1 ); VERIFY( *mbc == 'X' ); VERIFY( ++violations == NumViolations ); #endif mbcsPtr = mbcs; rc = mbsrtowcs_s( NULL, NULL, 0, (const char**)(&mbcsPtr), 1, &state ); VERIFY( rc != 0 ); VERIFY( ++violations == NumViolations ); rc = mbsrtowcs_s( &retval, NULL, 0, NULL, 1, &state ); VERIFY( rc != 0 ); VERIFY( retval == -1 ); VERIFY( ++violations == NumViolations ); mbcsPtr = NULL; rc = mbsrtowcs_s( &retval, NULL, 0, (const char**)(&mbcsPtr), 1, &state ); VERIFY( rc != 0 ); VERIFY( retval == -1 ); VERIFY( ++violations == NumViolations ); rc = mbsrtowcs_s( &retval, NULL, 0, (const char**)(&wcsPtr), 1, NULL ); VERIFY( rc != 0 ); VERIFY( retval == -1 ); VERIFY( ++violations == NumViolations ); rc = mbsrtowcs_s( &retval, NULL, 111, (const char**)(&wcsPtr), 1, &state ); VERIFY( rc != 0 ); VERIFY( retval == -1 ); VERIFY( ++violations == NumViolations ); wcsPtr = wcs; rc = wcsrtombs_s( &retval, mbcs, 5, (const wchar_t**)(&wcsPtr), 10, &state ); VERIFY( rc != 0 ); VERIFY( retval == -1 ); VERIFY( ++violations == NumViolations ); }