Replace strtod() with builtin string to number conversion.
This commit is contained in:
79
src/lj_str.c
79
src/lj_str.c
@@ -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)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user