int unix_utf8_to_wchar()

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;
}