scc

simple c99 compiler
git clone git://git.simple-cc.org/scc
Log | Files | Refs | Submodules | README | LICENSE

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:
Msrc/libc/wchar/mbsrtowcs.c | 26+++++++++++++++++++++-----
Mtests/libc/execute/.gitignore | 1+
Atests/libc/execute/0042-mbsrtowcs.c | 126+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mtests/libc/execute/libc-tests.lst | 1+
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