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 #include <errno.h> 9 #include "internal.h" 10 mbrtowc(wchar_t * restrict wc,const char * restrict src,size_t n,mbstate_t * restrict st)11size_t mbrtowc(wchar_t *restrict wc, const char *restrict src, size_t n, mbstate_t *restrict st) 12 { 13 static unsigned internal_state; 14 unsigned c; 15 const unsigned char *s = (const void *)src; 16 const unsigned N = n; 17 18 if (!st) st = (void *)&internal_state; 19 c = *(unsigned *)st; 20 21 if (!s) { 22 if (c) goto ilseq; 23 return 0; 24 } else if (!wc) wc = (void *)&wc; 25 26 if (!n) return -2; 27 if (!c) { 28 if (*s < 0x80) return !!(*wc = *s); 29 if (*s-SA > SB-SA) goto ilseq; 30 c = bittab[*s++-SA]; n--; 31 } 32 33 if (n) { 34 if (OOB(c,*s)) goto ilseq; 35 loop: 36 c = c<<6 | *s++-0x80; n--; 37 if (!(c&(1U<<31))) { 38 *(unsigned *)st = 0; 39 *wc = c; 40 return N-n; 41 } 42 if (n) { 43 if (*s-0x80u >= 0x40) goto ilseq; 44 goto loop; 45 } 46 } 47 48 *(unsigned *)st = c; 49 return -2; 50 ilseq: 51 *(unsigned *)st = 0; 52 errno = EILSEQ; 53 return -1; 54 } 55