1/*
2 * This code was written by Rich Felker in 2010; no copyright is claimed.
3 * This code is in the public domain. Attribution is appreciated but
4 * unnecessary.
5 */
6
7#include <wchar.h>
8
9size_t mbsnrtowcs(wchar_t *restrict wcs, const char **restrict src, size_t n, size_t wn, mbstate_t *restrict st)
10{
11	size_t l, cnt=0, n2;
12	wchar_t *ws, wbuf[256];
13	const char *s = *src;
14
15	if (!wcs) ws = wbuf, wn = sizeof wbuf / sizeof *wbuf;
16	else ws = wcs;
17
18	/* making sure output buffer size is at most n/4 will ensure
19	 * that mbsrtowcs never reads more than n input bytes. thus
20	 * we can use mbsrtowcs as long as it's practical.. */
21
22	while ( s && wn && ( (n2=n/4)>=wn || n2>32 ) ) {
23		if (n2>=wn) n2=wn;
24		n -= n2;
25		l = mbsrtowcs(ws, &s, n2, st);
26		if (!(l+1)) {
27			cnt = l;
28			wn = 0;
29			break;
30		}
31		if (ws != wbuf) {
32			ws += l;
33			wn -= l;
34		}
35		cnt += l;
36	}
37	if (s) while (wn && n) {
38		l = mbrtowc(ws, s, n, st);
39		if (l+2<=2) {
40			if (!(l+1)) {
41				cnt = l;
42				break;
43			}
44			if (!l) {
45				s = 0;
46				break;
47			}
48			/* have to roll back partial character */
49			*(unsigned *)st = 0;
50			break;
51		}
52		s += l; n -= l;
53		/* safe - this loop runs fewer than sizeof(wbuf)/8 times */
54		ws++; wn--;
55		cnt++;
56	}
57	if (wcs) *src = s;
58	return cnt;
59}
60