ReactOS 0.4.16-dev-835-gd769f56
wctomb.cpp
Go to the documentation of this file.
1//
2// wctomb.cpp
3//
4// Copyright (c) Microsoft Corporation. All rights reserved.
5//
6// Functions to convert a wide character to the equivalent multibyte character,
7// according to the LC_CTYPE category of the current locale. The return value
8// (or *return_value, for the _s-suffixed functions) depends on the destination
9// and destination_count:
10// * If destination == nullptr && count == 0, number of bytes needed for conversion
11// * If destination != nullptr: the number of bytes used for the conversion
12// * If destination == nullptr && count > 0, the state information
13// (0 for no state dependency, 1 if a state dependent encoding)
14//
15// Historically Windows has not supported state-dependent encodings for wctomb,
16// however UTF-8 can possible require more than one input wchar_t and maintain
17// state between calls.
18//
19// The return_value pointer may be null.
20//
21#include <corecrt_internal.h>
24#include <errno.h>
25#include <limits.h>
26#include <locale.h>
27#include <stdlib.h>
28
29
31 int* const return_value,
32 char* const destination,
33 size_t const destination_count,
34 wchar_t const wchar,
35 __crt_cached_ptd_host& ptd
36 )
37{
38 // Did the caller request if this is a state dependent encoding?
39 if (!destination && destination_count > 0)
40 {
41 // Indicate do not have state-dependent encodings:
42 if (return_value != nullptr)
43 *return_value = 0;
44
45 return 0;
46 }
47
48 if (return_value)
49 *return_value = -1;
50
51 // We need to cast destination_count to int, so we make sure we are not
52 // going to truncate destination_count:
54 _locale_t const locale = ptd.get_locale();
55
56 if (locale->locinfo->_public._locale_lc_codepage == CP_UTF8)
57 {
58 // Unlike c16rtomb. wctomb/wcrtomb have no ability to process a partial code point.
59 // So, we could call c16rtomb and check for a lone surrogate or other error, or for simplicity
60 // We can instead just call c32rtomb and check for any error. I choose the latter.
62 int result = static_cast<int>(__crt_mbstring::__c32rtomb_utf8(destination, static_cast<char32_t>(wchar), &state, ptd));
63 if (return_value != nullptr)
64 {
65 *return_value = result;
66 }
67 if (result <= 4)
68 {
69 return 0;
70 }
71 else
72 {
73 return ptd.get_errno().value_or(0);
74 }
75 }
76
77 // Check for C-locale behavior, which merely casts it to char (if in range)
78 // for ASCII-ish behavior.
79 if (!locale->locinfo->locale_name[LC_CTYPE])
80 {
81 // See if the WCHAR is > ASCII-ish range
82 if (wchar > 255) // Validate high byte
83 {
84 // Too big, can't convert, clear buffer and return error
85 if (destination != nullptr && destination_count > 0)
86 {
87 memset(destination, 0, destination_count);
88 }
89
90 return ptd.get_errno().set(EILSEQ);
91 }
92
93 // ASCII-ish, just cast to a (char)
94 if (destination != nullptr)
95 {
97 *destination = static_cast<char>(wchar);
98 }
99
100 if (return_value != nullptr)
101 {
102 // casting one WCHAR emits a single char
103 *return_value = 1;
104 }
105
106 // We're done
107 return 0;
108 }
109 else
110 {
113 locale->locinfo->_public._locale_lc_codepage,
114 0,
115 &wchar,
116 1,
117 destination,
118 static_cast<int>(destination_count),
119 nullptr,
120 &default_used);
121
122 if (size == 0 || default_used)
123 {
125 {
126 if (destination && destination_count > 0)
127 {
128 memset(destination, 0, destination_count);
129 }
130
131 _UCRT_VALIDATE_RETURN_ERRCODE(ptd, ("Buffer too small", 0), ERANGE);
132 }
133
134 return ptd.get_errno().set(EILSEQ);
135 }
136
137 if (return_value)
138 {
139 *return_value = size;
140 }
141
142 return 0;
143 }
144
145 // The last thing was an if/else, so we already returned.
146}
147
148extern "C" int __cdecl _wctomb_s_l(
149 int* const return_value,
150 char* const destination,
151 size_t const destination_count,
152 wchar_t const wchar,
153 _locale_t const locale
154 )
155{
156 __crt_cached_ptd_host ptd(locale);
157 return _wctomb_internal(return_value, destination, destination_count, wchar, ptd);
158}
159
161 int* const return_value,
162 char* const destination,
163 size_t const destination_count,
164 wchar_t const wchar
165 )
166{
167 __crt_cached_ptd_host ptd;
168 return _wctomb_internal(return_value, destination, destination_count, wchar, ptd);
169}
170
171extern "C" int __cdecl _wctomb_l(
172 char* const destination,
173 wchar_t const wchar,
174 _locale_t const locale
175 )
176{
177 __crt_cached_ptd_host ptd(locale);
178
179 int return_value{};
180 errno_t const e = _wctomb_internal(
181 &return_value,
182 destination,
183 ptd.get_locale()->locinfo->_public._locale_mb_cur_max,
184 wchar,
185 ptd);
186
187 if (e != 0)
188 {
189 return -1;
190 }
191
192 return return_value;
193}
194
195// Disable the OACR error that warns that 'MB_CUR_MAX' doesn't properly constrain buffer 'destination'.
196// wctomb() doesn't take a buffer size, so the function's contract is inherently dangerous.
199
200extern "C" int __cdecl wctomb(
201 char* const destination,
202 wchar_t const wchar
203 )
204{
205 __crt_cached_ptd_host ptd;
206
207 int return_value{};
208 errno_t const e = _wctomb_internal(&return_value, destination, MB_CUR_MAX, wchar, ptd);
209 if (e != 0)
210 {
211 return -1;
212 }
213
214 return return_value;
215}
216
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
static int state
Definition: maze.c:121
Definition: _locale.h:75
#define _UCRT_VALIDATE_RETURN_ERRCODE(ptd, expr, errorcode)
_In_ size_t const _In_ int _In_ bool const _In_ unsigned const _In_ __acrt_rounding_mode const _Inout_ __crt_cached_ptd_host & ptd
Definition: cvt.cpp:355
#define ERROR_INSUFFICIENT_BUFFER
Definition: dderror.h:10
unsigned int BOOL
Definition: ntddk_ex.h:94
GLsizeiptr size
Definition: glext.h:5919
GLuint64EXT * result
Definition: glext.h:11304
#define MB_CUR_MAX
Definition: ctype.h:624
#define LC_CTYPE
Definition: locale.h:19
#define INT_MAX
Definition: intsafe.h:150
#define e
Definition: ke_i.h:82
int disable
Definition: msacm.c:1365
size_t __cdecl __c32rtomb_utf8(char *s, char32_t c32, mbstate_t *ps, __crt_cached_ptd_host &ptd)
Definition: c32rtomb.cpp:21
static calc_node_t * pop(void)
Definition: rpn_ieee.c:90
static void push(calc_node_t *op)
Definition: rpn_ieee.c:113
#define EILSEQ
Definition: errno.h:109
#define CP_UTF8
Definition: nls.h:20
#define __pragma(x)
Definition: debug.h:260
#define warning(s)
Definition: debug.h:83
#define memset(x, y, z)
Definition: compat.h:39
#define __WARNING_POTENTIAL_BUFFER_OVERFLOW_HIGH_PRIORITY
Definition: suppress.h:450
#define wctomb(cp, wc)
Definition: wchar.h:161
int errno_t
Definition: corecrt.h:615
size_t const wchar_t const wchar
Definition: wcrtomb.cpp:53
size_t const destination_count
Definition: wcrtomb.cpp:52
BOOL default_used
Definition: wcrtomb.cpp:112
errno_t __cdecl wctomb_s(int *const return_value, char *const destination, size_t const destination_count, wchar_t const wchar)
Definition: wctomb.cpp:160
int __cdecl _wctomb_l(char *const destination, wchar_t const wchar, _locale_t const locale)
Definition: wctomb.cpp:171
int __cdecl _wctomb_s_l(int *const return_value, char *const destination, size_t const destination_count, wchar_t const wchar, _locale_t const locale)
Definition: wctomb.cpp:148
int __cdecl _wctomb_internal(int *const return_value, char *const destination, size_t const destination_count, wchar_t const wchar, __crt_cached_ptd_host &ptd)
Definition: wctomb.cpp:30
DWORD WINAPI GetLastError(void)
Definition: except.c:1042