diff options
author | pommicket <pommicket@gmail.com> | 2022-02-20 13:18:21 -0800 |
---|---|---|
committer | pommicket <pommicket@gmail.com> | 2022-02-20 13:18:21 -0800 |
commit | 9bc8a11afeed3569736b89754012e3ca22ee10f6 (patch) | |
tree | 5f0ec0d5c05f879b1ee86adfa654ed3ef2178d5f /05/musl-0.6.0/src/multibyte/mbsrtowcs.c | |
parent | 0f97a589b800bdb71dda05984192f0f66a52edaa (diff) |
conclusion
Diffstat (limited to '05/musl-0.6.0/src/multibyte/mbsrtowcs.c')
-rw-r--r-- | 05/musl-0.6.0/src/multibyte/mbsrtowcs.c | 121 |
1 files changed, 121 insertions, 0 deletions
diff --git a/05/musl-0.6.0/src/multibyte/mbsrtowcs.c b/05/musl-0.6.0/src/multibyte/mbsrtowcs.c new file mode 100644 index 0000000..64399cf --- /dev/null +++ b/05/musl-0.6.0/src/multibyte/mbsrtowcs.c @@ -0,0 +1,121 @@ +/* + * 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 <stdlib.h> +#include <inttypes.h> +#include <wchar.h> +#include <errno.h> + +#include "internal.h" + +size_t mbsrtowcs(wchar_t *ws, const char **src, size_t wn, mbstate_t *st) +{ + unsigned c; + const unsigned char *s = (const void *)*src; + const wchar_t *wsorig = ws; + + if (!st) st = (void *)&c, c = 0; + else c = *(unsigned *)st; + + if (c) { + *(unsigned *)st = 0; + if (!ws) { + wn = 0; + goto resume0; + } + goto resume; + } + + if (!ws) for (wn=0;;) { + if (*s-SA >= SB-SA) { + while (((uintptr_t)s&3) && *s-1u<0x7f) s++, wn++; + while (!(( *(uint32_t*)s | *(uint32_t*)s-0x01010101) & 0x80808080)) s+=4, wn+=4; + while (*s-1u<0x7f) s++, wn++; + if (!*s) return wn; + if (*s-SA >= SB-SA) goto ilseq2; + } + 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 (*s++-0x80u >= 0x40) goto ilseq2; + c <<= 6; if (!(c&(1U<<31))) break; + if (*s++-0x80u >= 0x40) goto ilseq2; + c <<= 6; if (!(c&(1U<<31))) break; +#endif + if (*s++-0x80u >= 0x40) goto ilseq2; + c <<= 6; if (!(c&(1U<<31))) break; + if (*s++-0x80u >= 0x40) goto ilseq2; + } while (0); + wn++; c = 0; + } + + while (wn) { + if (*s-SA >= SB-SA) { + if (wn >= 7) { + while (((uintptr_t)s&3) && *s-1u<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; + } + } + while (wn && *s-1u<0x7f) { + *ws++ = *s++; + wn--; + } + if (!wn) break; + if (!*s) { + *ws = 0; + *src = 0; + return ws-wsorig; + } + if (*s-SA >= SB-SA) goto ilseq; + } + 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 (*s-0x80u >= 0x40) goto ilseq; + c = (c<<6) | *s++-0x80; + if (!(c&(1U<<31))) break; + + if (*s-0x80u >= 0x40) goto ilseq; + c = (c<<6) | *s++-0x80; + if (!(c&(1U<<31))) break; +#endif + + if (*s-0x80u >= 0x40) goto ilseq; + c = (c<<6) | *s++-0x80; + if (!(c&(1U<<31))) break; + + if (*s-0x80u >= 0x40) goto ilseq; + c = (c<<6) | *s++-0x80; + } while (0); + + *ws++ = c; wn--; c = 0; + } + *src = (const void *)s; + return ws-wsorig; +ilseq: + *src = (const void *)s; +ilseq2: + /* enter permanently failing state */ + *(unsigned *)st = FAILSTATE; + errno = EILSEQ; + return -1; +} |