142 lines
2.9 KiB
C++
142 lines
2.9 KiB
C++
/* vi:set ts=8 sts=4 sw=4: */
|
|
/*
|
|
* strtod implementation.
|
|
* author: Yasuhiro Matsumoto
|
|
* license: public domain
|
|
*
|
|
* source from https://gist.github.com/mattn/1890186
|
|
*/
|
|
|
|
#include <ctype.h>
|
|
#include <errno.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
static const char* skipwhite(const char* q)
|
|
{
|
|
const char* p = q;
|
|
while (isspace(*p)) ++p;
|
|
return p;
|
|
}
|
|
|
|
extern "C"
|
|
{
|
|
double strtod(const char* str, char** end)
|
|
{
|
|
double d = 0.0;
|
|
int sign;
|
|
int n = 0;
|
|
const char *p, *a;
|
|
|
|
a = p = str;
|
|
p = skipwhite(p);
|
|
|
|
/* decimal part */
|
|
sign = 1;
|
|
if (*p == '-')
|
|
{
|
|
sign = -1;
|
|
++p;
|
|
}
|
|
else if (*p == '+')
|
|
++p;
|
|
if (isdigit(*p))
|
|
{
|
|
d = (double)(*p++ - '0');
|
|
while (*p && isdigit(*p))
|
|
{
|
|
d = d * 10.0 + (double)(*p - '0');
|
|
++p;
|
|
++n;
|
|
}
|
|
a = p;
|
|
}
|
|
else if (*p != '.')
|
|
goto done;
|
|
d *= sign;
|
|
|
|
/* fraction part */
|
|
if (*p == '.')
|
|
{
|
|
double f = 0.0;
|
|
double base = 0.1;
|
|
++p;
|
|
|
|
if (isdigit(*p))
|
|
{
|
|
while (*p && isdigit(*p))
|
|
{
|
|
f += base * (*p - '0');
|
|
base /= 10.0;
|
|
++p;
|
|
++n;
|
|
}
|
|
}
|
|
d += f * sign;
|
|
a = p;
|
|
}
|
|
|
|
/* exponential part */
|
|
if ((*p == 'E') || (*p == 'e'))
|
|
{
|
|
int e = 0;
|
|
++p;
|
|
|
|
sign = 1;
|
|
if (*p == '-')
|
|
{
|
|
sign = -1;
|
|
++p;
|
|
}
|
|
else if (*p == '+')
|
|
++p;
|
|
|
|
if (isdigit(*p))
|
|
{
|
|
while (*p == '0') ++p;
|
|
if (*p == '\0') --p;
|
|
e = (int)(*p++ - '0');
|
|
while (*p && isdigit(*p))
|
|
{
|
|
e = e * 10 + (int)(*p - '0');
|
|
++p;
|
|
}
|
|
e *= sign;
|
|
}
|
|
else if (!isdigit(*(a - 1)))
|
|
{
|
|
a = str;
|
|
goto done;
|
|
}
|
|
else if (*p == 0)
|
|
goto done;
|
|
|
|
if (d == 2.2250738585072011 && e == -308)
|
|
{
|
|
d = 0.0;
|
|
a = p;
|
|
errno = ERANGE;
|
|
goto done;
|
|
}
|
|
if (d == 2.2250738585072012 && e <= -308)
|
|
{
|
|
d *= 1.0e-308;
|
|
a = p;
|
|
goto done;
|
|
}
|
|
d *= __builtin_powi(10.0, e);
|
|
a = p;
|
|
}
|
|
else if (p > str && !isdigit(*(p - 1)))
|
|
{
|
|
a = str;
|
|
goto done;
|
|
}
|
|
|
|
done:
|
|
if (end) *end = const_cast<char*>(a);
|
|
return d;
|
|
}
|
|
}
|