Panda3D
Loading...
Searching...
No Matches
pstrtod.cxx
Go to the documentation of this file.
1/**
2 * PANDA 3D SOFTWARE
3 * Copyright (c) Carnegie Mellon University. All rights reserved.
4 *
5 * All use of this software is subject to the terms of the revised BSD
6 * license. You should have received a copy of this license along
7 * with this source code in a file named "LICENSE."
8 *
9 * @file pstrtod.cxx
10 * @author drose
11 * @date 2009-06-13
12 */
13
14#include "pstrtod.h"
15
16#include <ctype.h>
17#include <math.h>
18#include <limits>
19
20#ifdef _WIN32
21#define strncasecmp _strnicmp
22#endif
23
24/**
25 * This function re-implements strtod, to avoid the problems that occur when
26 * the LC_NUMERIC locale gets set to anything other than "C". Regardless of
27 * the user's locale, we need to be able to parse floating-point numbers
28 * internally understanding a "." as the decimal point.
29 */
30double
31pstrtod(const char *nptr, char **endptr) {
32 // First, skip whitespace.
33 const char *p = nptr;
34 while (isspace(*p)) {
35 ++p;
36 }
37
38 // Skip an optional leading sign.
39 char sign = '+';
40 if (*p == '+' || *p == '-') {
41 sign = *p;
42 ++p;
43 }
44
45 double value = 0.0;
46
47 if (isalpha(*p)) {
48 // Windows' implementation of strtod doesn't support "inf" or "nan", so
49 // check for those here.
50 if (strncasecmp(p, "inf", 3) == 0) {
51 p += 3;
52 if (strncasecmp(p, "inity", 5) == 0) {
53 p += 5;
54 }
55 value = std::numeric_limits<double>::infinity();
56
57 } else if (strncasecmp(p, "nan", 3) == 0) {
58 p += 3;
59
60 if (*p == 's' || *p == 'S') {
61 value = std::numeric_limits<double>::signaling_NaN();
62 ++p;
63 } else {
64 if (*p == 'q' || *p == 'Q') {
65 ++p;
66 }
67 value = std::numeric_limits<double>::quiet_NaN();
68 }
69
70 // It is optionally possible to include a character sequence between
71 // parentheses after "nan", to be passed to the new nan() function.
72 // Since it isn't supported universally, we will only accept a pair of
73 // empty parentheses.
74 if (strncmp(p, "()", 2) == 0) {
75 p += 2;
76 }
77
78 } else {
79 // Pass it up to the system implementation of strtod; perhaps it knows
80 // how to deal with this string.
81 return strtod(nptr, endptr);
82 }
83
84 } else {
85 // Start reading decimal digits to the left of the decimal point.
86 bool found_digits = false;
87 while (isdigit(*p)) {
88 value = (value * 10.0) + (*p - '0');
89 found_digits = true;
90 ++p;
91 }
92
93 if (*p == '.') {
94 ++p;
95 // Read decimal digits to the right of the decimal point.
96 double multiplicand = 0.1;
97 while (isdigit(*p)) {
98 value += (*p - '0') * multiplicand;
99 ++p;
100 found_digits = true;
101 multiplicand *= 0.1;
102 }
103 }
104
105 if (!found_digits) {
106 // Not a valid float.
107 if (endptr != nullptr) {
108 *endptr = (char *)nptr;
109 }
110 return 0.0;
111 }
112
113 if (tolower(*p) == 'e') {
114 // There's an exponent.
115 ++p;
116
117 char esign = '+';
118 if (*p == '+' || *p == '-') {
119 esign = *p;
120 ++p;
121 }
122
123 // Start reading decimal digits to the left of the decimal point.
124 double evalue = 0.0;
125 while (isdigit(*p)) {
126 evalue = (evalue * 10.0) + (*p - '0');
127 ++p;
128 }
129
130 if (esign == '-') {
131 value /= pow(10.0, evalue);
132 } else {
133 value *= pow(10.0, evalue);
134 }
135 }
136 }
137
138 if (sign == '-') {
139 value = -value;
140 }
141
142 if (endptr != nullptr) {
143 *endptr = (char *)p;
144 }
145 return value;
146}
147
148
149/**
150 * This function re-implements atof, to avoid the problems that occur when the
151 * LC_NUMERIC locale gets set to anything other than "C". Regardless of the
152 * user's locale, we need to be able to parse floating-point numbers
153 * internally understanding a "." as the decimal point.
154 */
155double
156patof(const char *str) {
157 return pstrtod(str, nullptr);
158}
double patof(const char *str)
This function re-implements atof, to avoid the problems that occur when the LC_NUMERIC locale gets se...
Definition pstrtod.cxx:156
double pstrtod(const char *nptr, char **endptr)
This function re-implements strtod, to avoid the problems that occur when the LC_NUMERIC locale gets ...
Definition pstrtod.cxx:31
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.