diff options
author | Chris Angelico <rosuav@gmail.com> | 2014-06-04 05:28:12 +1000 |
---|---|---|
committer | Paul Sokolovsky <pfalcon@users.sourceforge.net> | 2014-06-27 00:04:17 +0300 |
commit | 9a1a4beb563f8e2ae111ff062a64989774f29058 (patch) | |
tree | ded877921b2023845cb853dfc98a7ae04c1ec13f /py/builtin.c | |
parent | 64b468d8733845ac9f04776ee41434cdcc1a2602 (diff) | |
download | micropython-9a1a4beb563f8e2ae111ff062a64989774f29058.tar.gz micropython-9a1a4beb563f8e2ae111ff062a64989774f29058.zip |
builtin: ord, chr: Unicode support.
Diffstat (limited to 'py/builtin.c')
-rw-r--r-- | py/builtin.c | 45 |
1 files changed, 36 insertions, 9 deletions
diff --git a/py/builtin.c b/py/builtin.c index d4b77d37a8..0c0163d005 100644 --- a/py/builtin.c +++ b/py/builtin.c @@ -172,13 +172,30 @@ STATIC mp_obj_t mp_builtin_callable(mp_obj_t o_in) { MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_callable_obj, mp_builtin_callable); STATIC mp_obj_t mp_builtin_chr(mp_obj_t o_in) { - int ord = mp_obj_get_int(o_in); - if (0 <= ord && ord <= 0x10ffff) { - char str[1] = {ord}; - return mp_obj_new_str(str, 1, true); + int c = mp_obj_get_int(o_in); + char str[4]; + int len = 0; + if (c < 0x80) { + *str = c; len = 1; + } else if (c < 0x800) { + str[0] = (c >> 6) | 0xC0; + str[1] = (c & 0x3F) | 0x80; + len = 2; + } else if (c < 0x10000) { + str[0] = (c >> 12) | 0xE0; + str[1] = ((c >> 6) & 0x3F) | 0x80; + str[2] = (c & 0x3F) | 0x80; + len = 3; + } else if (c < 0x110000) { + str[0] = (c >> 18) | 0xF0; + str[1] = ((c >> 12) & 0x3F) | 0x80; + str[2] = ((c >> 6) & 0x3F) | 0x80; + str[3] = (c & 0x3F) | 0x80; + len = 4; } else { nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "chr() arg not in range(0x110000)")); } + return mp_obj_new_str(str, len, true); } MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_chr_obj, mp_builtin_chr); @@ -344,12 +361,22 @@ MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_oct_obj, mp_builtin_oct); STATIC mp_obj_t mp_builtin_ord(mp_obj_t o_in) { uint len; const char *str = mp_obj_str_get_data(o_in, &len); - if (len == 1) { - // don't sign extend when converting to ord - // TODO unicode - return mp_obj_new_int(((const byte*)str)[0]); + uint charlen = unichar_charlen(str, len); + if (charlen == 1) { + if (MP_OBJ_IS_STR(o_in) && UTF8_IS_NONASCII(*str)) { + machine_int_t ord = *str++ & 0x7F; + for (machine_int_t mask = 0x40; ord & mask; mask >>= 1) { + ord &= ~mask; + } + while (UTF8_IS_CONT(*str)) { + ord = (ord << 6) | (*str++ & 0x3F); + } + return mp_obj_new_int(ord); + } else { + return mp_obj_new_int(((const byte*)str)[0]); + } } else { - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "ord() expected a character, but string of length %d found", len)); + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "ord() expected a character, but string of length %d found", charlen)); } } |