1 /* Copyright (c) 2009 Corinna Vinschen <corinna@vinschen.de> */
2 /*
3 FUNCTION
4 <<wcsrtombs>>, <<wcsnrtombs>>---convert a wide-character string to a character string
5
6 INDEX
7 wcsrtombs
8 INDEX
9 _wcsrtombs_r
10 INDEX
11 wcsnrtombs
12 INDEX
13 _wcsnrtombs_r
14
15 SYNOPSIS
16 #include <wchar.h>
17 size_t wcsrtombs(char *__restrict <[dst]>,
18 const wchar_t **__restrict <[src]>, size_t <[len]>,
19 mbstate_t *__restrict <[ps]>);
20
21 #include <wchar.h>
22 size_t _wcsrtombs_r(struct _reent *<[ptr]>, char *<[dst]>,
23 const wchar_t **<[src]>, size_t <[len]>,
24 mbstate_t *<[ps]>);
25
26 #include <wchar.h>
27 size_t wcsnrtombs(char *__restrict <[dst]>,
28 const wchar_t **__restrict <[src]>,
29 size_t <[nwc]>, size_t <[len]>,
30 mbstate_t *__restrict <[ps]>);
31
32 #include <wchar.h>
33 size_t _wcsnrtombs_r(struct _reent *<[ptr]>, char *<[dst]>,
34 const wchar_t **<[src]>, size_t <[nwc]>,
35 size_t <[len]>, mbstate_t *<[ps]>);
36
37 DESCRIPTION
38 The <<wcsrtombs>> function converts a string of wide characters indirectly
39 pointed to by <[src]> to a corresponding multibyte character string stored in
40 the array pointed to by <[dst]>. No more than <[len]> bytes are written to
41 <[dst]>.
42
43 If <[dst]> is NULL, no characters are stored.
44
45 If <[dst]> is not NULL, the pointer pointed to by <[src]> is updated to point
46 to the character after the one that conversion stopped at. If conversion
47 stops because a null character is encountered, *<[src]> is set to NULL.
48
49 The mbstate_t argument, <[ps]>, is used to keep track of the shift state. If
50 it is NULL, <<wcsrtombs>> uses an internal, static mbstate_t object, which
51 is initialized to the initial conversion state at program startup.
52
53 The <<wcsnrtombs>> function behaves identically to <<wcsrtombs>>, except that
54 conversion stops after reading at most <[nwc]> characters from the buffer
55 pointed to by <[src]>.
56
57 RETURNS
58 The <<wcsrtombs>> and <<wcsnrtombs>> functions return the number of bytes
59 stored in the array pointed to by <[dst]> (not including any terminating
60 null), if successful, otherwise it returns (size_t)-1.
61
62 PORTABILITY
63 <<wcsrtombs>> is defined by C99 standard.
64 <<wcsnrtombs>> is defined by the POSIX.1-2008 standard.
65 */
66
67 #include <newlib.h>
68 #include <wchar.h>
69 #include <stdlib.h>
70 #include <stdio.h>
71 #include <errno.h>
72 #include "local.h"
73 #include "../locale/setlocale.h"
74
75 size_t
_wcsnrtombs_l(char * dst,const wchar_t ** src,size_t nwc,size_t len,mbstate_t * ps,struct __locale_t * loc)76 _wcsnrtombs_l (char *dst, const wchar_t **src, size_t nwc,
77 size_t len, mbstate_t *ps, struct __locale_t *loc)
78 {
79 char *ptr = dst;
80 char buff[10];
81 wchar_t *pwcs;
82 size_t n;
83 int i;
84
85 #ifdef _MB_CAPABLE
86 if (ps == NULL)
87 {
88 static NEWLIB_THREAD_LOCAL mbstate_t _wcsrtombs_state;
89 ps = &_wcsrtombs_state;
90 }
91 #endif
92
93 /* If no dst pointer, treat len as maximum possible value. */
94 if (dst == NULL)
95 len = (size_t)-1;
96
97 n = 0;
98 pwcs = (wchar_t *)(*src);
99
100 while (n < len && nwc-- > 0)
101 {
102 int count = ps->__count;
103 wint_t wch = ps->__value.__wch;
104 int bytes = loc->wctomb (buff, *pwcs, ps);
105 if (bytes == -1)
106 {
107 _REENT_ERRNO(r) = EILSEQ;
108 ps->__count = 0;
109 return (size_t)-1;
110 }
111 if (n + bytes <= len)
112 {
113 n += bytes;
114 if (dst)
115 {
116 for (i = 0; i < bytes; ++i)
117 *ptr++ = buff[i];
118 ++(*src);
119 }
120 if (*pwcs++ == 0x00)
121 {
122 if (dst)
123 *src = NULL;
124 ps->__count = 0;
125 return n - 1;
126 }
127 }
128 else
129 {
130 /* not enough room, we must back up state to before __WCTOMB call */
131 ps->__count = count;
132 ps->__value.__wch = wch;
133 len = 0;
134 }
135 }
136
137 return n;
138 }
139
140 #ifndef _REENT_ONLY
141 size_t
wcsnrtombs(char * __restrict dst,const wchar_t ** __restrict src,size_t nwc,size_t len,mbstate_t * __restrict ps)142 wcsnrtombs (char *__restrict dst,
143 const wchar_t **__restrict src,
144 size_t nwc,
145 size_t len,
146 mbstate_t *__restrict ps)
147 {
148 return _wcsnrtombs_l (dst, src, nwc, len, ps,
149 __get_current_locale ());
150 }
151 #endif /* !_REENT_ONLY */
152