Index: fusl/src/multibyte/mbsrtowcs.c |
diff --git a/fusl/src/multibyte/mbsrtowcs.c b/fusl/src/multibyte/mbsrtowcs.c |
new file mode 100644 |
index 0000000000000000000000000000000000000000..e23083d223fc4c5528d46730b7c12a936888ef64 |
--- /dev/null |
+++ b/fusl/src/multibyte/mbsrtowcs.c |
@@ -0,0 +1,120 @@ |
+/* |
+ * 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 <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 (;;) { |
+ 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; |
+} |