Home | History | Annotate | Download | only in musl-multibyte
      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 <stdint.h>
      8 #include <wchar.h>
      9 #include <errno.h>
     10 #include "internal.h"
     11 
     12 size_t mbsrtowcs(wchar_t *restrict ws, const char **restrict src, size_t wn, mbstate_t *restrict st)
     13 {
     14 	const unsigned char *s = (const void *)*src;
     15 	size_t wn0 = wn;
     16 	unsigned c = 0;
     17 
     18 	if (st && (c = *(unsigned *)st)) {
     19 		if (ws) {
     20 			*(unsigned *)st = 0;
     21 			goto resume;
     22 		} else {
     23 			goto resume0;
     24 		}
     25 	}
     26 
     27 	if (!ws) for (;;) {
     28 		if (*s-1u < 0x7f && (uintptr_t)s%4 == 0) {
     29 			while (!(( *(uint32_t*)s | *(uint32_t*)s-0x01010101) & 0x80808080)) {
     30 				s += 4;
     31 				wn -= 4;
     32 			}
     33 		}
     34 		if (*s-1u < 0x7f) {
     35 			s++;
     36 			wn--;
     37 			continue;
     38 		}
     39 		if (*s-SA > SB-SA) break;
     40 		c = bittab[*s++-SA];
     41 resume0:
     42 		if (OOB(c,*s)) { s--; break; }
     43 		s++;
     44 		if (c&(1U<<25)) {
     45 			if (*s-0x80u >= 0x40) { s-=2; break; }
     46 			s++;
     47 			if (c&(1U<<19)) {
     48 				if (*s-0x80u >= 0x40) { s-=3; break; }
     49 				s++;
     50 			}
     51 		}
     52 		wn--;
     53 		c = 0;
     54 	} else for (;;) {
     55 		if (!wn) {
     56 			*src = (const void *)s;
     57 			return wn0;
     58 		}
     59 		if (*s-1u < 0x7f && (uintptr_t)s%4 == 0) {
     60 			while (wn>=5 && !(( *(uint32_t*)s | *(uint32_t*)s-0x01010101) & 0x80808080)) {
     61 				*ws++ = *s++;
     62 				*ws++ = *s++;
     63 				*ws++ = *s++;
     64 				*ws++ = *s++;
     65 				wn -= 4;
     66 			}
     67 		}
     68 		if (*s-1u < 0x7f) {
     69 			*ws++ = *s++;
     70 			wn--;
     71 			continue;
     72 		}
     73 		if (*s-SA > SB-SA) break;
     74 		c = bittab[*s++-SA];
     75 resume:
     76 		if (OOB(c,*s)) { s--; break; }
     77 		c = (c<<6) | *s++-0x80;
     78 		if (c&(1U<<31)) {
     79 			if (*s-0x80u >= 0x40) { s-=2; break; }
     80 			c = (c<<6) | *s++-0x80;
     81 			if (c&(1U<<31)) {
     82 				if (*s-0x80u >= 0x40) { s-=3; break; }
     83 				c = (c<<6) | *s++-0x80;
     84 			}
     85 		}
     86 		*ws++ = c;
     87 		wn--;
     88 		c = 0;
     89 	}
     90 
     91 	if (!c && !*s) {
     92 		if (ws) {
     93 			*ws = 0;
     94 			*src = 0;
     95 		}
     96 		return wn0-wn;
     97 	}
     98 	errno = EILSEQ;
     99 	if (ws) *src = (const void *)s;
    100 	return -1;
    101 }
    102