2011-02-12 00:22:29 -05:00
|
|
|
/*
|
|
|
|
* This code was written by Rich Felker in 2010; no copyright is claimed.
|
|
|
|
* This code is in the public domain. Attribution is appreciated but
|
|
|
|
* unnecessary.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <wchar.h>
|
|
|
|
|
2012-09-06 22:44:55 -04:00
|
|
|
size_t wcsrtombs(char *restrict s, const wchar_t **restrict ws, size_t n, mbstate_t *restrict st)
|
2011-02-12 00:22:29 -05:00
|
|
|
{
|
|
|
|
const wchar_t *ws2;
|
|
|
|
char buf[4];
|
|
|
|
size_t N = n, l;
|
|
|
|
if (!s) {
|
|
|
|
for (n=0, ws2=*ws; *ws2; ws2++) {
|
2013-04-04 14:48:48 -04:00
|
|
|
if (*ws2 >= 0x80u) {
|
2011-02-12 00:22:29 -05:00
|
|
|
l = wcrtomb(buf, *ws2, 0);
|
|
|
|
if (!(l+1)) return -1;
|
|
|
|
n += l;
|
|
|
|
} else n++;
|
|
|
|
}
|
|
|
|
return n;
|
|
|
|
}
|
2014-06-02 16:21:47 -04:00
|
|
|
while (n>=4) {
|
|
|
|
if (**ws-1u >= 0x7fu) {
|
|
|
|
if (!**ws) {
|
|
|
|
*s = 0;
|
|
|
|
*ws = 0;
|
|
|
|
return N-n;
|
|
|
|
}
|
2011-02-12 00:22:29 -05:00
|
|
|
l = wcrtomb(s, **ws, 0);
|
|
|
|
if (!(l+1)) return -1;
|
|
|
|
s += l;
|
|
|
|
n -= l;
|
|
|
|
} else {
|
|
|
|
*s++ = **ws;
|
|
|
|
n--;
|
|
|
|
}
|
|
|
|
(*ws)++;
|
|
|
|
}
|
2014-06-02 16:21:47 -04:00
|
|
|
while (n) {
|
|
|
|
if (**ws-1u >= 0x7fu) {
|
|
|
|
if (!**ws) {
|
|
|
|
*s = 0;
|
|
|
|
*ws = 0;
|
|
|
|
return N-n;
|
|
|
|
}
|
2011-02-12 00:22:29 -05:00
|
|
|
l = wcrtomb(buf, **ws, 0);
|
|
|
|
if (!(l+1)) return -1;
|
|
|
|
if (l>n) return N-n;
|
|
|
|
wcrtomb(s, **ws, 0);
|
|
|
|
s += l;
|
|
|
|
n -= l;
|
|
|
|
} else {
|
|
|
|
*s++ = **ws;
|
|
|
|
n--;
|
|
|
|
}
|
|
|
|
(*ws)++;
|
|
|
|
}
|
2014-06-02 16:21:47 -04:00
|
|
|
return N;
|
2011-02-12 00:22:29 -05:00
|
|
|
}
|