Canonicalize string conversion of nan, inf, -inf.

This commit is contained in:
Mike Pall 2010-05-20 00:40:51 +02:00
parent c7a3103f41
commit 926f688cd0
4 changed files with 42 additions and 12 deletions

View File

@ -413,8 +413,7 @@ LJLIB_CF(print)
size = strV(o)->len;
} else if (shortcut && tvisnum(o)) {
char buf[LUAI_MAXNUMBER2STR];
lua_Number n = numV(o);
size = (size_t)lua_number2str(buf, n);
size = lj_str_bufnum(buf, o);
str = buf;
} else {
copyTV(L, L->top+1, o);

View File

@ -734,9 +734,23 @@ LJLIB_CF(string_format)
addintlen(form);
sprintf(buff, form, (unsigned LUA_INTFRM_T)lj_lib_checknum(L, arg));
break;
case 'e': case 'E': case 'f': case 'g': case 'G':
sprintf(buff, form, (double)lj_lib_checknum(L, arg));
case 'e': case 'E': case 'f': case 'g': case 'G': {
TValue tv;
tv.n = lj_lib_checknum(L, arg);
if (LJ_UNLIKELY((tv.u32.hi << 1) >= 0xffe00000)) {
/* Canonicalize output of non-finite values. */
size_t len = lj_str_bufnum(buff, &tv);
if (strfrmt[-1] == 'E' || strfrmt[-1] == 'G') {
buff[len-3] = buff[len-3] - 0x20;
buff[len-2] = buff[len-2] - 0x20;
buff[len-1] = buff[len-1] - 0x20;
}
luaL_addlstring(&b, buff, len);
continue;
}
sprintf(buff, form, (double)tv.n);
break;
}
case 'q':
addquoted(L, &b, arg);
continue;

View File

@ -173,13 +173,27 @@ parsedbl:
}
}
/* Print number to buffer. Canonicalizes non-finite values. */
size_t LJ_FASTCALL lj_str_bufnum(char *s, cTValue *o)
{
if (LJ_LIKELY((o->u32.hi << 1) < 0xffe00000)) { /* Finite? */
lua_Number n = o->n;
return (size_t)lua_number2str(s, n);
} else if (((o->u32.hi & 0x000fffff) | o->u32.lo) != 0) {
s[0] = 'n'; s[1] = 'a'; s[2] = 'n'; return 3;
} else if ((o->u32.hi & 0x80000000) == 0) {
s[0] = 'i'; s[1] = 'n'; s[2] = 'f'; return 3;
} else {
s[0] = '-'; s[1] = 'i'; s[2] = 'n'; s[3] = 'f'; return 4;
}
}
/* Convert number to string. */
GCstr * LJ_FASTCALL lj_str_fromnum(lua_State *L, const lua_Number *np)
{
char s[LUAI_MAXNUMBER2STR];
lua_Number n = *np;
size_t len = (size_t)lua_number2str(s, n);
return lj_str_new(L, s, len);
char buf[LUAI_MAXNUMBER2STR];
size_t len = lj_str_bufnum(buf, (TValue *)np);
return lj_str_new(L, buf, len);
}
#if LJ_HASJIT
@ -252,10 +266,12 @@ const char *lj_str_pushvf(lua_State *L, const char *fmt, va_list argp)
break;
}
case 'f': {
char buff[LUAI_MAXNUMBER2STR];
lua_Number n = cast_num(va_arg(argp, LUAI_UACNUMBER));
MSize len = (MSize)lua_number2str(buff, n);
addstr(L, sb, buff, len);
char buf[LUAI_MAXNUMBER2STR];
TValue tv;
MSize len;
tv.n = cast_num(va_arg(argp, LUAI_UACNUMBER));
len = (MSize)lj_str_bufnum(buf, &tv);
addstr(L, sb, buf, len);
break;
}
case 'p': {

View File

@ -22,6 +22,7 @@ LJ_FUNC void LJ_FASTCALL lj_str_free(global_State *g, GCstr *s);
/* Type conversions. */
LJ_FUNC int LJ_FASTCALL lj_str_numconv(const char *s, TValue *n);
LJ_FUNC int LJ_FASTCALL lj_str_tonum(GCstr *str, TValue *n);
LJ_FUNC size_t LJ_FASTCALL lj_str_bufnum(char *s, cTValue *o);
LJ_FUNCA GCstr * LJ_FASTCALL lj_str_fromnum(lua_State *L, const lua_Number *np);
#if LJ_HASJIT
LJ_FUNC GCstr * LJ_FASTCALL lj_str_fromint(lua_State *L, int32_t k);