mbrtowc.c raw

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