in source/shared/globalization.h [194:269]
size_t Convert(
iconv_buffer<DestType> & dest,
iconv_buffer<SrcType> & src,
bool failIfLossy = false, bool * pHasLoss = NULL, DWORD * pErrorCode = NULL ) const
{
if ( !IsValidIConv() )
return 0;
size_t iconv_ret;
size_t cchDest = dest.m_nBytesLeft/sizeof(DestType);
if ( NULL != pHasLoss )
*pHasLoss = false;
if ( NULL != pErrorCode )
*pErrorCode = ERROR_SUCCESS;
while ( 0 < dest.m_nBytesLeft && 0 < src.m_nBytesLeft )
{
// First clear any intermediate state left over from previous conversions
iconv_ret = iconv( m_pCvtCache->GetIConv(), NULL, NULL, NULL, NULL );
assert( 0 == iconv_ret );
// Now attempt conversion
iconv_ret = iconv( m_pCvtCache->GetIConv(), &src.m_pBytes, &src.m_nBytesLeft, &dest.m_pBytes, &dest.m_nBytesLeft );
if ( iconv_ret == (size_t)(-1) )
{
// If there's no dest bytes left, then treat as E2BIG even if the error
// is EILSEQ, etc. We want E2BIG to take precedence like Windows.
int err = (0 < dest.m_nBytesLeft ? errno : E2BIG);
if ( E2BIG != err && failIfLossy )
{
if ( NULL != pErrorCode )
*pErrorCode = ERROR_NO_UNICODE_TRANSLATION;
return 0;
}
switch ( err )
{
case EILSEQ: // Invalid multibyte sequence in input
if ( CP_UTF8 == m_srcCodePage )
src.SkipUtf8Ch();
else if ( 1 == sizeof(SrcType) )
src.SkipDoubleCh(); // DBCS
else
src.SkipSingleCh(); // utf32 or incomplate utf16 surrogate
if ( !AddDefault(&dest, pHasLoss, pErrorCode) )
return 0;
break;
case EINVAL: // Incomplete multibyte sequence in input
if ( CP_UTF8 == m_srcCodePage )
src.SkipUtf8Ch();
else
src.SkipSingleCh();
if ( !AddDefault(&dest, pHasLoss, pErrorCode) )
return 0;
break;
case E2BIG: // Output buffer is out of room
if ( NULL != pErrorCode )
*pErrorCode = ERROR_INSUFFICIENT_BUFFER;
return 0;
default:
if ( NULL != pErrorCode )
*pErrorCode = ERROR_INVALID_PARAMETER;
return 0;
}
}
//if a shift sequence is encountered, we need to advance output buffer
iconv_ret = iconv( m_pCvtCache->GetIConv(), NULL, NULL, &dest.m_pBytes, &dest.m_nBytesLeft );
}
return cchDest - (dest.m_nBytesLeft / sizeof(DestType));
}