1 | /* |
---|
2 | FUNCTION |
---|
3 | <<wcstod>>, <<wcstof>>, <<wcstold>>, <<wcstod_l>>, <<wcstof_l>>, <<wcstold_l>>---wide char string to double or float |
---|
4 | |
---|
5 | INDEX |
---|
6 | wcstod |
---|
7 | |
---|
8 | INDEX |
---|
9 | wcstof |
---|
10 | |
---|
11 | INDEX |
---|
12 | wcstold |
---|
13 | |
---|
14 | INDEX |
---|
15 | wcstod_l |
---|
16 | |
---|
17 | INDEX |
---|
18 | wcstof_l |
---|
19 | |
---|
20 | INDEX |
---|
21 | wcstold_l |
---|
22 | |
---|
23 | INDEX |
---|
24 | _wcstod_r |
---|
25 | |
---|
26 | INDEX |
---|
27 | _wcstof_r |
---|
28 | |
---|
29 | SYNOPSIS |
---|
30 | #include <stdlib.h> |
---|
31 | double wcstod(const wchar_t *__restrict <[str]>, |
---|
32 | wchar_t **__restrict <[tail]>); |
---|
33 | float wcstof(const wchar_t *__restrict <[str]>, |
---|
34 | wchar_t **__restrict <[tail]>); |
---|
35 | long double wcstold(const wchar_t *__restrict <[str]>, |
---|
36 | wchar_t **__restrict <[tail]>); |
---|
37 | |
---|
38 | #include <stdlib.h> |
---|
39 | double wcstod_l(const wchar_t *__restrict <[str]>, |
---|
40 | wchar_t **__restrict <[tail]>, locale_t <[locale]>); |
---|
41 | float wcstof_l(const wchar_t *__restrict <[str]>, |
---|
42 | wchar_t **__restrict <[tail]>, locale_t <[locale]>); |
---|
43 | long double wcstold_l(const wchar_t *__restrict <[str]>, |
---|
44 | wchar_t **__restrict <[tail]>, |
---|
45 | locale_t <[locale]>); |
---|
46 | |
---|
47 | double _wcstod_r(void *<[reent]>, |
---|
48 | const wchar_t *<[str]>, wchar_t **<[tail]>); |
---|
49 | float _wcstof_r(void *<[reent]>, |
---|
50 | const wchar_t *<[str]>, wchar_t **<[tail]>); |
---|
51 | |
---|
52 | DESCRIPTION |
---|
53 | <<wcstod>>, <<wcstof>>, <<wcstold>> parse the wide-character string |
---|
54 | <[str]>, producing a substring which can be converted to a double, |
---|
55 | float, or long double value. The substring converted is the longest |
---|
56 | initial subsequence of <[str]>, beginning with the first non-whitespace |
---|
57 | character, that has one of these formats: |
---|
58 | .[+|-]<[digits]>[.[<[digits]>]][(e|E)[+|-]<[digits]>] |
---|
59 | .[+|-].<[digits]>[(e|E)[+|-]<[digits]>] |
---|
60 | .[+|-](i|I)(n|N)(f|F)[(i|I)(n|N)(i|I)(t|T)(y|Y)] |
---|
61 | .[+|-](n|N)(a|A)(n|N)[<(>[<[hexdigits]>]<)>] |
---|
62 | .[+|-]0(x|X)<[hexdigits]>[.[<[hexdigits]>]][(p|P)[+|-]<[digits]>] |
---|
63 | .[+|-]0(x|X).<[hexdigits]>[(p|P)[+|-]<[digits]>] |
---|
64 | The substring contains no characters if <[str]> is empty, consists |
---|
65 | entirely of whitespace, or if the first non-whitespace |
---|
66 | character is something other than <<+>>, <<->>, <<.>>, or a |
---|
67 | digit, and cannot be parsed as infinity or NaN. If the platform |
---|
68 | does not support NaN, then NaN is treated as an empty substring. |
---|
69 | If the substring is empty, no conversion is done, and |
---|
70 | the value of <[str]> is stored in <<*<[tail]>>>. Otherwise, |
---|
71 | the substring is converted, and a pointer to the final string |
---|
72 | (which will contain at least the terminating null character of |
---|
73 | <[str]>) is stored in <<*<[tail]>>>. If you want no |
---|
74 | assignment to <<*<[tail]>>>, pass a null pointer as <[tail]>. |
---|
75 | |
---|
76 | This implementation returns the nearest machine number to the |
---|
77 | input decimal string. Ties are broken by using the IEEE |
---|
78 | round-even rule. However, <<wcstof>> is currently subject to |
---|
79 | double rounding errors. |
---|
80 | |
---|
81 | <<wcstod_l>>, <<wcstof_l>>, <<wcstold_l>> are like <<wcstod>>, |
---|
82 | <<wcstof>>, <<wcstold>> but perform the conversion based on the |
---|
83 | locale specified by the locale object locale. If <[locale]> is |
---|
84 | LC_GLOBAL_LOCALE or not a valid locale object, the behaviour is |
---|
85 | undefined. |
---|
86 | |
---|
87 | The alternate functions <<_wcstod_r>> and <<_wcstof_r>> are |
---|
88 | reentrant versions of <<wcstod>> and <<wcstof>>, respectively. |
---|
89 | The extra argument <[reent]> is a pointer to a reentrancy structure. |
---|
90 | |
---|
91 | RETURNS |
---|
92 | Return the converted substring value, if any. If |
---|
93 | no conversion could be performed, 0 is returned. If the |
---|
94 | correct value is out of the range of representable values, |
---|
95 | plus or minus <<HUGE_VAL>> is returned, and <<ERANGE>> is |
---|
96 | stored in errno. If the correct value would cause underflow, 0 |
---|
97 | is returned and <<ERANGE>> is stored in errno. |
---|
98 | |
---|
99 | PORTABILITY |
---|
100 | <<wcstod>> is ANSI. |
---|
101 | <<wcstof>>, <<wcstold>> are C99. |
---|
102 | <<wcstod_l>>, <<wcstof_l>>, <<wcstold_l>> are GNU extensions. |
---|
103 | |
---|
104 | Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>, |
---|
105 | <<lseek>>, <<read>>, <<sbrk>>, <<write>>. |
---|
106 | */ |
---|
107 | |
---|
108 | /*- |
---|
109 | * Copyright (c) 2002 Tim J. Robbins |
---|
110 | * All rights reserved. |
---|
111 | * |
---|
112 | * Redistribution and use in source and binary forms, with or without |
---|
113 | * modification, are permitted provided that the following conditions |
---|
114 | * are met: |
---|
115 | * 1. Redistributions of source code must retain the above copyright |
---|
116 | * notice, this list of conditions and the following disclaimer. |
---|
117 | * 2. Redistributions in binary form must reproduce the above copyright |
---|
118 | * notice, this list of conditions and the following disclaimer in the |
---|
119 | * documentation and/or other materials provided with the distribution. |
---|
120 | * |
---|
121 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND |
---|
122 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
---|
123 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
---|
124 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
---|
125 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
---|
126 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
---|
127 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
---|
128 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
---|
129 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
---|
130 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
---|
131 | * SUCH DAMAGE. |
---|
132 | */ |
---|
133 | |
---|
134 | #include <_ansi.h> |
---|
135 | #include <errno.h> |
---|
136 | #include <stdlib.h> |
---|
137 | #include <string.h> |
---|
138 | #include <wchar.h> |
---|
139 | #include <wctype.h> |
---|
140 | #include <locale.h> |
---|
141 | #include <math.h> |
---|
142 | #include "mprec.h" |
---|
143 | |
---|
144 | double |
---|
145 | _wcstod_l (struct _reent *ptr, const wchar_t *nptr, wchar_t **endptr, |
---|
146 | locale_t loc) |
---|
147 | { |
---|
148 | static const mbstate_t initial; |
---|
149 | mbstate_t mbs; |
---|
150 | double val; |
---|
151 | char *buf, *end; |
---|
152 | const wchar_t *wcp; |
---|
153 | size_t len; |
---|
154 | |
---|
155 | while (iswspace_l(*nptr, loc)) |
---|
156 | nptr++; |
---|
157 | |
---|
158 | /* |
---|
159 | * Convert the supplied numeric wide char. string to multibyte. |
---|
160 | * |
---|
161 | * We could attempt to find the end of the numeric portion of the |
---|
162 | * wide char. string to avoid converting unneeded characters but |
---|
163 | * choose not to bother; optimising the uncommon case where |
---|
164 | * the input string contains a lot of text after the number |
---|
165 | * duplicates a lot of strtod()'s functionality and slows down the |
---|
166 | * most common cases. |
---|
167 | */ |
---|
168 | wcp = nptr; |
---|
169 | mbs = initial; |
---|
170 | if ((len = _wcsnrtombs_l(ptr, NULL, &wcp, (size_t) -1, 0, &mbs, loc)) |
---|
171 | == (size_t) -1) { |
---|
172 | if (endptr != NULL) |
---|
173 | *endptr = (wchar_t *)nptr; |
---|
174 | return (0.0); |
---|
175 | } |
---|
176 | if ((buf = _malloc_r(ptr, len + 1)) == NULL) |
---|
177 | return (0.0); |
---|
178 | mbs = initial; |
---|
179 | _wcsnrtombs_l(ptr, buf, &wcp, (size_t) -1, len + 1, &mbs, loc); |
---|
180 | |
---|
181 | /* Let strtod() do most of the work for us. */ |
---|
182 | val = _strtod_l(ptr, buf, &end, loc); |
---|
183 | |
---|
184 | /* |
---|
185 | * We only know where the number ended in the _multibyte_ |
---|
186 | * representation of the string. If the caller wants to know |
---|
187 | * where it ended, count multibyte characters to find the |
---|
188 | * corresponding position in the wide char string. |
---|
189 | */ |
---|
190 | if (endptr != NULL) { |
---|
191 | /* The only valid multibyte char in a float converted by |
---|
192 | strtod/wcstod is the radix char. What we do here is, |
---|
193 | figure out if the radix char was in the valid leading |
---|
194 | float sequence in the incoming string. If so, the |
---|
195 | multibyte float string is strlen(radix char) - 1 bytes |
---|
196 | longer than the incoming wide char string has characters. |
---|
197 | To fix endptr, reposition end as if the radix char was |
---|
198 | just one byte long. The resulting difference (end - buf) |
---|
199 | is then equivalent to the number of valid wide characters |
---|
200 | in the input string. */ |
---|
201 | len = strlen (__localeconv_l (loc)->decimal_point); |
---|
202 | if (len > 1) { |
---|
203 | char *d = strstr (buf, |
---|
204 | __localeconv_l (loc)->decimal_point); |
---|
205 | if (d && d < end) |
---|
206 | end -= len - 1; |
---|
207 | } |
---|
208 | *endptr = (wchar_t *)nptr + (end - buf); |
---|
209 | } |
---|
210 | |
---|
211 | _free_r(ptr, buf); |
---|
212 | |
---|
213 | return (val); |
---|
214 | } |
---|
215 | |
---|
216 | double |
---|
217 | _wcstod_r (struct _reent *ptr, |
---|
218 | const wchar_t *nptr, |
---|
219 | wchar_t **endptr) |
---|
220 | { |
---|
221 | return _wcstod_l (ptr, nptr, endptr, __get_current_locale ()); |
---|
222 | } |
---|
223 | |
---|
224 | float |
---|
225 | _wcstof_r (struct _reent *ptr, |
---|
226 | const wchar_t *nptr, |
---|
227 | wchar_t **endptr) |
---|
228 | { |
---|
229 | double retval = _wcstod_l (ptr, nptr, endptr, __get_current_locale ()); |
---|
230 | if (isnan (retval)) |
---|
231 | return nanf (NULL); |
---|
232 | return (float)retval; |
---|
233 | } |
---|
234 | |
---|
235 | #ifndef _REENT_ONLY |
---|
236 | |
---|
237 | double |
---|
238 | wcstod_l (const wchar_t *__restrict nptr, wchar_t **__restrict endptr, |
---|
239 | locale_t loc) |
---|
240 | { |
---|
241 | return _wcstod_l (_REENT, nptr, endptr, loc); |
---|
242 | } |
---|
243 | |
---|
244 | double |
---|
245 | wcstod (const wchar_t *__restrict nptr, wchar_t **__restrict endptr) |
---|
246 | { |
---|
247 | return _wcstod_l (_REENT, nptr, endptr, __get_current_locale ()); |
---|
248 | } |
---|
249 | |
---|
250 | float |
---|
251 | wcstof_l (const wchar_t *__restrict nptr, wchar_t **__restrict endptr, |
---|
252 | locale_t loc) |
---|
253 | { |
---|
254 | double val = _wcstod_l (_REENT, nptr, endptr, loc); |
---|
255 | if (isnan (val)) |
---|
256 | return nanf (NULL); |
---|
257 | float retval = (float) val; |
---|
258 | #ifndef NO_ERRNO |
---|
259 | if (isinf (retval) && !isinf (val)) |
---|
260 | _REENT->_errno = ERANGE; |
---|
261 | #endif |
---|
262 | return retval; |
---|
263 | } |
---|
264 | |
---|
265 | float |
---|
266 | wcstof (const wchar_t *__restrict nptr, |
---|
267 | wchar_t **__restrict endptr) |
---|
268 | { |
---|
269 | double val = _wcstod_l (_REENT, nptr, endptr, __get_current_locale ()); |
---|
270 | if (isnan (val)) |
---|
271 | return nanf (NULL); |
---|
272 | float retval = (float) val; |
---|
273 | #ifndef NO_ERRNO |
---|
274 | if (isinf (retval) && !isinf (val)) |
---|
275 | _REENT->_errno = ERANGE; |
---|
276 | #endif |
---|
277 | |
---|
278 | return retval; |
---|
279 | } |
---|
280 | |
---|
281 | #endif |
---|