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