github.com/afumu/libc@v0.0.6/musl/src/multibyte/mbsrtowcs.c (about)

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