diff options
Diffstat (limited to 'libs/litehtml/src/strtod.cpp')
-rw-r--r-- | libs/litehtml/src/strtod.cpp | 275 |
1 files changed, 275 insertions, 0 deletions
diff --git a/libs/litehtml/src/strtod.cpp b/libs/litehtml/src/strtod.cpp new file mode 100644 index 0000000000..22392c4943 --- /dev/null +++ b/libs/litehtml/src/strtod.cpp @@ -0,0 +1,275 @@ +/* + * strtod.c -- + * + * Source code for the "strtod" library procedure. + * + * Copyright (c) 1988-1993 The Regents of the University of California. + * Copyright (c) 1994 Sun Microsystems, Inc. + * + * Permission to use, copy, modify, and distribute this + * software and its documentation for any purpose and without + * fee is hereby granted, provided that the above copyright + * notice appear in all copies. The University of California + * makes no representations about the suitability of this + * software for any purpose. It is provided "as is" without + * express or implied warranty. + * + * RCS: @(#) $Id$ + */ + +#include "html.h" +#include <cstdlib> +#include <cctype> +#include <cerrno> + +#ifndef TRUE +#define TRUE 1 +#define FALSE 0 +#endif +#ifndef NULL +#define NULL 0 +#endif + +static int maxExponent = 511; /* Largest possible base 10 exponent. Any + * exponent larger than this will already + * produce underflow or overflow, so there's + * no need to worry about additional digits. + */ +static double powersOf10[] = { /* Table giving binary powers of 10. Entry */ + 10., /* is 10^2^i. Used to convert decimal */ + 100., /* exponents into floating-point numbers. */ + 1.0e4, + 1.0e8, + 1.0e16, + 1.0e32, + 1.0e64, + 1.0e128, + 1.0e256 +}; + +/* + *---------------------------------------------------------------------- + * + * strtod -- + * + * This procedure converts a floating-point number from an ASCII + * decimal representation to internal double-precision format. + * + * Results: + * The return value is the double-precision floating-point + * representation of the characters in string. If endPtr isn't + * NULL, then *endPtr is filled in with the address of the + * next character after the last one that was part of the + * floating-point number. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +double litehtml::t_strtod(const char* string, char** endPtr) +{ + int sign, expSign = FALSE; + double fraction, dblExp, *d; + const char *p; + int c; + int exp = 0; /* Exponent read from "EX" field. */ + int fracExp = 0; /* Exponent that derives from the fractional + * part. Under normal circumstatnces, it is + * the negative of the number of digits in F. + * However, if I is very long, the last digits + * of I get dropped (otherwise a long I with a + * large negative exponent could cause an + * unnecessary overflow on I alone). In this + * case, fracExp is incremented one for each + * dropped digit. */ + int mantSize; /* Number of digits in mantissa. */ + int decPt; /* Number of mantissa digits BEFORE decimal + * point. */ + const char *pExp; /* Temporarily holds location of exponent + * in string. */ + + /* + * Strip off leading blanks and check for a sign. + */ + + p = string; + while (isspace(*p)) + { + p += 1; + } + if (*p == '-') + { + sign = TRUE; + p += 1; + } else + { + if (*p == '+') + { + p += 1; + } + sign = FALSE; + } + + /* + * Count the number of digits in the mantissa (including the decimal + * point), and also locate the decimal point. + */ + + decPt = -1; + for (mantSize = 0; ; mantSize += 1) + { + c = *p; + if (!t_isdigit(c)) + { + if ((c != '.') || (decPt >= 0)) + { + break; + } + decPt = mantSize; + } + p += 1; + } + + /* + * Now suck up the digits in the mantissa. Use two integers to + * collect 9 digits each (this is faster than using floating-point). + * If the mantissa has more than 18 digits, ignore the extras, since + * they can't affect the value anyway. + */ + + pExp = p; + p -= mantSize; + if (decPt < 0) + { + decPt = mantSize; + } else + { + mantSize -= 1; /* One of the digits was the point. */ + } + if (mantSize > 18) + { + fracExp = decPt - 18; + mantSize = 18; + } else + { + fracExp = decPt - mantSize; + } + if (mantSize == 0) + { + fraction = 0.0; + p = string; + goto done; + } else + { + int frac1, frac2; + frac1 = 0; + for ( ; mantSize > 9; mantSize -= 1) + { + c = *p; + p += 1; + if (c == '.') + { + c = *p; + p += 1; + } + frac1 = 10*frac1 + (c - '0'); + } + frac2 = 0; + for (; mantSize > 0; mantSize -= 1) + { + c = *p; + p += 1; + if (c == '.') + { + c = *p; + p += 1; + } + frac2 = 10*frac2 + (c - '0'); + } + fraction = (1.0e9 * frac1) + frac2; + } + + /* + * Skim off the exponent. + */ + + p = pExp; + if ((*p == 'E') || (*p == 'e')) + { + p += 1; + if (*p == '-') + { + expSign = TRUE; + p += 1; + } else + { + if (*p == '+') + { + p += 1; + } + expSign = FALSE; + } + while (isdigit(*p)) + { + exp = exp * 10 + (*p - '0'); + p += 1; + } + } + if (expSign) + { + exp = fracExp - exp; + } else + { + exp = fracExp + exp; + } + + /* + * Generate a floating-point number that represents the exponent. + * Do this by processing the exponent one bit at a time to combine + * many powers of 2 of 10. Then combine the exponent with the + * fraction. + */ + + if (exp < 0) + { + expSign = TRUE; + exp = -exp; + } else + { + expSign = FALSE; + } + if (exp > maxExponent) + { + exp = maxExponent; + errno = ERANGE; + } + dblExp = 1.0; + for (d = powersOf10; exp != 0; exp >>= 1, d += 1) + { + if (exp & 01) + { + dblExp *= *d; + } + } + if (expSign) + { + fraction /= dblExp; + } else + { + fraction *= dblExp; + } + +done: + if (endPtr != nullptr) + { + *endPtr = (char *) p; + } + + if (sign) + { + return -fraction; + } + return fraction; +} |