From beff5b078ac3ffce1af983bdad53cb0e664439c6 Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Fri, 5 Jul 2013 11:35:49 -0300 Subject: [PATCH] 'tonumber': does not accept numbers when given a base + convertion from strings to numbers with a base moved to a separated function (more modular) --- lbaselib.c | 69 ++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 43 insertions(+), 26 deletions(-) diff --git a/lbaselib.c b/lbaselib.c index 6a18253d..1e99579f 100644 --- a/lbaselib.c +++ b/lbaselib.c @@ -1,5 +1,5 @@ /* -** $Id: lbaselib.c,v 1.276 2013/02/21 13:44:53 roberto Exp roberto $ +** $Id: lbaselib.c,v 1.277 2013/05/16 18:35:57 roberto Exp roberto $ ** Basic library ** See Copyright Notice in lua.h */ @@ -45,40 +45,57 @@ static int luaB_print (lua_State *L) { #define SPACECHARS " \f\n\r\t\v" +static int b_str2int (const char *s, const char *e, int base, lua_Integer *pn) { + lua_Unsigned n = 0; + int neg = 0; + s += strspn(s, SPACECHARS); /* skip initial spaces */ + if (*s == '-') { s++; neg = 1; } /* handle signal */ + else if (*s == '+') s++; + if (!isalnum((unsigned char)*s)) /* no digit? */ + return 0; + do { + int digit = (isdigit((unsigned char)*s)) ? *s - '0' + : toupper((unsigned char)*s) - 'A' + 10; + if (digit >= base) return 0; /* invalid numeral */ + n = n * base + digit; + s++; + } while (isalnum((unsigned char)*s)); + s += strspn(s, SPACECHARS); /* skip trailing spaces */ + if (s != e) /* invalid trailing characters? */ + return 0; + *pn = (neg) ? -(lua_Integer)n : (lua_Integer)n; + return 1; +} + + static int luaB_tonumber (lua_State *L) { if (lua_isnoneornil(L, 2)) { /* standard conversion */ luaL_checkany(L, 1); - if (lua_cvtonum(L, 1)) { /* can convert to a number? */ - lua_settop(L, 1); /* yes; return converted value */ + if (lua_type(L, 1) == LUA_TNUMBER) { /* already a number? */ + lua_settop(L, 1); /* yes; return it */ return 1; - } /* else not a number */ + } + else { + size_t l; + const char *s = lua_tolstring(L, 1, &l); + if (s != NULL && lua_strtonum(L, s, l)) /* can convert to a number? */ + return 1; + /* else not a number */ + } } else { size_t l; - const char *s = luaL_checklstring(L, 1, &l); - const char *e = s + l; /* end point for 's' */ - int base = luaL_checkint(L, 2); - int neg = 0; + const char *s; + lua_Integer n; + int base = lua_tointeger(L, 2); + luaL_checktype(L, 1, LUA_TSTRING); /* before 'luaL_checklstring'! */ + s = luaL_checklstring(L, 1, &l); luaL_argcheck(L, 2 <= base && base <= 36, 2, "base out of range"); - s += strspn(s, SPACECHARS); /* skip initial spaces */ - if (*s == '-') { s++; neg = 1; } /* handle signal */ - else if (*s == '+') s++; - if (isalnum((unsigned char)*s)) { - lua_Integer n = 0; - do { - int digit = (isdigit((unsigned char)*s)) ? *s - '0' - : toupper((unsigned char)*s) - 'A' + 10; - if (digit >= base) break; /* invalid numeral; force a fail */ - n = n * base + digit; - s++; - } while (isalnum((unsigned char)*s)); - s += strspn(s, SPACECHARS); /* skip trailing spaces */ - if (s == e) { /* no invalid trailing characters? */ - lua_pushinteger(L, (neg) ? -n : n); - return 1; - } /* else not a number */ + if (b_str2int(s, s + l, base, &n)) { + lua_pushinteger(L, n); + return 1; } /* else not a number */ - } + } /* else not a number */ lua_pushnil(L); /* not a number */ return 1; }