mirror of
https://github.com/lua/lua
synced 2024-11-22 12:51:30 +03:00
new macro 'cvt2str' to better control whether numbers are convertible
to strings
This commit is contained in:
parent
1aa5262634
commit
34ac039fb8
12
lapi.c
12
lapi.c
@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lapi.c,v 2.230 2014/07/21 16:02:57 roberto Exp roberto $
|
||||
** $Id: lapi.c,v 2.231 2014/07/22 18:07:47 roberto Exp roberto $
|
||||
** Lua API
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@ -279,8 +279,8 @@ LUA_API int lua_isnumber (lua_State *L, int idx) {
|
||||
|
||||
|
||||
LUA_API int lua_isstring (lua_State *L, int idx) {
|
||||
int t = lua_type(L, idx);
|
||||
return (t == LUA_TSTRING || t == LUA_TNUMBER);
|
||||
const TValue *o = index2addr(L, idx);
|
||||
return (ttisstring(o) || cvt2str(o));
|
||||
}
|
||||
|
||||
|
||||
@ -371,14 +371,14 @@ LUA_API int lua_toboolean (lua_State *L, int idx) {
|
||||
LUA_API const char *lua_tolstring (lua_State *L, int idx, size_t *len) {
|
||||
StkId o = index2addr(L, idx);
|
||||
if (!ttisstring(o)) {
|
||||
lua_lock(L); /* `luaV_tostring' may create a new string */
|
||||
if (!luaV_tostring(L, o)) { /* conversion failed? */
|
||||
if (!cvt2str(o)) { /* not convertible? */
|
||||
if (len != NULL) *len = 0;
|
||||
lua_unlock(L);
|
||||
return NULL;
|
||||
}
|
||||
lua_lock(L); /* `luaO_tostring' may create a new string */
|
||||
luaC_checkGC(L);
|
||||
o = index2addr(L, idx); /* previous call may reallocate the stack */
|
||||
luaO_tostring(L, o);
|
||||
lua_unlock(L);
|
||||
}
|
||||
if (len != NULL) *len = tsvalue(o)->len;
|
||||
|
5
ldebug.c
5
ldebug.c
@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: ldebug.c,v 2.98 2014/07/15 21:26:50 roberto Exp roberto $
|
||||
** $Id: ldebug.c,v 2.99 2014/07/17 12:30:53 roberto Exp roberto $
|
||||
** Debug Interface
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@ -526,8 +526,7 @@ l_noret luaG_typeerror (lua_State *L, const TValue *o, const char *op) {
|
||||
|
||||
|
||||
l_noret luaG_concaterror (lua_State *L, const TValue *p1, const TValue *p2) {
|
||||
if (ttisstring(p1) || ttisnumber(p1)) p1 = p2;
|
||||
lua_assert(!ttisstring(p1) && !ttisnumber(p1));
|
||||
if (ttisstring(p1) || cvt2str(p1)) p1 = p2;
|
||||
luaG_typeerror(L, p1, "concatenate");
|
||||
}
|
||||
|
||||
|
39
lobject.c
39
lobject.c
@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lobject.c,v 2.86 2014/05/12 21:44:17 roberto Exp roberto $
|
||||
** $Id: lobject.c,v 2.87 2014/06/30 19:48:08 roberto Exp roberto $
|
||||
** Some generic functions over Lua objects
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@ -327,6 +327,32 @@ int luaO_utf8esc (char *buff, unsigned int x) {
|
||||
}
|
||||
|
||||
|
||||
/* maximum length of the conversion of a number to a string */
|
||||
#define MAXNUMBER2STR 50
|
||||
|
||||
|
||||
/*
|
||||
** Convert a number object to a string
|
||||
*/
|
||||
void luaO_tostring (lua_State *L, StkId obj) {
|
||||
char buff[MAXNUMBER2STR];
|
||||
size_t len;
|
||||
lua_assert(ttisnumber(obj));
|
||||
if (ttisinteger(obj))
|
||||
len = lua_integer2str(buff, ivalue(obj));
|
||||
else {
|
||||
len = lua_number2str(buff, fltvalue(obj));
|
||||
#if !defined(LUA_COMPAT_FLOATSTRING)
|
||||
if (buff[strspn(buff, "-0123456789")] == '\0') { /* looks like an int? */
|
||||
buff[len++] = '.';
|
||||
buff[len++] = '0'; /* adds '.0' to result */
|
||||
}
|
||||
#endif
|
||||
}
|
||||
setsvalue2s(L, obj, luaS_newlstr(L, buff, len));
|
||||
}
|
||||
|
||||
|
||||
static void pushstr (lua_State *L, const char *str, size_t l) {
|
||||
setsvalue2s(L, L->top++, luaS_newlstr(L, str, l));
|
||||
}
|
||||
@ -349,24 +375,23 @@ const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) {
|
||||
break;
|
||||
}
|
||||
case 'c': {
|
||||
char buff;
|
||||
buff = cast(char, va_arg(argp, int));
|
||||
char buff = cast(char, va_arg(argp, int));
|
||||
pushstr(L, &buff, 1);
|
||||
break;
|
||||
}
|
||||
case 'd': {
|
||||
setivalue(L->top++, cast_int(va_arg(argp, int)));
|
||||
luaV_tostring(L, L->top - 1);
|
||||
setivalue(L->top++, va_arg(argp, int));
|
||||
luaO_tostring(L, L->top - 1);
|
||||
break;
|
||||
}
|
||||
case 'I': {
|
||||
setivalue(L->top++, cast(lua_Integer, va_arg(argp, l_uacInt)));
|
||||
luaV_tostring(L, L->top - 1);
|
||||
luaO_tostring(L, L->top - 1);
|
||||
break;
|
||||
}
|
||||
case 'f': {
|
||||
setfltvalue(L->top++, cast_num(va_arg(argp, l_uacNumber)));
|
||||
luaV_tostring(L, L->top - 1);
|
||||
luaO_tostring(L, L->top - 1);
|
||||
break;
|
||||
}
|
||||
case 'p': {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lobject.h,v 2.99 2014/07/18 14:46:47 roberto Exp roberto $
|
||||
** $Id: lobject.h,v 2.100 2014/07/29 16:22:24 roberto Exp roberto $
|
||||
** Type definitions for Lua objects
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@ -527,6 +527,7 @@ LUAI_FUNC void luaO_arith (lua_State *L, int op, const TValue *p1,
|
||||
const TValue *p2, TValue *res);
|
||||
LUAI_FUNC size_t luaO_str2num (const char *s, TValue *o);
|
||||
LUAI_FUNC int luaO_hexavalue (int c);
|
||||
LUAI_FUNC void luaO_tostring (lua_State *L, StkId obj);
|
||||
LUAI_FUNC const char *luaO_pushvfstring (lua_State *L, const char *fmt,
|
||||
va_list argp);
|
||||
LUAI_FUNC const char *luaO_pushfstring (lua_State *L, const char *fmt, ...);
|
||||
|
37
lvm.c
37
lvm.c
@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lvm.c,v 2.219 2014/07/18 13:36:14 roberto Exp roberto $
|
||||
** $Id: lvm.c,v 2.220 2014/07/21 16:02:10 roberto Exp roberto $
|
||||
** Lua virtual machine
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@ -33,10 +33,6 @@
|
||||
#define MAXTAGLOOP 2000
|
||||
|
||||
|
||||
/* maximum length of the conversion of a number to a string */
|
||||
#define MAXNUMBER2STR 50
|
||||
|
||||
|
||||
/*
|
||||
** Similar to 'tonumber', but does not attempt to convert strings and
|
||||
** ensure correct precision (no extra bits). Used in comparisons.
|
||||
@ -119,32 +115,6 @@ int luaV_tointeger_ (const TValue *obj, lua_Integer *p) {
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Convert a number object to a string
|
||||
*/
|
||||
int luaV_tostring (lua_State *L, StkId obj) {
|
||||
if (!ttisnumber(obj))
|
||||
return 0;
|
||||
else {
|
||||
char buff[MAXNUMBER2STR];
|
||||
size_t len;
|
||||
if (ttisinteger(obj))
|
||||
len = lua_integer2str(buff, ivalue(obj));
|
||||
else {
|
||||
len = lua_number2str(buff, fltvalue(obj));
|
||||
#if !defined(LUA_COMPAT_FLOATSTRING)
|
||||
if (buff[strspn(buff, "-0123456789")] == '\0') { /* looks like an int? */
|
||||
buff[len++] = '.';
|
||||
buff[len++] = '0'; /* adds '.0' to result */
|
||||
}
|
||||
#endif
|
||||
}
|
||||
setsvalue2s(L, obj, luaS_newlstr(L, buff, len));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Try to convert a 'for' limit to an integer, preserving the
|
||||
** semantics of the loop.
|
||||
@ -374,7 +344,8 @@ int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2) {
|
||||
|
||||
|
||||
/* macro used by 'luaV_concat' to ensure that element at 'o' is a string */
|
||||
#define tostring(L,o) (ttisstring(o) || (luaV_tostring(L, o)))
|
||||
#define tostring(L,o) \
|
||||
(ttisstring(o) || (cvt2str(o) && (luaO_tostring(L, o), 1)))
|
||||
|
||||
/*
|
||||
** Main operation for concatenation: concat 'total' values in the stack,
|
||||
@ -385,7 +356,7 @@ void luaV_concat (lua_State *L, int total) {
|
||||
do {
|
||||
StkId top = L->top;
|
||||
int n = 2; /* number of elements handled in this pass (at least 2) */
|
||||
if (!(ttisstring(top-2) || ttisnumber(top-2)) || !tostring(L, top-1))
|
||||
if (!(ttisstring(top-2) || cvt2str(top-2)) || !tostring(L, top-1))
|
||||
luaT_trybinTM(L, top-2, top-1, top-2, TM_CONCAT);
|
||||
else if (tsvalue(top-1)->len == 0) /* second operand is empty? */
|
||||
cast_void(tostring(L, top - 2)); /* result is first operand */
|
||||
|
10
lvm.h
10
lvm.h
@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lvm.h,v 2.30 2014/05/12 21:22:05 roberto Exp roberto $
|
||||
** $Id: lvm.h,v 2.31 2014/05/26 17:10:22 roberto Exp roberto $
|
||||
** Lua virtual machine
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@ -24,12 +24,18 @@
|
||||
#define luaV_rawequalobj(t1,t2) luaV_equalobj(NULL,t1,t2)
|
||||
|
||||
|
||||
#if !defined(LUA_NOCVTN2S)
|
||||
#define cvt2str(o) ttisnumber(o)
|
||||
#else
|
||||
#define cvt2str(o) 0 /* no convertion from numbers to strings */
|
||||
#endif
|
||||
|
||||
|
||||
LUAI_FUNC int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2);
|
||||
LUAI_FUNC int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r);
|
||||
LUAI_FUNC int luaV_lessequal (lua_State *L, const TValue *l, const TValue *r);
|
||||
LUAI_FUNC int luaV_tonumber_ (const TValue *obj, lua_Number *n);
|
||||
LUAI_FUNC int luaV_tointeger_ (const TValue *obj, lua_Integer *p);
|
||||
LUAI_FUNC int luaV_tostring (lua_State *L, StkId obj);
|
||||
LUAI_FUNC void luaV_gettable (lua_State *L, const TValue *t, TValue *key,
|
||||
StkId val);
|
||||
LUAI_FUNC void luaV_settable (lua_State *L, const TValue *t, TValue *key,
|
||||
|
Loading…
Reference in New Issue
Block a user