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