mbrtowc.c 1.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
  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. #include <stdlib.h>
  7. #include <inttypes.h>
  8. #include <wchar.h>
  9. #include <errno.h>
  10. #include "internal.h"
  11. size_t mbrtowc(wchar_t *wc, const char *src, size_t n, mbstate_t *st)
  12. {
  13. static unsigned internal_state;
  14. unsigned c;
  15. const unsigned char *s = (const void *)src;
  16. const unsigned N = n;
  17. if (!st) st = (void *)&internal_state;
  18. c = *(unsigned *)st;
  19. if (!s) {
  20. s = (void *)"";
  21. wc = (void *)&wc;
  22. n = 1;
  23. } else if (!wc) wc = (void *)&wc;
  24. if (!n) return -2;
  25. if (!c) {
  26. if (*s < 0x80) return !!(*wc = *s);
  27. if (*s-SA > SB-SA) goto ilseq;
  28. c = bittab[*s++-SA]; n--;
  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. *(unsigned *)st = c;
  45. return -2;
  46. ilseq:
  47. *(unsigned *)st = FAILSTATE;
  48. errno = EILSEQ;
  49. return -1;
  50. }