mbsrtowcs.c raw

   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  }
 121