handle funny cases for win32

This commit is contained in:
David Rose 2009-06-14 16:19:56 +00:00
parent 8f96a87460
commit 49dfc46215

View File

@ -17,31 +17,6 @@
#include <ctype.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
@ -68,91 +43,65 @@ pstrtod(const char *nptr, char **endptr) {
}
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 {
// 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)) {
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 (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 (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;
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)) {
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 (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 == '-') {
value = -value;
}