summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authortjr <tjr@FreeBSD.org>2004-07-21 10:54:57 +0000
committertjr <tjr@FreeBSD.org>2004-07-21 10:54:57 +0000
commit5b4f25c6e9c9b37dcda00bd4a94aabeffeed31b0 (patch)
tree1c3c81fbcfab80a357977aa6546dc3166c9d5257 /lib
parentf892b6158fb86942cd8cee58017eded760b7546d (diff)
downloadFreeBSD-src-5b4f25c6e9c9b37dcda00bd4a94aabeffeed31b0.zip
FreeBSD-src-5b4f25c6e9c9b37dcda00bd4a94aabeffeed31b0.tar.gz
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.
Diffstat (limited to 'lib')
-rw-r--r--lib/libc/locale/Makefile.inc8
-rw-r--r--lib/libc/locale/mblocal.h24
-rw-r--r--lib/libc/locale/mbsnrtowcs.c91
-rw-r--r--lib/libc/locale/mbsrtowcs.331
-rw-r--r--lib/libc/locale/mbsrtowcs.c43
-rw-r--r--lib/libc/locale/mbstowcs.c3
-rw-r--r--lib/libc/locale/none.c33
-rw-r--r--lib/libc/locale/setrunelocale.c25
-rw-r--r--lib/libc/locale/table.c8
-rw-r--r--lib/libc/locale/wcsnrtombs.c111
-rw-r--r--lib/libc/locale/wcsrtombs.331
-rw-r--r--lib/libc/locale/wcsrtombs.c68
-rw-r--r--lib/libc/locale/wcstombs.c3
-rw-r--r--lib/libc/stdio/fputws.c3
14 files changed, 317 insertions, 165 deletions
diff --git a/lib/libc/locale/Makefile.inc b/lib/libc/locale/Makefile.inc
index 1e8a363..cf02a3f 100644
--- a/lib/libc/locale/Makefile.inc
+++ b/lib/libc/locale/Makefile.inc
@@ -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
diff --git a/lib/libc/locale/mblocal.h b/lib/libc/locale/mblocal.h
index 8e36ad5..3727b72 100644
--- a/lib/libc/locale/mblocal.h
+++ b/lib/libc/locale/mblocal.h
@@ -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.
diff --git a/lib/libc/locale/mbsnrtowcs.c b/lib/libc/locale/mbsnrtowcs.c
new file mode 100644
index 0000000..5284087
--- /dev/null
+++ b/lib/libc/locale/mbsnrtowcs.c
@@ -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);
+}
diff --git a/lib/libc/locale/mbsrtowcs.3 b/lib/libc/locale/mbsrtowcs.3
index 9963d85..f54e419 100644
--- a/lib/libc/locale/mbsrtowcs.3
+++ b/lib/libc/locale/mbsrtowcs.3
@@ -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.
diff --git a/lib/libc/locale/mbsrtowcs.c b/lib/libc/locale/mbsrtowcs.c
index a90c655..1239c82 100644
--- a/lib/libc/locale/mbsrtowcs.c
+++ b/lib/libc/locale/mbsrtowcs.c
@@ -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));
}
diff --git a/lib/libc/locale/mbstowcs.c b/lib/libc/locale/mbstowcs.c
index 4623535..ad259d8 100644
--- a/lib/libc/locale/mbstowcs.c
+++ b/lib/libc/locale/mbstowcs.c
@@ -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));
}
diff --git a/lib/libc/locale/none.c b/lib/libc/locale/none.c
index 2a3ada6..d964233 100644
--- a/lib/libc/locale/none.c
+++ b/lib/libc/locale/none.c
@@ -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);
diff --git a/lib/libc/locale/setrunelocale.c b/lib/libc/locale/setrunelocale.c
index de3ee06..4c19ff7 100644
--- a/lib/libc/locale/setrunelocale.c
+++ b/lib/libc/locale/setrunelocale.c
@@ -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);
diff --git a/lib/libc/locale/table.c b/lib/libc/locale/table.c
index 4d72959..de71a4b 100644
--- a/lib/libc/locale/table.c
+++ b/lib/libc/locale/table.c
@@ -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;
diff --git a/lib/libc/locale/wcsnrtombs.c b/lib/libc/locale/wcsnrtombs.c
new file mode 100644
index 0000000..6f2d5b0
--- /dev/null
+++ b/lib/libc/locale/wcsnrtombs.c
@@ -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);
+}
diff --git a/lib/libc/locale/wcsrtombs.3 b/lib/libc/locale/wcsrtombs.3
index 91e61fd..ff607c2 100644
--- a/lib/libc/locale/wcsrtombs.3
+++ b/lib/libc/locale/wcsrtombs.3
@@ -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.
diff --git a/lib/libc/locale/wcsrtombs.c b/lib/libc/locale/wcsrtombs.c
index a03f0d3..f3b38b7 100644
--- a/lib/libc/locale/wcsrtombs.c
+++ b/lib/libc/locale/wcsrtombs.c
@@ -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));
}
diff --git a/lib/libc/locale/wcstombs.c b/lib/libc/locale/wcstombs.c
index 5bb5954..acd0051 100644
--- a/lib/libc/locale/wcstombs.c
+++ b/lib/libc/locale/wcstombs.c
@@ -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));
}
diff --git a/lib/libc/stdio/fputws.c b/lib/libc/stdio/fputws.c
index b5be731..025e1c0 100644
--- a/lib/libc/stdio/fputws.c
+++ b/lib/libc/stdio/fputws.c
@@ -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;
OpenPOWER on IntegriCloud