Implement the GNU extensions of mbsnrtowcs() and wcsnrtombs(). These are

convenient when the source string isn't null-terminated.

Implement the other conversion functions (mbstowcs(), mbsrtowcs(), wcstombs(),
wcsrtombs()) in terms of these new functions.
This commit is contained in:
Tim J. Robbins 2004-07-21 10:54:57 +00:00
parent 5c0b01b427
commit 1949a3470f
15 changed files with 321 additions and 165 deletions

View File

@ -209,6 +209,10 @@ int wcwidth(wchar_t);
#if __BSD_VISIBLE
wchar_t *fgetwln(struct __sFILE * __restrict, size_t * __restrict);
size_t mbsnrtowcs(wchar_t * __restrict, const char ** __restrict, size_t,
size_t, mbstate_t * __restrict);
size_t wcsnrtombs(char * __restrict, const wchar_t ** __restrict, size_t,
size_t, mbstate_t * __restrict);
size_t wcslcat(wchar_t *, const wchar_t *, size_t);
size_t wcslcpy(wchar_t *, const wchar_t *, size_t);
#endif

View File

@ -8,11 +8,13 @@ SRCS+= big5.c btowc.c collate.c collcmp.c euc.c fix_grouping.c frune.c \
gb18030.c gb2312.c gbk.c isctype.c iswctype.c \
ldpart.c lmessages.c lmonetary.c lnumeric.c localeconv.c mblen.c \
mbrlen.c \
mbrtowc.c mbrune.c mbsinit.c mbsrtowcs.c mbtowc.c mbstowcs.c \
mbrtowc.c mbrune.c mbsinit.c mbsnrtowcs.c \
mbsrtowcs.c mbtowc.c mbstowcs.c \
mskanji.c nextwctype.c nl_langinfo.c nomacros.c none.c rune.c \
runetype.c setinvalidrune.c setlocale.c setrunelocale.c srune.c \
table.c \
tolower.c toupper.c utf2.c utf8.c wcrtomb.c wcsrtombs.c wcsftime.c \
tolower.c toupper.c utf2.c utf8.c wcrtomb.c wcsnrtombs.c \
wcsrtombs.c wcsftime.c \
wcstof.c wcstod.c \
wcstoimax.c wcstol.c wcstold.c wcstoll.c \
wcstombs.c \
@ -47,9 +49,11 @@ MLINKS+=iswalnum.3 iswalpha.3 iswalnum.3 iswascii.3 iswalnum.3 iswblank.3 \
iswalnum.3 iswupper.3 iswalnum.3 iswxdigit.3
MLINKS+=isxdigit.3 ishexnumber.3
MLINKS+=mbrune.3 mbmb.3 mbrune.3 mbrrune.3
MLINKS+=mbsrtowcs.3 mbsnrtowcs.3
MLINKS+=rune.3 fgetrune.3 rune.3 fputrune.3 rune.3 fungetrune.3 \
rune.3 setinvalidrune.3 rune.3 setrunelocale.3 rune.3 sgetrune.3 \
rune.3 sputrune.3
MLINKS+=wcsrtombs.3 wcsnrtombs.3
MLINKS+=wcstod.3 wcstof.3 wcstod.3 wcstold.3
MLINKS+=wcstol.3 wcstoul.3 wcstol.3 wcstoll.3 wcstol.3 wcstoull.3 \
wcstol.3 wcstoimax.3 wcstol.3 wcstoumax.3

View File

@ -37,11 +37,11 @@
extern size_t (*__mbrtowc)(wchar_t * __restrict, const char * __restrict,
size_t, mbstate_t * __restrict);
extern int (*__mbsinit)(const mbstate_t *);
extern size_t (*__mbsrtowcs)(wchar_t * __restrict, const char ** __restrict,
size_t, mbstate_t * __restrict);
extern size_t (*__mbsnrtowcs)(wchar_t * __restrict, const char ** __restrict,
size_t, size_t, mbstate_t * __restrict);
extern size_t (*__wcrtomb)(char * __restrict, wchar_t, mbstate_t * __restrict);
extern size_t (*__wcsrtombs)(char * __restrict, const wchar_t ** __restrict,
size_t, mbstate_t * __restrict);
extern size_t (*__wcsnrtombs)(char * __restrict, const wchar_t ** __restrict,
size_t, size_t, mbstate_t * __restrict);
/*
* Conversion functions for "NONE"/C/POSIX encoding.
@ -49,17 +49,17 @@ extern size_t (*__wcsrtombs)(char * __restrict, const wchar_t ** __restrict,
extern size_t _none_mbrtowc(wchar_t * __restrict, const char * __restrict,
size_t, mbstate_t * __restrict);
extern int _none_mbsinit(const mbstate_t *);
extern size_t _none_mbsrtowcs(wchar_t * __restrict, const char ** __restrict,
size_t, mbstate_t * __restrict);
extern size_t _none_mbsnrtowcs(wchar_t * __restrict, const char ** __restrict,
size_t, size_t, mbstate_t * __restrict);
extern size_t _none_wcrtomb(char * __restrict, wchar_t,
mbstate_t * __restrict);
extern size_t _none_wcsrtombs(char * __restrict, const wchar_t ** __restrict,
size_t, mbstate_t * __restrict);
extern size_t _none_wcsnrtombs(char * __restrict, const wchar_t ** __restrict,
size_t, size_t, mbstate_t * __restrict);
extern size_t __mbsrtowcs_std(wchar_t * __restrict, const char ** __restrict,
size_t, mbstate_t * __restrict);
extern size_t __wcsrtombs_std(char * __restrict, const wchar_t ** __restrict,
size_t, mbstate_t * __restrict);
extern size_t __mbsnrtowcs_std(wchar_t * __restrict, const char ** __restrict,
size_t, size_t, mbstate_t * __restrict);
extern size_t __wcsnrtombs_std(char * __restrict, const wchar_t ** __restrict,
size_t, size_t, mbstate_t * __restrict);
/*
* Rune emulation functions.

View File

@ -0,0 +1,91 @@
/*-
* 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 <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <errno.h>
#include <limits.h>
#include <stdlib.h>
#include <wchar.h>
#include "mblocal.h"
size_t
mbsnrtowcs(wchar_t * __restrict dst, const char ** __restrict src,
size_t nms, size_t len, mbstate_t * __restrict ps)
{
static mbstate_t mbs;
if (ps == NULL)
ps = &mbs;
return (__mbsnrtowcs(dst, src, nms, len, ps));
}
size_t
__mbsnrtowcs_std(wchar_t * __restrict dst, const char ** __restrict src,
size_t nms, size_t len, mbstate_t * __restrict ps)
{
const char *s;
size_t nchr;
wchar_t wc;
size_t nb;
s = *src;
nchr = 0;
if (dst == NULL) {
for (;;) {
if ((nb = __mbrtowc(&wc, s, nms, ps)) == (size_t)-1)
/* Invalid sequence - mbrtowc() sets errno. */
return ((size_t)-1);
else if (nb == 0 || nb == (size_t)-2)
return (nchr);
s += nb;
nms -= nb;
nchr++;
}
/*NOTREACHED*/
}
while (len-- > 0) {
if ((nb = __mbrtowc(dst, s, nms, ps)) == (size_t)-1) {
*src = s;
return ((size_t)-1);
} else if (nb == (size_t)-2) {
*src = s + nms;
return (nchr);
} else if (nb == 0) {
*src = NULL;
return (nchr);
}
s += nb;
nms -= nb;
nchr++;
dst++;
}
*src = s;
return (nchr);
}

View File

@ -23,11 +23,12 @@
.\" SUCH DAMAGE.
.\"
.\" $FreeBSD$
.Dd April 8, 2004
.Dd July 21, 2004
.Dt MBSRTOWCS 3
.Os
.Sh NAME
.Nm mbsrtowcs
.Nm mbsrtowcs ,
.Nm mbsnrtowcs
.Nd "convert a character string to a wide-character string (restartable)"
.Sh LIBRARY
.Lb libc
@ -38,6 +39,11 @@
.Fa "wchar_t * restrict dst" "const char ** restrict src" "size_t len"
.Fa "mbstate_t * restrict ps"
.Fc
.Ft size_t
.Fo mbsnrtowcs
.Fa "wchar_t * restrict dst" "const char ** restrict src" "size_t nms"
.Fa "size_t len" "mbstate_t * restrict ps"
.Fc
.Sh DESCRIPTION
The
.Fn mbsrtowcs
@ -82,10 +88,21 @@ uses an internal, static
.Vt mbstate_t
object, which is initialized to the initial conversion state
at program startup.
.Pp
The
.Fn mbsnrtowcs
function behaves identically to
.Fn mbsrtowcs ,
except that conversion stops after reading at most
.Fa nms
bytes from the buffer pointed to by
.Fa src .
.Sh RETURN VALUES
The
.Fn mbsrtowcs
function returns the number of wide characters stored in
and
.Fn mbsnrtowcs
functions return the number of wide characters stored in
the array pointed to by
.Fa dst
if successful, otherwise it returns
@ -93,7 +110,9 @@ if successful, otherwise it returns
.Sh ERRORS
The
.Fn mbsrtowcs
function will fail if:
and
.Fn mbsnrtowcs
functions will fail if:
.Bl -tag -width Er
.It Bq Er EILSEQ
An invalid multibyte character sequence was encountered.
@ -110,3 +129,7 @@ The
.Fn mbsrtowcs
function conforms to
.St -isoC-99 .
.Pp
The
.Fn mbsnrtowcs
function is an extension to the standard.

View File

@ -41,46 +41,5 @@ mbsrtowcs(wchar_t * __restrict dst, const char ** __restrict src, size_t len,
if (ps == NULL)
ps = &mbs;
return (__mbsrtowcs(dst, src, len, ps));
}
size_t
__mbsrtowcs_std(wchar_t * __restrict dst, const char ** __restrict src,
size_t len, mbstate_t * __restrict ps)
{
const char *s;
size_t nchr;
wchar_t wc;
int nb;
s = *src;
nchr = 0;
if (dst == NULL) {
for (;;) {
if ((nb = (int)__mbrtowc(&wc, s, MB_CUR_MAX, ps)) < 0)
/* Invalid sequence - mbrtowc() sets errno. */
return ((size_t)-1);
else if (nb == 0)
return (nchr);
s += nb;
nchr++;
}
/*NOTREACHED*/
}
while (len-- > 0) {
if ((nb = (int)__mbrtowc(dst, s, MB_CUR_MAX, ps)) < 0) {
*src = s;
return ((size_t)-1);
} else if (nb == 0) {
*src = NULL;
return (nchr);
}
s += nb;
nchr++;
dst++;
}
*src = s;
return (nchr);
return (__mbsnrtowcs(dst, src, SIZE_T_MAX, len, ps));
}

View File

@ -27,6 +27,7 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <limits.h>
#include <stdlib.h>
#include <wchar.h>
#include "mblocal.h"
@ -38,5 +39,5 @@ mbstowcs(wchar_t * __restrict pwcs, const char * __restrict s, size_t n)
mbstate_t mbs;
mbs = initial;
return (__mbsrtowcs(pwcs, &s, n, &mbs));
return (__mbsnrtowcs(pwcs, &s, SIZE_T_MAX, n, &mbs));
}

View File

@ -55,11 +55,12 @@ int _none_init(_RuneLocale *);
size_t _none_mbrtowc(wchar_t * __restrict, const char * __restrict, size_t,
mbstate_t * __restrict);
int _none_mbsinit(const mbstate_t *);
size_t _none_mbsrtowcs(wchar_t * __restrict, const char ** __restrict,
size_t, mbstate_t * __restrict);
size_t _none_mbsnrtowcs(wchar_t * __restrict dst,
const char ** __restrict src, size_t nms, size_t len,
mbstate_t * __restrict ps __unused);
size_t _none_wcrtomb(char * __restrict, wchar_t, mbstate_t * __restrict);
size_t _none_wcsrtombs(char * __restrict, const wchar_t ** __restrict,
size_t, mbstate_t * __restrict);
size_t _none_wcsnrtombs(char * __restrict, const wchar_t ** __restrict,
size_t, size_t, mbstate_t * __restrict);
int
_none_init(_RuneLocale *rl)
@ -67,9 +68,9 @@ _none_init(_RuneLocale *rl)
__mbrtowc = _none_mbrtowc;
__mbsinit = _none_mbsinit;
__mbsrtowcs = _none_mbsrtowcs;
__mbsnrtowcs = _none_mbsnrtowcs;
__wcrtomb = _none_wcrtomb;
__wcsrtombs = _none_wcsrtombs;
__wcsnrtombs = _none_wcsnrtombs;
_CurrentRuneLocale = rl;
__mb_cur_max = 1;
return(0);
@ -119,18 +120,20 @@ _none_wcrtomb(char * __restrict s, wchar_t wc,
}
size_t
_none_mbsrtowcs(wchar_t * __restrict dst, const char ** __restrict src,
size_t len, mbstate_t * __restrict ps __unused)
_none_mbsnrtowcs(wchar_t * __restrict dst, const char ** __restrict src,
size_t nms, size_t len, mbstate_t * __restrict ps __unused)
{
const char *s;
size_t nchr;
if (dst == NULL)
return (strlen(*src));
if (dst == NULL) {
s = memchr(*src, '\0', nms);
return (s != NULL ? s - *src : nms);
}
s = *src;
nchr = 0;
while (len-- > 0) {
while (len-- > 0 && nms-- > 0) {
if ((*dst++ = (unsigned char)*s++) == L'\0') {
*src = NULL;
return (nchr);
@ -142,14 +145,14 @@ _none_mbsrtowcs(wchar_t * __restrict dst, const char ** __restrict src,
}
size_t
_none_wcsrtombs(char * __restrict dst, const wchar_t ** __restrict src,
size_t len, mbstate_t * __restrict ps __unused)
_none_wcsnrtombs(char * __restrict dst, const wchar_t ** __restrict src,
size_t nwc, size_t len, mbstate_t * __restrict ps __unused)
{
const wchar_t *s;
size_t nchr;
if (dst == NULL) {
for (s = *src; *s != L'\0'; s++) {
for (s = *src; nwc > 0 && *s != L'\0'; s++, nwc--) {
if (*s < 0 || *s > UCHAR_MAX) {
errno = EILSEQ;
return ((size_t)-1);
@ -160,7 +163,7 @@ _none_wcsrtombs(char * __restrict dst, const wchar_t ** __restrict src,
s = *src;
nchr = 0;
while (len-- > 0) {
while (len-- > 0 && nwc-- > 0) {
if (*s < 0 || *s > UCHAR_MAX) {
errno = EILSEQ;
return ((size_t)-1);

View File

@ -100,10 +100,11 @@ __setrunelocale(const char *encoding)
static size_t (*Cached__wcrtomb)(char * __restrict, wchar_t,
mbstate_t * __restrict);
static int (*Cached__mbsinit)(const mbstate_t *);
static size_t (*Cached__mbsrtowcs)(wchar_t * __restrict,
const char ** __restrict, size_t, mbstate_t * __restrict);
static size_t (*Cached__wcsrtombs)(char * __restrict,
const wchar_t ** __restrict, size_t, mbstate_t * __restrict);
static size_t (*Cached__mbsnrtowcs)(wchar_t * __restrict,
const char ** __restrict, size_t, size_t, mbstate_t * __restrict);
static size_t (*Cached__wcsnrtombs)(char * __restrict,
const wchar_t ** __restrict, size_t, size_t,
mbstate_t * __restrict);
/*
* The "C" and "POSIX" locale are always here.
@ -113,9 +114,9 @@ __setrunelocale(const char *encoding)
__mb_cur_max = 1;
__mbrtowc = _none_mbrtowc;
__mbsinit = _none_mbsinit;
__mbsrtowcs = _none_mbsrtowcs;
__mbsnrtowcs = _none_mbsnrtowcs;
__wcrtomb = _none_wcrtomb;
__wcsrtombs = _none_wcsrtombs;
__wcsnrtombs = _none_wcsnrtombs;
return (0);
}
@ -128,9 +129,9 @@ __setrunelocale(const char *encoding)
__mb_cur_max = Cached__mb_cur_max;
__mbrtowc = Cached__mbrtowc;
__mbsinit = Cached__mbsinit;
__mbsrtowcs = Cached__mbsrtowcs;
__mbsnrtowcs = Cached__mbsnrtowcs;
__wcrtomb = Cached__wcrtomb;
__wcsrtombs = Cached__wcsrtombs;
__wcsnrtombs = Cached__wcsnrtombs;
return (0);
}
@ -156,9 +157,9 @@ __setrunelocale(const char *encoding)
__mbrtowc = NULL;
__mbsinit = NULL;
__mbsrtowcs = __mbsrtowcs_std;
__mbsnrtowcs = __mbsnrtowcs_std;
__wcrtomb = NULL;
__wcsrtombs = __wcsrtombs_std;
__wcsnrtombs = __wcsnrtombs_std;
rl->__sputrune = __emulated_sputrune;
rl->__sgetrune = __emulated_sgetrune;
if (strcmp(rl->__encoding, "NONE") == 0)
@ -192,9 +193,9 @@ __setrunelocale(const char *encoding)
Cached__mb_cur_max = __mb_cur_max;
Cached__mbrtowc = __mbrtowc;
Cached__mbsinit = __mbsinit;
Cached__mbsrtowcs = __mbsrtowcs;
Cached__mbsnrtowcs = __mbsnrtowcs;
Cached__wcrtomb = __wcrtomb;
Cached__wcsrtombs = __wcsrtombs;
Cached__wcsnrtombs = __wcsnrtombs;
(void)strcpy(ctype_encoding, encoding);
} else
free(rl);

View File

@ -255,9 +255,9 @@ int __mb_cur_max = 1;
size_t (*__mbrtowc)(wchar_t * __restrict, const char * __restrict, size_t,
mbstate_t * __restrict) = _none_mbrtowc;
int (*__mbsinit)(const mbstate_t *) = _none_mbsinit;
size_t (*__mbsrtowcs)(wchar_t * __restrict, const char ** __restrict,
size_t, mbstate_t * __restrict) = _none_mbsrtowcs;
size_t (*__mbsnrtowcs)(wchar_t * __restrict, const char ** __restrict,
size_t, size_t, mbstate_t * __restrict) = _none_mbsnrtowcs;
size_t (*__wcrtomb)(char * __restrict, wchar_t, mbstate_t * __restrict) =
_none_wcrtomb;
size_t (*__wcsrtombs)(char * __restrict, const wchar_t ** __restrict,
size_t, mbstate_t * __restrict) = _none_wcsrtombs;
size_t (*__wcsnrtombs)(char * __restrict, const wchar_t ** __restrict,
size_t, size_t, mbstate_t * __restrict) = _none_wcsnrtombs;

View File

@ -0,0 +1,111 @@
/*-
* 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 <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <limits.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#include "mblocal.h"
size_t
wcsnrtombs(char * __restrict dst, const wchar_t ** __restrict src, size_t nwc,
size_t len, mbstate_t * __restrict ps)
{
static mbstate_t mbs;
if (ps == NULL)
ps = &mbs;
return (__wcsnrtombs(dst, src, nwc, len, ps));
}
size_t
__wcsnrtombs_std(char * __restrict dst, const wchar_t ** __restrict src,
size_t nwc, size_t len, mbstate_t * __restrict ps)
{
mbstate_t mbsbak;
char buf[MB_LEN_MAX];
const wchar_t *s;
size_t nbytes;
size_t nb;
s = *src;
nbytes = 0;
if (dst == NULL) {
while (nwc-- > 0) {
if ((nb = __wcrtomb(buf, *s, ps)) == (size_t)-1)
/* Invalid character - wcrtomb() sets errno. */
return ((size_t)-1);
else if (*s == L'\0')
break;
s++;
nbytes += nb;
}
return (nbytes + nb - 1);
}
while (len > 0 && nwc-- > 0) {
if (len > (size_t)MB_CUR_MAX) {
/* Enough space to translate in-place. */
if ((nb = (int)__wcrtomb(dst, *s, ps)) < 0) {
*src = s;
return ((size_t)-1);
}
} else {
/*
* May not be enough space; use temp. buffer.
*
* We need to save a copy of the conversion state
* here so we can restore it if the multibyte
* character is too long for the buffer.
*/
mbsbak = *ps;
if ((nb = (int)__wcrtomb(buf, *s, ps)) < 0) {
*src = s;
return ((size_t)-1);
}
if (nb > (int)len) {
/* MB sequence for character won't fit. */
*ps = mbsbak;
break;
}
memcpy(dst, buf, nb);
}
if (*s == L'\0') {
*src = NULL;
return (nbytes + nb - 1);
}
s++;
dst += nb;
len -= nb;
nbytes += nb;
}
*src = s;
return (nbytes);
}

View File

@ -24,11 +24,12 @@
.\"
.\" $FreeBSD$
.\"
.Dd April 8, 2004
.Dd July 21, 2004
.Dt WCSRTOMBS 3
.Os
.Sh NAME
.Nm wcsrtombs
.Nm wcsrtombs ,
.Nm wcsnrtombs
.Nd "convert a wide-character string to a character string (restartable)"
.Sh LIBRARY
.Lb libc
@ -39,6 +40,11 @@
.Fa "char * restrict dst" "const wchar_t ** restrict src"
.Fa "size_t len" "mbstate_t * restrict ps"
.Fc
.Ft size_t
.Fo wcsnrtombs
.Fa "char * restrict dst" "const wchar_t ** restrict src" "size_t nwc"
.Fa "size_t len" "mbstate_t * restrict ps"
.Fc
.Sh DESCRIPTION
The
.Fn wcsrtombs
@ -82,10 +88,21 @@ uses an internal, static
.Vt mbstate_t
object, which is initialized to the initial conversion state
at program startup.
.Pp
The
.Fn wcsnrtombs
function behaves identically to
.Fn wcsrtombs ,
except that conversion stops after reading at most
.Fa nwc
characters from the buffer pointed to by
.Fa src .
.Sh RETURN VALUES
The
.Fn wcsrtombs
function returns the number of bytes stored in
and
.Fn wcsnrtombs
functions return the number of bytes stored in
the array pointed to by
.Fa dst
(not including any terminating null), if successful, otherwise it returns
@ -93,7 +110,9 @@ the array pointed to by
.Sh ERRORS
The
.Fn wcsrtombs
function will fail if:
and
.Fn wcsnrtombs
functions will fail if:
.Bl -tag -width Er
.It Bq Er EILSEQ
An invalid wide character was encountered.
@ -109,3 +128,7 @@ The
.Fn wcsrtombs
function conforms to
.St -isoC-99 .
.Pp
The
.Fn wcsnrtombs
function is an extension to the standard.

View File

@ -41,71 +41,5 @@ wcsrtombs(char * __restrict dst, const wchar_t ** __restrict src, size_t len,
if (ps == NULL)
ps = &mbs;
return (__wcsrtombs(dst, src, len, ps));
}
size_t
__wcsrtombs_std(char * __restrict dst, const wchar_t ** __restrict src,
size_t len, mbstate_t * __restrict ps)
{
mbstate_t mbsbak;
char buf[MB_LEN_MAX];
const wchar_t *s;
size_t nbytes;
int nb;
s = *src;
nbytes = 0;
if (dst == NULL) {
for (;;) {
if ((nb = (int)__wcrtomb(buf, *s, ps)) < 0)
/* Invalid character - wcrtomb() sets errno. */
return ((size_t)-1);
else if (*s == L'\0')
return (nbytes + nb - 1);
s++;
nbytes += nb;
}
/*NOTREACHED*/
}
while (len > 0) {
if (len > (size_t)MB_CUR_MAX) {
/* Enough space to translate in-place. */
if ((nb = (int)__wcrtomb(dst, *s, ps)) < 0) {
*src = s;
return ((size_t)-1);
}
} else {
/*
* May not be enough space; use temp. buffer.
*
* We need to save a copy of the conversion state
* here so we can restore it if the multibyte
* character is too long for the buffer.
*/
mbsbak = *ps;
if ((nb = (int)__wcrtomb(buf, *s, ps)) < 0) {
*src = s;
return ((size_t)-1);
}
if (nb > (int)len) {
/* MB sequence for character won't fit. */
*ps = mbsbak;
break;
}
memcpy(dst, buf, nb);
}
if (*s == L'\0') {
*src = NULL;
return (nbytes + nb - 1);
}
s++;
dst += nb;
len -= nb;
nbytes += nb;
}
*src = s;
return (nbytes);
return (__wcsnrtombs(dst, src, SIZE_T_MAX, len, ps));
}

View File

@ -27,6 +27,7 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <limits.h>
#include <stdlib.h>
#include <wchar.h>
#include "mblocal.h"
@ -38,5 +39,5 @@ wcstombs(char * __restrict s, const wchar_t * __restrict pwcs, size_t n)
mbstate_t mbs;
mbs = initial;
return (__wcsrtombs(s, &pwcs, n, &mbs));
return (__wcsnrtombs(s, &pwcs, SIZE_T_MAX, n, &mbs));
}

View File

@ -29,6 +29,7 @@ __FBSDID("$FreeBSD$");
#include "namespace.h"
#include <errno.h>
#include <limits.h>
#include <stdio.h>
#include <wchar.h>
#include "un-namespace.h"
@ -53,7 +54,7 @@ fputws(const wchar_t * __restrict ws, FILE * __restrict fp)
uio.uio_iovcnt = 1;
iov.iov_base = buf;
do {
nbytes = __wcsrtombs(buf, &ws, sizeof(buf),
nbytes = __wcsnrtombs(buf, &ws, SIZE_T_MAX, sizeof(buf),
&fp->_extra->mbstate);
if (nbytes == (size_t)-1)
goto error;