commit 36606c7df70f2465a4305395c529e7ea1add693f
parent 01921365fc084e3b592c00bdd090d0d457502904
Author: Roberto E. Vargas Caballero <k0ga@shike2.net>
Date: Fri, 21 Mar 2025 19:23:17 +0100
tests/libc: Add 0042-mbsrtowc
Diffstat:
4 files changed, 149 insertions(+), 5 deletions(-)
diff --git a/src/libc/wchar/mbsrtowcs.c b/src/libc/wchar/mbsrtowcs.c
@@ -1,4 +1,5 @@
#include <limits.h>
+#include <string.h>
#include <wchar.h>
#undef mbsrtowcs
@@ -8,24 +9,39 @@ mbsrtowcs(wchar_t *restrict dest, const char **restrict src, size_t len,
mbstate_t *restrict ps)
{
wchar_t wc;
+ const char *s = *src;
size_t cnt, n;
+ static mbstate_t st;
+
+ if (!ps)
+ ps = &st;
for (n = 0; ; n++) {
- cnt = mbrtowc(&wc, *src, MB_LEN_MAX, ps);
+ cnt = mbrtowc(&wc, s, MB_LEN_MAX, ps);
+ if (cnt == (size_t) -2) {
+ s += MB_LEN_MAX;
+ continue;
+ }
if (cnt == (size_t) -1)
return -1;
if (dest) {
- if (n == len)
+ if (n == len) {
+ *src = s;
return n;
+ }
*dest++ = wc;
}
- *src += cnt;
+ s += cnt;
- if (wc == L'\0')
+ if (wc == 0)
break;
}
- *src = NULL;
+
+ if (dest) {
+ memset(ps, 0, sizeof(mbstate_t));
+ *src = NULL;
+ }
return n;
}
diff --git a/tests/libc/execute/.gitignore b/tests/libc/execute/.gitignore
@@ -39,6 +39,7 @@
0039-mbrtowc
0040-wcrtomb
0041-mbrlen
+0042-mbsrtowcs
0044-wcslen
0045-wcscmp
0046-wcsncmp
diff --git a/tests/libc/execute/0042-mbsrtowcs.c b/tests/libc/execute/0042-mbsrtowcs.c
@@ -0,0 +1,126 @@
+#include <assert.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+
+/*
+output:
+testing
+testing mbsrtowcs1
+testing mbsrtowcs2
+testing mbstowcs
+done
+end:
+*/
+
+#define NELEM(x) (sizeof(x)/sizeof(x[0]))
+
+static char str[20];
+static wchar_t wcs[20];
+static struct mbstests {
+ char *s;
+ char *sexp;
+
+ wchar_t *wcs;
+ wchar_t *wcsexp;
+
+ size_t n;
+ int r;
+ int syserr;
+ int mbstate;
+} tests[] = {
+ /* s sexp wcs wcsexp n r syserr mbstate */
+ {"\0", NULL, wcs, (wchar_t[]) {0}, 1, 0, 0, 1},
+ {"\0", str, wcs, (wchar_t[]) {0}, 0, 0, 0, 1},
+ {"\0", str, NULL, (wchar_t[]) {0}, 1, 0, 0, 1},
+ {"\0", str, NULL, (wchar_t[]) {0}, 0, 0, 0, 1},
+
+ {"\x31", NULL, wcs, (wchar_t[]) {0x31, 0}, 2, 1, 0, 1},
+ {"\x31", str+1, wcs, (wchar_t[]) {0x31, 0}, 1, 1, 0, 1},
+ {"\x31", str, NULL, (wchar_t[]) {0x31, 0}, 1, 1, 0, 1},
+ {"\x31", str, NULL, (wchar_t[]) {0x31, 0}, 0, 1, 0, 1},
+
+ {"\x21\xc2\xa1\xe2\x80\x94\xf0\x9f\x92\xa9",
+ NULL, wcs,
+ (wchar_t[]) {0x21,0xa1,0x2014,0x1f4A9}, 20, 4, 0, 1},
+
+ {"\xf0\x9f",str, wcs, NULL, 20,-1, EILSEQ, 0},
+};
+
+void
+tests_mbsrtowcs(void)
+{
+ int r;
+ const char *s;
+ mbstate_t st;
+ struct mbstests *tp;
+
+ puts("testing mbsrtowcs1");
+ for (tp = tests; tp < &tests[NELEM(tests)]; ++tp) {
+ errno = 0;
+ if (tp->s != NULL)
+ s = strcpy(str, tp->s);
+ memset(wcs, -1, sizeof(wcs));
+
+ r = mbsrtowcs(tp->wcs, &s, tp->n, NULL);
+ assert(tp->r == r);
+ assert(tp->syserr == errno);
+ if (tp->r >= 0) {
+ assert(s == tp->sexp);
+ if (tp->wcs)
+ assert(!wcsncmp(tp->wcsexp, tp->wcs, tp->r));
+ }
+ }
+
+ puts("testing mbsrtowcs2");
+ for (tp = tests; tp < &tests[NELEM(tests)]; ++tp) {
+ errno = 0;
+ if (tp->s != NULL)
+ s = strcpy(str, tp->s);
+ memset(wcs, -1, sizeof(wcs));
+ memset(&st, 0, sizeof(st));
+
+ r = mbsrtowcs(tp->wcs, &s, tp->n, &st);
+ assert(tp->r == r);
+ assert(tp->syserr == errno);
+ if (tp->r >= 0) {
+ assert(s == tp->sexp);
+ if (tp->wcs)
+ assert(!wcsncmp(tp->wcsexp, tp->wcs, tp->r));
+ assert(mbsinit(&st) != 0 == tp->mbstate);
+ }
+ }
+}
+
+void
+tests_mbstowcs(void)
+{
+ int r;
+ struct mbstests *tp;
+
+ puts("testing mbstowcs");
+ for (tp = tests; tp < &tests[NELEM(tests)]; ++tp) {
+ errno = 0;
+ memset(wcs, -1, sizeof(wcs));
+
+ r = mbstowcs(tp->wcs, tp->s, tp->n);
+ assert(tp->r == r);
+ assert(tp->syserr == errno);
+ if (tp->r >= 0) {
+ if (tp->wcs)
+ assert(!wcsncmp(tp->wcsexp, tp->wcs, tp->r));
+ }
+ }
+}
+
+int
+main(void)
+{
+ puts("testing");
+ tests_mbsrtowcs();
+ tests_mbstowcs();
+ puts("done");
+ return 0;
+}
diff --git a/tests/libc/execute/libc-tests.lst b/tests/libc/execute/libc-tests.lst
@@ -38,6 +38,7 @@
0039-mbrtowc
0040-wcrtomb
0041-mbrlen
+0042-mbsrtowcs
0044-wcslen
0045-wcscmp
0046-wcsncmp