ReactOS 0.4.16-dev-974-g5022a45
wcstombs.cpp
Go to the documentation of this file.
1/***
2*wcstombs.c - Convert wide char string to multibyte char string.
3*
4* Copyright (c) Microsoft Corporation. All rights reserved.
5*
6*Purpose:
7* Convert a wide char string into the equivalent multibyte char string.
8*
9*******************************************************************************/
13#include <ctype.h>
14#include <errno.h>
15#include <locale.h>
16#include <stdint.h>
17#include <stdlib.h>
18
19/***
20*size_t __cdecl wcsncnt - count wide characters in a string, up to n.
21*
22*Purpose:
23* Internal local support function. Counts characters in string including nullptr.
24* If nullptr not found in n chars, then return n.
25*
26*Entry:
27* const wchar_t *string - start of string
28* size_t n - character count
29*
30*Exit:
31* returns number of wide characters from start of string to
32* nullptr (inclusive), up to n.
33*
34*Exceptions:
35*
36*******************************************************************************/
37
38_Post_satisfies_(return <= cnt && return <= _String_length_(string + 1))
39static size_t __cdecl wcsncnt (
40 _In_reads_or_z_(cnt) const wchar_t *string,
41 _In_ size_t cnt
42 )
43{
44 size_t n = cnt+1;
45 wchar_t *cp = (wchar_t *)string;
46
47 while (--n && *cp)
48 cp++;
49
50 if (n && !*cp)
51 return cp - string + 1;
52 return cnt;
53}
54
55/***
56*size_t wcstombs() - Convert wide char string to multibyte char string.
57*
58*Purpose:
59* Convert a wide char string into the equivalent multibyte char string,
60* according to the LC_CTYPE category of the current locale.
61* [ANSI].
62*
63* The destination string is null terminated only if the null terminator
64* is copied from the source string.
65*
66*Entry:
67* char *s = pointer to destination multibyte char string
68* const wchar_t *pwc = pointer to source wide character string
69* size_t n = maximum number of bytes to store in s
70*
71*Exit:
72* If s != nullptr, returns (size_t)-1 (if a wchar cannot be converted)
73* Otherwise: Number of bytes modified (<=n), not including
74* the terminating NUL, if any.
75*
76*Exceptions:
77* Returns (size_t)-1 if an error is encountered.
78* Input parameters are validated. Refer to the validation section of the function.
79*
80*******************************************************************************/
81
82_Success_(return != static_cast<size_t>(-1))
83static size_t __cdecl _wcstombs_l_helper(
84 _Out_writes_(n) char * s,
85 _In_z_ const wchar_t * pwcs,
86 _In_ size_t n,
87 _Inout_ __crt_cached_ptd_host& ptd
88 )
89{
90 size_t count = 0;
91 int i, retval;
94
95 if (s && n == 0)
96 /* dest string exists, but 0 bytes converted */
97 return 0;
98
99 /* validation section */
100 _UCRT_VALIDATE_RETURN(ptd, pwcs != nullptr, EINVAL, (size_t)-1);
101
102
103 /* if destination string exists, fill it in */
104 const _locale_t locale = ptd.get_locale();
105
106 if (locale->locinfo->_public._locale_lc_codepage == CP_UTF8)
107 {
110 }
111
112 if (s)
113 {
114 if ( locale->locinfo->locale_name[LC_CTYPE] == nullptr )
115 {
116 /* C locale: easy and fast */
117 /* Actually, there are such wchar_t characters which are > 255,
118 * but they can be transformed to a valid single byte char
119 * (i.e. a char in the C locale case). Like, for example,
120 * alternative digits in unicode like Arabic-Indic U+0660..U+0669.
121 * The problem is that WideCharToMultiByte() does not translate those
122 * wchar_t unless we pass the correct codepage (1256, Arabic).
123 * See bug VSW:192653.
124 */
125 while(count < n)
126 {
127 if (static_cast<uint16_t>(*pwcs) > 0xFF) /* validate high byte */
128 {
129 ptd.get_errno().set(EILSEQ);
130 return (size_t)-1; /* error */
131 }
132 s[count] = (char) *pwcs;
133 if (*pwcs++ == L'\0')
134 {
135 return count;
136 }
137 count++;
138 }
139 return count;
140 }
141 else
142 {
143
144 if (1 == locale->locinfo->_public._locale_mb_cur_max)
145 {
146 /* If SBCS, one wchar_t maps to one char */
147
148 /* WideCharToMultiByte will compare past nullptr - reset n */
149 if (n > 0)
150 {
151 n = wcsncnt(pwcs, n);
152 }
153 if ( ((count = __acrt_WideCharToMultiByte( locale->locinfo->_public._locale_lc_codepage,
154 0,
155 pwcs,
156 (int)n,
157 s,
158 (int)n,
159 nullptr,
160 &defused )) != 0) &&
161 (!defused) )
162 {
163 if (s[count - 1] == '\0')
164 {
165 count--; /* don't count NUL */
166 }
167
168 return count;
169 }
170
171 ptd.get_errno().set(EILSEQ);
172 return (size_t)-1;
173 }
174 else
175 {
176
177 /* If MBCS, wchar_t to char mapping unknown */
178
179 /* Assume that usually the buffer is large enough */
180 if ( ((count = __acrt_WideCharToMultiByte( locale->locinfo->_public._locale_lc_codepage,
181 0,
182 pwcs,
183 -1,
184 s,
185 (int)n,
186 nullptr,
187 &defused )) != 0) &&
188 (!defused) )
189 {
190 return count - 1; /* don't count NUL */
191 }
192
194 {
195 ptd.get_errno().set(EILSEQ);
196 return (size_t)-1;
197 }
198
199 /* buffer not large enough, must do char by char */
200 while (count < n)
201 {
202 int mb_cur_max = locale->locinfo->_public._locale_mb_cur_max;
203 if ( ((retval = __acrt_WideCharToMultiByte( locale->locinfo->_public._locale_lc_codepage,
204 0,
205 pwcs,
206 1,
207 buffer,
208 __min(MB_LEN_MAX, mb_cur_max),
209 nullptr,
210 &defused )) == 0)
211 || defused )
212 {
213 ptd.get_errno().set(EILSEQ);
214 return (size_t)-1;
215 }
216
217 /* enforce this for prefast */
218 if (retval < 0 ||
220 {
221 ptd.get_errno().set(EILSEQ);
222 return (size_t)-1;
223 }
224
225 if (count + retval > n)
226 return count;
227
228 for (i = 0; i < retval; i++, count++) /* store character */
229 {
230 if((s[count] = buffer[i])=='\0')
231 {
232 return count;
233 }
234 }
235
236 pwcs++;
237 }
238
239 return count;
240 }
241 }
242 }
243 else
244 { /* s == nullptr, get size only, pwcs must be NUL-terminated */
245 if ( locale->locinfo->locale_name[LC_CTYPE] == nullptr )
246 {
247 size_t len = 0;
248 for (wchar_t *pw = (wchar_t *)pwcs; *pw != 0; pw++) /* validate high byte */
249 {
250 if (*pw > 255) /* validate high byte */
251 {
252 ptd.get_errno().set(EILSEQ);
253 return (size_t)-1; /* error */
254 }
255 ++len;
256 }
257
258 return len;
259 }
260 else
261 {
262 if ( ((count = __acrt_WideCharToMultiByte( locale->locinfo->_public._locale_lc_codepage,
263 0,
264 pwcs,
265 -1,
266 nullptr,
267 0,
268 nullptr,
269 &defused )) == 0) ||
270 (defused) )
271 {
272 ptd.get_errno().set(EILSEQ);
273 return (size_t)-1;
274 }
275
276 return count - 1;
277 }
278 }
279}
280
281extern "C" size_t __cdecl _wcstombs_l(
282 char * s,
283 const wchar_t * pwcs,
284 size_t n,
286 )
287{
288 __crt_cached_ptd_host ptd(plocinfo);
289 return _wcstombs_l_helper(s, pwcs, n, ptd);
290}
291
292extern "C" size_t __cdecl wcstombs(
293 char * s,
294 const wchar_t * pwcs,
295 size_t n
296 )
297{
298 __crt_cached_ptd_host ptd;
299 return _wcstombs_l_helper(s, pwcs, n, ptd);
300}
301
302/***
303*errno_t wcstombs_s() - Convert wide char string to multibyte char string.
304*
305*Purpose:
306* Convert a wide char string into the equivalent multibyte char string,
307* according to the LC_CTYPE category of the current locale.
308*
309* The destination string is always null terminated.
310*
311*Entry:
312* size_t *pConvertedChars = Number of bytes modified including the terminating nullptr
313* This pointer can be nullptr.
314* char *dst = pointer to destination multibyte char string
315* size_t sizeInBytes = size of the destination buffer
316* const wchar_t *src = pointer to source wide character string
317* size_t n = maximum number of bytes to store in s (not including the terminating nullptr)
318*
319*Exit:
320* The error code.
321*
322*Exceptions:
323* Input parameters are validated. Refer to the validation section of the function.
324*
325*******************************************************************************/
326
327static errno_t __cdecl _wcstombs_internal (
328 size_t * pConvertedChars,
329 char * dst,
330 size_t sizeInBytes,
331 const wchar_t * src,
332 size_t n,
333 __crt_cached_ptd_host& ptd
334 )
335{
336 size_t retsize;
337 errno_t retvalue = 0;
338
339 /* validation section */
340 _UCRT_VALIDATE_RETURN_ERRCODE(ptd, (dst != nullptr && sizeInBytes > 0) || (dst == nullptr && sizeInBytes == 0), EINVAL);
341 if (dst != nullptr)
342 {
344 }
345
346 if (pConvertedChars != nullptr)
347 {
348 *pConvertedChars = 0;
349 }
350
351 size_t bufferSize = n > sizeInBytes ? sizeInBytes : n;
353
354 retsize = _wcstombs_l_helper(dst, src, bufferSize, ptd);
355
356 if (retsize == (size_t)-1)
357 {
358 if (dst != nullptr)
359 {
361 }
362 return ptd.get_errno().value_or(0);
363 }
364
365 /* count the null terminator */
366 retsize++;
367
368 if (dst != nullptr)
369 {
370 /* return error if the string does not fit, unless n == _TRUNCATE */
371 if (retsize > sizeInBytes)
372 {
373 if (n != _TRUNCATE)
374 {
377 }
378 retsize = sizeInBytes;
379 retvalue = STRUNCATE;
380 }
381
382 /* ensure the string is null terminated */
383 dst[retsize - 1] = '\0';
384 }
385
386 if (pConvertedChars != nullptr)
387 {
388 *pConvertedChars = retsize;
389 }
390
391 return retvalue;
392}
393
394extern "C" errno_t __cdecl _wcstombs_s_l (
395 size_t *pConvertedChars,
396 char * dst,
397 size_t sizeInBytes,
398 const wchar_t * src,
399 size_t n,
401 )
402{
403 __crt_cached_ptd_host ptd(plocinfo);
404 return _wcstombs_internal(pConvertedChars, dst, sizeInBytes, src, n, ptd);
405}
406
407extern "C" errno_t __cdecl wcstombs_s (
408 size_t *pConvertedChars,
409 char * dst,
410 size_t sizeInBytes,
411 const wchar_t * src,
412 size_t n
413 )
414{
415 __crt_cached_ptd_host ptd;
416 return _wcstombs_internal(pConvertedChars, dst, sizeInBytes, src, n, ptd);
417}
return __acrt_WideCharToMultiByte(code_page, 0, buffer.get(), -1, result_size !=0 ? result :nullptr, result_size, nullptr, nullptr)
#define EINVAL
Definition: acclib.h:90
#define ERANGE
Definition: acclib.h:92
#define __cdecl
Definition: accygwin.h:79
unsigned short int uint16_t
Definition: acefiex.h:54
static int state
Definition: maze.c:121
Definition: _locale.h:75
#define _UCRT_VALIDATE_RETURN(ptd, expr, errorcode, retexpr)
#define _UCRT_VALIDATE_RETURN_ERRCODE(ptd, expr, errorcode)
#define _RESET_STRING(_String, _Size)
#define ERROR_INSUFFICIENT_BUFFER
Definition: dderror.h:10
unsigned char
Definition: typeof.h:29
unsigned int BOOL
Definition: ntddk_ex.h:94
size_t bufferSize
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLdouble s
Definition: gl.h:2039
GLdouble n
Definition: glext.h:7729
GLenum src
Definition: glext.h:6340
GLuint buffer
Definition: glext.h:5915
GLenum GLenum dst
Definition: glext.h:6340
GLenum GLsizei len
Definition: glext.h:6722
#define LC_CTYPE
Definition: locale.h:19
#define __min(a, b)
Definition: stdlib.h:102
#define MB_LEN_MAX
Definition: stdlib.h:19
_wcstombs_l
Definition: stdlib.h:1039
_wcstombs_s_l
Definition: stdlib.h:1039
wcstombs
Definition: stdlib.h:1013
#define INT_MAX
Definition: intsafe.h:150
_locale_t plocinfo
Definition: ismbbyte.cpp:75
size_t sizeInBytes
Definition: mbslwr.cpp:119
_Check_return_wat_ _CRTIMP errno_t __cdecl wcstombs_s(_Out_opt_ size_t *pcchConverted, _Out_writes_bytes_to_opt_(cjDstSize, *pcchConverted) char *pmbsDst, _In_ size_t cjDstSize, _In_z_ const wchar_t *pwszSrc, _In_ size_t cjMaxCount)
size_t __cdecl __wcsrtombs_utf8(char *dst, const wchar_t **src, size_t len, mbstate_t *ps, __crt_cached_ptd_host &ptd)
Definition: wcrtomb.cpp:439
#define _Inout_
Definition: no_sal2.h:162
#define _Success_(c)
Definition: no_sal2.h:84
#define _In_z_
Definition: no_sal2.h:164
#define _In_reads_or_z_(s)
Definition: no_sal2.h:174
#define _Out_writes_(s)
Definition: no_sal2.h:176
#define _Post_satisfies_(e)
Definition: no_sal2.h:66
#define _In_
Definition: no_sal2.h:158
#define L(x)
Definition: ntvdm.h:50
#define STRUNCATE
Definition: errno.h:110
#define EILSEQ
Definition: errno.h:109
#define CP_UTF8
Definition: nls.h:20
#define _countof(array)
Definition: sndvol32.h:70
int errno_t
Definition: corecrt.h:615
#define _TRUNCATE
Definition: corecrt.h:278
_In_z_ const wchar_t _In_ size_t n
Definition: wcstombs.cpp:86
int retval
Definition: wcstombs.cpp:91
BOOL defused
Definition: wcstombs.cpp:93
_In_z_ const wchar_t _In_ size_t _Inout_ __crt_cached_ptd_host & ptd
Definition: wcstombs.cpp:89
int i
Definition: wcstombs.cpp:91
_In_z_ const wchar_t * pwcs
Definition: wcstombs.cpp:85
_In_ size_t cnt
Definition: wcstombs.cpp:43
wchar_t * cp
Definition: wcstombs.cpp:45
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
#define const
Definition: zconf.h:233