|
@@ -17,31 +17,6 @@
|
|
|
#include <ctype.h>
|
|
#include <ctype.h>
|
|
|
#include <math.h>
|
|
#include <math.h>
|
|
|
|
|
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
|
|
-// Function: pstrnicmp
|
|
|
|
|
-// Description: This case-insenstive string compare function is used
|
|
|
|
|
-// by pstrtod, below.
|
|
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
|
|
-static int
|
|
|
|
|
-pstrnicmp(const char *s1, const char *s2, size_t n) {
|
|
|
|
|
- if (n == 0) {
|
|
|
|
|
- // Trivial equivalence.
|
|
|
|
|
- return 0;
|
|
|
|
|
- }
|
|
|
|
|
- while (tolower(*s1) == tolower(*s2)) {
|
|
|
|
|
- --n;
|
|
|
|
|
- if ((*s1) == '\0' || n == 0) {
|
|
|
|
|
- // They reached the end of the string together.
|
|
|
|
|
- return 0;
|
|
|
|
|
- }
|
|
|
|
|
- ++s1;
|
|
|
|
|
- ++s2;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // There's a difference somewhere.
|
|
|
|
|
- return (int)(unsigned char)(*s1) - (int)(unsigned char)(*s2);
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
////////////////////////////////////////////////////////////////////
|
|
|
// Function: pstrtod
|
|
// Function: pstrtod
|
|
@@ -68,90 +43,64 @@ pstrtod(const char *nptr, char **endptr) {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
double value = 0.0;
|
|
double value = 0.0;
|
|
|
-
|
|
|
|
|
- if (pstrnicmp(p, "infinity", 8) == 0) {
|
|
|
|
|
- value = INFINITY;
|
|
|
|
|
- p += 8;
|
|
|
|
|
- } else if (pstrnicmp(p, "inf", 3) == 0) {
|
|
|
|
|
- value = INFINITY;
|
|
|
|
|
- p += 3;
|
|
|
|
|
- } else if (pstrnicmp(p, "nan", 3) == 0) {
|
|
|
|
|
- value = NAN;
|
|
|
|
|
- p += 3;
|
|
|
|
|
- if (pstrnicmp(p, "0x", 2) == 0) {
|
|
|
|
|
- // The NaN code also appears in the string. Use it.
|
|
|
|
|
- static const size_t nan_code_size = 32;
|
|
|
|
|
- char nan_code[nan_code_size + 1];
|
|
|
|
|
- nan_code[0] = '0';
|
|
|
|
|
- nan_code[1] = 'x';
|
|
|
|
|
- const char *q = p + 2;
|
|
|
|
|
- int ni = 2;
|
|
|
|
|
- while (isdigit(*q) || (tolower(*q) >= 'a' && tolower(*q) <= 'f')) {
|
|
|
|
|
- if (ni < nan_code_size) {
|
|
|
|
|
- nan_code[ni] = *q;
|
|
|
|
|
- ++ni;
|
|
|
|
|
- }
|
|
|
|
|
- ++q;
|
|
|
|
|
- }
|
|
|
|
|
- nan_code[ni] = '\0';
|
|
|
|
|
- value = nan(nan_code);
|
|
|
|
|
- p = q;
|
|
|
|
|
- }
|
|
|
|
|
|
|
|
|
|
- } else {
|
|
|
|
|
|
|
+ if (isalpha(*p)) {
|
|
|
|
|
+ // For special cases like "inf" and "nan", pass these up to the
|
|
|
|
|
+ // system implementation of strtod.
|
|
|
|
|
+ return strtod(nptr, endptr);
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- // Start reading decimal digits to the left of the decimal point.
|
|
|
|
|
- bool found_digits = false;
|
|
|
|
|
|
|
+ // Start reading decimal digits to the left of the decimal point.
|
|
|
|
|
+ bool found_digits = false;
|
|
|
|
|
+ while (isdigit(*p)) {
|
|
|
|
|
+ value = (value * 10.0) + (*p - '0');
|
|
|
|
|
+ found_digits = true;
|
|
|
|
|
+ ++p;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (*p == '.') {
|
|
|
|
|
+ ++p;
|
|
|
|
|
+ // Read decimal digits to the right of the decimal point.
|
|
|
|
|
+ double multiplicand = 0.1;
|
|
|
while (isdigit(*p)) {
|
|
while (isdigit(*p)) {
|
|
|
- value = (value * 10.0) + (*p - '0');
|
|
|
|
|
|
|
+ value += (*p - '0') * multiplicand;
|
|
|
|
|
+ ++p;
|
|
|
found_digits = true;
|
|
found_digits = true;
|
|
|
|
|
+ multiplicand *= 0.1;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (!found_digits) {
|
|
|
|
|
+ // Not a valid float.
|
|
|
|
|
+ if (endptr != NULL) {
|
|
|
|
|
+ *endptr = (char *)nptr;
|
|
|
|
|
+ }
|
|
|
|
|
+ return 0.0;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (tolower(*p) == 'e') {
|
|
|
|
|
+ // There's an exponent.
|
|
|
|
|
+ ++p;
|
|
|
|
|
+
|
|
|
|
|
+ char esign = '+';
|
|
|
|
|
+ if (*p == '+' || *p == '-') {
|
|
|
|
|
+ esign = *p;
|
|
|
++p;
|
|
++p;
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
- if (*p == '.') {
|
|
|
|
|
|
|
+
|
|
|
|
|
+ // Start reading decimal digits to the left of the decimal point.
|
|
|
|
|
+ double evalue = 0.0;
|
|
|
|
|
+ while (isdigit(*p)) {
|
|
|
|
|
+ evalue = (evalue * 10.0) + (*p - '0');
|
|
|
++p;
|
|
++p;
|
|
|
- // Read decimal digits to the right of the decimal point.
|
|
|
|
|
- double multiplicand = 0.1;
|
|
|
|
|
- while (isdigit(*p)) {
|
|
|
|
|
- value += (*p - '0') * multiplicand;
|
|
|
|
|
- ++p;
|
|
|
|
|
- found_digits = true;
|
|
|
|
|
- multiplicand *= 0.1;
|
|
|
|
|
- }
|
|
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
- if (!found_digits) {
|
|
|
|
|
- // Not a valid float.
|
|
|
|
|
- if (endptr != NULL) {
|
|
|
|
|
- *endptr = (char *)nptr;
|
|
|
|
|
- }
|
|
|
|
|
- return 0.0;
|
|
|
|
|
|
|
+
|
|
|
|
|
+ if (esign == '-') {
|
|
|
|
|
+ value /= pow(evalue, 10.0);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ value *= pow(evalue, 10.0);
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
- if (tolower(*p) == 'e') {
|
|
|
|
|
- // There's an exponent.
|
|
|
|
|
- ++p;
|
|
|
|
|
-
|
|
|
|
|
- char esign = '+';
|
|
|
|
|
- if (*p == '+' || *p == '-') {
|
|
|
|
|
- esign = *p;
|
|
|
|
|
- ++p;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // Start reading decimal digits to the left of the decimal point.
|
|
|
|
|
- double evalue = 0.0;
|
|
|
|
|
- while (isdigit(*p)) {
|
|
|
|
|
- evalue = (evalue * 10.0) + (*p - '0');
|
|
|
|
|
- ++p;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- if (esign == '-') {
|
|
|
|
|
- value /= pow(evalue, 10.0);
|
|
|
|
|
- } else {
|
|
|
|
|
- value *= pow(evalue, 10.0);
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
if (sign == '-') {
|
|
if (sign == '-') {
|
|
|
value = -value;
|
|
value = -value;
|