diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2010-12-27 16:00:38 -0200 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2010-12-27 16:00:38 -0200 |
commit | aa6faa6331e3e5e326bf5830474ffd9b04425678 (patch) | |
tree | ea8db67fabdda7fbaa9a5c30a8d2613b473430d0 | |
parent | 0b3f4e254e52f7497b813098c79619a4aaa83c4d (diff) | |
download | lua-aa6faa6331e3e5e326bf5830474ffd9b04425678.tar.gz lua-aa6faa6331e3e5e326bf5830474ffd9b04425678.tar.bz2 lua-aa6faa6331e3e5e326bf5830474ffd9b04425678.zip |
own implementation of 'tunumber', so that it works correctly with
numbers outside the 'int' range
-rw-r--r-- | lbaselib.c | 42 |
1 files changed, 24 insertions, 18 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lbaselib.c,v 1.255 2010/12/13 16:38:00 roberto Exp roberto $ | 2 | ** $Id: lbaselib.c,v 1.256 2010/12/17 15:14:58 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 | */ |
@@ -47,33 +47,39 @@ static int luaB_print (lua_State *L) { | |||
47 | 47 | ||
48 | static int luaB_tonumber (lua_State *L) { | 48 | static int luaB_tonumber (lua_State *L) { |
49 | int base = luaL_optint(L, 2, 10); | 49 | int base = luaL_optint(L, 2, 10); |
50 | luaL_argcheck(L, 2 <= base && base <= 36, 2, "base out of range"); | ||
50 | if (base == 10) { /* standard conversion */ | 51 | if (base == 10) { /* standard conversion */ |
51 | luaL_checkany(L, 1); | 52 | luaL_checkany(L, 1); |
52 | if (lua_isnumber(L, 1)) { | 53 | if (lua_isnumber(L, 1)) { |
53 | lua_pushnumber(L, lua_tonumber(L, 1)); | 54 | lua_pushnumber(L, lua_tonumber(L, 1)); |
54 | return 1; | 55 | return 1; |
55 | } | 56 | } /* else not a number */ |
56 | } | 57 | } |
57 | else { | 58 | else { |
58 | size_t l1; | 59 | size_t l; |
59 | const char *s1 = luaL_checklstring(L, 1, &l1); | 60 | const char *s = luaL_checklstring(L, 1, &l); |
60 | const char *e1 = s1 + l1; | 61 | const char *e = s + l; /* end point for 's' */ |
61 | char *s2; | ||
62 | unsigned long n; | ||
63 | int neg = 0; | 62 | int neg = 0; |
64 | luaL_argcheck(L, 2 <= base && base <= 36, 2, "base out of range"); | 63 | s += strspn(s, SPACECHARS); /* skip initial spaces */ |
65 | s1 += strspn(s1, SPACECHARS); /* skip initial spaces */ | 64 | if (*s == '-') { s++; neg = 1; } /* handle signal */ |
66 | if (*s1 == '-') { s1++; neg = 1; } | 65 | else if (*s == '+') s++; |
67 | n = strtoul(s1, &s2, base); | 66 | if (isalnum((unsigned char)*s)) { |
68 | if (s1 != s2) { /* at least one valid digit? */ | 67 | lua_Number n = 0; |
69 | s2 += strspn(s2, SPACECHARS); /* skip trailing spaces */ | 68 | do { |
70 | if (s2 == e1) { /* no invalid trailing characters? */ | 69 | int digit = (isdigit((unsigned char)*s)) ? *s - '0' |
71 | lua_pushnumber(L, (neg) ? -(lua_Number)n : (lua_Number)n); | 70 | : toupper((unsigned char)*s) - 'A' + 10; |
71 | if (digit >= base) break; /* invalid numeral; force a fail */ | ||
72 | n = n * (lua_Number)base + (lua_Number)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_pushnumber(L, (neg) ? -n : n); | ||
72 | return 1; | 78 | return 1; |
73 | } | 79 | } /* else not a number */ |
74 | } | 80 | } /* else not a number */ |
75 | } | 81 | } |
76 | lua_pushnil(L); /* else not a number */ | 82 | lua_pushnil(L); /* not a number */ |
77 | return 1; | 83 | return 1; |
78 | } | 84 | } |
79 | 85 | ||