ReactOS 0.4.16-dev-853-g88d9285
fcvt.cpp
Go to the documentation of this file.
1//
2// fcvt.cpp
3//
4// Copyright (c) Microsoft Corporation. All rights reserved.
5//
6// Defines the _ecvt and _fcvt families of functions.
7//
8#include <corecrt_internal.h>
12#include <minmax.h>
13#include <stdlib.h>
14
15
16
17// Tries to get the pre-thread conversion buffer; returns nullptr on failure.
18static char* __cdecl try_get_ptd_buffer(__crt_cached_ptd_host& ptd)
19{
20 __acrt_ptd* const raw_ptd = ptd.get_raw_ptd_noexit();
21 if (!raw_ptd)
22 {
23 return nullptr;
24 }
25
26 if (raw_ptd->_cvtbuf)
27 {
28 return raw_ptd->_cvtbuf;
29 }
30
31 raw_ptd->_cvtbuf = _malloc_crt_t(char, _CVTBUFSIZE).detach();
32
33 return raw_ptd->_cvtbuf;
34}
35
36
37
38// An internal helper that wraps the call to convert the STRFLT to a string and
39// updates all of the data that is used by its callers.
42 size_t const buffer_count,
43 STRFLT const strflt,
44 int const requested_digits,
45 int* const decimal_point,
46 int* const sign,
47 __crt_cached_ptd_host& ptd
48 ) throw()
49{
50 // Make sure we don't overflow the buffer. If the user asks for more digits
51 // than the buffer can handle, truncate it to the maximum size allowed in
52 // the buffer. The maximum size is two less than the buffer size because we
53 // use one character for overflow and one for the null terminator.
54 size_t const minimum_buffer_count = static_cast<size_t>((requested_digits > 0 ? requested_digits : 0) + 2);
55
56 _UCRT_VALIDATE_RETURN_ERRCODE(ptd, buffer_count >= minimum_buffer_count, ERANGE);
57
58 int const capped_digits = min(requested_digits, static_cast<int>(buffer_count - 2));
59
61
62 if (e != 0)
63 {
64 return ptd.get_errno().set(e);
65 }
66
67 *sign = strflt->sign == '-' ? 1 : 0;
68 *decimal_point = strflt->decpt;
69
70 return 0;
71}
72
73
74
75// The _fcvt functions, like the _ecvt functions, convert a floating point value
76// to a narrow character string. The functions prepare the data for the Fortran
77// F-format with the number of digits following the decimal point specified by
78// requested_digits. The position of the decimal point is returned indirectly
79// through *decimal_point. The correct digit for Fortran F-format is rounded.
80//
81// These functions update either (a) the user-provided string (_s-suffixed
82// function) or (b) the per-thread conversion buffer. The _s-suffixed
83// function returns zero on success, or an error code on failure. The
84// *decimal_point and *sign values are updated with the results of the
85// conversion.
87 char* const buffer,
88 size_t const buffer_count,
89 double const value,
90 int const requested_digits,
91 int* const decimal_point,
92 int* const sign,
93 __crt_cached_ptd_host& ptd
94 )
95{
99 _UCRT_VALIDATE_RETURN_ERRCODE(ptd, decimal_point != nullptr, EINVAL);
101
102 char result_string[_CVTBUFSIZE + 1];
103
104 _strflt strflt{};
106 reinterpret_cast<_CRT_DOUBLE const&>(value),
107 _countof(result_string),
109 &strflt,
110 result_string,
111 _countof(result_string));
112
113 int const actual_digits = strflt.decpt + requested_digits;
114
115 bool const buffer_insufficiently_large =
116 requested_digits > 0 && strflt.decpt > 0 &&
117 actual_digits < requested_digits;
118
119 int const capped_digits = buffer_insufficiently_large ? INT_MAX : actual_digits;
120
121 return internal_to_string(buffer, buffer_count, &strflt, capped_digits, decimal_point, sign, ptd);
122}
123
125 char* const buffer,
126 size_t const buffer_count,
127 double const value,
128 int const requested_digits,
129 int* const decimal_point,
130 int* const sign
131 )
132{
133 __crt_cached_ptd_host ptd;
134 return _fcvt_s_internal(buffer, buffer_count, value, requested_digits, decimal_point, sign, ptd);
135}
136
138 double const value,
139 int const requested_digits,
140 int* const decimal_point,
141 int* const sign,
142 __crt_cached_ptd_host& ptd
143 )
144{
145 char* const buffer = try_get_ptd_buffer(ptd);
146 if (!buffer)
147 {
148 return nullptr;
149 }
150
151 char result_string[_CVTBUFSIZE + 1];
152
153 _strflt strflt{};
155 reinterpret_cast<_CRT_DOUBLE const&>(value),
156 _countof(result_string),
158 &strflt,
159 result_string,
160 _countof(result_string));
161
162 // Make sure we don't overflow the buffer. If the user asks for more digits
163 // than the buffer can handle, truncate it to the maximum size allowed in
164 // the buffer. The maximum size is two less than the buffer size because we
165 // use one character for overflow and one for the null terminator.
166 int const capped_digits = min(requested_digits, _CVTBUFSIZE - 2 - strflt.decpt);
167
168 errno_t const status = _fcvt_s_internal(buffer, _CVTBUFSIZE, value, capped_digits, decimal_point, sign, ptd);
169 if (status != 0)
170 {
171 return nullptr;
172 }
173
174 return buffer;
175}
176
177extern "C" char* __cdecl _fcvt(
178 double const value,
179 int const requested_digits,
180 int* const decimal_point,
181 int* const sign
182 )
183{
184 __crt_cached_ptd_host ptd;
185 return _fcvt_internal(value, requested_digits, decimal_point, sign, ptd);
186}
187
188
189// The _ecvt functions, which convert a floating point value to a string. The
190// position of the decimal point relative to the beginning of the string is
191// stored indirectly through the decimal_point argument, where a negative value
192// means that the decimal point is to the left of the returned digits. If the
193// sign of the result is negative, the word pointed to by sign is nonzero;
194// otherwise it is zero. The low order digit is rounded.
195//
196// These functions update either (a) the user-provided string (_s-suffixed
197// function) or (b) the per-thread conversion buffer. The _s-suffixed
198// function returns zero on success, or an error code on failure. The
199// *decimal_point and *sign values are updated with the results of the
200// conversion.
202 char* const buffer,
203 size_t const buffer_count,
204 double const value,
205 int const requested_digits,
206 int* const decimal_point,
207 int* const sign,
208 __crt_cached_ptd_host& ptd
209 )
210{
214 _UCRT_VALIDATE_RETURN_ERRCODE(ptd, decimal_point != nullptr, EINVAL);
216
217 char result_string[_CVTBUFSIZE + 1];
218
219 _strflt strflt{};
221 reinterpret_cast<_CRT_DOUBLE const&>(value),
222 _countof(result_string),
224 &strflt,
225 result_string,
226 _countof(result_string));
227
228 errno_t const e = internal_to_string(buffer, buffer_count, &strflt, requested_digits, decimal_point, sign, ptd);
229
230 // Make sure we don't overflow the buffer. If the user asks for more digits
231 // than the buffer can handle, truncate it to the maximum size allowed in
232 // the buffer. The maximum size is two less than the buffer size because we
233 // use one character for overflow and one for the null terminator.
234 int const capped_digits = min(requested_digits, static_cast<int>(buffer_count - 2));
235
236 // The conversion function occasionally returns an extra char in the buffer:
237 if (capped_digits >= 0 && buffer[capped_digits])
238 {
239 buffer[capped_digits] = '\0';
240 }
241
242 return e;
243}
244
246 char* const buffer,
247 size_t const buffer_count,
248 double const value,
249 int const requested_digits,
250 int* const decimal_point,
251 int* const sign
252 )
253{
254 __crt_cached_ptd_host ptd;
255 return _ecvt_s_internal(buffer, buffer_count, value, requested_digits, decimal_point, sign, ptd);
256}
257
259 double const value,
260 int const requested_digits,
261 int* const decimal_point,
262 int* const sign,
263 __crt_cached_ptd_host& ptd
264 )
265{
266 char* const buffer = try_get_ptd_buffer(ptd);
267 if (!buffer)
268 {
269 return nullptr;
270 }
271
272 // Make sure we don't overflow the buffer. If the user asks for more digits
273 // than the buffer can handle, truncate it to the maximum size allowed in
274 // the buffer. The maximum size is two less than the buffer size because we
275 // use one character for overflow and one for the null terminator.
276 int const capped_digits = min(requested_digits, _CVTBUFSIZE - 2);
277
278 errno_t const e = _ecvt_s_internal(buffer, _CVTBUFSIZE, value, capped_digits, decimal_point, sign, ptd);
279 if (e != 0)
280 {
281 return nullptr;
282 }
283
284 return buffer;
285}
286
287extern "C" char* __cdecl _ecvt(
288 double const value,
289 int const requested_digits,
290 int* const decimal_point,
291 int* const sign
292 )
293{
294 __crt_cached_ptd_host ptd;
295 return _ecvt_internal(value, requested_digits, decimal_point, sign, ptd);
296}
errno_t __cdecl __acrt_fp_strflt_to_string(char *const buffer, size_t const buffer_count, int digits, STRFLT const pflt, __acrt_has_trailing_digits const trailing_digits, __acrt_rounding_mode const rounding_mode, __crt_cached_ptd_host &ptd)
Definition: _fptostr.cpp:104
#define EINVAL
Definition: acclib.h:90
#define ERANGE
Definition: acclib.h:92
#define __cdecl
Definition: accygwin.h:79
__acrt_has_trailing_digits __cdecl __acrt_fltout(_CRT_DOUBLE value, unsigned const precision, __acrt_precision_style const precision_style, STRFLT const flt, char *const result, size_t const result_count)
Definition: cfout.cpp:315
#define _UCRT_VALIDATE_RETURN_ERRCODE(ptd, expr, errorcode)
#define _RESET_STRING(_String, _Size)
_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
static char *__cdecl _fcvt_internal(double const value, int const requested_digits, int *const decimal_point, int *const sign, __crt_cached_ptd_host &ptd)
Definition: fcvt.cpp:137
char *__cdecl _fcvt(double const value, int const requested_digits, int *const decimal_point, int *const sign)
Definition: fcvt.cpp:177
static char *__cdecl try_get_ptd_buffer(__crt_cached_ptd_host &ptd)
Definition: fcvt.cpp:18
static char *__cdecl _ecvt_internal(double const value, int const requested_digits, int *const decimal_point, int *const sign, __crt_cached_ptd_host &ptd)
Definition: fcvt.cpp:258
static errno_t __cdecl internal_to_string(_Out_writes_z_(buffer_count) char *const buffer, size_t const buffer_count, STRFLT const strflt, int const requested_digits, int *const decimal_point, int *const sign, __crt_cached_ptd_host &ptd)
Definition: fcvt.cpp:40
errno_t __cdecl _ecvt_s(char *const buffer, size_t const buffer_count, double const value, int const requested_digits, int *const decimal_point, int *const sign)
Definition: fcvt.cpp:245
static errno_t __cdecl _fcvt_s_internal(char *const buffer, size_t const buffer_count, double const value, int const requested_digits, int *const decimal_point, int *const sign, __crt_cached_ptd_host &ptd)
Definition: fcvt.cpp:86
errno_t __cdecl _fcvt_s(char *const buffer, size_t const buffer_count, double const value, int const requested_digits, int *const decimal_point, int *const sign)
Definition: fcvt.cpp:124
char *__cdecl _ecvt(double const value, int const requested_digits, int *const decimal_point, int *const sign)
Definition: fcvt.cpp:287
static errno_t __cdecl _ecvt_s_internal(char *const buffer, size_t const buffer_count, double const value, int const requested_digits, int *const decimal_point, int *const sign, __crt_cached_ptd_host &ptd)
Definition: fcvt.cpp:201
GLuint buffer
Definition: glext.h:5915
#define _CVTBUFSIZE
Definition: stdlib.h:1050
#define INT_MAX
Definition: intsafe.h:150
#define e
Definition: ke_i.h:82
#define sign(x)
Definition: mapdesc.cc:613
#define min(a, b)
Definition: monoChain.cc:55
#define _Out_writes_z_(s)
Definition: no_sal2.h:180
#define _countof(array)
Definition: sndvol32.h:70
Definition: ps.c:97
int errno_t
Definition: corecrt.h:615
Definition: pdh_main.c:96
size_t const buffer_count
Definition: xtoa.cpp:36
#define const
Definition: zconf.h:233