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