VirtualBox

source: vbox/trunk/src/VBox/Runtime/common/string/strtofloat.cpp@ 96170

Last change on this file since 96170 was 96170, checked in by vboxsync, 3 years ago

IPRT: Doxygen fixes in strtonum.cpp and strtofloat.cpp. bugref:20261

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 45.0 KB
Line 
1/* $Id: strtofloat.cpp 96170 2022-08-12 12:23:56Z vboxsync $ */
2/** @file
3 * IPRT - String To Floating Point Conversion.
4 */
5
6/*
7 * Copyright (C) 2006-2022 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.215389.xyz. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27
28/*********************************************************************************************************************************
29* Header Files *
30*********************************************************************************************************************************/
31#include <iprt/string.h>
32#include "internal/iprt.h"
33
34#include <iprt/asm.h>
35#include <iprt/assert.h>
36#include <iprt/ctype.h> /* needed for RT_C_IS_DIGIT */
37#include <iprt/err.h>
38
39#include <float.h>
40#include <math.h>
41#if !defined(_MSC_VER) || !defined(IPRT_NO_CRT) /** @todo fix*/
42# include <fenv.h>
43#endif
44
45#if defined(SOFTFLOAT_FAST_INT64) && !defined(RT_COMPILER_WITH_128BIT_LONG_DOUBLE) /** @todo better softfloat indicator? */
46# define USE_SOFTFLOAT /* for scaling by power of 10 */
47#endif
48#ifdef USE_SOFTFLOAT
49# include <softfloat.h>
50#endif
51
52
53/*********************************************************************************************************************************
54* Structures and Typedefs *
55*********************************************************************************************************************************/
56typedef struct FLOATUNION
57{
58#ifdef RT_COMPILER_WITH_128BIT_LONG_DOUBLE
59 RTFLOAT128U lrd;
60#elif defined(RT_COMPILER_WITH_80BIT_LONG_DOUBLE)
61 RTFLOAT80U2 lrd;
62#endif
63 RTFLOAT64U rd;
64 RTFLOAT32U r;
65} FLOATUNION;
66
67#define RET_TYPE_FLOAT 0
68#define RET_TYPE_DOUBLE 1
69#define RET_TYPE_LONG_DOUBLE 2
70
71#ifdef RT_COMPILER_WITH_128BIT_LONG_DOUBLE
72typedef RTFLOAT128U LONG_DOUBLE_U_T;
73typedef __uint128_t UINT_MANTISSA_T;
74# define UINT_MANTISSA_T_BITS 128
75#elif defined(RT_COMPILER_WITH_80BIT_LONG_DOUBLE)
76typedef RTFLOAT80U2 LONG_DOUBLE_U_T;
77typedef uint64_t UINT_MANTISSA_T;
78# define UINT_MANTISSA_T_BITS 64
79#else
80typedef RTFLOAT64U LONG_DOUBLE_U_T;
81typedef uint64_t UINT_MANTISSA_T;
82# define UINT_MANTISSA_T_BITS 64
83#endif
84
85
86/*********************************************************************************************************************************
87* Global Variables *
88*********************************************************************************************************************************/
89/* in strtonum.cpp */
90extern const unsigned char g_auchDigits[256];
91
92#define DIGITS_ZERO_TERM 254
93#define DIGITS_COLON 253
94#define DIGITS_SPACE 252
95#define DIGITS_DOT 251
96
97#if 0
98/** Maximum exponent value in the binary representation for a RET_TYPE_XXX. */
99static const int32_t g_iMaxExp[3] =
100{
101 RTFLOAT32U_EXP_MAX - 1 - RTFLOAT32U_EXP_BIAS,
102 RTFLOAT64U_EXP_MAX - 1 - RTFLOAT64U_EXP_BIAS,
103#if defined(RT_COMPILER_WITH_128BIT_LONG_DOUBLE)
104 RTFLOAT128U_EXP_MAX - 1 - RTFLOAT128U_EXP_BIAS,
105#elif defined(RT_COMPILER_WITH_80BIT_LONG_DOUBLE)
106 RTFLOAT80U_EXP_MAX - 1 - RTFLOAT80U_EXP_BIAS,
107#else
108 RTFLOAT64U_EXP_MAX - 1 - RTFLOAT64U_EXP_BIAS,
109#endif
110};
111
112/** Minimum exponent value in the binary representation for a RET_TYPE_XXX. */
113static const int32_t g_iMinExp[3] =
114{
115 1 - RTFLOAT32U_EXP_BIAS,
116 1 - RTFLOAT64U_EXP_BIAS,
117#if defined(RT_COMPILER_WITH_128BIT_LONG_DOUBLE)
118 1 - RTFLOAT128U_EXP_BIAS,
119#elif defined(RT_COMPILER_WITH_80BIT_LONG_DOUBLE)
120 1 - RTFLOAT80U_EXP_BIAS,
121#else
122 1 - RTFLOAT64U_EXP_BIAS,
123#endif
124};
125#endif
126
127/** NaN fraction value masks. */
128static uint64_t const g_fNanMasks[3] =
129{
130 RT_BIT_64(RTFLOAT32U_FRACTION_BITS - 1) - 1, /* 22=quiet(1) / silent(0) */
131 RT_BIT_64(RTFLOAT64U_FRACTION_BITS - 1) - 1, /* 51=quiet(1) / silent(0) */
132#if defined(RT_COMPILER_WITH_128BIT_LONG_DOUBLE)
133 RT_BIT_64(RTFLOAT128U_FRACTION_BITS - 1 - 64) - 1, /* 111=quiet(1) / silent(0) */
134#elif defined(RT_COMPILER_WITH_80BIT_LONG_DOUBLE)
135 RT_BIT_64(RTFLOAT80U_FRACTION_BITS - 1) - 1, /* bit 63=NaN; bit 62=quiet(1) / silent(0) */
136#else
137 RT_BIT_64(RTFLOAT64U_FRACTION_BITS - 1) - 1,
138#endif
139};
140
141#if 0 /* unused */
142# if defined(RT_COMPILER_WITH_80BIT_LONG_DOUBLE) || defined(RT_COMPILER_WITH_128BIT_LONG_DOUBLE)
143static const long double g_lrdPowerMin10 = 1e4931L;
144static const long double g_lrdPowerMax10 = 1e4932L;
145# else
146static const long double g_lrdPowerMin10 = 1e307L;
147static const long double g_lrdPowerMax10 = 1e308L;
148# endif
149#endif
150
151#ifdef USE_SOFTFLOAT
152/** SoftFloat: Power of 10 table using 128-bit floating point.
153 *
154 * @code
155 softfloat_state_t SoftState = SOFTFLOAT_STATE_INIT_DEFAULTS();
156 float128_t Power10;
157 ui32_to_f128M(10, &Power10, &SoftState);
158 for (unsigned iBit = 0; iBit < 13; iBit++)
159 {
160 RTAssertMsg2(" { { UINT64_C(%#018RX64), UINT64_C(%#018RX64) } }, %c* 1e%u (%RU64) *%c\n", Power10.v[0], Power10.v[1],
161 '/', RT_BIT_32(iBit), f128M_to_ui64(&Power10, softfloat_round_near_even, false, &SoftState), '/');
162 f128M_mul(&Power10, &Power10, &Power10, &SoftState);
163 }
164 @endcode */
165static const float128_t g_ar128Power10[] =
166{
167 { { UINT64_C(0x0000000000000000), UINT64_C(0x4002400000000000) } }, /* 1e1 (10) */
168 { { UINT64_C(0x0000000000000000), UINT64_C(0x4005900000000000) } }, /* 1e2 (100) */
169 { { UINT64_C(0x0000000000000000), UINT64_C(0x400c388000000000) } }, /* 1e4 (10000) */
170 { { UINT64_C(0x0000000000000000), UINT64_C(0x40197d7840000000) } }, /* 1e8 (100000000) */
171 { { UINT64_C(0x0000000000000000), UINT64_C(0x40341c37937e0800) } }, /* 1e16 (10000000000000000) */
172 { { UINT64_C(0x6b3be04000000000), UINT64_C(0x40693b8b5b5056e1) } }, /* 1e32 (18446744073709551615) */
173 { { UINT64_C(0x4daa797ed6e38ed6), UINT64_C(0x40d384f03e93ff9f) } }, /* 1e64 (18446744073709551615) */
174 { { UINT64_C(0x19bf8cde66d86d61), UINT64_C(0x41a827748f9301d3) } }, /* 1e128 (18446744073709551615) */
175 { { UINT64_C(0xbd1bbb77203731fb), UINT64_C(0x435154fdd7f73bf3) } }, /* 1e256 (18446744073709551615) */
176 { { UINT64_C(0x238d98cab8a97899), UINT64_C(0x46a3c633415d4c1d) } }, /* 1e512 (18446744073709551615) */
177 { { UINT64_C(0x182eca1a7a51e308), UINT64_C(0x4d4892eceb0d02ea) } }, /* 1e1024 (18446744073709551615) */
178 { { UINT64_C(0xbbc94e9a519c651e), UINT64_C(0x5a923d1676bb8a7a) } }, /* 1e2048 (18446744073709551615) */
179 { { UINT64_C(0x2f3592982a7f005a), UINT64_C(0x752588c0a4051441) } }, /* 1e4096 (18446744073709551615) */
180 /* INF */
181};
182
183/** SoftFloat: Initial value for power of 10 scaling.
184 * This deals with the first 32 powers of 10, covering the a full 64-bit
185 * mantissa and a small exponent w/o needing to make use of g_ar128Power10.
186 *
187 * @code
188 softfloat_state_t SoftState = SOFTFLOAT_STATE_INIT_DEFAULTS();
189 float128_t Num10;
190 ui32_to_f128M(10, &Num10, &SoftState);
191 float128_t Power10;
192 ui32_to_f128M(1, &Power10, &SoftState);
193 for (unsigned cTimes = 0; cTimes < 32; cTimes++)
194 {
195 RTAssertMsg2(" { { UINT64_C(%#018RX64), UINT64_C(%#018RX64) } }, %c* 1e%u (%RU64) *%c\n", Power10.v[0], Power10.v[1],
196 '/', cTimes, f128M_to_ui64(&Power10, softfloat_round_near_even, false, &SoftState), '/');
197 f128M_mul(&Power10, &Num10, &Power10, &SoftState);
198 }
199 @endcode */
200static const float128_t g_ar128Power10Initial[] =
201{
202 { { UINT64_C(0x0000000000000000), UINT64_C(0x3fff000000000000) } }, /* 1e0 (1) */
203 { { UINT64_C(0x0000000000000000), UINT64_C(0x4002400000000000) } }, /* 1e1 (10) */
204 { { UINT64_C(0x0000000000000000), UINT64_C(0x4005900000000000) } }, /* 1e2 (100) */
205 { { UINT64_C(0x0000000000000000), UINT64_C(0x4008f40000000000) } }, /* 1e3 (1000) */
206 { { UINT64_C(0x0000000000000000), UINT64_C(0x400c388000000000) } }, /* 1e4 (10000) */
207 { { UINT64_C(0x0000000000000000), UINT64_C(0x400f86a000000000) } }, /* 1e5 (100000) */
208 { { UINT64_C(0x0000000000000000), UINT64_C(0x4012e84800000000) } }, /* 1e6 (1000000) */
209 { { UINT64_C(0x0000000000000000), UINT64_C(0x4016312d00000000) } }, /* 1e7 (10000000) */
210 { { UINT64_C(0x0000000000000000), UINT64_C(0x40197d7840000000) } }, /* 1e8 (100000000) */
211 { { UINT64_C(0x0000000000000000), UINT64_C(0x401cdcd650000000) } }, /* 1e9 (1000000000) */
212 { { UINT64_C(0x0000000000000000), UINT64_C(0x40202a05f2000000) } }, /* 1e10 (10000000000) */
213 { { UINT64_C(0x0000000000000000), UINT64_C(0x402374876e800000) } }, /* 1e11 (100000000000) */
214 { { UINT64_C(0x0000000000000000), UINT64_C(0x4026d1a94a200000) } }, /* 1e12 (1000000000000) */
215 { { UINT64_C(0x0000000000000000), UINT64_C(0x402a2309ce540000) } }, /* 1e13 (10000000000000) */
216 { { UINT64_C(0x0000000000000000), UINT64_C(0x402d6bcc41e90000) } }, /* 1e14 (100000000000000) */
217 { { UINT64_C(0x0000000000000000), UINT64_C(0x4030c6bf52634000) } }, /* 1e15 (1000000000000000) */
218 { { UINT64_C(0x0000000000000000), UINT64_C(0x40341c37937e0800) } }, /* 1e16 (10000000000000000) */
219 { { UINT64_C(0x0000000000000000), UINT64_C(0x40376345785d8a00) } }, /* 1e17 (100000000000000000) */
220 { { UINT64_C(0x0000000000000000), UINT64_C(0x403abc16d674ec80) } }, /* 1e18 (1000000000000000000) */
221 { { UINT64_C(0x0000000000000000), UINT64_C(0x403e158e460913d0) } }, /* 1e19 (10000000000000000000) */
222 { { UINT64_C(0x0000000000000000), UINT64_C(0x40415af1d78b58c4) } }, /* 1e20 (18446744073709551615) */
223 { { UINT64_C(0x0000000000000000), UINT64_C(0x4044b1ae4d6e2ef5) } }, /* 1e21 (18446744073709551615) */
224 { { UINT64_C(0x2000000000000000), UINT64_C(0x40480f0cf064dd59) } }, /* 1e22 (18446744073709551615) */
225 { { UINT64_C(0x6800000000000000), UINT64_C(0x404b52d02c7e14af) } }, /* 1e23 (18446744073709551615) */
226 { { UINT64_C(0x4200000000000000), UINT64_C(0x404ea784379d99db) } }, /* 1e24 (18446744073709551615) */
227 { { UINT64_C(0x0940000000000000), UINT64_C(0x405208b2a2c28029) } }, /* 1e25 (18446744073709551615) */
228 { { UINT64_C(0x4b90000000000000), UINT64_C(0x40554adf4b732033) } }, /* 1e26 (18446744073709551615) */
229 { { UINT64_C(0x1e74000000000000), UINT64_C(0x40589d971e4fe840) } }, /* 1e27 (18446744073709551615) */
230 { { UINT64_C(0x1308800000000000), UINT64_C(0x405c027e72f1f128) } }, /* 1e28 (18446744073709551615) */
231 { { UINT64_C(0x17caa00000000000), UINT64_C(0x405f431e0fae6d72) } }, /* 1e29 (18446744073709551615) */
232 { { UINT64_C(0x9dbd480000000000), UINT64_C(0x406293e5939a08ce) } }, /* 1e30 (18446744073709551615) */
233 { { UINT64_C(0x452c9a0000000000), UINT64_C(0x4065f8def8808b02) } }, /* 1e31 (18446744073709551615) */
234};
235
236#else /* !USE_SOFTFLOAT */
237/** Long Double: Power of 10 table scaling table.
238 * @note LDBL_MAX_10_EXP is 4932 for 80-bit and 308 for 64-bit type. */
239static const long double a_lrdPower10[] =
240{
241 1e1L,
242 1e2L,
243 1e4L,
244 1e8L,
245 1e16L,
246 1e32L,
247 1e64L,
248 1e128L,
249 1e256L,
250# if defined(RT_COMPILER_WITH_80BIT_LONG_DOUBLE) || defined(RT_COMPILER_WITH_128BIT_LONG_DOUBLE)
251 1e512L,
252 1e1024L,
253 1e2048L,
254 1e4096L,
255# endif
256};
257
258/** Long double: Initial value for power of 10 scaling.
259 * This deals with the first 32 powers of 10, covering the a full 64-bit
260 * mantissa and a small exponent w/o needing to make use of g_ar128Power10. */
261static const long double g_alrdPower10Initial[] =
262{
263 1e0L,
264 1e1L,
265 1e2L,
266 1e3L,
267 1e4L,
268 1e5L,
269 1e6L,
270 1e7L,
271 1e8L,
272 1e9L,
273 1e10L,
274 1e11L,
275 1e12L,
276 1e13L,
277 1e14L,
278 1e15L,
279 1e16L,
280 1e17L,
281 1e18L,
282 1e19L,
283 1e20L,
284 1e21L,
285 1e22L,
286 1e23L,
287 1e24L,
288 1e25L,
289 1e26L,
290 1e27L,
291 1e28L,
292 1e29L,
293 1e30L,
294 1e31L,
295};
296
297/* Tell the compiler that we'll mess with the FPU environment. */
298# ifdef _MSC_VER
299# pragma fenv_access(on)
300# endif
301#endif /*!USE_SOFTFLOAT */
302
303
304/**
305 * Multiply @a pVal by 10 to the power of @a iExponent10.
306 *
307 * This is currently a weak point where we might end up with rounding issues.
308 */
309static int rtStrToLongDoubleExp10(LONG_DOUBLE_U_T *pVal, int iExponent10)
310{
311 AssertReturn(iExponent10 != 0, VINF_SUCCESS);
312#ifdef USE_SOFTFLOAT
313 /* Use 128-bit precision floating point from softfloat to improve accuracy. */
314
315 softfloat_state_t SoftState = SOFTFLOAT_STATE_INIT_DEFAULTS();
316 float128_t Val;
317# ifdef RT_COMPILER_WITH_80BIT_LONG_DOUBLE
318 extFloat80M Tmp = EXTFLOAT80M_INIT(pVal->s2.uSignAndExponent, pVal->s2.uMantissa);
319 extF80M_to_f128M(&Tmp, &Val, &SoftState);
320# else
321 float64_t Tmp = { pVal->u };
322 f64_to_f128M(Tmp, &Val, &SoftState);
323# endif
324
325 /*
326 * Calculate the scaling factor. If we need to make use of the last table
327 * entry, we will do part of the scaling here to avoid overflowing Factor.
328 */
329 unsigned uAbsExp = (unsigned)RT_ABS(iExponent10);
330 AssertCompile(RT_ELEMENTS(g_ar128Power10Initial) == 32);
331 unsigned iBit = 5;
332 float128_t Factor = g_ar128Power10Initial[uAbsExp & 31];
333 uAbsExp >>= iBit;
334 while (uAbsExp != 0)
335 {
336 if (iBit < RT_ELEMENTS(g_ar128Power10))
337 {
338 if (uAbsExp & 1)
339 {
340 if (iBit < RT_ELEMENTS(g_ar128Power10) - 1)
341 f128M_mul(&Factor, &g_ar128Power10[iBit], &Factor, &SoftState);
342 else
343 {
344 /* Must do it in two steps to avoid prematurely overflowing the factor value. */
345 if (iExponent10 > 0)
346 f128M_mul(&Val, &Factor, &Val, &SoftState);
347 else
348 f128M_div(&Val, &Factor, &Val, &SoftState);
349 Factor = g_ar128Power10[iBit];
350 }
351 }
352 }
353 else if (iExponent10 < 0)
354 {
355 pVal->r = pVal->r < 0.0L ? -0.0L : +0.0L;
356 return VERR_FLOAT_UNDERFLOW;
357 }
358 else
359 {
360 pVal->r = pVal->r < 0.0L ? -INFINITY : +INFINITY;
361 return VERR_FLOAT_OVERFLOW;
362 }
363 iBit++;
364 uAbsExp >>= 1;
365 }
366
367 /*
368 * Do the scaling (or what remains).
369 */
370 if (iExponent10 > 0)
371 f128M_mul(&Val, &Factor, &Val, &SoftState);
372 else
373 f128M_div(&Val, &Factor, &Val, &SoftState);
374
375# ifdef RT_COMPILER_WITH_80BIT_LONG_DOUBLE
376 f128M_to_extF80M(&Val, &Tmp, &SoftState);
377 pVal->s2.uSignAndExponent = Tmp.signExp;
378 pVal->s2.uMantissa = Tmp.signif;
379# else
380 Tmp = f128M_to_f64(&Val, &SoftState);
381 pVal->u = Tmp.v;
382# endif
383
384 /*
385 * Check for under/overflow and return.
386 */
387 int rc;
388 if (!(SoftState.exceptionFlags & (softfloat_flag_underflow | softfloat_flag_overflow)))
389 rc = VINF_SUCCESS;
390 else if (SoftState.exceptionFlags & softfloat_flag_underflow)
391 rc = VERR_FLOAT_UNDERFLOW;
392 else
393 rc = VERR_FLOAT_OVERFLOW;
394
395#else /* !USE_SOFTFLOAT */
396# if 0
397 /*
398 * Use RTBigNum, falling back on the simple approach if we don't need the
399 * precision or run out of memory?
400 */
401 /** @todo implement RTBigNum approach */
402# endif
403
404 /*
405 * Simple approach.
406 */
407# if !defined(_MSC_VER) || !defined(IPRT_NO_CRT) /** @todo fix*/
408 fenv_t SavedFpuEnv;
409 feholdexcept(&SavedFpuEnv);
410# endif
411
412 /*
413 * Calculate the scaling factor. If we need to make use of the last table
414 * entry, we will do part of the scaling here to avoid overflowing lrdFactor.
415 */
416 AssertCompile(RT_ELEMENTS(g_alrdPower10Initial) == 32);
417 int rc = VINF_SUCCESS;
418 unsigned uAbsExp = (unsigned)RT_ABS(iExponent10);
419 long double lrdFactor = g_alrdPower10Initial[uAbsExp & 31];
420 unsigned iBit = 5;
421 uAbsExp >>= iBit;
422
423 while (uAbsExp != 0)
424 {
425 if (iBit < RT_ELEMENTS(a_lrdPower10))
426 {
427 if (uAbsExp & 1)
428 {
429 if (iBit < RT_ELEMENTS(a_lrdPower10) - 1)
430 lrdFactor *= a_lrdPower10[iBit];
431 else
432 {
433 /* Must do it in two steps to avoid prematurely overflowing the factor value. */
434 if (iExponent10 < 0)
435 pVal->r /= lrdFactor;
436 else
437 pVal->r *= lrdFactor;
438 lrdFactor = a_lrdPower10[iBit];
439 }
440 }
441 }
442 else if (iExponent10 < 0)
443 {
444 pVal->r = pVal->r < 0.0L ? -0.0L : +0.0L;
445 rc = VERR_FLOAT_UNDERFLOW;
446 break;
447 }
448 else
449 {
450 pVal->r = pVal->r < 0.0L ? -INFINITY : +INFINITY;
451 rc = VERR_FLOAT_OVERFLOW;
452 break;
453 }
454 iBit++;
455 uAbsExp >>= 1;
456 }
457
458 /*
459 * Do the scaling (or what remains).
460 */
461 if (iExponent10 < 0)
462 pVal->r /= lrdFactor;
463 else
464 pVal->r *= lrdFactor;
465
466# if !defined(_MSC_VER) || !defined(IPRT_NO_CRT) /** @todo fix*/
467 fesetenv(&SavedFpuEnv);
468# endif
469
470#endif /* !USE_SOFTFLOAT */
471 return rc;
472}
473
474
475
476/**
477 * Set @a ppszNext and check for trailing spaces & chars if @a rc is
478 * VINF_SUCCESS.
479 *
480 * @returns IPRT status code.
481 * @param psz The current input position.
482 * @param ppszNext Where to return the pointer to the end of the value.
483 * Optional.
484 * @param cchMax Number of bytes left in the string starting at @a psz.
485 * @param rc The status code to return.
486 */
487static int rtStrToLongDoubleReturnChecks(const char *psz, char **ppszNext, size_t cchMax, int rc)
488{
489 if (ppszNext)
490 *ppszNext = (char *)psz;
491
492 /* Trailing spaces/chars warning: */
493 if (rc == VINF_SUCCESS && cchMax > 0 && *psz)
494 {
495 do
496 {
497 char ch = *psz++;
498 if (ch == ' ' || ch == '\t')
499 cchMax--;
500 else
501 return ch == '\0' ? VWRN_TRAILING_SPACES : VWRN_TRAILING_CHARS;
502 } while (cchMax > 0);
503 rc = VWRN_TRAILING_SPACES;
504 }
505 return rc;
506}
507
508
509/**
510 * Set @a pRet to infinity, set @a ppszNext, and check for trailing spaces &
511 * chars if @a rc is VINF_SUCCESS.
512 *
513 * @returns IPRT status code.
514 * @param psz The current input position.
515 * @param ppszNext Where to return the pointer to the end of the value.
516 * Optional.
517 * @param cchMax Number of bytes left in the string starting at @a psz.
518 * @param fPositive Whether the infinity should be positive or negative.
519 * @param rc The status code to return.
520 * @param iRetType The target type.
521 * @param pRet Where to store the result.
522 */
523static int rtStrToLongDoubleReturnInf(const char *psz, char **ppszNext, size_t cchMax, bool fPositive,
524 int rc, unsigned iRetType, FLOATUNION *pRet)
525{
526 /*
527 * Skip to the end of long form?
528 */
529 char ch;
530 if ( cchMax >= 5
531 && ((ch = psz[0]) == 'i' || ch == 'I')
532 && ((ch = psz[1]) == 'n' || ch == 'N')
533 && ((ch = psz[2]) == 'i' || ch == 'I')
534 && ((ch = psz[3]) == 't' || ch == 'T')
535 && ((ch = psz[4]) == 'y' || ch == 'Y'))
536 {
537 psz += 5;
538 cchMax -= 5;
539 }
540
541 /*
542 * Set the return value:
543 */
544 switch (iRetType)
545 {
546 case RET_TYPE_FLOAT:
547 {
548 RTFLOAT32U const uRet = RTFLOAT32U_INIT_INF(!fPositive);
549 AssertCompile(sizeof(uRet) == sizeof(pRet->r.r));
550 pRet->r.r = uRet.r;
551 break;
552 }
553
554 case RET_TYPE_LONG_DOUBLE:
555#if defined(RT_COMPILER_WITH_80BIT_LONG_DOUBLE) || defined(RT_COMPILER_WITH_128BIT_LONG_DOUBLE)
556 {
557# if defined(RT_COMPILER_WITH_80BIT_LONG_DOUBLE)
558 RTFLOAT80U2 const uRet = RTFLOAT80U_INIT_INF(!fPositive);
559# else
560 RTFLOAT128U const uRet = RTFLOAT128U_INIT_INF(!fPositive);
561# endif
562 pRet->lrd.lrd = uRet.lrd;
563 break;
564 }
565#else
566 AssertCompile(sizeof(long double) == sizeof(pRet->rd.rd));
567 RT_FALL_THRU();
568#endif
569 case RET_TYPE_DOUBLE:
570 {
571 RTFLOAT64U const uRet = RTFLOAT64U_INIT_INF(!fPositive);
572 AssertCompile(sizeof(uRet) == sizeof(pRet->rd.rd));
573 pRet->rd.rd = uRet.rd;
574 break;
575 }
576
577 default: AssertFailedBreak();
578 }
579
580 /*
581 * Deal with whatever follows and return:
582 */
583 return rtStrToLongDoubleReturnChecks(psz, ppszNext, cchMax, rc);
584}
585
586
587/**
588 * Parses the tag of a "NaN(tag)" value.
589 *
590 * We take the tag to be a number to be put in the mantissa of the NaN, possibly
591 * prefixed by 'quiet_' or 'silent_' (all or part) to indicate the type of NaN.
592 *
593 * @returns Value found in the tag string. Caller must mask it to fit in the
594 * target format.
595 * @param pchTag The tag string to parse. Not zero terminated.
596 * @param cchTag The length of the tag string value.
597 * @param pfQuiet Where to return the type of NaN. Default is quiet.
598 * @param puHiNum Where to rturn the high 64-bits of the tag.
599 */
600static uint64_t rtStrParseNanTag(const char *pchTag, size_t cchTag, bool *pfQuiet, uint64_t *puHiNum)
601{
602 *pfQuiet = true;
603
604 /*
605 * Skip 0x - content is hexadecimal, so this is not necessary.
606 */
607 if (cchTag > 2 && pchTag[0] == '0' && (pchTag[1] == 'x' || pchTag[1] == 'X'))
608 {
609 pchTag += 2;
610 cchTag -= 2;
611 }
612
613 /*
614 * Parse the number, ignoring overflows and stopping on non-xdigit.
615 */
616 *puHiNum = 0;
617 uint64_t uRet = 0;
618 unsigned iXDigit = 0;
619 while (cchTag > 0)
620 {
621 unsigned char uch = (unsigned char)*pchTag;
622 unsigned char uchDigit = g_auchDigits[uch];
623 if (uchDigit >= 16)
624 break;
625 iXDigit++;
626 if (iXDigit >= 16)
627 *puHiNum = (*puHiNum << 4) | (uRet >> 60);
628 uRet <<= 4;
629 uRet += uchDigit;
630 pchTag++;
631 cchTag--;
632 }
633
634 /*
635 * Check for special "non-standard" quiet / signalling indicator.
636 */
637 while (cchTag > 0 && *pchTag == '_')
638 pchTag++, cchTag--;
639 if (cchTag > 0)
640 {
641 char const ch = pchTag[0];
642 if (ch == 'q' || ch == 'Q')
643 *pfQuiet = true;
644 else if (ch == 's' || ch == 'S')
645 *pfQuiet = false;
646 }
647
648 return uRet;
649}
650
651
652/**
653 * Finish parsing NaN, set @a pRet to NaN, set @a ppszNext, and check for
654 * trailing spaces & chars if @a rc is VINF_SUCCESS.
655 *
656 * @returns IPRT status code.
657 * @param psz The current input position.
658 * @param ppszNext Where to return the pointer to the end of the value.
659 * Optional.
660 * @param cchMax Number of bytes left in the string starting at @a psz.
661 * @param fPositive Whether the NaN should be positive or negative.
662 * @param iRetType The target type.
663 * @param pRet Where to store the result.
664 */
665static int rtStrToLongDoubleReturnNan(const char *psz, char **ppszNext, size_t cchMax, bool fPositive,
666 unsigned iRetType, FLOATUNION *pRet)
667{
668 /*
669 * Any NaN sub-number? E.g. NaN(1) or Nan(0x42). We'll require a closing
670 * parenthesis or we'll just ignore it.
671 */
672 bool fQuiet = true;
673 uint64_t uNum = 1;
674 uint64_t uHiNum = 0;
675 if (cchMax >= 2 && *psz == '(')
676 {
677 unsigned cch = 1;
678 char ch = '\0';
679 while (cch < cchMax && (RT_C_IS_ALNUM((ch = psz[cch])) || ch == '_'))
680 cch++;
681 if (ch == ')')
682 {
683 uNum = rtStrParseNanTag(psz + 1, cch - 1, &fQuiet, &uHiNum);
684 psz += cch + 1;
685 cchMax -= cch + 1;
686
687 Assert(iRetType < RT_ELEMENTS(g_fNanMasks));
688#if defined(RT_COMPILER_WITH_128BIT_LONG_DOUBLE)
689 if (iRetType == RET_TYPE_LONG_DOUBLE)
690 {
691 uHiNum &= g_fNanMasks[RET_TYPE_LONG_DOUBLE];
692 if (!uNum && !uHiNum)
693 uNum = 1; /* must not be zero, or it'll turn into an infinity */
694 }
695 else
696#endif
697 {
698 uNum &= g_fNanMasks[iRetType];
699 if (!uNum)
700 uNum = 1; /* must not be zero, or it'll turn into an infinity */
701 }
702 }
703 }
704
705 /*
706 * Set the return value.
707 */
708 switch (iRetType)
709 {
710 case RET_TYPE_FLOAT:
711 {
712 RTFLOAT32U const uRet = RTFLOAT32U_INIT_NAN_EX(fQuiet, !fPositive, (uint32_t)uNum);
713 pRet->r = uRet;
714 break;
715 }
716
717 case RET_TYPE_LONG_DOUBLE:
718#if defined(RT_COMPILER_WITH_80BIT_LONG_DOUBLE) || defined(RT_COMPILER_WITH_128BIT_LONG_DOUBLE)
719 {
720# if defined(RT_COMPILER_WITH_80BIT_LONG_DOUBLE)
721 RTFLOAT80U2 const uRet = RTFLOAT80U_INIT_NAN_EX(fQuiet, !fPositive, uNum);
722# else
723 RTFLOAT128U const uRet = RTFLOAT128U_INIT_NAN_EX(fQuiet, !fPositive, uHiNum, uNum);
724# endif
725 pRet->lrd = uRet;
726 break;
727 }
728#else
729 AssertCompile(sizeof(long double) == sizeof(pRet->rd.rd));
730 RT_FALL_THRU();
731#endif
732 case RET_TYPE_DOUBLE:
733 {
734 RTFLOAT64U const uRet = RTFLOAT64U_INIT_NAN_EX(fQuiet, !fPositive, uNum);
735 pRet->rd = uRet;
736 break;
737 }
738
739 default: AssertFailedBreak();
740 }
741
742 return rtStrToLongDoubleReturnChecks(psz, ppszNext, cchMax, VINF_SUCCESS);
743}
744
745
746/**
747 * Set @a pRet to zero, set @a ppszNext, and check for trailing spaces &
748 * chars if @a rc is VINF_SUCCESS.
749 *
750 * @returns IPRT status code.
751 * @param psz The current input position.
752 * @param ppszNext Where to return the pointer to the end of the value.
753 * Optional.
754 * @param cchMax Number of bytes left in the string starting at @a psz.
755 * @param rc The status code to return.
756 * @param iRetType The target type.
757 * @param pRet Where to store the result.
758 */
759static int rtStrToLongDoubleReturnZero(const char *psz, char **ppszNext, size_t cchMax, bool fPositive,
760 int rc, unsigned iRetType, FLOATUNION *pRet)
761{
762 switch (iRetType)
763 {
764 case RET_TYPE_FLOAT:
765 pRet->r.r = fPositive ? +0.0F : -0.0F;
766 break;
767
768 case RET_TYPE_LONG_DOUBLE:
769#if defined(RT_COMPILER_WITH_80BIT_LONG_DOUBLE) || defined(RT_COMPILER_WITH_128BIT_LONG_DOUBLE)
770 pRet->lrd.lrd = fPositive ? +0.0L : -0.0L;
771 break;
772#else
773 AssertCompile(sizeof(long double) == sizeof(pRet->rd.rd));
774 RT_FALL_THRU();
775#endif
776 case RET_TYPE_DOUBLE:
777 pRet->rd.rd = fPositive ? +0.0 : -0.0;
778 break;
779
780 default: AssertFailedBreak();
781 }
782
783 return rtStrToLongDoubleReturnChecks(psz, ppszNext, cchMax, rc);
784}
785
786
787/**
788 * Return overflow or underflow - setting @a pRet and @a ppszNext accordingly.
789 *
790 * @returns IPRT status code.
791 * @param psz The current input position.
792 * @param ppszNext Where to return the pointer to the end of the value.
793 * Optional.
794 * @param cchMax Number of bytes left in the string starting at @a psz.
795 * @param fPositive Whether the value should be positive or negative.
796 * @param iExponent Overflow/underflow indicator.
797 * @param iRetType The target type.
798 * @param pRet Where to store the result.
799 */
800static int rtStrToLongDoubleReturnOverflow(const char *psz, char **ppszNext, size_t cchMax, bool fPositive,
801 int32_t iExponent, unsigned iRetType, FLOATUNION *pRet)
802{
803 if (iExponent > 0)
804 return rtStrToLongDoubleReturnInf(psz, ppszNext, cchMax, fPositive, VERR_FLOAT_OVERFLOW, iRetType, pRet);
805 return rtStrToLongDoubleReturnZero(psz, ppszNext, cchMax, fPositive, VERR_FLOAT_UNDERFLOW, iRetType, pRet);
806}
807
808
809/**
810 * Returns a denormal/subnormal value.
811 *
812 * This implies that iRetType is long double, or double if they are the same,
813 * and that we should warn about underflowing.
814 */
815static int rtStrToLongDoubleReturnSubnormal(const char *psz, char **ppszNext, size_t cchMax, LONG_DOUBLE_U_T const *pVal,
816 unsigned iRetType, FLOATUNION *pRet)
817{
818#if defined(RT_COMPILER_WITH_80BIT_LONG_DOUBLE) || defined(RT_COMPILER_WITH_128BIT_LONG_DOUBLE)
819 Assert(iRetType == RET_TYPE_LONG_DOUBLE);
820 pRet->lrd = *pVal;
821#else
822 Assert(iRetType == RET_TYPE_LONG_DOUBLE || iRetType == RET_TYPE_DOUBLE);
823 pRet->rd = *pVal;
824#endif
825 RT_NOREF(iRetType);
826 return rtStrToLongDoubleReturnChecks(psz, ppszNext, cchMax, VWRN_FLOAT_UNDERFLOW);
827}
828
829
830/**
831 * Packs the given sign, mantissa, and (power of 2) exponent into the
832 * return value.
833 */
834static int rtStrToLongDoubleReturnValue(const char *psz, char **ppszNext, size_t cchMax,
835 bool fPositive, UINT_MANTISSA_T uMantissa, int32_t iExponent,
836 unsigned iRetType, FLOATUNION *pRet)
837{
838 int rc = VINF_SUCCESS;
839 switch (iRetType)
840 {
841 case RET_TYPE_FLOAT:
842 iExponent += RTFLOAT32U_EXP_BIAS;
843 if (iExponent <= 0)
844 {
845 /* Produce a subnormal value if it's within range, otherwise return zero. */
846 if (iExponent < -RTFLOAT32U_FRACTION_BITS)
847 return rtStrToLongDoubleReturnZero(psz, ppszNext, cchMax, fPositive, VERR_FLOAT_UNDERFLOW, iRetType, pRet);
848 rc = VWRN_FLOAT_UNDERFLOW;
849 uMantissa >>= -iExponent + 1;
850 iExponent = 0;
851 }
852 else if (iExponent >= RTFLOAT32U_EXP_MAX)
853 return rtStrToLongDoubleReturnInf(psz, ppszNext, cchMax, fPositive, VERR_FLOAT_OVERFLOW, iRetType, pRet);
854
855 pRet->r.s.uFraction = (uMantissa >> (UINT_MANTISSA_T_BITS - 1 - RTFLOAT32U_FRACTION_BITS))
856 & (RT_BIT_32(RTFLOAT32U_FRACTION_BITS) - 1);
857 pRet->r.s.uExponent = iExponent;
858 pRet->r.s.fSign = !fPositive;
859 break;
860
861 case RET_TYPE_LONG_DOUBLE:
862#ifdef RT_COMPILER_WITH_80BIT_LONG_DOUBLE
863# if UINT_MANTISSA_T_BITS != 64
864# error Unsupported UINT_MANTISSA_T_BITS count.
865# endif
866 iExponent += RTFLOAT80U_EXP_BIAS;
867 if (iExponent <= 0)
868 {
869 /* Produce a subnormal value if it's within range, otherwise return zero. */
870 if (iExponent < -RTFLOAT80U_FRACTION_BITS)
871 return rtStrToLongDoubleReturnZero(psz, ppszNext, cchMax, fPositive, VERR_FLOAT_UNDERFLOW, iRetType, pRet);
872 rc = VWRN_FLOAT_UNDERFLOW;
873 uMantissa >>= -iExponent + 1;
874 iExponent = 0;
875 }
876 else if (iExponent >= RTFLOAT80U_EXP_MAX)
877 return rtStrToLongDoubleReturnInf(psz, ppszNext, cchMax, fPositive, VERR_FLOAT_OVERFLOW, iRetType, pRet);
878
879 pRet->lrd.s.uMantissa = uMantissa;
880 pRet->lrd.s.uExponent = iExponent;
881 pRet->lrd.s.fSign = !fPositive;
882 break;
883#elif defined(RT_COMPILER_WITH_128BIT_LONG_DOUBLE)
884 iExponent += RTFLOAT128U_EXP_BIAS;
885 uMantissa >>= 128 - RTFLOAT128U_FRACTION_BITS;
886 if (iExponent <= 0)
887 {
888 /* Produce a subnormal value if it's within range, otherwise return zero. */
889 if (iExponent < -RTFLOAT128U_FRACTION_BITS)
890 return rtStrToLongDoubleReturnZero(psz, ppszNext, cchMax, fPositive, VERR_FLOAT_UNDERFLOW, iRetType, pRet);
891 rc = VWRN_FLOAT_UNDERFLOW;
892 uMantissa >>= -iExponent + 1;
893 iExponent = 0;
894 }
895 else if (iExponent >= RTFLOAT80U_EXP_MAX)
896 return rtStrToLongDoubleReturnInf(psz, ppszNext, cchMax, fPositive, VERR_FLOAT_OVERFLOW, iRetType, pRet);
897 pRet->lrd.s64.uFractionHi = (uint64_t)(uMantissa >> 64) & (RT_BIT_64(RTFLOAT128U_FRACTION_BITS - 64) - 1);
898 pRet->lrd.s64.uFractionLo = (uint64_t)uMantissa;
899 pRet->lrd.s64.uExponent = iExponent;
900 pRet->lrd.s64.fSign = !fPositive;
901 break;
902#else
903 AssertCompile(sizeof(long double) == sizeof(pRet->rd.rd));
904 RT_FALL_THRU();
905#endif
906 case RET_TYPE_DOUBLE:
907 iExponent += RTFLOAT64U_EXP_BIAS;
908 if (iExponent <= 0)
909 {
910 /* Produce a subnormal value if it's within range, otherwise return zero. */
911 if (iExponent < -RTFLOAT64U_FRACTION_BITS)
912 return rtStrToLongDoubleReturnZero(psz, ppszNext, cchMax, fPositive, VERR_FLOAT_UNDERFLOW, iRetType, pRet);
913 rc = VWRN_FLOAT_UNDERFLOW;
914 uMantissa >>= -iExponent + 1;
915 iExponent = 0;
916 }
917 else if (iExponent >= RTFLOAT64U_EXP_MAX)
918 return rtStrToLongDoubleReturnInf(psz, ppszNext, cchMax, fPositive, VERR_FLOAT_OVERFLOW, iRetType, pRet);
919
920 pRet->rd.s64.uFraction = (uMantissa >> (UINT_MANTISSA_T_BITS - 1 - RTFLOAT64U_FRACTION_BITS))
921 & (RT_BIT_64(RTFLOAT64U_FRACTION_BITS) - 1);
922 pRet->rd.s64.uExponent = iExponent;
923 pRet->rd.s64.fSign = !fPositive;
924 break;
925
926 default:
927 AssertFailedReturn(VERR_INTERNAL_ERROR_3);
928 }
929 return rtStrToLongDoubleReturnChecks(psz, ppszNext, cchMax, rc);
930}
931
932
933/**
934 * Worker for RTStrToLongDoubleEx, RTStrToDoubleEx and RTStrToFloatEx.
935 *
936 * @returns IPRT status code
937 * @param pszValue The string value to convert.
938 * @param ppszNext Where to return the pointer to the end of the value.
939 * Optional.
940 * @param cchMax Number of bytes left in the string starting at @a psz.
941 * @param iRetType The return type: float, double or long double.
942 * @param pRet The return value union.
943 */
944static int rtStrToLongDoubleWorker(const char *pszValue, char **ppszNext, size_t cchMax, unsigned iRetType, FLOATUNION *pRet)
945{
946 const char *psz = pszValue;
947 if (!cchMax)
948 cchMax = ~(size_t)cchMax;
949
950 /*
951 * Sign.
952 */
953 bool fPositive = true;
954 while (cchMax > 0)
955 {
956 if (*psz == '+')
957 fPositive = true;
958 else if (*psz == '-')
959 fPositive = !fPositive;
960 else
961 break;
962 psz++;
963 cchMax--;
964 }
965
966 /*
967 * Constant like "Inf", "Infinity", "NaN" or "NaN(hexstr)"?
968 */
969 /* "Inf" or "Infinity"? */
970 if (cchMax == 0)
971 return rtStrToLongDoubleReturnZero(pszValue, ppszNext, cchMax, fPositive, VERR_NO_DIGITS, iRetType, pRet);
972 if (cchMax >= 3)
973 {
974 char ch = *psz;
975 /* Inf: */
976 if (ch == 'i' || ch == 'I')
977 {
978 if ( ((ch = psz[1]) == 'n' || ch == 'N')
979 && ((ch = psz[2]) == 'f' || ch == 'F'))
980 return rtStrToLongDoubleReturnInf(psz + 3, ppszNext, cchMax - 3, fPositive, VINF_SUCCESS, iRetType, pRet);
981 }
982 /* Nan: */
983 else if (ch == 'n' || ch == 'N')
984 {
985 if ( ((ch = psz[1]) == 'a' || ch == 'A')
986 && ((ch = psz[2]) == 'n' || ch == 'N'))
987 return rtStrToLongDoubleReturnNan(psz + 3, ppszNext, cchMax - 3, fPositive, iRetType, pRet);
988 }
989 }
990
991 /*
992 * Check for hex prefix.
993 */
994#ifdef RT_COMPILER_WITH_128BIT_LONG_DOUBLE
995 unsigned cMaxDigits = 33;
996#elif defined(RT_COMPILER_WITH_80BIT_LONG_DOUBLE)
997 unsigned cMaxDigits = 19;
998#else
999 unsigned cMaxDigits = 18;
1000#endif
1001 unsigned uBase = 10;
1002 unsigned uExpDigitFactor = 1;
1003 if (cchMax >= 2 && psz[0] == '0' && (psz[1] == 'x' || psz[1] == 'X'))
1004 {
1005 cMaxDigits = 16;
1006 uBase = 16;
1007 uExpDigitFactor = 4;
1008 cchMax -= 2;
1009 psz += 2;
1010 }
1011
1012 /*
1013 * Now, parse the mantissa.
1014 */
1015#ifdef RT_COMPILER_WITH_128BIT_LONG_DOUBLE
1016 uint8_t abDigits[36];
1017#else
1018 uint8_t abDigits[20];
1019#endif
1020 unsigned cDigits = 0;
1021 unsigned cFractionDigits = 0;
1022 uint8_t fSeenNonZeroDigit = 0;
1023 bool fInFraction = false;
1024 bool fSeenDigits = false;
1025 while (cchMax > 0)
1026 {
1027 uint8_t b = g_auchDigits[(unsigned char)*psz];
1028 if (b < uBase)
1029 {
1030 fSeenDigits = true;
1031 fSeenNonZeroDigit |= b;
1032 if (fSeenNonZeroDigit)
1033 {
1034 if (cDigits < RT_ELEMENTS(abDigits))
1035 abDigits[cDigits] = b;
1036 cDigits++;
1037 cFractionDigits += fInFraction;
1038 }
1039 }
1040 else if (b == DIGITS_DOT && !fInFraction)
1041 fInFraction = true;
1042 else
1043 break;
1044 psz++;
1045 cchMax--;
1046 }
1047
1048 /* If we've seen no digits, or just a dot, return zero already. */
1049 if (!fSeenDigits)
1050 {
1051 if (fInFraction) /* '+.' => 0.0 ? */
1052 return rtStrToLongDoubleReturnZero(psz, ppszNext, cchMax, fPositive, VINF_SUCCESS, iRetType, pRet);
1053 if (uBase == 16) /* '+0x' => 0.0 & *=pszNext="x..." */
1054 return rtStrToLongDoubleReturnZero(psz - 1, ppszNext, cchMax, fPositive, VINF_SUCCESS, iRetType, pRet);
1055 /* '' and '+' -> no digits + 0.0. */
1056 return rtStrToLongDoubleReturnZero(pszValue, ppszNext, cchMax, fPositive, VERR_NO_DIGITS, iRetType, pRet);
1057 }
1058
1059 /*
1060 * Parse the exponent.
1061 * This is optional and we ignore incomplete ones like "e+".
1062 */
1063 int32_t iExponent = 0;
1064 if (cchMax >= 2) /* min "e0" */
1065 {
1066 char ch = *psz;
1067 if (uBase == 10 ? ch == 'e' || ch == 'E' : ch == 'p' || ch == 'P')
1068 {
1069 bool fExpOverflow = false;
1070 bool fPositiveExp = true;
1071 size_t off = 1;
1072 ch = psz[off];
1073 if (ch == '+' || ch == '-')
1074 {
1075 fPositiveExp = ch == '+';
1076 off++;
1077 }
1078 uint8_t b;
1079 if ( off < cchMax
1080 && (b = g_auchDigits[(unsigned char)psz[off]]) < 10)
1081 {
1082 do
1083 {
1084 int32_t const iPreviousExponent = iExponent;
1085 iExponent *= 10;
1086 iExponent += b;
1087 if (iExponent < iPreviousExponent)
1088 fExpOverflow = true;
1089 off++;
1090 } while (off < cchMax && (b = g_auchDigits[(unsigned char)psz[off]]) < 10);
1091 if (!fPositiveExp)
1092 iExponent = -iExponent;
1093 cchMax -= off;
1094 psz += off;
1095 }
1096 if (fExpOverflow || iExponent <= -65536 || iExponent >= 65536)
1097 return rtStrToLongDoubleReturnOverflow(pszValue, ppszNext, cchMax, fPositive, iExponent, iRetType, pRet);
1098 }
1099 }
1100
1101 /* If the mantissa was all zeros, we can return zero now that we're past the exponent. */
1102 if (!fSeenNonZeroDigit)
1103 return rtStrToLongDoubleReturnZero(psz, ppszNext, cchMax, fPositive, VINF_SUCCESS, iRetType, pRet);
1104
1105 /*
1106 * Adjust the expontent so we've got all digits to the left of the decimal point.
1107 */
1108 iExponent -= cFractionDigits * uExpDigitFactor;
1109
1110 /*
1111 * Drop digits we won't translate.
1112 */
1113 if (cDigits > cMaxDigits)
1114 {
1115 iExponent += (cDigits - cMaxDigits) * uExpDigitFactor;
1116 cDigits = cMaxDigits;
1117 }
1118
1119 /*
1120 * Strip least significant zero digits.
1121 */
1122 while (cDigits > 0 && abDigits[cDigits - 1] == 0)
1123 {
1124 cDigits--;
1125 iExponent += uExpDigitFactor;
1126 }
1127
1128 /*
1129 * The hexadecimal is relatively straight forward.
1130 */
1131 if (uBase == 16)
1132 {
1133 UINT_MANTISSA_T uMantissa = 0;
1134 for (unsigned iDigit = 0; iDigit < cDigits; iDigit++)
1135 {
1136 uMantissa |= (UINT_MANTISSA_T)abDigits[iDigit] << (UINT_MANTISSA_T_BITS - 4 - iDigit * 4);
1137 iExponent += 4;
1138 }
1139 Assert(uMantissa != 0);
1140
1141 /* Shift to the left till the most significant bit is 1. */
1142 if (!((uMantissa >> (UINT_MANTISSA_T_BITS - 1)) & 1))
1143 {
1144#if UINT_MANTISSA_T_BITS == 64
1145 unsigned cShift = 64 - ASMBitLastSetU64(uMantissa);
1146 uMantissa <<= cShift;
1147 iExponent -= cShift;
1148 Assert(uMantissa & RT_BIT_64(63));
1149#else
1150 do
1151 {
1152 uMantissa <<= 1;
1153 iExponent -= 1;
1154 } while (!((uMantissa >> (UINT_MANTISSA_T_BITS - 1)) & 1));
1155#endif
1156 }
1157
1158 /* Account for the 1 left of the decimal point. */
1159 iExponent--;
1160
1161 /*
1162 * Produce the return value.
1163 */
1164 return rtStrToLongDoubleReturnValue(psz, ppszNext, cchMax, fPositive, uMantissa, iExponent, iRetType, pRet);
1165 }
1166
1167 /*
1168 * For the decimal format, we'll rely on the floating point conversion of
1169 * the compiler/CPU for the mantissa.
1170 */
1171 UINT_MANTISSA_T uMantissa = 0;
1172 for (unsigned iDigit = 0; iDigit < cDigits; iDigit++)
1173 {
1174 uMantissa *= 10;
1175 uMantissa += abDigits[iDigit];
1176 }
1177 Assert(uMantissa != 0);
1178
1179 LONG_DOUBLE_U_T uTmp;
1180 uTmp.r = fPositive ? (long double)uMantissa : -(long double)uMantissa;
1181
1182 /*
1183 * Here comes the fun part, scaling it according to the power of 10 exponent.
1184 * We only need to consider overflows and underflows when scaling, when
1185 * iExponent is zero we can be sure the target type can handle the result.
1186 */
1187 if (iExponent != 0)
1188 {
1189 rtStrToLongDoubleExp10(&uTmp, iExponent);
1190#ifdef RT_COMPILER_WITH_80BIT_LONG_DOUBLE
1191 if (!RTFLOAT80U_IS_NORMAL(&uTmp))
1192#elif defined(RT_COMPILER_WITH_128BIT_LONG_DOUBLE)
1193 if (!RTFLOAT128U_IS_NORMAL(&uTmp))
1194#else
1195 if (!RTFLOAT64U_IS_NORMAL(&uTmp))
1196#endif
1197 {
1198#ifdef RT_COMPILER_WITH_80BIT_LONG_DOUBLE
1199 if (RTFLOAT80U_IS_DENORMAL(&uTmp) && iRetType == RET_TYPE_LONG_DOUBLE)
1200#elif defined(RT_COMPILER_WITH_128BIT_LONG_DOUBLE)
1201 if (RTFLOAT128U_IS_SUBNORMAL(&uTmp) && iRetType == RET_TYPE_LONG_DOUBLE)
1202#else
1203 if (RTFLOAT64U_IS_SUBNORMAL(&uTmp) && iRetType != RET_TYPE_FLOAT)
1204#endif
1205 return rtStrToLongDoubleReturnSubnormal(psz, ppszNext, cchMax, &uTmp, iRetType, pRet);
1206 return rtStrToLongDoubleReturnOverflow(psz, ppszNext, cchMax, fPositive, iExponent, iRetType, pRet);
1207 }
1208 }
1209
1210 /*
1211 * We've got a normal value in uTmp when we get here, just repack it in the
1212 * target format and return.
1213 */
1214#ifdef RT_COMPILER_WITH_80BIT_LONG_DOUBLE
1215 Assert(RTFLOAT80U_IS_NORMAL(&uTmp));
1216 if (iRetType == RET_TYPE_LONG_DOUBLE)
1217 {
1218 pRet->lrd = uTmp;
1219 return rtStrToLongDoubleReturnChecks(psz, ppszNext, cchMax, VINF_SUCCESS);
1220 }
1221 fPositive = uTmp.s.fSign;
1222 iExponent = uTmp.s.uExponent - RTFLOAT80U_EXP_BIAS;
1223 uMantissa = uTmp.s.uMantissa;
1224# if UINT_MANTISSA_T_BITS > 64
1225 uMantissa <<= UINT_MANTISSA_T_BITS - 64;
1226# endif
1227#elif defined(RT_COMPILER_WITH_128BIT_LONG_DOUBLE)
1228 Assert(RTFLOAT128U_IS_NORMAL(&uTmp));
1229 if (iRetType == RET_TYPE_LONG_DOUBLE)
1230 {
1231 pRet->lrd = uTmp;
1232 return rtStrToLongDoubleReturnChecks(psz, ppszNext, cchMax, VINF_SUCCESS);
1233 }
1234 fPositive = uTmp.s64.fSign;
1235 iExponent = uTmp.s64.uExponent - RTFLOAT128U_EXP_BIAS;
1236 uMantissa = (UINT_MANTISSA_T)uTmp.s64.uFractionHi << (UINT_MANTISSA_T_BITS - RTFLOAT128U_FRACTION_BITS - 1 + 64);
1237 uMantissa |= (UINT_MANTISSA_T)uTmp.s64.uFractionLo << (UINT_MANTISSA_T_BITS - RTFLOAT128U_FRACTION_BITS - 1);
1238 uMantissa |= (UINT_MANTISSA_T)1 << (UINT_MANTISSA_T_BITS - 1);
1239#else
1240 Assert(RTFLOAT64U_IS_NORMAL(&uTmp));
1241 if ( iRetType == RET_TYPE_DOUBLE
1242 || iRetType == RET_TYPE_LONG_DOUBLE)
1243 {
1244 pRet->rd = uTmp;
1245 return rtStrToLongDoubleReturnChecks(psz, ppszNext, cchMax, VINF_SUCCESS);
1246 }
1247 fPositive = uTmp.s64.fSign;
1248 iExponent = uTmp.s64.uExponent - RTFLOAT64U_EXP_BIAS;
1249 uMantissa = uTmp.s64.uFraction | RT_BIT_64(RTFLOAT64U_FRACTION_BITS);
1250# if UINT_MANTISSA_T_BITS > 64
1251 uMantissa <<= UINT_MANTISSA_T_BITS - 64;
1252# endif
1253#endif
1254 return rtStrToLongDoubleReturnValue(psz, ppszNext, cchMax, fPositive, uMantissa, iExponent, iRetType, pRet);
1255}
1256
1257
1258RTDECL(int) RTStrToLongDoubleEx(const char *pszValue, char **ppszNext, size_t cchMax, long double *plrd)
1259{
1260 FLOATUNION u;
1261 int rc = rtStrToLongDoubleWorker(pszValue, ppszNext, cchMax, RET_TYPE_LONG_DOUBLE, &u);
1262 if (plrd)
1263#ifdef RT_COMPILER_WITH_80BIT_LONG_DOUBLE
1264 *plrd = u.lrd.lrd;
1265#else
1266 *plrd = u.rd.rd;
1267#endif
1268 return rc;
1269}
1270
1271
1272RTDECL(int) RTStrToDoubleEx(const char *pszValue, char **ppszNext, size_t cchMax, double *prd)
1273{
1274 FLOATUNION u;
1275 int rc = rtStrToLongDoubleWorker(pszValue, ppszNext, cchMax, RET_TYPE_DOUBLE, &u);
1276 if (prd)
1277 *prd = u.rd.rd;
1278 return rc;
1279}
1280
1281
1282RTDECL(int) RTStrToFloatEx(const char *pszValue, char **ppszNext, size_t cchMax, float *pr)
1283{
1284 FLOATUNION u;
1285 int rc = rtStrToLongDoubleWorker(pszValue, ppszNext, cchMax, RET_TYPE_FLOAT, &u);
1286 if (pr)
1287 *pr = u.r.r;
1288 return rc;
1289}
1290
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette