in src/odbc/rsodbc/rsunicode.c [463:558]
int unix_utf8_to_wchar(const char *szStr, int cbLen, WCHAR *wszStr, int cchLen)
{
int iLen, iCount;
int wch;
const char *pEnd = szStr + cbLen;
if (!cchLen)
return unix_utf8_to_wchar_len(szStr, cbLen);
for (iCount = cchLen; iCount && (szStr < pEnd); iCount--, wszStr++)
{
char ch = *szStr++;
wch = 0;
if ((unsigned char)ch < 0x80) /* 7-bit ASCII */
{
wch = ch;
*wszStr = wch;
continue;
}
iLen = g_utf8_len_data[((unsigned char)ch)-0x80];
wch = ch & g_utf8_mask_data[iLen];
switch(iLen)
{
case 5:
{
if (szStr >= pEnd)
goto end;
if ((ch = *szStr ^ 0x80) >= 0x40)
return 0;
wch = (wch << 6) | ch;
szStr++;
}
// no break
case 4:
{
if (szStr >= pEnd)
goto end;
if ((ch = *szStr ^ 0x80) >= 0x40)
return 0;
wch = (wch << 6) | ch;
szStr++;
}
// no break
case 3:
{
if (szStr >= pEnd)
goto end;
if ((ch = *szStr ^ 0x80) >= 0x40)
return 0;
wch = (wch << 6) | ch;
szStr++;
}
// no break
case 2:
{
if (szStr >= pEnd)
goto end;
if ((ch = *szStr ^ 0x80) >= 0x40)
return 0;
wch = (wch << 6) | ch;
szStr++;
}
// no break
case 1:
{
if (szStr >= pEnd)
goto end;
if ((ch = *szStr ^ 0x80) >= 0x40)
return 0;
wch = (wch << 6) | ch;
szStr++;
if (wch < g_utf8_minval_data[iLen])
return 0;
if (wch >= 0x10000)
return 0;
*wszStr = wch;
continue;
}
} // Switch
} // Loop
if (szStr < pEnd)
return 0;
end:
return cchLen - iCount;
}