diff options
Diffstat (limited to 'lbaselib.c')
-rw-r--r-- | lbaselib.c | 69 |
1 files changed, 43 insertions, 26 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lbaselib.c,v 1.276 2013/02/21 13:44:53 roberto Exp roberto $ | 2 | ** $Id: lbaselib.c,v 1.277 2013/05/16 18:35:57 roberto Exp roberto $ |
3 | ** Basic library | 3 | ** Basic library |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -45,40 +45,57 @@ static int luaB_print (lua_State *L) { | |||
45 | 45 | ||
46 | #define SPACECHARS " \f\n\r\t\v" | 46 | #define SPACECHARS " \f\n\r\t\v" |
47 | 47 | ||
48 | static int b_str2int (const char *s, const char *e, int base, lua_Integer *pn) { | ||
49 | lua_Unsigned n = 0; | ||
50 | int neg = 0; | ||
51 | s += strspn(s, SPACECHARS); /* skip initial spaces */ | ||
52 | if (*s == '-') { s++; neg = 1; } /* handle signal */ | ||
53 | else if (*s == '+') s++; | ||
54 | if (!isalnum((unsigned char)*s)) /* no digit? */ | ||
55 | return 0; | ||
56 | do { | ||
57 | int digit = (isdigit((unsigned char)*s)) ? *s - '0' | ||
58 | : toupper((unsigned char)*s) - 'A' + 10; | ||
59 | if (digit >= base) return 0; /* invalid numeral */ | ||
60 | n = n * base + digit; | ||
61 | s++; | ||
62 | } while (isalnum((unsigned char)*s)); | ||
63 | s += strspn(s, SPACECHARS); /* skip trailing spaces */ | ||
64 | if (s != e) /* invalid trailing characters? */ | ||
65 | return 0; | ||
66 | *pn = (neg) ? -(lua_Integer)n : (lua_Integer)n; | ||
67 | return 1; | ||
68 | } | ||
69 | |||
70 | |||
48 | static int luaB_tonumber (lua_State *L) { | 71 | static int luaB_tonumber (lua_State *L) { |
49 | if (lua_isnoneornil(L, 2)) { /* standard conversion */ | 72 | if (lua_isnoneornil(L, 2)) { /* standard conversion */ |
50 | luaL_checkany(L, 1); | 73 | luaL_checkany(L, 1); |
51 | if (lua_cvtonum(L, 1)) { /* can convert to a number? */ | 74 | if (lua_type(L, 1) == LUA_TNUMBER) { /* already a number? */ |
52 | lua_settop(L, 1); /* yes; return converted value */ | 75 | lua_settop(L, 1); /* yes; return it */ |
53 | return 1; | 76 | return 1; |
54 | } /* else not a number */ | 77 | } |
78 | else { | ||
79 | size_t l; | ||
80 | const char *s = lua_tolstring(L, 1, &l); | ||
81 | if (s != NULL && lua_strtonum(L, s, l)) /* can convert to a number? */ | ||
82 | return 1; | ||
83 | /* else not a number */ | ||
84 | } | ||
55 | } | 85 | } |
56 | else { | 86 | else { |
57 | size_t l; | 87 | size_t l; |
58 | const char *s = luaL_checklstring(L, 1, &l); | 88 | const char *s; |
59 | const char *e = s + l; /* end point for 's' */ | 89 | lua_Integer n; |
60 | int base = luaL_checkint(L, 2); | 90 | int base = lua_tointeger(L, 2); |
61 | int neg = 0; | 91 | luaL_checktype(L, 1, LUA_TSTRING); /* before 'luaL_checklstring'! */ |
92 | s = luaL_checklstring(L, 1, &l); | ||
62 | luaL_argcheck(L, 2 <= base && base <= 36, 2, "base out of range"); | 93 | luaL_argcheck(L, 2 <= base && base <= 36, 2, "base out of range"); |
63 | s += strspn(s, SPACECHARS); /* skip initial spaces */ | 94 | if (b_str2int(s, s + l, base, &n)) { |
64 | if (*s == '-') { s++; neg = 1; } /* handle signal */ | 95 | lua_pushinteger(L, n); |
65 | else if (*s == '+') s++; | 96 | return 1; |
66 | if (isalnum((unsigned char)*s)) { | ||
67 | lua_Integer n = 0; | ||
68 | do { | ||
69 | int digit = (isdigit((unsigned char)*s)) ? *s - '0' | ||
70 | : toupper((unsigned char)*s) - 'A' + 10; | ||
71 | if (digit >= base) break; /* invalid numeral; force a fail */ | ||
72 | n = n * base + digit; | ||
73 | s++; | ||
74 | } while (isalnum((unsigned char)*s)); | ||
75 | s += strspn(s, SPACECHARS); /* skip trailing spaces */ | ||
76 | if (s == e) { /* no invalid trailing characters? */ | ||
77 | lua_pushinteger(L, (neg) ? -n : n); | ||
78 | return 1; | ||
79 | } /* else not a number */ | ||
80 | } /* else not a number */ | 97 | } /* else not a number */ |
81 | } | 98 | } /* else not a number */ |
82 | lua_pushnil(L); /* not a number */ | 99 | lua_pushnil(L); /* not a number */ |
83 | return 1; | 100 | return 1; |
84 | } | 101 | } |