diff --git a/libc/Android.mk b/libc/Android.mk index 864287a63..0fee71acd 100644 --- a/libc/Android.mk +++ b/libc/Android.mk @@ -336,9 +336,21 @@ libc_upstream_openbsd_src_files := \ upstream-openbsd/lib/libc/gen/time.c \ upstream-openbsd/lib/libc/gen/tolower_.c \ upstream-openbsd/lib/libc/gen/toupper_.c \ + upstream-openbsd/lib/libc/locale/btowc.c \ + upstream-openbsd/lib/libc/locale/mbrlen.c \ + upstream-openbsd/lib/libc/locale/mbstowcs.c \ upstream-openbsd/lib/libc/locale/mbtowc.c \ upstream-openbsd/lib/libc/locale/wcscoll.c \ + upstream-openbsd/lib/libc/locale/wcstod.c \ + upstream-openbsd/lib/libc/locale/wcstof.c \ + upstream-openbsd/lib/libc/locale/wcstol.c \ + upstream-openbsd/lib/libc/locale/wcstold.c \ + upstream-openbsd/lib/libc/locale/wcstoll.c \ + upstream-openbsd/lib/libc/locale/wcstombs.c \ + upstream-openbsd/lib/libc/locale/wcstoul.c \ + upstream-openbsd/lib/libc/locale/wcstoull.c \ upstream-openbsd/lib/libc/locale/wcsxfrm.c \ + upstream-openbsd/lib/libc/locale/wctob.c \ upstream-openbsd/lib/libc/stdio/asprintf.c \ upstream-openbsd/lib/libc/stdio/clrerr.c \ upstream-openbsd/lib/libc/stdio/fdopen.c \ diff --git a/libc/bionic/wchar.cpp b/libc/bionic/wchar.cpp index 674dc3a4e..4e62f6197 100644 --- a/libc/bionic/wchar.cpp +++ b/libc/bionic/wchar.cpp @@ -29,16 +29,13 @@ #include #include #include +#include #include #include #include /* stubs for wide-char functions */ -wint_t btowc(int c) { - return (c == EOF) ? WEOF : c; -} - int fwprintf(FILE* stream, const wchar_t* format, ...) { va_list args; va_start(args, format); @@ -158,10 +155,6 @@ int mbsinit(const mbstate_t* /*ps*/) { return 1; } -size_t mbrlen(const char* s, size_t n, mbstate_t* /*ps*/) { - return (n == 0 || s[0] == 0) ? 0 : 1; -} - size_t mbrtowc(wchar_t* pwc, const char* s, size_t n, mbstate_t* /*ps*/) { if (s == NULL) { return 0; @@ -175,24 +168,44 @@ size_t mbrtowc(wchar_t* pwc, const char* s, size_t n, mbstate_t* /*ps*/) { return (*s != 0); } -size_t mbsrtowcs(wchar_t* dst, const char** src, size_t len, mbstate_t* /*ps*/) { - const char* s = *src; - const char* s2 = reinterpret_cast(memchr(s, 0, len)); - - if (s2 != NULL) { - len = (size_t)(s2 - s) + 1U; +size_t mbsnrtowcs(wchar_t* dst, const char** src, size_t n, size_t dst_size, mbstate_t* /*ps*/) { + size_t i = 0; // Number of input bytes read. + size_t o = 0; // Number of output characters written. + for (; i < n && (*src)[i] != 0; ++i) { + // TODO: UTF-8 support. + if ((*src)[i] > 0x7f) { + errno = EILSEQ; + if (dst != NULL) { + *src = &(*src)[i]; + } + return static_cast(-1); + } + if (dst != NULL) { + if (o + 1 > dst_size) { + break; + } + dst[o++] = static_cast((*src)[i]); + } else { + ++o; + } } - - if (dst) { - memcpy(reinterpret_cast(dst), s, len ); + // If we consumed all the input, terminate the output. + if (dst != NULL && o < dst_size) { + dst[o] = 0; } - - *src = s + len; - return len; + // If we were actually consuming input, record how far we got. + if (dst != NULL) { + if ((*src)[i] != 0) { + *src = &(*src)[i]; // This is where the next call should pick up. + } else { + *src = NULL; // We consumed everything. + } + } + return o; } -size_t mbstowcs(wchar_t* dst, const char* src, size_t len) { - return mbsrtowcs(dst, &src, len, NULL); +size_t mbsrtowcs(wchar_t* dst, const char** src, size_t dst_size, mbstate_t* ps) { + return mbsnrtowcs(dst, src, SIZE_MAX, dst_size, ps); } wint_t putwc(wchar_t wc, FILE* stream) { @@ -239,10 +252,10 @@ size_t wcsftime(wchar_t* wcs, size_t maxsize, const wchar_t* format, const stru return strftime(reinterpret_cast(wcs), maxsize, reinterpret_cast(format), timptr); } -size_t wcsrtombs(char* dst, const wchar_t** src, size_t n, mbstate_t* /*ps*/) { +size_t wcsnrtombs(char* dst, const wchar_t** src, size_t n, size_t dst_size, mbstate_t* /*ps*/) { size_t i = 0; // Number of input characters read. size_t o = 0; // Number of output bytes written. - for (; (*src)[i] != 0; ++i) { + for (; i < n && (*src)[i] != 0; ++i) { // TODO: UTF-8 support. if ((*src)[i] > 0x7f) { errno = EILSEQ; @@ -252,7 +265,7 @@ size_t wcsrtombs(char* dst, const wchar_t** src, size_t n, mbstate_t* /*ps*/) { return static_cast(-1); } if (dst != NULL) { - if (o + 1 > n) { + if (o + 1 > dst_size) { break; } dst[o++] = static_cast((*src)[i]); @@ -261,7 +274,7 @@ size_t wcsrtombs(char* dst, const wchar_t** src, size_t n, mbstate_t* /*ps*/) { } } // If we consumed all the input, terminate the output. - if (dst != NULL && o < n) { + if (dst != NULL && o < dst_size) { dst[o] = 0; } // If we were actually consuming input, record how far we got. @@ -275,25 +288,8 @@ size_t wcsrtombs(char* dst, const wchar_t** src, size_t n, mbstate_t* /*ps*/) { return o; } -size_t wcstombs(char* dst, const wchar_t* src, size_t len) { - const wchar_t* p = src; - return wcsrtombs(dst, &p, len, NULL); -} - -double wcstod(const wchar_t* nptr, wchar_t** endptr) { - return strtod(reinterpret_cast(nptr), reinterpret_cast(endptr)); -} - -long int wcstol(const wchar_t* nptr, wchar_t** endptr, int base) { - return strtol(reinterpret_cast(nptr), reinterpret_cast(endptr), base); -} - -unsigned long int wcstoul(const wchar_t* nptr, wchar_t** endptr, int base) { - return strtoul(reinterpret_cast(nptr), reinterpret_cast(endptr), base); -} - -int wctob(wint_t c) { - return c; +size_t wcsrtombs(char* dst, const wchar_t** src, size_t dst_size, mbstate_t* ps) { + return wcsnrtombs(dst, src, SIZE_MAX, dst_size, ps); } wctype_t wctype(const char* property) { diff --git a/libc/include/wchar.h b/libc/include/wchar.h index 0029a65be..12715c279 100644 --- a/libc/include/wchar.h +++ b/libc/include/wchar.h @@ -87,7 +87,8 @@ extern wint_t getwchar(void); extern int mbsinit(const mbstate_t *); extern size_t mbrlen(const char *, size_t, mbstate_t *); extern size_t mbrtowc(wchar_t *, const char *, size_t, mbstate_t *); -extern size_t mbsrtowcs(wchar_t *, const char **, size_t, mbstate_t *); +extern size_t mbsrtowcs(wchar_t*, const char**, size_t, mbstate_t*); +extern size_t mbsnrtowcs(wchar_t*, const char**, size_t, size_t, mbstate_t*); extern size_t mbstowcs(wchar_t *, const char *, size_t); extern wint_t putwc(wchar_t, FILE *); extern wint_t putwchar(wchar_t); @@ -113,16 +114,20 @@ extern int wcsncasecmp(const wchar_t *, const wchar_t *, size_t); extern wchar_t *wcsncat(wchar_t *, const wchar_t *, size_t); extern int wcsncmp(const wchar_t *, const wchar_t *, size_t); extern wchar_t *wcsncpy(wchar_t *, const wchar_t *, size_t); +extern size_t wcsnrtombs(char*, const wchar_t**, size_t, size_t, mbstate_t*); extern wchar_t *wcspbrk(const wchar_t *, const wchar_t *); extern wchar_t *wcsrchr(const wchar_t *, wchar_t); -extern size_t wcsrtombs(char *, const wchar_t **, size_t, mbstate_t *); +extern size_t wcsrtombs(char*, const wchar_t**, size_t, mbstate_t*); extern size_t wcsspn(const wchar_t *, const wchar_t *); extern wchar_t *wcsstr(const wchar_t *, const wchar_t *); -extern double wcstod(const wchar_t *, wchar_t **); -extern wchar_t *wcstok(wchar_t *, const wchar_t *, wchar_t **); -extern long int wcstol(const wchar_t *, wchar_t **, int); -extern size_t wcstombs(char *, const wchar_t *, size_t); -extern unsigned long int wcstoul(const wchar_t *, wchar_t **, int); +extern double wcstod(const wchar_t*, wchar_t**); +extern float wcstof(const wchar_t*, wchar_t**); +extern wchar_t* wcstok(wchar_t*, const wchar_t*, wchar_t**); +extern long wcstol(const wchar_t*, wchar_t**, int); +extern long long wcstoll(const wchar_t*, wchar_t**, int); +extern long double wcstold(const wchar_t*, wchar_t**); +extern unsigned long wcstoul(const wchar_t*, wchar_t**, int); +extern unsigned long long wcstoull(const wchar_t*, wchar_t**, int); extern wchar_t *wcswcs(const wchar_t *, const wchar_t *); extern int wcswidth(const wchar_t *, size_t); extern size_t wcsxfrm(wchar_t *, const wchar_t *, size_t); diff --git a/libc/upstream-openbsd/lib/libc/locale/_wcstod.h b/libc/upstream-openbsd/lib/libc/locale/_wcstod.h new file mode 100644 index 000000000..ae993ad67 --- /dev/null +++ b/libc/upstream-openbsd/lib/libc/locale/_wcstod.h @@ -0,0 +1,153 @@ +/* $OpenBSD: _wcstod.h,v 1.2 2013/06/02 15:22:20 matthew Exp $ */ +/* $NetBSD: wcstod.c,v 1.4 2001/10/28 12:08:43 yamt Exp $ */ + +/*- + * Copyright (c)1999, 2000, 2001 Citrus Project, + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Citrus: xpg4dl/FreeBSD/lib/libc/locale/wcstod.c,v 1.2 2001/09/27 16:23:57 yamt Exp $ + */ + +/* + * function template for wcstof, wcstod and wcstold. + * + * parameters: + * FUNCNAME : function name + * float_type : return type + * STRTOD_FUNC : conversion function + */ + +float_type +FUNCNAME(const wchar_t *nptr, wchar_t **endptr) +{ + const wchar_t *src; + size_t size; + const wchar_t *start; + const wchar_t *aftersign; + + /* + * check length of string and call strtod + */ + src = nptr; + + /* skip space first */ + while (iswspace(*src)) { + src++; + } + + /* get length of string */ + start = src; + if (*src && wcschr(L"+-", *src)) + src++; + aftersign = src; + if (wcsncasecmp(src, L"inf", 3) == 0) { + src += 3; + if (wcsncasecmp(src, L"inity", 5) == 0) + src += 5; + goto match; + } + if (wcsncasecmp(src, L"nan", 3) == 0) { + src += 3; + if (*src == L'(') { + size = 1; + while (src[size] != L'\0' && src[size] != L')') + size++; + if (src[size] == L')') + src += size + 1; + } + goto match; + } + size = wcsspn(src, L"0123456789"); + src += size; + if (*src == L'.') {/* XXX use localeconv */ + src++; + size = wcsspn(src, L"0123456789"); + src += size; + } + if (*src && wcschr(L"Ee", *src)) { + src++; + if (*src && wcschr(L"+-", *src)) + src++; + size = wcsspn(src, L"0123456789"); + src += size; + } +match: + size = src - start; + + /* + * convert to a char-string and pass it to strtod. + */ + if (src > aftersign) { + mbstate_t st; + char *buf; + char *end; + const wchar_t *s; + size_t size_converted; + float_type result; + size_t bufsize; + + s = start; + memset(&st, 0, sizeof(st)); + bufsize = wcsnrtombs(NULL, &s, size, 0, &st); + + buf = malloc(bufsize + 1); + if (!buf) { + errno = ENOMEM; /* XXX */ + goto fail; + } + + s = start; + memset(&st, 0, sizeof(st)); + size_converted = wcsnrtombs(buf, &s, size, bufsize, &st); + if (size_converted != bufsize) { + /* XXX should not happen */ + free(buf); + errno = EILSEQ; + goto fail; + } + + buf[bufsize] = 0; + result = STRTOD_FUNC(buf, &end); + + if (endptr) { + const char *s = buf; + memset(&st, 0, sizeof(st)); + size = mbsnrtowcs(NULL, &s, end - buf, 0, &st); + + /* LINTED bad interface */ + *endptr = (wchar_t*)start + size; + } + + free(buf); + + return result; + } + +fail: + if (endptr) + /* LINTED bad interface */ + *endptr = (wchar_t*)nptr; + + return 0; +} diff --git a/libc/upstream-openbsd/lib/libc/locale/_wcstol.h b/libc/upstream-openbsd/lib/libc/locale/_wcstol.h new file mode 100644 index 000000000..7b49bbff2 --- /dev/null +++ b/libc/upstream-openbsd/lib/libc/locale/_wcstol.h @@ -0,0 +1,136 @@ +/* $OpenBSD: _wcstol.h,v 1.1 2005/07/01 08:59:27 espie Exp $ */ +/* $NetBSD: _wcstol.h,v 1.2 2003/08/07 16:43:03 agc Exp $ */ + +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Original version ID: + * @(#)strtol.c 8.1 (Berkeley) 6/4/93 + * NetBSD: wcstol.c,v 1.1 2001/09/27 16:30:36 yamt Exp + * Citrus: xpg4dl/FreeBSD/lib/libc/locale/wcstol.c,v 1.2 2001/09/21 16:11:41 yamt Exp + */ + +/* + * function template for wcstol, wcstoll and wcstoimax. + * + * parameters: + * FUNCNAME : function name + * int_type : return type + * MIN_VALUE : lower limit of the return type + * MAX_VALUE : upper limit of the return type + */ + +int_type +FUNCNAME(const wchar_t *nptr, wchar_t **endptr, int base) +{ + const wchar_t *s; + int_type acc, cutoff; + wint_t wc; + int i; + int neg, any, cutlim; + + /* check base value */ + if (base && (base < 2 || base > 36)) { + errno = EINVAL; + return 0; + } + + /* + * Skip white space and pick up leading +/- sign if any. + * If base is 0, allow 0x for hex and 0 for octal, else + * assume decimal; if base is already 16, allow 0x. + */ + s = nptr; + do { + wc = (wchar_t) *s++; + } while (iswspace(wc)); + if (wc == L'-') { + neg = 1; + wc = *s++; + } else { + neg = 0; + if (wc == L'+') + wc = *s++; + } + if ((base == 0 || base == 16) && + wc == L'0' && (*s == L'x' || *s == L'X')) { + wc = s[1]; + s += 2; + base = 16; + } + if (base == 0) + base = wc == L'0' ? 8 : 10; + + /* + * See strtol for comments as to the logic used. + */ + cutoff = neg ? MIN_VALUE : MAX_VALUE; + cutlim = (int)(cutoff % base); + cutoff /= base; + if (neg) { + if (cutlim > 0) { + cutlim -= base; + cutoff += 1; + } + cutlim = -cutlim; + } + for (acc = 0, any = 0;; wc = (wchar_t) *s++) { + i = wctoint(wc); + if (i == -1) + break; + if (i >= base) + break; + if (any < 0) + continue; + if (neg) { + if (acc < cutoff || (acc == cutoff && i > cutlim)) { + any = -1; + acc = MIN_VALUE; + errno = ERANGE; + } else { + any = 1; + acc *= base; + acc -= i; + } + } else { + if (acc > cutoff || (acc == cutoff && i > cutlim)) { + any = -1; + acc = MAX_VALUE; + errno = ERANGE; + } else { + any = 1; + acc *= base; + acc += i; + } + } + } + if (endptr != 0) + /* LINTED interface specification */ + *endptr = (wchar_t *)(any ? s - 1 : nptr); + return (acc); +} diff --git a/libc/upstream-openbsd/lib/libc/locale/_wcstoul.h b/libc/upstream-openbsd/lib/libc/locale/_wcstoul.h new file mode 100644 index 000000000..736b38fbe --- /dev/null +++ b/libc/upstream-openbsd/lib/libc/locale/_wcstoul.h @@ -0,0 +1,116 @@ +/* $OpenBSD: _wcstoul.h,v 1.1 2005/07/01 08:59:27 espie Exp $ */ +/* $NetBSD: _wcstoul.h,v 1.2 2003/08/07 16:43:03 agc Exp $ */ + +/* + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Original version ID: + * @(#)strtoul.c 8.1 (Berkeley) 6/4/93 + * Citrus: xpg4dl/FreeBSD/lib/libc/locale/wcstoul.c,v 1.2 2001/09/21 16:11:41 yamt Exp + * NetBSD: wcstoul.c,v 1.1 2001/09/27 16:30:37 yamt Exp + */ + +/* + * function template for wcstoul, wcstoull and wcstoumax. + * + * parameters: + * FUNCNAME : function name + * uint_type : return type + * MAX_VALUE : upper limit of the return type + */ + +uint_type +FUNCNAME(const wchar_t *nptr, wchar_t **endptr, int base) +{ + const wchar_t *s; + uint_type acc, cutoff; + wint_t wc; + int i; + int neg, any, cutlim; + + if (base && (base < 2 || base > 36)) { + errno = EINVAL; + return 0; + } + + /* + * Skip white space and pick up leading +/- sign if any. + * If base is 0, allow 0x for hex and 0 for octal, else + * assume decimal; if base is already 16, allow 0x. + */ + s = nptr; + do { + wc = (wchar_t) *s++; + } while (iswspace(wc)); + if (wc == L'-') { + neg = 1; + wc = *s++; + } else { + neg = 0; + if (wc == L'+') + wc = *s++; + } + if ((base == 0 || base == 16) && + wc == L'0' && (*s == L'x' || *s == L'X')) { + wc = s[1]; + s += 2; + base = 16; + } + if (base == 0) + base = wc == L'0' ? 8 : 10; + + /* + * See strtoul for comments as to the logic used. + */ + cutoff = MAX_VALUE / (uint_type)base; + cutlim = (int)(MAX_VALUE % (uint_type)base); + for (acc = 0, any = 0;; wc = (wchar_t) *s++) { + i = wctoint(wc); + if (i == (wint_t)-1) + break; + if (i >= base) + break; + if (any < 0) + continue; + if (acc > cutoff || (acc == cutoff && i > cutlim)) { + any = -1; + acc = MAX_VALUE; + errno = ERANGE; + } else { + any = 1; + acc *= (uint_type)base; + acc += i; + } + } + if (neg && any > 0) + acc = -acc; + if (endptr != 0) + /* LINTED interface specification */ + *endptr = (wchar_t *)(any ? s - 1 : nptr); + return (acc); +} diff --git a/libc/upstream-openbsd/lib/libc/locale/btowc.c b/libc/upstream-openbsd/lib/libc/locale/btowc.c new file mode 100644 index 000000000..96273401e --- /dev/null +++ b/libc/upstream-openbsd/lib/libc/locale/btowc.c @@ -0,0 +1,52 @@ +/* $OpenBSD: btowc.c,v 1.2 2012/12/05 23:20:00 deraadt Exp $ */ + +/*- + * Copyright (c) 2002, 2003 Tim J. Robbins. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include + +wint_t +btowc(int c) +{ + mbstate_t mbs; + char cc; + wchar_t wc; + + if (c == EOF) + return (WEOF); + /* + * We expect mbrtowc() to return 0 or 1, hence the check for n > 1 + * which detects error return values as well as "impossible" byte + * counts. + */ + memset(&mbs, 0, sizeof(mbs)); + cc = (char)c; + if (mbrtowc(&wc, &cc, 1, &mbs) > 1) + return (WEOF); + return (wc); +} diff --git a/libc/upstream-openbsd/lib/libc/locale/mbrlen.c b/libc/upstream-openbsd/lib/libc/locale/mbrlen.c new file mode 100644 index 000000000..0f05bd072 --- /dev/null +++ b/libc/upstream-openbsd/lib/libc/locale/mbrlen.c @@ -0,0 +1,39 @@ +/* $OpenBSD: mbrlen.c,v 1.2 2012/12/05 23:20:00 deraadt Exp $ */ + +/*- + * Copyright (c) 2002-2004 Tim J. Robbins. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +size_t +mbrlen(const char * __restrict s, size_t n, mbstate_t * __restrict ps) +{ + static mbstate_t mbs; + + if (ps == NULL) + ps = &mbs; + return (mbrtowc(NULL, s, n, ps)); +} diff --git a/libc/upstream-openbsd/lib/libc/locale/mbstowcs.c b/libc/upstream-openbsd/lib/libc/locale/mbstowcs.c new file mode 100644 index 000000000..c17a85827 --- /dev/null +++ b/libc/upstream-openbsd/lib/libc/locale/mbstowcs.c @@ -0,0 +1,44 @@ +/* $OpenBSD: mbstowcs.c,v 1.2 2012/12/05 23:20:00 deraadt Exp $ */ + +/*- + * Copyright (c) 2002-2004 Tim J. Robbins. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#include +#include +#include +#include + +size_t +mbstowcs(wchar_t * __restrict pwcs, const char * __restrict s, size_t n) +{ + mbstate_t mbs; + const char *sp; + + memset(&mbs, 0, sizeof(mbs)); + sp = s; + return (mbsrtowcs(pwcs, &sp, n, &mbs)); +} diff --git a/libc/upstream-openbsd/lib/libc/locale/wcstod.c b/libc/upstream-openbsd/lib/libc/locale/wcstod.c new file mode 100644 index 000000000..957d0a149 --- /dev/null +++ b/libc/upstream-openbsd/lib/libc/locale/wcstod.c @@ -0,0 +1,13 @@ +/* $OpenBSD: wcstod.c,v 1.3 2009/01/13 18:18:31 kettenis Exp $ */ + +#include +#include +#include +#include +#include + +#define FUNCNAME wcstod +typedef double float_type; +#define STRTOD_FUNC strtod + +#include "_wcstod.h" diff --git a/libc/upstream-openbsd/lib/libc/locale/wcstof.c b/libc/upstream-openbsd/lib/libc/locale/wcstof.c new file mode 100644 index 000000000..40d76c791 --- /dev/null +++ b/libc/upstream-openbsd/lib/libc/locale/wcstof.c @@ -0,0 +1,13 @@ +/* $OpenBSD: wcstof.c,v 1.1 2009/01/13 18:18:31 kettenis Exp $ */ + +#include +#include +#include +#include +#include + +#define FUNCNAME wcstof +typedef float float_type; +#define STRTOD_FUNC strtof + +#include "_wcstod.h" diff --git a/libc/upstream-openbsd/lib/libc/locale/wcstol.c b/libc/upstream-openbsd/lib/libc/locale/wcstol.c new file mode 100644 index 000000000..03395a0fe --- /dev/null +++ b/libc/upstream-openbsd/lib/libc/locale/wcstol.c @@ -0,0 +1,18 @@ +/* $OpenBSD: wcstol.c,v 1.2 2005/08/08 08:05:35 espie Exp $ */ +/* $NetBSD: wcstol.c,v 1.2 2003/03/11 09:21:23 tshiozak Exp $ */ + +#include +#include +#include +#include +#include +#include + +#include "wctoint.h" + +#define FUNCNAME wcstol +typedef long int_type; +#define MIN_VALUE LONG_MIN +#define MAX_VALUE LONG_MAX + +#include "_wcstol.h" diff --git a/libc/upstream-openbsd/lib/libc/locale/wcstold.c b/libc/upstream-openbsd/lib/libc/locale/wcstold.c new file mode 100644 index 000000000..a6425422e --- /dev/null +++ b/libc/upstream-openbsd/lib/libc/locale/wcstold.c @@ -0,0 +1,13 @@ +/* $OpenBSD: wcstold.c,v 1.1 2009/01/13 18:18:31 kettenis Exp $ */ + +#include +#include +#include +#include +#include + +#define FUNCNAME wcstold +typedef long double float_type; +#define STRTOD_FUNC strtold + +#include "_wcstod.h" diff --git a/libc/upstream-openbsd/lib/libc/locale/wcstoll.c b/libc/upstream-openbsd/lib/libc/locale/wcstoll.c new file mode 100644 index 000000000..926db70f6 --- /dev/null +++ b/libc/upstream-openbsd/lib/libc/locale/wcstoll.c @@ -0,0 +1,18 @@ +/* $OpenBSD: wcstoll.c,v 1.2 2005/08/08 08:05:35 espie Exp $ */ +/* $NetBSD: wcstoll.c,v 1.1 2003/03/11 09:21:23 tshiozak Exp $ */ + +#include +#include +#include +#include +#include +#include + +#include "wctoint.h" + +#define FUNCNAME wcstoll +typedef long long int int_type; +#define MIN_VALUE LLONG_MIN +#define MAX_VALUE LLONG_MAX + +#include "_wcstol.h" diff --git a/libc/upstream-openbsd/lib/libc/locale/wcstombs.c b/libc/upstream-openbsd/lib/libc/locale/wcstombs.c new file mode 100644 index 000000000..e8054c401 --- /dev/null +++ b/libc/upstream-openbsd/lib/libc/locale/wcstombs.c @@ -0,0 +1,43 @@ +/* $OpenBSD: wcstombs.c,v 1.2 2012/12/05 23:20:00 deraadt Exp $ */ + +/*- + * Copyright (c) 2002-2004 Tim J. Robbins. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include +#include + +size_t +wcstombs(char * __restrict s, const wchar_t * __restrict pwcs, size_t n) +{ + mbstate_t mbs; + const wchar_t *pwcsp; + + memset(&mbs, 0, sizeof(mbs)); + pwcsp = pwcs; + return (wcsrtombs(s, &pwcsp, n, &mbs)); +} diff --git a/libc/upstream-openbsd/lib/libc/locale/wcstoul.c b/libc/upstream-openbsd/lib/libc/locale/wcstoul.c new file mode 100644 index 000000000..e863862d3 --- /dev/null +++ b/libc/upstream-openbsd/lib/libc/locale/wcstoul.c @@ -0,0 +1,17 @@ +/* $OpenBSD: wcstoul.c,v 1.2 2005/08/08 08:05:35 espie Exp $ */ +/* $NetBSD: wcstoul.c,v 1.2 2003/03/11 09:21:24 tshiozak Exp $ */ + +#include +#include +#include +#include +#include +#include + +#include "wctoint.h" + +#define FUNCNAME wcstoul +typedef unsigned long uint_type; +#define MAX_VALUE ULONG_MAX + +#include "_wcstoul.h" diff --git a/libc/upstream-openbsd/lib/libc/locale/wcstoull.c b/libc/upstream-openbsd/lib/libc/locale/wcstoull.c new file mode 100644 index 000000000..6671c3759 --- /dev/null +++ b/libc/upstream-openbsd/lib/libc/locale/wcstoull.c @@ -0,0 +1,17 @@ +/* $OpenBSD: wcstoull.c,v 1.2 2005/08/08 08:05:35 espie Exp $ */ +/* $NetBSD: wcstoull.c,v 1.1 2003/03/11 09:21:24 tshiozak Exp $ */ + +#include +#include +#include +#include +#include +#include + +#include "wctoint.h" + +#define FUNCNAME wcstoull +typedef unsigned long long int uint_type; +#define MAX_VALUE ULLONG_MAX + +#include "_wcstoul.h" diff --git a/libc/upstream-openbsd/lib/libc/locale/wctob.c b/libc/upstream-openbsd/lib/libc/locale/wctob.c new file mode 100644 index 000000000..ea1f40c58 --- /dev/null +++ b/libc/upstream-openbsd/lib/libc/locale/wctob.c @@ -0,0 +1,43 @@ +/* $OpenBSD: wctob.c,v 1.2 2012/12/05 23:20:00 deraadt Exp $ */ +/*- + * Copyright (c) 2002-2004 Tim J. Robbins. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include +#include + +int +wctob(wint_t c) +{ + mbstate_t mbs; + char buf[MB_LEN_MAX]; + + memset(&mbs, 0, sizeof(mbs)); + if (c == WEOF || wcrtomb(buf, c, &mbs) != 1) + return (EOF); + return ((unsigned char)*buf); +} diff --git a/libc/upstream-openbsd/lib/libc/locale/wctoint.h b/libc/upstream-openbsd/lib/libc/locale/wctoint.h new file mode 100644 index 000000000..c9bf084c3 --- /dev/null +++ b/libc/upstream-openbsd/lib/libc/locale/wctoint.h @@ -0,0 +1,79 @@ +/* $OpenBSD: wctoint.h,v 1.1 2005/07/01 08:59:27 espie Exp $ */ +/* $NetBSD: __wctoint.h,v 1.1 2001/09/28 11:25:37 yamt Exp $ */ + +/*- + * Copyright (c)2001 Citrus Project, + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Citrus: xpg4dl/FreeBSD/lib/libc/locale/__wctoint.h,v 1.1 2001/09/21 13:52:32 yamt Exp $ + */ + + +__inline static int +wctoint(wchar_t wc) +{ + int n; + + switch (wc) { + case L'0': n = 0; break; + case L'1': n = 1; break; + case L'2': n = 2; break; + case L'3': n = 3; break; + case L'4': n = 4; break; + case L'5': n = 5; break; + case L'6': n = 6; break; + case L'7': n = 7; break; + case L'8': n = 8; break; + case L'9': n = 9; break; + case L'A': case L'a': n = 10; break; + case L'B': case L'b': n = 11; break; + case L'C': case L'c': n = 12; break; + case L'D': case L'd': n = 13; break; + case L'E': case L'e': n = 14; break; + case L'F': case L'f': n = 15; break; + case L'G': case L'g': n = 16; break; + case L'H': case L'h': n = 17; break; + case L'I': case L'i': n = 18; break; + case L'J': case L'j': n = 19; break; + case L'K': case L'k': n = 20; break; + case L'L': case L'l': n = 21; break; + case L'M': case L'm': n = 22; break; + case L'N': case L'n': n = 23; break; + case L'O': case L'o': n = 24; break; + case L'P': case L'p': n = 25; break; + case L'Q': case L'q': n = 26; break; + case L'R': case L'r': n = 27; break; + case L'S': case L's': n = 28; break; + case L'T': case L't': n = 29; break; + case L'U': case L'u': n = 30; break; + case L'V': case L'v': n = 31; break; + case L'W': case L'w': n = 32; break; + case L'X': case L'x': n = 33; break; + case L'Y': case L'y': n = 34; break; + case L'Z': case L'z': n = 35; break; + default: n = -1; break; /* error */ + } + + return n; +} diff --git a/tests/Android.mk b/tests/Android.mk index d85e8eb5b..94474ff74 100644 --- a/tests/Android.mk +++ b/tests/Android.mk @@ -38,6 +38,8 @@ test_cflags = \ -Werror \ -fno-builtin \ +test_cflags += -D__STDC_LIMIT_MACROS # For glibc. + libBionicStandardTests_src_files := \ buffer_tests.cpp \ ctype_test.cpp \ diff --git a/tests/unistd_test.cpp b/tests/unistd_test.cpp index f56b767dc..ce0bebadd 100644 --- a/tests/unistd_test.cpp +++ b/tests/unistd_test.cpp @@ -18,8 +18,6 @@ #include "ScopedSignalHandler.h" #include "TemporaryFile.h" -#define __STDC_LIMIT_MACROS // For glibc. - #include #include #include diff --git a/tests/wchar_test.cpp b/tests/wchar_test.cpp index 3c38f1ffc..f6c26837c 100644 --- a/tests/wchar_test.cpp +++ b/tests/wchar_test.cpp @@ -18,6 +18,7 @@ #include #include +#include #include TEST(wchar, sizeof_wchar_t) { @@ -212,3 +213,56 @@ TEST(wchar, mbrtowc) { ASSERT_EQ(0U, mbrtowc(NULL, NULL, 0, NULL)); } + +TEST(wchar, wcstod) { + ASSERT_DOUBLE_EQ(1.23, wcstod(L"1.23", NULL)); +} + +TEST(wchar, wcstof) { + ASSERT_FLOAT_EQ(1.23f, wcstof(L"1.23", NULL)); +} + +TEST(wchar, wcstol) { + ASSERT_EQ(123L, wcstol(L"123", NULL, 0)); +} + +TEST(wchar, wcstoll) { + ASSERT_EQ(123LL, wcstol(L"123", NULL, 0)); +} + +TEST(wchar, wcstold) { + ASSERT_DOUBLE_EQ(1.23L, wcstold(L"1.23", NULL)); +} + +TEST(wchar, wcstoul) { + ASSERT_EQ(123UL, wcstoul(L"123", NULL, 0)); +} + +TEST(wchar, wcstoull) { + ASSERT_EQ(123ULL, wcstoul(L"123", NULL, 0)); +} + +TEST(wchar, mbsnrtowcs) { + wchar_t dst[128]; + const char* s = "hello, world!"; + const char* src; + + memset(dst, 0, sizeof(dst)); + src = s; + ASSERT_EQ(0U, mbsnrtowcs(dst, &src, 0, 0, NULL)); + + memset(dst, 0, sizeof(dst)); + src = s; + ASSERT_EQ(2U, mbsnrtowcs(dst, &src, 2, 123, NULL)); // glibc chokes on SIZE_MAX here. + ASSERT_EQ(L'h', dst[0]); + ASSERT_EQ(L'e', dst[1]); + ASSERT_EQ(&s[2], src); + + memset(dst, 0, sizeof(dst)); + src = s; + ASSERT_EQ(3U, mbsnrtowcs(dst, &src, SIZE_MAX, 3, NULL)); + ASSERT_EQ(L'h', dst[0]); + ASSERT_EQ(L'e', dst[1]); + ASSERT_EQ(L'l', dst[2]); + ASSERT_EQ(&s[3], src); +}