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