diff options
| -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 | } |
