Replace strtod() with builtin string to number conversion.

This commit is contained in:
Mike Pall
2012-08-25 23:02:29 +02:00
parent 653facd0d5
commit 4c882fe714
24 changed files with 660 additions and 272 deletions

View File

@@ -169,85 +169,6 @@ void LJ_FASTCALL lj_str_free(global_State *g, GCstr *s)
/* -- Type conversions ---------------------------------------------------- */
/* Convert string object to number. */
int LJ_FASTCALL lj_str_tonum(GCstr *str, TValue *n)
{
int ok = lj_str_numconv(strdata(str), n);
if (ok && tvisint(n))
setnumV(n, (lua_Number)intV(n));
return ok;
}
int LJ_FASTCALL lj_str_tonumber(GCstr *str, TValue *n)
{
return lj_str_numconv(strdata(str), n);
}
/* Convert string to number. */
int LJ_FASTCALL lj_str_numconv(const char *s, TValue *n)
{
#if LJ_DUALNUM
int sign = 1;
#else
lua_Number sign = 1;
#endif
const uint8_t *p = (const uint8_t *)s;
while (lj_char_isspace(*p)) p++;
if (*p == '-') { p++; sign = -1; } else if (*p == '+') { p++; }
if ((uint32_t)(*p - '0') < 10) {
uint32_t k = (uint32_t)(*p++ - '0');
if (k == 0 && ((*p & ~0x20) == 'X')) {
p++;
if (!lj_char_isxdigit(*p))
return 0; /* Don't accept '0x' without hex digits. */
do {
if (k >= 0x10000000u) goto parsedbl;
k = (k << 4) + (*p & 15u);
if (!lj_char_isdigit(*p)) k += 9;
p++;
} while (lj_char_isxdigit(*p));
} else {
while ((uint32_t)(*p - '0') < 10) {
if (LJ_UNLIKELY(k >= 429496729) && (k != 429496729 || *p > '5'))
goto parsedbl;
k = k * 10u + (uint32_t)(*p++ - '0');
}
}
while (LJ_UNLIKELY(lj_char_isspace(*p))) p++;
if (LJ_LIKELY(*p == '\0')) {
#if LJ_DUALNUM
if (sign == 1) {
if (k < 0x80000000u) {
setintV(n, (int32_t)k);
return 1;
}
} else if (k <= 0x80000000u) {
setintV(n, -(int32_t)k);
return 1;
}
#endif
setnumV(n, sign * (lua_Number)k);
return 1;
}
}
parsedbl:
{
TValue tv;
char *endptr;
setnumV(&tv, lua_str2number(s, &endptr));
if (endptr == s) return 0; /* Conversion failed. */
if (LJ_UNLIKELY(*endptr != '\0')) {
while (lj_char_isspace((uint8_t)*endptr)) endptr++;
if (*endptr != '\0') return 0; /* Invalid trailing characters? */
}
if (LJ_LIKELY(!tvisnan(&tv)))
setnumV(n, numV(&tv));
else
setnanV(n); /* Canonicalize injected NaNs. */
return 1;
}
}
/* Print number to buffer. Canonicalizes non-finite values. */
size_t LJ_FASTCALL lj_str_bufnum(char *s, cTValue *o)
{