in win_unicode.c [540:667]
SQLULEN utf8_to_ucs4_lf(const char *utf8str, SQLLEN ilen, BOOL lfconv,
UInt4 *ucs4str, SQLULEN bufcount, BOOL errcheck)
{
int i;
SQLULEN rtn, ocount, wcode;
const UCHAR *str;
MYLOG(MIN_LOG_LEVEL, " ilen=" FORMAT_LEN " bufcount=" FORMAT_ULEN "\n", ilen, bufcount);
if (!utf8str)
return 0;
MYLOG(99, " string=%s\n", utf8str);
if (!bufcount)
ucs4str = NULL;
else if (!ucs4str)
bufcount = 0;
if (ilen < 0)
ilen = strlen(utf8str);
for (i = 0, ocount = 0, str = (SQLCHAR *) utf8str; i < ilen && *str;)
{
if ((*str & 0x80) == 0)
{
if (lfconv && PG_LINEFEED == *str &&
(i == 0 || PG_CARRIAGE_RETURN != str[-1]))
{
if (ocount < bufcount)
ucs4str[ocount] = PG_CARRIAGE_RETURN;
ocount++;
}
if (ocount < bufcount)
ucs4str[ocount] = *str;
ocount++;
i++;
str++;
}
else if (0xf8 == (*str & 0xf8)) /* more than 5 byte code */
{
ocount = (SQLULEN) -1;
goto cleanup;
}
else if (0xf0 == (*str & 0xf8)) /* 4 byte code */
{
if (errcheck)
{
if (i + 4 > ilen ||
0 == (str[1] & 0x80) ||
0 == (str[2] & 0x80) ||
0 == (str[3] & 0x80))
{
ocount = (SQLULEN) -1;
goto cleanup;
}
}
if (ocount < bufcount)
{
wcode = (((((UInt4) *str) & byte4_m1) << 18) |
((((UInt4) str[1]) & byte4_m2) << 12) |
((((UInt4) str[2]) & byte4_m3) << 6)) |
(((UInt4) str[3]) & byte4_m4);
ucs4str[ocount] = wcode;
}
ocount++;
i += 4;
str += 4;
}
else if (0xe0 == (*str & 0xf0)) /* 3 byte code */
{
if (errcheck)
{
if (i + 3 > ilen ||
0 == (str[1] & 0x80) ||
0 == (str[2] & 0x80))
{
ocount = (SQLULEN) -1;
goto cleanup;
}
}
if (ocount < bufcount)
{
wcode = ((((UInt4) *str) & byte3_m1) << 12) |
((((UInt4) str[1]) & byte3_m2) << 6) |
(((UInt4) str[2]) & byte3_m3);
ucs4str[ocount] = wcode;
}
ocount++;
i += 3;
str += 3;
}
else if (0xc0 == (*str & 0xe0)) /* 2 byte code */
{
if (errcheck)
{
if (i + 2 > ilen ||
0 == (str[1] & 0x80))
{
ocount = (SQLULEN) -1;
goto cleanup;
}
}
if (ocount < bufcount)
{
wcode = ((((UInt4) *str) & byte2_m1) << 6) |
(((UInt4) str[1]) & byte2_m2);
ucs4str[ocount] = (SQLWCHAR) wcode;
}
ocount++;
i += 2;
str += 2;
}
else
{
ocount = (SQLULEN) -1;
goto cleanup;
}
}
cleanup:
rtn = ocount;
if (ocount == (SQLULEN) -1)
{
if (!errcheck)
rtn = 0;
ocount = 0;
}
if (ocount < bufcount && ucs4str)
ucs4str[ocount] = 0;
MYLOG(MIN_LOG_LEVEL, " ocount=" FORMAT_ULEN "\n", ocount);
return rtn;
}