123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101 |
- /*
- * This code was written by Rich Felker in 2010; no copyright is claimed.
- * This code is in the public domain. Attribution is appreciated but
- * unnecessary.
- */
- #include <stdint.h>
- #include <wchar.h>
- #include <errno.h>
- #include "internal.h"
- size_t mbsrtowcs(wchar_t *restrict ws, const char **restrict src, size_t wn, mbstate_t *restrict st)
- {
- const unsigned char *s = (const void *)*src;
- size_t wn0 = wn;
- unsigned c = 0;
- if (st && (c = *(unsigned *)st)) {
- if (ws) {
- *(unsigned *)st = 0;
- goto resume;
- } else {
- goto resume0;
- }
- }
- if (!ws) for (;;) {
- if (*s-1u < 0x7f && (uintptr_t)s%4 == 0) {
- while (!(( *(uint32_t*)s | *(uint32_t*)s-0x01010101) & 0x80808080)) {
- s += 4;
- wn -= 4;
- }
- }
- if (*s-1u < 0x7f) {
- s++;
- wn--;
- continue;
- }
- if (*s-SA > SB-SA) break;
- c = bittab[*s++-SA];
- resume0:
- if (OOB(c,*s)) { s--; break; }
- s++;
- if (c&(1U<<25)) {
- if (*s-0x80u >= 0x40) { s-=2; break; }
- s++;
- if (c&(1U<<19)) {
- if (*s-0x80u >= 0x40) { s-=3; break; }
- s++;
- }
- }
- wn--;
- c = 0;
- } else for (;;) {
- if (!wn) {
- *src = (const void *)s;
- return wn0;
- }
- if (*s-1u < 0x7f && (uintptr_t)s%4 == 0) {
- while (wn>=5 && !(( *(uint32_t*)s | *(uint32_t*)s-0x01010101) & 0x80808080)) {
- *ws++ = *s++;
- *ws++ = *s++;
- *ws++ = *s++;
- *ws++ = *s++;
- wn -= 4;
- }
- }
- if (*s-1u < 0x7f) {
- *ws++ = *s++;
- wn--;
- continue;
- }
- if (*s-SA > SB-SA) break;
- c = bittab[*s++-SA];
- resume:
- if (OOB(c,*s)) { s--; break; }
- c = (c<<6) | *s++-0x80;
- if (c&(1U<<31)) {
- if (*s-0x80u >= 0x40) { s-=2; break; }
- c = (c<<6) | *s++-0x80;
- if (c&(1U<<31)) {
- if (*s-0x80u >= 0x40) { s-=3; break; }
- c = (c<<6) | *s++-0x80;
- }
- }
- *ws++ = c;
- wn--;
- c = 0;
- }
- if (!c && !*s) {
- if (ws) {
- *ws = 0;
- *src = 0;
- }
- return wn0-wn;
- }
- errno = EILSEQ;
- if (ws) *src = (const void *)s;
- return -1;
- }
|