PostgreSQL Source Code  git master
strtof.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * strtof.c
4  *
5  * Portions Copyright (c) 2019-2024, PostgreSQL Global Development Group
6  *
7  *
8  * IDENTIFICATION
9  * src/port/strtof.c
10  *
11  *-------------------------------------------------------------------------
12  */
13 
14 #include "c.h"
15 
16 #include <float.h>
17 #include <math.h>
18 
19 
20 /*
21  * Cygwin has a strtof() which is literally just (float)strtod(), which means
22  * we can't avoid the double-rounding problem; but using this wrapper does get
23  * us proper over/underflow checks. (Also, if they fix their strtof(), the
24  * wrapper doesn't break anything.)
25  *
26  * Test results on Mingw suggest that it has the same problem, though looking
27  * at the code I can't figure out why.
28  */
29 float
30 pg_strtof(const char *nptr, char **endptr)
31 {
32  int caller_errno = errno;
33  float fresult;
34 
35  errno = 0;
36  fresult = (strtof) (nptr, endptr);
37  if (errno)
38  {
39  /* On error, just return the error to the caller. */
40  return fresult;
41  }
42  else if ((*endptr == nptr) || isnan(fresult) ||
43  ((fresult >= FLT_MIN || fresult <= -FLT_MIN) && !isinf(fresult)))
44  {
45  /*
46  * If we got nothing parseable, or if we got a non-0 non-subnormal
47  * finite value (or NaN) without error, then return that to the caller
48  * without error.
49  */
50  errno = caller_errno;
51  return fresult;
52  }
53  else
54  {
55  /*
56  * Try again. errno is already 0 here.
57  */
58  double dresult = strtod(nptr, NULL);
59 
60  if (errno)
61  {
62  /* On error, just return the error */
63  return fresult;
64  }
65  else if ((dresult == 0.0 && fresult == 0.0) ||
66  (isinf(dresult) && isinf(fresult) && (fresult == dresult)))
67  {
68  /* both values are 0 or infinities of the same sign */
69  errno = caller_errno;
70  return fresult;
71  }
72  else if ((dresult > 0 && dresult <= FLT_MIN && (float) dresult != 0.0) ||
73  (dresult < 0 && dresult >= -FLT_MIN && (float) dresult != 0.0))
74  {
75  /* subnormal but nonzero value */
76  errno = caller_errno;
77  return (float) dresult;
78  }
79  else
80  {
81  errno = ERANGE;
82  return fresult;
83  }
84  }
85 }
float pg_strtof(const char *nptr, char **endptr)
Definition: strtof.c:30