diff options
Diffstat (limited to 'libc-top-half/musl/src/multibyte/mbsrtowcs.c')
-rw-r--r-- | libc-top-half/musl/src/multibyte/mbsrtowcs.c | 120 |
1 files changed, 120 insertions, 0 deletions
diff --git a/libc-top-half/musl/src/multibyte/mbsrtowcs.c b/libc-top-half/musl/src/multibyte/mbsrtowcs.c new file mode 100644 index 0000000..9b2f2df --- /dev/null +++ b/libc-top-half/musl/src/multibyte/mbsrtowcs.c @@ -0,0 +1,120 @@ +#include <stdint.h> +#include <wchar.h> +#include <errno.h> +#include <string.h> +#include <stdlib.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 (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--; + } + *ws = 0; + *src = 0; + return wn0-wn; + } + + if (!ws) for (;;) { +#ifdef __GNUC__ + typedef uint32_t __attribute__((__may_alias__)) w32; + if (*s-1u < 0x7f && (uintptr_t)s%4 == 0) { + while (!(( *(w32*)s | *(w32*)s-0x01010101) & 0x80808080)) { + s += 4; + wn -= 4; + } + } +#endif + 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; + } +#ifdef __GNUC__ + typedef uint32_t __attribute__((__may_alias__)) w32; + if (*s-1u < 0x7f && (uintptr_t)s%4 == 0) { + while (wn>=5 && !(( *(w32*)s | *(w32*)s-0x01010101) & 0x80808080)) { + *ws++ = *s++; + *ws++ = *s++; + *ws++ = *s++; + *ws++ = *s++; + wn -= 4; + } + } +#endif + 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; +} |