diff options
author | Damien George <damien.p.george@gmail.com> | 2014-01-15 22:58:39 +0000 |
---|---|---|
committer | Damien George <damien.p.george@gmail.com> | 2014-01-15 22:58:39 +0000 |
commit | 5573f9f150d513ed3f996722e2b57b58cfb24f3b (patch) | |
tree | 44a46d84515c9c8943ab20aa89fce0acce0fa5a5 /py | |
parent | 4899ff9470734f0593bbe1f5272bc3d23facf7f7 (diff) | |
parent | 3e4ed25138b7ffc295843dfc11e44bccfb22ab9c (diff) | |
download | micropython-5573f9f150d513ed3f996722e2b57b58cfb24f3b.tar.gz micropython-5573f9f150d513ed3f996722e2b57b58cfb24f3b.zip |
Merge branch 'str2int' of github.com:xyb/micropython into xyb-str2int
Conflicts:
py/objint.c
unix-cpy/Makefile
unix/Makefile
Diffstat (limited to 'py')
-rw-r--r-- | py/misc.h | 2 | ||||
-rw-r--r-- | py/obj.h | 1 | ||||
-rw-r--r-- | py/objint.c | 14 | ||||
-rw-r--r-- | py/py.mk | 1 | ||||
-rw-r--r-- | py/strtonum.c | 96 |
5 files changed, 110 insertions, 4 deletions
@@ -50,6 +50,8 @@ bool unichar_isdigit(unichar c); #define streq(s1, s2) (strcmp((s1), (s2)) == 0) */ +long strtonum(const char *restrict s, int base); + /** variable string *********************************************/ typedef struct _vstr_t { @@ -243,6 +243,7 @@ bool mp_obj_equal(mp_obj_t o1, mp_obj_t o2); bool mp_obj_less(mp_obj_t o1, mp_obj_t o2); machine_int_t mp_obj_get_int(mp_obj_t arg); +machine_int_t mp_obj_parse_int(mp_obj_t arg, mp_obj_t base_arg); #if MICROPY_ENABLE_FLOAT mp_float_t mp_obj_get_float(mp_obj_t self_in); void mp_obj_get_complex(mp_obj_t self_in, mp_float_t *real, mp_float_t *imag); diff --git a/py/objint.c b/py/objint.c index efec60030d..937bff7ae3 100644 --- a/py/objint.c +++ b/py/objint.c @@ -18,11 +18,17 @@ static mp_obj_t int_make_new(mp_obj_t type_in, int n_args, const mp_obj_t *args) return MP_OBJ_NEW_SMALL_INT(0); case 1: - // TODO allow string as arg and parse it - return mp_obj_new_int(mp_obj_get_int(args[0])); + if (MP_OBJ_IS_TYPE(args[0], &str_type)) { + // a string, parse it + return MP_OBJ_NEW_SMALL_INT(strtonum(qstr_str(mp_obj_get_qstr(args[0])), 0)); + } else { + return MP_OBJ_NEW_SMALL_INT(mp_obj_get_int(args[0])); + } - //case 2: - // TODO, parse with given base + case 2: + // should be a string, parse it + // TODO proper error checking of argument types + return MP_OBJ_NEW_SMALL_INT(strtonum(qstr_str(mp_obj_get_qstr(args[1])), mp_obj_get_int(args[0]))); default: nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "int takes at most 2 arguments, %d given", (void*)(machine_int_t)n_args)); @@ -70,6 +70,7 @@ PY_O_BASENAME = \ emitinlinethumb.o \ runtime.o \ map.o \ + strtonum.o \ obj.o \ objbool.o \ objboundmeth.o \ diff --git a/py/strtonum.c b/py/strtonum.c new file mode 100644 index 0000000000..02c1506683 --- /dev/null +++ b/py/strtonum.c @@ -0,0 +1,96 @@ +#if defined(UNIX) + +#include <ctype.h> +#include <errno.h> +#include <stdlib.h> + +#include "misc.h" +#include "mpconfig.h" +#include "mpqstr.h" +#include "nlr.h" +#include "obj.h" + +long strtonum(const char *restrict s, int base) { + int c, neg = 0; + const char *p = s; + char *num; + long found; + + // check radix base + if ((base != 0 && base < 2) || base > 36) { + nlr_jump(mp_obj_new_exception_msg(MP_QSTR_ValueError, "ValueError: int() arg 2 must be >=2 and <= 36")); + } + // skip surrounded whitespace + while (isspace((c = *(p++)))); + if (c == 0) { + goto value_error; + } + // preced sign + if (c == '+' || c == '-') { + neg = - (c == '-'); + c = *(p++); + } + + // find real radix base, and strip preced '0x', '0o' and '0b' + // TODO somehow merge with similar code in parse.c + if ((base == 0 || base == 16) && c == '0') { + c = *(p++); + if ((c | 32) == 'x') { + base = 16; + } else if (base == 0 && (c | 32) == 'o') { + base = 8; + } else if (base == 0 && (c | 32) == 'b') { + base = 2; + } else { + base = 10; + p -= 2; + } + } else if (base == 8 && c == '0') { + c = *(p++); + if ((c | 32) != 'o') { + p -= 2; + } + } else if (base == 2 && c == '0') { + c = *(p++); + if ((c | 32) != 'b') { + p -= 2; + } + } else { + if (base == 0) base = 10; + p--; + } + + found = strtol(p, &num, base); + if (errno) { + goto value_error; + } else if (found && *(num) == 0) { + goto done; + } else if (found || num != p) { + goto check_tail_space; + } else { + goto value_error; + } + +check_tail_space: + if (*(num) != 0) { + while (isspace((c = *(num++)))); + if (c != 0) { + goto value_error; + } + } + +done: + return (found ^ neg) - neg; + +value_error: + nlr_jump(mp_obj_new_exception_msg_2_args(MP_QSTR_ValueError, "invalid literal for int() with base %d: '%s'", (void*)(machine_uint_t)base, s)); +} + +#else /* defined(UNIX) */ + +long strtonum(const char *restrict s, int base) { + // TODO port strtol to stm + return 0; +} + +#endif /* defined(UNIX) */ |