diff options
author | Martin Möhrmann <martisch@uos.de> | 2016-10-30 01:54:19 +0200 |
---|---|---|
committer | Brad Fitzpatrick <bradfitz@golang.org> | 2016-11-01 14:04:39 +0000 |
commit | d7b34d5f29324d77fad572676f0ea139556235e0 (patch) | |
tree | 25897e07f5b4624487d4384691ab758571faebff /src/runtime/string.go | |
parent | 40aaf283124de44d513ca086976194f0133faa82 (diff) | |
download | go-d7b34d5f29324d77fad572676f0ea139556235e0.tar.gz go-d7b34d5f29324d77fad572676f0ea139556235e0.zip |
runtime: improve atoi implementation
- Adds overflow checks
- Adds parsing of negative integers
- Adds boolean return value to signal parsing errors
- Adds atoi32 for parsing of integers that fit in an int32
- Adds tests
Handling of errors to provide error messages
at the call sites is left to future CLs.
Updates #17718
Change-Id: I3cacd0ab1230b9efc5404c68edae7304d39bcbc0
Reviewed-on: https://go-review.googlesource.com/32390
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Diffstat (limited to 'src/runtime/string.go')
-rw-r--r-- | src/runtime/string.go | 63 |
1 files changed, 58 insertions, 5 deletions
diff --git a/src/runtime/string.go b/src/runtime/string.go index 07528236ee..822adaacf1 100644 --- a/src/runtime/string.go +++ b/src/runtime/string.go @@ -320,13 +320,66 @@ func hasprefix(s, t string) bool { return len(s) >= len(t) && s[:len(t)] == t } -func atoi(s string) int { - n := 0 - for len(s) > 0 && '0' <= s[0] && s[0] <= '9' { - n = n*10 + int(s[0]) - '0' +const ( + maxUint = ^uint(0) + maxInt = int(maxUint >> 1) +) + +// atoi parses an int from a string s. +// The bool result reports whether s is a number +// representable by a value of type int. +func atoi(s string) (int, bool) { + if s == "" { + return 0, false + } + + neg := false + if s[0] == '-' { + neg = true s = s[1:] } - return n + + un := uint(0) + for i := 0; i < len(s); i++ { + c := s[i] + if c < '0' || c > '9' { + return 0, false + } + if un > maxUint/10 { + // overflow + return 0, false + } + un *= 10 + un1 := un + uint(c) - '0' + if un1 < un { + // overflow + return 0, false + } + un = un1 + } + + if !neg && un > uint(maxInt) { + return 0, false + } + if neg && un > uint(maxInt)+1 { + return 0, false + } + + n := int(un) + if neg { + n = -n + } + + return n, true +} + +// atoi32 is like atoi but for integers +// that fit into an int32. +func atoi32(s string) (int32, bool) { + if n, ok := atoi(s); n == int(int32(n)) { + return int32(n), ok + } + return 0, false } //go:nosplit |