tech-userlevel archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: [PATCH] Support for mbsnrtowcs and wcsnrtomb
On Sun, Apr 21, 2013 at 04:10:42PM +0200, Joerg Sonnenberger wrote:
> attached patch adds the POSIX2008 functions mbsnrtowcs and wcsnrtombs.
> They differ from the non-n variant in the possibility of limiting the
> input size.
Attached is an updated and simplified version.
Joerg
Index: distrib/sets/lists/debug/mi
===================================================================
RCS file: /home/joerg/repo/netbsd/src/distrib/sets/lists/debug/mi,v
retrieving revision 1.22
diff -u -p -r1.22 mi
--- distrib/sets/lists/debug/mi 8 May 2013 17:41:31 -0000 1.22
+++ distrib/sets/lists/debug/mi 17 May 2013 13:08:32 -0000
@@ -1543,6 +1543,7 @@
./usr/libdata/debug/usr/tests/lib/libc/locale/t_io.debug
tests-lib-debug debug,atf
./usr/libdata/debug/usr/tests/lib/libc/locale/t_mbrtowc.debug
tests-lib-debug debug,atf
./usr/libdata/debug/usr/tests/lib/libc/locale/t_mbstowcs.debug
tests-lib-debug debug,atf
+./usr/libdata/debug/usr/tests/lib/libc/locale/t_mbsnrtowcs.debug
tests-lib-debug debug,atf
./usr/libdata/debug/usr/tests/lib/libc/locale/t_mbtowc.debug
tests-lib-debug debug,atf
./usr/libdata/debug/usr/tests/lib/libc/locale/t_wcscspn.debug
tests-lib-debug debug,atf
./usr/libdata/debug/usr/tests/lib/libc/locale/t_wcspbrk.debug
tests-lib-debug debug,atf
Index: distrib/sets/lists/tests/mi
===================================================================
RCS file: /home/joerg/repo/netbsd/src/distrib/sets/lists/tests/mi,v
retrieving revision 1.535
diff -u -p -r1.535 mi
--- distrib/sets/lists/tests/mi 22 Apr 2013 21:06:28 -0000 1.535
+++ distrib/sets/lists/tests/mi 17 May 2013 13:08:32 -0000
@@ -1942,6 +1942,7 @@
./usr/tests/lib/libc/locale/t_io tests-lib-tests atf
./usr/tests/lib/libc/locale/t_mbrtowc tests-lib-tests atf
./usr/tests/lib/libc/locale/t_mbstowcs tests-lib-tests atf
+./usr/tests/lib/libc/locale/t_mbsnrtowcs tests-lib-tests atf
./usr/tests/lib/libc/locale/t_mbtowc tests-lib-tests atf
./usr/tests/lib/libc/locale/t_wcscspn tests-lib-tests atf
./usr/tests/lib/libc/locale/t_wcspbrk tests-lib-tests atf
Index: include/wchar.h
===================================================================
RCS file: /home/joerg/repo/netbsd/src/include/wchar.h,v
retrieving revision 1.37
diff -u -p -r1.37 wchar.h
--- include/wchar.h 19 Apr 2013 23:45:15 -0000 1.37
+++ include/wchar.h 17 May 2013 13:08:32 -0000
@@ -212,6 +212,11 @@ typedef struct _locale *locale_t;
# define __LOCALE_T_DECLARED
# endif
__BEGIN_DECLS
+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);
+
int wcscoll_l(const wchar_t *, const wchar_t *, locale_t);
size_t wcsxfrm_l(wchar_t *, const wchar_t *, size_t, locale_t);
int wcsncasecmp_l(const wchar_t *, const wchar_t *, size_t, locale_t);
@@ -246,9 +251,13 @@ size_t mbrtowc_l(wchar_t * __restrict, c
int mbsinit_l(const mbstate_t *, locale_t);
size_t mbsrtowcs_l(wchar_t * __restrict, const char ** __restrict, size_t,
mbstate_t * __restrict, locale_t);
+size_t mbsnrtowcs_l(wchar_t * __restrict, const char ** __restrict, size_t,
+ size_t, mbstate_t * __restrict, locale_t);
size_t wcrtomb_l(char * __restrict, wchar_t, mbstate_t * __restrict, locale_t);
size_t wcsrtombs_l(char * __restrict, const wchar_t ** __restrict, size_t,
mbstate_t * __restrict, locale_t);
+size_t wcsnrtombs_l(char * __restrict, const wchar_t ** __restrict, size_t,
+ size_t, mbstate_t * __restrict, locale_t);
int wctob_l(wint_t, locale_t);
int fwprintf_l(FILE * __restrict, locale_t, const wchar_t * __restrict, ...);
Index: lib/libc/citrus/citrus_ctype.c
===================================================================
RCS file: /home/joerg/repo/netbsd/src/lib/libc/citrus/citrus_ctype.c,v
retrieving revision 1.6
diff -u -p -r1.6 citrus_ctype.c
--- lib/libc/citrus/citrus_ctype.c 19 Nov 2011 18:34:21 -0000 1.6
+++ lib/libc/citrus/citrus_ctype.c 21 May 2013 17:46:29 -0000
@@ -92,6 +92,8 @@ _initctypemodule(_citrus_ctype_t cc, cha
cc->cc_ops->co_wctob = &_citrus_ctype_wctob_fallback;
/* FALLTHROUGH */
case 0x00000002:
+ cc->cc_ops->co_mbsnrtowcs = &_citrus_ctype_mbsnrtowcs_fallback;
+ cc->cc_ops->co_wcsnrtombs = &_citrus_ctype_wcsnrtombs_fallback;
/* FALLTHROUGH */
default:
break;
@@ -106,10 +108,12 @@ _initctypemodule(_citrus_ctype_t cc, cha
cc->cc_ops->co_mbrtowc == NULL ||
cc->cc_ops->co_mbsinit == NULL ||
cc->cc_ops->co_mbsrtowcs == NULL ||
+ cc->cc_ops->co_mbsnrtowcs == NULL ||
cc->cc_ops->co_mbstowcs == NULL ||
cc->cc_ops->co_mbtowc == NULL ||
cc->cc_ops->co_wcrtomb == NULL ||
cc->cc_ops->co_wcsrtombs == NULL ||
+ cc->cc_ops->co_wcsnrtombs == NULL ||
cc->cc_ops->co_wcstombs == NULL ||
cc->cc_ops->co_wctomb == NULL ||
cc->cc_ops->co_btowc == NULL ||
Index: lib/libc/citrus/citrus_ctype.h
===================================================================
RCS file: /home/joerg/repo/netbsd/src/lib/libc/citrus/citrus_ctype.h,v
retrieving revision 1.2
diff -u -p -r1.2 citrus_ctype.h
--- lib/libc/citrus/citrus_ctype.h 5 Mar 2003 20:18:15 -0000 1.2
+++ lib/libc/citrus/citrus_ctype.h 17 May 2013 13:08:32 -0000
@@ -95,6 +95,16 @@ _citrus_ctype_mbsrtowcs(_citrus_ctype_t
}
static __inline int
+_citrus_ctype_mbsnrtowcs(_citrus_ctype_t cc, wchar_t *pwcs, const char **s,
+ size_t in, size_t n, void *pspriv, size_t *nresult)
+{
+
+ _DIAGASSERT(cc && cc->cc_ops && cc->cc_ops->co_mbsnrtowcs && nresult);
+ return (*cc->cc_ops->co_mbsnrtowcs)(cc, pwcs, s, in, n,
+ pspriv, nresult);
+}
+
+static __inline int
_citrus_ctype_mbstowcs(_citrus_ctype_t cc, wchar_t *pwcs, const char *s,
size_t n, size_t *nresult)
{
@@ -133,6 +143,16 @@ _citrus_ctype_wcsrtombs(_citrus_ctype_t
}
static __inline int
+_citrus_ctype_wcsnrtombs(_citrus_ctype_t cc, char *s, const wchar_t **ppwcs,
+ size_t in, size_t n, void *pspriv, size_t *nresult)
+{
+
+ _DIAGASSERT(cc && cc->cc_ops && cc->cc_ops->co_wcsnrtombs && nresult);
+ return (*cc->cc_ops->co_wcsnrtombs)(cc, s, ppwcs, in, n,
+ pspriv, nresult);
+}
+
+static __inline int
_citrus_ctype_wcstombs(_citrus_ctype_t cc, char *s, const wchar_t *wcs,
size_t n, size_t *nresult)
{
Index: lib/libc/citrus/citrus_ctype_fallback.c
===================================================================
RCS file: /home/joerg/repo/netbsd/src/lib/libc/citrus/citrus_ctype_fallback.c,v
retrieving revision 1.2
diff -u -p -r1.2 citrus_ctype_fallback.c
--- lib/libc/citrus/citrus_ctype_fallback.c 27 Jun 2003 14:52:25 -0000
1.2
+++ lib/libc/citrus/citrus_ctype_fallback.c 20 May 2013 19:33:44 -0000
@@ -35,6 +35,7 @@ __RCSID("$NetBSD: citrus_ctype_fallback.
#include <sys/types.h>
#include <assert.h>
+#include <errno.h>
#include <wchar.h>
#include <stdio.h>
#include <string.h>
@@ -108,3 +109,121 @@ _citrus_ctype_wctob_fallback(_citrus_cty
return 0;
}
+
+/*
+ * for ABI version >= 0x00000003
+ */
+
+int
+_citrus_ctype_mbsnrtowcs_fallback(_citrus_ctype_rec_t * __restrict cc,
+ wchar_t * __restrict pwcs, const char ** __restrict s, size_t in,
+ size_t n, void * __restrict psenc, size_t * __restrict nresult)
+{
+ int err;
+ size_t cnt, siz;
+ const char *s0, *se;
+
+ _DIAGASSERT(nresult != 0);
+ _DIAGASSERT(psenc != NULL);
+ _DIAGASSERT(s != NULL);
+ _DIAGASSERT(*s != NULL);
+
+ /* if pwcs is NULL, ignore n */
+ if (pwcs == NULL)
+ n = 1; /* arbitrary >0 value */
+
+ err = 0;
+ cnt = 0;
+ se = *s + in;
+ s0 = *s; /* to keep *s unchanged for now, use copy instead. */
+ while (s0 < se && n > 0) {
+ err = _citrus_ctype_mbrtowc(cc, pwcs, s0, (size_t)(se - s0),
+ psenc, &siz);
+ if (err) {
+ cnt = (size_t)-1;
+ goto bye;
+ }
+ if (siz == (size_t)-2) {
+ s0 = se;
+ goto bye;
+ }
+ switch (siz) {
+ case 0:
+ if (pwcs) {
+ size_t dum;
+ _citrus_ctype_mbrtowc(cc, NULL, NULL, 0, psenc,
+ &dum);
+ }
+ s0 = 0;
+ goto bye;
+ default:
+ if (pwcs) {
+ pwcs++;
+ n--;
+ }
+ s0 += siz;
+ cnt++;
+ break;
+ }
+ }
+bye:
+ if (pwcs)
+ *s = s0;
+
+ *nresult = cnt;
+
+ return err;
+}
+
+int
+_citrus_ctype_wcsnrtombs_fallback(_citrus_ctype_rec_t * __restrict cc,
+ char * __restrict s, const wchar_t ** __restrict pwcs, size_t in,
+ size_t n, void * __restrict psenc, size_t * __restrict nresult)
+{
+ size_t cnt = 0;
+ int err;
+ char buf[MB_LEN_MAX];
+ size_t siz;
+ const wchar_t* pwcs0;
+ mbstate_t state;
+
+ pwcs0 = *pwcs;
+
+ if (!s)
+ n = 1;
+
+ while (in > 0 && n > 0) {
+ memcpy(&state, psenc, sizeof(state));
+ err = _citrus_ctype_wcrtomb(cc, buf, *pwcs0, psenc, &siz);
+ if (siz == (size_t)-1) {
+ *nresult = siz;
+ return (err);
+ }
+
+ if (s) {
+ if (n < siz) {
+ memcpy(psenc, &state, sizeof(state));
+ break;
+ }
+ memcpy(s, buf, siz);
+ s += siz;
+ n -= siz;
+ }
+ cnt += siz;
+ if (!*pwcs0) {
+ if (s) {
+ memset(psenc, 0, sizeof(state));
+ }
+ pwcs0 = 0;
+ cnt--; /* don't include terminating null */
+ break;
+ }
+ pwcs0++;
+ --in;
+ }
+ if (s)
+ *pwcs = pwcs0;
+
+ *nresult = cnt;
+ return (0);
+}
Index: lib/libc/citrus/citrus_ctype_fallback.h
===================================================================
RCS file: /home/joerg/repo/netbsd/src/lib/libc/citrus/citrus_ctype_fallback.h,v
retrieving revision 1.1
diff -u -p -r1.1 citrus_ctype_fallback.h
--- lib/libc/citrus/citrus_ctype_fallback.h 5 Mar 2003 20:18:15 -0000
1.1
+++ lib/libc/citrus/citrus_ctype_fallback.h 17 May 2013 13:08:32 -0000
@@ -35,4 +35,16 @@ int _citrus_ctype_btowc_fallback(_citrus
int _citrus_ctype_wctob_fallback(_citrus_ctype_rec_t * __restrict,
wint_t, int * __restrict);
+/* fallback functions for 0x00000003 */
+int _citrus_ctype_mbsnrtowcs_fallback(_citrus_ctype_rec_t * __restrict,
+ wchar_t * __restrict,
+ const char ** __restrict, size_t,
+ size_t, void * __restrict,
+ size_t * __restrict);
+int _citrus_ctype_wcsnrtombs_fallback(_citrus_ctype_rec_t * __restrict,
+ char * __restrict,
+ const wchar_t ** __restrict, size_t,
+ size_t, void * __restrict,
+ size_t * __restrict);
+
#endif
Index: lib/libc/citrus/citrus_ctype_local.h
===================================================================
RCS file: /home/joerg/repo/netbsd/src/lib/libc/citrus/citrus_ctype_local.h,v
retrieving revision 1.3
diff -u -p -r1.3 citrus_ctype_local.h
--- lib/libc/citrus/citrus_ctype_local.h 9 Feb 2008 14:56:20 -0000
1.3
+++ lib/libc/citrus/citrus_ctype_local.h 17 May 2013 13:08:32 -0000
@@ -60,6 +60,11 @@ static int _citrus_##_e_##_ctype_mbsrtow
const char ** __restrict, \
size_t, void * __restrict, \
size_t * __restrict); \
+static int _citrus_##_e_##_ctype_mbsnrtowcs(_citrus_ctype_rec_t *
__restrict, \
+ wchar_t * __restrict, \
+ const char ** __restrict, \
+ size_t, size_t, void * __restrict, \
+ size_t * __restrict); \
static int _citrus_##_e_##_ctype_mbstowcs(void * __restrict, \
wchar_t * __restrict, \
const char * __restrict, \
@@ -77,6 +82,11 @@ static int _citrus_##_e_##_ctype_wcsrtom
const wchar_t ** __restrict, \
size_t, void * __restrict, \
size_t * __restrict); \
+static int _citrus_##_e_##_ctype_wcsnrtombs(_citrus_ctype_rec_t *
__restrict, \
+ char * __restrict, \
+ const wchar_t ** __restrict, \
+ size_t, size_t, void * __restrict, \
+ size_t * __restrict); \
static int _citrus_##_e_##_ctype_wcstombs(void * __restrict, \
char * __restrict, \
const wchar_t * __restrict, \
@@ -107,7 +117,9 @@ _citrus_ctype_ops_rec_t _citrus_##_e_##_
/* co_wcstombs */ &_citrus_##_e_##_ctype_wcstombs, \
/* co_wctomb */ &_citrus_##_e_##_ctype_wctomb, \
/* co_btowc */ &_citrus_##_e_##_ctype_btowc, \
- /* co_wctob */ &_citrus_##_e_##_ctype_wctob \
+ /* co_wctob */ &_citrus_##_e_##_ctype_wctob, \
+ /* co_mbsnrtowcs */ &_citrus_##_e_##_ctype_mbsnrtowcs, \
+ /* co_wcsnrtombs */ &_citrus_##_e_##_ctype_wcsnrtombs, \
}
typedef struct _citrus_ctype_ops_rec _citrus_ctype_ops_rec_t;
@@ -129,7 +141,10 @@ typedef int (*_citrus_ctype_mbsinit_t)
(void * __restrict, const void * __restrict, int * __restrict);
typedef int (*_citrus_ctype_mbsrtowcs_t)
(void * __restrict, wchar_t * __restrict, const char ** __restrict,
- size_t, void * __restrict,
+ size_t, void * __restrict, size_t * __restrict);
+typedef int (*_citrus_ctype_mbsnrtowcs_t)
+ (_citrus_ctype_rec_t * __restrict, wchar_t * __restrict,
+ const char ** __restrict, size_t, size_t, void * __restrict,
size_t * __restrict);
typedef int (*_citrus_ctype_mbstowcs_t)
(void * __restrict, wchar_t * __restrict, const char * __restrict,
@@ -143,6 +158,10 @@ typedef int (*_citrus_ctype_wcrtomb_t)
typedef int (*_citrus_ctype_wcsrtombs_t)
(void * __restrict, char * __restrict, const wchar_t ** __restrict,
size_t, void * __restrict, size_t * __restrict);
+typedef int (*_citrus_ctype_wcsnrtombs_t)
+ (_citrus_ctype_rec_t * __restrict, char * __restrict,
+ const wchar_t ** __restrict, size_t, size_t, void * __restrict,
+ size_t * __restrict);
typedef int (*_citrus_ctype_wcstombs_t)
(void * __restrict, char * __restrict, const wchar_t * __restrict,
size_t, size_t * __restrict);
@@ -152,16 +171,20 @@ typedef int (*_citrus_ctype_btowc_t)
(_citrus_ctype_rec_t * __restrict, int, wint_t * __restrict);
typedef int (*_citrus_ctype_wctob_t)
(_citrus_ctype_rec_t * __restrict, wint_t, int * __restrict);
+#include "citrus_ctype_fallback.h"
/*
* ABI Version change log:
* 0x00000001
* initial version
* 0x00000002
- * ops record: btowc and wctob are added.
+ * ops record: btowc and wctob added.
+ * ctype record: unchanged.
+ * 0x00000003
+ * ops record: mbsnrtowcs and wcsnrtombs added.
* ctype record: unchanged.
*/
-#define _CITRUS_CTYPE_ABI_VERSION 0x00000002
+#define _CITRUS_CTYPE_ABI_VERSION 0x00000003
struct _citrus_ctype_ops_rec {
uint32_t co_abi_version;
/* version 0x00000001 */
@@ -182,6 +205,9 @@ struct _citrus_ctype_ops_rec {
/* version 0x00000002 */
_citrus_ctype_btowc_t co_btowc;
_citrus_ctype_wctob_t co_wctob;
+ /* version 0x00000003 */
+ _citrus_ctype_mbsnrtowcs_t co_mbsnrtowcs;
+ _citrus_ctype_wcsnrtombs_t co_wcsnrtombs;
};
#define _CITRUS_DEFAULT_CTYPE_NAME "NONE"
Index: lib/libc/citrus/citrus_ctype_template.h
===================================================================
RCS file: /home/joerg/repo/netbsd/src/lib/libc/citrus/citrus_ctype_template.h,v
retrieving revision 1.35
diff -u -p -r1.35 citrus_ctype_template.h
--- lib/libc/citrus/citrus_ctype_template.h 9 Feb 2008 14:56:20 -0000
1.35
+++ lib/libc/citrus/citrus_ctype_template.h 21 May 2013 16:03:37 -0000
@@ -85,8 +85,10 @@
* mbrtowc
* mbtowc
* mbsrtowcs
+ * mbsnrtowcs
* wcrtomb
* wcsrtombs
+ * wcsnrtombs
* wctomb
* These need to be keeped in the ctype encoding information structure,
* pointed by "cei".
@@ -238,8 +240,8 @@ _FUNCNAME(mbsrtowcs_priv)(_ENCODING_INFO
_DIAGASSERT(nresult != 0);
_DIAGASSERT(ei != NULL);
_DIAGASSERT(psenc != NULL);
- _DIAGASSERT(s == NULL);
- _DIAGASSERT(*s == NULL);
+ _DIAGASSERT(s != NULL);
+ _DIAGASSERT(*s != NULL);
/* if pwcs is NULL, ignore n */
if (pwcs == NULL)
@@ -282,6 +284,66 @@ bye:
return err;
}
+static int
+_FUNCNAME(mbsnrtowcs_priv)(_ENCODING_INFO * __restrict ei,
+ wchar_t * __restrict pwcs,
+ const char ** __restrict s, size_t in,
+ size_t n, _ENCODING_STATE * __restrict psenc,
+ size_t * __restrict nresult)
+{
+ int err;
+ size_t cnt, siz;
+ const char *s0, *se;
+
+ _DIAGASSERT(nresult != 0);
+ _DIAGASSERT(ei != NULL);
+ _DIAGASSERT(psenc != NULL);
+ _DIAGASSERT(s != NULL);
+ _DIAGASSERT(*s != NULL);
+
+ /* if pwcs is NULL, ignore n */
+ if (pwcs == NULL)
+ n = 1; /* arbitrary >0 value */
+
+ err = 0;
+ cnt = 0;
+ se = *s + in;
+ s0 = *s; /* to keep *s unchanged for now, use copy instead. */
+ while (s0 < se && n > 0) {
+ err = _FUNCNAME(mbrtowc_priv)(ei, pwcs, &s0, se - s0,
+ psenc, &siz);
+ if (err) {
+ cnt = (size_t)-1;
+ goto bye;
+ }
+ if (siz == (size_t)-2) {
+ s0 = se;
+ goto bye;
+ }
+ switch (siz) {
+ case 0:
+ if (pwcs) {
+ _FUNCNAME(init_state)(ei, psenc);
+ }
+ s0 = 0;
+ goto bye;
+ default:
+ if (pwcs) {
+ pwcs++;
+ n--;
+ }
+ cnt++;
+ break;
+ }
+ }
+bye:
+ if (pwcs)
+ *s = s0;
+
+ *nresult = cnt;
+
+ return err;
+}
static int
_FUNCNAME(wcsrtombs_priv)(_ENCODING_INFO * __restrict ei, char * __restrict s,
@@ -289,6 +351,66 @@ _FUNCNAME(wcsrtombs_priv)(_ENCODING_INFO
size_t n, _ENCODING_STATE * __restrict psenc,
size_t * __restrict nresult)
{
+ int err;
+ char buf[MB_LEN_MAX];
+ size_t cnt, siz;
+ const wchar_t* pwcs0;
+#if _ENCODING_IS_STATE_DEPENDENT
+ _ENCODING_STATE state;
+#endif
+
+ pwcs0 = *pwcs;
+
+ cnt = 0;
+ if (!s)
+ n = 1;
+
+ while (n > 0) {
+#if _ENCODING_IS_STATE_DEPENDENT
+ state = *psenc;
+#endif
+ err = _FUNCNAME(wcrtomb_priv)(ei, buf, sizeof(buf),
+ *pwcs0, psenc, &siz);
+ if (siz == (size_t)-1) {
+ *nresult = siz;
+ return (err);
+ }
+
+ if (s) {
+ if (n < siz) {
+#if _ENCODING_IS_STATE_DEPENDENT
+ *psenc = state;
+#endif
+ break;
+ }
+ memcpy(s, buf, siz);
+ s += siz;
+ n -= siz;
+ }
+ cnt += siz;
+ if (!*pwcs0) {
+ if (s) {
+ _FUNCNAME(init_state)(ei, psenc);
+ }
+ pwcs0 = 0;
+ cnt--; /* don't include terminating null */
+ break;
+ }
+ pwcs0++;
+ }
+ if (s)
+ *pwcs = pwcs0;
+
+ *nresult = cnt;
+ return (0);
+}
+
+static int
+_FUNCNAME(wcsnrtombs_priv)(_ENCODING_INFO * __restrict ei, char * __restrict s,
+ const wchar_t ** __restrict pwcs, size_t in,
+ size_t n, _ENCODING_STATE * __restrict psenc,
+ size_t * __restrict nresult)
+{
int cnt = 0, err;
char buf[MB_LEN_MAX];
size_t siz;
@@ -302,7 +424,7 @@ _FUNCNAME(wcsrtombs_priv)(_ENCODING_INFO
if (!s)
n = 1;
- while (n > 0) {
+ while (in > 0 && n > 0) {
#if _ENCODING_IS_STATE_DEPENDENT
state = *psenc;
#endif
@@ -334,6 +456,7 @@ _FUNCNAME(wcsrtombs_priv)(_ENCODING_INFO
break;
}
pwcs0++;
+ --in;
}
if (s)
*pwcs = pwcs0;
@@ -525,6 +648,27 @@ _FUNCNAME(ctype_mbsrtowcs)(void * __rest
return (err);
}
+static int __used
+_FUNCNAME(ctype_mbsnrtowcs)(_citrus_ctype_rec_t * __restrict cc, wchar_t *
__restrict pwcs,
+ const char ** __restrict s, size_t in, size_t n,
+ void * __restrict pspriv,
+ size_t * __restrict nresult)
+{
+ void *cl = cc->cc_closure;
+ _ENCODING_STATE *psenc;
+ _ENCODING_INFO *ei;
+ int err = 0;
+
+ _DIAGASSERT(cl != NULL);
+
+ ei = _CEI_TO_EI(_TO_CEI(cl));
+ _RESTART_BEGIN(mbsnrtowcs, _TO_CEI(cl), pspriv, psenc);
+ err = _FUNCNAME(mbsnrtowcs_priv)(ei, pwcs, s, in, n, psenc, nresult);
+ _RESTART_END(mbsnrtowcs, _TO_CEI(cl), pspriv, psenc);
+
+ return (err);
+}
+
static int
_FUNCNAME(ctype_mbstowcs)(void * __restrict cl, wchar_t * __restrict pwcs,
const char * __restrict s, size_t n,
@@ -637,6 +781,29 @@ _FUNCNAME(ctype_wcsrtombs)(void * __rest
return err;
}
+static int __used
+/*ARGSUSED*/
+_FUNCNAME(ctype_wcsnrtombs)(_citrus_ctype_rec_t * __restrict cc,
+ char * __restrict s,
+ const wchar_t ** __restrict pwcs, size_t in,
+ size_t n, void * __restrict pspriv,
+ size_t * __restrict nresult)
+{
+ void *cl = cc->cc_closure;
+ _ENCODING_STATE *psenc;
+ _ENCODING_INFO *ei;
+ int err = 0;
+
+ _DIAGASSERT(cl != NULL);
+
+ ei = _CEI_TO_EI(_TO_CEI(cl));
+ _RESTART_BEGIN(wcsnrtombs, _TO_CEI(cl), pspriv, psenc);
+ err = _FUNCNAME(wcsnrtombs_priv)(ei, s, pwcs, in, n, psenc, nresult);
+ _RESTART_END(wcsnrtombs, _TO_CEI(cl), pspriv, psenc);
+
+ return err;
+}
+
static int
/*ARGSUSED*/
_FUNCNAME(ctype_wcstombs)(void * __restrict cl, char * __restrict s,
Index: lib/libc/citrus/citrus_none.c
===================================================================
RCS file: /home/joerg/repo/netbsd/src/lib/libc/citrus/citrus_none.c,v
retrieving revision 1.18
diff -u -p -r1.18 citrus_none.c
--- lib/libc/citrus/citrus_none.c 14 Jun 2008 16:01:07 -0000 1.18
+++ lib/libc/citrus/citrus_none.c 17 May 2013 13:08:32 -0000
@@ -185,6 +185,47 @@ _citrus_NONE_ctype_mbsrtowcs(void * __re
}
static int
+/*ARGSUSED*/
+_citrus_NONE_ctype_mbsnrtowcs(_citrus_ctype_rec_t * __restrict cc,
+ wchar_t * __restrict pwcs,
+ const char ** __restrict s, size_t in, size_t n,
+ void * __restrict pspriv,
+ size_t * __restrict nresult)
+{
+ int cnt;
+ const char *s0;
+
+ /* if pwcs is NULL, ignore n */
+ if (pwcs == NULL)
+ n = 1; /* arbitrary >0 value */
+
+ cnt = 0;
+ s0 = *s; /* to keep *s unchanged for now, use copy instead. */
+ while (in > 0 && n > 0) {
+ if (pwcs != NULL) {
+ *pwcs = (wchar_t)(unsigned char)*s0;
+ }
+ if (*s0 == '\0') {
+ s0 = NULL;
+ break;
+ }
+ s0++;
+ --in;
+ if (pwcs != NULL) {
+ pwcs++;
+ n--;
+ }
+ cnt++;
+ }
+ if (pwcs)
+ *s = s0;
+
+ *nresult = (size_t)cnt;
+
+ return (0);
+}
+
+static int
_citrus_NONE_ctype_mbstowcs(void * __restrict cl, wchar_t * __restrict wcs,
const char * __restrict s, size_t n,
size_t * __restrict nresult)
@@ -282,6 +323,48 @@ _citrus_NONE_ctype_wcsrtombs(void * __re
}
static int
+/*ARGSUSED*/
+_citrus_NONE_ctype_wcsnrtombs(_citrus_ctype_rec_t * __restrict cc,
+ char * __restrict s,
+ const wchar_t ** __restrict pwcs, size_t in,
+ size_t n, void * __restrict pspriv,
+ size_t * __restrict nresult)
+{
+ size_t count;
+ const wchar_t *pwcs0;
+
+ pwcs0 = *pwcs;
+ count = 0;
+
+ if (s == NULL)
+ n = 1;
+
+ while (in > 0 && n > 0) {
+ if ((*pwcs0 & ~0xFFU) != 0) {
+ *nresult = (size_t)-1;
+ return (EILSEQ);
+ }
+ if (s != NULL) {
+ *s++ = (char)*pwcs0;
+ n--;
+ }
+ if (*pwcs0 == L'\0') {
+ pwcs0 = NULL;
+ break;
+ }
+ count++;
+ pwcs0++;
+ --in;
+ }
+ if (s != NULL)
+ *pwcs = pwcs0;
+
+ *nresult = count;
+
+ return (0);
+}
+
+static int
_citrus_NONE_ctype_wcstombs(void * __restrict cl, char * __restrict s,
const wchar_t * __restrict pwcs, size_t n,
size_t * __restrict nresult)
Index: lib/libc/citrus/modules/citrus_big5.c
===================================================================
RCS file: /home/joerg/repo/netbsd/src/lib/libc/citrus/modules/citrus_big5.c,v
retrieving revision 1.13
diff -u -p -r1.13 citrus_big5.c
--- lib/libc/citrus/modules/citrus_big5.c 23 May 2011 14:53:46 -0000
1.13
+++ lib/libc/citrus/modules/citrus_big5.c 17 May 2013 13:08:32 -0000
@@ -115,8 +115,10 @@ typedef struct {
_BIG5State s_mbrtowc;
_BIG5State s_mbtowc;
_BIG5State s_mbsrtowcs;
+ _BIG5State s_mbsnrtowcs;
_BIG5State s_wcrtomb;
_BIG5State s_wcsrtombs;
+ _BIG5State s_wcsnrtombs;
_BIG5State s_wctomb;
} states;
} _BIG5CTypeInfo;
Index: lib/libc/citrus/modules/citrus_dechanyu.c
===================================================================
RCS file:
/home/joerg/repo/netbsd/src/lib/libc/citrus/modules/citrus_dechanyu.c,v
retrieving revision 1.4
diff -u -p -r1.4 citrus_dechanyu.c
--- lib/libc/citrus/modules/citrus_dechanyu.c 19 Nov 2011 18:20:13 -0000
1.4
+++ lib/libc/citrus/modules/citrus_dechanyu.c 17 May 2013 13:08:32 -0000
@@ -71,8 +71,10 @@ typedef struct {
_DECHanyuState s_mbrtowc;
_DECHanyuState s_mbtowc;
_DECHanyuState s_mbsrtowcs;
+ _DECHanyuState s_mbsnrtowcs;
_DECHanyuState s_wcrtomb;
_DECHanyuState s_wcsrtombs;
+ _DECHanyuState s_wcsnrtombs;
_DECHanyuState s_wctomb;
} states;
} _DECHanyuCTypeInfo;
Index: lib/libc/citrus/modules/citrus_euc.c
===================================================================
RCS file: /home/joerg/repo/netbsd/src/lib/libc/citrus/modules/citrus_euc.c,v
retrieving revision 1.14
diff -u -p -r1.14 citrus_euc.c
--- lib/libc/citrus/modules/citrus_euc.c 11 Jan 2009 02:46:24 -0000
1.14
+++ lib/libc/citrus/modules/citrus_euc.c 17 May 2013 13:08:32 -0000
@@ -107,8 +107,10 @@ typedef struct {
_EUCState s_mbrtowc;
_EUCState s_mbtowc;
_EUCState s_mbsrtowcs;
+ _EUCState s_mbsnrtowcs;
_EUCState s_wcrtomb;
_EUCState s_wcsrtombs;
+ _EUCState s_wcsnrtombs;
_EUCState s_wctomb;
} states;
} _EUCCTypeInfo;
Index: lib/libc/citrus/modules/citrus_euctw.c
===================================================================
RCS file: /home/joerg/repo/netbsd/src/lib/libc/citrus/modules/citrus_euctw.c,v
retrieving revision 1.11
diff -u -p -r1.11 citrus_euctw.c
--- lib/libc/citrus/modules/citrus_euctw.c 14 Jun 2008 16:01:07 -0000
1.11
+++ lib/libc/citrus/modules/citrus_euctw.c 17 May 2013 13:08:32 -0000
@@ -98,8 +98,10 @@ typedef struct {
_EUCTWState s_mbrtowc;
_EUCTWState s_mbtowc;
_EUCTWState s_mbsrtowcs;
+ _EUCTWState s_mbsnrtowcs;
_EUCTWState s_wcrtomb;
_EUCTWState s_wcsrtombs;
+ _EUCTWState s_wcsnrtombs;
_EUCTWState s_wctomb;
} states;
} _EUCTWCTypeInfo;
Index: lib/libc/citrus/modules/citrus_gbk2k.c
===================================================================
RCS file: /home/joerg/repo/netbsd/src/lib/libc/citrus/modules/citrus_gbk2k.c,v
retrieving revision 1.7
diff -u -p -r1.7 citrus_gbk2k.c
--- lib/libc/citrus/modules/citrus_gbk2k.c 14 Jun 2008 16:01:07 -0000
1.7
+++ lib/libc/citrus/modules/citrus_gbk2k.c 17 May 2013 13:08:32 -0000
@@ -72,8 +72,10 @@ typedef struct {
_GBK2KState s_mbrtowc;
_GBK2KState s_mbtowc;
_GBK2KState s_mbsrtowcs;
+ _GBK2KState s_mbsnrtowcs;
_GBK2KState s_wcrtomb;
_GBK2KState s_wcsrtombs;
+ _GBK2KState s_wcsnrtombs;
_GBK2KState s_wctomb;
} states;
} _GBK2KCTypeInfo;
Index: lib/libc/citrus/modules/citrus_hz.c
===================================================================
RCS file: /home/joerg/repo/netbsd/src/lib/libc/citrus/modules/citrus_hz.c,v
retrieving revision 1.2
diff -u -p -r1.2 citrus_hz.c
--- lib/libc/citrus/modules/citrus_hz.c 14 Jun 2008 16:01:07 -0000 1.2
+++ lib/libc/citrus/modules/citrus_hz.c 17 May 2013 13:08:32 -0000
@@ -143,8 +143,10 @@ typedef struct {
_HZState s_mbrtowc;
_HZState s_mbtowc;
_HZState s_mbsrtowcs;
+ _HZState s_mbsnrtowcs;
_HZState s_wcrtomb;
_HZState s_wcsrtombs;
+ _HZState s_wcsnrtombs;
_HZState s_wctomb;
} states;
} _HZCTypeInfo;
Index: lib/libc/citrus/modules/citrus_iso2022.c
===================================================================
RCS file: /home/joerg/repo/netbsd/src/lib/libc/citrus/modules/citrus_iso2022.c,v
retrieving revision 1.22
diff -u -p -r1.22 citrus_iso2022.c
--- lib/libc/citrus/modules/citrus_iso2022.c 10 Oct 2011 22:45:45 -0000
1.22
+++ lib/libc/citrus/modules/citrus_iso2022.c 17 May 2013 13:08:32 -0000
@@ -133,8 +133,10 @@ typedef struct {
_ISO2022State s_mbrtowc;
_ISO2022State s_mbtowc;
_ISO2022State s_mbsrtowcs;
+ _ISO2022State s_mbsnrtowcs;
_ISO2022State s_wcrtomb;
_ISO2022State s_wcsrtombs;
+ _ISO2022State s_wcsnrtombs;
_ISO2022State s_wctomb;
} states;
} _ISO2022CTypeInfo;
Index: lib/libc/citrus/modules/citrus_johab.c
===================================================================
RCS file: /home/joerg/repo/netbsd/src/lib/libc/citrus/modules/citrus_johab.c,v
retrieving revision 1.4
diff -u -p -r1.4 citrus_johab.c
--- lib/libc/citrus/modules/citrus_johab.c 14 Jun 2008 16:01:07 -0000
1.4
+++ lib/libc/citrus/modules/citrus_johab.c 17 May 2013 13:08:32 -0000
@@ -71,8 +71,10 @@ typedef struct {
_JOHABState s_mbrtowc;
_JOHABState s_mbtowc;
_JOHABState s_mbsrtowcs;
+ _JOHABState s_mbsnrtowcs;
_JOHABState s_wcrtomb;
_JOHABState s_wcsrtombs;
+ _JOHABState s_wcsnrtombs;
_JOHABState s_wctomb;
} states;
} _JOHABCTypeInfo;
Index: lib/libc/citrus/modules/citrus_mskanji.c
===================================================================
RCS file: /home/joerg/repo/netbsd/src/lib/libc/citrus/modules/citrus_mskanji.c,v
retrieving revision 1.13
diff -u -p -r1.13 citrus_mskanji.c
--- lib/libc/citrus/modules/citrus_mskanji.c 14 Jun 2008 16:01:08 -0000
1.13
+++ lib/libc/citrus/modules/citrus_mskanji.c 17 May 2013 13:08:32 -0000
@@ -107,8 +107,10 @@ typedef struct {
_MSKanjiState s_mbrtowc;
_MSKanjiState s_mbtowc;
_MSKanjiState s_mbsrtowcs;
+ _MSKanjiState s_mbsnrtowcs;
_MSKanjiState s_wcrtomb;
_MSKanjiState s_wcsrtombs;
+ _MSKanjiState s_wcsnrtombs;
_MSKanjiState s_wctomb;
} states;
} _MSKanjiCTypeInfo;
Index: lib/libc/citrus/modules/citrus_ues.c
===================================================================
RCS file: /home/joerg/repo/netbsd/src/lib/libc/citrus/modules/citrus_ues.c,v
retrieving revision 1.3
diff -u -p -r1.3 citrus_ues.c
--- lib/libc/citrus/modules/citrus_ues.c 12 Feb 2012 13:51:29 -0000
1.3
+++ lib/libc/citrus/modules/citrus_ues.c 17 May 2013 13:08:32 -0000
@@ -68,8 +68,10 @@ typedef struct {
_UESState s_mbrtowc;
_UESState s_mbtowc;
_UESState s_mbsrtowcs;
+ _UESState s_mbsnrtowcs;
_UESState s_wcrtomb;
_UESState s_wcsrtombs;
+ _UESState s_wcsnrtombs;
_UESState s_wctomb;
} states;
} _UESCTypeInfo;
Index: lib/libc/citrus/modules/citrus_utf7.c
===================================================================
RCS file: /home/joerg/repo/netbsd/src/lib/libc/citrus/modules/citrus_utf7.c,v
retrieving revision 1.5
diff -u -p -r1.5 citrus_utf7.c
--- lib/libc/citrus/modules/citrus_utf7.c 23 Aug 2006 12:57:24 -0000
1.5
+++ lib/libc/citrus/modules/citrus_utf7.c 17 May 2013 13:08:32 -0000
@@ -79,8 +79,10 @@ typedef struct {
_UTF7State s_mbrtowc;
_UTF7State s_mbtowc;
_UTF7State s_mbsrtowcs;
+ _UTF7State s_mbsnrtowcs;
_UTF7State s_wcrtomb;
_UTF7State s_wcsrtombs;
+ _UTF7State s_wcsnrtombs;
_UTF7State s_wctomb;
} states;
} _UTF7CTypeInfo;
Index: lib/libc/citrus/modules/citrus_utf8.c
===================================================================
RCS file: /home/joerg/repo/netbsd/src/lib/libc/citrus/modules/citrus_utf8.c,v
retrieving revision 1.17
diff -u -p -r1.17 citrus_utf8.c
--- lib/libc/citrus/modules/citrus_utf8.c 14 Jun 2008 16:01:08 -0000
1.17
+++ lib/libc/citrus/modules/citrus_utf8.c 17 May 2013 13:08:32 -0000
@@ -111,8 +111,10 @@ typedef struct {
_UTF8State s_mbrtowc;
_UTF8State s_mbtowc;
_UTF8State s_mbsrtowcs;
+ _UTF8State s_mbsnrtowcs;
_UTF8State s_wcrtomb;
_UTF8State s_wcsrtombs;
+ _UTF8State s_wcsnrtombs;
_UTF8State s_wctomb;
} states;
} _UTF8CTypeInfo;
Index: lib/libc/citrus/modules/citrus_viqr.c
===================================================================
RCS file: /home/joerg/repo/netbsd/src/lib/libc/citrus/modules/citrus_viqr.c,v
retrieving revision 1.5
diff -u -p -r1.5 citrus_viqr.c
--- lib/libc/citrus/modules/citrus_viqr.c 19 Nov 2011 18:20:13 -0000
1.5
+++ lib/libc/citrus/modules/citrus_viqr.c 17 May 2013 13:08:32 -0000
@@ -234,8 +234,10 @@ typedef struct {
_VIQRState s_mbrtowc;
_VIQRState s_mbtowc;
_VIQRState s_mbsrtowcs;
+ _VIQRState s_mbsnrtowcs;
_VIQRState s_wcrtomb;
_VIQRState s_wcsrtombs;
+ _VIQRState s_wcsnrtombs;
_VIQRState s_wctomb;
} states;
} _VIQRCTypeInfo;
Index: lib/libc/citrus/modules/citrus_zw.c
===================================================================
RCS file: /home/joerg/repo/netbsd/src/lib/libc/citrus/modules/citrus_zw.c,v
retrieving revision 1.4
diff -u -p -r1.4 citrus_zw.c
--- lib/libc/citrus/modules/citrus_zw.c 14 Jun 2008 16:01:08 -0000 1.4
+++ lib/libc/citrus/modules/citrus_zw.c 17 May 2013 13:08:32 -0000
@@ -77,8 +77,10 @@ typedef struct {
_ZWState s_mbrtowc;
_ZWState s_mbtowc;
_ZWState s_mbsrtowcs;
+ _ZWState s_mbsnrtowcs;
_ZWState s_wcrtomb;
_ZWState s_wcsrtombs;
+ _ZWState s_wcsnrtombs;
_ZWState s_wctomb;
} states;
} _ZWCTypeInfo;
Index: lib/libc/locale/multibyte_amd1.c
===================================================================
RCS file: /home/joerg/repo/netbsd/src/lib/libc/locale/multibyte_amd1.c,v
retrieving revision 1.12
diff -u -p -r1.12 multibyte_amd1.c
--- lib/libc/locale/multibyte_amd1.c 17 May 2013 12:55:57 -0000 1.12
+++ lib/libc/locale/multibyte_amd1.c 17 May 2013 13:11:57 -0000
@@ -151,6 +151,29 @@ mbsrtowcs(wchar_t *pwcs, const char **s,
}
size_t
+mbsnrtowcs_l(wchar_t *pwcs, const char **s, size_t in, size_t n, mbstate_t *ps,
+ locale_t loc)
+{
+ size_t ret;
+ int err0;
+
+ _fixup_ps(_RUNE_LOCALE(loc), ps, s == NULL);
+
+ err0 = _citrus_ctype_mbsnrtowcs(_ps_to_ctype(ps), pwcs, s, in, n,
+ _ps_to_private(ps), &ret);
+ if (err0)
+ errno = err0;
+
+ return ret;
+}
+
+size_t
+mbsnrtowcs(wchar_t *pwcs, const char **s, size_t in, size_t n, mbstate_t *ps)
+{
+ return mbsnrtowcs_l(pwcs, s, in, n, ps, _current_locale());
+}
+
+size_t
wcrtomb_l(char *s, wchar_t wc, mbstate_t *ps, locale_t loc)
{
size_t ret;
Index: lib/libc/locale/multibyte_c90.c
===================================================================
RCS file: /home/joerg/repo/netbsd/src/lib/libc/locale/multibyte_c90.c,v
retrieving revision 1.10
diff -u -p -r1.10 multibyte_c90.c
--- lib/libc/locale/multibyte_c90.c 17 May 2013 12:55:57 -0000 1.10
+++ lib/libc/locale/multibyte_c90.c 17 May 2013 14:14:19 -0000
@@ -45,6 +45,10 @@ __RCSID("$NetBSD: multibyte_c90.c,v 1.10
#include "citrus_module.h"
#include "citrus_ctype.h"
#include "runetype_local.h"
+#include "multibyte.h"
+
+#define _RUNE_LOCALE(loc) \
+ ((_RuneLocale *)((loc)->part_impl[(size_t)LC_CTYPE]))
#define _CITRUS_CTYPE(loc) \
(((_RuneLocale *)((loc)->part_impl[(size_t)LC_CTYPE]))->rl_citrus_ctype)
@@ -126,6 +130,29 @@ wcstombs(char *s, const wchar_t *wcs, si
return wcstombs_l(s, wcs, n, _current_locale());
}
+size_t
+wcsnrtombs_l(char *s, const wchar_t **ppwcs, size_t in, size_t n, mbstate_t
*ps,
+ locale_t loc)
+{
+ size_t ret;
+ int err0;
+
+ _fixup_ps(_RUNE_LOCALE(loc), ps, s == NULL);
+
+ err0 = _citrus_ctype_wcsnrtombs(_ps_to_ctype(ps), s, ppwcs, in, n,
+ _ps_to_private(ps), &ret);
+ if (err0)
+ errno = err0;
+
+ return ret;
+}
+
+size_t
+wcsnrtombs(char *s, const wchar_t **ppwcs, size_t in, size_t n, mbstate_t *ps)
+{
+ return wcsnrtombs_l(s, ppwcs, in, n, ps, _current_locale());
+}
+
int
wctomb_l(char *s, wchar_t wc, locale_t loc)
{
Index: tests/lib/libc/locale/Makefile
===================================================================
RCS file: /home/joerg/repo/netbsd/src/tests/lib/libc/locale/Makefile,v
retrieving revision 1.5
diff -u -p -r1.5 Makefile
--- tests/lib/libc/locale/Makefile 28 Feb 2013 21:52:02 -0000 1.5
+++ tests/lib/libc/locale/Makefile 17 May 2013 13:08:32 -0000
@@ -6,6 +6,7 @@ TESTSDIR= ${TESTSBASE}/lib/libc/locale
TESTS_C+= t_mbrtowc
TESTS_C+= t_mbstowcs
+TESTS_C+= t_mbsnrtowcs
TESTS_C+= t_mbtowc
TESTS_C+= t_wcscspn
TESTS_C+= t_wcspbrk
Index: tests/lib/libc/locale/t_mbsnrtowcs.c
===================================================================
RCS file: tests/lib/libc/locale/t_mbsnrtowcs.c
diff -N tests/lib/libc/locale/t_mbsnrtowcs.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ tests/lib/libc/locale/t_mbsnrtowcs.c 21 May 2013 15:59:07 -0000
@@ -0,0 +1,97 @@
+/* $NetBSD$ */
+
+/*-
+ * Copyright (c) 2013 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Joerg Sonnenberger.
+ *
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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>
+__RCSID("$NetBSD$");
+
+#include <locale.h>
+#include <wchar.h>
+
+#include <atf-c.h>
+
+static const struct test {
+ const char *locale;
+ const char *data;
+ size_t limit;
+ const wchar_t output1[64];
+ size_t output1_len;
+ const wchar_t output2[64];
+ size_t output2_len;
+} tests[] = {
+ { "C", "ABCD0123", 4, { 0x41, 0x42, 0x43, 0x44 }, 4,
+ { 0x30, 0x31, 0x32, 0x33, 0x0 }, 5 },
+ { "en_US.UTF-8", "ABCD0123", 4, { 0x41, 0x42, 0x43, 0x44 }, 4,
+ { 0x30, 0x31, 0x32, 0x33, 0x0 }, 5 },
+ { "en_US.UTF-8", "ABC\303\2440123", 4, { 0x41, 0x42, 0x43, }, 3,
+ { 0xe4, 0x30, 0x31, 0x32, 0x33, 0x0 }, 6 },
+};
+
+ATF_TC(mbsnrtowcs);
+ATF_TC_HEAD(mbsnrtowcs, tc)
+{
+ atf_tc_set_md_var(tc, "descr",
+ "Checks mbsnrtowc(3) with different locales");
+}
+ATF_TC_BODY(mbsnrtowcs, tc)
+{
+ size_t i;
+ const struct test *t;
+ mbstate_t state;
+ wchar_t buf[64];
+ const char *src;
+ size_t len;
+
+ for (i = 0; i < __arraycount(tests); ++i) {
+ t = &tests[i];
+ ATF_REQUIRE_STREQ(setlocale(LC_ALL, "C"), "C");
+ ATF_REQUIRE(setlocale(LC_CTYPE, t->locale) != NULL);
+ memset(&state, 0, sizeof(state));
+ src = t->data;
+ len = mbsnrtowcs(buf, &src, t->limit,
+ __arraycount(buf), &state);
+ ATF_REQUIRE_EQ(src, t->data + t->limit);
+ ATF_REQUIRE_EQ(len, t->output1_len);
+ ATF_REQUIRE(wmemcmp(t->output1, buf, len) == 0);
+ len = mbsnrtowcs(buf, &src, strlen(src) + 1,
+ __arraycount(buf), &state);
+ ATF_REQUIRE_EQ(len, strlen(t->data) - t->limit);
+ ATF_REQUIRE(wmemcmp(t->output2, buf, len + 1) == 0);
+ ATF_REQUIRE_EQ(src, NULL);
+ }
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, mbsnrtowcs);
+
+ return atf_no_error();
+}
Home |
Main Index |
Thread Index |
Old Index