diff --git a/spec/tags/core/string/to_i_tags.txt b/spec/tags/core/string/to_i_tags.txt index 9172abba8..dbec10fe9 100644 --- a/spec/tags/core/string/to_i_tags.txt +++ b/spec/tags/core/string/to_i_tags.txt @@ -1,8 +1 @@ fails:String#to_i interprets leading characters as a number in the given base -fails:String#to_i auto-detects base 8 via leading 0 when base = 0 -fails:String#to_i auto-detects base 2 via 0b when base = 0 -fails:String#to_i auto-detects base 10 via 0d when base = 0 -fails:String#to_i auto-detects base 8 via 0o when base = 0 -fails:String#to_i auto-detects base 16 via 0x when base = 0 -fails:String#to_i auto-detects base 10 with no base specifier when base = 0 -fails:String#to_i doesn't handle foreign base specifiers when base is > 0 diff --git a/topaz/objects/stringobject.py b/topaz/objects/stringobject.py index c38161bab..344755758 100644 --- a/topaz/objects/stringobject.py +++ b/topaz/objects/stringobject.py @@ -10,11 +10,14 @@ from rpython.rlib.rsre import rsre_core from rpython.rlib.rstring import split +from topaz.coerce import Coerce from topaz.module import ClassDef, check_frozen from topaz.modules.comparable import Comparable from topaz.objects.objectobject import W_Object from topaz.utils.formatting import StringFormatter +RADIX_MAP = {"x": 16, "d": 10, "b": 2, "o": 8, "X": 16, "D": 10, "B": 2, "O": 8} + def create_trans_table(source, replacement, inv=False): src = expand_trans_str(source, len(source), inv) @@ -775,19 +778,39 @@ def to_bigint(self, s, neg, i, radix): val = val.neg() return val - @classdef.method("to_i", radix="int") - def method_to_i(self, space, radix=10): - if not 2 <= radix <= 36: - raise space.error(space.w_ArgumentError, "invalid radix %d" % radix) + @classdef.method("to_i") + def method_to_i(self, space, w_radix=None): + if w_radix is None: + is_radix = False + radix = 10 + else: + is_radix = True + radix = Coerce.int(space, w_radix) s = space.str_w(self) i = 0 - while i < len(s): + length = len(s) + while i < length: if not s[i].isspace(): break i += 1 - neg = i < len(s) and s[i] == "-" + neg = i < length and s[i] == "-" if neg: i += 1 + if i < length and s[i] == "0": + if i + 1 < length: + try: + r = RADIX_MAP[s[i + 1]] + except KeyError: + if radix == 0: + radix = 8 + else: + if not is_radix or radix == r or radix == 0: + radix = r + i += 2 + if radix == 0: + radix = 10 + if not 2 <= radix <= 36: + raise space.error(space.w_ArgumentError, "invalid radix %d" % radix) try: value = self.to_int(s, neg, i, radix) except OverflowError: