#include <stdio.h>
#include <math.h>
#include <stdlib.h>
// SVG specs for numbers :
//
// number ::= integer ([Ee] integer)?
// | [+-]? [0-9]* "." [0-9]+ ([Ee] integer)?
#define TRY(S) printf("%10s => %f (error is %g)\n", #S, my_atof(#S, NULL), my_atof(#S, NULL) - atof(#S));
#define TRY_BAD(S) printf("%10s %f fails at:", #S, my_atof(#S, &end)); printf("%s\n", end);
float my_atof(const char *str, char ** last)
{
char * end = (char*)str;
float res = (float)strtoll(str, &end, 10);
int badConv = end == str;
float sign = res < 0 || (*end == '-' && ++end) ? -1 : (end == str && *end == '+' && ++end) || 1; // Trim sign
if (badConv && *end != '.') // Invalid input
{
if (last != NULL) *last = (char*)str;
return 0;
}
if (*end == '.')
{
char* beg = ++end, *tmp = 0; // So end is correct when returning below
long long frac = strtoll(beg, &tmp, 10);
if (*beg < '0' || *beg > '9')
{
if (last != NULL) *last = badConv ? str : end;
return res;
}
end = tmp;
res
+= sign
* frac
/pow(10, end
-beg
); }
if (*end == 'e' || *end == 'E')
{
char * tmp = 0;
if (tmp != end + 1) end = tmp; // Reject 34e as 34 followed by e
}
if (last != NULL) *last = end;
return res;
}
int main(void) {
TRY(-5);
TRY(+5);
TRY(-5.1);
TRY(.5);
TRY(.5e2);
TRY(.5541e-2);
TRY(.5e+2);
TRY(+.57e-2);
TRY(+.001e+1);
char * end = 0;
TRY_BAD(34f4);
TRY_BAD(34.+44);
TRY_BAD(34.-44);
TRY_BAD(+.f)
TRY_BAD(+e10)
TRY_BAD(+.e10)
TRY_BAD(34e)
TRY_BAD(+33+4)
return 0;
}
I2luY2x1ZGUgPHN0ZGlvLmg+CiNpbmNsdWRlIDxtYXRoLmg+CiNpbmNsdWRlIDxzdGRsaWIuaD4KCi8vIFNWRyBzcGVjcyBmb3IgbnVtYmVycyA6Ci8vCi8vIG51bWJlciA6Oj0gaW50ZWdlciAoW0VlXSBpbnRlZ2VyKT8KLy8gICAgICAgICAgIHwgWystXT8gWzAtOV0qICIuIiBbMC05XSsgKFtFZV0gaW50ZWdlcik/CgojZGVmaW5lIFRSWShTKSBwcmludGYoIiUxMHMgPT4gJWYgKGVycm9yIGlzICVnKVxuIiwgI1MsIG15X2F0b2YoI1MsIE5VTEwpLCBteV9hdG9mKCNTLCBOVUxMKSAtIGF0b2YoI1MpKTsgCiNkZWZpbmUgVFJZX0JBRChTKSBwcmludGYoIiUxMHMgJWYgZmFpbHMgYXQ6IiwgI1MsIG15X2F0b2YoI1MsICZlbmQpKTsgcHJpbnRmKCIlc1xuIiwgZW5kKTsKCmZsb2F0IG15X2F0b2YoY29uc3QgY2hhciAqc3RyLCBjaGFyICoqIGxhc3QpCnsKICAgIGNoYXIgKiBlbmQgPSAoY2hhciopc3RyOwogIAogICAgZmxvYXQgcmVzID0gKGZsb2F0KXN0cnRvbGwoc3RyLCAmZW5kLCAxMCk7CglpbnQgYmFkQ29udiA9IGVuZCA9PSBzdHI7CiAgICBmbG9hdCBzaWduID0gcmVzIDwgMCB8fCAoKmVuZCA9PSAnLScgJiYgKytlbmQpID8gLTEgOiAoZW5kID09IHN0ciAmJiAqZW5kID09ICcrJyAmJiArK2VuZCkgfHwgMTsgLy8gVHJpbSBzaWduIAoJCglpZiAoYmFkQ29udiAmJiAqZW5kICE9ICcuJykgLy8gSW52YWxpZCBpbnB1dAoJewoJCWlmIChsYXN0ICE9IE5VTEwpICpsYXN0ID0gKGNoYXIqKXN0cjsKCQlyZXR1cm4gMDsKCX0KCQoKICAgIGlmICgqZW5kID09ICcuJykKICAgIHsKICAgIAljaGFyKiBiZWcgPSArK2VuZCwgKnRtcCA9IDA7ICAgLy8gU28gZW5kIGlzIGNvcnJlY3Qgd2hlbiByZXR1cm5pbmcgYmVsb3cKICAgIAlsb25nIGxvbmcgZnJhYyA9IHN0cnRvbGwoYmVnLCAmdG1wLCAxMCk7CiAgICAgICAgaWYgKCpiZWcgPCAnMCcgfHwgKmJlZyA+ICc5JykgCiAgICAgICAgewogICAgICAgIAlpZiAobGFzdCAhPSBOVUxMKSAqbGFzdCA9IGJhZENvbnYgPyBzdHIgOiBlbmQ7CiAgICAgICAgCXJldHVybiByZXM7CiAgICAgICAgfQogICAgICAgIGVuZCA9IHRtcDsKICAgIAlyZXMgKz0gc2lnbiAqIGZyYWMvcG93KDEwLCBlbmQtYmVnKTsKICAgIH0KICAgIAogICAgaWYgKCplbmQgPT0gJ2UnIHx8ICplbmQgPT0gJ0UnKSAKICAgIHsKICAgIAljaGFyICogdG1wID0gMDsKICAgIAlyZXMgKj0gcG93KDEwLCBzdHJ0b2woZW5kKzEsICZ0bXAsIDEwKSk7CiAgICAJaWYgKHRtcCAhPSBlbmQgKyAxKSBlbmQgPSB0bXA7IC8vIFJlamVjdCAzNGUgYXMgMzQgZm9sbG93ZWQgYnkgZQogICAgfQoJCglpZiAobGFzdCAhPSBOVUxMKSAqbGFzdCA9IGVuZDsKICAgIHJldHVybiByZXM7Cn0KCmludCBtYWluKHZvaWQpIHsKCVRSWSgtNSk7CglUUlkoKzUpOwoJVFJZKC01LjEpOwoJVFJZKC41KTsKCVRSWSguNWUyKTsKCVRSWSguNTU0MWUtMik7CglUUlkoLjVlKzIpOwoJVFJZKCsuNTdlLTIpOwoJVFJZKCsuMDAxZSsxKTsKCWNoYXIgKiBlbmQgPSAwOwoJVFJZX0JBRCgzNGY0KTsKCVRSWV9CQUQoMzQuKzQ0KTsKCVRSWV9CQUQoMzQuLTQ0KTsKCVRSWV9CQUQoKy5mKQoJVFJZX0JBRCgrZTEwKQoJVFJZX0JBRCgrLmUxMCkKCVRSWV9CQUQoMzRlKQoJVFJZX0JBRCgrMzMrNCkKCXJldHVybiAwOwp9Cg==