diff --git a/src/strconv/atoi.go b/src/strconv/atoi.go index ecbc9f4bbe..31774d0c9a 100644 --- a/src/strconv/atoi.go +++ b/src/strconv/atoi.go @@ -71,18 +71,22 @@ func ParseUint(s string, base int, bitSize int) (uint64, error) { case base == 0: // Look for octal, hex prefix. - switch { - case s[0] == '0' && len(s) >= 3 && lower(s[1]) == 'x': - if len(s) < 3 { - return 0, syntaxError(fnParseUint, s0) + base = 10 + if s[0] == '0' { + switch { + case len(s) >= 3 && lower(s[1]) == 'b': + base = 2 + s = s[2:] + case len(s) >= 3 && lower(s[1]) == 'o': + base = 8 + s = s[2:] + case len(s) >= 3 && lower(s[1]) == 'x': + base = 16 + s = s[2:] + default: + base = 8 + s = s[1:] } - base = 16 - s = s[2:] - case s[0] == '0': - base = 8 - s = s[1:] - default: - base = 10 } default: @@ -149,13 +153,14 @@ func ParseUint(s string, base int, bitSize int) (uint64, error) { // bit size (0 to 64) and returns the corresponding value i. // // If base == 0, the base is implied by the string's prefix: -// base 16 for "0x", base 8 for "0", and base 10 otherwise. -// For bases 1, below 0 or above 36 an error is returned. +// base 2 for "0b", base 8 for "0" or "0o", base 16 for "0x", +// and base 10 otherwise. +// If base is below 0, is 1, or is above 36, an error is returned. // // The bitSize argument specifies the integer type // that the result must fit into. Bit sizes 0, 8, 16, 32, and 64 // correspond to int, int8, int16, int32, and int64. -// For a bitSize below 0 or above 64 an error is returned. +// If bitSize is below 0 or above 64, an error is returned. // // The errors that ParseInt returns have concrete type *NumError // and include err.Num = s. If s is empty or contains invalid diff --git a/src/strconv/atoi_test.go b/src/strconv/atoi_test.go index ec0542abf8..8b0576b659 100644 --- a/src/strconv/atoi_test.go +++ b/src/strconv/atoi_test.go @@ -65,42 +65,69 @@ var parseUint64BaseTests = []parseUint64BaseTest{ {"01777777777777777777778", 0, 0, ErrSyntax}, {"02000000000000000000000", 0, 1<<64 - 1, ErrRange}, {"0200000000000000000000", 0, 1 << 61, nil}, + {"0b", 0, 0, ErrSyntax}, + {"0B", 0, 0, ErrSyntax}, + {"0b101", 0, 5, nil}, + {"0B101", 0, 5, nil}, + {"0o", 0, 0, ErrSyntax}, + {"0O", 0, 0, ErrSyntax}, + {"0o377", 0, 255, nil}, + {"0O377", 0, 255, nil}, // underscores allowed with base == 0 only - {"1_2_3_4_5", 0, 12345, nil}, + {"1_2_3_4_5", 0, 12345, nil}, // base 0 => 10 {"_12345", 0, 0, ErrSyntax}, {"1__2345", 0, 0, ErrSyntax}, {"12345_", 0, 0, ErrSyntax}, - {"1_2_3_4_5", 10, 0, ErrSyntax}, + {"1_2_3_4_5", 10, 0, ErrSyntax}, // base 10 {"_12345", 10, 0, ErrSyntax}, {"1__2345", 10, 0, ErrSyntax}, {"12345_", 10, 0, ErrSyntax}, - {"0x_1_2_3_4_5", 0, 0x12345, nil}, + {"0x_1_2_3_4_5", 0, 0x12345, nil}, // base 0 => 16 {"_0x12345", 0, 0, ErrSyntax}, {"0x__12345", 0, 0, ErrSyntax}, {"0x1__2345", 0, 0, ErrSyntax}, {"0x1234__5", 0, 0, ErrSyntax}, {"0x12345_", 0, 0, ErrSyntax}, - {"1_2_3_4_5", 16, 0, ErrSyntax}, + {"1_2_3_4_5", 16, 0, ErrSyntax}, // base 16 {"_12345", 16, 0, ErrSyntax}, {"1__2345", 16, 0, ErrSyntax}, {"1234__5", 16, 0, ErrSyntax}, {"12345_", 16, 0, ErrSyntax}, - {"0_1_2_3_4_5", 0, 012345, nil}, + {"0_1_2_3_4_5", 0, 012345, nil}, // base 0 => 8 (0377) {"_012345", 0, 0, ErrSyntax}, {"0__12345", 0, 0, ErrSyntax}, {"01234__5", 0, 0, ErrSyntax}, {"012345_", 0, 0, ErrSyntax}, - {"0_1_2_3_4_5", 8, 0, ErrSyntax}, + {"0o_1_2_3_4_5", 0, 012345, nil}, // base 0 => 8 (0o377) + {"_0o12345", 0, 0, ErrSyntax}, + {"0o__12345", 0, 0, ErrSyntax}, + {"0o1234__5", 0, 0, ErrSyntax}, + {"0o12345_", 0, 0, ErrSyntax}, + + {"0_1_2_3_4_5", 8, 0, ErrSyntax}, // base 8 {"_012345", 8, 0, ErrSyntax}, {"0__12345", 8, 0, ErrSyntax}, {"01234__5", 8, 0, ErrSyntax}, {"012345_", 8, 0, ErrSyntax}, + + {"0b_1_0_1", 0, 5, nil}, // base 0 => 2 (0b101) + {"_0b101", 0, 0, ErrSyntax}, + {"0b__101", 0, 0, ErrSyntax}, + {"0b1__01", 0, 0, ErrSyntax}, + {"0b10__1", 0, 0, ErrSyntax}, + {"0b101_", 0, 0, ErrSyntax}, + + {"1_0_1", 2, 0, ErrSyntax}, // base 2 + {"_101", 2, 0, ErrSyntax}, + {"1_01", 2, 0, ErrSyntax}, + {"10_1", 2, 0, ErrSyntax}, + {"101_", 2, 0, ErrSyntax}, } type parseInt64Test struct {