X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Fmultibyte%2Fmbsrtowcs.c;h=e23083d223fc4c5528d46730b7c12a936888ef64;hb=74483c5955a632af5d9a4783cc2b541764450551;hp=e2b434807d930160053f72b53107e445de3f9eea;hpb=0b44a0315b47dd8eced9f3b7f31580cf14bbfc01;p=oweals%2Fmusl.git diff --git a/src/multibyte/mbsrtowcs.c b/src/multibyte/mbsrtowcs.c index e2b43480..e23083d2 100644 --- a/src/multibyte/mbsrtowcs.c +++ b/src/multibyte/mbsrtowcs.c @@ -4,118 +4,117 @@ * unnecessary. */ -#include -#include +#include #include #include - +#include +#include #include "internal.h" -size_t mbsrtowcs(wchar_t *ws, const char **src, size_t wn, mbstate_t *st) +size_t mbsrtowcs(wchar_t *restrict ws, const char **restrict src, size_t wn, mbstate_t *restrict st) { - unsigned c; - const unsigned char *s = *src; - const wchar_t *wsorig = ws; - - if (!st) st = (void *)&c, c = 0; - else c = *(unsigned *)st; + const unsigned char *s = (const void *)*src; + size_t wn0 = wn; + unsigned c = 0; - if (c) { - *(unsigned *)st = 0; - if (!ws) { - wn = 0; + if (st && (c = *(unsigned *)st)) { + if (ws) { + *(unsigned *)st = 0; + goto resume; + } else { goto resume0; } - goto resume; } - if (!ws) for (wn=0;;) { - if ((unsigned)*s-SA >= SB-SA) { - while (((unsigned)s&3) && (unsigned)*s-1<0x7f) s++, wn++; - while (!(( *(uint32_t*)s | *(uint32_t*)s-0x01010101) & 0x80808080)) s+=4, wn+=4; - while ((unsigned)*s-1<0x7f) s++, wn++; - if (!*s) return wn; - if ((unsigned)*s-SA >= SB-SA) goto ilseq2; + if (MB_CUR_MAX==1) { + if (!ws) return strlen((const char *)s); + for (;;) { + if (!wn) { + *src = (const void *)s; + return wn0; + } + if (!*s) break; + c = *s++; + *ws++ = CODEUNIT(c); + wn--; } - c = bittab[*s++-SA]; - do { -resume0: - if (OOB(c,*s)) goto ilseq2; s++; - c <<= 6; if (!(c&(1U<<31))) break; -#ifdef I_FAILED_TO_RTFM_RFC3629 - if ((unsigned)*s++-0x80 >= 0x40) goto ilseq2; - c <<= 6; if (!(c&(1U<<31))) break; - if ((unsigned)*s++-0x80 >= 0x40) goto ilseq2; - c <<= 6; if (!(c&(1U<<31))) break; -#endif - if ((unsigned)*s++-0x80 >= 0x40) goto ilseq2; - c <<= 6; if (!(c&(1U<<31))) break; - if ((unsigned)*s++-0x80 >= 0x40) goto ilseq2; - } while (0); - wn++; c = 0; + *ws = 0; + *src = 0; + return wn0-wn; } - while (wn) { - if ((unsigned)*s-SA >= SB-SA) { - if (wn >= 7) { - while (((unsigned)s&3) && (unsigned)*s-1<0x7f) { - *ws++ = *s++; - wn--; - } - while (wn>=4 && !(( *(uint32_t*)s | *(uint32_t*)s-0x01010101) & 0x80808080)) { - *ws++ = *s++; - *ws++ = *s++; - *ws++ = *s++; - *ws++ = *s++; - wn -= 4; - } + 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; } - while (wn && (unsigned)*s-1<0x7f) { - *ws++ = *s++; - wn--; + } + 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++; } - if (!wn) break; - if (!*s) { - *ws = 0; - *src = 0; - return ws-wsorig; + } + 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 ((unsigned)*s-SA >= SB-SA) goto ilseq; } + if (*s-1u < 0x7f) { + *ws++ = *s++; + wn--; + continue; + } + if (*s-SA > SB-SA) break; c = bittab[*s++-SA]; - do { resume: - if (OOB(c,*s)) goto ilseq; - c = (c<<6) | *s++-0x80; - if (!(c&(1U<<31))) break; - -#ifdef I_FAILED_TO_RTFM_RFC3629 - if ((unsigned)*s-0x80 >= 0x40) goto ilseq; - c = (c<<6) | *s++-0x80; - if (!(c&(1U<<31))) break; - - if ((unsigned)*s-0x80 >= 0x40) goto ilseq; + 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))) break; -#endif - - if ((unsigned)*s-0x80 >= 0x40) goto ilseq; - c = (c<<6) | *s++-0x80; - if (!(c&(1U<<31))) break; - - if ((unsigned)*s-0x80 >= 0x40) goto ilseq; - c = (c<<6) | *s++-0x80; - } while (0); + if (c&(1U<<31)) { + if (*s-0x80u >= 0x40) { s-=3; break; } + c = (c<<6) | *s++-0x80; + } + } + *ws++ = c; + wn--; + c = 0; + } - *ws++ = c; wn--; c = 0; + if (!c && !*s) { + if (ws) { + *ws = 0; + *src = 0; + } + return wn0-wn; } - *src = s; - return ws-wsorig; -ilseq: - *src = s; -ilseq2: - /* enter permanently failing state */ - *(unsigned *)st = FAILSTATE; errno = EILSEQ; + if (ws) *src = (const void *)s; return -1; }